private static SyntaxKind GetInvertedOperatorKind(SyntaxToken operatorToken)
        {
            switch (operatorToken.Kind())
            {
            case SyntaxKind.AmpersandAmpersandToken:
                return(SyntaxKind.BarBarToken);

            case SyntaxKind.BarBarToken:
                return(SyntaxKind.AmpersandAmpersandToken);

            case SyntaxKind.EqualsEqualsToken:
                return(SyntaxKind.ExclamationEqualsToken);

            case SyntaxKind.ExclamationEqualsToken:
                return(SyntaxKind.EqualsEqualsToken);

            case SyntaxKind.GreaterThanToken:
                return(SyntaxKind.LessThanEqualsToken);

            case SyntaxKind.GreaterThanEqualsToken:
                return(SyntaxKind.LessThanToken);

            case SyntaxKind.LessThanToken:
                return(SyntaxKind.GreaterThanEqualsToken);

            case SyntaxKind.LessThanEqualsToken:
                return(SyntaxKind.GreaterThanToken);

            default:
            {
                SyntaxDebug.Fail(operatorToken);
                return(operatorToken.Kind());
            }
            }
        }
Esempio n. 2
0
        private static void ReportDiagnostic(SymbolAnalysisContext context, ISymbol member)
        {
            SyntaxNode node = member.GetSyntaxOrDefault(context.CancellationToken);

            Debug.Assert(node != null, member.ToString());

            if (node == null)
            {
                return;
            }

            SyntaxToken identifier = CSharpUtility.GetIdentifier(node);

            SyntaxDebug.Assert(!identifier.IsKind(SyntaxKind.None), node);

            if (identifier.IsKind(SyntaxKind.None))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(
                context,
                DiagnosticRules.StaticMemberInGenericTypeShouldUseTypeParameter,
                identifier);
        }
Esempio n. 3
0
        private static TypeSyntax DetermineReturnType(SyntaxNode node)
        {
            switch (node.Kind())
            {
            case SyntaxKind.LocalFunctionStatement:
                return(((LocalFunctionStatementSyntax)node).ReturnType);

            case SyntaxKind.MethodDeclaration:
                return(((MethodDeclarationSyntax)node).ReturnType);

            case SyntaxKind.OperatorDeclaration:
                return(((OperatorDeclarationSyntax)node).ReturnType);

            case SyntaxKind.ConversionOperatorDeclaration:
                return(((ConversionOperatorDeclarationSyntax)node).Type);

            case SyntaxKind.PropertyDeclaration:
                return(((PropertyDeclarationSyntax)node).Type);

            case SyntaxKind.IndexerDeclaration:
                return(((IndexerDeclarationSyntax)node).Type);
            }

            if (node is AccessorDeclarationSyntax)
            {
                SyntaxDebug.Assert(node.IsParentKind(SyntaxKind.AccessorList), node.Parent);

                if (node.IsParentKind(SyntaxKind.AccessorList))
                {
                    return(DetermineReturnType(node.Parent.Parent));
                }
            }

            return(null);
        }
        private static void AnalyzeCompilationUnit(SyntaxNodeAnalysisContext context)
        {
            var compilationUnit = (CompilationUnitSyntax)context.Node;

            if (compilationUnit.Span.Length == 0)
            {
                return;
            }

            SyntaxToken token = compilationUnit.EndOfFileToken;

            if (token.FullSpan.Start > 0)
            {
                token = compilationUnit.GetFirstToken();

                SyntaxDebug.Assert(token.FullSpan.Start == 0, token);

                if (token.FullSpan.Start > 0)
                {
                    return;
                }
            }

            SyntaxTriviaList.Enumerator en = token.LeadingTrivia.GetEnumerator();

            if (en.MoveNext() &&
                en.Current.IsWhitespaceOrEndOfLineTrivia())
            {
                ReportDiagnostic(context, token);
            }
        private static void AnalyzeLocalFunctionStatement(SyntaxNodeAnalysisContext context)
        {
            var localFunctionStatement = (LocalFunctionStatementSyntax)context.Node;

            SyntaxTokenList modifiers = localFunctionStatement.Modifiers;

            int index = modifiers.IndexOf(SyntaxKind.UnsafeKeyword);

            if (index == -1)
            {
                return;
            }

            SyntaxNode parent = localFunctionStatement.Parent;

            SyntaxDebug.Assert(parent.IsKind(SyntaxKind.Block), parent);

            if (parent is not BlockSyntax)
            {
                return;
            }

            parent = parent.Parent;

            if (!ParentDeclarationsContainsUnsafeModifier(parent))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryUnsafeContext, modifiers[index]);
        }
Esempio n. 6
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindNode(root, context.Span, out SyntaxNode node))
            {
                return;
            }

            Diagnostic diagnostic = context.Diagnostics[0];

            for (SyntaxNode parent = node.Parent; parent != null; parent = parent.Parent)
            {
                if (parent is MemberDeclarationSyntax memberDeclaration)
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ISymbol symbol = semanticModel.GetSymbol(node, context.CancellationToken);

                    if (symbol?.IsErrorType() != false)
                    {
                        return;
                    }

                    SyntaxDebug.Assert(SyntaxInfo.ModifierListInfo(memberDeclaration).IsStatic, memberDeclaration);

                    if (SyntaxInfo.ModifierListInfo(memberDeclaration).IsStatic)
                    {
                        if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeMemberNonStatic, context.Document, root.SyntaxTree))
                        {
                            ModifiersCodeFixRegistrator.RemoveModifier(
                                context,
                                diagnostic,
                                memberDeclaration,
                                SyntaxKind.StaticKeyword,
                                title: $"Make containing {CSharpFacts.GetTitle(memberDeclaration)} non-static",
                                additionalKey: CodeFixIdentifiers.MakeMemberNonStatic);
                        }

                        if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier, context.Document, root.SyntaxTree))
                        {
                            AddStaticModifier(context, diagnostic, node, semanticModel);
                        }
                    }

                    return;
                }
                else if (parent is ConstructorInitializerSyntax)
                {
                    if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier, context.Document, root.SyntaxTree))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        AddStaticModifier(context, diagnostic, node, semanticModel);
                    }

                    return;
                }
            }
        }
        private static TypeSyntax GetTypeSyntax(SyntaxNode node)
        {
            switch (node)
            {
            case EventDeclarationSyntax eventDeclaration:
            {
                return(eventDeclaration.Type);
            }

            case VariableDeclaratorSyntax declarator:
            {
                if (declarator.Parent is VariableDeclarationSyntax declaration)
                {
                    return(declaration.Type);
                }

                SyntaxDebug.Fail(declarator.Parent);
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node);
                break;
            }
            }

            return(null);
        }
Esempio n. 8
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ExpressionSyntax expression))
            {
                return;
            }

            Document   document   = context.Document;
            Diagnostic diagnostic = context.Diagnostics[0];

            if (expression is InvocationExpressionSyntax invocationExpression)
            {
                CodeAction codeAction = CodeAction.Create(
                    ConvertHasFlagCallToBitwiseOperationRefactoring.Title,
                    ct => ConvertHasFlagCallToBitwiseOperationRefactoring.RefactorAsync(document, invocationExpression, ct),
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
            }
            else
            {
                SyntaxDebug.Assert(expression.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression), expression);

                CodeAction codeAction = CodeAction.Create(
                    "Call 'HasFlag'",
                    ct => ConvertBitwiseOperationToHasFlagCallAsync(document, (BinaryExpressionSyntax)expression, ct),
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
            }
        }
Esempio n. 9
0
        private static async Task <Document> UseStringLengthInsteadOfComparisonWithEmptyStringAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax left = binaryExpression.Left;

            ExpressionSyntax right = binaryExpression.Right;

            BinaryExpressionSyntax newNode;

            if (CSharpUtility.IsEmptyStringExpression(left, semanticModel, cancellationToken))
            {
                newNode = binaryExpression
                          .WithLeft(NumericLiteralExpression(0))
                          .WithRight(CreateConditionalAccess(right));
            }
            else if (CSharpUtility.IsEmptyStringExpression(right, semanticModel, cancellationToken))
            {
                newNode = binaryExpression
                          .WithLeft(CreateConditionalAccess(left))
                          .WithRight(NumericLiteralExpression(0));
            }
            else
            {
                SyntaxDebug.Fail(binaryExpression);
                return(document);
            }

            newNode = newNode.WithTriviaFrom(binaryExpression).WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false));
        }
            public override void VisitInvocationExpression(InvocationExpressionSyntax node)
            {
                switch (node.Expression)
                {
                case SimpleNameSyntax simpleName:
                {
                    AnalyzeSimpleName(simpleName);
                    break;
                }

                case MemberBindingExpressionSyntax memberBindingExpression:
                {
                    AnalyzeSimpleName(memberBindingExpression.Name);
                    break;
                }

                case MemberAccessExpressionSyntax memberAccessExpression:
                {
                    AnalyzeSimpleName(memberAccessExpression.Name);
                    break;
                }

                default:
                {
                    SyntaxDebug.Fail(node);
                    break;
                }
                }

                base.VisitInvocationExpression(node);
            }
Esempio n. 11
0
        public static async Task <Document> RefactorAsync(
            Document document,
            AccessorListSyntax accessorList,
            CancellationToken cancellationToken)
        {
            if (accessorList.Accessors.All(f => f.BodyOrExpressionBody() == null))
            {
                SyntaxNode parent = accessorList.Parent;

                switch (parent)
                {
                case PropertyDeclarationSyntax propertyDeclaration:
                {
                    TextSpan span = TextSpan.FromBounds(
                        propertyDeclaration.Identifier.Span.End,
                        accessorList.CloseBraceToken.SpanStart);

                    PropertyDeclarationSyntax newNode = propertyDeclaration.RemoveWhitespace(span);

                    newNode = newNode.WithFormatterAnnotation();

                    return(await document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken).ConfigureAwait(false));
                }

                case IndexerDeclarationSyntax indexerDeclaration:
                {
                    TextSpan span = TextSpan.FromBounds(
                        indexerDeclaration.ParameterList.CloseBracketToken.Span.End,
                        accessorList.CloseBraceToken.SpanStart);

                    IndexerDeclarationSyntax newNode = indexerDeclaration.RemoveWhitespace(span);

                    newNode = newNode.WithFormatterAnnotation();

                    return(await document.ReplaceNodeAsync(indexerDeclaration, newNode, cancellationToken).ConfigureAwait(false));
                }

                default:
                {
                    SyntaxDebug.Fail(parent);
                    return(document);
                }
                }
            }
            else
            {
                AccessorListSyntax newAccessorList = GetNewAccessorList(accessorList);

                newAccessorList = AddNewLineAfterFirstAccessorIfNecessary(accessorList, newAccessorList, cancellationToken);

                newAccessorList = newAccessorList.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(accessorList, newAccessorList, cancellationToken).ConfigureAwait(false));
            }
        }
Esempio n. 12
0
        private static void AddStaticModifier(
            CodeFixContext context,
            Diagnostic diagnostic,
            SyntaxNode node,
            SemanticModel semanticModel)
        {
            ISymbol symbol = semanticModel.GetSymbol(node, context.CancellationToken);

            if (symbol == null)
            {
                return;
            }

            SyntaxNode syntax = symbol.GetSyntaxOrDefault(context.CancellationToken);

            if (syntax == null)
            {
                return;
            }

            if (syntax.IsKind(SyntaxKind.VariableDeclarator))
            {
                syntax = syntax.Parent?.Parent;
            }

            SyntaxDebug.Assert(syntax.IsKind(SyntaxKind.EventDeclaration, SyntaxKind.EventFieldDeclaration, SyntaxKind.FieldDeclaration, SyntaxKind.MethodDeclaration, SyntaxKind.PropertyDeclaration), syntax);

            if (syntax is not MemberDeclarationSyntax memberDeclaration)
            {
                return;
            }

            if (SyntaxInfo.ModifierListInfo(memberDeclaration).IsStatic)
            {
                return;
            }

            Document document = context.Document;

            SyntaxTree tree = memberDeclaration.SyntaxTree;

            if (tree != node.SyntaxTree)
            {
                document = context.Solution().GetDocument(tree);
            }

            ModifiersCodeFixRegistrator.AddModifier(
                context,
                document,
                diagnostic,
                memberDeclaration,
                SyntaxKind.StaticKeyword,
                title: $"Make '{symbol.Name}' static",
                additionalKey: CodeFixIdentifiers.AddStaticModifier);
        }
Esempio n. 13
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindNode(
                    root,
                    context.Span,
                    out ExpressionSyntax expression))
            {
                return;
            }

            SyntaxDebug.Assert(expression.IsKind(SyntaxKind.NullLiteralExpression, SyntaxKind.DefaultLiteralExpression, SyntaxKind.DefaultExpression), expression);

            if (!expression.IsKind(SyntaxKind.NullLiteralExpression, SyntaxKind.DefaultLiteralExpression, SyntaxKind.DefaultExpression))
            {
                return;
            }

            if (expression.IsKind(SyntaxKind.NullLiteralExpression) &&
                expression.IsParentKind(SyntaxKind.EqualsValueClause) &&
                expression.Parent.IsParentKind(SyntaxKind.Parameter))
            {
                return;
            }

            Diagnostic diagnostic = context.Diagnostics[0];
            Document   document   = context.Document;

            switch (diagnostic.Id)
            {
            case CompilerDiagnosticIdentifiers.CS8625_CannotConvertNullLiteralToNonNullableReferenceType:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, context.Document, root.SyntaxTree))
                {
                    break;
                }

                CodeAction codeAction = CodeAction.Create(
                    "Use null-forgiving operator",
                    ct =>
                    {
                        PostfixUnaryExpressionSyntax newExpression = SuppressNullableWarningExpression(expression.WithoutTrivia())
                                                                     .WithTriviaFrom(expression);

                        return(document.ReplaceNodeAsync(expression, newExpression, ct));
                    },
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);

                break;
            }
            }
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Diagnostic diagnostic = context.Diagnostics[0];

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

            if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType, context.Document, root.SyntaxTree))
            {
                return;
            }

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out SyntaxNode node, predicate: f => f.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement)))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(node, context.CancellationToken);

            SyntaxDebug.Assert(methodSymbol != null, node);

            ITypeSymbol typeSymbol = methodSymbol.ReturnType;

            if (typeSymbol.IsErrorType())
            {
                return;
            }

            (bool containsReturnAwait, bool containsAwaitStatement) = AnalyzeAwaitExpressions(node);

            SyntaxDebug.Assert(containsAwaitStatement || containsReturnAwait, node);

            if (containsAwaitStatement)
            {
                INamedTypeSymbol taskSymbol = semanticModel.GetTypeByMetadataName("System.Threading.Tasks.Task");

                CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, node, taskSymbol, semanticModel, "Task");
            }

            if (containsReturnAwait)
            {
                typeSymbol = semanticModel.GetTypeByMetadataName("System.Threading.Tasks.Task`1").Construct(typeSymbol);

                CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, node, typeSymbol, semanticModel, "TaskOfT");
            }
        }
        private static InvocationExpressionSyntax GetNewInvocation(InvocationExpressionSyntax invocation)
        {
            ExpressionSyntax   expression   = invocation.Expression;
            ArgumentListSyntax argumentList = invocation.ArgumentList;
            SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;
            ArgumentSyntax argument = arguments[0];

            MemberAccessExpressionSyntax newMemberAccess = CreateNewMemberAccessExpression();

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

            return(invocation
                   .WithExpression(newMemberAccess)
                   .WithArgumentList(argumentList.WithArguments(arguments.Remove(argument))));

            MemberAccessExpressionSyntax CreateNewMemberAccessExpression()
            {
                switch (expression.Kind())
                {
                case SyntaxKind.IdentifierName:
                case SyntaxKind.GenericName:
                {
                    return(SimpleMemberAccessExpression(
                               ParenthesizedExpression(argument.Expression),
                               (SimpleNameSyntax)expression));
                }

                case SyntaxKind.SimpleMemberAccessExpression:
                {
                    var memberAccess = (MemberAccessExpressionSyntax)expression;

                    return(memberAccess.WithExpression(ParenthesizedExpression(argument.Expression)));
                }

                default:
                {
                    SyntaxDebug.Fail(expression);
                    return(null);
                }
                }
            }
        }
Esempio n. 16
0
        public static Task <Document> RefactorAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax left  = binaryExpression.Left;
            ExpressionSyntax right = binaryExpression.Right;

            ExpressionSyntax newNode = binaryExpression;

            TextSpan span = TextSpan.FromBounds(left.Span.End, right.SpanStart);

            IEnumerable <SyntaxTrivia> trivia = binaryExpression.DescendantTrivia(span);

            bool isWhiteSpaceOrEndOfLine = trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia());

            if (IsBooleanLiteralExpression(left.Kind()))
            {
                SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia();

                if (!isWhiteSpaceOrEndOfLine)
                {
                    leadingTrivia = leadingTrivia.AddRange(trivia);
                }

                newNode = right.WithLeadingTrivia(leadingTrivia);
            }
            else if (IsBooleanLiteralExpression(right.Kind()))
            {
                SyntaxTriviaList trailingTrivia = binaryExpression.GetTrailingTrivia();

                if (!isWhiteSpaceOrEndOfLine)
                {
                    trailingTrivia = trailingTrivia.InsertRange(0, trivia);
                }

                newNode = left.WithTrailingTrivia(trailingTrivia);
            }
            else
            {
                SyntaxDebug.Fail(binaryExpression);
            }

            return(document.ReplaceNodeAsync(binaryExpression, newNode.WithFormatterAnnotation(), cancellationToken));
        }
Esempio n. 17
0
        public override bool CanBeRenamed(SyntaxToken token)
        {
            switch (token.Kind())
            {
            case SyntaxKind.IdentifierToken:
                return(true);

            case SyntaxKind.ThisKeyword:
            case SyntaxKind.BaseKeyword:
            case SyntaxKind.GetKeyword:
            case SyntaxKind.SetKeyword:
            case SyntaxKind.AddKeyword:
            case SyntaxKind.RemoveKeyword:
                return(false);
            }

            SyntaxDebug.Fail(token);

            return(false);
        }
Esempio n. 18
0
        private static void AnalyzeForEachVariableStatement(SyntaxNodeAnalysisContext context)
        {
            var forEachStatement = (ForEachVariableStatementSyntax)context.Node;

            switch (forEachStatement.Variable)
            {
            case DeclarationExpressionSyntax declarationExpression:
            {
                if (CSharpTypeAnalysis.IsImplicitThatCanBeExplicit(forEachStatement, context.SemanticModel))
                {
                    ReportDiagnostic(context, declarationExpression.Type);
                }

                break;
            }

            case TupleExpressionSyntax tupleExpression:
            {
                foreach (ArgumentSyntax argument in tupleExpression.Arguments)
                {
                    if (argument.Expression is not DeclarationExpressionSyntax declarationExpression)
                    {
                        continue;
                    }

                    if (CSharpTypeAnalysis.IsImplicitThatCanBeExplicit(declarationExpression, context.SemanticModel, context.CancellationToken))
                    {
                        ReportDiagnostic(context, declarationExpression.Type);
                    }
                }

                break;
            }

            default:
            {
                SyntaxDebug.Assert(forEachStatement.ContainsDiagnostics, forEachStatement.Variable);
                break;
            }
            }
        }
        private static SyntaxKind GetBinaryExpressionKind(AssignmentExpressionSyntax assignmentExpression)
        {
            switch (assignmentExpression.Kind())
            {
            case SyntaxKind.AddAssignmentExpression:
                return(SyntaxKind.AddExpression);

            case SyntaxKind.SubtractAssignmentExpression:
                return(SyntaxKind.SubtractExpression);

            case SyntaxKind.MultiplyAssignmentExpression:
                return(SyntaxKind.MultiplyExpression);

            case SyntaxKind.DivideAssignmentExpression:
                return(SyntaxKind.DivideExpression);

            case SyntaxKind.ModuloAssignmentExpression:
                return(SyntaxKind.ModuloExpression);

            case SyntaxKind.AndAssignmentExpression:
                return(SyntaxKind.BitwiseAndExpression);

            case SyntaxKind.OrAssignmentExpression:
                return(SyntaxKind.BitwiseOrExpression);

            case SyntaxKind.ExclusiveOrAssignmentExpression:
                return(SyntaxKind.ExclusiveOrExpression);

            case SyntaxKind.LeftShiftAssignmentExpression:
                return(SyntaxKind.LeftShiftExpression);

            case SyntaxKind.RightShiftAssignmentExpression:
                return(SyntaxKind.RightShiftExpression);
            }

            SyntaxDebug.Fail(assignmentExpression);
            return(SyntaxKind.None);
        }
        private static void AnalyzeNameEquals(SyntaxNodeAnalysisContext context)
        {
            var node = (NameEqualsSyntax)context.Node;

            switch (node.Parent.Kind())
            {
            case SyntaxKind.AttributeArgument:
            {
                var attributeArgument = (AttributeArgumentSyntax)node.Parent;

                Analyze(context, attributeArgument.NameEquals.EqualsToken, attributeArgument.Expression);
                break;
            }

            case SyntaxKind.AnonymousObjectMemberDeclarator:
            {
                var declarator = (AnonymousObjectMemberDeclaratorSyntax)node.Parent;

                Analyze(context, declarator.NameEquals.EqualsToken, declarator.Expression);
                break;
            }

            case SyntaxKind.UsingDirective:
            {
                var usingDirective = (UsingDirectiveSyntax)node.Parent;

                Analyze(context, usingDirective.Alias.EqualsToken, usingDirective.Name);
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node.Parent);
                break;
            }
            }
        }
        private static (ISymbol symbol, ITypeSymbol typeSymbol) GetContainingSymbolAndType(
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default)
        {
            switch (semanticModel.GetEnclosingSymbol(expression.SpanStart, cancellationToken))
            {
            case IMethodSymbol methodSymbol:
            {
                MethodKind methodKind = methodSymbol.MethodKind;

                if (methodKind == MethodKind.PropertyGet)
                {
                    var propertySymbol = (IPropertySymbol)methodSymbol.AssociatedSymbol;

                    return(propertySymbol, propertySymbol.Type);
                }

                if (methodKind == MethodKind.Ordinary &&
                    methodSymbol.PartialImplementationPart != null)
                {
                    methodSymbol = methodSymbol.PartialImplementationPart;
                }

                return(methodSymbol, methodSymbol.ReturnType);
            }

            case IFieldSymbol fieldSymbol:
            {
                return(fieldSymbol, fieldSymbol.Type);
            }
            }

            SyntaxDebug.Fail(expression);

            return(default((ISymbol, ITypeSymbol)));
        }
        private static bool ParentDeclarationsContainsUnsafeModifier(SyntaxNode node)
        {
            while (node.IsKind(SyntaxKind.LocalFunctionStatement))
            {
                var localFunction = (LocalFunctionStatementSyntax)node;

                if (localFunction.Modifiers.Contains(SyntaxKind.UnsafeKeyword))
                {
                    return(true);
                }

                node = node.Parent;

                SyntaxDebug.Assert(node.IsKind(SyntaxKind.Block), node);

                if (!node.IsKind(SyntaxKind.Block))
                {
                    break;
                }

                node = node.Parent;
            }

            SyntaxDebug.Assert(node is MemberDeclarationSyntax, node);

            if (node is MemberDeclarationSyntax memberDeclaration)
            {
                if (SyntaxInfo.ModifierListInfo(memberDeclaration).IsUnsafe)
                {
                    return(true);
                }

                return(ParentTypeDeclarationsContainsUnsafeModifier(memberDeclaration));
            }

            return(false);
        }
Esempio n. 23
0
            public override SyntaxNode VisitYieldStatement(YieldStatementSyntax node)
            {
                SyntaxToken      keyword    = node.ReturnOrBreakKeyword;
                ExpressionSyntax expression = node.Expression;

                SyntaxKind kind = node.Kind();

                if (kind == SyntaxKind.YieldReturnStatement)
                {
                    ParenthesizedExpressionSyntax parenthesizedExpression = expression.Parenthesize();

                    CastExpressionSyntax castExpression = CastExpression(
                        _typeSymbol.ToMinimalTypeSyntax(_semanticModel, node.SpanStart),
                        parenthesizedExpression);

                    InvocationExpressionSyntax invocationExpression = SimpleMemberInvocationExpression(
                        _identifierName,
                        _addName,
                        Argument(castExpression.WithSimplifierAnnotation()));

                    return(ExpressionStatement(invocationExpression.WithoutTrivia())
                           .WithTriviaFrom(node)
                           .AppendToLeadingTrivia(node.DescendantTrivia(TextSpan.FromBounds(keyword.Span.End, expression.SpanStart))));
                }
                else if (kind == SyntaxKind.YieldBreakStatement)
                {
                    return(ReturnStatement(
                               Token(keyword.LeadingTrivia, SyntaxKind.ReturnKeyword, keyword.TrailingTrivia),
                               _identifierName,
                               node.SemicolonToken));
                }

                SyntaxDebug.Fail(node);

                return(base.VisitYieldStatement(node));
            }
Esempio n. 24
0
        private static void Analyze(SymbolAnalysisContext context, ISymbol symbol)
        {
            if (symbol.IsImplicitlyDeclared)
            {
                return;
            }

            if (!symbol.IsSealed)
            {
                return;
            }

            if (symbol.ContainingType?.IsSealed != true)
            {
                return;
            }

            Debug.Assert(symbol.ContainingType.TypeKind == TypeKind.Class, symbol.ContainingType.TypeKind.ToString());

            SyntaxNode node = symbol.GetSyntax(context.CancellationToken);

            SyntaxDebug.Assert(node.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.PropertyDeclaration, SyntaxKind.IndexerDeclaration), node);

            ModifierListInfo info = SyntaxInfo.ModifierListInfo(node);

            Debug.Assert(info.IsSealed, info.Modifiers.ToString());

            if (!info.IsSealed)
            {
                return;
            }

            SyntaxToken sealedKeyword = info.Modifiers.Find(SyntaxKind.SealedKeyword);

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveRedundantSealedModifier, sealedKeyword);
        }
        private static void AnalyzeSimpleAssignment(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.ContainsDiagnostics)
            {
                return;
            }

            if (context.Node.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

            var assignment = (AssignmentExpressionSyntax)context.Node;

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(assignment);

            if (!assignmentInfo.Success)
            {
                return;
            }

            if (assignmentInfo.Left is not IdentifierNameSyntax identifierName)
            {
                return;
            }

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(assignmentInfo.Statement);

            if (!statementsInfo.Success)
            {
                return;
            }

            int index = statementsInfo.IndexOf(assignmentInfo.Statement);

            if (index == statementsInfo.Count - 1)
            {
                return;
            }

            if (index > 0)
            {
                StatementSyntax previousStatement = statementsInfo[index - 1];

                SimpleAssignmentStatementInfo assignmentInfo2 = SyntaxInfo.SimpleAssignmentStatementInfo(previousStatement);

                if (assignmentInfo2.Success &&
                    assignmentInfo2.Left is IdentifierNameSyntax identifierName2 &&
                    string.Equals(identifierName.Identifier.ValueText, identifierName2.Identifier.ValueText, StringComparison.Ordinal))
                {
                    return;
                }
            }

            StatementSyntax nextStatement = statementsInfo[index + 1];

            if (nextStatement.SpanOrLeadingTriviaContainsDirectives())
            {
                return;
            }

            if (nextStatement is not ReturnStatementSyntax returnStatement)
            {
                return;
            }

            if (returnStatement.Expression?.WalkDownParentheses() is not IdentifierNameSyntax identifierName3)
            {
                return;
            }

            if (!string.Equals(identifierName.Identifier.ValueText, identifierName3.Identifier.ValueText, StringComparison.Ordinal))
            {
                return;
            }

            ISymbol symbol = context.SemanticModel.GetSymbol(identifierName, context.CancellationToken);

            switch (symbol?.Kind)
            {
            case SymbolKind.Local:
            {
                break;
            }

            case SymbolKind.Parameter:
            {
                if (((IParameterSymbol)symbol).RefKind != RefKind.None)
                {
                    return;
                }

                break;
            }

            default:
            {
                return;
            }
            }

            if (IsAssignedInsideAnonymousFunctionButDeclaredOutsideOfIt())
            {
                return;
            }

            bool result;
            RemoveRedundantAssignmentWalker walker = null;

            try
            {
                walker = RemoveRedundantAssignmentWalker.GetInstance();

                walker.Symbol            = symbol;
                walker.SemanticModel     = context.SemanticModel;
                walker.CancellationToken = context.CancellationToken;
                walker.Result            = false;

                walker.Visit(assignmentInfo.Right);

                result = walker.Result;
            }
            finally
            {
                if (walker != null)
                {
                    RemoveRedundantAssignmentWalker.Free(walker);
                }
            }

            if (result)
            {
                return;
            }

            if (IsDeclaredInTryStatementOrCatchClauseAndReferencedInFinallyClause(context, assignmentInfo.Statement, symbol))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveRedundantAssignment, assignment);

            bool IsAssignedInsideAnonymousFunctionButDeclaredOutsideOfIt()
            {
                SyntaxNode declaringSyntax = null;
                SyntaxNode n = assignment.Parent;

                do
                {
                    if (CSharpFacts.IsAnonymousFunctionExpression(n.Kind()))
                    {
                        if (declaringSyntax == null)
                        {
                            declaringSyntax = symbol.GetSyntaxOrDefault();

                            Debug.Assert(declaringSyntax != null, "");

                            if (declaringSyntax == null)
                            {
                                break;
                            }

                            SyntaxDebug.Assert(declaringSyntax.IsKind(SyntaxKind.VariableDeclarator, SyntaxKind.Parameter), declaringSyntax);
                        }

                        SyntaxNode n2 = declaringSyntax.Parent;

                        do
                        {
                            if (CSharpFacts.IsAnonymousFunctionExpression(n2.Kind()))
                            {
                                return(!object.ReferenceEquals(n, n2));
                            }

                            if (n2 is MemberDeclarationSyntax)
                            {
                                break;
                            }

                            n2 = n2.Parent;
                        }while (n2 != null);

                        return(true);
                    }
                    else if (n is MemberDeclarationSyntax)
                    {
                        break;
                    }

                    n = n.Parent;
                }while (n != null);

                return(false);
            }
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ExpressionSyntax expression))
            {
                return;
            }

            Diagnostic diagnostic = context.Diagnostics[0];
            Document   document   = context.Document;

            switch (expression)
            {
            case SimpleNameSyntax simpleName:
            {
                SyntaxDebug.Assert(expression.IsKind(SyntaxKind.IdentifierName, SyntaxKind.GenericName), expression);

                if (simpleName.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var memberAccessExpression = (MemberAccessExpressionSyntax)simpleName.Parent;

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    if (memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression))
                    {
                        if (!memberAccessExpression.Parent.IsParentKind(SyntaxKind.ConditionalAccessExpression) &&
                            IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceInvocationWithMemberAccessOrViceVersa, context.Document, root.SyntaxTree))
                        {
                            var invocationExpression = (InvocationExpressionSyntax)memberAccessExpression.Parent;

                            if (!invocationExpression.ArgumentList.Arguments.Any())
                            {
                                ReplaceInvocationWithMemberAccess(context, diagnostic, memberAccessExpression, invocationExpression, semanticModel);
                            }
                        }
                    }
                    else
                    {
                        if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.FixMemberAccessName, context.Document, root.SyntaxTree))
                        {
                            CodeFixRegistrationResult result = ReplaceCountWithLengthOrViceVersa(context, diagnostic, memberAccessExpression.Expression, simpleName, semanticModel);

                            if (result.Success)
                            {
                                break;
                            }
                        }

                        if (!memberAccessExpression.IsParentKind(SyntaxKind.ConditionalAccessExpression) &&
                            IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceInvocationWithMemberAccessOrViceVersa, context.Document, root.SyntaxTree))
                        {
                            ReplaceMemberAccessWithInvocation(context, diagnostic, memberAccessExpression, semanticModel);
                        }
                    }
                }

                break;
            }

            case MemberBindingExpressionSyntax memberBindingExpression:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.FixMemberAccessName, context.Document, root.SyntaxTree))
                {
                    break;
                }

                if (memberBindingExpression.Parent is not ConditionalAccessExpressionSyntax conditionalAccessExpression)
                {
                    break;
                }

                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                CodeFixRegistrationResult result = ReplaceCountWithLengthOrViceVersa(context, diagnostic, conditionalAccessExpression.Expression, memberBindingExpression.Name, semanticModel);

                break;
            }

            case AwaitExpressionSyntax awaitExpression:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveAwaitKeyword, context.Document, root.SyntaxTree))
                {
                    break;
                }

                CodeAction codeAction = CodeAction.Create(
                    "Remove 'await'",
                    ct =>
                    {
                        ExpressionSyntax expression2 = awaitExpression.Expression;

                        SyntaxTriviaList leadingTrivia = awaitExpression
                                                         .GetLeadingTrivia()
                                                         .AddRange(awaitExpression.AwaitKeyword.TrailingTrivia.EmptyIfWhitespace())
                                                         .AddRange(expression2.GetLeadingTrivia().EmptyIfWhitespace());

                        ExpressionSyntax newNode = expression2.WithLeadingTrivia(leadingTrivia);

                        return(document.ReplaceNodeAsync(awaitExpression, newNode, ct));
                    },
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
                break;
            }
            }
        }
        private static SyntaxNode Refactor(SyntaxNode node)
        {
            switch (node.Kind())
            {
            case SyntaxKind.MethodDeclaration:
                {
                    var methodDeclaration            = (MethodDeclarationSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(methodDeclaration.Body);

                    return(methodDeclaration
                           .WithExpressionBody(CreateExpressionBody(analysis, methodDeclaration))
                           .WithSemicolonToken(CreateSemicolonToken(methodDeclaration.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.ConstructorDeclaration:
                {
                    var constructorDeclaration       = (ConstructorDeclarationSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(constructorDeclaration.Body);

                    return(constructorDeclaration
                           .WithExpressionBody(CreateExpressionBody(analysis, constructorDeclaration))
                           .WithSemicolonToken(CreateSemicolonToken(constructorDeclaration.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.DestructorDeclaration:
                {
                    var destructorDeclaration        = (DestructorDeclarationSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(destructorDeclaration.Body);

                    return(destructorDeclaration
                           .WithExpressionBody(CreateExpressionBody(analysis, destructorDeclaration))
                           .WithSemicolonToken(CreateSemicolonToken(destructorDeclaration.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.LocalFunctionStatement:
                {
                    var localFunction = (LocalFunctionStatementSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(localFunction.Body);

                    return(localFunction
                           .WithExpressionBody(CreateExpressionBody(analysis, localFunction))
                           .WithSemicolonToken(CreateSemicolonToken(localFunction.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.OperatorDeclaration:
            {
                var operatorDeclaration          = (OperatorDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body);

                return(operatorDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis))
                       .WithBody(null));
            }

            case SyntaxKind.ConversionOperatorDeclaration:
            {
                var operatorDeclaration          = (ConversionOperatorDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body);

                return(operatorDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis))
                       .WithBody(null));
            }

            case SyntaxKind.PropertyDeclaration:
            {
                var propertyDeclaration          = (PropertyDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(propertyDeclaration.AccessorList);

                return(propertyDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, propertyDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis))
                       .WithAccessorList(null));
            }

            case SyntaxKind.IndexerDeclaration:
            {
                var indexerDeclaration           = (IndexerDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(indexerDeclaration.AccessorList);

                return(indexerDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, indexerDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis))
                       .WithAccessorList(null));
            }

            case SyntaxKind.GetAccessorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            case SyntaxKind.InitAccessorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
            {
                var accessor = (AccessorDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(accessor);

                return(accessor
                       .WithExpressionBody(CreateExpressionBody(analysis, accessor))
                       .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis))
                       .WithBody(null));
            }

            default:
            {
                SyntaxDebug.Fail(node);
                return(node);
            }
            }
        }
Esempio n. 28
0
        public virtual void VisitStatement(StatementSyntax node)
        {
            switch (node.Kind())
            {
            case SyntaxKind.Block:
            {
                VisitBlock((BlockSyntax)node);
                break;
            }

            case SyntaxKind.BreakStatement:
            {
                VisitBreakStatement((BreakStatementSyntax)node);
                break;
            }

            case SyntaxKind.ContinueStatement:
            {
                VisitContinueStatement((ContinueStatementSyntax)node);
                break;
            }

            case SyntaxKind.DoStatement:
            {
                VisitDoStatement((DoStatementSyntax)node);
                break;
            }

            case SyntaxKind.EmptyStatement:
            {
                VisitEmptyStatement((EmptyStatementSyntax)node);
                break;
            }

            case SyntaxKind.ExpressionStatement:
            {
                VisitExpressionStatement((ExpressionStatementSyntax)node);
                break;
            }

            case SyntaxKind.FixedStatement:
            {
                VisitFixedStatement((FixedStatementSyntax)node);
                break;
            }

            case SyntaxKind.ForEachStatement:
            {
                VisitForEachStatement((ForEachStatementSyntax)node);
                break;
            }

            case SyntaxKind.ForEachVariableStatement:
            {
                VisitForEachVariableStatement((ForEachVariableStatementSyntax)node);
                break;
            }

            case SyntaxKind.ForStatement:
            {
                VisitForStatement((ForStatementSyntax)node);
                break;
            }

            case SyntaxKind.GotoStatement:
            case SyntaxKind.GotoCaseStatement:
            case SyntaxKind.GotoDefaultStatement:
            {
                VisitGotoStatement((GotoStatementSyntax)node);
                break;
            }

            case SyntaxKind.CheckedStatement:
            case SyntaxKind.UncheckedStatement:
            {
                VisitCheckedStatement((CheckedStatementSyntax)node);
                break;
            }

            case SyntaxKind.IfStatement:
            {
                VisitIfStatement((IfStatementSyntax)node);
                break;
            }

            case SyntaxKind.LabeledStatement:
            {
                VisitLabeledStatement((LabeledStatementSyntax)node);
                break;
            }

            case SyntaxKind.LocalDeclarationStatement:
            {
                VisitLocalDeclarationStatement((LocalDeclarationStatementSyntax)node);
                break;
            }

            case SyntaxKind.LocalFunctionStatement:
            {
                VisitLocalFunctionStatement((LocalFunctionStatementSyntax)node);
                break;
            }

            case SyntaxKind.LockStatement:
            {
                VisitLockStatement((LockStatementSyntax)node);
                break;
            }

            case SyntaxKind.ReturnStatement:
            {
                VisitReturnStatement((ReturnStatementSyntax)node);
                break;
            }

            case SyntaxKind.SwitchStatement:
            {
                VisitSwitchStatement((SwitchStatementSyntax)node);
                break;
            }

            case SyntaxKind.ThrowStatement:
            {
                VisitThrowStatement((ThrowStatementSyntax)node);
                break;
            }

            case SyntaxKind.TryStatement:
            {
                VisitTryStatement((TryStatementSyntax)node);
                break;
            }

            case SyntaxKind.UnsafeStatement:
            {
                VisitUnsafeStatement((UnsafeStatementSyntax)node);
                break;
            }

            case SyntaxKind.UsingStatement:
            {
                VisitUsingStatement((UsingStatementSyntax)node);
                break;
            }

            case SyntaxKind.WhileStatement:
            {
                VisitWhileStatement((WhileStatementSyntax)node);
                break;
            }

            case SyntaxKind.YieldBreakStatement:
            case SyntaxKind.YieldReturnStatement:
            {
                VisitYieldStatement((YieldStatementSyntax)node);
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node);
                Visit(node);
                break;
            }
            }
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Diagnostic diagnostic = context.Diagnostics[0];

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

            if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveUnreachableCode, context.Document, root.SyntaxTree))
            {
                return;
            }

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out StatementSyntax statement))
            {
                return;
            }

            SyntaxDebug.Assert(context.Span.Start == statement.SpanStart, statement);

            if (context.Span.Start != statement.SpanStart)
            {
                return;
            }

            CodeAction codeAction = CreateCodeActionForIfElse(context.Document, diagnostic, statement.Parent);

            if (codeAction != null)
            {
                context.RegisterCodeFix(codeAction, diagnostic);
                return;
            }

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            if (statementsInfo.Success)
            {
                codeAction = CodeAction.Create(
                    Title,
                    ct =>
                {
                    SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

                    int index = statements.IndexOf(statement);

                    if (index == statements.Count - 1)
                    {
                        return(context.Document.RemoveStatementAsync(statement, ct));
                    }
                    else
                    {
                        int lastIndex = statements.LastIndexOf(f => !f.IsKind(SyntaxKind.LocalFunctionStatement));

                        SyntaxList <StatementSyntax> nodes = RemoveRange(statements, index, lastIndex - index + 1, f => !f.IsKind(SyntaxKind.LocalFunctionStatement));

                        return(context.Document.ReplaceStatementsAsync(
                                   statementsInfo,
                                   nodes,
                                   ct));
                    }
                },
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
            }
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Diagnostic diagnostic = context.Diagnostics[0];

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

            if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemovePropertyOrFieldInitializer, context.Document, root.SyntaxTree))
            {
                return;
            }

            if (!TryFindToken(root, context.Span.Start, out SyntaxToken token))
            {
                return;
            }

            SyntaxDebug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token);

            if (!token.IsKind(SyntaxKind.IdentifierToken))
            {
                return;
            }

            switch (token.Parent)
            {
            case PropertyDeclarationSyntax propertyDeclaration:
            {
                EqualsValueClauseSyntax initializer = propertyDeclaration.Initializer;

                CodeAction codeAction = CodeAction.Create(
                    Title,
                    ct =>
                    {
                        PropertyDeclarationSyntax newNode = propertyDeclaration
                                                            .RemoveNode(initializer)
                                                            .WithSemicolonToken(default(SyntaxToken))
                                                            .AppendToTrailingTrivia(propertyDeclaration.SemicolonToken.GetAllTrivia())
                                                            .WithFormatterAnnotation();

                        return(context.Document.ReplaceNodeAsync(propertyDeclaration, newNode, ct));
                    },
                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.RemovePropertyOrFieldInitializer));

                context.RegisterCodeFix(codeAction, diagnostic);
                break;
            }

            case VariableDeclaratorSyntax variableDeclarator:
            {
                EqualsValueClauseSyntax initializer = variableDeclarator.Initializer;

                CodeAction codeAction = CodeAction.Create(
                    Title,
                    ct =>
                    {
                        VariableDeclaratorSyntax newNode = variableDeclarator
                                                           .RemoveNode(initializer)
                                                           .WithFormatterAnnotation();

                        return(context.Document.ReplaceNodeAsync(variableDeclarator, newNode, ct));
                    },
                    GetEquivalenceKey(CompilerDiagnosticIdentifiers.CS0573_CannotHaveInstancePropertyOrFieldInitializersInStruct, CodeFixIdentifiers.RemovePropertyOrFieldInitializer));

                context.RegisterCodeFix(codeAction, diagnostic);
                break;
            }
            }
        }