Ejemplo n.º 1
0
            public ICollection <ISymbol> TryGetSymbolsForCaseClauses([NotNull] SwitchAnalysisContext analysisContext)
            {
                IEnumerable <ISingleValueCaseClauseOperation> caseClauses =
                    analysisContext.SwitchStatement.Cases.SelectMany(@case =>
                                                                     @case.Clauses.OfType <ISingleValueCaseClauseOperation>());

                foreach (ISingleValueCaseClauseOperation caseClause in caseClauses)
                {
                    analysisContext.CancellationToken.ThrowIfCancellationRequested();

                    if (ProcessAsLiteralSyntax(analysisContext, caseClause) || ProcessAsField(caseClause) ||
                        ProcessAsConversion(analysisContext, caseClause))
                    {
                        continue;
                    }

#pragma warning disable AV2310 // Code blocks should not contain inline comments
                    // Switch statements with non-constant case expressions are not supported
                    // because they make completion analysis non-trivial.
#pragma warning restore AV2310 // Code blocks should not contain inline comments
                    return(null);
                }

                return(caseClauseValues);
            }
Ejemplo n.º 2
0
            public ICollection <ISymbol> TryGetSymbolsForCaseClauses([NotNull] SwitchAnalysisContext analysisContext)
            {
                IEnumerable <ISingleValueCaseClauseOperation> caseClauses =
                    analysisContext.SwitchStatement.Cases.SelectMany(@case =>
                                                                     @case.Clauses.OfType <ISingleValueCaseClauseOperation>());

                foreach (ISingleValueCaseClauseOperation caseClause in caseClauses)
                {
                    analysisContext.CancellationToken.ThrowIfCancellationRequested();

                    if (ProcessAsLiteralSyntax(analysisContext, caseClause) || ProcessAsField(caseClause) ||
                        ProcessAsConversion(analysisContext, caseClause))
                    {
                        continue;
                    }

                    // Switch statements with non-constant case expressions are not supported
                    // because they make exhaustiveness analysis non-trivial.

#pragma warning disable AV1135 // Do not return null for strings, collections or tasks
                    return(null);

#pragma warning restore AV1135 // Do not return null for strings, collections or tasks
                }

                return(caseClauseValues);
            }
Ejemplo n.º 3
0
        private bool?HasCaseClausesFor([NotNull][ItemCanBeNull] ICollection <ISymbol> expectedValues,
                                       [NotNull] SwitchAnalysisContext analysisContext)
        {
            var collector = new CaseClauseCollector();
            ICollection <ISymbol> caseClauseValues = collector.TryGetSymbolsForCaseClauses(analysisContext);

            return(caseClauseValues == null ? null : HasCaseClauseForExpectedValues(expectedValues, caseClauseValues));
        }
Ejemplo n.º 4
0
 private bool ProcessLiteralSyntaxAsFalseKeyword([NotNull] SwitchAnalysisContext analysisContext,
                                                 [NotNull] LiteralExpressionSyntax literalSyntax)
 {
     if (literalSyntax.Token.IsKind(SyntaxKind.FalseKeyword))
     {
         caseClauseValues.Add(analysisContext.BooleanFalse);
         return(true);
     }
     return(false);
 }
Ejemplo n.º 5
0
        private static void AnalyzeSwitchExhaustiveness([NotNull] ISwitchOperation switchStatement,
                                                        [NotNull] INamedTypeSymbol systemBoolean, OperationAnalysisContext context)
        {
            var analysisContext = new SwitchAnalysisContext(switchStatement, systemBoolean, context);

            if (IsSwitchExhaustive(analysisContext) == false)
            {
                Location location = switchStatement.TryGetLocationForKeyword() ?? switchStatement.Syntax.GetLocation();
                context.ReportDiagnostic(Diagnostic.Create(Rule, location));
            }
        }
Ejemplo n.º 6
0
            private bool ProcessAsLiteralSyntax([NotNull] SwitchAnalysisContext analysisContext,
                                                [NotNull] ISingleValueCaseClause caseClause)
            {
                if (caseClause.Value.Syntax is LiteralExpressionSyntax literalSyntax)
                {
                    if (ProcessLiteralSyntaxAsTrueKeyword(analysisContext, literalSyntax) ||
                        ProcessLiteralSyntaxAsFalseKeyword(analysisContext, literalSyntax) ||
                        ProcessLiteralSyntaxAsNullKeyword(literalSyntax))
                    {
                        return(true);
                    }
                }

                return(false);
            }
Ejemplo n.º 7
0
            private bool ProcessAsConversion([NotNull] SwitchAnalysisContext analysisContext,
                                             [NotNull] ISingleValueCaseClause caseClause)
            {
                var conversion   = caseClause.Value as IConversionExpression;
                var memberSyntax = conversion?.Syntax as MemberAccessExpressionSyntax;

                IFieldSymbol field = analysisContext.GetFieldOrNull(memberSyntax);

                if (field != null)
                {
                    caseClauseValues.Add(field);
                    return(true);
                }

                return(false);
            }
        private bool?IsSwitchCompleteForBooleanTypes([NotNull] IdentifierInfo identifierInfo,
                                                     [NotNull] SwitchAnalysisContext analysisContext)
        {
            bool isBoolean         = identifierInfo.Type.SpecialType == SpecialType.System_Boolean;
            bool isNullableBoolean = identifierInfo.Type.IsNullableBoolean();

            if (isBoolean || isNullableBoolean)
            {
                ImmutableArray <ISymbol> possibleValues = isBoolean
                    ? ImmutableArray.Create(analysisContext.BooleanTrue, analysisContext.BooleanFalse)
                    : ImmutableArray.Create(analysisContext.BooleanTrue, analysisContext.BooleanFalse, null);

                return(HasCaseClausesFor(possibleValues, analysisContext));
            }

            return(null);
        }
        private void AnalyzeSwitchStatement(OperationAnalysisContext context, [NotNull] INamedTypeSymbol systemBoolean)
        {
            var switchStatement = (ISwitchStatement)context.Operation;

            if (HasDefaultCase(switchStatement))
            {
                return;
            }

            context.CancellationToken.ThrowIfCancellationRequested();

            var analysisContext = new SwitchAnalysisContext(switchStatement, systemBoolean, context);

            if (IsSwitchComplete(analysisContext) == false)
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule, switchStatement.Syntax.GetLocation()));
            }
        }
        private bool?HasCaseClausesFor([NotNull][ItemCanBeNull] ICollection <ISymbol> expectedValues,
                                       [NotNull] SwitchAnalysisContext analysisContext)
        {
            ICollection <ISymbol> caseClauseValues = TryGetSymbolsForCaseClauses(analysisContext);

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

            foreach (ISymbol expectedValue in expectedValues)
            {
                if (!caseClauseValues.Contains(expectedValue))
                {
                    return(false);
                }
            }

            return(true);
        }
        private bool?IsSwitchCompleteForEnumerationTypes([NotNull] IdentifierInfo identifierInfo,
                                                         [NotNull] SwitchAnalysisContext analysisContext)
        {
            bool isEnumeration = identifierInfo.Type.BaseType != null &&
                                 identifierInfo.Type.BaseType.SpecialType == SpecialType.System_Enum;
            bool isNullableEnumeration = identifierInfo.Type.IsNullableEnumeration();

            if (isEnumeration || isNullableEnumeration)
            {
                ITypeSymbol enumType = isEnumeration
                    ? (INamedTypeSymbol)identifierInfo.Type
                    : ((INamedTypeSymbol)identifierInfo.Type).TypeArguments[0];

                ISymbol[] possibleValues = isEnumeration
                    ? enumType.GetMembers().OfType <IFieldSymbol>().Cast <ISymbol>().ToArray()
                    : enumType.GetMembers().OfType <IFieldSymbol>().Concat(NullSymbolArray).ToArray();

                return(HasCaseClausesFor(possibleValues, analysisContext));
            }

            return(null);
        }
 private bool?IsSwitchComplete([NotNull] SwitchAnalysisContext analysisContext, [NotNull] IdentifierInfo identifierInfo)
 {
     return(IsSwitchCompleteForBooleanTypes(identifierInfo, analysisContext) ??
            IsSwitchCompleteForEnumerationTypes(identifierInfo, analysisContext));
 }
        private bool?IsSwitchComplete([NotNull] SwitchAnalysisContext analysisContext)
        {
            IdentifierInfo identifierInfo = analysisContext.SwitchStatement.Value.TryGetIdentifierInfo();

            return(identifierInfo != null?IsSwitchComplete(analysisContext, identifierInfo) : null);
        }
        private ICollection <ISymbol> TryGetSymbolsForCaseClauses([NotNull] SwitchAnalysisContext analysisContext)
        {
            var caseClauseValues = new HashSet <ISymbol>();

            IEnumerable <ISingleValueCaseClause> caseClauses =
                analysisContext.SwitchStatement.Cases.SelectMany(@case => @case.Clauses.OfType <ISingleValueCaseClause>());

            foreach (ISingleValueCaseClause caseClause in caseClauses)
            {
                analysisContext.CancellationToken.ThrowIfCancellationRequested();

                var literalSyntax = caseClause.Value.Syntax as LiteralExpressionSyntax;
                if (literalSyntax != null)
                {
                    if (literalSyntax.Token.IsKind(SyntaxKind.TrueKeyword))
                    {
                        caseClauseValues.Add(analysisContext.BooleanTrue);
                        continue;
                    }

                    if (literalSyntax.Token.IsKind(SyntaxKind.FalseKeyword))
                    {
                        caseClauseValues.Add(analysisContext.BooleanFalse);
                        continue;
                    }

                    if (literalSyntax.Token.IsKind(SyntaxKind.NullKeyword))
                    {
                        caseClauseValues.Add(null);
                        continue;
                    }
                }

                var enumField = caseClause.Value as IFieldReferenceExpression;
                if (enumField != null)
                {
                    caseClauseValues.Add(enumField.Field);
                    continue;
                }

                var conversion   = caseClause.Value as IConversionExpression;
                var memberSyntax = conversion?.Syntax as MemberAccessExpressionSyntax;
                if (memberSyntax != null)
                {
                    IFieldSymbol field = analysisContext.GetFieldOrNull(memberSyntax);
                    if (field != null)
                    {
                        caseClauseValues.Add(field);
                        continue;
                    }
                }

#pragma warning disable AV2310 // Code blocks should not contain inline comments
                // Switch statements with non-constant case expressions are not supported
                // because they make completion analysis non-trivial.
#pragma warning restore AV2310 // Code blocks should not contain inline comments
                return(null);
            }

            return(caseClauseValues);
        }
Ejemplo n.º 15
0
 private static bool?IsSwitchExhaustive([NotNull] SwitchAnalysisContext analysisContext,
                                        [NotNull] IdentifierInfo identifierInfo)
 {
     return(IsSwitchExhaustiveForBooleanTypes(identifierInfo, analysisContext) ??
            IsSwitchExhaustiveForEnumerationTypes(identifierInfo, analysisContext));
 }