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]);
        }
예제 #2
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 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);
            }
예제 #4
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);
            }
        }
예제 #5
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);
        }
예제 #6
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);
        }
예제 #7
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);
        }
예제 #8
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");
            }
        }
예제 #10
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 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);
        }
예제 #12
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;
            }
            }
        }
예제 #15
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

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

            SyntaxKind kind       = token.Kind();
            Diagnostic diagnostic = context.Diagnostics[0];
            Document   document   = context.Document;

            switch (diagnostic.Id)
            {
            case CompilerDiagnosticIdentifiers.CS0023_OperatorCannotBeAppliedToOperand:
            {
                if (kind == SyntaxKind.QuestionToken &&
                    token.Parent is ConditionalAccessExpressionSyntax conditionalAccess)
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(conditionalAccess.Expression, context.CancellationToken);

                    if (typeSymbol?.IsErrorType() == false &&
                        !typeSymbol.IsNullableType())
                    {
                        if (typeSymbol.IsValueType)
                        {
                            if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConditionalAccess, document, root.SyntaxTree))
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Remove '?' operator",
                                    ct => document.WithTextChangeAsync(token.Span, "", ct),
                                    GetEquivalenceKey(diagnostic));

                                context.RegisterCodeFix(codeAction, diagnostic);
                            }
                        }
                        else if (typeSymbol.IsReferenceType)
                        {
                            if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList, document, root.SyntaxTree) &&
                                conditionalAccess.WhenNotNull is MemberBindingExpressionSyntax memberBindingExpression)
                            {
                                ConditionalAccessExpressionSyntax newNode = conditionalAccess.WithWhenNotNull(
                                    InvocationExpression(
                                        memberBindingExpression.WithoutTrailingTrivia(),
                                        ArgumentList().WithTrailingTrivia(memberBindingExpression.GetTrailingTrivia())));

                                CodeAction codeAction = CodeAction.Create(
                                    "Add argument list",
                                    ct => document.ReplaceNodeAsync(conditionalAccess, newNode, ct),
                                    GetEquivalenceKey(diagnostic));

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

                break;
            }

            case CompilerDiagnosticIdentifiers.CS0267_PartialModifierCanOnlyAppearImmediatelyBeforeClassStructInterfaceOrVoid:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.OrderModifiers, document, root.SyntaxTree))
                {
                    break;
                }

                ModifiersCodeFixRegistrator.MoveModifier(context, diagnostic, token.Parent, token);
                break;
            }

            case CompilerDiagnosticIdentifiers.CS1750_ValueCannotBeUsedAsDefaultParameter:
            {
                if (token.Parent is not ParameterSyntax parameter)
                {
                    break;
                }

                ExpressionSyntax value = parameter.Default?.Value;

                if (value == null)
                {
                    break;
                }

                if (value.IsKind(SyntaxKind.NullLiteralExpression))
                {
                    if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue, document, root.SyntaxTree))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, value, semanticModel);
                    }
                }
                else if (!value.IsKind(SyntaxKind.DefaultExpression, SyntaxKind.DefaultLiteralExpression))
                {
                    if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeParameterType, document, root.SyntaxTree))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(value, context.CancellationToken);

                        if (!typeSymbol.IsKind(SymbolKind.ErrorType))
                        {
                            CodeFixRegistrator.ChangeType(context, diagnostic, parameter.Type, typeSymbol, semanticModel);
                        }
                    }
                }

                break;
            }

            case CompilerDiagnosticIdentifiers.CS0126_ObjectOfTypeConvertibleToTypeIsRequired:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReturnDefaultValue, document, root.SyntaxTree))
                {
                    break;
                }

                if (!token.IsKind(SyntaxKind.ReturnKeyword))
                {
                    break;
                }

                if (!token.IsParentKind(SyntaxKind.ReturnStatement))
                {
                    break;
                }

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

                ISymbol symbol = semanticModel.GetEnclosingSymbol(token.SpanStart, context.CancellationToken);

                if (symbol == null)
                {
                    break;
                }

                SymbolKind symbolKind = symbol.Kind;

                ITypeSymbol typeSymbol = null;

                if (symbolKind == SymbolKind.Method)
                {
                    var methodSymbol = (IMethodSymbol)symbol;

                    typeSymbol = methodSymbol.ReturnType;

                    if (methodSymbol.IsAsync &&
                        (typeSymbol is INamedTypeSymbol namedTypeSymbol))
                    {
                        ImmutableArray <ITypeSymbol> typeArguments = namedTypeSymbol.TypeArguments;

                        if (typeArguments.Any())
                        {
                            typeSymbol = typeArguments[0];
                        }
                    }
                }
                else if (symbolKind == SymbolKind.Property)
                {
                    typeSymbol = ((IPropertySymbol)symbol).Type;
                }
                else
                {
                    Debug.Fail(symbolKind.ToString());
                }

                if (typeSymbol == null)
                {
                    break;
                }

                if (typeSymbol.Kind == SymbolKind.ErrorType)
                {
                    break;
                }

                if (!typeSymbol.SupportsExplicitDeclaration())
                {
                    break;
                }

                var returnStatement = (ReturnStatementSyntax)token.Parent;

                CodeAction codeAction = CodeAction.Create(
                    "Return default value",
                    ct =>
                    {
                        ExpressionSyntax expression = typeSymbol.GetDefaultValueSyntax(document.GetDefaultSyntaxOptions());

                        if (expression.IsKind(SyntaxKind.DefaultExpression) &&
                            document.SupportsLanguageFeature(CSharpLanguageFeature.DefaultLiteral))
                        {
                            expression = CSharpFactory.DefaultLiteralExpression().WithTriviaFrom(expression);
                        }

                        ReturnStatementSyntax newNode = returnStatement.WithExpression(expression);

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

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

            case CompilerDiagnosticIdentifiers.CS1031_TypeExpected:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddMissingType, document, root.SyntaxTree))
                {
                    break;
                }

                if (!token.IsKind(SyntaxKind.CloseParenToken))
                {
                    break;
                }

                if (token.Parent is not DefaultExpressionSyntax defaultExpression)
                {
                    break;
                }

                if (defaultExpression.Type is not IdentifierNameSyntax identifierName)
                {
                    break;
                }

                if (!identifierName.IsMissing)
                {
                    break;
                }

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

                TypeInfo typeInfo = semanticModel.GetTypeInfo(defaultExpression, context.CancellationToken);

                ITypeSymbol convertedType = typeInfo.ConvertedType;

                if (convertedType?.SupportsExplicitDeclaration() != true)
                {
                    break;
                }

                CodeAction codeAction = CodeAction.Create(
                    $"Add type '{SymbolDisplay.ToMinimalDisplayString(convertedType, semanticModel, defaultExpression.SpanStart, SymbolDisplayFormats.DisplayName)}'",
                    ct =>
                    {
                        TypeSyntax newType = convertedType.ToTypeSyntax()
                                             .WithTriviaFrom(identifierName)
                                             .WithFormatterAndSimplifierAnnotation();

                        return(document.ReplaceNodeAsync(identifierName, newType, ct));
                    },
                    GetEquivalenceKey(diagnostic));

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

            case CompilerDiagnosticIdentifiers.CS1597_SemicolonAfterMethodOrAccessorBlockIsNotValid:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveSemicolon, document, root.SyntaxTree))
                {
                    break;
                }

                if (!token.IsKind(SyntaxKind.SemicolonToken))
                {
                    break;
                }

                switch (token.Parent)
                {
                case MethodDeclarationSyntax methodDeclaration:
                {
                    BlockSyntax body = methodDeclaration.Body;

                    if (body == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove semicolon",
                        ct =>
                            {
                                SyntaxTriviaList trivia = body
                                                          .GetTrailingTrivia()
                                                          .EmptyIfWhitespace()
                                                          .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                          .AddRange(token.TrailingTrivia);

                                MethodDeclarationSyntax newNode = methodDeclaration
                                                                  .WithBody(body.WithTrailingTrivia(trivia))
                                                                  .WithSemicolonToken(default(SyntaxToken));

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

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

                case PropertyDeclarationSyntax propertyDeclaration:
                {
                    AccessorListSyntax accessorList = propertyDeclaration.AccessorList;

                    if (accessorList == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove semicolon",
                        ct =>
                            {
                                SyntaxTriviaList trivia = accessorList
                                                          .GetTrailingTrivia()
                                                          .EmptyIfWhitespace()
                                                          .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                          .AddRange(token.TrailingTrivia);

                                PropertyDeclarationSyntax newNode = propertyDeclaration
                                                                    .WithAccessorList(accessorList.WithTrailingTrivia(trivia))
                                                                    .WithSemicolonToken(default(SyntaxToken));

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

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

                case AccessorDeclarationSyntax accessorDeclaration:
                {
                    BlockSyntax body = accessorDeclaration.Body;

                    if (body == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove semicolon",
                        ct =>
                            {
                                SyntaxTriviaList trivia = body
                                                          .GetTrailingTrivia()
                                                          .EmptyIfWhitespace()
                                                          .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                          .AddRange(token.TrailingTrivia);

                                AccessorDeclarationSyntax newNode = accessorDeclaration
                                                                    .WithBody(body.WithTrailingTrivia(trivia))
                                                                    .WithSemicolonToken(default(SyntaxToken));

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

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

                break;
            }

            case CompilerDiagnosticIdentifiers.CS0030_CannotConvertType:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeForEachType, document, root.SyntaxTree))
                {
                    break;
                }

                if (!token.IsKind(SyntaxKind.ForEachKeyword))
                {
                    break;
                }

                if (token.Parent is not ForEachStatementSyntax forEachStatement)
                {
                    break;
                }

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

                ForEachStatementInfo info = semanticModel.GetForEachStatementInfo(forEachStatement);

                ITypeSymbol typeSymbol = info.ElementType;

                if (typeSymbol.SupportsExplicitDeclaration())
                {
                    CodeFixRegistrator.ChangeType(context, diagnostic, forEachStatement.Type, typeSymbol, semanticModel, CodeFixIdentifiers.ChangeForEachType);
                }

                CodeFixRegistrator.ChangeTypeToVar(context, diagnostic, forEachStatement.Type, CodeFixIdentifiers.ChangeTypeToVar);
                break;
            }

            case CompilerDiagnosticIdentifiers.CS1737_OptionalParametersMustAppearAfterAllRequiredParameters:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDefaultValueToParameter, document, root.SyntaxTree))
                {
                    break;
                }

                if (token.Parent is not BaseParameterListSyntax parameterList)
                {
                    break;
                }

                SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

                ParameterSyntax parameter = null;

                for (int i = 0; i < parameters.Count; i++)
                {
                    ParameterSyntax p = parameters[i];

                    if (p.FullSpan.End <= token.SpanStart)
                    {
                        parameter = p;
                    }
                    else
                    {
                        break;
                    }
                }

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

                IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                ITypeSymbol typeSymbol = parameterSymbol.Type;

                if (typeSymbol.Kind == SymbolKind.ErrorType)
                {
                    break;
                }

                CodeAction codeAction = CodeAction.Create(
                    "Add default value",
                    ct =>
                    {
                        ExpressionSyntax defaultValue = typeSymbol.GetDefaultValueSyntax(document.GetDefaultSyntaxOptions());

                        ParameterSyntax newParameter = parameter
                                                       .WithDefault(EqualsValueClause(defaultValue).WithTrailingTrivia(parameter.GetTrailingTrivia()))
                                                       .WithoutTrailingTrivia()
                                                       .WithFormatterAnnotation();

                        return(document.ReplaceNodeAsync(parameter, newParameter, ct));
                    },
                    GetEquivalenceKey(diagnostic));

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

            case CompilerDiagnosticIdentifiers.CS8632_AnnotationForNullableReferenceTypesShouldOnlyBeUsedWithinNullableAnnotationsContext:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveAnnotationForNullableReferenceTypes, document, root.SyntaxTree))
                {
                    break;
                }

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

                CodeAction codeAction = CodeAction.Create(
                    "Remove 'nullable' annotation",
                    ct =>
                    {
                        var textChange = new TextChange(token.Span, "");

                        return(document.WithTextChangeAsync(textChange, ct));
                    },
                    GetEquivalenceKey(diagnostic));

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

            case CompilerDiagnosticIdentifiers.CS8602_DereferenceOfPossiblyNullReference:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, document, root.SyntaxTree))
                {
                    break;
                }

                Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token.Kind().ToString());

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

                if (!token.IsParentKind(SyntaxKind.IdentifierName))
                {
                    return;
                }

                SyntaxNode node = token.Parent
                                  .WalkUp(f => f.IsKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.InvocationExpression, SyntaxKind.ElementAccessExpression))
                                  .Parent;

                if (node.IsKind(SyntaxKind.ExpressionStatement) &&
                    token.SpanStart == node.SpanStart)
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use null propagation operator",
                        ct =>
                        {
                            var textChange = new TextChange(new TextSpan(token.Span.End, 0), "?");

                            return(document.WithTextChangeAsync(textChange, ct));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                }

                return;
            }

            case CompilerDiagnosticIdentifiers.CS8604_PossibleNullReferenceArgumentForParameter:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, document, root.SyntaxTree))
                {
                    break;
                }

                Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token.Kind().ToString());

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

                if (!token.IsParentKind(SyntaxKind.IdentifierName))
                {
                    return;
                }

                CodeAction codeAction = CodeAction.Create(
                    "Use null-forgiving operator",
                    ct =>
                    {
                        var identifierName = (IdentifierNameSyntax)token.Parent;

                        PostfixUnaryExpressionSyntax newExpression = SuppressNullableWarningExpression(identifierName.WithoutTrivia())
                                                                     .WithTriviaFrom(identifierName);

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

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

            case CompilerDiagnosticIdentifiers.CS8618_NonNullableMemberIsUninitialized:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, document, root.SyntaxTree))
                {
                    break;
                }

                Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token.Kind().ToString());

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

                if (token.IsParentKind(SyntaxKind.PropertyDeclaration))
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use null-forgiving operator",
                        ct =>
                        {
                            var property = (PropertyDeclarationSyntax)token.Parent;

                            PropertyDeclarationSyntax newProperty = property
                                                                    .WithoutTrailingTrivia()
                                                                    .WithInitializer(EqualsValueClause(SuppressNullableWarningExpression(NullLiteralExpression())))
                                                                    .WithSemicolonToken(SemicolonToken().WithTrailingTrivia(property.GetTrailingTrivia()));

                            return(document.ReplaceNodeAsync(property, newProperty, ct));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                }
                else
                {
                    SyntaxDebug.Assert(
                        (token.IsParentKind(SyntaxKind.VariableDeclarator) &&
                         token.Parent.IsParentKind(SyntaxKind.VariableDeclaration) &&
                         token.Parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration)) ||
                        token.IsParentKind(SyntaxKind.ConstructorDeclaration),
                        token);

                    if (token.IsParentKind(SyntaxKind.VariableDeclarator) &&
                        token.Parent.IsParentKind(SyntaxKind.VariableDeclaration) &&
                        token.Parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration))
                    {
                        CodeAction codeAction = CodeAction.Create(
                            "Use null-forgiving operator",
                            ct =>
                            {
                                var declarator = (VariableDeclaratorSyntax)token.Parent;

                                VariableDeclaratorSyntax newDeclarator = declarator
                                                                         .WithoutTrailingTrivia()
                                                                         .WithInitializer(
                                    EqualsValueClause(SuppressNullableWarningExpression(NullLiteralExpression()))
                                    .WithTrailingTrivia(declarator.GetTrailingTrivia()));

                                return(document.ReplaceNodeAsync(declarator, newDeclarator, ct));
                            },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }
                }

                break;
            }

            case CompilerDiagnosticIdentifiers.CS8403_MethodWithIteratorBlockMustBeAsyncToReturnIAsyncEnumerableOfT:
            {
                if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddAsyncModifier, document, root.SyntaxTree))
                {
                    break;
                }

                SyntaxDebug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token);
                SyntaxDebug.Assert(token.IsParentKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement), token.Parent);

                if (token.IsParentKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement))
                {
                    ModifiersCodeFixRegistrator.AddModifier(
                        context,
                        diagnostic,
                        token.Parent,
                        SyntaxKind.AsyncKeyword,
                        additionalKey: CodeFixIdentifiers.AddAsyncModifier);
                }

                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;
            }
            }
        }
        public static void ComputeCodeFix(
            CodeFixContext context,
            Diagnostic diagnostic,
            ExpressionSyntax expression,
            SemanticModel semanticModel)
        {
            TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken);

            ITypeSymbol expressionTypeSymbol = typeInfo.Type;

            if (expressionTypeSymbol == null)
            {
                return;
            }

            if (!expressionTypeSymbol.SupportsExplicitDeclaration())
            {
                return;
            }

            (ISymbol symbol, ITypeSymbol typeSymbol) = GetContainingSymbolAndType(expression, semanticModel, context.CancellationToken);

            SyntaxDebug.Assert(symbol != null, expression);

            if (symbol == null)
            {
                return;
            }

            if (symbol.IsOverride)
            {
                return;
            }

            if (symbol.ImplementsInterfaceMember())
            {
                return;
            }

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

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

            TypeSyntax type = CSharpUtility.GetTypeOrReturnType(node);

            if (type == null)
            {
                return;
            }

            ITypeSymbol newTypeSymbol = expressionTypeSymbol;

            string additionalKey = null;

            var isAsyncMethod = false;
            var insertAwait   = false;
            var isYield       = false;

            if (symbol.IsAsyncMethod())
            {
                isAsyncMethod = true;

                INamedTypeSymbol taskOfT = semanticModel.GetTypeByMetadataName("System.Threading.Tasks.Task`1");

                if (taskOfT == null)
                {
                    return;
                }

                if (expression.Kind() == SyntaxKind.AwaitExpression)
                {
                    newTypeSymbol = taskOfT.Construct(expressionTypeSymbol);
                }
                else if (SymbolEqualityComparer.Default.Equals(expressionTypeSymbol, taskOfT))
                {
                    insertAwait   = true;
                    additionalKey = "InsertAwait";
                }
                else if (expressionTypeSymbol.HasMetadataName(MetadataNames.System_Threading_Tasks_Task))
                {
                    return;
                }
            }
            else if (expression.IsParentKind(SyntaxKind.YieldReturnStatement))
            {
                isYield = true;

                newTypeSymbol = semanticModel
                                .Compilation
                                .GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T)
                                .Construct(expressionTypeSymbol);
            }

            if (!isYield &&
                !isAsyncMethod &&
                !typeSymbol.OriginalDefinition.IsIEnumerableOfT() &&
                newTypeSymbol.OriginalDefinition.HasMetadataName(MetadataNames.System_Linq_IOrderedEnumerable_T))
            {
                INamedTypeSymbol constructedEnumerableSymbol = semanticModel
                                                               .Compilation
                                                               .GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T)
                                                               .Construct(((INamedTypeSymbol)newTypeSymbol).TypeArguments.ToArray());

                RegisterCodeFix(context, diagnostic, node, type, expression, constructedEnumerableSymbol, semanticModel, insertAwait: false);
                additionalKey = "IOrderedEnumerable<T>";
            }

            RegisterCodeFix(context, diagnostic, node, type, expression, newTypeSymbol, semanticModel, insertAwait: insertAwait, additionalKey: additionalKey);
        }
예제 #19
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.CS1591_MissingXmlCommentForPubliclyVisibleTypeOrMember:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDocumentationComment, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add documentation comment",
                        ct => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, ct),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    CodeAction codeAction2 = CodeAction.Create(
                        "Add documentation comment (copy from base if available)",
                        ct => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, ct),
                        GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable"));

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

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

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

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

                    ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType;

                    CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel);

                    break;
                }

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

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

                    var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                    MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken);

                    if (otherPart == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Change return type to 'void'",
                        ct =>
                        {
                            return(context.Document.Solution().ReplaceNodesAsync(
                                       new MethodDeclarationSyntax[] { methodDeclaration, otherPart },
                                       (node, _) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)),
                                       ct));
                        },
                        GetEquivalenceKey(diagnostic));

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

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

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

                    ITypeSymbol typeSymbol = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.PropertyDeclaration:
                    case SyntaxKind.IndexerDeclaration:
                    {
                        var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = propertySymbol.OverriddenProperty.Type;
                        break;
                    }

                    case SyntaxKind.EventDeclaration:
                    {
                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }

                    case SyntaxKind.EventFieldDeclaration:
                    {
                        VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables[0];

                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }
                    }

                    CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel);

                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0260_MissingPartialModifier:
                case CompilerDiagnosticIdentifiers.CS0751_PartialMethodMustBeDeclaredInPartialClassOrPartialStruct:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddPartialModifier, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    SyntaxNode node = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.MethodDeclaration:
                    {
                        if (memberDeclaration.IsParentKind(
                                SyntaxKind.ClassDeclaration,
                                SyntaxKind.StructDeclaration,
                                SyntaxKind.RecordDeclaration,
                                SyntaxKind.RecordStructDeclaration))
                        {
                            node = memberDeclaration.Parent;
                        }

                        break;
                    }

                    case SyntaxKind.ClassDeclaration:
                    case SyntaxKind.StructDeclaration:
                    case SyntaxKind.RecordStructDeclaration:
                    case SyntaxKind.InterfaceDeclaration:
                    case SyntaxKind.RecordDeclaration:
                    {
                        node = memberDeclaration;
                        break;
                    }
                    }

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

                    if (node == null)
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword, title: $"Make {CSharpFacts.GetTitle(node)} partial");
                    break;
                }

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

                    if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(
                        context,
                        diagnostic,
                        memberDeclaration.Parent,
                        SyntaxKind.AbstractKeyword,
                        title: "Make containing class abstract");

                    break;
                }

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

                    var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration;

                    CodeAction codeAction = CodeAction.Create(
                        "Remove parameters",
                        ct =>
                        {
                            ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                            ParameterListSyntax newParameterList = parameterList
                                                                   .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>))
                                                                   .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia())
                                                                   .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia());

                            ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList);

                            return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, ct));
                        },
                        GetEquivalenceKey(diagnostic));

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

                case CompilerDiagnosticIdentifiers.CS0541_ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct:
                case CompilerDiagnosticIdentifiers.CS0525_InterfacesCannotContainFields:
                case CompilerDiagnosticIdentifiers.CS0567_InterfacesCannotContainOperators:
                case CompilerDiagnosticIdentifiers.CS0524_InterfacesCannotDeclareTypes:
                case CompilerDiagnosticIdentifiers.CS0575_OnlyClassTypesCanContainDestructors:
                case CompilerDiagnosticIdentifiers.CS0568_StructsCannotContainExplicitParameterlessConstructors:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveMemberDeclaration, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    CodeFixRegistrator.RemoveMemberDeclaration(context, diagnostic, memberDeclaration);
                    break;
                }

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

                    if (memberDeclaration is not DestructorDeclarationSyntax destructorDeclaration)
                    {
                        break;
                    }

                    if (memberDeclaration.Parent is not ClassDeclarationSyntax classDeclaration)
                    {
                        break;
                    }

                    if (classDeclaration.Identifier.ValueText.Length == 0)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Rename destructor to match class name",
                        ct =>
                        {
                            DestructorDeclarationSyntax newNode = destructorDeclaration.WithIdentifier(classDeclaration.Identifier.WithTriviaFrom(destructorDeclaration.Identifier));

                            return(context.Document.ReplaceNodeAsync(destructorDeclaration, newNode, ct));
                        },
                        GetEquivalenceKey(diagnostic));

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

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

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

                    if (memberDeclaration is MethodDeclarationSyntax methodDeclaration)
                    {
                        IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

                        if (methodSymbol.ReturnType is not INamedTypeSymbol tupleType)
                        {
                            break;
                        }

                        if (!tupleType.IsTupleType)
                        {
                            break;
                        }

                        if (methodSymbol.OverriddenMethod?.ReturnType is not INamedTypeSymbol baseTupleType)
                        {
                            break;
                        }

                        if (!baseTupleType.IsTupleType)
                        {
                            break;
                        }

                        ImmutableArray <IFieldSymbol> elements     = tupleType.TupleElements;
                        ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements;

                        if (elements.Length != baseElements.Length)
                        {
                            break;
                        }

                        int i = 0;
                        while (i < elements.Length)
                        {
                            if (elements[i].Name != baseElements[i].Name)
                            {
                                break;
                            }

                            i++;
                        }

                        if (i == elements.Length)
                        {
                            break;
                        }

                        TupleElementSyntax tupleElement = ((TupleTypeSyntax)methodDeclaration.ReturnType).Elements[i];

                        CodeAction codeAction = CodeAction.Create(
                            $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'",
                            ct => RenameTupleElementAsync(context.Document, methodDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }
                    else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration)
                    {
                        IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken);

                        if (propertySymbol.Type is not INamedTypeSymbol tupleType)
                        {
                            break;
                        }

                        if (!tupleType.IsTupleType)
                        {
                            break;
                        }

                        if (propertySymbol.OverriddenProperty?.Type is not INamedTypeSymbol baseTupleType)
                        {
                            break;
                        }

                        if (!baseTupleType.IsTupleType)
                        {
                            break;
                        }

                        ImmutableArray <IFieldSymbol> elements     = tupleType.TupleElements;
                        ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements;

                        if (elements.Length != baseElements.Length)
                        {
                            break;
                        }

                        int i = 0;
                        while (i < elements.Length)
                        {
                            if (elements[i].Name != baseElements[i].Name)
                            {
                                break;
                            }

                            i++;
                        }

                        if (i == elements.Length)
                        {
                            break;
                        }

                        TupleElementSyntax tupleElement = ((TupleTypeSyntax)propertyDeclaration.Type).Elements[i];

                        CodeAction codeAction = CodeAction.Create(
                            $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'",
                            ct => RenameTupleElementAsync(context.Document, propertyDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CS3000_MethodsWithVariableArgumentsAreNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3001_ArgumentTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3002_ReturnTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3003_TypeOfVariableIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3005_IdentifierDifferingOnlyInCaseIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3006_OverloadedMethodDifferingOnlyInRefOrOutOrInArrayRankIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3007_OverloadedMethodDifferingOnlyByUnnamedArrayTypesIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3008_IdentifierIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3009_BaseTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3016_ArraysAsAttributeArgumentsIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3024_ConstraintTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3027_TypeIsNotCLSCompliantBecauseBaseInterfaceIsNotCLSCompliant:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MarkDeclarationAsNonCLSCompliant, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Mark {CSharpFacts.GetTitle(memberDeclaration)} as non-CLS-compliant",
                        ct => MarkDeclarationAsNonCLSCompliantAsync(context.Document, memberDeclaration, ct),
                        GetEquivalenceKey(diagnostic));

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

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

                    var context2 = new CommonFixContext(
                        context.Document,
                        GetEquivalenceKey(diagnostic),
                        await context.GetSemanticModelAsync().ConfigureAwait(false),
                        context.CancellationToken);

                    CodeAction codeAction = AddParameterToInterfaceMemberRefactoring.ComputeRefactoringForExplicitImplementation(context2, memberDeclaration);

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

                    break;
                }
                }
            }
        }
예제 #20
0
        public static async Task <Document> RefactorAsync(
            Document document,
            MemberDeclarationSyntax member,
            bool copyAfter = true,
            CancellationToken cancellationToken = default)
        {
            MemberDeclarationSyntax newMember = member;

            SyntaxToken identifier = GetIdentifier(member);

            if (identifier != default)
            {
                SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                string newName = identifier.ValueText;

                if (!member.IsKind(SyntaxKind.ConstructorDeclaration))
                {
                    newName = NameGenerator.Default.EnsureUniqueName(newName, semanticModel, member.SpanStart);

                    ISymbol symbol = semanticModel.GetDeclaredSymbol(member, cancellationToken);

                    ImmutableArray <SyntaxNode> references = await SyntaxFinder.FindReferencesAsync(symbol, document.Solution(), documents : ImmutableHashSet.Create(document), cancellationToken : cancellationToken).ConfigureAwait(false);

                    SyntaxToken newIdentifier = SyntaxFactory.Identifier(newName);

                    newMember = member.ReplaceNodes(
                        references.Where(n => member.Contains(n)),
                        (n, _) =>
                    {
                        if (n is IdentifierNameSyntax identifierName)
                        {
                            return(identifierName.WithIdentifier(newIdentifier.WithTriviaFrom(identifierName.Identifier)));
                        }
                        else
                        {
                            SyntaxDebug.Assert(n.IsKind(SyntaxKind.ThisConstructorInitializer, SyntaxKind.BaseConstructorInitializer), n);

                            return(n);
                        }
                    });

                    newMember = SetIdentifier(newMember, newIdentifier.WithRenameAnnotation());
                }
            }
            else
            {
                newMember = newMember.WithNavigationAnnotation();
            }

            MemberDeclarationListInfo memberList = SyntaxInfo.MemberDeclarationListInfo(member.Parent);

            int index = memberList.IndexOf(member);

            if (index == 0)
            {
                if (copyAfter)
                {
                    SyntaxToken?openBrace = memberList.OpenBraceToken;

                    if (openBrace != null &&
                        openBrace.Value.GetFullSpanEndLine() == member.GetFullSpanStartLine())
                    {
                        newMember = newMember.WithLeadingTrivia(member.GetLeadingTrivia().Insert(0, NewLine()));
                    }
                }
                else
                {
                    SyntaxToken?closeBrace = memberList.CloseBraceToken;

                    if (closeBrace != null)
                    {
                        newMember = newMember.WithTrailingTrivia(member.GetTrailingTrivia().Add(NewLine()));
                    }
                }
            }

            int insertIndex = (copyAfter) ? index + 1 : index;

            return(await document.ReplaceMembersAsync(memberList, memberList.Members.Insert(insertIndex, newMember), cancellationToken).ConfigureAwait(false));
        }
예제 #21
0
        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;
            }

            BlockSyntax body = (node is MethodDeclarationSyntax methodDeclaration)
                ? methodDeclaration.Body
                : ((LocalFunctionStatementSyntax)node).Body;

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

            if (body == null)
            {
                return;
            }

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

            ITypeSymbol           typeSymbol           = null;
            HashSet <ITypeSymbol> typeSymbols          = null;
            INamedTypeSymbol      ienumerableOfTSymbol = null;

            foreach (SyntaxNode descendant in body.DescendantNodes(descendIntoChildren: f => !CSharpFacts.IsFunction(f.Kind())))
            {
                if (!descendant.IsKind(SyntaxKind.YieldReturnStatement))
                {
                    continue;
                }

                var yieldReturn = (YieldStatementSyntax)descendant;

                ExpressionSyntax expression = yieldReturn.Expression;

                if (expression == null)
                {
                    continue;
                }

                var namedTypeSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken) as INamedTypeSymbol;

                if (namedTypeSymbol?.IsErrorType() != false)
                {
                    continue;
                }

                if (typeSymbol == null)
                {
                    typeSymbol = namedTypeSymbol;
                }
                else
                {
                    if (typeSymbols == null)
                    {
                        typeSymbols = new HashSet <ITypeSymbol>()
                        {
                            typeSymbol
                        };
                    }

                    if (!typeSymbols.Add(namedTypeSymbol))
                    {
                        continue;
                    }
                }

                if (ienumerableOfTSymbol == null)
                {
                    ienumerableOfTSymbol = semanticModel.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1");
                }

                CodeFixRegistrator.ChangeTypeOrReturnType(
                    context,
                    diagnostic,
                    node,
                    ienumerableOfTSymbol.Construct(namedTypeSymbol),
                    semanticModel,
                    additionalKey: SymbolDisplay.ToMinimalDisplayString(namedTypeSymbol, semanticModel, node.SpanStart, SymbolDisplayFormats.DisplayName));
            }
        }
        public static SyntaxList <AttributeListSyntax> GetAttributeLists(this SyntaxNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            switch (node.Kind())
            {
            case SyntaxKind.EnumDeclaration:
                return(((EnumDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.DelegateDeclaration:
                return(((DelegateDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.ClassDeclaration:
                return(((ClassDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.TypeParameter:
                return(((TypeParameterSyntax)node).AttributeLists);

            case SyntaxKind.RecordDeclaration:
            case SyntaxKind.RecordStructDeclaration:
                return(((RecordDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.StructDeclaration:
                return(((StructDeclarationSyntax)node).AttributeLists);

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

            case SyntaxKind.Parameter:
                return(((ParameterSyntax)node).AttributeLists);

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

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

            case SyntaxKind.InterfaceDeclaration:
                return(((InterfaceDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.IndexerDeclaration:
                return(((IndexerDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.FieldDeclaration:
                return(((FieldDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.EventFieldDeclaration:
                return(((EventFieldDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.EventDeclaration:
                return(((EventDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.EnumMemberDeclaration:
                return(((EnumMemberDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.DestructorDeclaration:
                return(((DestructorDeclarationSyntax)node).AttributeLists);

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

            case SyntaxKind.ConstructorDeclaration:
                return(((ConstructorDeclarationSyntax)node).AttributeLists);

            case SyntaxKind.IncompleteMember:
                return(((IncompleteMemberSyntax)node).AttributeLists);

            case SyntaxKind.GetAccessorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
                return(((AccessorDeclarationSyntax)node).AttributeLists);

            default:
            {
                SyntaxDebug.Assert(node.IsKind(SyntaxKind.GlobalStatement), node);
                return(default);
            }
            }
예제 #23
0
        private static void AnalyzeSuppressNullableWarningExpression(SyntaxNodeAnalysisContext context)
        {
            var suppressExpression = (PostfixUnaryExpressionSyntax)context.Node;

            SyntaxNode node = suppressExpression.WalkUpParentheses().Parent;

            if (node is ArgumentSyntax argument)
            {
                IParameterSymbol parameterSymbol = context.SemanticModel.DetermineParameter(
                    argument,
                    cancellationToken: context.CancellationToken);

                if (parameterSymbol?.Type.IsErrorType() == false &&
                    parameterSymbol.Type.IsReferenceType &&
                    parameterSymbol.Type.NullableAnnotation == NullableAnnotation.Annotated)
                {
                    foreach (AttributeData attribute in parameterSymbol.GetAttributes())
                    {
                        INamedTypeSymbol attributeClass = attribute.AttributeClass;

                        if (attributeClass.HasMetadataName(System_Diagnostics_CodeAnalysis_MaybeNullWhenAttribute) ||
                            attributeClass.HasMetadataName(System_Diagnostics_CodeAnalysis_NotNullIfNotNullAttribute) ||
                            attributeClass.HasMetadataName(System_Diagnostics_CodeAnalysis_NotNullWhenAttribute))
                        {
                            return;
                        }
                    }

                    context.ReportDiagnostic(DiagnosticRules.UnnecessaryNullForgivingOperator, suppressExpression.OperatorToken);
                }
            }
            else if (node.IsKind(SyntaxKind.EqualsValueClause))
            {
                if (suppressExpression.Operand.WalkDownParentheses().IsKind(
                        SyntaxKind.NullLiteralExpression,
                        SyntaxKind.DefaultLiteralExpression,
                        SyntaxKind.DefaultExpression))
                {
                    SyntaxNode parent = node.Parent;

                    if (parent.IsKind(SyntaxKind.PropertyDeclaration))
                    {
                        var property = (PropertyDeclarationSyntax)node.Parent;

                        if (IsNullableReferenceType(context, property.Type))
                        {
                            context.ReportDiagnostic(DiagnosticRules.UnnecessaryNullForgivingOperator, node);
                        }
                    }
                    else if (parent.IsKind(SyntaxKind.VariableDeclarator))
                    {
                        SyntaxDebug.Assert(
                            parent.IsParentKind(SyntaxKind.VariableDeclaration) &&
                            parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration, SyntaxKind.LocalDeclarationStatement),
                            parent);

                        if (parent.IsParentKind(SyntaxKind.VariableDeclaration) &&
                            parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration, SyntaxKind.LocalDeclarationStatement))
                        {
                            var variableDeclaration = (VariableDeclarationSyntax)parent.Parent;

                            if (IsNullableReferenceType(context, variableDeclaration.Type))
                            {
                                if (parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration))
                                {
                                    context.ReportDiagnostic(DiagnosticRules.UnnecessaryNullForgivingOperator, node);
                                }
                                else
                                {
                                    context.ReportDiagnostic(DiagnosticRules.UnnecessaryNullForgivingOperator, suppressExpression.OperatorToken);
                                }
                            }
                        }
                    }
                }
            }
예제 #24
0
        private static void AnalyzeObjectCreationExpression(SyntaxNodeAnalysisContext context)
        {
            var objectCreation = (ObjectCreationExpressionSyntax)context.Node;

            SyntaxNode parent = objectCreation.Parent;

            switch (parent.Kind())
            {
            case SyntaxKind.ThrowExpression:
            case SyntaxKind.ThrowStatement:
            {
                if (UseImplicitObjectCreation(context) &&
                    context.SemanticModel.GetTypeSymbol(objectCreation, context.CancellationToken)?
                    .HasMetadataName(MetadataNames.System_Exception) == true)
                {
                    ReportDiagnostic(context, objectCreation);
                }

                break;
            }

            case SyntaxKind.EqualsValueClause:
            {
                if (!UseImplicitObjectCreation(context))
                {
                    return;
                }

                parent = parent.Parent;

                SyntaxDebug.Assert(parent.IsKind(SyntaxKind.VariableDeclarator, SyntaxKind.PropertyDeclaration), parent);

                if (parent.IsKind(SyntaxKind.VariableDeclarator))
                {
                    parent = parent.Parent;

                    if (parent is VariableDeclarationSyntax variableDeclaration)
                    {
                        SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.LocalDeclarationStatement, SyntaxKind.UsingStatement), parent.Parent);

                        if (parent.IsParentKind(SyntaxKind.FieldDeclaration))
                        {
                            AnalyzeType(context, objectCreation, variableDeclaration.Type);
                        }
                        else if (parent.IsParentKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.UsingStatement))
                        {
                            if (context.UseVarInsteadOfImplicitObjectCreation() == false)
                            {
                                if (variableDeclaration.Type.IsVar)
                                {
                                    ReportDiagnostic(context, objectCreation);
                                }
                                else
                                {
                                    AnalyzeType(context, objectCreation, variableDeclaration.Type);
                                }
                            }
                        }
                    }
                }
                else if (parent.IsKind(SyntaxKind.PropertyDeclaration))
                {
                    AnalyzeType(context, objectCreation, ((PropertyDeclarationSyntax)parent).Type);
                }

                break;
            }

            case SyntaxKind.ArrowExpressionClause:
            {
                if (UseImplicitObjectCreation(context))
                {
                    TypeSyntax type = DetermineReturnType(parent.Parent);

                    SyntaxDebug.Assert(type is not null, parent);

                    if (type is not null)
                    {
                        AnalyzeType(context, objectCreation, type);
                    }
                }

                break;
            }

            case SyntaxKind.ArrayInitializerExpression:
            {
                SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.ArrayCreationExpression, SyntaxKind.ImplicitArrayCreationExpression), parent.Parent);

                if (UseImplicitObjectCreation(context) &&
                    parent.IsParentKind(SyntaxKind.ArrayCreationExpression))
                {
                    var arrayCreationExpression = (ArrayCreationExpressionSyntax)parent.Parent;

                    AnalyzeType(context, objectCreation, arrayCreationExpression.Type.ElementType);
                }

                break;
            }

            case SyntaxKind.ReturnStatement:
            case SyntaxKind.YieldReturnStatement:
            {
                if (!UseImplicitObjectCreationWhenTypeIsNotObvious(context))
                {
                    return;
                }

                for (SyntaxNode node = parent.Parent; node is not null; node = node.Parent)
                {
                    if (CSharpFacts.IsAnonymousFunctionExpression(node.Kind()))
                    {
                        return;
                    }

                    TypeSyntax type = DetermineReturnType(node);

                    if (type is not null)
                    {
                        if (parent.IsKind(SyntaxKind.YieldReturnStatement))
                        {
                            ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(type, context.CancellationToken);

                            if (typeSymbol?.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T)
                            {
                                var ienumerableOfT = (INamedTypeSymbol)typeSymbol;

                                ITypeSymbol typeSymbol2 = ienumerableOfT.TypeArguments.Single();

                                AnalyzeTypeSymbol(context, objectCreation, typeSymbol2);
                            }
                        }
                        else
                        {
                            AnalyzeType(context, objectCreation, type);
                        }

                        return;
                    }
                }

                break;
            }

            case SyntaxKind.SimpleAssignmentExpression:
            case SyntaxKind.CoalesceAssignmentExpression:
            case SyntaxKind.AddAssignmentExpression:
            case SyntaxKind.SubtractAssignmentExpression:
            {
                if (UseImplicitObjectCreationWhenTypeIsNotObvious(context))
                {
                    var assignment = (AssignmentExpressionSyntax)parent;
                    AnalyzeExpression(context, objectCreation, assignment.Left);
                }

                break;
            }

            case SyntaxKind.CoalesceExpression:
            {
                if (UseImplicitObjectCreationWhenTypeIsNotObvious(context))
                {
                    var coalesceExpression = (BinaryExpressionSyntax)parent;
                    AnalyzeExpression(context, objectCreation, coalesceExpression.Left);
                }

                break;
            }

            case SyntaxKind.CollectionInitializerExpression:
            {
                SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.ObjectCreationExpression, SyntaxKind.ImplicitObjectCreationExpression, SyntaxKind.SimpleAssignmentExpression), parent.Parent);

                if (!UseImplicitObjectCreation(context))
                {
                    return;
                }

                parent = parent.Parent;
                if (parent.IsKind(SyntaxKind.ObjectCreationExpression, SyntaxKind.ImplicitObjectCreationExpression))
                {
                    SyntaxNode parentObjectCreation = parent;

                    parent = parent.Parent;
                    if (parent.IsKind(SyntaxKind.EqualsValueClause))
                    {
                        parent = parent.Parent;
                        if (parent.IsKind(SyntaxKind.VariableDeclarator))
                        {
                            parent = parent.Parent;
                            if (parent is VariableDeclarationSyntax variableDeclaration &&
                                parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.LocalDeclarationStatement))
                            {
                                if (parentObjectCreation is ExpressionSyntax parentObjectCreationExpression)
                                {
                                    AnalyzeExpression(context, objectCreation, parentObjectCreationExpression, isGenericType: true);
                                }
                                else
                                {
                                    AnalyzeType(context, objectCreation, variableDeclaration.Type, isGenericType: true);
                                }
                            }
                        }
                        else if (parent.IsKind(SyntaxKind.PropertyDeclaration))
                        {
                            AnalyzeType(context, objectCreation, ((PropertyDeclarationSyntax)parent).Type);
                        }
                    }
                }

                break;
            }

            case SyntaxKind.ComplexElementInitializerExpression:
            {
                break;
            }
            }
        }
예제 #25
0
        private void AnalyzeImplicitObjectCreationExpression(SyntaxNodeAnalysisContext context)
        {
            var implicitObjectCreation = (ImplicitObjectCreationExpressionSyntax)context.Node;

            SyntaxNode parent = implicitObjectCreation.Parent;

            switch (parent.Kind())
            {
            case SyntaxKind.ThrowExpression:
            case SyntaxKind.ThrowStatement:
            {
                if (UseExplicitObjectCreation(context) &&
                    context.SemanticModel.GetTypeSymbol(implicitObjectCreation, context.CancellationToken)?
                    .HasMetadataName(MetadataNames.System_Exception) == true)
                {
                    ReportDiagnostic(context, implicitObjectCreation);
                }

                break;
            }

            case SyntaxKind.EqualsValueClause:
            {
                parent = parent.Parent;

                SyntaxDebug.Assert(parent.IsKind(SyntaxKind.VariableDeclarator, SyntaxKind.PropertyDeclaration), parent);

                if (parent.IsKind(SyntaxKind.VariableDeclarator))
                {
                    parent = parent.Parent;

                    if (parent is VariableDeclarationSyntax variableDeclaration)
                    {
                        SyntaxDebug.Assert(!variableDeclaration.Type.IsVar, variableDeclaration);

                        SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.LocalDeclarationStatement, SyntaxKind.UsingStatement), parent.Parent);

                        if (UseExplicitObjectCreation(context))
                        {
                            ReportDiagnostic(context, implicitObjectCreation);
                        }
                        else if (parent.IsParentKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.UsingStatement) &&
                                 variableDeclaration.Variables.Count == 1 &&
                                 !variableDeclaration.Type.IsVar &&
                                 context.UseVarInsteadOfImplicitObjectCreation() == true)
                        {
                            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UseImplicitOrExplicitObjectCreation, variableDeclaration, "explicit");
                        }
                    }
                }
                else if (parent.IsKind(SyntaxKind.PropertyDeclaration))
                {
                    if (UseExplicitObjectCreation(context))
                    {
                        ReportDiagnostic(context, implicitObjectCreation);
                    }
                }

                break;
            }

            case SyntaxKind.ArrowExpressionClause:
            {
                if (UseExplicitObjectCreation(context))
                {
                    TypeSyntax type = DetermineReturnType(parent.Parent);

                    SyntaxDebug.Assert(type is not null, parent);

                    if (type is not null)
                    {
                        ReportDiagnostic(context, implicitObjectCreation);
                    }
                }

                return;
            }

            case SyntaxKind.ArrayInitializerExpression:
            {
                SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.ArrayCreationExpression, SyntaxKind.ImplicitArrayCreationExpression), parent.Parent);

                if (UseExplicitObjectCreation(context) &&
                    parent.IsParentKind(SyntaxKind.ArrayCreationExpression))
                {
                    ReportDiagnostic(context, implicitObjectCreation);
                }

                break;
            }

            case SyntaxKind.ReturnStatement:
            case SyntaxKind.YieldReturnStatement:
            {
                if (!UseExplicitObjectCreationWhenTypeIsNotObvious(context))
                {
                    return;
                }

                for (SyntaxNode node = parent.Parent; node is not null; node = node.Parent)
                {
                    if (CSharpFacts.IsAnonymousFunctionExpression(node.Kind()))
                    {
                        return;
                    }

                    TypeSyntax type = DetermineReturnType(node);

                    if (type is not null)
                    {
                        if (parent.IsKind(SyntaxKind.YieldReturnStatement))
                        {
                            ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(type, context.CancellationToken);

                            if (typeSymbol?.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T)
                            {
                                ReportDiagnostic(context, implicitObjectCreation);
                            }
                        }
                        else
                        {
                            ReportDiagnostic(context, implicitObjectCreation);
                        }
                    }
                }

                break;
            }

            case SyntaxKind.SimpleAssignmentExpression:
            case SyntaxKind.CoalesceAssignmentExpression:
            case SyntaxKind.AddAssignmentExpression:
            case SyntaxKind.SubtractAssignmentExpression:
            case SyntaxKind.CoalesceExpression:
            {
                if (UseExplicitObjectCreationWhenTypeIsNotObvious(context))
                {
                    ReportDiagnostic(context, implicitObjectCreation);
                }

                break;
            }

            case SyntaxKind.CollectionInitializerExpression:
            {
                SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.ObjectCreationExpression, SyntaxKind.ImplicitObjectCreationExpression, SyntaxKind.SimpleAssignmentExpression), parent.Parent);

                if (!UseExplicitObjectCreation(context))
                {
                    return;
                }

                parent = parent.Parent;
                if (parent.IsKind(SyntaxKind.ObjectCreationExpression, SyntaxKind.ImplicitObjectCreationExpression))
                {
                    parent = parent.Parent;
                    if (parent.IsKind(SyntaxKind.EqualsValueClause))
                    {
                        parent = parent.Parent;
                        if (parent.IsKind(SyntaxKind.VariableDeclarator))
                        {
                            parent = parent.Parent;
                            if (parent is VariableDeclarationSyntax)
                            {
                                SyntaxDebug.Assert(parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.LocalDeclarationStatement, SyntaxKind.UsingStatement), parent.Parent);

                                if (UseExplicitObjectCreation(context))
                                {
                                    ReportDiagnostic(context, implicitObjectCreation);
                                }
                            }
                        }
                        else if (parent.IsKind(SyntaxKind.PropertyDeclaration))
                        {
                            if (UseExplicitObjectCreation(context))
                            {
                                ReportDiagnostic(context, implicitObjectCreation);
                            }
                        }
                    }
                }

                break;
            }

            case SyntaxKind.ComplexElementInitializerExpression:
            {
                break;
            }
            }
        }