private static Solution UpdateMainDocument(Document document, SyntaxNode root, MethodDeclarationSyntax method, IEnumerable<IGrouping<Document, ReferenceLocation>> documentGroups)
 {
     var mainDocGroup = documentGroups.FirstOrDefault(dg => dg.Key.Equals(document));
     SyntaxNode newRoot;
     if (mainDocGroup == null)
     {
         newRoot = root.ReplaceNode(method, method.AddModifiers(staticToken));
     }
     else
     {
         var diagnosticNodes = mainDocGroup.Select(referenceLocation => root.FindNode(referenceLocation.Location.SourceSpan)).ToList();
         newRoot = root.TrackNodes(diagnosticNodes.Union(new[] { method }));
         newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(method), method.AddModifiers(staticToken));
         foreach (var diagnosticNode in diagnosticNodes)
         {
             var token = newRoot.FindToken(diagnosticNode.GetLocation().SourceSpan.Start);
             var tokenParent = token.Parent;
             if (token.Parent.IsKind(SyntaxKind.IdentifierName)) continue;
             var invocationExpression = newRoot.GetCurrentNode(diagnosticNode).FirstAncestorOrSelfOfType<InvocationExpressionSyntax>()?.Expression;
             if (invocationExpression == null || invocationExpression.IsKind(SyntaxKind.IdentifierName)) continue;
             var memberAccess = invocationExpression as MemberAccessExpressionSyntax;
             if (memberAccess == null) continue;
             var newMemberAccessParent = memberAccess.Parent.ReplaceNode(memberAccess, memberAccess.Name)
                 .WithAdditionalAnnotations(Formatter.Annotation);
             newRoot = newRoot.ReplaceNode(memberAccess.Parent, newMemberAccessParent);
         }
     }
     var newSolution = document.Project.Solution.WithDocumentSyntaxRoot(document.Id, newRoot);
     return newSolution;
 }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan);

            var variableDeclarator = syntaxNode.FirstAncestorOrSelf<VariableDeclaratorSyntax>();
            var variableDeclaration = variableDeclarator?.Parent as VariableDeclarationSyntax;
            if (variableDeclaration == null)
            {
                return;
            }

            if (variableDeclaration.Variables.Count == 1)
            {
                var fieldDeclaration = variableDeclaration.Parent as FieldDeclarationSyntax;
                if (fieldDeclaration == null)
                {
                    return;
                }

                context.RegisterCodeFix(
                    CodeAction.Create(
                        Title,
                        c =>
                        {
                            var newFieldDeclaration = fieldDeclaration.AddModifiers(
                                SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword));
                            var newRoot = root.ReplaceNode(fieldDeclaration, newFieldDeclaration);
                            return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                        }),
                    context.Diagnostics);
            }
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var nameEquals = root.FindNode(diagnosticSpan) as NameEqualsSyntax;
            var anonymousObjectCreation = nameEquals?.Parent?.Parent as AnonymousObjectCreationExpressionSyntax;
            if (anonymousObjectCreation == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newInitializersWithSeparators = anonymousObjectCreation.Initializers.GetWithSeparators()
                            .Select(item => GetNewSyntaxListItem(item));
                        var newAnonymousObjectCreation = anonymousObjectCreation
                            .WithInitializers(SyntaxFactory.SeparatedList<AnonymousObjectMemberDeclaratorSyntax>(newInitializersWithSeparators))
                            .WithTriviaFrom(anonymousObjectCreation);

                        var newRoot = root.ReplaceNode(
                            anonymousObjectCreation,
                            newAnonymousObjectCreation);
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true) as PrefixUnaryExpressionSyntax;

            if (syntaxNode == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var expression = syntaxNode.Operand.RemoveParentheses();
                        var newBinary = ChangeOperator((BinaryExpressionSyntax)expression);

                        if (syntaxNode.Parent is ExpressionSyntax &&
                            !ExpressionTypesWithNoParens.Any(type => type.IsInstanceOfType(syntaxNode.Parent)))
                        {
                            newBinary = SyntaxFactory.ParenthesizedExpression(newBinary);
                        }

                        var newRoot = root.ReplaceNode(
                            syntaxNode,
                            newBinary.WithAdditionalAnnotations(Formatter.Annotation));

                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
		public static IEnumerable<SyntaxNode> GetUnnecessaryImports(SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken)
		{
			var diagnostics = semanticModel.GetDiagnostics(cancellationToken: cancellationToken);
			if (!diagnostics.Any())
			{
				return null;
			}

			var unnecessaryImports = new HashSet<UsingDirectiveSyntax>();

			foreach (var diagnostic in diagnostics)
			{
				if (diagnostic.Id == "CS8019")
				{
					var node = root.FindNode(diagnostic.Location.SourceSpan) as UsingDirectiveSyntax;

					if (node != null)
					{
						unnecessaryImports.Add(node);
					}
				}
			}

			if (cancellationToken.IsCancellationRequested || !unnecessaryImports.Any())
			{
				return null;
			}

			return unnecessaryImports;
		}
        private Document CreateCodeFix(Document document, Diagnostic diagnostic, SyntaxNode syntaxRoot)
        {
            SyntaxNode newSyntaxRoot = syntaxRoot;
            var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan);
            var indentationOptions = IndentationOptions.FromDocument(document);

            switch (node.Kind())
            {
            case SyntaxKind.ClassDeclaration:
            case SyntaxKind.InterfaceDeclaration:
            case SyntaxKind.StructDeclaration:
            case SyntaxKind.EnumDeclaration:
                newSyntaxRoot = this.RegisterBaseTypeDeclarationCodeFix(syntaxRoot, (BaseTypeDeclarationSyntax)node, indentationOptions);
                break;

            case SyntaxKind.AccessorList:
                newSyntaxRoot = this.RegisterPropertyLikeDeclarationCodeFix(syntaxRoot, (BasePropertyDeclarationSyntax)node.Parent, indentationOptions);
                break;

            case SyntaxKind.Block:
                newSyntaxRoot = this.RegisterMethodLikeDeclarationCodeFix(syntaxRoot, (BaseMethodDeclarationSyntax)node.Parent, indentationOptions);
                break;

            case SyntaxKind.NamespaceDeclaration:
                newSyntaxRoot = this.RegisterNamespaceDeclarationCodeFix(syntaxRoot, (NamespaceDeclarationSyntax)node, indentationOptions);
                break;
            }

            return document.WithSyntaxRoot(newSyntaxRoot);
        }
 /// <summary>
 /// Register the property fix for property documentation.
 /// </summary>
 /// <param name="root">the syntax root node.</param>
 /// <param name="context">the code fix context, containing the location of the fix.</param>
 /// <param name="diagnostic">the diagnostic, where the invalid code was located.</param>
 private void RegisterMethodDocumentationCodeFix(SyntaxNode root, CodeFixContext context, Diagnostic diagnostic)
 {
     var startNode = root.FindNode(diagnostic.Location.SourceSpan);
     var constructorDeclaration = startNode as ConstructorDeclarationSyntax;
     if (constructorDeclaration != null)
         this.RegisterConstructorCodeFix(constructorDeclaration, root, context, diagnostic);
 }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var literal = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true) as LiteralExpressionSyntax;
            if (literal == null)
            {
                return;
            }

            var newLiteral = SyntaxFactory.Literal(
                literal.Token.Text.ToUpperInvariant(),
                (long)literal.Token.Value);

            if (!newLiteral.IsKind(SyntaxKind.None))
            {
                context.RegisterCodeFix(
                    CodeAction.Create(
                        Title,
                        c =>
                        {
                            var newRoot = root.ReplaceNode(literal,
                                literal.WithToken(newLiteral).WithTriviaFrom(literal));
                            return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                        }),
                    context.Diagnostics);
            }
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan);
            var initializer = syntaxNode as ConstructorInitializerSyntax;
            if (initializer != null)
            {
                RegisterActionForBaseCall(context, root, initializer);
                return;
            }

            var method = syntaxNode.FirstAncestorOrSelf<BaseMethodDeclarationSyntax>();

            if (method is ConstructorDeclarationSyntax)
            {
                RegisterActionForConstructor(context, root, method);
                return;
            }

            if (method is DestructorDeclarationSyntax)
            {
                RegisterActionForDestructor(context, root, method);
            }
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var prefix = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true) as PrefixUnaryExpressionSyntax;

            if (prefix == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        ExpressionSyntax expression;
                        uint count;
                        GetExpression(prefix, out expression, out count);

                        if (count%2 == 1)
                        {
                            expression = SyntaxFactory.PrefixUnaryExpression(
                                prefix.Kind(),
                                expression);
                        }

                        var newRoot = root.ReplaceNode(prefix, expression
                            .WithAdditionalAnnotations(Formatter.Annotation));
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
 /// <summary>
 /// Register the property fix for property documentation.
 /// </summary>
 /// <param name="root">the syntax root node.</param>
 /// <param name="context">the code fix context, containing the location of the fix.</param>
 /// <param name="diagnostic">the diagnostic, where the invalid code was located.</param>
 private void RegisterMethodDocumentationCodeFix(SyntaxNode root, CodeFixContext context, Diagnostic diagnostic)
 {
     var startNode = root.FindNode(diagnostic.Location.SourceSpan);
     var methodDeclarationSyntax = startNode as MethodDeclarationSyntax;
     if (methodDeclarationSyntax != null)
         this.RegisterMethodCodeFix(methodDeclarationSyntax, root, context, diagnostic);
 }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true) as ExpressionSyntax;
            if (syntaxNode == null)
            {
                return;
            }

            var parent = syntaxNode.Parent;
            syntaxNode = syntaxNode.RemoveParentheses();

            var binary = syntaxNode as BinaryExpressionSyntax;
            if (binary != null)
            {
                RegisterBinaryExpressionReplacement(context, root, syntaxNode, binary);
                return;
            }

            var conditional = syntaxNode as ConditionalExpressionSyntax;
            if (conditional != null)
            {
                RegisterConditionalExpressionRemoval(context, root, conditional);
                return;
            }

            var literal = syntaxNode as LiteralExpressionSyntax;
            if (literal == null)
            {
                return;
            }

            if (parent is PrefixUnaryExpressionSyntax)
            {
                RegisterBooleanInversion(context, root, literal);
                return;
            }

            var conditionalParent = parent as ConditionalExpressionSyntax;
            if (conditionalParent != null)
            {
                RegisterConditionalExpressionRewrite(context, root, literal, conditionalParent);
                return;
            }

            var binaryParent = parent as BinaryExpressionSyntax;
            if (binaryParent != null)
            {
                RegisterBinaryExpressionRemoval(context, root, literal, binaryParent);
                return;
            }

            var forStatement = parent as ForStatementSyntax;
            if (forStatement != null)
            {
                RegisterForStatementConditionRemoval(context, root, forStatement);
                return;
            }
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var attribute = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true) as AttributeSyntax;
            var attributeList = attribute?.Parent as AttributeListSyntax;
            if (attribute == null ||
                attributeList == null)
            {
                return;
            }

            var semanticModel = await context.Document.GetSemanticModelAsync().ConfigureAwait(false);
            var optionalAttribute = semanticModel?.Compilation?.GetTypeByMetadataName(
                KnownType.System_Runtime_InteropServices_OptionalAttribute.TypeName);
            if (optionalAttribute == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newRoot = root.ReplaceNode(
                            attributeList,
                            GetNewAttributeList(attributeList, optionalAttribute, semanticModel));
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
        private async Task<Document> AddConstructorsAsync(Document document, IEnumerable<Diagnostic> diagnostics, SyntaxNode root, CancellationToken cancellationToken)
        {
            var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
            var generator = editor.Generator;
            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var diagnosticSpan = diagnostics.First().Location.SourceSpan; // All the diagnostics are reported at the same location -- the name of the declared class -- so it doesn't matter which one we pick
            var node = root.FindNode(diagnosticSpan);
            var targetNode = editor.Generator.GetDeclaration(node, DeclarationKind.Class);
            var typeSymbol = model.GetDeclaredSymbol(targetNode) as INamedTypeSymbol;

            foreach (var diagnostic in diagnostics)
            {
                var missingCtorSignature = (ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature)Enum.Parse(typeof(ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature), diagnostic.Properties["Signature"]);

                switch (missingCtorSignature)
                {
                    case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithNoParameter:
                        // Add missing CtorWithNoParameter
                        var newConstructorNode1 = generator.ConstructorDeclaration(typeSymbol.Name, accessibility: Accessibility.Public);
                        editor.AddMember(targetNode, newConstructorNode1);
                        break;
                    case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringParameter:
                        // Add missing CtorWithStringParameter 
                        var newConstructorNode2 = generator.ConstructorDeclaration(
                                                    containingTypeName: typeSymbol.Name,
                                                    parameters: new[]
                                                    {
                                                    generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation)))
                                                    },
                                                    accessibility: Accessibility.Public,
                                                    baseConstructorArguments: new[]
                                                    {
                                                    generator.Argument(generator.IdentifierName("message"))
                                                    });
                        editor.AddMember(targetNode, newConstructorNode2);
                        break;
                    case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringAndExceptionParameters:
                        // Add missing CtorWithStringAndExceptionParameters 
                        var newConstructorNode3 = generator.ConstructorDeclaration(
                                                    containingTypeName: typeSymbol.Name,
                                                    parameters: new[]
                                                    {
                                                    generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation))),
                                                    generator.ParameterDeclaration("innerException", generator.TypeExpression(WellKnownTypes.Exception(editor.SemanticModel.Compilation)))
                                                    },
                                                    accessibility: Accessibility.Public,
                                                    baseConstructorArguments: new[]
                                                    {
                                                    generator.Argument(generator.IdentifierName("message")),
                                                    generator.Argument(generator.IdentifierName("innerException"))
                                                    });
                        editor.AddMember(targetNode, newConstructorNode3);
                        break;
                }
            }

            return editor.GetChangedDocument();
        }
        private static async Task<Document> Fix(CodeFixContext context, SyntaxNode root, SyntaxGenerator generator, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            SyntaxNode node = root.FindNode(context.Span);
            Diagnostic diagnostic = context.Diagnostics.First();
            switch (diagnostic.Properties[OperatorOverloadsHaveNamedAlternatesAnalyzer.DiagnosticKindText])
            {
                case OperatorOverloadsHaveNamedAlternatesAnalyzer.AddAlternateText:
                    SyntaxNode methodDeclaration = generator.GetDeclaration(node, DeclarationKind.Operator) ?? generator.GetDeclaration(node, DeclarationKind.ConversionOperator);
                    var operatorOverloadSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken);
                    INamedTypeSymbol typeSymbol = operatorOverloadSymbol.ContainingType;

                    // For C# the following `typeDeclarationSyntax` and `typeDeclaration` nodes are identical, but for VB they're different so in
                    // an effort to keep this as language-agnostic as possible, the heavy-handed approach is used.
                    SyntaxNode typeDeclarationSyntax = typeSymbol.DeclaringSyntaxReferences.First().GetSyntax(cancellationToken);
                    SyntaxNode typeDeclaration = generator.GetDeclaration(typeDeclarationSyntax, DeclarationKind.Class);

                    SyntaxNode addedMember;
                    ImmutableArray<SyntaxNode> bodyStatements = ImmutableArray.Create(
                        generator.ThrowStatement(generator.ObjectCreationExpression(semanticModel.Compilation.GetTypeByMetadataName("System.NotImplementedException"))));
                    if (OperatorOverloadsHaveNamedAlternatesAnalyzer.IsPropertyExpected(operatorOverloadSymbol.Name))
                    {
                        // add a property
                        addedMember = generator.PropertyDeclaration(
                            name: OperatorOverloadsHaveNamedAlternatesAnalyzer.IsTrueText,
                            type: generator.TypeExpression(SpecialType.System_Boolean),
                            accessibility: Accessibility.Public,
                            modifiers: DeclarationModifiers.ReadOnly,
                            getAccessorStatements: bodyStatements);
                    }
                    else
                    {
                        // add a method
                        ExpectedMethodSignature expectedSignature = GetExpectedMethodSignature(operatorOverloadSymbol, semanticModel.Compilation);
                        addedMember = generator.MethodDeclaration(
                            name: expectedSignature.Name,
                            parameters: expectedSignature.Parameters.Select(p => generator.ParameterDeclaration(p.Item1, generator.TypeExpression(p.Item2))),
                            returnType: generator.TypeExpression(expectedSignature.ReturnType),
                            accessibility: Accessibility.Public,
                            modifiers: expectedSignature.IsStatic ? DeclarationModifiers.Static : DeclarationModifiers.None,
                            statements: bodyStatements);
                    }

                    SyntaxNode newTypeDeclaration = generator.AddMembers(typeDeclaration, addedMember);
                    return context.Document.WithSyntaxRoot(root.ReplaceNode(typeDeclaration, newTypeDeclaration));
                case OperatorOverloadsHaveNamedAlternatesAnalyzer.FixVisibilityText:
                    SyntaxNode badVisibilityNode = generator.GetDeclaration(node, DeclarationKind.Method) ?? generator.GetDeclaration(node, DeclarationKind.Property);
                    ISymbol badVisibilitySymbol = semanticModel.GetDeclaredSymbol(badVisibilityNode, cancellationToken);
                    SymbolEditor symbolEditor = SymbolEditor.Create(context.Document);
                    ISymbol newSymbol = await symbolEditor.EditOneDeclarationAsync(badVisibilitySymbol,
                        (documentEditor, syntaxNode) => documentEditor.SetAccessibility(badVisibilityNode, Accessibility.Public)).ConfigureAwait(false);
                    Document newDocument = symbolEditor.GetChangedDocuments().Single();
                    SyntaxNode newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                    return context.Document.WithSyntaxRoot(newRoot);
                default:
                    return context.Document;
            }
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan);

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c => ChangeToThenByAsync(context.Document, syntaxNode, c)),
                context.Diagnostics);
        }
Exemplo n.º 17
0
        private SyntaxNode GetNode(SyntaxNode root, ValueTuple<TextSpan, int, int> spanAndKindAndId)
        {
            var node = root.FindNode(spanAndKindAndId.Item1, getInnermostNodeForTie: true);
            if (spanAndKindAndId.Item2 == 0)
            {
                return node;
            }

            var nodeOfKind = node.FirstAncestorOrSelf<SyntaxNode>(n => n.RawKind == spanAndKindAndId.Item2);
            Assert.NotNull(nodeOfKind);
            return nodeOfKind;
        }
        internal static bool GetRelationalExpression(SyntaxNode root, TextSpan span, out ExpressionSyntax expr, out SyntaxToken token)
        {
            expr = null;
            token = default(SyntaxToken);
            var bOp = root.FindNode(span).SkipArgument() as BinaryExpressionSyntax;
            if (bOp != null && bOp.OperatorToken.Span.Contains(span) && CSharpUtil.IsRelationalOperator(bOp.Kind()))
            {
                expr = bOp;
                token = bOp.OperatorToken;
                return true;
            }

            var uOp = root.FindNode(span).SkipArgument() as PrefixUnaryExpressionSyntax;
            if (uOp != null && uOp.OperatorToken.Span.Contains(span) && uOp.IsKind(SyntaxKind.LogicalNotExpression))
            {
                expr = uOp;
                token = uOp.OperatorToken;
                return true;
            }
            return false;
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var node = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true);

            var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
            var operation = semanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol;
            var enumDeclaration = operation?.ReturnType?.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(context.CancellationToken)
                as EnumDeclarationSyntax;

            if (enumDeclaration == null)
            {
                return;
            }

            var flagsAttributeType = semanticModel.Compilation.GetTypeByMetadataName(KnownType.System_FlagsAttribute.TypeName);
            if (flagsAttributeType == null)
            {
                return;
            }

            var currentSolution = context.Document.Project.Solution;
            var documentId = currentSolution.GetDocumentId(enumDeclaration.SyntaxTree);

            if (documentId == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    async c =>
                    {
                        var enumDeclarationRoot = await currentSolution.GetDocument(documentId).GetSyntaxRootAsync(c);

                        var flagsAttributeName = flagsAttributeType.ToMinimalDisplayString(semanticModel, enumDeclaration.SpanStart);
                        flagsAttributeName = flagsAttributeName.Remove(flagsAttributeName.IndexOf("Attribute", System.StringComparison.Ordinal));

                        var attributes = enumDeclaration.AttributeLists.Add(
                            SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(new[] {
                                SyntaxFactory.Attribute(SyntaxFactory.ParseName(flagsAttributeName)) })));

                        var newDeclaration = enumDeclaration.WithAttributeLists(attributes);
                        var newRoot = enumDeclarationRoot.ReplaceNode(
                            enumDeclaration,
                            newDeclaration);
                        return currentSolution.WithDocumentSyntaxRoot(documentId, newRoot);
                    }),
                context.Diagnostics);
        }
 private static async Task<Solution> UpdateMainDocumentAsync(Document document, string fullMethodName, SyntaxNode root, MethodDeclarationSyntax method, IEnumerable<IGrouping<Document, ReferenceLocation>> documentGroups, CancellationToken cancellationToken)
 {
     var mainDocGroup = documentGroups.FirstOrDefault(dg => dg.Key.Equals(document));
     SyntaxNode newRoot;
     if (mainDocGroup == null)
     {
         newRoot = root.ReplaceNode(method, method.WithoutTrivia().AddModifiers(staticToken).WithTriviaFrom(method));
     }
     else
     {
         var newMemberAccess = (MemberAccessExpressionSyntax)SyntaxFactory.ParseExpression(fullMethodName);
         newMemberAccess = newMemberAccess.WithExpression(
             newMemberAccess.Expression.WithAdditionalAnnotations(Simplifier.Annotation));
         var diagnosticNodes = mainDocGroup.Select(referenceLocation => root.FindNode(referenceLocation.Location.SourceSpan)).ToList();
         newRoot = root.TrackNodes(diagnosticNodes.Union(new[] { method }));
         var trackedMethod = newRoot.GetCurrentNode(method);
         var staticMethod = method.WithoutTrivia().AddModifiers(staticToken).WithTriviaFrom(method);
         newRoot = newRoot.ReplaceNode(trackedMethod, staticMethod);
         foreach (var diagnosticNode in diagnosticNodes)
         {
             var tempDoc = document.WithSyntaxRoot(newRoot);
             newRoot = await tempDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
             var semanticModel = await tempDoc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
             var syntaxNode = newRoot.GetCurrentNode(diagnosticNode);
             var memberAccess = syntaxNode.FirstAncestorOrSelfOfType<MemberAccessExpressionSyntax>();
             if (memberAccess?.Expression == null) continue;
             if (!syntaxNode.Equals(memberAccess.Name)) continue;
             var memberAccessExpressionSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol;
             var containingMember = memberAccess.FirstAncestorOrSelfThatIsAMember();
             var memberSymbol = semanticModel.GetDeclaredSymbol(containingMember);
             var allContainingTypes = memberSymbol.GetAllContainingTypes().ToList();
             var methodTypeSymbol = GetMethodTypeSymbol(memberAccessExpressionSymbol);
             var expressionToReplaceMemberAccess = allContainingTypes.Any(t => t.Equals(methodTypeSymbol))
                 // ideally we would check the symbols
                 // but there is a bug on Roslyn 1.0, fixed on 1.1:
                 // https://github.com/dotnet/roslyn/issues/3096
                 // so if we try to check the method symbol, it fails and always returns null
                 // so if we find a name clash, whatever one, we fall back to the full name
                 ? allContainingTypes.Count(t => t.MemberNames.Any(n => n == memberSymbol.Name)) > 1
                     ? (SyntaxNode)newMemberAccess
                     : memberAccess.Name
                 : newMemberAccess;
             var newMemberAccessParent = memberAccess.Parent.ReplaceNode(memberAccess, expressionToReplaceMemberAccess)
                 .WithAdditionalAnnotations(Formatter.Annotation)
                 .WithAdditionalAnnotations(Simplifier.Annotation);
             newRoot = newRoot.ReplaceNode(memberAccess.Parent, newMemberAccessParent);
         }
     }
     var newSolution = document.Project.Solution.WithDocumentSyntaxRoot(document.Id, newRoot);
     return newSolution;
 }
        /// <summary>
        /// Register the property fix for property documentation.
        /// </summary>
        /// <param name="root">the syntax root node.</param>
        /// <param name="context">the code fix context, containing the location of the fix.</param>
        /// <param name="diagnostic">the diagnostic, where the invalid code was located.</param>
        private void RegisterPropertyDocumentationCodeFix(SyntaxNode root, CodeFixContext context, Diagnostic diagnostic)
        {
            var node = root.FindNode(diagnostic.Location.SourceSpan);
            var propertyDeclaration = (PropertyDeclarationSyntax)node;

            var documentationStructure = propertyDeclaration.GetDocumentationCommentTriviaSyntax();
            var action = CodeAction.Create(
                "Generate property documentation.",
                c => this.AddDocumentationAsync(context, root, propertyDeclaration, documentationStructure),
                "SA1623D");
            context.RegisterCodeFix(
                action,
                diagnostic);
        }
        /// <summary>
        /// Register the property fix for property documentation.
        /// </summary>
        /// <param name="root">the syntax root node.</param>
        /// <param name="context">the code fix context, containing the location of the fix.</param>
        /// <param name="diagnostic">the diagnostic, where the invalid code was located.</param>
        private void RegisterMemberDocumentationCodeFix(SyntaxNode root, CodeFixContext context, Diagnostic diagnostic)
        {
            var node = root.FindNode(diagnostic.Location.SourceSpan);
            var fieldDeclarationSyntax = node.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().First();

            var documentationStructure = fieldDeclarationSyntax.GetDocumentationCommentTriviaSyntax();
            var action = CodeAction.Create(
                "Generate member documentation.",
                c => this.AddDocumentationAsync(context, root, fieldDeclarationSyntax, documentationStructure),
                "SA1600D");
            context.RegisterCodeFix(
                action,
                diagnostic);
        }
        private static async Task<Solution> UseShorthandNotationAsync(Document document, SyntaxNode root, SyntaxToken declaration)
        {
            var node = root.FindNode(declaration.Span);
            var typeNode = (GenericNameSyntax) node;
            var semanticModel = await document.GetSemanticModelAsync();
            var type = semanticModel.GetTypeInfo(typeNode.TypeArgumentList.Arguments.First()).Type;
            var typeNameString = type.MetadataName;

            if (!type.IsExtern)
            {
                switch (type.MetadataName)
                {
                    case "Int32":
                        typeNameString = "int";
                        break;
                    case "UInt32":
                        typeNameString = "uint";
                        break;
                    case "Int64":
                        typeNameString = "long";
                        break;
                    case "UInt64":
                        typeNameString = "ulong";
                        break;
                    case "Int16":
                        typeNameString = "short";
                        break;
                    case "UInt16":
                        typeNameString = "ushort";
                        break;
                    case "Single":
                        typeNameString = "float";
                        break;
                    case "Double":
                        typeNameString = "double";
                        break;
                    case "Decimal":
                        typeNameString = "decimal";
                        break;
                }
            }

            var newExpression = SyntaxFactory.ParseTypeName(typeNameString + "?");

            var newParent = node.ReplaceNode(node, newExpression).WithAdditionalAnnotations(Formatter.Annotation);
            var newRoot = root.ReplaceNode(node, newParent);
            var newDocument = document.WithSyntaxRoot(newRoot);

            return newDocument.Project.Solution;
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var name = root.FindNode(diagnosticSpan) as ModifiedIdentifierSyntax;

            var variableDeclarator = name?.Parent as VariableDeclaratorSyntax;
            if (variableDeclarator == null ||
                variableDeclarator.Names.Count != 1)
            {
                return;
            }

            var simpleAsClause = variableDeclarator.AsClause as SimpleAsClauseSyntax;
            if (simpleAsClause == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var type = simpleAsClause.Type.WithoutTrivia();
                        var typeAsArrayType = type as ArrayTypeSyntax;
                        var rankSpecifiers = name.ArrayRankSpecifiers.Select(rank => rank.WithoutTrivia());
                        var newType = typeAsArrayType == null
                            ? SyntaxFactory.ArrayType(
                                        type,
                                        SyntaxFactory.List(rankSpecifiers))
                            : typeAsArrayType.AddRankSpecifiers(rankSpecifiers.ToArray());

                        newType = newType.WithTriviaFrom(simpleAsClause.Type);

                        var newVariableDeclarator = variableDeclarator
                            .WithNames(SyntaxFactory.SeparatedList(new[] {
                                SyntaxFactory.ModifiedIdentifier(name.Identifier, name.ArrayBounds).WithTriviaFrom(name)
                            }))
                            .WithAsClause(simpleAsClause.WithType(newType));

                        var newRoot = root.ReplaceNode(
                            variableDeclarator,
                            newVariableDeclarator);

                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan);
            var method = syntaxNode.FirstAncestorOrSelf<MethodDeclarationSyntax>();

            if (method.Body.CloseBraceToken.IsMissing ||
                method.Body.OpenBraceToken.IsMissing)
            {
                return;
            }

            await RegisterCodeFixesForMethodsAsync(context, root, method).ConfigureAwait(false);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan);
            var parameter = syntaxNode?.FirstAncestorOrSelf<ParameterSyntax>();
            if (parameter == null)
            {
                return;
            }

            var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
            var parameterSymbol = semanticModel.GetDeclaredSymbol(parameter);
            var methodSymbol = parameterSymbol?.ContainingSymbol as IMethodSymbol;
            if (methodSymbol == null)
            {
                return;
            }

            ParameterSyntax newParameter;
            string title;

            if (methodSymbol.ExplicitInterfaceImplementations.Any())
            {
                newParameter = parameter.WithDefault(null);
                title = TitleExplicitInterface;
            }
            else
            {
                var index = methodSymbol.Parameters.IndexOf(parameterSymbol);
                IMethodSymbol overriddenMember;
                if (index == -1 ||
                    !methodSymbol.TryGetOverriddenOrInterfaceMember(out overriddenMember))
                {
                    return;
                }

                var overriddenParameter = overriddenMember.Parameters[index];

                if (!TryGetNewParameterSyntax(parameter, overriddenParameter, out newParameter))
                {
                    return;
                }
                title = TitleGeneral;
            }

            RegisterCodeFix(context, root, parameter, newParameter, title);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan);

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newRoot = root.RemoveNode(syntaxNode, SyntaxRemoveOptions.KeepExteriorTrivia | SyntaxRemoveOptions.KeepEndOfLine);
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var ifStatement = root.FindNode(diagnosticSpan).FirstAncestorOrSelf<IfStatementSyntax>();

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newRoot = CalculateNewRoot(root, ifStatement);
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var node = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true);

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newRoot = CalculateNewRoot(root, node);
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    },
                    Title),
                context.Diagnostics);
        }
        protected sealed override async Task RegisterCodeFixesAsync(SyntaxNode root, CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var baseList = (BaseListSyntax)root.FindNode(diagnosticSpan);
            var redundantIndex = int.Parse(diagnostic.Properties[RedundantInheritanceList.RedundantIndexKey]);

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newRoot = RemoveDeclaration(root, baseList, redundantIndex);
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
Exemplo n.º 31
0
 /// <summary>
 /// 获取类型定义节点
 /// </summary>
 /// <returns></returns>
 public static InterfaceDeclarationSyntax InterfaceNode(this SyntaxNode node, int index = 0)
 {
     return(node.FindNode <InterfaceDeclarationSyntax>(index));
 }
Exemplo n.º 32
0
 /// <summary>
 /// 获取类型定义节点
 /// </summary>
 /// <returns></returns>
 public static EnumDeclarationSyntax EnumNode(this SyntaxNode node, int index = 0)
 {
     return(node.FindNode <EnumDeclarationSyntax>(index));
 }
Exemplo n.º 33
0
 /// <summary>
 /// 获取类型定义节点
 /// </summary>
 /// <returns></returns>
 public static ClassDeclarationSyntax ClassNode(this SyntaxNode node, int index = 0)
 {
     return(node.FindNode <ClassDeclarationSyntax>(index));
 }
 /// <summary>
 /// 获取类型定义节点
 /// </summary>
 /// <returns></returns>
 public static StructDeclarationSyntax StructNode(this SyntaxNode node, int index = 0)
 {
     return(node.FindNode <StructDeclarationSyntax>(index));
 }