public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddComparisonWithBooleanLiteral) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.CreateSingletonArray) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseUncheckedExpression) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseCoalesceExpression) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionThatIsAlwaysEqualToTrueOrFalse) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceLocalVariable) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceField) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseYieldReturnInsteadOfReturn) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddArgumentList))
            {
                return;
            }

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

            if (!TryFindNode(root, context.Span, out ExpressionSyntax expression))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertTypeExplicitConversionExists:
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

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

                    ITypeSymbol type          = typeInfo.Type;
                    ITypeSymbol convertedType = typeInfo.ConvertedType;

                    if ((type is INamedTypeSymbol namedType) &&
                        namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T)
                    {
                        if (convertedType?.IsBoolean() == true ||
                            AddComparisonWithBooleanLiteralRefactoring.IsCondition(expression))
                        {
                            if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddComparisonWithBooleanLiteral))
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    AddComparisonWithBooleanLiteralRefactoring.GetTitle(expression),
                                    cancellationToken => AddComparisonWithBooleanLiteralRefactoring.RefactorAsync(context.Document, expression, cancellationToken),
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddComparisonWithBooleanLiteral));

                                context.RegisterCodeFix(codeAction, diagnostic);
                            }
                        }
                        else if (namedType.TypeArguments[0].Equals(convertedType))
                        {
                            if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseCoalesceExpression))
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Use coalesce expression",
                                    cancellationToken =>
                                    {
                                        ExpressionSyntax defaultValue = convertedType.ToDefaultValueSyntax(semanticModel, expression.SpanStart);

                                        ExpressionSyntax newNode = CoalesceExpression(expression.WithoutTrivia(), defaultValue)
                                                                   .WithTriviaFrom(expression)
                                                                   .Parenthesize()
                                                                   .WithFormatterAnnotation();

                                        return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken));
                                    },
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseCoalesceExpression));

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

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) &&
                        expression.IsParentKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement))
                    {
                        ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddCastExpression))
                    {
                        CodeFixRegistrator.AddCastExpression(context, diagnostic, expression, convertedType, semanticModel);
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.CreateSingletonArray) &&
                        type?.IsErrorType() == false &&
                        !type.Equals(convertedType) &&
                        (convertedType is IArrayTypeSymbol arrayType) &&
                        semanticModel.IsImplicitConversion(expression, arrayType.ElementType))
                    {
                        CodeAction codeAction = CodeAction.Create(
                            "Create singleton array",
                            cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken),
                            GetEquivalenceKey(diagnostic, CodeFixIdentifiers.CreateSingletonArray));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ConstantValueCannotBeConverted:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseUncheckedExpression))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Use 'unchecked'",
                        cancellationToken =>
                        {
                            CheckedExpressionSyntax newNode = CSharpFactory.UncheckedExpression(expression.WithoutTrivia());

                            newNode = newNode.WithTriviaFrom(expression);

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

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

                case CompilerDiagnosticIdentifiers.ExpressionBeingAssignedMustBeConstant:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstModifier))
                    {
                        break;
                    }

                    LocalDeclarationStatementSyntax localDeclarationStatement = GetLocalDeclarationStatement(expression);

                    if (localDeclarationStatement == null)
                    {
                        break;
                    }

                    SyntaxTokenList modifiers = localDeclarationStatement.Modifiers;

                    if (!modifiers.Contains(SyntaxKind.ConstKeyword))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, localDeclarationStatement, SyntaxKind.ConstKeyword);

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeBecauseItIsNonNullableValueType:
                case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeParameterBecauseItCouldBeNonNullableValueType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue))
                    {
                        break;
                    }

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

                    CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, expression, semanticModel);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ResultOfExpressionIsAlwaysConstantSinceValueIsNeverEqualToNull:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionThatIsAlwaysEqualToTrueOrFalse))
                    {
                        break;
                    }

                    NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(expression, allowedKinds: NullCheckKind.ComparisonToNull);

                    if (!nullCheck.Success)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove condition",
                        cancellationToken =>
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            SyntaxNode newRoot = RemoveHelper.RemoveCondition(root, expression, nullCheck.Kind == NullCheckKind.NotEqualsToNull);

                            return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot)));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    break;
                }

                case CompilerDiagnosticIdentifiers.OnlyAssignmentCallIncrementDecrementAndNewObjectExpressionsCanBeUsedAsStatement:
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    if (expression.Parent is ArrowExpressionClauseSyntax arrowExpresssionClause)
                    {
                        if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression))
                        {
                            break;
                        }

                        ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel);
                    }
                    else if (expression.Parent is ExpressionStatementSyntax expressionStatement)
                    {
                        if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddArgumentList) &&
                            expression.IsKind(
                                SyntaxKind.IdentifierName,
                                SyntaxKind.SimpleMemberAccessExpression))
                        {
                            SyntaxNode invocationExpression = SyntaxFactory.InvocationExpression(expression);

                            if (semanticModel.GetSpeculativeMethodSymbol(expression.SpanStart, invocationExpression) != null)
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Add argument list",
                                    cancellationToken => context.Document.ReplaceNodeAsync(expression, invocationExpression, cancellationToken),
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddArgumentList));

                                context.RegisterCodeFix(codeAction, diagnostic);
                            }
                        }

                        if (Settings.IsAnyCodeFixEnabled(
                                CodeFixIdentifiers.IntroduceLocalVariable,
                                CodeFixIdentifiers.IntroduceField))
                        {
                            if (semanticModel.GetSymbol(expression, context.CancellationToken)?.IsErrorType() != false)
                            {
                                break;
                            }

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

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

                            if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceLocalVariable) &&
                                !expressionStatement.IsEmbedded())
                            {
                                bool addAwait = typeSymbol.IsConstructedFromTaskOfT(semanticModel) &&
                                                semanticModel.GetEnclosingSymbol(expressionStatement.SpanStart, context.CancellationToken).IsAsyncMethod();

                                CodeAction codeAction = CodeAction.Create(
                                    IntroduceLocalVariableRefactoring.GetTitle(expression),
                                    cancellationToken => IntroduceLocalVariableRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, addAwait, semanticModel, cancellationToken),
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceLocalVariable));

                                context.RegisterCodeFix(codeAction, diagnostic);
                            }

                            if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceField))
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    $"Introduce field for '{expression}'",
                                    cancellationToken => IntroduceFieldRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, semanticModel, cancellationToken),
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceField));

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

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertType:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) &&
                        expression.IsParentKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel);
                        break;
                    }

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral) &&
                        expression?.IsKind(SyntaxKind.StringLiteralExpression) == true)
                    {
                        var literalExpression = (LiteralExpressionSyntax)expression;

                        if (literalExpression.Token.ValueText.Length == 1)
                        {
                            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                            if (semanticModel.GetTypeInfo(expression, context.CancellationToken).ConvertedType?.IsChar() == true)
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Replace string literal with character literal",
                                    cancellationToken => ReplaceStringLiteralWithCharacterLiteralRefactoring.RefactorAsync(context.Document, literalExpression, cancellationToken),
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral));

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

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseYieldReturnInsteadOfReturn) &&
                        expression.IsParentKind(SyntaxKind.ReturnStatement))
                    {
                        var returnStatement = (ReturnStatementSyntax)expression.Parent;

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

                        ISymbol containingSymbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken);

                        if (containingSymbol?.IsKind(SymbolKind.Method) == true &&
                            ((IMethodSymbol)containingSymbol).ReturnType?.IsIEnumerableOrConstructedFromIEnumerableOfT() == true)
                        {
                            CodeAction codeAction = CodeAction.Create(
                                "Use yield return instead of return",
                                cancellationToken => UseYieldReturnInsteadOfReturnRefactoring.RefactorAsync(context.Document, returnStatement, SyntaxKind.YieldReturnStatement, semanticModel, cancellationToken),
                                GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseYieldReturnInsteadOfReturn));

                            context.RegisterCodeFix(codeAction, diagnostic);
                        }
                    }

                    break;
                }
                }
            }
        }
        public static void AnalyzeUsingStatement(SyntaxNodeAnalysisContext context)
        {
            var usingStatement = (UsingStatementSyntax)context.Node;

            VariableDeclaratorSyntax declarator = usingStatement.Declaration?.Variables.SingleOrDefault(shouldThrow: false);

            if (declarator == null)
            {
                return;
            }

            if (!(usingStatement.Statement?.SingleNonBlockStatementOrDefault() is WhileStatementSyntax whileStatement))
            {
                return;
            }

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(whileStatement.Condition);

            if (!invocationInfo.Success)
            {
                return;
            }

            if (invocationInfo.Arguments.Any())
            {
                return;
            }

            if (!string.Equals(invocationInfo.NameText, WellKnownMemberNames.MoveNextMethodName, StringComparison.Ordinal))
            {
                return;
            }

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

            SimpleMemberInvocationExpressionInfo invocationInfo2 = SyntaxInfo.SimpleMemberInvocationExpressionInfo(declarator.Initializer.Value);

            if (!invocationInfo2.Success)
            {
                return;
            }

            if (invocationInfo2.Arguments.Any())
            {
                return;
            }

            if (!string.Equals(invocationInfo2.NameText, WellKnownMemberNames.GetEnumeratorMethodName, StringComparison.Ordinal))
            {
                return;
            }

            UnnecessaryUsageOfEnumeratorWalker walker = UnnecessaryUsageOfEnumeratorWalker.GetInstance();

            walker.SetValues(declarator, context.SemanticModel, context.CancellationToken);

            walker.Visit(whileStatement.Statement);

            bool?isFixable = walker.IsFixable;

            UnnecessaryUsageOfEnumeratorWalker.Free(walker);

            if (isFixable == true)
            {
                DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UnnecessaryUsageOfEnumerator, usingStatement.UsingKeyword);
            }
        }
Example #3
0
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionOfTSymbol)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

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

            if (ifStatement.ContainsDiagnostics)
            {
                return;
            }

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

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, allowedStyles: NullCheckStyles.NotEqualsToNull);

            ExpressionSyntax expression = nullCheck.Expression;

            if (expression == null)
            {
                return;
            }

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(ifStatement.SingleNonBlockStatementOrDefault());

            ExpressionSyntax expression2 = invocationInfo.Expression;

            if (expression2 == null)
            {
                return;
            }

            ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(expression);

            if (typeSymbol == null)
            {
                return;
            }

            if (typeSymbol.IsNullableType())
            {
                if (!expression2.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    return;
                }

                var memberAccess = (MemberAccessExpressionSyntax)expression2;

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

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

                expression2 = memberAccess.Expression;
            }

            if (!CSharpFactory.AreEquivalent(expression, expression2))
            {
                return;
            }

            if (ifStatement.IsInExpressionTree(expressionOfTSymbol, context.SemanticModel, context.CancellationToken))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UseConditionalAccess, ifStatement);
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            ArgumentSyntax argument,
            MemberInvocationExpressionInfo invocationInfo,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            InvocationExpressionSyntax invocation    = invocationInfo.InvocationExpression;
            InvocationExpressionSyntax newInvocation = null;

            bool isAppendLine = string.Equals(invocationInfo.NameText, "AppendLine", StringComparison.Ordinal);

            ExpressionSyntax expression = argument.Expression;

            switch (expression.Kind())
            {
            case SyntaxKind.InterpolatedStringExpression:
            {
                newInvocation = ConvertInterpolatedStringExpressionToInvocationExpression((InterpolatedStringExpressionSyntax)argument.Expression, invocationInfo, semanticModel);
                break;
            }

            case SyntaxKind.AddExpression:
            {
                ImmutableArray <ExpressionSyntax> expressions = SyntaxInfo.BinaryExpressionChainInfo((BinaryExpressionSyntax)expression).Expressions;

                newInvocation = invocation
                                .ReplaceNode(invocationInfo.Name, IdentifierName("Append").WithTriviaFrom(invocationInfo.Name))
                                .WithArgumentList(invocation.ArgumentList.WithArguments(SingletonSeparatedList(Argument(expressions[0]))).WithoutTrailingTrivia());

                for (int i = 1; i < expressions.Length; i++)
                {
                    ExpressionSyntax argumentExpression = expressions[i];

                    string methodName;
                    if (i == expressions.Length - 1 &&
                        isAppendLine &&
                        semanticModel
                        .GetTypeInfo(argumentExpression, cancellationToken)
                        .ConvertedType?
                        .SpecialType == SpecialType.System_String)
                    {
                        methodName = "AppendLine";
                    }
                    else
                    {
                        methodName = "Append";
                    }

                    newInvocation = SimpleMemberInvocationExpression(
                        newInvocation,
                        IdentifierName(methodName),
                        ArgumentList(Argument(argumentExpression)));

                    if (i == expressions.Length - 1 &&
                        isAppendLine &&
                        !string.Equals(methodName, "AppendLine", StringComparison.Ordinal))
                    {
                        newInvocation = SimpleMemberInvocationExpression(
                            newInvocation,
                            IdentifierName("AppendLine"),
                            ArgumentList());
                    }
                }

                break;
            }

            default:
            {
                newInvocation = CreateInvocationExpression(
                    (InvocationExpressionSyntax)expression,
                    invocation);

                if (isAppendLine)
                {
                    newInvocation = SimpleMemberInvocationExpression(newInvocation, IdentifierName("AppendLine"), ArgumentList());
                }

                break;
            }
            }

            newInvocation = newInvocation
                            .WithTriviaFrom(invocation)
                            .WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(invocation, newInvocation, cancellationToken).ConfigureAwait(false));
        }
Example #5
0
 private static SingleLocalDeclarationStatementInfo GetLocalInfo(StatementSyntax statement)
 {
     return((statement.IsKind(SyntaxKind.LocalDeclarationStatement))
         ? SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement)
         : default);
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

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

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            if (!statementsInfo.Success)
            {
                return;
            }

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

            ExpressionSyntax expression = returnStatement?.Expression;

            if (expression == null)
            {
                return;
            }

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

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

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

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

            if (symbol == null)
            {
                return;
            }

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

            foreach (IfStatementOrElseClause ifOrElse in ifStatement.AsCascade())
            {
                StatementSyntax statement = ifOrElse.Statement;

                if (statement.IsKind(SyntaxKind.Block))
                {
                    statement = ((BlockSyntax)statement).Statements.LastOrDefault();
                }

                if (!IsSymbolAssignedInStatement(symbol, statement, semanticModel, cancellationToken))
                {
                    return;
                }
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseReturnInsteadOfAssignment, ifStatement);
        }
        private static InterpolatedStringExpressionSyntax ReplaceInterpolationWithStringLiteralInnerText(
            SeparatedSyntaxList <ArgumentSyntax> arguments,
            InterpolatedStringExpressionSyntax interpolatedString,
            string text)
        {
            StringBuilder sb = StringBuilderCache.GetInstance();

            int pos = 0;

            SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents;

            for (int i = 0; i < contents.Count; i++)
            {
                if (contents[i].Kind() != SyntaxKind.Interpolation)
                {
                    continue;
                }

                var interpolation = (InterpolationSyntax)contents[i];

                ExpressionSyntax expression = interpolation.Expression;

                if (expression?.Kind() != SyntaxKind.NumericLiteralExpression)
                {
                    continue;
                }

                var index = (int)((LiteralExpressionSyntax)expression).Token.Value;

                if (index < 0)
                {
                    continue;
                }

                if (index >= arguments.Count)
                {
                    continue;
                }

                ExpressionSyntax argumentExpression = arguments[index + 1].Expression;

                StringLiteralExpressionInfo stringLiteral = SyntaxInfo.StringLiteralExpressionInfo(argumentExpression);

                if (!stringLiteral.Success)
                {
                    continue;
                }

                sb.Append(text, pos, interpolation.SpanStart - pos);

                int startIndex = sb.Length;
                sb.Append(stringLiteral.InnerText);
                sb.Replace("{", "{{", startIndex);
                sb.Replace("}", "}}", startIndex);

                pos = interpolation.Span.End;
            }

            sb.Append(text, pos, text.Length - pos);

            return((InterpolatedStringExpressionSyntax)ParseExpression(StringBuilderCache.GetStringAndFree(sb)));
        }
Example #8
0
        public static async Task <Document> RefactorAsync(
            Document document,
            PropertyDeclarationSyntax propertyDeclaration,
            bool prefixIdentifierWithUnderscore = true,
            CancellationToken cancellationToken = default)
        {
            string fieldName = StringUtility.ToCamelCase(
                propertyDeclaration.Identifier.ValueText,
                prefixWithUnderscore: prefixIdentifierWithUnderscore);

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

            fieldName = NameGenerator.Default.EnsureUniqueName(
                fieldName,
                semanticModel,
                propertyDeclaration.SpanStart);

            FieldDeclarationSyntax fieldDeclaration = FieldDeclaration(
                (propertyDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) ? Modifiers.Private_Static() : Modifiers.Private(),
                propertyDeclaration.Type,
                fieldName,
                propertyDeclaration.Initializer).WithFormatterAnnotation();

            IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

            PropertyDeclarationSyntax newPropertyDeclaration = ExpandAccessors(document, propertyDeclaration, propertySymbol, fieldName, semanticModel)
                                                               .WithModifiers(propertyDeclaration.Modifiers.Replace(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword))
                                                               .WithTriviaFrom(propertyDeclaration)
                                                               .WithFormatterAnnotation();

            MemberDeclarationListInfo membersInfo = SyntaxInfo.MemberDeclarationListInfo(propertyDeclaration.Parent);

            SyntaxList <MemberDeclarationSyntax> members = membersInfo.Members;

            int propertyIndex = membersInfo.IndexOf(propertyDeclaration);

            AccessorListSyntax accessorList = propertyDeclaration.AccessorList;

            if (accessorList?.Getter()?.IsAutoImplemented() == true &&
                accessorList.Setter() == null)
            {
                ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(propertySymbol, document, cancellationToken : cancellationToken).ConfigureAwait(false);

                IdentifierNameSyntax newNode = IdentifierName(fieldName);

                SyntaxNode newParent = membersInfo.Parent.ReplaceNodes(nodes, (node, _) =>
                {
                    if (node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) &&
                        ((MemberAccessExpressionSyntax)node.Parent).Expression.IsKind(SyntaxKind.BaseExpression))
                    {
                        return(node);
                    }

                    return(newNode.WithTriviaFrom(node));
                });

                MemberDeclarationListInfo newMembersInfo = SyntaxInfo.MemberDeclarationListInfo(newParent);

                members = newMembersInfo.Members;
            }

            SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceAt(propertyIndex, newPropertyDeclaration);

            newMembers = MemberDeclarationInserter.Default.Insert(newMembers, fieldDeclaration);

            return(await document.ReplaceMembersAsync(membersInfo, newMembers, cancellationToken).ConfigureAwait(false));
        }
Example #9
0
        private static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.SpanContainsDirectives())
            {
                return;
            }

            var conditionalExpression = (ConditionalExpressionSyntax)context.Node;

            ConditionalExpressionInfo conditionalExpressionInfo = SyntaxInfo.ConditionalExpressionInfo(conditionalExpression);

            if (!conditionalExpressionInfo.Success)
            {
                return;
            }

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

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(conditionalExpressionInfo.Condition, semanticModel: semanticModel, cancellationToken: cancellationToken);

            if (!nullCheck.Success)
            {
                return;
            }

            ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse;

            ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue;

            if (CSharpFactory.AreEquivalent(nullCheck.Expression, whenNotNull))
            {
                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression) &&
                    semanticModel
                    .GetTypeSymbol(nullCheck.Expression, cancellationToken)?
                    .IsReferenceTypeOrNullableType() == true)
                {
                    DiagnosticHelpers.ReportDiagnostic(context,
                                                       DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression,
                                                       conditionalExpression);
                }
            }
            else if (whenNotNull.IsKind(
                         SyntaxKind.SimpleMemberAccessExpression,
                         SyntaxKind.ElementAccessExpression,
                         SyntaxKind.ConditionalAccessExpression,
                         SyntaxKind.InvocationExpression))
            {
                ExpressionSyntax expression = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed(
                    nullCheck.Expression,
                    whenNotNull,
                    semanticModel,
                    cancellationToken);

                if (expression == null)
                {
                    return;
                }

                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken);

                if (typeSymbol == null)
                {
                    return;
                }

                if (typeSymbol.IsReferenceType)
                {
                    Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken);
                }
                else if (typeSymbol.IsNullableType())
                {
                    if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent;

                        if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
                            (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value")
                        {
                            if (memberAccessExpression == whenNotNull)
                            {
                                if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression))
                                {
                                    DiagnosticHelpers.ReportDiagnostic(
                                        context,
                                        DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression,
                                        conditionalExpression);
                                }
                            }
                            else
                            {
                                Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken);
                            }
                        }
                    }
                }
            }
            else if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression) &&
                     ((CSharpCompilation)context.Compilation).LanguageVersion >= LanguageVersion.CSharp6 &&
                     whenNotNull.IsKind(SyntaxKind.CastExpression) &&
                     whenNull.IsKind(SyntaxKind.NullLiteralExpression, SyntaxKind.DefaultLiteralExpression))
            {
                var castExpression = (CastExpressionSyntax)whenNotNull;

                if (castExpression.Type.IsKind(SyntaxKind.NullableType) &&
                    castExpression.Expression.IsKind(SyntaxKind.InvocationExpression, SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression))
                {
                    ExpressionSyntax expression = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed(
                        nullCheck.Expression,
                        castExpression.Expression,
                        isNullable: true,
                        semanticModel,
                        cancellationToken);

                    if (expression != null)
                    {
                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken);

                        if (typeSymbol?.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
                        {
                            DiagnosticHelpers.ReportDiagnostic(context,
                                                               DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression,
                                                               conditionalExpression);
                        }
                    }
                }
            }
        }
        public static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context, INamedTypeSymbol eventArgsSymbol)
        {
            var methodDeclaration = (MethodDeclarationSyntax)context.Node;

            if (methodDeclaration.ContainsDiagnostics)
            {
                return;
            }

            if (methodDeclaration.IsParentKind(SyntaxKind.InterfaceDeclaration))
            {
                return;
            }

            if (methodDeclaration.Modifiers.ContainsAny(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword))
            {
                return;
            }

            ParameterInfo parameterInfo = SyntaxInfo.ParameterInfo(methodDeclaration);

            if (!parameterInfo.Success)
            {
                return;
            }

            if (ContainsOnlyThrowNewExpression(parameterInfo.Body))
            {
                return;
            }

            IMethodSymbol methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

            if (methodSymbol == null)
            {
                return;
            }

            if (SymbolUtility.IsEventHandlerMethod(methodSymbol, eventArgsSymbol))
            {
                return;
            }

            if (!methodSymbol.ExplicitInterfaceImplementations.IsDefaultOrEmpty)
            {
                return;
            }

            if (methodSymbol.ImplementsInterfaceMember(allInterfaces: true))
            {
                return;
            }

            Dictionary <string, NodeSymbolInfo> unusedNodes = FindUnusedNodes(context, parameterInfo);

            if (unusedNodes.Count == 0)
            {
                return;
            }

            if (IsReferencedAsMethodGroup(context, methodDeclaration))
            {
                return;
            }

            foreach (KeyValuePair <string, NodeSymbolInfo> kvp in unusedNodes)
            {
                ReportDiagnostic(context, kvp.Value.Node);
            }

            unusedNodes.Clear();
        }
        public static async Task ComputeRefactoringAsync(
            RefactoringContext context,
            PropertyDeclarationSyntax property)
        {
            AccessorDeclarationSyntax setter = property.Setter();

            if (setter == null)
            {
                return;
            }

            ExpressionSyntax expression = GetExpression();

            if (expression == null)
            {
                return;
            }

            SimpleAssignmentExpressionInfo simpleAssignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression);

            if (!simpleAssignment.Success)
            {
                return;
            }

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

            if (!(simpleAssignment.Right is IdentifierNameSyntax identifierName))
            {
                return;
            }

            if (identifierName.Identifier.ValueText != "value")
            {
                return;
            }

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

            INamedTypeSymbol containingType = semanticModel
                                              .GetDeclaredSymbol(property, context.CancellationToken)?
                                              .ContainingType;

            if (containingType == null)
            {
                return;
            }

            if (!containingType.Implements(MetadataNames.System_ComponentModel_INotifyPropertyChanged, allInterfaces: true))
            {
                return;
            }

            IMethodSymbol methodSymbol = SymbolUtility.FindMethodThatRaisePropertyChanged(containingType, expression.SpanStart, semanticModel);

            if (methodSymbol == null)
            {
                return;
            }

            Document document = context.Document;

            context.RegisterRefactoring(
                "Notify when property change",
                ct => RefactorAsync(document, property, methodSymbol.Name, ct),
                RefactoringIdentifiers.NotifyWhenPropertyChange);

            ExpressionSyntax GetExpression()
            {
                BlockSyntax body = setter.Body;

                if (body != null)
                {
                    if (body.Statements.SingleOrDefault(shouldThrow: false) is ExpressionStatementSyntax expressionStatement)
                    {
                        return(expressionStatement.Expression);
                    }
                }
                else
                {
                    return(setter.ExpressionBody?.Expression);
                }

                return(null);
            }
        }
Example #12
0
        public static async Task <Document> InvertIfAsync(
            Document document,
            IfStatementSyntax ifStatement,
            bool recursive = false,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            StatementSyntax statement = ifStatement.Statement;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            InvertIfAnalysis analysis = InvertIfAnalysis.Create(ifStatement, statement);

            int ifStatementIndex = statements.IndexOf(ifStatement);

            StatementSyntax lastStatement = analysis.LastStatement;

            int lastStatementIndex = statements.IndexOf(lastStatement);

            bool isLastStatementRedundant = IsLastStatementRedundant();

            bool shouldUseElseClause = !CSharpFacts.IsJumpStatement(lastStatement.Kind());

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

            SyntaxList <StatementSyntax> newStatements = statements;

            if (!recursive)
            {
                Refactor();
            }
            else
            {
                IfStatementSyntax lastIfStatement;

                InvertIfAnalysis a = analysis.AnalyzeNextStatement();

                do
                {
                    lastIfStatement = a.IfStatement;

                    a = a.AnalyzeNextStatement();
                } while (a.Success);

                int firstLastStatementIndex = lastStatementIndex;

                int index = statements.IndexOf(lastIfStatement);

                int firstIndex = ifStatementIndex;

                while (index >= firstIndex)
                {
                    ifStatementIndex = index;
                    ifStatement      = (IfStatementSyntax)statements[ifStatementIndex];
                    statement        = ifStatement.Statement;
                    Refactor();
                    lastStatementIndex = firstLastStatementIndex + newStatements.Count - statements.Count;
                    lastStatement      = (statement is BlockSyntax block) ? block.Statements.Last() : statement;
                    index--;
                }
            }

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

            void Refactor()
            {
                cancellationToken.ThrowIfCancellationRequested();

                SyntaxList <StatementSyntax> nextStatements = newStatements
                                                              .Skip(ifStatementIndex + 1)
                                                              .Take(lastStatementIndex - ifStatementIndex)
                                                              .ToSyntaxList()
                                                              .TrimTrivia();

                BlockSyntax newStatement;
                SyntaxList <StatementSyntax> newNextStatements;

                if (statement is BlockSyntax block)
                {
                    newStatement      = block.WithStatements(nextStatements);
                    newNextStatements = block.Statements;
                }
                else
                {
                    newStatement      = Block(nextStatements);
                    newNextStatements = SingletonList(statement);
                }

                if (isLastStatementRedundant)
                {
                    newNextStatements = newNextStatements.RemoveAt(newNextStatements.Count - 1);
                }

                ElseClauseSyntax elseClause = null;

                if (newNextStatements.Any() &&
                    shouldUseElseClause)
                {
                    elseClause        = ElseClause(Block(newNextStatements));
                    newNextStatements = default;
                }

                IfStatementSyntax newIfStatement = ifStatement.Update(
                    ifKeyword: ifStatement.IfKeyword,
                    openParenToken: ifStatement.OpenParenToken,
                    condition: SyntaxInverter.LogicallyInvert(ifStatement.Condition, semanticModel, cancellationToken),
                    closeParenToken: ifStatement.CloseParenToken,
                    statement: newStatement,
                    @else: elseClause);

                newIfStatement = newIfStatement.WithFormatterAnnotation();

                SyntaxList <StatementSyntax> newNodes = newNextStatements.Insert(0, newIfStatement);

                newStatements = newStatements.ReplaceRange(ifStatementIndex, lastStatementIndex - ifStatementIndex + 1, newNodes);
            }

            bool IsLastStatementRedundant()
            {
                StatementSyntax jumpStatement = analysis.JumpStatement;

                switch (jumpStatement.Kind())
                {
                case SyntaxKind.ReturnStatement:
                {
                    if (((ReturnStatementSyntax)jumpStatement).Expression == null &&
                        RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ReturnStatement))
                    {
                        return(true);
                    }

                    break;
                }

                case SyntaxKind.ContinueStatement:
                {
                    if (RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ContinueStatement))
                    {
                        return(true);
                    }

                    break;
                }
                }

                return(false);
            }
        }
Example #13
0
        public static async Task <Document> RefactorAsync(
            Document document,
            ConditionalExpressionSyntax conditionalExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false);

            ConditionalExpressionInfo conditionalExpressionInfo = SyntaxInfo.ConditionalExpressionInfo(conditionalExpression);

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(conditionalExpressionInfo.Condition, semanticModel: semanticModel, cancellationToken: cancellationToken);

            ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse;

            ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue;

            ExpressionSyntax expression = (whenNotNull.IsKind(SyntaxKind.CastExpression))
                ? UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, ((CastExpressionSyntax)whenNotNull).Expression)
                : UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull);

            bool coalesce = false;

            ExpressionSyntax newNode = null;

            if (CSharpFactory.AreEquivalent(nullCheck.Expression, whenNotNull))
            {
                //RCS1084 UseCoalesceExpressionInsteadOfConditionalExpression
                newNode  = nullCheck.Expression;
                coalesce = true;
            }
            else if (semanticModel
                     .GetTypeSymbol(nullCheck.Expression, cancellationToken)
                     .IsNullableType())
            {
                if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent;

                    if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
                        (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value")
                    {
                        if (memberAccessExpression == whenNotNull)
                        {
                            //RCS1084 UseCoalesceExpressionInsteadOfConditionalExpression
                            newNode  = nullCheck.Expression;
                            coalesce = true;
                        }
                        else
                        {
                            newNode = ParseExpression($"{expression}?{whenNotNull.ToString().Substring(memberAccessExpression.Span.End - whenNotNull.SpanStart)}");
                        }
                    }
                }
            }

            if (newNode == null)
            {
                newNode = ParseExpression(whenNotNull.ToString().Insert(expression.Span.End - whenNotNull.SpanStart, "?"));
            }

            if (coalesce || !semanticModel.GetTypeSymbol(whenNotNull, cancellationToken).IsReferenceTypeOrNullableType())
            {
                newNode = CoalesceExpression(newNode.Parenthesize(), whenNull.Parenthesize());
            }

            newNode = newNode
                      .WithTriviaFrom(conditionalExpression)
                      .Parenthesize();

            return(await document.ReplaceNodeAsync(conditionalExpression, newNode, cancellationToken).ConfigureAwait(false));
        }
        public static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.SpanContainsDirectives())
            {
                return;
            }

            var conditionalExpression = (ConditionalExpressionSyntax)context.Node;

            ConditionalExpressionInfo conditionalExpressionInfo = SyntaxInfo.ConditionalExpressionInfo(conditionalExpression);

            if (!conditionalExpressionInfo.Success)
            {
                return;
            }

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

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(conditionalExpressionInfo.Condition, semanticModel: semanticModel, cancellationToken: cancellationToken);

            if (!nullCheck.Success)
            {
                return;
            }

            ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse;

            ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue;

            if (SyntaxComparer.AreEquivalent(nullCheck.Expression, whenNotNull))
            {
                if (semanticModel
                    .GetTypeSymbol(nullCheck.Expression, cancellationToken)?
                    .IsReferenceTypeOrNullableType() == true)
                {
                    context.ReportDiagnostic(
                        DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression,
                        conditionalExpression);
                }
            }
            else if (whenNotNull.IsKind(
                         SyntaxKind.SimpleMemberAccessExpression,
                         SyntaxKind.ElementAccessExpression,
                         SyntaxKind.ConditionalAccessExpression,
                         SyntaxKind.InvocationExpression))
            {
                ExpressionSyntax expression = UseConditionalAccessRefactoring.FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull);

                if (expression == null)
                {
                    return;
                }

                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken);

                if (typeSymbol == null)
                {
                    return;
                }

                if (typeSymbol.IsReferenceType)
                {
                    Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken);
                }
                else if (typeSymbol.IsConstructedFrom(SpecialType.System_Nullable_T))
                {
                    if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent;

                        if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
                            (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value")
                        {
                            if (memberAccessExpression == whenNotNull)
                            {
                                context.ReportDiagnostic(
                                    DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression,
                                    conditionalExpression);
                            }
                            else
                            {
                                Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken);
                            }
                        }
                    }
                }
            }
        }
Example #15
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeParameterConstraintSyntax constraint))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.NewConstraintMustBeLastConstraintSpecified:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MoveConstraint))
                    {
                        break;
                    }

                    TypeParameterConstraintInfo constraintInfo = SyntaxInfo.TypeParameterConstraintInfo(constraint);

                    if (!constraintInfo.Success)
                    {
                        break;
                    }

                    MoveConstraint(context, diagnostic, constraintInfo, constraintInfo.Constraints.Count - 1);

                    break;
                }

                case CompilerDiagnosticIdentifiers.DuplicateConstraintForTypeParameter:
                {
                    if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstraint))
                    {
                        RemoveConstraint(context, diagnostic, constraint);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ClassOrStructConstraintMustComeBeforeAnyOtherConstraints:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MoveConstraint))
                    {
                        break;
                    }

                    TypeParameterConstraintInfo constraintInfo = SyntaxInfo.TypeParameterConstraintInfo(constraint);

                    if (!constraintInfo.Success)
                    {
                        break;
                    }

                    if (constraintInfo.IsDuplicateConstraint)
                    {
                        RemoveConstraint(context, diagnostic, constraint);
                    }
                    else
                    {
                        MoveConstraint(context, diagnostic, constraintInfo, 0);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotSpecifyBothConstraintClassAndClassOrStructConstraint:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstraint))
                    {
                        break;
                    }

                    TypeParameterConstraintInfo constraintInfo = SyntaxInfo.TypeParameterConstraintInfo(constraint);

                    if (!constraintInfo.Success)
                    {
                        break;
                    }

                    RemoveConstraint(context, diagnostic, constraint);

                    TypeParameterConstraintSyntax classConstraint = constraintInfo.Constraints.Find(SyntaxKind.ClassConstraint);

                    if (classConstraint != null)
                    {
                        RemoveConstraint(context, diagnostic, classConstraint);
                    }

                    TypeParameterConstraintSyntax structConstraint = constraintInfo.Constraints.Find(SyntaxKind.StructConstraint);

                    if (structConstraint != null)
                    {
                        RemoveConstraint(context, diagnostic, structConstraint);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.NewConstraintCannotBeUsedWithStructConstraint:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstraint))
                    {
                        break;
                    }

                    RemoveConstraint(context, diagnostic, constraint);

                    TypeParameterConstraintInfo constraintInfo = SyntaxInfo.TypeParameterConstraintInfo(constraint);

                    if (!constraintInfo.Success)
                    {
                        break;
                    }

                    TypeParameterConstraintSyntax structConstraint = constraintInfo.Constraints.Find(SyntaxKind.StructConstraint);

                    RemoveConstraint(context, diagnostic, structConstraint);
                    break;
                }
                }
            }
        }
Example #16
0
        public static void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.ContainsDiagnostics)
            {
                return;
            }

            var localDeclaration = (LocalDeclarationStatementSyntax)context.Node;

            if (localDeclaration.IsConst)
            {
                return;
            }

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(localDeclaration);

            if (!statementsInfo.Success)
            {
                return;
            }

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

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

            int index = statements.IndexOf(localDeclaration);

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

            LocalDeclarationStatementInfo localInfo = SyntaxInfo.LocalDeclarationStatementInfo(localDeclaration);

            if (!localInfo.Success)
            {
                return;
            }

            ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(localInfo.Type, context.CancellationToken);

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

            foreach (VariableDeclaratorSyntax declarator in localInfo.Variables)
            {
                if (!HasConstantValue(declarator.Initializer?.Value, typeSymbol, context.SemanticModel, context.CancellationToken))
                {
                    return;
                }
            }

            if (!CanBeMarkedAsConst(localInfo.Variables, statements, index + 1))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.MarkLocalVariableAsConst, localInfo.Type);
        }
        public static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context)
        {
            var switchStatement = (SwitchStatementSyntax)context.Node;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(switchStatement);

            if (!statementsInfo.Success)
            {
                return;
            }

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

            ExpressionSyntax expression = returnStatement?.Expression;

            if (expression == null)
            {
                return;
            }

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

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

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

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

            if (symbol == null)
            {
                return;
            }

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

            foreach (SwitchSectionSyntax section in switchStatement.Sections)
            {
                SyntaxList <StatementSyntax> statements = section.GetStatements();

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

                if (!statements.Last().IsKind(SyntaxKind.BreakStatement))
                {
                    return;
                }

                if (!IsSymbolAssignedInStatement(symbol, statements[statements.Count - 2], semanticModel, cancellationToken))
                {
                    return;
                }
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseReturnInsteadOfAssignment, switchStatement);
        }
        private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement.ContainsDiagnostics)
            {
                return;
            }

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

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

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

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

            if (IsPartOfLazyInitialization())
            {
                return;
            }

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(
                ifStatement.Condition,
                semanticModel: context.SemanticModel,
                allowedStyles: NullCheckStyles.CheckingNull,
                cancellationToken: context.CancellationToken);

            if (!nullCheck.Success)
            {
                return;
            }

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault());

            if (!assignmentInfo.Success)
            {
                return;
            }

            if (!CSharpFactory.AreEquivalent(assignmentInfo.Left, nullCheck.Expression))
            {
                return;
            }

            if (!assignmentInfo.Right.IsSingleLine())
            {
                return;
            }

            int index = statements.IndexOf(ifStatement);

            if (index > 0 &&
                !context.IsAnalyzerSuppressed(DiagnosticDescriptors.UseCoalesceExpression))
            {
                StatementSyntax previousStatement = statements[index - 1];

                if (!previousStatement.ContainsDiagnostics &&
                    !previousStatement.GetTrailingTrivia().Any(f => f.IsDirective) &&
                    !ifStatement.GetLeadingTrivia().Any(f => f.IsDirective) &&
                    CanUseCoalesceExpression(previousStatement, nullCheck.Expression))
                {
                    DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UseCoalesceExpression, previousStatement);
                }
            }

            if (context.IsAnalyzerSuppressed(DiagnosticDescriptors.InlineLazyInitialization))
            {
                return;
            }

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

            StatementSyntax nextStatement = statements[index + 1];

            if (nextStatement.ContainsDiagnostics)
            {
                return;
            }

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(nextStatement);

            if (!invocationInfo.Success)
            {
                return;
            }

            if (!CSharpFactory.AreEquivalent(nullCheck.Expression, invocationInfo.Expression))
            {
                return;
            }

            if (ifStatement.GetTrailingTrivia().Any(f => f.IsDirective))
            {
                return;
            }

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

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.InlineLazyInitialization, ifStatement);

            bool IsPartOfLazyInitialization()
            {
                return(statements.Count == 2 &&
                       statements.IndexOf(ifStatement) == 0 &&
                       statements[1].IsKind(SyntaxKind.ReturnStatement));
            }
        }
 private static bool CanRefactor(SyntaxNode node)
 {
     return(node.IsKind(SyntaxKind.LogicalAndExpression, SyntaxKind.LogicalOrExpression) &&
            SyntaxInfo.BinaryExpressionInfo((BinaryExpressionSyntax)node).Success);
 }
Example #20
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, InvocationExpressionSyntax invocation)
        {
            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

            if (!invocationInfo.Success)
            {
                return;
            }

            switch (invocationInfo.NameText)
            {
            case "First":
            {
                if (invocationInfo.Arguments.Any())
                {
                    break;
                }

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

                if (!UseElementAccessAnalysis.IsFixableFirst(invocationInfo, semanticModel, context.CancellationToken))
                {
                    break;
                }

                context.RegisterRefactoring(
                    "Use [] instead of calling 'First'",
                    cancellationToken => UseElementAccessInsteadOfEnumerableMethodRefactoring.UseElementAccessInsteadOfFirstAsync(context.Document, invocation, cancellationToken),
                    RefactoringIdentifiers.UseElementAccessInsteadOfEnumerableMethod);

                break;
            }

            case "Last":
            {
                if (invocationInfo.Arguments.Any())
                {
                    break;
                }

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

                if (!UseElementAccessAnalysis.IsFixableLast(invocationInfo, semanticModel, context.CancellationToken))
                {
                    break;
                }

                string propertyName = CSharpUtility.GetCountOrLengthPropertyName(invocationInfo.Expression, semanticModel, context.CancellationToken);

                if (propertyName == null)
                {
                    break;
                }

                context.RegisterRefactoring(
                    "Use [] instead of calling 'Last'",
                    cancellationToken => UseElementAccessInsteadOfEnumerableMethodRefactoring.UseElementAccessInsteadOfLastAsync(context.Document, invocation, propertyName, cancellationToken),
                    RefactoringIdentifiers.UseElementAccessInsteadOfEnumerableMethod);

                break;
            }

            case "ElementAt":
            {
                if (invocationInfo.Arguments.SingleOrDefault(shouldThrow: false)?.Expression?.IsMissing != false)
                {
                    break;
                }

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

                if (!UseElementAccessAnalysis.IsFixableElementAt(invocationInfo, semanticModel, context.CancellationToken))
                {
                    break;
                }

                context.RegisterRefactoring(
                    "Use [] instead of calling 'ElementAt'",
                    cancellationToken => UseElementAccessInsteadOfEnumerableMethodRefactoring.UseElementAccessInsteadOfElementAtAsync(context.Document, invocation, cancellationToken),
                    RefactoringIdentifiers.UseElementAccessInsteadOfEnumerableMethod);

                break;
            }
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out InvocationExpressionSyntax invocation))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case DiagnosticIdentifiers.CombineEnumerableWhereMethodChain:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Combine 'Where' method chain",
                        cancellationToken => CombineEnumerableWhereMethodChainRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseCountOrLengthPropertyInsteadOfAnyMethod:
                {
                    string propertyName = diagnostic.Properties["PropertyName"];

                    CodeAction codeAction = CodeAction.Create(
                        $"Use '{propertyName}' property instead of calling 'Any'",
                        cancellationToken => UseCountOrLengthPropertyInsteadOfAnyMethodRefactoring.RefactorAsync(context.Document, invocation, propertyName, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseCountOrLengthPropertyInsteadOfCountMethod:
                {
                    string propertyName = diagnostic.Properties["PropertyName"];

                    CodeAction codeAction = CodeAction.Create(
                        $"Use '{propertyName}' property instead of calling 'Count'",
                        cancellationToken => UseCountOrLengthPropertyInsteadOfCountMethodRefactoring.RefactorAsync(context.Document, invocation, diagnostic.Properties["PropertyName"], cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseBitwiseOperationInsteadOfCallingHasFlag:
                {
                    CodeAction codeAction = CodeAction.Create(
                        UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.Title,
                        cancellationToken => UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.RemoveRedundantToStringCall:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Remove redundant 'ToString' call",
                        cancellationToken => context.Document.ReplaceNodeAsync(invocation, RefactoringUtility.RemoveInvocation(invocation).WithFormatterAnnotation(), cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallCastInsteadOfSelect:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Cast' instead of 'Select'",
                        cancellationToken => CallCastInsteadOfSelectRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.RemoveRedundantStringToCharArrayCall:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Remove redundant 'ToCharArray' call",
                        cancellationToken => context.Document.ReplaceNodeAsync(invocation, RefactoringUtility.RemoveInvocation(invocation).WithFormatterAnnotation(), cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallFindInsteadOfFirstOrDefault:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Find' instead of 'FirstOrDefault'",
                        cancellationToken => CallFindInsteadOfFirstOrDefaultRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseElementAccessInsteadOfElementAt:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use [] instead of calling 'ElementAt'",
                        cancellationToken => UseElementAccessInsteadOfElementAtRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.UseElementAccessInsteadOfFirst:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use [] instead of calling 'First'",
                        cancellationToken => UseElementAccessInsteadOfFirstRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallStringConcatInsteadOfStringJoin:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Concat' instead of 'Join'",
                        cancellationToken => CallStringConcatInsteadOfStringJoinRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallDebugFailInsteadOfDebugAssert:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Fail' instead of 'Assert'",
                        cancellationToken => CallDebugFailInsteadOfDebugAssertRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallExtensionMethodAsInstanceMethod:
                {
                    CodeAction codeAction = CodeAction.Create(
                        CallExtensionMethodAsInstanceMethodRefactoring.Title,
                        cancellationToken => CallExtensionMethodAsInstanceMethodRefactoring.RefactorAsync(context.Document, invocation, cancellationToken),
                        GetEquivalenceKey(diagnostic));

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

                case DiagnosticIdentifiers.CallThenByInsteadOfOrderBy:
                {
                    SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation);

                    string oldName = invocationInfo.NameText;

                    string newName = (string.Equals(oldName, "OrderBy", StringComparison.Ordinal))
                                ? "ThenBy"
                                : "ThenByDescending";

                    CodeAction codeAction = CodeAction.Create(
                        $"Call '{newName}' instead of '{oldName}'",
                        cancellationToken => CallThenByInsteadOfOrderByRefactoring.RefactorAsync(context.Document, invocation, newName, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
Example #22
0
        internal static bool IsFixable(
            PropertyDeclarationSyntax propertyDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true)
                {
                    return(false);
                }

                var memberAccess = (MemberAccessExpressionSyntax)expression;

                if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                SimpleNameSyntax simpleName = memberAccess.Name;

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

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

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

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

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

                return(overriddenProperty.Equals(symbol));
            }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression);

                if (!assignment.Success)
                {
                    return(false);
                }

                if (assignment.Left.Kind() != SyntaxKind.SimpleMemberAccessExpression)
                {
                    return(false);
                }

                var memberAccess = (MemberAccessExpressionSyntax)assignment.Left;

                if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

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

                var identifierName = (IdentifierNameSyntax)assignment.Right;

                if (identifierName.Identifier.ValueText != "value")
                {
                    return(false);
                }

                SimpleNameSyntax simpleName = memberAccess.Name;

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

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

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

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

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

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

                return(overriddenProperty.Equals(symbol));
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                Debug.Fail(accessor.Kind().ToString());
                return(false);
            }
            }
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo)
        {
            INamedTypeSymbol stringBuilderSymbol = context.GetTypeByMetadataName(MetadataNames.System_Text_StringBuilder);

            if (stringBuilderSymbol != null)
            {
                InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression;

                if (context.SemanticModel.TryGetMethodInfo(invocationExpression, out MethodInfo methodInfo, context.CancellationToken) &&
                    !methodInfo.IsExtensionMethod &&
                    methodInfo.ContainingType?.Equals(stringBuilderSymbol) == true)
                {
                    ImmutableArray <IParameterSymbol>    parameters = methodInfo.Parameters;
                    SeparatedSyntaxList <ArgumentSyntax> arguments  = invocationInfo.Arguments;

                    if (parameters.Length == 1 &&
                        arguments.Count == 1 &&
                        methodInfo.IsName("Append", "AppendLine"))
                    {
                        ArgumentSyntax argument = arguments.First();

                        ExpressionSyntax expression = argument.Expression;

                        SyntaxKind expressionKind = expression.Kind();

                        switch (expressionKind)
                        {
                        case SyntaxKind.InterpolatedStringExpression:
                        {
                            context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name);
                            return;
                        }

                        case SyntaxKind.AddExpression:
                        {
                            StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo((BinaryExpressionSyntax)expression, context.SemanticModel, context.CancellationToken);
                            if (concatenationInfo.Success)
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name);
                                return;
                            }

                            break;
                        }

                        default:
                        {
                            if (expressionKind == SyntaxKind.InvocationExpression &&
                                IsFixable((InvocationExpressionSyntax)expression, context.SemanticModel, context.CancellationToken))
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name);
                                return;
                            }

                            if (methodInfo.IsName("Append") &&
                                parameters.Length == 1 &&
                                parameters[0].Type.IsObject() &&
                                context.SemanticModel.GetTypeSymbol(argument.Expression, context.CancellationToken).IsValueType)
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.AvoidBoxingOfValueType, argument);
                                return;
                            }

                            break;
                        }
                        }
                    }
                    else if (parameters.Length > 1 &&
                             methodInfo.IsName("Insert") &&
                             methodInfo.HasParameters(SpecialType.System_Int32, SpecialType.System_Object) &&
                             context.SemanticModel
                             .GetTypeSymbol(arguments[1].Expression, context.CancellationToken)
                             .IsValueType)
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.AvoidBoxingOfValueType, arguments[1]);
                    }
                }
            }
        }
Example #24
0
        private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
        {
            var methodDeclaration = (MethodDeclarationSyntax)context.Node;

            if (methodDeclaration.ContainsDirectives)
            {
                return;
            }

            if (methodDeclaration.ContainsDiagnostics)
            {
                return;
            }

            if (methodDeclaration.AttributeLists.Any())
            {
                return;
            }

            if (!CheckModifiers(methodDeclaration.Modifiers))
            {
                return;
            }

            if (methodDeclaration.HasDocumentationComment())
            {
                return;
            }

            if (!methodDeclaration.DescendantTrivia(methodDeclaration.Span).All(f => f.IsWhitespaceOrEndOfLineTrivia()))
            {
                return;
            }

            ExpressionSyntax expression = GetMethodExpression(methodDeclaration);

            SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(expression);

            if (!invocationInfo.Success)
            {
                return;
            }

            if (invocationInfo.Expression.Kind() != SyntaxKind.BaseExpression)
            {
                return;
            }

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

            IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken);

            if (methodSymbol == null)
            {
                return;
            }

            IMethodSymbol overriddenMethod = methodSymbol.OverriddenMethod;

            if (overriddenMethod == null)
            {
                return;
            }

            ISymbol symbol = semanticModel.GetSymbol(invocationInfo.Name, cancellationToken);

            if (!overriddenMethod.Equals(symbol))
            {
                return;
            }

            if (!CheckParameters(methodDeclaration.ParameterList, invocationInfo.ArgumentList, semanticModel, cancellationToken))
            {
                return;
            }

            if (!CheckDefaultValues(methodSymbol.Parameters, overriddenMethod.Parameters))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context,
                                               DiagnosticDescriptors.RemoveRedundantOverridingMember,
                                               methodDeclaration,
                                               CSharpFacts.GetTitle(methodDeclaration));
        }
Example #25
0
        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, DiagnosticRules.UseForStatementInsteadOfWhileStatement, whileStatement.WhileKeyword);

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

                walker.ContainsContinueStatement = false;

                var 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));
            }
        }
Example #26
0
        internal static bool IsFixable(
            IndexerDeclarationSyntax indexerDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                if (!(expression is ElementAccessExpressionSyntax elementAccess))
                {
                    return(false);
                }

                if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (elementAccess.ArgumentList == null)
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

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

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

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

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

                return(overriddenProperty.Equals(symbol) &&
                       CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) &&
                       CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters));
            }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression);

                if (!assignment.Success)
                {
                    return(false);
                }

                if (assignment.Left.Kind() != SyntaxKind.ElementAccessExpression)
                {
                    return(false);
                }

                var elementAccess = (ElementAccessExpressionSyntax)assignment.Left;

                if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (elementAccess.ArgumentList == null)
                {
                    return(false);
                }

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

                var identifierName = (IdentifierNameSyntax)assignment.Right;

                if (identifierName.Identifier.ValueText != "value")
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

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

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

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

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

                return(overriddenProperty.Equals(symbol) &&
                       CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) &&
                       CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters));
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                Debug.Fail(accessor.Kind().ToString());
                return(false);
            }
            }
        }
        private static ReduceIfNestingAnalysisResult AnalyzeCore(
            IfStatementSyntax ifStatement,
            SemanticModel semanticModel,
            SyntaxKind jumpKind,
            ReduceIfNestingOptions options,
            INamedTypeSymbol taskSymbol         = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            if (!statementsInfo.Success)
            {
                return(Fail(ifStatement));
            }

            SyntaxNode node       = statementsInfo.Parent;
            SyntaxNode parent     = node.Parent;
            SyntaxKind parentKind = parent.Kind();

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            if (statementsInfo.IsParentSwitchSection ||
                parentKind == SyntaxKind.SwitchSection)
            {
                SyntaxNode switchSection = (statementsInfo.IsParentSwitchSection) ? node : parent;

                if (!options.AllowSwitchSection())
                {
                    return(Fail(switchSection));
                }

                if (ifStatement != statements.LastButOneOrDefault())
                {
                    return(Fail(switchSection));
                }

                if (!IsFixableJumpStatement(statements.Last(), ref jumpKind))
                {
                    return(Fail(switchSection));
                }

                if (!options.AllowNestedFix() &&
                    IsNestedFix(switchSection.Parent, semanticModel, options, taskSymbol, cancellationToken))
                {
                    return(Fail(switchSection));
                }

                return(Success(jumpKind, switchSection));
            }

            if (parentKind.Is(
                    SyntaxKind.ForStatement,
                    SyntaxKind.ForEachStatement,
                    SyntaxKind.DoStatement,
                    SyntaxKind.WhileStatement))
            {
                if (!options.AllowLoop())
                {
                    return(Fail(parent));
                }

                StatementSyntax lastStatement = statements.Last();

                if (ifStatement == lastStatement)
                {
                    jumpKind = SyntaxKind.ContinueStatement;
                }
                else
                {
                    if (ifStatement != statements.LastButOneOrDefault())
                    {
                        return(Fail(parent));
                    }

                    if (!IsFixableJumpStatement(lastStatement, ref jumpKind))
                    {
                        return(Fail(parent));
                    }
                }

                if (!options.AllowNestedFix() &&
                    IsNestedFix(parent.Parent, semanticModel, options, taskSymbol, cancellationToken))
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            if (!IsFixable(ifStatement, statements, ref jumpKind))
            {
                return(Fail(node));
            }

            switch (parentKind)
            {
            case SyntaxKind.ConstructorDeclaration:
            case SyntaxKind.DestructorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
            {
                if (jumpKind == SyntaxKind.None)
                {
                    jumpKind = SyntaxKind.ReturnStatement;
                }
                else if (jumpKind != SyntaxKind.ReturnStatement)
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            case SyntaxKind.OperatorDeclaration:
            case SyntaxKind.ConversionOperatorDeclaration:
            case SyntaxKind.GetAccessorDeclaration:
            {
                if (jumpKind == SyntaxKind.None)
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            case SyntaxKind.MethodDeclaration:
            {
                var methodDeclaration = (MethodDeclarationSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (methodDeclaration.ReturnsVoid())
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (methodDeclaration.Modifiers.Contains(SyntaxKind.AsyncKeyword) &&
                    taskSymbol != null &&
                    semanticModel
                    .GetDeclaredSymbol(methodDeclaration, cancellationToken)?
                    .ReturnType
                    .Equals(taskSymbol) == true)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (semanticModel
                    .GetDeclaredSymbol(methodDeclaration, cancellationToken)?
                    .ReturnType
                    .OriginalDefinition
                    .IsIEnumerableOrIEnumerableOfT() == true &&
                    methodDeclaration.ContainsYield())
                {
                    return(Success(SyntaxKind.YieldBreakStatement, parent));
                }

                break;
            }

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

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (localFunction.ReturnsVoid())
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (localFunction.Modifiers.Contains(SyntaxKind.AsyncKeyword) &&
                    taskSymbol != null &&
                    semanticModel.GetDeclaredSymbol(localFunction, cancellationToken)?
                    .ReturnType
                    .Equals(taskSymbol) == true)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (semanticModel.GetDeclaredSymbol(localFunction, cancellationToken)?
                    .ReturnType
                    .OriginalDefinition
                    .IsIEnumerableOrIEnumerableOfT() == true &&
                    localFunction.ContainsYield())
                {
                    return(Success(SyntaxKind.YieldBreakStatement, parent));
                }

                break;
            }

            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.ParenthesizedLambdaExpression:
            {
                var anonymousFunction = (AnonymousFunctionExpressionSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                var methodSymbol = semanticModel.GetSymbol(anonymousFunction, cancellationToken) as IMethodSymbol;

                if (methodSymbol == null)
                {
                    return(Fail(parent));
                }

                if (methodSymbol.ReturnsVoid)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (anonymousFunction.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword &&
                    methodSymbol.ReturnType.Equals(taskSymbol))
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                break;
            }

            case SyntaxKind.IfStatement:
            {
                ifStatement = (IfStatementSyntax)parent;

                if (ifStatement.Parent is ElseClauseSyntax elseClause)
                {
                    if (ifStatement.Else != null)
                    {
                        return(Fail(parent));
                    }

                    if (!options.AllowIfInsideIfElse())
                    {
                        return(Fail(parent));
                    }

                    return(AnalyzeCore(ifStatement.GetTopmostIf(), semanticModel, jumpKind, options, taskSymbol, cancellationToken));
                }
                else
                {
                    if (!IsFixable(ifStatement))
                    {
                        return(Fail(parent));
                    }

                    if (!options.AllowNestedFix())
                    {
                        return(Fail(parent));
                    }

                    return(AnalyzeCore(ifStatement, semanticModel, jumpKind, options, taskSymbol, cancellationToken));
                }
            }

            case SyntaxKind.ElseClause:
            {
                if (!options.AllowIfInsideIfElse())
                {
                    return(Fail(parent));
                }

                var elseClause = (ElseClauseSyntax)parent;

                return(AnalyzeCore(elseClause.GetTopmostIf(), semanticModel, jumpKind, options, taskSymbol, cancellationToken));
            }
            }

            return(Fail(parent));
        }
Example #28
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);
        }
Example #29
0
        private static void AnalyzeIsExpression(SyntaxNodeAnalysisContext context)
        {
            var isExpression = (BinaryExpressionSyntax)context.Node;

            IsExpressionInfo isExpressionInfo = SyntaxInfo.IsExpressionInfo(isExpression);

            if (!isExpressionInfo.Success)
            {
                return;
            }

            ExpressionSyntax expression = isExpressionInfo.Expression;

            var identifierName = expression as IdentifierNameSyntax;

            if (identifierName == null)
            {
                if (expression.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var memberAccess = (MemberAccessExpressionSyntax)expression;

                    if (memberAccess.Expression.IsKind(SyntaxKind.ThisExpression))
                    {
                        identifierName = memberAccess.Name as IdentifierNameSyntax;
                    }
                }

                if (identifierName == null)
                {
                    return;
                }
            }

            ExpressionSyntax left = isExpression.WalkUpParentheses();

            SyntaxNode node = left.Parent;

            if (node.ContainsDiagnostics)
            {
                return;
            }

            switch (node.Kind())
            {
            case SyntaxKind.LogicalAndExpression:
            {
                var logicalAnd = (BinaryExpressionSyntax)node;

                if (left != logicalAnd.Left)
                {
                    return;
                }

                ExpressionSyntax right = logicalAnd.Right;

                if (right == null)
                {
                    return;
                }

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

                if (semanticModel.GetTypeSymbol(isExpressionInfo.Type, cancellationToken).IsNullableType())
                {
                    return;
                }

                if (logicalAnd.Parent.IsInExpressionTree(semanticModel, cancellationToken))
                {
                    return;
                }

                if (!IsFixable(right, identifierName, semanticModel, cancellationToken))
                {
                    return;
                }

                DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UsePatternMatchingInsteadOfIsAndCast, logicalAnd);
                break;
            }

            case SyntaxKind.IfStatement:
            {
                var ifStatement = (IfStatementSyntax)node;

                if (left != ifStatement.Condition)
                {
                    return;
                }

                StatementSyntax statement = ifStatement.Statement;

                if (statement == null)
                {
                    return;
                }

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

                if (semanticModel.GetTypeSymbol(isExpressionInfo.Type, cancellationToken).IsNullableType())
                {
                    return;
                }

                if (!IsFixable(statement, identifierName, semanticModel, cancellationToken))
                {
                    return;
                }

                DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UsePatternMatchingInsteadOfIsAndCast, ifStatement.Condition);
                break;
            }
            }
        }
        public static AccessibilityFlags GetAllowedAccessibilityFlags(MemberDeclarationSelection selectedMembers, bool allowOverride = false)
        {
            if (selectedMembers.Count < 2)
            {
                return(AccessibilityFlags.None);
            }

            var allFlags = AccessibilityFlags.None;

            AccessibilityFlags allowedFlags = AccessibilityFlags.Public
                                              | AccessibilityFlags.Internal
                                              | AccessibilityFlags.Protected
                                              | AccessibilityFlags.Private;

            foreach (MemberDeclarationSyntax member in selectedMembers)
            {
                Accessibility accessibility = SyntaxInfo.AccessibilityInfo(member).Accessibility;

                if (accessibility == Accessibility.NotApplicable)
                {
                    accessibility = member.GetDefaultExplicitAccessibility();

                    if (accessibility == Accessibility.NotApplicable)
                    {
                        return(AccessibilityFlags.None);
                    }
                }

                AccessibilityFlags flag = accessibility.GetAccessibilityFlag();

                switch (accessibility)
                {
                case Accessibility.Private:
                case Accessibility.Protected:
                case Accessibility.ProtectedAndInternal:
                case Accessibility.ProtectedOrInternal:
                case Accessibility.Internal:
                case Accessibility.Public:
                {
                    allFlags |= flag;
                    break;
                }

                default:
                {
                    Debug.Fail(accessibility.ToString());
                    return(AccessibilityFlags.None);
                }
                }

                foreach (Accessibility accessibility2 in Accessibilities)
                {
                    if (accessibility != accessibility2 &&
                        !CSharpUtility.IsAllowedAccessibility(member, accessibility2, allowOverride: allowOverride))
                    {
                        allowedFlags &= ~accessibility2.GetAccessibilityFlag();
                    }
                }
            }

            switch (allFlags)
            {
            case AccessibilityFlags.Private:
            case AccessibilityFlags.Protected:
            case AccessibilityFlags.Internal:
            case AccessibilityFlags.Public:
            {
                allowedFlags &= ~allFlags;
                break;
            }
            }

            return(allowedFlags);
        }