Esempio n. 1
0
        private static Task <Document> RefactorAsync(
            Document document,
            LocalDeclarationStatementSyntax localDeclaration,
            CancellationToken cancellationToken)
        {
            VariableDeclaratorSyntax variableDeclarator = localDeclaration
                                                          .Declaration
                                                          .Variables
                                                          .Single();

            ExpressionSyntax expression = variableDeclarator
                                          .Initializer
                                          .Value
                                          .WalkDownParentheses();

            AsExpressionInfo asExpressionInfo = SyntaxInfo.AsExpressionInfo(expression);

            PrefixUnaryExpressionSyntax newCondition = LogicalNotExpression(
                ParenthesizedExpression(
                    IsPatternExpression(
                        asExpressionInfo.Expression,
                        DeclarationPattern(
                            asExpressionInfo.Type,
                            SingleVariableDesignation(variableDeclarator.Identifier)))));

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(localDeclaration);

            int index = statementsInfo.IndexOf(localDeclaration);

            var ifStatement = (IfStatementSyntax)statementsInfo[index + 1];

            SyntaxTriviaList leadingTrivia = statementsInfo.Parent
                                             .DescendantTrivia(TextSpan.FromBounds(localDeclaration.SpanStart, ifStatement.SpanStart))
                                             .ToSyntaxTriviaList()
                                             .EmptyIfWhitespace();

            leadingTrivia = localDeclaration.GetLeadingTrivia().AddRange(leadingTrivia);

            StatementSyntax newStatement = ifStatement.Statement;

            if (ifStatement.SingleNonBlockStatementOrDefault() is ReturnStatementSyntax returnStatement &&
                returnStatement.Expression?.WalkDownParentheses() is IdentifierNameSyntax identifierName &&
                string.Equals(identifierName.Identifier.ValueText, variableDeclarator.Identifier.ValueText, System.StringComparison.Ordinal))
            {
                newStatement = newStatement.ReplaceNode(returnStatement.Expression, NullLiteralExpression().WithTriviaFrom(returnStatement.Expression));
            }

            IfStatementSyntax newIfStatement = ifStatement
                                               .WithCondition(newCondition.WithTriviaFrom(ifStatement.Condition))
                                               .WithStatement(newStatement)
                                               .WithLeadingTrivia(leadingTrivia)
                                               .WithFormatterAnnotation();

            SyntaxList <StatementSyntax> newStatements = statementsInfo.Statements.ReplaceRange(index, 2, newIfStatement);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
        }
Esempio n. 2
0
        public static async Task <Document> RefactorAsync(
            Document document,
            WhileStatementSyntax whileStatement,
            CancellationToken cancellationToken)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(whileStatement);

            if (statementsInfo.Success)
            {
                SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                int index = FindLocalDeclarationStatementIndex(
                    whileStatement,
                    statementsInfo.Statements,
                    startIndex: 0,
                    count: statementsInfo.IndexOf(whileStatement),
                    mustBeReferencedInsideWhileStatement: true,
                    semanticModel: semanticModel,
                    cancellationToken: cancellationToken);

                if (index >= 0)
                {
                    List <LocalDeclarationStatementSyntax> localDeclarations = statementsInfo
                                                                               .Statements
                                                                               .Skip(index)
                                                                               .Take(statementsInfo.IndexOf(whileStatement) - index)
                                                                               .Cast <LocalDeclarationStatementSyntax>()
                                                                               .ToList();

                    return(await RefactorAsync(document, whileStatement, localDeclarations, cancellationToken).ConfigureAwait(false));
                }
            }

            return(await document.ReplaceNodeAsync(
                       whileStatement,
                       SyntaxRefactorings.ConvertWhileStatementToForStatement(whileStatement),
                       cancellationToken)
                   .ConfigureAwait(false));
        }
Esempio n. 3
0
        private static Task <Document> RefactorAsync(
            Document document,
            LocalDeclarationStatementSyntax localDeclaration,
            CancellationToken cancellationToken)
        {
            VariableDeclaratorSyntax variableDeclarator = localDeclaration
                                                          .Declaration
                                                          .Variables
                                                          .Single();

            ExpressionSyntax expression = variableDeclarator
                                          .Initializer
                                          .Value
                                          .WalkDownParentheses();

            AsExpressionInfo asExpressionInfo = SyntaxInfo.AsExpressionInfo(expression);

            PrefixUnaryExpressionSyntax newCondition = LogicalNotExpression(
                ParenthesizedExpression(
                    IsPatternExpression(
                        asExpressionInfo.Expression,
                        DeclarationPattern(
                            asExpressionInfo.Type,
                            SingleVariableDesignation(variableDeclarator.Identifier)))));

            StatementListInfo statements = SyntaxInfo.StatementListInfo(localDeclaration);

            int index = statements.IndexOf(localDeclaration);

            var ifStatement = (IfStatementSyntax)statements[index + 1];

            SyntaxTriviaList leadingTrivia = localDeclaration
                                             .DescendantTrivia(TextSpan.FromBounds(localDeclaration.SpanStart, ifStatement.SpanStart))
                                             .ToSyntaxTriviaList()
                                             .EmptyIfWhitespace();

            leadingTrivia = localDeclaration.GetLeadingTrivia().AddRange(leadingTrivia);

            IfStatementSyntax newIfStatement = ifStatement
                                               .WithCondition(newCondition.WithTriviaFrom(ifStatement.Condition))
                                               .WithLeadingTrivia(leadingTrivia);

            StatementListInfo newStatements = statements.RemoveAt(index).ReplaceAt(index, newIfStatement);

            return(document.ReplaceStatementsAsync(statements, newStatements, cancellationToken));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            SingleLocalDeclarationStatementInfo localInfo,
            TypeSyntax type,
            StatementListInfo statementsInfo,
            CancellationToken cancellationToken)
        {
            LocalDeclarationStatementSyntax localStatement = localInfo.Statement;

            int index = statementsInfo.IndexOf(localStatement);

            VariableDeclaratorSyntax declarator = localInfo.Declarator;

            VariableDeclaratorSyntax newDeclarator = declarator.WithInitializer(null);

            VariableDeclarationSyntax newDeclaration = localInfo.Declaration.ReplaceNode(declarator, newDeclarator);

            if (type != null)
            {
                newDeclaration = newDeclaration.WithType(type.WithTriviaFrom(newDeclaration.Type));
            }

            LocalDeclarationStatementSyntax newLocalStatement = localStatement
                                                                .WithDeclaration(newDeclaration)
                                                                .WithTrailingTrivia(NewLine())
                                                                .WithFormatterAnnotation();

            ExpressionStatementSyntax assignmentStatement = SimpleAssignmentStatement(IdentifierName(localInfo.Identifier), localInfo.Initializer.Value)
                                                            .WithTrailingTrivia(localStatement.GetTrailingTrivia())
                                                            .WithFormatterAnnotation();

            StatementListInfo newStatementsInfo = statementsInfo
                                                  .Insert(index + 1, assignmentStatement)
                                                  .ReplaceAt(index, newLocalStatement);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatementsInfo, cancellationToken));
        }
        private static bool IsLocalVariableReferenced(
            SyntaxNodeAnalysisContext context,
            SingleLocalDeclarationStatementInfo localInfo,
            SwitchStatementSyntax switchStatement)
        {
            ISymbol localSymbol = context.SemanticModel.GetDeclaredSymbol(localInfo.Declarator, context.CancellationToken);

            if (localSymbol.IsKind(SymbolKind.Local))
            {
                ContainsLocalOrParameterReferenceWalker walker = ContainsLocalOrParameterReferenceWalker.GetInstance(localSymbol, context.SemanticModel, context.CancellationToken);

                walker.VisitList(switchStatement.Sections);

                if (!walker.Result)
                {
                    StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(switchStatement);

                    if (statementsInfo.Success)
                    {
                        int index = statementsInfo.IndexOf(switchStatement);

                        if (index < statementsInfo.Count - 1)
                        {
                            walker.VisitList(statementsInfo.Statements, index + 1);
                        }
                    }
                }

                bool isReferenced = walker.Result;

                ContainsLocalOrParameterReferenceWalker.Free(walker);

                return(isReferenced);
            }

            return(false);
        }
        private static Task <Document> UsePatternMatchingAsync(
            Document document,
            SwitchStatementSyntax switchStatement,
            CancellationToken cancellationToken)
        {
            SyntaxList <SwitchSectionSyntax> newSections = switchStatement.Sections.Select(section =>
            {
                if (!(section.Labels.Single() is CaseSwitchLabelSyntax label))
                {
                    return(section);
                }

                SyntaxList <StatementSyntax> statements = section.Statements;

                StatementSyntax statement = statements[0];

                if (statement is BlockSyntax block)
                {
                    statement = block.Statements.FirstOrDefault();
                }

                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement);

                var castExpression = (CastExpressionSyntax)localInfo.Value;

                CasePatternSwitchLabelSyntax newLabel = CasePatternSwitchLabel(
                    DeclarationPattern(
                        castExpression.Type,
                        SingleVariableDesignation(localInfo.Identifier)),
                    label.ColonToken);

                SwitchSectionSyntax newSection = section.RemoveStatement(localInfo.Statement);

                newSection = newSection.WithLabels(newSection.Labels.ReplaceAt(0, newLabel));

                return(newSection.WithFormatterAnnotation());
            })
                                                           .ToSyntaxList();

            ExpressionSyntax expression = switchStatement.Expression;

            ExpressionSyntax newExpression = expression;

            LocalDeclarationStatementSyntax localDeclaration = null;

            if (expression.IsKind(SyntaxKind.InvocationExpression))
            {
                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

                newExpression = invocationInfo.Expression;
            }
            else
            {
                localDeclaration = (LocalDeclarationStatementSyntax)switchStatement.PreviousStatement();

                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

                SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(localInfo.Value);

                newExpression = invocationInfo.Expression;
            }

            SwitchStatementSyntax newSwitchStatement = switchStatement
                                                       .WithExpression(newExpression.WithTriviaFrom(expression))
                                                       .WithSections(newSections);

            if (localDeclaration != null)
            {
                StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(switchStatement);

                newSwitchStatement = newSwitchStatement.WithLeadingTrivia(localDeclaration.GetLeadingTrivia());

                SyntaxList <StatementSyntax> newStatements = statementsInfo.Statements
                                                             .Replace(switchStatement, newSwitchStatement)
                                                             .RemoveAt(statementsInfo.IndexOf(localDeclaration));

                return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
            }
            else
            {
                return(document.ReplaceNodeAsync(switchStatement, newSwitchStatement, cancellationToken));
            }
        }
        private static async Task <StatementListInfo> RefactorAsync <TStatement>(
            Document document,
            TStatement statement,
            StatementListInfo statementsInfo,
            Func <TStatement, TStatement> createNewStatement,
            int count,
            bool removeReturnStatement,
            CancellationToken cancellationToken) where TStatement : StatementSyntax
        {
            int statementIndex = statementsInfo.IndexOf(statement);

            var returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1];

            ExpressionSyntax returnExpression    = returnStatement.Expression;
            ExpressionSyntax newReturnExpression = null;
            SyntaxTriviaList newTrailingTrivia   = default;

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

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

            if (symbol.Kind == SymbolKind.Local &&
                statementIndex > 0 &&
                statementsInfo[statementIndex - 1] is LocalDeclarationStatementSyntax localDeclarationStatement &&
                !localDeclarationStatement.ContainsDiagnostics &&
                !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() &&
                !statement.GetLeadingTrivia().Any(f => f.IsDirective))
            {
                SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables;

                VariableDeclaratorSyntax declarator = declarators.FirstOrDefault(f => semanticModel.GetDeclaredSymbol(f, cancellationToken)?.Equals(symbol) == true);

                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)
                        {
                            newReturnExpression = value;

                            if (declarators.Count == 1)
                            {
                                if (!removeReturnStatement &&
                                    returnStatement.GetTrailingTrivia().IsEmptyOrWhitespace())
                                {
                                    SyntaxTriviaList trailingTrivia = localDeclarationStatement.GetTrailingTrivia();

                                    if (trailingTrivia
                                        .SkipWhile(f => f.IsWhitespaceTrivia())
                                        .FirstOrDefault()
                                        .IsKind(SyntaxKind.SingleLineCommentTrivia))
                                    {
                                        newTrailingTrivia = trailingTrivia;
                                    }
                                }

                                SyntaxRemoveOptions removeOptions = SyntaxRefactorings.GetRemoveOptions(localDeclarationStatement);

                                if (newTrailingTrivia.Any())
                                {
                                    removeOptions &= ~SyntaxRemoveOptions.KeepTrailingTrivia;
                                }

                                statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, removeOptions);
                                statementIndex--;
                            }
                            else
                            {
                                statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, SyntaxRefactorings.GetRemoveOptions(declarator)));
                            }

                            returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1];
                        }
                    }
                }
            }

            if (removeReturnStatement)
            {
                statementsInfo = statementsInfo.RemoveNode(returnStatement, SyntaxRefactorings.GetRemoveOptions(returnStatement));
            }
            else if (newReturnExpression != null)
            {
                ReturnStatementSyntax newReturnStatement = returnStatement.WithExpression(newReturnExpression.WithTriviaFrom(returnExpression));

                if (newTrailingTrivia.Any())
                {
                    newReturnStatement = newReturnStatement.WithTrailingTrivia(newTrailingTrivia);
                }

                statementsInfo = statementsInfo.ReplaceNode(returnStatement, newReturnStatement);
            }

            StatementSyntax oldNode = statementsInfo[statementIndex];

            TStatement newNode = createNewStatement((TStatement)oldNode).WithFormatterAnnotation();

            return(statementsInfo.ReplaceNode(oldNode, newNode));
        }
        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);
            }
        }
Esempio n. 9
0
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.ContainsDiagnostics)
            {
                return;
            }

            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement.IsSimpleIf())
            {
                return;
            }

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            if (!statementsInfo.Success)
            {
                return;
            }

            int index = statementsInfo.IndexOf(ifStatement);

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

            if (returnStatement == null)
            {
                return;
            }

            if (returnStatement.ContainsDiagnostics)
            {
                return;
            }

            ExpressionSyntax expression = returnStatement.Expression;

            if (expression == null)
            {
                return;
            }

            if (ifStatement.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

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

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

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

            if (!IsLocalDeclaredInScopeOrNonRefOrOutParameterOfEnclosingSymbol(symbol, statementsInfo.Parent, semanticModel, cancellationToken))
            {
                return;
            }

            foreach (IfStatementOrElseClause ifOrElse in ifStatement.AsCascade())
            {
                if (!IsSymbolAssignedInLastStatement(ifOrElse, symbol, semanticModel, cancellationToken))
                {
                    return;
                }
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UseReturnInsteadOfAssignment, ifStatement);
        }
Esempio n. 10
0
        public static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.ContainsDiagnostics)
            {
                return;
            }

            var switchStatement = (SwitchStatementSyntax)context.Node;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(switchStatement);

            if (!statementsInfo.Success)
            {
                return;
            }

            int index = statementsInfo.IndexOf(switchStatement);

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

            if (returnStatement == null)
            {
                return;
            }

            ExpressionSyntax expression = returnStatement.Expression;

            if (expression == null)
            {
                return;
            }

            if (expression.ContainsDiagnostics)
            {
                return;
            }

            if (switchStatement.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

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

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

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

            if (!IsLocalDeclaredInScopeOrNonRefOrOutParameterOfEnclosingSymbol(symbol, statementsInfo.Parent, semanticModel, cancellationToken))
            {
                return;
            }

            if (!switchStatement
                .Sections
                .All(section => IsValueAssignedInLastStatement(section, symbol, semanticModel, cancellationToken)))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UseReturnInsteadOfAssignment, switchStatement);
        }
Esempio n. 11
0
        internal 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 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 ReturnStatementSyntax returnStatement))
            {
                return;
            }

            if (!(returnStatement.Expression?.WalkDownParentheses() is 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;
            }
            }

            RemoveRedundantAssignmentWalker walker = RemoveRedundantAssignmentWalker.GetInstance();

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

            walker.Visit(assignmentInfo.Right);

            bool result = walker.Result;

            RemoveRedundantAssignmentWalker.Free(walker);

            if (result)
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.RemoveRedundantAssignment, assignment);
        }
Esempio n. 12
0
        public static Task <Document> InlineLazyInitializationAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken = default)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            var assignmentStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault();

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(assignmentStatement, walkDownParentheses: false);

            ExpressionSyntax right = assignmentInfo.Right;

            int index = statementsInfo.IndexOf(ifStatement);

            var expressionStatement2 = (ExpressionStatementSyntax)statementsInfo[index + 1];

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(expressionStatement2);

            ExpressionSyntax expression = invocationInfo.Expression;

            var newLeading = new List <SyntaxTrivia>(ifStatement.GetLeadingTrivia());

            ExpressionSyntax coalesceExpression;

            if (document.SupportsLanguageFeature(CSharpLanguageFeature.NullCoalescingAssignmentOperator))
            {
                AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, right.SpanStart)).ToSyntaxTriviaList());

                coalesceExpression = CoalesceAssignmentExpression(expression.WithoutTrivia(), right.WithoutTrivia());
            }
            else
            {
                AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, assignmentInfo.AssignmentExpression.SpanStart)).ToSyntaxTriviaList());

                coalesceExpression = CoalesceExpression(expression.WithoutTrivia(), ParenthesizedExpression(assignmentInfo.AssignmentExpression.WithoutTrivia()));
            }

            AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(right.Span.End, ifStatement.Span.End)).ToSyntaxTriviaList());
            AddTrivia(ifStatement.GetTrailingTrivia());
            AddTrivia(expressionStatement2.GetLeadingTrivia());

            ParenthesizedExpressionSyntax newExpression = ParenthesizedExpression(coalesceExpression)
                                                          .WithLeadingTrivia(newLeading)
                                                          .WithTrailingTrivia(expression.GetTrailingTrivia());

            StatementSyntax newExpressionStatement = expressionStatement2.ReplaceNode(expression, newExpression);

            StatementListInfo newStatements = statementsInfo
                                              .Replace(expressionStatement2, newExpressionStatement)
                                              .RemoveAt(index);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));

            void AddTrivia(SyntaxTriviaList trivia)
            {
                if (!trivia.IsEmptyOrWhitespace())
                {
                    newLeading.AddRange(trivia);
                }
            }
        }
Esempio n. 13
0
        private static async Task <StatementListInfo> RefactorAsync <TStatement>(
            Document document,
            TStatement statement,
            StatementListInfo statementsInfo,
            Func <TStatement, TStatement> createNewStatement,
            int count,
            bool removeReturnStatement,
            CancellationToken cancellationToken) where TStatement : StatementSyntax
        {
            int index = statementsInfo.IndexOf(statement);

            var returnStatement = (ReturnStatementSyntax)statementsInfo[index + 1];

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

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

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

            if (symbol.Kind == SymbolKind.Local &&
                index > 0)
            {
                var localDeclarationStatement = statementsInfo[index - 1] as LocalDeclarationStatementSyntax;

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

                    VariableDeclaratorSyntax declarator = declarators.FirstOrDefault(f => semanticModel.GetDeclaredSymbol(f, cancellationToken)?.Equals(symbol) == true);

                    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, SyntaxRemover.GetRemoveOptions(localDeclarationStatement));
                                    index--;
                                }
                                else
                                {
                                    statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, SyntaxRemover.GetRemoveOptions(declarator)));
                                }

                                returnStatement = (ReturnStatementSyntax)statementsInfo[index + 1];
                            }
                        }
                    }
                }
            }

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

            StatementSyntax oldNode = statementsInfo[index];

            TStatement newNode = createNewStatement((TStatement)oldNode).WithFormatterAnnotation();

            return(statementsInfo.ReplaceNode(oldNode, newNode));
        }
Esempio n. 14
0
        internal 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 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 ReturnStatementSyntax returnStatement))
            {
                return;
            }

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

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

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

            if (symbol == null)
            {
                return;
            }

            if (!IsFixableSymbol(symbol))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.RemoveRedundantAssignment, assignment);
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            int index = statementsInfo.IndexOf(statement);

            switch (statement.Kind())
            {
            case SyntaxKind.IfStatement:
            {
                var ifStatement = (IfStatementSyntax)statement;

                int  count        = 0;
                bool endsWithElse = false;

                foreach (IfStatementOrElseClause ifOrElse in ifStatement.AsCascade())
                {
                    count++;
                    endsWithElse = ifOrElse.IsElse;
                }

                StatementListInfo newStatementsInfo = await RefactorAsync(
                    document,
                    statementsInfo,
                    ifStatement,
                    CreateNewIfStatement,
                    index,
                    count,
                    endsWithElse,
                    semanticModel,
                    cancellationToken).ConfigureAwait(false);

                return(await document.ReplaceNodeAsync(statementsInfo.Parent, newStatementsInfo.Parent, cancellationToken).ConfigureAwait(false));
            }

            case SyntaxKind.SwitchStatement:
            {
                var switchStatement = (SwitchStatementSyntax)statement;

                StatementListInfo newStatementsInfo = await RefactorAsync(
                    document,
                    statementsInfo,
                    switchStatement,
                    CreateNewSwitchStatement,
                    index,
                    switchStatement.Sections.Count,
                    switchStatement.Sections.Any(f => f.ContainsDefaultLabel()),
                    semanticModel,
                    cancellationToken).ConfigureAwait(false);

                return(await document.ReplaceNodeAsync(statementsInfo.Parent, newStatementsInfo.Parent, cancellationToken).ConfigureAwait(false));
            }
            }

            Debug.Fail(statement.Kind().ToString());

            return(document);
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            int index = statementsInfo.IndexOf(statement);

            switch (statement.Kind())
            {
            case SyntaxKind.IfStatement:
            {
                var ifStatement = (IfStatementSyntax)statement;

                IEnumerable <ExpressionStatementSyntax> expressionStatements = ifStatement
                                                                               .AsCascade()
                                                                               .Select(ifOrElse => (ExpressionStatementSyntax)GetLastStatementOrDefault(ifOrElse.Statement));

                IfStatementSyntax newIfStatement = ifStatement.ReplaceNodes(
                    expressionStatements,
                    (f, _) =>
                    {
                        var assignment = (AssignmentExpressionSyntax)f.Expression;

                        return(ReturnStatement(assignment.Right).WithTriviaFrom(f));
                    });

                int  count        = 0;
                bool endsWithElse = false;

                foreach (IfStatementOrElseClause ifOrElse in ifStatement.AsCascade())
                {
                    count++;
                    endsWithElse = ifOrElse.IsElse;
                }

                StatementListInfo newStatementsInfo = await RefactorAsync(
                    document,
                    statementsInfo,
                    ifStatement,
                    newIfStatement,
                    index,
                    count,
                    endsWithElse,
                    semanticModel,
                    cancellationToken).ConfigureAwait(false);

                return(await document.ReplaceNodeAsync(statementsInfo.Parent, newStatementsInfo.Parent, cancellationToken).ConfigureAwait(false));
            }

            case SyntaxKind.SwitchStatement:
            {
                var switchStatement = (SwitchStatementSyntax)statement;

                SyntaxList <SwitchSectionSyntax> newSections = switchStatement
                                                               .Sections
                                                               .Select(CreateNewSection)
                                                               .ToSyntaxList();

                SwitchStatementSyntax newSwitchStatement = switchStatement.WithSections(newSections);

                StatementListInfo newStatementsInfo = await RefactorAsync(
                    document,
                    statementsInfo,
                    switchStatement,
                    newSwitchStatement,
                    index,
                    switchStatement.Sections.Count,
                    switchStatement.Sections.Any(f => f.ContainsDefaultLabel()),
                    semanticModel,
                    cancellationToken).ConfigureAwait(false);

                return(await document.ReplaceNodeAsync(statementsInfo.Parent, newStatementsInfo.Parent, cancellationToken).ConfigureAwait(false));
            }
            }

            Debug.Fail(statement.Kind().ToString());

            return(document);
        }