private string GetOutsideTypeQualifiedName(SyntaxNode node)
        {
            // Get the name space name enclosing this node.
            string namespaceName = node.AncestorsAndSelf().
                // ancestors whose kind is name space node.
                Where(n => n.Kind == SyntaxKind.NamespaceDeclaration).
                // conver to the syntax and get the name.
                Select(n => (NamespaceDeclarationSyntax)n).First().Name.PlainName;

            // Get the class name enclosing this node.
            var classesNames = node.AncestorsAndSelf().
                // ancestors whose kind is class node.
                Where(n => n.Kind == SyntaxKind.ClassDeclaration).
                // convert each one to the kind class node syntax.
                Select(n => (ClassDeclarationSyntax)n).
                // order all the class decs by their length, in decending order.
                OrderByDescending(n => n.Span.Length).
                // select their names.
                Select(n => n.Identifier.ValueText);

            // Combine all the names to get the scope string.
            var qualifiedName = namespaceName + "." + StringUtil.ConcatenateAll(".", classesNames);
            logger.Info(qualifiedName);
            return qualifiedName;
        }
示例#2
0
        public SyntaxToken GenerateUniqueName(
            SemanticModel semanticModel,
            SyntaxNode location, SyntaxNode containerOpt,
            string baseName, Func <ISymbol, bool> filter,
            IEnumerable <string> usedNames, CancellationToken cancellationToken)
        {
            var container = containerOpt ?? location.AncestorsAndSelf().FirstOrDefault(
                a => BlockFacts.IsExecutableBlock(a) || SyntaxFacts.IsParameterList(a) || SyntaxFacts.IsMethodBody(a));

            var candidates         = GetCollidableSymbols(semanticModel, location, container, cancellationToken);
            var filteredCandidates = filter != null?candidates.Where(filter) : candidates;

            return(GenerateUniqueName(baseName, filteredCandidates.Select(s => s.Name).Concat(usedNames)));
        }
示例#3
0
        /// <summary>Adds a XML documentation header to a diagnosted member declaration.</summary>
        /// <param name="document">The document that includes the diagnostic.</param>
        /// <param name="diagnostic">The detected disgnostic, that should be fixed.</param>
        /// <param name="cancellationToken">A cancellation token to cancel the action.</param>
        /// <returns>A solution including the fixed code.</returns>
        private static async Task <Solution> AddDocumentationHeaderAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken);

            SyntaxNode syntaxNode = root.FindNode(diagnostic.Location.SourceSpan);
            MemberDeclarationSyntax targetNode = syntaxNode.AncestorsAndSelf().OfType <MemberDeclarationSyntax>().First();
            SyntaxNode newSyntaxNode           = DocumentationBuilder.AddCompleteDocumentationHeader(targetNode);
            Document   newDocument             = document.WithSyntaxRoot(root.ReplaceNode(targetNode, newSyntaxNode));

            // Make sure the document is well formatted
            newDocument = await Formatter.FormatAsync(newDocument, newDocument.Project.Solution.Options, cancellationToken);

            return(newDocument.Project.Solution);
        }
示例#4
0
        public override IMethodSymbol GetCallerMethodSymbol(SyntaxNode node, SemanticModel semanticModel)
        {
            if (node == null)
            {
                return(null);
            }

            MethodBlockSyntax declaration = node.AncestorsAndSelf().OfType <MethodBlockSyntax>().FirstOrDefault();

            if (declaration != null)
            {
                return(semanticModel.GetDeclaredSymbol(declaration));
            }

            SubNewStatementSyntax constructor = node.AncestorsAndSelf().OfType <SubNewStatementSyntax>().FirstOrDefault();

            if (constructor != null)
            {
                return(semanticModel.GetDeclaredSymbol(constructor));
            }

            return(null);
        }
示例#5
0
        public async Task <bool> IsAvailableAsync(CancellationToken token)
        {
            // Refactoring should be available only on selected nodes, like return statement or return type of the method
            if (!IsSelectedNodeSuiteableForRefactoring(_selectedNode))
            {
                return(false);
            }

            var methodDeclaration = _selectedNode.AncestorsAndSelf().OfType <MethodDeclarationSyntax>().FirstOrDefault();

            if (methodDeclaration == null)
            {
                // Could be null for constructors, for instance
                return(false);
            }

            return(methodDeclaration.UnwrapReturnTypeIfNeeded(_semanticModel).IsNullable(_semanticModel) &&
                   // Task is a special case. Ignore it! There is an assumption that Task should not be null. Adding
                   // this ensures will just pollute the code
                   !methodDeclaration.ReturnType.TypeEquals(typeof(Task), _semanticModel) &&
                   !methodDeclaration.IsAbstract() &&
                   (!await methodDeclaration.EnsuresReturnValueIsNotNull(_semanticModel, token)));
        }
        private void TrackAssignmentsToLocalsAndPrivateFields(ISymbol symbol, Solution solution, ISet <NodeAndSymbol> trackedNodesAndSymbols)
        {
            var referencedSymbols = SymbolFinder.FindReferencesAsync(symbol, solution).Result;

            foreach (var referencedSymbol in referencedSymbols)
            {
                foreach (var referenceLocation in referencedSymbol.Locations)
                {
                    SyntaxNode node = referenceLocation.Location.SourceTree.GetRoot().FindNode(referenceLocation.Location.SourceSpan);

                    var assignment = node.AncestorsAndSelf().OfType <AssignmentExpressionSyntax>().FirstOrDefault();
                    if (assignment == null || assignment.Parent is UsingStatementSyntax)
                    {
                        continue;
                    }

                    SemanticModel currentModel = referenceLocation.Document.GetSemanticModelAsync().Result;
                    if (!currentModel.Compilation.ContainsSyntaxTree(referenceLocation.Location.SourceTree))
                    {
                        continue;
                    }

                    SemanticModel model          = currentModel.Compilation.GetSemanticModel(referenceLocation.Location.SourceTree);
                    ISymbol       assignedSymbol = model.GetSymbol(assignment.Left);
                    if (assignedSymbol == null || !assignedSymbol.Equals(symbol, SymbolEqualityComparer.Default))
                    {
                        continue;
                    }

                    if (assignment.Parent.IsKind(SyntaxKind.UsingStatement) || !IsInstantiation(assignment.Right, model))
                    {
                        continue;
                    }

                    var leftReferencedSymbol = model.GetSymbol(assignment.Left);
                    if (leftReferencedSymbol == null || !leftReferencedSymbol.Equals(symbol, SymbolEqualityComparer.Default))
                    {
                        continue;
                    }

                    if (IsLocalOrPrivateField(leftReferencedSymbol))
                    {
                        trackedNodesAndSymbols.Add(new NodeAndSymbol {
                            Node = assignment, Symbol = leftReferencedSymbol
                        });
                    }
                }
            }
        }
示例#7
0
        ///Todo: register only on namespace
        public static bool CheckSupport(SyntaxNode node)
        {
            bool foundSupportedNameSpace = false;
            var  nsDeclarations          = node.AncestorsAndSelf().OfType <NamespaceDeclarationSyntax>();

            foreach (var nsd in nsDeclarations)
            {
                foundSupportedNameSpace = nsd.Name.ToFullString().ToLowerInvariant().Contains(SupportedNamespace.ToLowerInvariant());
                if (foundSupportedNameSpace)
                {
                    break;
                }
            }
            return(foundSupportedNameSpace);
        }
示例#8
0
        public override SyntaxNode FindNodeToUpdate(Document document, SyntaxNode node)
        {
            if (_updatableNodeKinds.Contains(node.Kind()))
            {
                return(node);
            }

            // TODO: file bug about this: var invocation = csnode.Ancestors().FirstOrDefault(a => a.Kind == SyntaxKind.InvocationExpression);
            var matchingNode = node.AncestorsAndSelf().FirstOrDefault(n => _updatableAncestorKinds.Contains(n.Kind()));

            if (matchingNode == null)
            {
                return(null);
            }

            var nodeContainingOriginal = GetNodeContainingTargetNode(matchingNode);

            if (nodeContainingOriginal == null)
            {
                return(null);
            }

            return(node.AncestorsAndSelf().Any(n => n == nodeContainingOriginal) ? matchingNode : null);
        }
        public void ComputeRefactoringsForNodeInsideTrivia()
        {
            SyntaxNode node = Root.FindNode(Span, findInsideTrivia: true, getInnermostNodeForTie: true);

            if (node == null)
            {
                return;
            }

            bool fDirectiveTrivia = false;

            using (IEnumerator <SyntaxNode> en = node.AncestorsAndSelf().GetEnumerator())
            {
                while (en.MoveNext())
                {
                    node = en.Current;

                    Debug.WriteLine(node.Kind().ToString());

                    if (!fDirectiveTrivia &&
                        (node is DirectiveTriviaSyntax directiveTrivia))
                    {
                        DirectiveTriviaRefactoring.ComputeRefactorings(this, directiveTrivia);

                        SyntaxKind kind = node.Kind();

                        if (kind == SyntaxKind.RegionDirectiveTrivia ||
                            kind == SyntaxKind.EndRegionDirectiveTrivia)
                        {
                            RegionDirectiveTriviaRefactoring.ComputeRefactorings(this);
                        }

                        RemoveAllPreprocessorDirectivesRefactoring.ComputeRefactorings(this);

                        if (kind == SyntaxKind.RegionDirectiveTrivia)
                        {
                            RegionDirectiveTriviaRefactoring.ComputeRefactorings(this, (RegionDirectiveTriviaSyntax)node);
                        }
                        else if (kind == SyntaxKind.EndRegionDirectiveTrivia)
                        {
                            RegionDirectiveTriviaRefactoring.ComputeRefactorings(this, (EndRegionDirectiveTriviaSyntax)node);
                        }

                        fDirectiveTrivia = true;
                    }
                }
            }
        }
        public override ITypeSymbol GetEnclosingTypeSymbol(SyntaxNode node, SemanticModel semanticModel)
        {
            if (node == null)
            {
                return(null);
            }

            ClassDeclarationSyntax declaration = node.AncestorsAndSelf().OfType <ClassDeclarationSyntax>().FirstOrDefault();

            if (declaration == null)
            {
                return(null);
            }

            return(semanticModel.GetDeclaredSymbol(declaration));
        }
        private static async Task <SyntaxNode> ReplacePropertyInSyntaxRootAsync(SyntaxNode propertyDeclarationSyntaxNode, CancellationToken cancellationToken, SemanticModel semanticModel, SyntaxNode root)
        {
            var property = propertyDeclarationSyntaxNode.AncestorsAndSelf().OfType <PropertyDeclarationSyntax>().First();
            var fieldVariableDeclaratorSyntax = await GetFieldDeclarationSyntaxNodeAsync(property, cancellationToken, semanticModel).ConfigureAwait(false);

            if (fieldVariableDeclaratorSyntax == null)
            {
                return(root);
            }
            var fieldReferences = await GetFieldReferencesAsync(fieldVariableDeclaratorSyntax, cancellationToken, semanticModel).ConfigureAwait(false);

            var nodesToUpdate = fieldReferences.Cast <SyntaxNode>().Union(Enumerable.Repeat(property, 1)).Union(Enumerable.Repeat(fieldVariableDeclaratorSyntax, 1));
            var newRoot       = FixWithTrackNode(root, property, fieldVariableDeclaratorSyntax, nodesToUpdate);

            return(newRoot);
        }
        private SyntaxToken GenerateUniqueName(
            SemanticModel semanticModel,
            SyntaxNode location, SyntaxNode containerOpt,
            string baseName, Func <ISymbol, bool> filter,
            IEnumerable <string> usedNames, CancellationToken cancellationToken)
        {
            var syntaxFacts = this.SyntaxFactsService;

            var container = containerOpt ?? location.AncestorsAndSelf().FirstOrDefault(
                a => syntaxFacts.IsExecutableBlock(a) || syntaxFacts.IsMethodBody(a));

            var candidates = semanticModel.LookupSymbols(location.SpanStart).Concat(
                semanticModel.GetExistingSymbols(container, cancellationToken));

            return(GenerateUniqueName(
                       semanticModel, location, containerOpt, baseName, filter != null ? candidates.Where(filter) : candidates, usedNames, cancellationToken));
        }
示例#13
0
        public static bool CanSafelyMoveLocalToBlock(this ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock)
        {
            if (currentBlock != destinationBlock)
            {
                var localFunctionOrMethodDeclaration = currentBlock.AncestorsAndSelf()
                                                       .FirstOrDefault(node => node.IsKind(SyntaxKind.LocalFunctionStatement) || node.IsKind(SyntaxKind.MethodDeclaration));
                var localFunctionStatement = destinationBlock.FirstAncestorOrSelf <LocalFunctionStatementSyntax>();

                if (localFunctionOrMethodDeclaration != localFunctionStatement &&
                    HasTypeParameterWithName(localFunctionOrMethodDeclaration, localSymbol.Type.Name) &&
                    HasTypeParameterWithName(localFunctionStatement, localSymbol.Type.Name))
                {
                    return(false);
                }
            }

            return(true);
        public SyntaxToken GenerateUniqueName(
            SemanticModel semanticModel, SyntaxNode location, SyntaxNode containerOpt,
            string baseName, CancellationToken cancellationToken)
        {
            var syntaxFacts = this.SyntaxFactsService;

            var container = containerOpt ?? location.AncestorsAndSelf().FirstOrDefault(
                a => syntaxFacts.IsExecutableBlock(a) || syntaxFacts.IsMethodBody(a));
            var existingSymbols = semanticModel.GetExistingSymbols(container, cancellationToken);

            var reservedNames = semanticModel.LookupSymbols(location.SpanStart)
                                .Select(s => s.Name)
                                .Concat(existingSymbols.Select(s => s.Name));

            return(syntaxFacts.ToIdentifierToken(
                       NameGenerator.EnsureUniqueness(baseName, reservedNames, syntaxFacts.IsCaseSensitive)));
        }
示例#15
0
            private bool DetermineIsInConstructor(SemanticDocument semanticDocument, SyntaxNode simpleName)
            {
                if (!ContainingType.OriginalDefinition.Equals(TypeToGenerateIn.OriginalDefinition))
                {
                    return(false);
                }

                // If we're in an lambda/local function we're not actually 'in' the constructor.
                // i.e. we can't actually write to read-only fields here.
                var syntaxFacts = semanticDocument.Document.GetRequiredLanguageService <ISyntaxFactsService>();

                if (simpleName.AncestorsAndSelf().Any(n => syntaxFacts.IsAnonymousOrLocalFunction(n)))
                {
                    return(false);
                }

                return(syntaxFacts.IsInConstructor(simpleName));
            }
示例#16
0
        public static bool ContainedInValidType(this SyntaxNode node)
        {
            Contract.ThrowIfNull(node);
            foreach (var ancestor in node.AncestorsAndSelf())
            {
                if (ancestor is TypeDeclarationSyntax)
                {
                    return(true);
                }

                if (ancestor is NamespaceDeclarationSyntax)
                {
                    return(false);
                }
            }

            return(true);
        }
示例#17
0
文件: TypeDef.cs 项目: zihotki/Excess
        private static SyntaxNode Typedef(SyntaxNode node, Scope scope)
        {
            var field = node
                        .AncestorsAndSelf()
                        .OfType <FieldDeclarationSyntax>()
                        .FirstOrDefault();

            if (field == null)
            {
                scope.AddError("xs01", "malformed typedef", node);
                //td: error, malformed typedef
                return(node);
            }


            if (field.Declaration.Variables.Count != 1)
            {
                scope.AddError("xs01", "malformed typedef", node);
                return(node);
            }

            var variable = field
                           .Declaration
                           .Variables[0];

            Debug.Assert(variable.Initializer == null || variable.Initializer.IsMissing);

            var type       = RoslynCompiler.UnMark(field.Declaration.Type);
            var identifier = variable.Identifier;

            var parentScope = scope.CreateScope <SyntaxToken, SyntaxNode, SemanticModel>(field.Parent);

            Debug.Assert(parentScope != null);

            parentScope.set("__tdef" + identifier.ToString(), type);

            //schedule deletion
            var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>();

            document.change(field.Parent, RoslynCompiler.RemoveMember(field));

            //return intact
            return(node);
        }
示例#18
0
        public static void ComputeRefactoringsForNodeInsideTrivia(this RefactoringContext context)
        {
            SyntaxNode node = context.FindNode(findInsideTrivia: true);

            if (node == null)
            {
                return;
            }

            bool fDirectiveTrivia = false;

            using (IEnumerator <SyntaxNode> en = node.AncestorsAndSelf().GetEnumerator())
            {
                while (en.MoveNext())
                {
                    node = en.Current;

                    Debug.WriteLine(node.Kind().ToString());

                    if (!fDirectiveTrivia)
                    {
                        var directiveTrivia = node as DirectiveTriviaSyntax;
                        if (directiveTrivia != null)
                        {
                            DirectiveTriviaRefactoring.ComputeRefactorings(context, directiveTrivia);

                            if (node.IsKind(SyntaxKind.RegionDirectiveTrivia, SyntaxKind.EndRegionDirectiveTrivia))
                            {
                                RegionDirectiveTriviaRefactoring.ComputeRefactorings(context);
                            }

                            RemoveAllPreprocessorDirectivesRefactoring.ComputeRefactorings(context);

                            if (node.IsKind(SyntaxKind.RegionDirectiveTrivia, SyntaxKind.EndRegionDirectiveTrivia))
                            {
                                RegionDirectiveTriviaRefactoring.ComputeRefactorings(context, (RegionDirectiveTriviaSyntax)node);
                            }

                            fDirectiveTrivia = true;
                        }
                    }
                }
            }
        }
        private static void ExcludeDisposedAndClosedLocalsAndPrivateFields(SyntaxNode typeDeclaration, SemanticModel semanticModel, ISet <ISymbol> excludedSymbols)
        {
            var invocationsAndConditionalAccesses = typeDeclaration
                                                    .AncestorsAndSelf()
                                                    .OfType <ExpressionStatementSyntax>()
                                                    .Where(n => n.Expression.IsKind(SyntaxKind.InvocationExpression) || n.Expression.IsKind(SyntaxKind.ConditionalAccessExpression))
                                                    .Select(expr => expr.Expression);

            foreach (var invocationOrConditionalAccess in invocationsAndConditionalAccesses)
            {
                SimpleNameSyntax name       = null;
                ExpressionSyntax expression = null;

                if (invocationOrConditionalAccess is InvocationExpressionSyntax invocation)
                {
                    var memberAccessNode = invocation.Expression as MemberAccessExpressionSyntax;
                    name       = memberAccessNode?.Name;
                    expression = memberAccessNode?.Expression;
                }
                else if (invocationOrConditionalAccess is ConditionalAccessExpressionSyntax conditionalAccess)
                {
                    if (!(conditionalAccess.WhenNotNull is InvocationExpressionSyntax conditionalInvocation))
                    {
                        continue;
                    }

                    var memberBindingNode = conditionalInvocation.Expression as MemberBindingExpressionSyntax;
                    name       = memberBindingNode?.Name;
                    expression = conditionalAccess.Expression;
                }
                if (name == null || !DisposeMethods.Contains(name.Identifier.Text))
                {
                    continue;
                }

                var referencedSymbol = semanticModel.GetSymbol(expression);
                if (referencedSymbol != null && IsLocalOrPrivateField(referencedSymbol))
                {
                    excludedSymbols.Add(referencedSymbol);
                }
            }
        }
        protected override ITypeSymbol GetQueryClauseInfo(
            SemanticModel semanticModel,
            SyntaxNode node,
            CancellationToken cancellationToken
            )
        {
            var query = node.AncestorsAndSelf().OfType <QueryExpressionSyntax>().First();

            if (
                InfoBoundSuccessfully(
                    semanticModel.GetQueryClauseInfo(query.FromClause, cancellationToken)
                    )
                )
            {
                return(null);
            }

            foreach (var clause in query.Body.Clauses)
            {
                if (
                    InfoBoundSuccessfully(
                        semanticModel.GetQueryClauseInfo(clause, cancellationToken)
                        )
                    )
                {
                    return(null);
                }
            }

            if (
                InfoBoundSuccessfully(
                    semanticModel.GetSymbolInfo(query.Body.SelectOrGroup, cancellationToken)
                    )
                )
            {
                return(null);
            }

            var fromClause = query.FromClause;

            return(semanticModel.GetTypeInfo(fromClause.Expression, cancellationToken).Type);
        }
        public override Task <CodeAction> CalculateActionAsync(Document document, SyntaxNode root, SyntaxNode selectedNode, CancellationToken cancellationToken)
        {
            var parentStatement = selectedNode.AncestorsAndSelf().OfType <StatementSyntax>().FirstOrDefault();

            if (parentStatement == null)
            {
                return(Task.FromResult <CodeAction>(null));
            }

            var childStatements = parentStatement.ChildNodes().OfType <StatementSyntax>().ToList();

            if (childStatements.Count != 1)
            {
                return(Task.FromResult <CodeAction>(null));
            }

            var block = childStatements.First() as BlockSyntax;

            if (block == null)
            {
                return(Task.FromResult <CodeAction>(null));
            }

            var innerStatements = block.ChildNodes().OfType <StatementSyntax>().ToList();

            if (innerStatements.Count != 1)
            {
                return(Task.FromResult <CodeAction>(null));
            }

            if (IsElseClauseEscapeCase(innerStatements.First(), parentStatement))
            {
                return(Task.FromResult <CodeAction>(null));
            }

            var action =
                CodeAction.Create(
                    Resources.RemoveBraces,
                    token => RemoveBracesAsync(document, root, innerStatements.First(), parentStatement, token));

            return(Task.FromResult(action));
        }
        private static SyntaxNode GetNodeForLeadingTrivia(this SyntaxNode node)
        {
            foreach (SyntaxNode ancestor in node.AncestorsAndSelf())
            {
                if (ancestor.IsKind(SyntaxKind.IfStatement))
                {
                    return(((IfStatementSyntax)ancestor).ParentElse() ?? ancestor);
                }
                else if (ancestor.IsMemberDeclaration())
                {
                    return(ancestor);
                }
                else if (ancestor.IsStatement())
                {
                    return(ancestor);
                }
            }

            return(node);
        }
        private static void ExcludeReturnedPassedAndAliasedLocalsAndPrivateFields(SyntaxNode typeDeclaration, SemanticModel semanticModel, ISet <ISymbol> excludedSymbols)
        {
            var identifiersAndSimpleMemberAccesses = typeDeclaration
                                                     .AncestorsAndSelf()
                                                     .Where(n => n.IsKind(SyntaxKind.IdentifierName) ||
                                                            n.IsKind(SyntaxKind.Argument) ||
                                                            n.IsKind(SyntaxKind.SimpleMemberAccessExpression));

            foreach (var identifierOrSimpleMemberAccess in identifiersAndSimpleMemberAccesses)
            {
                SyntaxNode expression = null;
                if (identifierOrSimpleMemberAccess.IsKind(SyntaxKind.IdentifierName))
                {
                    expression = (IdentifierNameSyntax)identifierOrSimpleMemberAccess;
                }
                else if (identifierOrSimpleMemberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var memberAccess = (MemberAccessExpressionSyntax)identifierOrSimpleMemberAccess;
                    if (!memberAccess.Expression.IsKind(SyntaxKind.ThisExpression))
                    {
                        continue;
                    }
                    expression = memberAccess;
                }
                else if (identifierOrSimpleMemberAccess.IsKind(SyntaxKind.Argument))
                {
                    expression = identifierOrSimpleMemberAccess as ArgumentSyntax;
                }

                if (!IsStandaloneExpression(expression))
                {
                    continue;
                }

                var referencedSymbol = semanticModel.GetSymbol(expression is ArgumentSyntax ? (expression as ArgumentSyntax).Expression : expression);
                if (referencedSymbol != null && IsLocalOrPrivateField(referencedSymbol))
                {
                    excludedSymbols.Add(referencedSymbol);
                }
            }
        }
 private static IEnumerable <ParameterSyntax> GetParametersInScope(SyntaxNode node)
 {
     foreach (var ancestor in node.AncestorsAndSelf())
     {
         if (ancestor.IsKind(SyntaxKind.SimpleLambdaExpression))
         {
             yield return(((SimpleLambdaExpressionSyntax)ancestor).Parameter);
         }
         else
         {
             var parameterList = ancestor.GetParameterList();
             if (parameterList != null)
             {
                 foreach (var parameter in parameterList.Parameters)
                 {
                     yield return(parameter);
                 }
             }
         }
     }
 }
示例#25
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Project project = context.Document.Project;

            TextDocument exceptionsDocument = project.AdditionalDocuments.FirstOrDefault(doc => doc.Name.Equals(AvoidDuplicateCodeAnalyzer.ExceptionsFileName, StringComparison.Ordinal));

            if (exceptionsDocument == null)
            {
                return;
            }

            SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                TextSpan diagnosticSpan = diagnostic.Location.SourceSpan;

                if (root != null)
                {
                    SyntaxNode syntaxNode = root.FindToken(diagnosticSpan.Start).Parent;
                    if (syntaxNode != null)
                    {
                        MethodDeclarationSyntax methodDeclarationSyntax =
                            syntaxNode.AncestorsAndSelf().OfType <MethodDeclarationSyntax>().FirstOrDefault();
                        if (methodDeclarationSyntax != null)
                        {
                            string methodName = methodDeclarationSyntax.Identifier.ValueText;

                            string title = $@"Add {methodName} to duplicate code exceptions list";
                            context.RegisterCodeFix(
                                CodeAction.Create(
                                    title: title,
                                    createChangedSolution: c => GetFix(exceptionsDocument, methodName, c),
                                    equivalenceKey: title),
                                diagnostic);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Adds "using Task = System.Threading.Tasks.Task;" to the document if it is not already present.
        /// </summary>
        /// <param name="syntaxNode">Any syntax node within the document.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns>The original <paramref name="syntaxNode"/> given, as it is represented in the updated syntax tree.</returns>
        internal static async Task<SyntaxNode> AddUsingTaskEqualsDirectiveAsync(SyntaxNode syntaxNode, CancellationToken cancellationToken)
        {
            var existingUsings = syntaxNode.AncestorsAndSelf().OfType<UsingDirectiveSyntax>().Concat(
                syntaxNode.DescendantNodes(n => n is CompilationUnitSyntax || n is NamespaceDeclarationSyntax).OfType<UsingDirectiveSyntax>());
            if (existingUsings.Any(u => u.Alias?.Name?.Identifier.ValueText == nameof(Task)))
            {
                // The user has already aliased Task.
                return syntaxNode;
            }

            var trackAnnotation = new SyntaxAnnotation();
            syntaxNode = syntaxNode.WithAdditionalAnnotations(trackAnnotation);

            var usingTaskDirective = SyntaxFactory.UsingDirective(
                QualifyName(Namespaces.SystemThreadingTasks, SyntaxFactory.IdentifierName(nameof(Task))))
                .WithAlias(SyntaxFactory.NameEquals(nameof(Task)));

            var syntaxRoot = (CompilationUnitSyntax)await syntaxNode.SyntaxTree.GetRootAsync(cancellationToken);
            syntaxRoot = syntaxRoot.AddUsings(usingTaskDirective);

            return syntaxRoot.GetAnnotatedNodes(trackAnnotation).Single();
        }
示例#27
0
        public static bool CanSafelyMoveLocalToBlock(this ILocalSymbol localSymbol, SyntaxNode currentBlock, SyntaxNode destinationBlock)
        {
            if (currentBlock != destinationBlock)
            {
                var localFunctionOrMethodDeclaration = currentBlock.AncestorsAndSelf()
                                                       .FirstOrDefault(node => node.IsKind(SyntaxKind.LocalFunctionStatement) || node.IsKind(SyntaxKind.MethodDeclaration));
                var localFunctionStatement = destinationBlock.FirstAncestorOrSelf <LocalFunctionStatementSyntax>();

                if (localFunctionOrMethodDeclaration != localFunctionStatement &&
                    HasTypeParameterWithName(localFunctionOrMethodDeclaration, localSymbol.Type.Name) &&
                    HasTypeParameterWithName(localFunctionStatement, localSymbol.Type.Name))
                {
                    return(false);
                }
            }

            return(true);

            bool HasTypeParameterWithName(SyntaxNode node, string name)
            {
                SeparatedSyntaxList <TypeParameterSyntax>?typeParameters;

                switch (node)
                {
                case MethodDeclarationSyntax methodDeclaration:
                    typeParameters = methodDeclaration.TypeParameterList?.Parameters;
                    break;

                case LocalFunctionStatementSyntax localFunctionStatement:
                    typeParameters = localFunctionStatement.TypeParameterList?.Parameters;
                    break;

                default:
                    return(false);
                }

                return(typeParameters.HasValue && typeParameters.Value.Any(typeParameter => typeParameter.Identifier.ValueText == name));
            }
        }
        private static IEnumerable <ExpressionSyntax> GetUnreachableExpressions(SyntaxNode constantExpression, bool constantValue)
        {
            // This is ugly with LINQ, hence the loop
            foreach (var current in constantExpression.AncestorsAndSelf())
            {
                if (current.Parent is ParenthesizedExpressionSyntax)
                {
                    continue;
                }

                var binary = current.Parent as BinaryExpressionSyntax;
                if (!IsShortcuttingExpression(binary, constantValue))
                {
                    break;
                }

                if (binary.Left == current)
                {
                    yield return(binary.Right);
                }
            }
        }
        static SyntaxNode GetNewRoot(SyntaxNode root, SyntaxNode node)
        {
            var decl = node.AncestorsAndSelf().OfType <LocalDeclarationStatementSyntax>().FirstOrDefault();

            if (decl != null)
            {
                return(root.RemoveNode(decl, SyntaxRemoveOptions.KeepNoTrivia));
            }
            if (node.Parent.IsKind(SyntaxKind.ElseClause))
            {
                return(root.RemoveNode(node.Parent, SyntaxRemoveOptions.KeepNoTrivia));
            }

            var statement = node as StatementSyntax;

            if (statement != null)
            {
                return(root.RemoveNode(statement, SyntaxRemoveOptions.KeepNoTrivia));
            }

            return(root.RemoveNode(node.Parent, SyntaxRemoveOptions.KeepNoTrivia));
        }
        private static IEnumerable <ParameterSyntax> GetParametersInScope(SyntaxNode node)
        {
            foreach (SyntaxNode ancestor in node.AncestorsAndSelf())
            {
                if (ancestor.IsKind(SyntaxKind.SimpleLambdaExpression))
                {
                    yield return(((SimpleLambdaExpressionSyntax)ancestor).Parameter);
                }
                else
                {
                    BaseParameterListSyntax parameterList = GetParameterList(ancestor);

                    if (parameterList != null)
                    {
                        for (int i = 0; i < parameterList.Parameters.Count; i++)
                        {
                            yield return(parameterList.Parameters[i]);
                        }
                    }
                }
            }
        }
        private async Task <Solution> UsePropertyAsync(Document document, SyntaxNode statement)
        {
            // Create a new property
            // Using property naming conventions
            // Including possible initializers
            // And attributes

            var variableDeclarator  = statement.AncestorsAndSelf().OfType <VariableDeclaratorSyntax>().First();
            var fieldStatement      = variableDeclarator.AncestorsAndSelf().OfType <FieldDeclarationSyntax>().First();
            var variableDeclaration = variableDeclarator.AncestorsAndSelf().OfType <VariableDeclarationSyntax>().First();

            var newProperty = SyntaxFactory.PropertyDeclaration(variableDeclaration.Type, variableDeclarator.Identifier)
                              .WithAttributeLists(fieldStatement.AttributeLists)
                              .WithModifiers(fieldStatement.Modifiers)
                              .WithAdditionalAnnotations(Formatter.Annotation)
                              .WithAccessorList(
                SyntaxFactory.AccessorList(
                    SyntaxFactory.List(new[]
            {
                SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
                SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
            })));

            if (variableDeclarator.Initializer != null)
            {
                newProperty =
                    newProperty.WithInitializer(variableDeclarator.Initializer)
                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken));
            }

            var editor = await DocumentEditor.CreateAsync(document);

            editor.InsertAfter(statement, newProperty);
            editor.RemoveNode(variableDeclarator);
            return(editor.GetChangedDocument().Project.Solution);
        }
 /// <summary>
 /// Try to get the statement syntax node that is enclosing the given method invocation.
 /// </summary>
 /// <param name="invocation"></param>
 /// <param name="statement"></param>
 /// <returns></returns>
 private bool TryGetStatementEnclosingInvocation(SyntaxNode invocation, out SyntaxNode statement)
 {
     var statements = invocation.AncestorsAndSelf().OfType<StatementSyntax>().ToList();
     if(statements.Any())
     {
         statement = statements.First();
         return true;
     }
     statement = null;
     return false;
 }