public static async Task <Solution> RefactorAsync(
            Document document,
            FieldDeclarationSyntax fieldDeclaration,
            VariableDeclaratorSyntax variableDeclarator,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax value = variableDeclarator.Initializer.Value;

            ParenthesizedExpressionSyntax newValue = value
                                                     .Parenthesize(moveTrivia: true)
                                                     .WithSimplifierAnnotation();

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

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

            IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false);

            var newDocuments = new List <KeyValuePair <DocumentId, SyntaxNode> >();

            foreach (IGrouping <Document, ReferenceLocation> grouping in referencedSymbols
                     .First()
                     .Locations
                     .Where(f => !f.IsImplicit && !f.IsCandidateLocation)
                     .GroupBy(f => f.Document))
            {
                SyntaxNode root = await grouping.Key.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                SyntaxNode newRoot = root.ReplaceNodes(
                    GetNodesToReplace(grouping.AsEnumerable(), root, fieldDeclaration, variableDeclarator),
                    (f, g) =>
                {
                    if (f.IsKind(SyntaxKind.FieldDeclaration, SyntaxKind.VariableDeclarator))
                    {
                        return(f.WithAdditionalAnnotations(_removeAnnotation));
                    }

                    return(newValue);
                });

                SyntaxNode nodeToRemove = newRoot.GetAnnotatedNodes(_removeAnnotation).FirstOrDefault();

                if (nodeToRemove != null)
                {
                    newRoot = newRoot.RemoveNode(nodeToRemove, RemoveHelper.GetRemoveOptions(nodeToRemove));
                }

                newDocuments.Add(new KeyValuePair <DocumentId, SyntaxNode>(grouping.Key.Id, newRoot));
            }

            Solution newSolution = document.Solution();

            foreach (KeyValuePair <DocumentId, SyntaxNode> kvp in newDocuments)
            {
                newSolution = newSolution.WithDocumentSyntaxRoot(kvp.Key, kvp.Value);
            }

            return(newSolution);
        }
        private static void RemoveConstraint(
            CodeFixContext context,
            Diagnostic diagnostic,
            TypeParameterConstraintSyntax constraint)
        {
            CodeAction codeAction = CodeAction.Create(
                $"Remove constraint '{constraint}'",
                cancellationToken => context.Document.RemoveNodeAsync(constraint, RemoveHelper.GetRemoveOptions(constraint), cancellationToken),
                GetEquivalenceKey(diagnostic, constraint.Kind().ToString()));

            context.RegisterCodeFix(codeAction, diagnostic);
        }
Пример #3
0
        public static Task <Document> RefactorAsync(
            Document document,
            ThrowStatementSyntax throwStatement,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            ExpressionSyntax expression = throwStatement.Expression;

            ThrowStatementSyntax newThrowStatement = throwStatement
                                                     .RemoveNode(expression, RemoveHelper.GetRemoveOptions(expression))
                                                     .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(throwStatement, newThrowStatement, cancellationToken));
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveAttribute))
            {
                return;
            }

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

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out AttributeSyntax attribute))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.AttributeIsNotValidOnThisDeclarationType:
                case CompilerDiagnosticIdentifiers.AttributeIsOnlyValidOnMethodsOrAttributeClasses:
                {
                    CodeAction codeAction = CodeAction.Create(
                        $"Remove attribute '{attribute.Name}'",
                        cancellationToken =>
                        {
                            var attributeList = (AttributeListSyntax)attribute.Parent;

                            SeparatedSyntaxList <AttributeSyntax> attributes = attributeList.Attributes;

                            if (attributes.Count == 1)
                            {
                                return(context.Document.RemoveNodeAsync(attributeList, RemoveHelper.GetRemoveOptions(attributeList), cancellationToken));
                            }
                            else
                            {
                                return(context.Document.RemoveNodeAsync(attribute, RemoveHelper.GetRemoveOptions(attributeList), cancellationToken));
                            }
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        public static Task <Document> RefactorAsync(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken)
        {
            if (node.Kind() == SyntaxKind.VariableDeclarator)
            {
                var variableDeclaration = (VariableDeclarationSyntax)node.Parent;

                if (variableDeclaration.Variables.Count == 1)
                {
                    SyntaxNode parent = variableDeclaration.Parent;

                    return(document.RemoveNodeAsync(parent, RemoveHelper.GetRemoveOptions(parent), cancellationToken));
                }
            }

            return(document.RemoveNodeAsync(node, RemoveHelper.GetRemoveOptions(node), cancellationToken));
        }
Пример #6
0
        public static Task <Document> RefactorAsync(
            Document document,
            InvocationExpressionSyntax invocation,
            CancellationToken cancellationToken)
        {
            var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression;

            ArgumentSyntax lastArgument = invocation.ArgumentList.Arguments.Last();

            var lambdaExpression = (LambdaExpressionSyntax)lastArgument.Expression;

            GenericNameSyntax newName = GenericName(
                Identifier("Cast"),
                GetCastExpression(lambdaExpression.Body).Type);
            InvocationExpressionSyntax newInvocation = invocation
                                                       .RemoveNode(lastArgument, RemoveHelper.GetRemoveOptions(lastArgument))
                                                       .WithExpression(memberAccess.WithName(newName));

            return(document.ReplaceNodeAsync(invocation, newInvocation, cancellationToken));
        }
        private static SyntaxNode RemoveUsingDirective(SyntaxNode node, int index)
        {
            switch (node.Kind())
            {
            case SyntaxKind.CompilationUnit:
            {
                var compilationUnit = (CompilationUnitSyntax)node;

                UsingDirectiveSyntax usingDirective = compilationUnit.Usings[index];
                return(compilationUnit.RemoveNode(usingDirective, RemoveHelper.GetRemoveOptions(usingDirective)));
            }

            case SyntaxKind.NamespaceDeclaration:
            {
                var namespaceDeclaration = (NamespaceDeclarationSyntax)node;

                UsingDirectiveSyntax usingDirective = namespaceDeclaration.Usings[index];
                return(namespaceDeclaration.RemoveNode(usingDirective, RemoveHelper.GetRemoveOptions(usingDirective)));
            }
            }

            return(node);
        }
Пример #8
0
        private void RemoveConstraint(
            CodeFixContext context,
            Diagnostic diagnostic,
            TypeParameterConstraintSyntax constraint)
        {
            SeparatedSyntaxList <TypeParameterConstraintSyntax> constraints;

            if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraints))
            {
                CodeAction codeAction = CodeAction.Create(
                    $"Remove constraint '{constraint}'",
                    cancellationToken => context.Document.RemoveNodeAsync(constraint, RemoveHelper.GetRemoveOptions(constraint), cancellationToken),
                    GetEquivalenceKey(diagnostic, constraint.Kind().ToString()));

                context.RegisterCodeFix(codeAction, diagnostic);
            }
        }
Пример #9
0
        private static async Task <StatementsInfo> RefactorAsync(
            Document document,
            StatementsInfo statementsInfo,
            StatementSyntax statement,
            StatementSyntax newStatement,
            int index,
            int count,
            bool removeReturnStatement,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ReturnStatementSyntax returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index);

            ExpressionSyntax expression    = returnStatement.Expression;
            ExpressionSyntax newExpression = null;

            ISymbol symbol = semanticModel.GetSymbol(expression, cancellationToken);

            if (symbol.IsLocal() &&
                index > 0)
            {
                LocalDeclarationStatementSyntax localDeclarationStatement = FindLocalDeclarationStatementAbove(statementsInfo.Statements, index);

                if (localDeclarationStatement?.ContainsDiagnostics == false &&
                    !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() &&
                    !statement.GetLeadingTrivia().Any(f => f.IsDirective))
                {
                    SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables;
                    VariableDeclaratorSyntax declarator = FindVariableDeclarator(semanticModel, symbol, declarators, cancellationToken);

                    if (declarator != null)
                    {
                        ExpressionSyntax value = declarator.Initializer?.Value;

                        if (removeReturnStatement || value != null)
                        {
                            IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false);

                            if (referencedSymbols.First().Locations.Count() == count + 1)
                            {
                                newExpression = value;

                                if (declarators.Count == 1)
                                {
                                    statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, RemoveHelper.GetRemoveOptions(localDeclarationStatement));
                                    index--;
                                }
                                else
                                {
                                    statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, RemoveHelper.GetRemoveOptions(declarator)));
                                }

                                returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index);
                            }
                        }
                    }
                }
            }

            if (removeReturnStatement)
            {
                statementsInfo = statementsInfo.RemoveNode(returnStatement, RemoveHelper.GetRemoveOptions(returnStatement));
            }
            else if (newExpression != null)
            {
                statementsInfo = statementsInfo.ReplaceNode(returnStatement, returnStatement.WithExpression(newExpression.WithTriviaFrom(expression)));
            }

            return(statementsInfo.ReplaceNode(statementsInfo.Statements[index], newStatement));
        }
Пример #10
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsAnyCodeFixEnabled(
                    CodeFixIdentifiers.ChangeTypeOfParamsParameter,
                    CodeFixIdentifiers.RemoveDefaultValueFromParameter))
            {
                return;
            }

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

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ParameterSyntax parameter))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.ParamsParameterMustBeSingleDimensionalArray:
                {
                    TypeSyntax type = parameter.Type;

                    if (type?.IsMissing == false)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

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

                        if (typeSymbol?.IsNamedType() == true)
                        {
                            ArrayTypeSyntax newType = SyntaxFactory.ArrayType(
                                typeSymbol.ToMinimalTypeSyntax(semanticModel, parameter.SpanStart),
                                SyntaxFactory.SingletonList(SyntaxFactory.ArrayRankSpecifier()));

                            CodeAction codeAction = CodeAction.Create(
                                $"Change parameter type to '{newType}'",
                                cancellationToken => context.Document.ReplaceNodeAsync(type, newType.WithTriviaFrom(type), cancellationToken),
                                GetEquivalenceKey(diagnostic));

                            context.RegisterCodeFix(codeAction, diagnostic);
                        }
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotSpecifyDefaultValueForParameterArray:
                {
                    EqualsValueClauseSyntax defaultValue = parameter.Default;

                    CodeAction codeAction = CodeAction.Create(
                        "Remove default value from parameter",
                        cancellationToken =>
                        {
                            ParameterSyntax newParameter = parameter
                                                           .RemoveNode(defaultValue, RemoveHelper.GetRemoveOptions(defaultValue))
                                                           .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(parameter, newParameter, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        private static CodeAction CreateCodeActionForIfElse(Document document, Diagnostic diagnostic, SyntaxNode node)
        {
            switch (node?.Kind())
            {
            case SyntaxKind.IfStatement:
            {
                var ifStatement = (IfStatementSyntax)node;

                StatementSyntax statement = ifStatement.Else?.Statement;

                if (statement != null)
                {
                    if (statement.IsKind(SyntaxKind.Block))
                    {
                        var block = (BlockSyntax)statement;

                        SyntaxList <StatementSyntax> statements = block.Statements;

                        if (statements.Any())
                        {
                            return(CreateCodeAction(document, diagnostic, ifStatement, statements));
                        }
                    }
                    else
                    {
                        return(CreateCodeAction(document, diagnostic, ifStatement, statement));
                    }
                }

                return(CodeAction.Create(
                           Title,
                           cancellationToken => document.RemoveStatementAsync(ifStatement, cancellationToken),
                           GetEquivalenceKey(diagnostic)));
            }

            case SyntaxKind.ElseClause:
            {
                var elseClause = (ElseClauseSyntax)node;

                if (elseClause.IsParentKind(SyntaxKind.IfStatement))
                {
                    var ifStatement = (IfStatementSyntax)elseClause.Parent;

                    if (ifStatement.IsTopmostIf())
                    {
                        StatementSyntax statement = ifStatement.Statement;

                        if (statement != null)
                        {
                            if (statement.IsKind(SyntaxKind.Block))
                            {
                                var block = (BlockSyntax)statement;

                                SyntaxList <StatementSyntax> statements = block.Statements;

                                if (statements.Any())
                                {
                                    return(CreateCodeAction(document, diagnostic, ifStatement, statements));
                                }
                            }
                            else
                            {
                                return(CreateCodeAction(document, diagnostic, ifStatement, statement));
                            }
                        }
                    }
                }

                return(CodeAction.Create(
                           Title,
                           cancellationToken => document.RemoveNodeAsync(elseClause, RemoveHelper.GetRemoveOptions(elseClause), cancellationToken),
                           GetEquivalenceKey(diagnostic)));
            }

            case SyntaxKind.Block:
            {
                return(CreateCodeActionForIfElse(document, diagnostic, node.Parent));
            }
            }

            return(null);
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemovePropertyOrFieldInitializer))
            {
                return;
            }

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

            SyntaxToken token = root.FindToken(context.Span.Start);

            Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), $"{nameof(token)} is not IdentifierToken");

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

            SyntaxNode parent = token.Parent;

            switch (parent.Kind())
            {
            case SyntaxKind.PropertyDeclaration:
            {
                var propertyDeclaration = (PropertyDeclarationSyntax)parent;

                EqualsValueClauseSyntax initializer = propertyDeclaration.Initializer;

                CodeAction codeAction = CodeAction.Create(
                    Title,
                    cancellationToken =>
                    {
                        PropertyDeclarationSyntax newNode = propertyDeclaration
                                                            .RemoveNode(initializer, RemoveHelper.GetRemoveOptions(initializer))
                                                            .WithSemicolonToken(default(SyntaxToken))
                                                            .AppendToTrailingTrivia(propertyDeclaration.SemicolonToken.GetLeadingAndTrailingTrivia())
                                                            .WithFormatterAnnotation();

                        return(context.Document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken));
                    },
                    GetEquivalenceKey(CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct));

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

            case SyntaxKind.VariableDeclarator:
            {
                var variableDeclarator = (VariableDeclaratorSyntax)parent;
                EqualsValueClauseSyntax initializer = variableDeclarator.Initializer;

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

                        return(context.Document.ReplaceNodeAsync(variableDeclarator, newNode, cancellationToken));
                    },
                    GetEquivalenceKey(CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct));

                context.RegisterCodeFix(codeAction, context.Diagnostics);
                break;
            }
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveUnusedVariable))
            {
                return;
            }

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

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

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.VariableIsDeclaredButNeverUsed:
                case CompilerDiagnosticIdentifiers.VariableIsAssignedButItsValueIsNeverUsed:
                {
                    switch (token.Parent.Kind())
                    {
                    case SyntaxKind.VariableDeclarator:
                    {
                        var variableDeclarator = (VariableDeclaratorSyntax)token.Parent;

                        var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent;

                        if (variableDeclaration.Variables.Count == 1)
                        {
                            var localDeclarationStatement = (LocalDeclarationStatementSyntax)variableDeclaration.Parent;

                            if (!localDeclarationStatement.IsEmbedded() &&
                                !localDeclarationStatement.SpanContainsDirectives())
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Remove unused variable",
                                    cancellationToken => context.Document.RemoveNodeAsync(localDeclarationStatement, RemoveHelper.GetRemoveOptions(localDeclarationStatement), cancellationToken),
                                    GetEquivalenceKey(diagnostic));

                                context.RegisterCodeFix(codeAction, diagnostic);
                            }
                        }
                        else if (!variableDeclarator.SpanContainsDirectives())
                        {
                            CodeAction codeAction = CodeAction.Create(
                                "Remove unused variable",
                                cancellationToken => context.Document.RemoveNodeAsync(variableDeclarator, RemoveHelper.GetRemoveOptions(variableDeclarator), cancellationToken),
                                GetEquivalenceKey(diagnostic));

                            context.RegisterCodeFix(codeAction, diagnostic);
                        }

                        break;
                    }

                    case SyntaxKind.CatchDeclaration:
                    {
                        var catchDeclaration = (CatchDeclarationSyntax)token.Parent;

                        CodeAction codeAction = CodeAction.Create(
                            "Remove unused variable",
                            cancellationToken =>
                                {
                                    CatchDeclarationSyntax newNode = catchDeclaration
                                                                     .WithIdentifier(default(SyntaxToken))
                                                                     .WithCloseParenToken(catchDeclaration.CloseParenToken.PrependToLeadingTrivia(token.GetLeadingAndTrailingTrivia()))
                                                                     .WithFormatterAnnotation();

                                    return(context.Document.ReplaceNodeAsync(catchDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

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

                    case SyntaxKind.LocalFunctionStatement:
                    {
                        var localFunction = (LocalFunctionStatementSyntax)token.Parent;

                        CodeAction codeAction = CodeAction.Create(
                            "Remove unused local function",
                            cancellationToken => context.Document.RemoveStatementAsync(localFunction, cancellationToken),
                            GetEquivalenceKey(diagnostic, "LocalFunction"));

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

                    break;
                }
                }
            }
        }