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);
        }
示例#2
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);
        }
示例#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));
        }
        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);
        }
        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);
            }
        }
示例#8
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);
        }
示例#9
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);
                }
            }
        }
        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);
                }
                }
            }
        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);
        }
示例#13
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);
        }
示例#14
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 SingleLocalDeclarationStatementInfo GetLocalInfo(StatementSyntax statement)
 {
     return((statement.IsKind(SyntaxKind.LocalDeclarationStatement))
         ? SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement)
         : default);
        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 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 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))));
            }
        }
示例#19
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));
            }
        }
        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;
            }
            }
        }
示例#21
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);
        }