private static Task <Document> RefactorAsync(
            Document document,
            SingleLocalDeclarationStatementInfo localInfo,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            StatementsInfo statementsInfo = SyntaxInfo.StatementsInfo(localInfo.Statement);

            var localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(localInfo.Declarator, cancellationToken);

            IdentifierNameSyntax identifierName = FindLastReference(localSymbol, statementsInfo.Node, semanticModel, cancellationToken);

            TextSpan span;

            if (identifierName == null)
            {
                span = localInfo.Statement.Span;
            }
            else
            {
                int position = identifierName.SpanStart;
                span = TextSpan.FromBounds(localInfo.Statement.SpanStart, statementsInfo.First(f => f.Span.Contains(position)).Span.End);
            }

            StatementsSelection selectedStatements = StatementsSelection.Create(statementsInfo, span);

            var refactoring = new WrapStatements.WrapInUsingStatementRefactoring();

            return(refactoring.RefactorAsync(document, selectedStatements, cancellationToken));
        }
        private static bool CanRefactor(SingleLocalDeclarationStatementInfo localInfo, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (!localInfo.Success)
            {
                return(false);
            }

            ExpressionSyntax value = localInfo.Value;

            if (value?.IsKind(SyntaxKind.NullLiteralExpression, SyntaxKind.DefaultExpression) != false)
            {
                return(false);
            }

            if (CannotBeEqualToNull(value))
            {
                return(false);
            }

            IdentifierNameSyntax identifierName = IdentifierName(localInfo.Identifier);

            if (NullCheckExists(identifierName, localInfo.Statement))
            {
                return(false);
            }

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(localInfo.Type, cancellationToken);

            if (typeSymbol == null)
            {
                return(false);
            }

            return(typeSymbol.IsReferenceTypeOrNullableType());
        }
Exemplo n.º 3
0
        private static Task <Document> ConvertWhileStatementToForStatementAsync(
            Document document,
            WhileStatementSyntax whileStatement,
            CancellationToken cancellationToken)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(whileStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(whileStatement);

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statements[index - 1]);

            var block = (BlockSyntax)whileStatement.Statement;

            var expressionStatement = (ExpressionStatementSyntax)block.Statements.Last();

            var postIncrementExpression = (PostfixUnaryExpressionSyntax)expressionStatement.Expression;

            BlockSyntax newBlock = block.WithStatements(block.Statements.Remove(expressionStatement));

            ForStatementSyntax forStatement = CSharpFactory.ForStatement(
                declaration: localInfo.Declaration.TrimTrivia(),
                condition: whileStatement.Condition,
                incrementor: postIncrementExpression.TrimTrivia(),
                statement: newBlock);

            forStatement = forStatement
                           .WithLeadingTrivia(localInfo.Statement.GetLeadingTrivia().AddRange(whileStatement.GetLeadingTrivia().EmptyIfWhitespace()))
                           .WithFormatterAnnotation();

            SyntaxList <StatementSyntax> newStatements = statements.ReplaceRange(index - 1, 2, new StatementSyntax[] { forStatement });

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
        }
Exemplo n.º 4
0
        private static bool CanUseCoalesceExpression(StatementSyntax statement, ExpressionSyntax expression)
        {
            SyntaxKind kind = statement.Kind();

            if (kind == SyntaxKind.LocalDeclarationStatement)
            {
                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement);

                return(localInfo.Success &&
                       !localInfo.Type.IsKind(SyntaxKind.RefType) &&
                       expression.IsKind(SyntaxKind.IdentifierName) &&
                       string.Equals(localInfo.IdentifierText, ((IdentifierNameSyntax)expression).Identifier.ValueText, StringComparison.Ordinal) &&
                       !localInfo.Value.GetTrailingTrivia().Any(f => f.IsDirective) &&
                       !localInfo.SemicolonToken.ContainsDirectives);
            }
            else if (kind == SyntaxKind.ExpressionStatement)
            {
                var expressionStatement = (ExpressionStatementSyntax)statement;

                SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement);

                return(assignmentInfo.Success &&
                       CSharpFactory.AreEquivalent(expression, assignmentInfo.Left) &&
                       !assignmentInfo.Right.GetTrailingTrivia().Any(f => f.IsDirective) &&
                       !expressionStatement.SemicolonToken.ContainsDirectives);
            }

            return(false);
        }
        public static async Task ComputeRefactoringAsync(
            RefactoringContext context,
            LocalDeclarationStatementSyntax localDeclaration)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(localDeclaration);

            if (!statementsInfo.Success)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

            if (!localInfo.Success)
            {
                return;
            }

            if (!context.Span.IsEmptyAndContainedInSpan(localInfo.EqualsToken))
            {
                return;
            }

            ExpressionSyntax value = localInfo.Value;

            if (value == null)
            {
                return;
            }

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

            TypeSyntax type = localInfo.Type;

            if (type.IsVar)
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(value, context.CancellationToken);

                if (typeSymbol?.SupportsExplicitDeclaration() != true)
                {
                    return;
                }

                type = typeSymbol.ToMinimalTypeSyntax(semanticModel, type.SpanStart);
            }
            else
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken);

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

            context.RegisterRefactoring(
                "Split declaration and initialization",
                ct => RefactorAsync(context.Document, localInfo, type, statementsInfo, ct),
                RefactoringIdentifiers.SplitDeclarationAndInitialization);
        }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxList <StatementSyntax> statements,
            SingleLocalDeclarationStatementInfo localDeclarationInfo,
            ExpressionSyntax expression)
        {
            if (expression?.IsKind(SyntaxKind.IdentifierName) == true)
            {
                var identifierName = (IdentifierNameSyntax)expression;

                string name = localDeclarationInfo.IdentifierText;

                if (string.Equals(name, identifierName.Identifier.ValueText, StringComparison.Ordinal))
                {
                    TextSpan span = TextSpan.FromBounds(expression.Span.End, statements.Last().Span.End);

                    SyntaxNode parent = localDeclarationInfo.Statement.Parent;

                    if (!IsLocalVariableReferenced(localDeclarationInfo.Declarator, name, parent, span, context.SemanticModel, context.CancellationToken) &&
                        !parent.ContainsDirectives(TextSpan.FromBounds(localDeclarationInfo.Statement.SpanStart, expression.Span.End)))
                    {
                        ReportDiagnostic(context, localDeclarationInfo, expression);
                    }
                }
            }
        }
Exemplo n.º 7
0
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxList <StatementSyntax> statements,
            SingleLocalDeclarationStatementInfo localDeclarationInfo,
            int index,
            ExpressionStatementSyntax expressionStatement)
        {
            SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expressionStatement.Expression);

            if (!assignment.Success)
            {
                return;
            }

            if (assignment.Right.Kind() != SyntaxKind.IdentifierName)
            {
                return;
            }

            var identifierName = (IdentifierNameSyntax)assignment.Right;

            string name = localDeclarationInfo.IdentifierText;

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

            VariableDeclaratorSyntax declarator = localDeclarationInfo.Declarator;

            ISymbol localSymbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

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

            bool isReferenced = IsLocalVariableReferenced(localSymbol, name, assignment.Left, assignment.Left.Span, context.SemanticModel, context.CancellationToken);

            if (!isReferenced &&
                index < statements.Count - 2)
            {
                TextSpan span = TextSpan.FromBounds(statements[index + 2].SpanStart, statements.Last().Span.End);

                isReferenced = IsLocalVariableReferenced(localSymbol, name, localDeclarationInfo.Statement.Parent, span, context.SemanticModel, context.CancellationToken);
            }

            if (isReferenced)
            {
                return;
            }

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

            ReportDiagnostic(context, localDeclarationInfo, assignment.Right);
        }
        public static async Task ComputeRefactoringAsync(RefactoringContext context, VariableDeclarationSyntax variableDeclaration)
        {
            if (!(variableDeclaration.Parent is LocalDeclarationStatementSyntax localDeclaration))
            {
                return;
            }

            if (!CSharpFacts.CanHaveStatements(localDeclaration.Parent.Kind()))
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

            if (!localInfo.Success)
            {
                return;
            }

            if (!context.Span.IsEmptyAndContainedInSpan(localInfo.Identifier))
            {
                return;
            }

            ExpressionSyntax value = localInfo.Value;

            if (value == null)
            {
                return;
            }

            if (value.Kind() == SyntaxKind.DefaultExpression)
            {
                return;
            }

            if (value is LiteralExpressionSyntax)
            {
                return;
            }

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

            var typeSymbol = semanticModel.GetTypeSymbol(localInfo.Type, context.CancellationToken) as INamedTypeSymbol;

            if (typeSymbol?.Implements(SpecialType.System_IDisposable, allInterfaces: true) != true)
            {
                return;
            }

            context.RegisterRefactoring(
                $"Using '{localInfo.IdentifierText}'",
                cancellationToken => RefactorAsync(context.Document, localInfo, semanticModel, cancellationToken),
                RefactoringIdentifiers.WrapInUsingStatement);
        }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxList <StatementSyntax> statements,
            SingleLocalDeclarationStatementInfo localDeclarationInfo,
            int index,
            ExpressionStatementSyntax expressionStatement)
        {
            ExpressionSyntax expression = expressionStatement.Expression;

            if (expression?.IsKind(SyntaxKind.SimpleAssignmentExpression) == true)
            {
                var assignment = (AssignmentExpressionSyntax)expression;

                ExpressionSyntax left  = assignment.Left;
                ExpressionSyntax right = assignment.Right;

                if (left?.IsMissing == false &&
                    right?.IsKind(SyntaxKind.IdentifierName) == true)
                {
                    var identifierName = (IdentifierNameSyntax)right;

                    string name = localDeclarationInfo.IdentifierText;

                    if (string.Equals(name, identifierName.Identifier.ValueText, StringComparison.Ordinal))
                    {
                        VariableDeclaratorSyntax declarator = localDeclarationInfo.Declarator;

                        ISymbol localSymbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                        if (localSymbol?.IsErrorType() == false)
                        {
                            bool isReferenced = IsLocalVariableReferenced(localSymbol, name, left, left.Span, context.SemanticModel, context.CancellationToken);

                            if (!isReferenced &&
                                index < statements.Count - 2)
                            {
                                TextSpan span = TextSpan.FromBounds(statements[index + 2].SpanStart, statements.Last().Span.End);

                                isReferenced = IsLocalVariableReferenced(localSymbol, name, localDeclarationInfo.Statement.Parent, span, context.SemanticModel, context.CancellationToken);
                            }

                            if (!isReferenced &&
                                !expressionStatement.SpanOrLeadingTriviaContainsDirectives())
                            {
                                ReportDiagnostic(context, localDeclarationInfo, right);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxList <StatementSyntax> statements,
            SingleLocalDeclarationStatementInfo localDeclarationInfo,
            int index,
            LocalDeclarationStatementSyntax localDeclaration2)
        {
            ExpressionSyntax value2 = localDeclaration2
                                      .Declaration?
                                      .Variables
                                      .SingleOrDefault(shouldThrow: false)?
                                      .Initializer?
                                      .Value;

            if (value2?.Kind() != SyntaxKind.IdentifierName)
            {
                return;
            }

            var identifierName = (IdentifierNameSyntax)value2;

            string name = localDeclarationInfo.IdentifierText;

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

            bool isReferenced = false;

            if (index < statements.Count - 2)
            {
                TextSpan span = TextSpan.FromBounds(statements[index + 2].SpanStart, statements.Last().Span.End);

                isReferenced = IsLocalVariableReferenced(localDeclarationInfo.Declarator, name, localDeclarationInfo.Statement.Parent, span, context.SemanticModel, context.CancellationToken);
            }

            if (isReferenced)
            {
                return;
            }

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

            ReportDiagnostic(context, localDeclarationInfo, value2);
        }
Exemplo n.º 11
0
        private static void ReportDiagnostic(
            SyntaxNodeAnalysisContext context,
            SingleLocalDeclarationStatementInfo localDeclarationInfo,
            ExpressionSyntax expression)
        {
            context.ReportDiagnostic(DiagnosticDescriptors.InlineLocalVariable, localDeclarationInfo.Statement);

            foreach (SyntaxToken modifier in localDeclarationInfo.Modifiers)
            {
                context.ReportToken(DiagnosticDescriptors.InlineLocalVariableFadeOut, modifier);
            }

            context.ReportNode(DiagnosticDescriptors.InlineLocalVariableFadeOut, localDeclarationInfo.Type);
            context.ReportToken(DiagnosticDescriptors.InlineLocalVariableFadeOut, localDeclarationInfo.Identifier);
            context.ReportToken(DiagnosticDescriptors.InlineLocalVariableFadeOut, localDeclarationInfo.EqualsToken);
            context.ReportToken(DiagnosticDescriptors.InlineLocalVariableFadeOut, localDeclarationInfo.SemicolonToken);
            context.ReportNode(DiagnosticDescriptors.InlineLocalVariableFadeOut, expression);
        }
        internal static async Task ComputeRefactoringAsync(RefactoringContext context, VariableDeclarationSyntax variableDeclaration)
        {
            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(variableDeclaration);

            if (!context.Span.IsContainedInSpanOrBetweenSpans(localInfo.Identifier))
            {
                return;
            }

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

            if (!CanRefactor(localInfo, semanticModel, context.CancellationToken))
            {
                return;
            }

            RegisterRefactoring(context, IdentifierName(localInfo.Identifier), localInfo.Statement);
        }
        public static async Task ComputeRefactoringAsync(RefactoringContext context, ConditionalExpressionSyntax conditionalExpression)
        {
            ExpressionSyntax expression = conditionalExpression.WalkUpParentheses();

            SyntaxNode parent = expression.Parent;

            if (parent.IsKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement))
            {
                context.RegisterRefactoring(
                    Title,
                    cancellationToken => RefactorAsync(context.Document, (StatementSyntax)parent, conditionalExpression, cancellationToken));
            }
            else if (parent is AssignmentExpressionSyntax assignment)
            {
                if (assignment.Parent is ExpressionStatementSyntax expressionStatement)
                {
                    context.RegisterRefactoring(
                        Title,
                        cancellationToken => RefactorAsync(context.Document, expressionStatement, conditionalExpression, cancellationToken));
                }
            }
            else
            {
                SingleLocalDeclarationStatementInfo localDeclarationInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(expression);

                if (localDeclarationInfo.Success)
                {
                    TypeSyntax type = localDeclarationInfo.Type;

                    if (type != null)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        if (!type.IsVar ||
                            semanticModel.GetTypeSymbol(type, context.CancellationToken)?.SupportsExplicitDeclaration() == true)
                        {
                            context.RegisterRefactoring(
                                Title,
                                cancellationToken => RefactorAsync(context.Document, localDeclarationInfo.Statement, conditionalExpression, semanticModel, cancellationToken));
                        }
                    }
                }
            }
        }
        internal static async Task ComputeRefactoringAsync(RefactoringContext context, StatementListSelection selectedStatements)
        {
            if (selectedStatements.Count <= 1)
            {
                return;
            }

            StatementSyntax statement = selectedStatements.First();

            SyntaxKind kind = statement.Kind();

            if (kind == SyntaxKind.LocalDeclarationStatement)
            {
                var localDeclaration = (LocalDeclarationStatementSyntax)statement;

                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

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

                if (!CanRefactor(localInfo, semanticModel, context.CancellationToken))
                {
                    return;
                }

                RegisterRefactoring(context, IdentifierName(localInfo.Identifier), localDeclaration, selectedStatements.Count - 1);
            }
            else if (kind == SyntaxKind.ExpressionStatement)
            {
                var expressionStatement = (ExpressionStatementSyntax)statement;

                SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement);

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

                if (!CanRefactor(assignmentInfo, assignmentInfo.Left, semanticModel, context.CancellationToken))
                {
                    return;
                }

                RegisterRefactoring(context, assignmentInfo.Left, expressionStatement, selectedStatements.Count - 1);
            }
        }
Exemplo n.º 15
0
        public async Task ComputeRefactoringAsync(RefactoringContext context, StatementListSelection selectedStatements)
        {
            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(selectedStatements.FirstOrDefault() as LocalDeclarationStatementSyntax);

            if (!localInfo.Success)
            {
                return;
            }

            ExpressionSyntax value = localInfo.Value;

            if (value == null)
            {
                return;
            }

            if (value.Kind() == SyntaxKind.DefaultExpression)
            {
                return;
            }

            if (value is LiteralExpressionSyntax)
            {
                return;
            }

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

            var typeSymbol = semanticModel.GetTypeSymbol(localInfo.Type, context.CancellationToken) as INamedTypeSymbol;

            if (typeSymbol?.Implements(SpecialType.System_IDisposable, allInterfaces: true) != true)
            {
                return;
            }

            context.RegisterRefactoring(
                $"Using '{localInfo.IdentifierText}'",
                cancellationToken => RefactorAsync(context.Document, selectedStatements, cancellationToken),
                RefactoringIdentifiers.WrapInUsingStatement);
        }
        private static Task <Document> RefactorAsync(
            Document document,
            SingleLocalDeclarationStatementInfo localInfo,
            TypeSyntax type,
            CancellationToken cancellationToken)
        {
            LocalDeclarationStatementSyntax localStatement = localInfo.Statement;

            StatementsInfo statementsInfo = SyntaxInfo.StatementsInfo(localStatement);

            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();

            StatementsInfo 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);
        }
Exemplo n.º 18
0
        public static void ComputeRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo)
        {
            BinaryExpressionSyntax binaryExpression = concatenationInfo.BinaryExpression;

            if (binaryExpression.IsParentKind(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression))
            {
                var assignment = (AssignmentExpressionSyntax)binaryExpression.Parent;

                if (assignment.IsParentKind(SyntaxKind.ExpressionStatement) &&
                    assignment.Right == binaryExpression)
                {
                    RegisterRefactoring(context, concatenationInfo, (StatementSyntax)assignment.Parent);
                }
            }
            else
            {
                SingleLocalDeclarationStatementInfo info = SyntaxInfo.SingleLocalDeclarationStatementInfo(binaryExpression);

                if (info.Success)
                {
                    RegisterRefactoring(context, concatenationInfo, info.Statement);
                }
            }
        }
        public static void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context)
        {
            var localDeclarationStatement = (LocalDeclarationStatementSyntax)context.Node;

            if (localDeclarationStatement.ContainsDiagnostics)
            {
                return;
            }

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

            SingleLocalDeclarationStatementInfo localDeclarationInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclarationStatement);

            if (!localDeclarationInfo.Success)
            {
                return;
            }

            ExpressionSyntax value = localDeclarationInfo.Value;

            if (value == null)
            {
                return;
            }

            SyntaxList <StatementSyntax> statements = SyntaxInfo.StatementListInfo(localDeclarationStatement).Statements;

            if (!statements.Any())
            {
                return;
            }

            int index = statements.IndexOf(localDeclarationStatement);

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

            StatementSyntax nextStatement = statements[index + 1];

            if (nextStatement.ContainsDiagnostics)
            {
                return;
            }

            switch (nextStatement.Kind())
            {
            case SyntaxKind.ExpressionStatement:
            {
                Analyze(context, statements, localDeclarationInfo, index, (ExpressionStatementSyntax)nextStatement);
                break;
            }

            case SyntaxKind.LocalDeclarationStatement:
            {
                Analyze(context, statements, localDeclarationInfo, index, (LocalDeclarationStatementSyntax)nextStatement);
                break;
            }

            case SyntaxKind.ReturnStatement:
            {
                var returnStatement = (ReturnStatementSyntax)nextStatement;

                if (!returnStatement.SpanOrLeadingTriviaContainsDirectives())
                {
                    ExpressionSyntax expression = returnStatement.Expression;

                    if (expression?.Kind() == SyntaxKind.IdentifierName)
                    {
                        var identifierName = (IdentifierNameSyntax)expression;

                        if (string.Equals(localDeclarationInfo.IdentifierText, identifierName.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            ReportDiagnostic(context, localDeclarationInfo, expression);
                        }
                    }
                }

                break;
            }

            case SyntaxKind.YieldReturnStatement:
            {
                var yieldStatement = (YieldStatementSyntax)nextStatement;

                if (index == statements.Count - 2 &&
                    !yieldStatement.SpanOrLeadingTriviaContainsDirectives())
                {
                    ExpressionSyntax expression = yieldStatement.Expression;

                    if (expression?.Kind() == SyntaxKind.IdentifierName)
                    {
                        var identifierName = (IdentifierNameSyntax)expression;

                        if (string.Equals(localDeclarationInfo.IdentifierText, identifierName.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            ReportDiagnostic(context, localDeclarationInfo, expression);
                        }
                    }
                }

                break;
            }

            case SyntaxKind.ForEachStatement:
            {
                if (value.WalkDownParentheses().IsKind(SyntaxKind.AwaitExpression))
                {
                    return;
                }

                if (!value.IsSingleLine())
                {
                    return;
                }

                if (value.IsKind(SyntaxKind.ArrayInitializerExpression))
                {
                    return;
                }

                var forEachStatement = (ForEachStatementSyntax)nextStatement;

                ISymbol localSymbol = GetLocalSymbol(localDeclarationInfo, forEachStatement.Expression, context.SemanticModel, context.CancellationToken);

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

                ContainsLocalOrParameterReferenceWalker walker = ContainsLocalOrParameterReferenceWalker.GetInstance(localSymbol, context.SemanticModel, context.CancellationToken);

                walker.Visit(forEachStatement.Statement);

                if (!walker.Result &&
                    index < statements.Count - 2)
                {
                    walker.VisitList(statements, index + 2);
                }

                if (ContainsLocalOrParameterReferenceWalker.GetResultAndFree(walker))
                {
                    return;
                }

                ReportDiagnostic(context, localDeclarationInfo, forEachStatement.Expression);

                break;
            }

            case SyntaxKind.SwitchStatement:
            {
                if (value.WalkDownParentheses().IsKind(SyntaxKind.AwaitExpression))
                {
                    return;
                }

                if (!value.IsSingleLine())
                {
                    return;
                }

                var switchStatement = (SwitchStatementSyntax)nextStatement;

                ISymbol localSymbol = GetLocalSymbol(localDeclarationInfo, switchStatement.Expression, context.SemanticModel, context.CancellationToken);

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

                ContainsLocalOrParameterReferenceWalker walker = ContainsLocalOrParameterReferenceWalker.GetInstance(localSymbol, context.SemanticModel, context.CancellationToken);

                walker.VisitList(switchStatement.Sections);

                if (!walker.Result &&
                    index < statements.Count - 2)
                {
                    walker.VisitList(statements, index + 2);
                }

                if (ContainsLocalOrParameterReferenceWalker.GetResultAndFree(walker))
                {
                    return;
                }

                ReportDiagnostic(context, localDeclarationInfo, switchStatement.Expression);

                break;
            }
            }
        }
        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 <Document> UsePatternMatchingAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            IsKindExpressionInfo isKindExpression = IsKindExpressionInfo.Create(ifStatement.Condition, semanticModel, cancellationToken: cancellationToken);

            switch (isKindExpression.Style)
            {
            case IsKindExpressionStyle.IsKind:
            case IsKindExpressionStyle.IsKindConditional:
            case IsKindExpressionStyle.Kind:
            case IsKindExpressionStyle.KindConditional:
            {
                var block = (BlockSyntax)ifStatement.Statement;

                IsPatternExpressionSyntax isPatternExpression = CreateIsPatternExpression(block.Statements[0]);

                BlockSyntax newBlock = block.WithStatements(block.Statements.RemoveAt(0));

                IfStatementSyntax newIfStatement = ifStatement.Update(
                    ifStatement.IfKeyword,
                    ifStatement.OpenParenToken,
                    isPatternExpression,
                    ifStatement.CloseParenToken,
                    newBlock,
                    ifStatement.Else);

                newIfStatement = newIfStatement.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false));
            }

            case IsKindExpressionStyle.NotIsKind:
            case IsKindExpressionStyle.NotIsKindConditional:
            case IsKindExpressionStyle.NotKind:
            case IsKindExpressionStyle.NotKindConditional:
            {
                StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

                SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

                int index = statements.IndexOf(ifStatement);

                IsPatternExpressionSyntax isPatternExpression = CreateIsPatternExpression(statements[index + 1]);

                IfStatementSyntax newIfStatement = ifStatement.WithCondition(LogicalNotExpression(isPatternExpression.Parenthesize()).WithTriviaFrom(ifStatement.Condition));

                SyntaxList <StatementSyntax> newStatements = statements
                                                             .ReplaceAt(index, newIfStatement)
                                                             .RemoveAt(index + 1);

                return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));
            }

            default:
            {
                throw new InvalidOperationException();
            }
            }

            IsPatternExpressionSyntax CreateIsPatternExpression(StatementSyntax statement)
            {
                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement);

                var castExpression = (CastExpressionSyntax)localInfo.Value;

                return(IsPatternExpression(
                           isKindExpression.Expression,
                           DeclarationPattern(castExpression.Type, SingleVariableDesignation(localInfo.Identifier))));
            }
        }
Exemplo n.º 22
0
        public static void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context)
        {
            var localDeclaration = (LocalDeclarationStatementSyntax)context.Node;

            if (localDeclaration.ContainsDiagnostics)
            {
                return;
            }

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

            if (localDeclaration.IsConst)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

            if (!localInfo.Success)
            {
                return;
            }

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(localDeclaration.NextStatementOrDefault());

            if (!assignmentInfo.Success)
            {
                return;
            }

            if (assignmentInfo.Statement.ContainsDiagnostics)
            {
                return;
            }

            if (assignmentInfo.Statement.SpanOrLeadingTriviaContainsDirectives())
            {
                return;
            }

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

            string name = identifierName.Identifier.ValueText;

            if (!string.Equals(localInfo.IdentifierText, name, StringComparison.Ordinal))
            {
                return;
            }

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

            var localSymbol = semanticModel.GetSymbol(identifierName, cancellationToken) as ILocalSymbol;

            if (localSymbol == null)
            {
                return;
            }

            if (!localSymbol.Equals(semanticModel.GetDeclaredSymbol(localInfo.Declarator, cancellationToken)))
            {
                return;
            }

            EqualsValueClauseSyntax initializer = localInfo.Initializer;
            ExpressionSyntax        value       = initializer?.Value;

            if (value != null)
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(localInfo.Type, cancellationToken);

                if (typeSymbol == null)
                {
                    return;
                }

                if (!semanticModel.IsDefaultValue(typeSymbol, value, cancellationToken))
                {
                    return;
                }

                if (IsReferenced(localSymbol, assignmentInfo.Right, semanticModel, cancellationToken))
                {
                    return;
                }
            }

            context.ReportDiagnostic(DiagnosticDescriptors.MergeLocalDeclarationWithAssignment, localInfo.Identifier);

            if (value != null)
            {
                context.ReportNode(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, initializer);
                context.ReportToken(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, assignmentInfo.OperatorToken);
            }

            context.ReportToken(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, localDeclaration.SemicolonToken);
            context.ReportNode(DiagnosticDescriptors.MergeLocalDeclarationWithAssignmentFadeOut, assignmentInfo.Left);
        }
        public static void AnalyzeAsExpression(SyntaxNodeAnalysisContext context)
        {
            var asExpression = (BinaryExpressionSyntax)context.Node;

            AsExpressionInfo asExpressionInfo = SyntaxInfo.AsExpressionInfo(asExpression);

            if (!asExpressionInfo.Success)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(asExpression);

            if (!localInfo.Success)
            {
                return;
            }

            if (localInfo.Statement.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

            if (!(localInfo.Statement.NextStatement() is IfStatementSyntax ifStatement))
            {
                return;
            }

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

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

            StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault();

            if (statement == null)
            {
                return;
            }

            if (!CSharpFacts.IsJumpStatement(statement.Kind()))
            {
                return;
            }

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull);

            if (!nullCheck.Success)
            {
                return;
            }

            if (!string.Equals(localInfo.IdentifierText, (nullCheck.Expression as IdentifierNameSyntax)?.Identifier.ValueText, StringComparison.Ordinal))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UsePatternMatchingInsteadOfAsAndNullCheck, localInfo.Statement);
        }
        private static void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context)
        {
            var localDeclaration = (LocalDeclarationStatementSyntax)context.Node;

            if (localDeclaration.ContainsDiagnostics)
            {
                return;
            }

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

            if (localDeclaration.IsConst)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclaration);

            if (!localInfo.Success)
            {
                return;
            }

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(localDeclaration.NextStatement());

            if (!assignmentInfo.Success)
            {
                return;
            }

            if (assignmentInfo.Statement.ContainsDiagnostics)
            {
                return;
            }

            if (assignmentInfo.Statement.SpanOrLeadingTriviaContainsDirectives())
            {
                return;
            }

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

            string name = identifierName.Identifier.ValueText;

            if (!string.Equals(localInfo.IdentifierText, name, StringComparison.Ordinal))
            {
                return;
            }

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

            if (semanticModel.GetSymbol(identifierName, cancellationToken) is not ILocalSymbol localSymbol)
            {
                return;
            }

            if (!SymbolEqualityComparer.Default.Equals(localSymbol, semanticModel.GetDeclaredSymbol(localInfo.Declarator, cancellationToken)))
            {
                return;
            }

            ExpressionSyntax value = localInfo.Value;

            if (value != null)
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(localInfo.Type, cancellationToken);

                if (typeSymbol == null)
                {
                    return;
                }

                if (!semanticModel.IsDefaultValue(typeSymbol, value, cancellationToken))
                {
                    return;
                }

                if (IsReferenced(localSymbol, assignmentInfo.Right, semanticModel, cancellationToken))
                {
                    return;
                }
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveRedundantAssignment, localInfo.Identifier);

            if (value != null)
            {
                DiagnosticHelpers.ReportNode(context, DiagnosticRules.RemoveRedundantAssignmentFadeOut, localInfo.Initializer);
                DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantAssignmentFadeOut, assignmentInfo.OperatorToken);
            }

            DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantAssignmentFadeOut, localDeclaration.SemicolonToken);
            DiagnosticHelpers.ReportNode(context, DiagnosticRules.RemoveRedundantAssignmentFadeOut, assignmentInfo.Left);
        }
Exemplo n.º 25
0
        private static void AnalyzeAsExpression(SyntaxNodeAnalysisContext context)
        {
            var asExpression = (BinaryExpressionSyntax)context.Node;

            AsExpressionInfo asExpressionInfo = SyntaxInfo.AsExpressionInfo(asExpression);

            if (!asExpressionInfo.Success)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(asExpression);

            if (!localInfo.Success)
            {
                return;
            }

            if (localInfo.Statement.SpanOrTrailingTriviaContainsDirectives())
            {
                return;
            }

            if (!(localInfo.Statement.NextStatement() is IfStatementSyntax ifStatement))
            {
                return;
            }

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

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

            StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault();

            if (statement == null)
            {
                return;
            }

            if (!CSharpFacts.IsJumpStatement(statement.Kind()))
            {
                return;
            }

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull);

            if (!nullCheck.Success)
            {
                return;
            }

            if (!string.Equals(localInfo.IdentifierText, (nullCheck.Expression as IdentifierNameSyntax)?.Identifier.ValueText, StringComparison.Ordinal))
            {
                return;
            }

            if (!localInfo.Type.IsVar)
            {
                SemanticModel     semanticModel     = context.SemanticModel;
                CancellationToken cancellationToken = context.CancellationToken;

                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(asExpressionInfo.Type, cancellationToken);

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

                if (!SymbolEqualityComparer.Default.Equals(semanticModel.GetTypeSymbol(localInfo.Type, cancellationToken), typeSymbol))
                {
                    return;
                }
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UsePatternMatchingInsteadOfAsAndNullCheck, localInfo.Statement);
        }
Exemplo n.º 26
0
        public static void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context)
        {
            var localDeclarationStatement = (LocalDeclarationStatementSyntax)context.Node;

            if (localDeclarationStatement.ContainsDiagnostics)
            {
                return;
            }

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

            SingleLocalDeclarationStatementInfo localDeclarationInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(localDeclarationStatement);

            if (!localDeclarationInfo.Success)
            {
                return;
            }

            ExpressionSyntax value = localDeclarationInfo.Value;

            if (value == null)
            {
                return;
            }

            SyntaxList <StatementSyntax> statements = SyntaxInfo.StatementListInfo(localDeclarationStatement).Statements;

            if (!statements.Any())
            {
                return;
            }

            int index = statements.IndexOf(localDeclarationStatement);

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

            StatementSyntax nextStatement = statements[index + 1];

            if (nextStatement.ContainsDiagnostics)
            {
                return;
            }

            switch (nextStatement.Kind())
            {
            case SyntaxKind.ExpressionStatement:
            {
                Analyze(context, statements, localDeclarationInfo, index, (ExpressionStatementSyntax)nextStatement);
                break;
            }

            case SyntaxKind.LocalDeclarationStatement:
            {
                Analyze(context, statements, localDeclarationInfo, index, (LocalDeclarationStatementSyntax)nextStatement);
                break;
            }

            case SyntaxKind.ReturnStatement:
            {
                var returnStatement = (ReturnStatementSyntax)nextStatement;

                if (!returnStatement.SpanOrLeadingTriviaContainsDirectives())
                {
                    ExpressionSyntax expression = returnStatement.Expression;

                    if (expression?.Kind() == SyntaxKind.IdentifierName)
                    {
                        var identifierName = (IdentifierNameSyntax)expression;

                        if (string.Equals(localDeclarationInfo.IdentifierText, identifierName.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            ReportDiagnostic(context, localDeclarationInfo, expression);
                        }
                    }
                }

                break;
            }

            case SyntaxKind.ForEachStatement:
            {
                if (value.IsSingleLine() &&
                    !value.IsKind(SyntaxKind.ArrayInitializerExpression))
                {
                    var forEachStatement = (ForEachStatementSyntax)nextStatement;
                    Analyze(context, statements, localDeclarationInfo, forEachStatement.Expression);
                }

                break;
            }

            case SyntaxKind.SwitchStatement:
            {
                if (value.IsSingleLine())
                {
                    var switchStatement = (SwitchStatementSyntax)nextStatement;
                    Analyze(context, statements, localDeclarationInfo, switchStatement.Expression);
                }

                break;
            }
            }
        }
        private static void AnalyzeWhileStatement(SyntaxNodeAnalysisContext context)
        {
            var whileStatement = (WhileStatementSyntax)context.Node;

            ExpressionSyntax condition = whileStatement.Condition;

            if (condition.IsMissing)
            {
                return;
            }

            if (!condition.IsSingleLine())
            {
                return;
            }

            StatementSyntax statement = whileStatement.Statement;

            if (!(statement is BlockSyntax block))
            {
                return;
            }

            SyntaxList <StatementSyntax> innerStatements = block.Statements;

            if (innerStatements.Count <= 1)
            {
                return;
            }

            ExpressionSyntax incrementedExpression = GetIncrementedExpression(innerStatements.Last());

            if (!incrementedExpression.IsKind(SyntaxKind.IdentifierName))
            {
                return;
            }

            SyntaxList <StatementSyntax> outerStatements = SyntaxInfo.StatementListInfo(whileStatement).Statements;

            int index = outerStatements.IndexOf(whileStatement);

            if (index <= 0)
            {
                return;
            }

            SingleLocalDeclarationStatementInfo localInfo = GetLocalInfo(outerStatements[index - 1]);

            if (!localInfo.Success)
            {
                return;
            }

            if (index > 1)
            {
                SingleLocalDeclarationStatementInfo localInfo2 = GetLocalInfo(outerStatements[index - 2]);

                if (localInfo2.Success)
                {
                    ExpressionSyntax incrementedExpression2 = GetIncrementedExpression(innerStatements[innerStatements.Count - 2]);

                    if (incrementedExpression2 is IdentifierNameSyntax identifierName2 &&
                        string.Equals(localInfo2.Identifier.ValueText, identifierName2.Identifier.ValueText, StringComparison.Ordinal))
                    {
                        return;
                    }
                }
            }

            var identifierName = (IdentifierNameSyntax)incrementedExpression;

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

            if (ContainsContinueStatement())
            {
                return;
            }

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

            ISymbol symbol = semanticModel.GetDeclaredSymbol(localInfo.Declarator, cancellationToken);

            if (symbol?.Kind != SymbolKind.Local)
            {
                return;
            }

            if (IsLocalVariableReferencedAfterWhileStatement())
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseForStatementInsteadOfWhileStatement, whileStatement.WhileKeyword);

            bool ContainsContinueStatement()
            {
                ContainsContinueStatementWalker walker = ContainsContinueStatementWalker.GetInstance();

                walker.ContainsContinueStatement = false;

                bool containsContinueStatement = false;

                foreach (StatementSyntax innerStatement in innerStatements)
                {
                    walker.Visit(innerStatement);

                    if (walker.ContainsContinueStatement)
                    {
                        containsContinueStatement = true;
                        break;
                    }
                }

                ContainsContinueStatementWalker.Free(walker);

                return(containsContinueStatement);
            }

            bool IsLocalVariableReferencedAfterWhileStatement()
            {
                ContainsLocalOrParameterReferenceWalker walker = ContainsLocalOrParameterReferenceWalker.GetInstance(symbol, semanticModel, cancellationToken);

                walker.VisitList(outerStatements, index + 1);

                return(ContainsLocalOrParameterReferenceWalker.GetResultAndFree(walker));
            }
        }
Exemplo n.º 28
0
        public static async Task ComputeRefactoringAsync(RefactoringContext context, ConditionalExpressionSyntax conditionalExpression)
        {
            ExpressionSyntax expression = conditionalExpression.WalkUpParentheses();

            SyntaxNode parent = expression.Parent;

            if (parent.IsKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement))
            {
                var statement = (StatementSyntax)parent;

                RegisterRefactoring(context, conditionalExpression, statement);

                if (IsRecursive())
                {
                    RegisterRefactoring(context, conditionalExpression, statement, recursive: true);
                }
            }
            else if (parent is AssignmentExpressionSyntax assignment)
            {
                if (assignment.Parent is ExpressionStatementSyntax expressionStatement)
                {
                    RegisterRefactoring(context, conditionalExpression, expressionStatement);

                    if (IsRecursive())
                    {
                        RegisterRefactoring(context, conditionalExpression, expressionStatement, recursive: true);
                    }
                }
            }
            else
            {
                SingleLocalDeclarationStatementInfo localDeclarationInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(expression);

                if (localDeclarationInfo.Success)
                {
                    TypeSyntax type = localDeclarationInfo.Type;

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

                    if (!type.IsVar ||
                        semanticModel.GetTypeSymbol(type, context.CancellationToken)?.SupportsExplicitDeclaration() == true)
                    {
                        LocalDeclarationStatementSyntax statement = localDeclarationInfo.Statement;

                        RegisterRefactoring(context, conditionalExpression, statement, semanticModel);

                        if (IsRecursive())
                        {
                            RegisterRefactoring(context, conditionalExpression, statement, semanticModel, recursive: true);
                        }
                    }
                }
            }

            bool IsRecursive()
            {
                return(conditionalExpression
                       .WhenFalse
                       .WalkDownParentheses()
                       .IsKind(SyntaxKind.ConditionalExpression));
            }
        }
        private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

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

            IsKindExpressionInfo isKindExpression = IsKindExpressionInfo.Create(ifStatement.Condition, semanticModel, cancellationToken: cancellationToken);

            if (!isKindExpression.Success)
            {
                return;
            }

            Optional <object> optionalConstantValue = semanticModel.GetConstantValue(isKindExpression.KindExpression, cancellationToken);

            if (!optionalConstantValue.HasValue)
            {
                return;
            }

            if (!(optionalConstantValue.Value is ushort value))
            {
                return;
            }

            if (!_syntaxKindValuesToNames.TryGetValue(value, out string name))
            {
                return;
            }

            if (!_syntaxKindNames.Contains(name))
            {
                return;
            }

            switch (isKindExpression.Style)
            {
            case IsKindExpressionStyle.IsKind:
            case IsKindExpressionStyle.IsKindConditional:
            case IsKindExpressionStyle.Kind:
            case IsKindExpressionStyle.KindConditional:
            {
                if (!(ifStatement.Statement is BlockSyntax block))
                {
                    return;
                }

                Analyze(block.Statements.FirstOrDefault());
                break;
            }

            case IsKindExpressionStyle.NotIsKind:
            case IsKindExpressionStyle.NotIsKindConditional:
            case IsKindExpressionStyle.NotKind:
            case IsKindExpressionStyle.NotKindConditional:
            {
                if (ifStatement.Else != null)
                {
                    return;
                }

                StatementSyntax statement = ifStatement.Statement.SingleNonBlockStatementOrDefault();

                if (statement == null)
                {
                    return;
                }

                if (!CSharpFacts.IsJumpStatement(statement.Kind()))
                {
                    return;
                }

                Analyze(ifStatement.NextStatement());
                break;
            }
            }

            void Analyze(StatementSyntax statement)
            {
                SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo(statement);

                if (!localInfo.Success)
                {
                    return;
                }

                if (!(localInfo.Value is CastExpressionSyntax castExpression))
                {
                    return;
                }

                if (!IsFixableSyntaxSymbol(castExpression.Type, name, semanticModel, cancellationToken))
                {
                    return;
                }

                if (!CSharpFactory.AreEquivalent(isKindExpression.Expression, castExpression.Expression))
                {
                    return;
                }

                context.ReportDiagnostic(DiagnosticDescriptors.UsePatternMatching, ifStatement.IfKeyword);
            }
        }
        private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context)
        {
            var switchStatement = (SwitchStatementSyntax)context.Node;

            SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections;

            if (!sections.Any())
            {
                return;
            }

            ExpressionSyntax switchExpression = switchStatement.Expression;

            SingleLocalDeclarationStatementInfo localInfo = default;

            string name = GetName();

            if (name == null)
            {
                return;
            }

            ITypeSymbol kindSymbol = context.SemanticModel.GetTypeSymbol(switchExpression, context.CancellationToken);

            if (kindSymbol?.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_CSharp_SyntaxKind) != true)
            {
                return;
            }

            foreach (SwitchSectionSyntax section in sections)
            {
                SwitchLabelSyntax label = section.Labels.SingleOrDefault(shouldThrow: false);

                if (label == null)
                {
                    return;
                }

                SyntaxKind labelKind = label.Kind();

                if (labelKind == SyntaxKind.DefaultSwitchLabel)
                {
                    continue;
                }

                if (labelKind != SyntaxKind.CaseSwitchLabel)
                {
                    Debug.Assert(labelKind == SyntaxKind.CasePatternSwitchLabel, labelKind.ToString());
                    return;
                }

                var caseLabel = (CaseSwitchLabelSyntax)label;

                ExpressionSyntax value = caseLabel.Value;

                if (!value.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    return;
                }

                var memberAccess = (MemberAccessExpressionSyntax)value;

                if (memberAccess.Name is not IdentifierNameSyntax identifierName)
                {
                    return;
                }

                string kindName = identifierName.Identifier.ValueText;

                if (!_syntaxKindNames.Contains(kindName))
                {
                    return;
                }

                SyntaxList <StatementSyntax> statements = section.Statements;

                StatementSyntax statement = statements.FirstOrDefault();

                if (statement == null)
                {
                    return;
                }

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

                if (!statement.IsKind(SyntaxKind.LocalDeclarationStatement))
                {
                    return;
                }

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

                if (!localStatement.Success)
                {
                    return;
                }

                if (localStatement.Value is not CastExpressionSyntax castExpression)
                {
                    return;
                }

                if (castExpression.Expression is not IdentifierNameSyntax localName)
                {
                    return;
                }

                if (name != localName.Identifier.ValueText)
                {
                    return;
                }

                if (!IsFixableSyntaxSymbol(castExpression.Type, kindName, context.SemanticModel, context.CancellationToken))
                {
                    return;
                }
            }

            if (localInfo.Success &&
                IsLocalVariableReferenced(context, localInfo, switchStatement))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UsePatternMatching, switchStatement.SwitchKeyword);

            string GetName()
            {
                switch (switchExpression.Kind())
                {
                case SyntaxKind.IdentifierName:
                {
                    StatementSyntax previousStatement = switchStatement.PreviousStatement();

                    if (!previousStatement.IsKind(SyntaxKind.LocalDeclarationStatement))
                    {
                        return(null);
                    }

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

                    if (!localInfo.Success)
                    {
                        return(null);
                    }

                    if (localInfo.IdentifierText != ((IdentifierNameSyntax)switchExpression).Identifier.ValueText)
                    {
                        return(null);
                    }

                    if (!localInfo.Value.IsKind(SyntaxKind.InvocationExpression))
                    {
                        return(null);
                    }

                    return(GetName2((InvocationExpressionSyntax)localInfo.Value));
                }

                case SyntaxKind.InvocationExpression:
                {
                    return(GetName2((InvocationExpressionSyntax)switchExpression));
                }

                default:
                {
                    return(null);
                }
                }
            }