Esempio n. 1
0
        static CSharpControlFlowNullReferenceState GetExpressionNullReferenceState(
            [NotNull] NullnessProvider nullnessProvider,
            [NotNull] CSharpControlFlowGraphInspector inspector,
            [NotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions,
            ICSharpExpression expression)
        {
            switch (expression)
            {
            case IReferenceExpression referenceExpression:
                var nullReferenceState = inspector.GetExpressionNullReferenceState(referenceExpression, true);

                if (nullReferenceState == CSharpControlFlowNullReferenceState.UNKNOWN)
                {
                    return(GetExpressionNullReferenceStateByAnnotations(nullnessProvider, referenceExpression));
                }

                return(nullReferenceState);

            case IAsExpression asExpression when alwaysSuccessTryCastExpressions.Contains(asExpression):
                return(CSharpControlFlowNullReferenceState.NOT_NULL);

            case IObjectCreationExpression _: return(CSharpControlFlowNullReferenceState.NOT_NULL);

            case IInvocationExpression invocationExpression:
                if (invocationExpression.InvokedExpression is IReferenceExpression invokedExpression)
                {
                    return(GetExpressionNullReferenceStateByAnnotations(nullnessProvider, invokedExpression));
                }

                goto default;

            default: return(CSharpControlFlowNullReferenceState.UNKNOWN);
            }
        }
        CSharpControlFlowNullReferenceState GetExpressionNullReferenceState(
            [CanBeNull] CSharpCompilerNullableInspector nullabilityInspector,
            [CanBeNull] CSharpControlFlowGraphInspector inspector,
            [CanBeNull][ItemNotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions,
            [NotNull] ICSharpExpression expression)
        {
            if (nullabilityInspector != null)
            {
                return(GetExpressionNullReferenceStateByNullableContext(nullabilityInspector, expression));
            }

            Debug.Assert(inspector != null);
            Debug.Assert(alwaysSuccessTryCastExpressions != null);

            while (true)
            {
                switch (expression)
                {
                case IReferenceExpression referenceExpression:
                    if (referenceExpression is IConditionalAccessExpression conditionalAccessExpression &&
                        conditionalAccessExpression.HasConditionalAccessSign)
                    {
                        var referenceState = GetExpressionNullReferenceStateByAnnotations(referenceExpression);
                        if (referenceState == CSharpControlFlowNullReferenceState.NOT_NULL)
                        {
                            expression = conditionalAccessExpression.ConditionalQualifier;
                            continue;
                        }
                    }

                    var nullReferenceState = inspector.GetExpressionNullReferenceState(referenceExpression, true);

                    if (nullReferenceState == CSharpControlFlowNullReferenceState.UNKNOWN)
                    {
                        nullReferenceState = GetExpressionNullReferenceStateByAnnotations(referenceExpression);
                    }

                    return(nullReferenceState);

                case IAsExpression asExpression when alwaysSuccessTryCastExpressions.Contains(asExpression):
                    return(CSharpControlFlowNullReferenceState.NOT_NULL);

                case IObjectCreationExpression _: return(CSharpControlFlowNullReferenceState.NOT_NULL);

                case IInvocationExpression invocationExpression:
                    if (invocationExpression.InvokedExpression is IReferenceExpression invokedExpression)
                    {
                        return(GetExpressionNullReferenceStateByAnnotations(invokedExpression));
                    }

                    goto default;

                default: return(CSharpControlFlowNullReferenceState.UNKNOWN);
                }
            }
        }
Esempio n. 3
0
        static void AnalyzeWhenExpressionIsKnownToBeNullOrNotNull(
            [NotNull] IHighlightingConsumer context,
            [NotNull] NullnessProvider nullnessProvider,
            [NotNull] CSharpControlFlowGraphInspector inspector,
            [NotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions,
            [NotNull] Assertion assertion,
            bool isKnownToBeNull)
        {
            if (assertion is AssertionStatement assertionStatement)
            {
                // pattern: Assert(null);
                Debug.Assert(CSharpTokenType.NULL_KEYWORD != null);
                if (isKnownToBeNull && IsLiteral(assertionStatement.Expression, CSharpTokenType.NULL_KEYWORD))
                {
                    context.AddHighlighting(
                        new RedundantAssertionStatementHighlighting(
                            "Assertion is redundant because the expression is always null.",
                            assertionStatement));
                }

                // pattern: Assert(x); when x is known to be null or not null
                switch (GetExpressionNullReferenceState(nullnessProvider, inspector, alwaysSuccessTryCastExpressions, assertionStatement.Expression))
                {
                case CSharpControlFlowNullReferenceState.NOT_NULL:
                    if (!isKnownToBeNull)
                    {
                        context.AddHighlighting(
                            new RedundantAssertionStatementHighlighting(
                                "Assertion is redundant because the expression is never null.",
                                assertionStatement));
                    }
                    break;

                case CSharpControlFlowNullReferenceState.NULL:
                    if (isKnownToBeNull)
                    {
                        context.AddHighlighting(
                            new RedundantAssertionStatementHighlighting(
                                "Assertion is redundant because the expression is always null.",
                                assertionStatement));
                    }
                    break;
                }
            }

            if (!isKnownToBeNull &&
                assertion is InlineAssertion inlineAssertion &&
                GetExpressionNullReferenceState(nullnessProvider, inspector, alwaysSuccessTryCastExpressions, inlineAssertion.QualifierExpression) ==
                CSharpControlFlowNullReferenceState.NOT_NULL)
            {
                context.AddHighlighting(
                    new RedundantInlineAssertionHighlighting("Assertion is redundant because the expression is never null.", inlineAssertion));
            }
        }
        /// <summary>Inspects the specified function.</summary>
        /// <param name="function">The function.</param>
        /// <returns>Returns the code annotation attribute.</returns>
        private static CodeAnnotationAttribute Inspect([NotNull] ICSharpFunctionDeclaration function)
        {
            if (function == null)
            {
                throw new ArgumentNullException("function");
            }

            var project = function.GetProject();

            if (project == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var projectFile = project.ProjectFile;

            if (projectFile == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            if (!function.DeclaredElement.ReturnType.IsReferenceType())
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            // return CodeAnnotationAttribute.NotNull;
            new AllNonQualifiedSignatureReferencesResolver().Process(function);
            var builder = new CSharpControlFlowBuilder();
            var graph   = builder.GraphFromNode(function, null, true) as ICSharpControlFlowGraph;

            if (graph == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var graphInspector = CSharpControlFlowGraphInspector.Inspect(graph, ValueAnalysisMode.OPTIMISTIC);

            switch (graphInspector.SuggestReturnValueAnnotationAttribute)
            {
            case CSharpControlFlowNullReferenceState.NOT_NULL:
                return(CodeAnnotationAttribute.NotNull);

            case CSharpControlFlowNullReferenceState.NULL:
                return(CodeAnnotationAttribute.CanBeNull);

            case CSharpControlFlowNullReferenceState.MAY_BE_NULL:
                return(CodeAnnotationAttribute.CanBeNull);
            }

            return(CodeAnnotationAttribute.NotSet);
        }
        public ICSharpControlFlowAnalysisResult InspectControlFlowGraph()
        {
            if (!_controlFlowGraphInspected)
            {
                ICSharpControlFlowGraph controlFlowGraph = this.GetControlFlowGraph();
                if (controlFlowGraph != null)
                {
                    ValueAnalysisMode analysisMode = this.SelectedElement.NotNull("context != null").GetSettingsStore().GetValue(HighlightingSettingsAccessor.ValueAnalysisMode);
                    CSharpControlFlowGraphInspector flowGraphInspector = CSharpControlFlowGraphInspector.Inspect(controlFlowGraph, analysisMode);
                    if (!flowGraphInspector.HasComplexityOverflow)
                    {
                        _cachedControlFlowGraphInspectionResult = flowGraphInspector;
                    }
                }

                _controlFlowGraphInspected = true;
            }

            return(_cachedControlFlowGraphInspectionResult);
        }
Esempio n. 6
0
        static Location?TryGetLocation([NotNull] ICSharpTreeNode element, [NotNull] ElementProblemAnalyzerData data)
        {
            switch (element.GetContainingFunctionLikeDeclarationOrClosure())
            {
            case IAccessorDeclaration accessorDeclaration:
                switch (accessorDeclaration.Kind)
                {
                case AccessorKind.GETTER:
                    switch (accessorDeclaration.Parent)
                    {
                    case IPropertyDeclaration _:
                        return(Location.PropertyGetter);

                    case IIndexerDeclaration _:
                        return(Location.IndexerGetter);
                    }
                    break;

                case AccessorKind.ADDER:
                case AccessorKind.REMOVER:
                    return(Location.EventAccessor);
                }
                break;

            case IPropertyDeclaration _:
                return(Location.PropertyGetter);

            case IIndexerDeclaration _:
                return(Location.IndexerGetter);

            case IMethodDeclaration methodDeclaration when methodDeclaration.DeclaredElement != null:
                var psiModule = element.GetPsiModule();

                var objectClass = TypeElementUtil.GetTypeElementByClrName(PredefinedType.OBJECT_FQN, psiModule).AssertNotNull();
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(GetMethod(objectClass, nameof(object.Equals))))
                {
                    return(Location.EqualsMethod);
                }
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(GetMethod(objectClass, nameof(GetHashCode))))
                {
                    return(Location.GetHashCodeMethod);
                }
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(GetMethod(objectClass, nameof(ToString))))
                {
                    return(Location.ToStringMethod);
                }

                if (methodDeclaration.DeclaredElement.OverridesOrImplements(
                        GetMethod(
                            TypeElementUtil.GetTypeElementByClrName(PredefinedType.GENERIC_IEQUATABLE_FQN, psiModule).AssertNotNull(),
                            nameof(IEquatable <int> .Equals))))
                {
                    return(Location.EqualsMethod);
                }

                var equalityComparerGenericInterface = TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.IEqualityComparerGeneric, psiModule)
                                                       .AssertNotNull();
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(
                        GetMethod(equalityComparerGenericInterface, nameof(IEqualityComparer <int> .Equals))))
                {
                    return(Location.EqualsMethodWithParameters);
                }
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(
                        GetMethod(equalityComparerGenericInterface, nameof(IEqualityComparer <int> .GetHashCode))))
                {
                    return(Location.GetHashCodeMethodWithParameter);
                }

                var equalityComparerInterface =
                    TypeElementUtil.GetTypeElementByClrName(ClrTypeNames.IEqualityComparer, psiModule).AssertNotNull();
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(
                        GetMethod(equalityComparerInterface, nameof(IEqualityComparer.Equals))))
                {
                    return(Location.EqualsMethodWithParameters);
                }
                if (methodDeclaration.DeclaredElement.OverridesOrImplements(
                        GetMethod(equalityComparerInterface, nameof(IEqualityComparer.GetHashCode))))
                {
                    return(Location.GetHashCodeMethodWithParameter);
                }

                if (methodDeclaration.DeclaredElement.OverridesOrImplements(
                        GetMethod(
                            TypeElementUtil.GetTypeElementByClrName(PredefinedType.IDISPOSABLE_FQN, psiModule).AssertNotNull(),
                            nameof(IDisposable.Dispose))))
                {
                    return(Location.DisposeMethod);
                }

                if (methodDeclaration.DeclaredElement.ShortName == disposeMethodName && methodDeclaration.DeclaredElement.Parameters.Count == 1)
                {
                    var parameter = methodDeclaration.DeclaredElement.Parameters[0];
                    if (parameter != null && parameter.Type.IsBool())
                    {
                        var controlFlowGraph = (ICSharpControlFlowGraph)ControlFlowBuilder.GetGraph(methodDeclaration);

                        var controlFlowEdge = controlFlowGraph?.ReachableExits.FirstOrDefault(
                            e => e?.Type == ControlFlowEdgeType.THROW && e.Source.SourceElement == element);

                        if (controlFlowEdge != null)
                        {
                            var inspector          = CSharpControlFlowGraphInspector.Inspect(controlFlowGraph, data.GetValueAnalysisMode());
                            var controlFlowContext = inspector.GetContext(controlFlowEdge);
                            var variableInfo       = inspector.FindVariableInfo(parameter);
                            if (variableInfo != null)
                            {
                                var variableValue = controlFlowContext?.GetVariableDefiniteState(variableInfo);
                                if (variableValue == null || variableValue == CSharpControlFlowVariableValue.FALSE)
                                {
                                    return(Location.DisposeMethodWithParameterFalseCodePath);
                                }
                            }
                        }
                    }
                }
                break;

            case IConstructorDeclaration constructorDeclaration when constructorDeclaration.IsStatic:
                return(Location.StaticConstructor);

            case IDestructorDeclaration _:
                return(Location.Finalizer);

            case ISignOperatorDeclaration signOperator:
                var tokenType = signOperator.OperatorSign?.GetTokenType();
                if (tokenType == CSharpTokenType.EQEQ || tokenType == CSharpTokenType.NE)
                {
                    return(Location.EqualityOperator);
                }
                break;

            case IConversionOperatorDeclaration conversionOperatorDeclaration
                when conversionOperatorDeclaration.Modifier?.GetTokenType() == CSharpTokenType.IMPLICIT_KEYWORD:
                return(Location.ImplicitCastOperator);
            }

            return(null);
        }
Esempio n. 7
0
        static void AnalyzeAssertions(
            [NotNull] ElementProblemAnalyzerData data,
            [NotNull] IHighlightingConsumer consumer,
            [NotNull] ICSharpTreeNode rootNode,
            [NotNull] ICSharpControlFlowGraph controlFlowGraph)
        {
            var codeAnnotationsCache = rootNode.GetPsiServices().GetCodeAnnotationsCache();

            var nullnessProvider = codeAnnotationsCache.GetProvider <NullnessProvider>();
            var assertionMethodAnnotationProvider    = codeAnnotationsCache.GetProvider <AssertionMethodAnnotationProvider>();
            var assertionConditionAnnotationProvider = codeAnnotationsCache.GetProvider <AssertionConditionAnnotationProvider>();

            var assertions = Assertion.CollectAssertions(assertionMethodAnnotationProvider, assertionConditionAnnotationProvider, rootNode);

            assertions.ExceptWith(
                from highlightingInfo in consumer.Highlightings
                where highlightingInfo != null
                let redundantAssertionHighlighting = highlightingInfo.Highlighting as RedundantAssertionHighlighting
                                                     where redundantAssertionHighlighting != null
                                                     select redundantAssertionHighlighting.Assertion);

            if (assertions.Count == 0)
            {
                return; // no (new) assertions found
            }

            var inspector = CSharpControlFlowGraphInspector.Inspect(controlFlowGraph, data.GetValueAnalysisMode());

            var alwaysSuccessTryCastExpressions = new HashSet <IAsExpression>(inspector.AlwaysSuccessTryCastExpressions ?? new IAsExpression[] { });

            foreach (var assertion in assertions)
            {
                switch (assertion.AssertionConditionType)
                {
                case AssertionConditionType.IS_TRUE:
                    AnalyzeWhenExpressionIsKnownToBeTrueOrFalse(
                        consumer,
                        nullnessProvider,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        true);
                    break;

                case AssertionConditionType.IS_FALSE:
                    AnalyzeWhenExpressionIsKnownToBeTrueOrFalse(
                        consumer,
                        nullnessProvider,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        false);
                    break;

                case AssertionConditionType.IS_NOT_NULL:
                    AnalyzeWhenExpressionIsKnownToBeNullOrNotNull(
                        consumer,
                        nullnessProvider,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        false);
                    break;

                case AssertionConditionType.IS_NULL:
                    AnalyzeWhenExpressionIsKnownToBeNullOrNotNull(
                        consumer,
                        nullnessProvider,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        true);
                    break;
                }
            }
        }
Esempio n. 8
0
        static void AnalyzeWhenExpressionIsKnownToBeTrueOrFalse(
            [NotNull] IHighlightingConsumer context,
            [NotNull] NullnessProvider nullnessProvider,
            [NotNull] CSharpControlFlowGraphInspector inspector,
            [NotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions,
            [NotNull] Assertion assertion,
            bool isKnownToBeTrue)
        {
            if (assertion is AssertionStatement assertionStatement)
            {
                // pattern: Assert(true); or Assert(false);
                Debug.Assert(CSharpTokenType.TRUE_KEYWORD != null);
                Debug.Assert(CSharpTokenType.FALSE_KEYWORD != null);
                if (IsLiteral(assertionStatement.Expression, isKnownToBeTrue ? CSharpTokenType.TRUE_KEYWORD : CSharpTokenType.FALSE_KEYWORD))
                {
                    context.AddHighlighting(
                        new RedundantAssertionStatementHighlighting(
                            $"Assertion is redundant because the expression is always {(isKnownToBeTrue ? "true" : "false")}.",
                            assertionStatement));
                }

                if (assertionStatement.Expression is IEqualityExpression equalityExpression)
                {
                    // pattern: Assert(x != null); when x is known to be null or not null
                    Debug.Assert(CSharpTokenType.NULL_KEYWORD != null);
                    var expression = TryGetOtherOperand(equalityExpression, EqualityExpressionType.NE, CSharpTokenType.NULL_KEYWORD);
                    if (expression != null)
                    {
                        switch (GetExpressionNullReferenceState(nullnessProvider, inspector, alwaysSuccessTryCastExpressions, expression))
                        {
                        case CSharpControlFlowNullReferenceState.NOT_NULL:
                            if (isKnownToBeTrue)
                            {
                                context.AddHighlighting(
                                    new RedundantAssertionStatementHighlighting(
                                        "Assertion is redundant because the expression is always true.",
                                        assertionStatement));
                            }
                            break;

                        case CSharpControlFlowNullReferenceState.NULL:
                            if (!isKnownToBeTrue)
                            {
                                context.AddHighlighting(
                                    new RedundantAssertionStatementHighlighting(
                                        "Assertion is redundant because the expression is always false.",
                                        assertionStatement));
                            }
                            break;
                        }
                    }

                    // pattern: Assert(x == null); when x is known to be null or not null
                    expression = TryGetOtherOperand(equalityExpression, EqualityExpressionType.EQEQ, CSharpTokenType.NULL_KEYWORD);
                    if (expression != null)
                    {
                        switch (GetExpressionNullReferenceState(nullnessProvider, inspector, alwaysSuccessTryCastExpressions, expression))
                        {
                        case CSharpControlFlowNullReferenceState.NOT_NULL:
                            if (!isKnownToBeTrue)
                            {
                                context.AddHighlighting(
                                    new RedundantAssertionStatementHighlighting(
                                        "Assertion is redundant because the expression is always false.",
                                        assertionStatement));
                            }
                            break;

                        case CSharpControlFlowNullReferenceState.NULL:
                            if (isKnownToBeTrue)
                            {
                                context.AddHighlighting(
                                    new RedundantAssertionStatementHighlighting(
                                        "Assertion is redundant because the expression is always true.",
                                        assertionStatement));
                            }
                            break;
                        }
                    }
                }
            }
        }
        void AnalyzeWhenExpressionIsKnownToBeNullOrNotNull(
            [NotNull] IHighlightingConsumer context,
            [CanBeNull] CSharpCompilerNullableInspector nullabilityInspector,
            [CanBeNull] CSharpControlFlowGraphInspector inspector,
            [CanBeNull][ItemNotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions,
            [NotNull] Assertion assertion,
            bool isKnownToBeNull)
        {
            if (assertion is AssertionStatement assertionStatement)
            {
                // pattern: Assert(null);
                Debug.Assert(CSharpTokenType.NULL_KEYWORD != null);
                if (isKnownToBeNull && IsLiteral(assertionStatement.Expression, CSharpTokenType.NULL_KEYWORD))
                {
                    context.AddHighlighting(
                        new RedundantAssertionStatementSuggestion("Assertion is redundant because the expression is null here.", assertionStatement));
                }

                // pattern: Assert(x); when x is known to be null or not null
                switch (GetExpressionNullReferenceState(
                            nullabilityInspector,
                            inspector,
                            alwaysSuccessTryCastExpressions,
                            assertionStatement.Expression))
                {
                case CSharpControlFlowNullReferenceState.NOT_NULL:
                    if (!isKnownToBeNull)
                    {
                        context.AddHighlighting(
                            new RedundantAssertionStatementSuggestion(
                                "Assertion is redundant because the expression is not null here.",
                                assertionStatement));
                    }
                    break;

                case CSharpControlFlowNullReferenceState.NULL:
                    if (isKnownToBeNull)
                    {
                        context.AddHighlighting(
                            new RedundantAssertionStatementSuggestion(
                                "Assertion is redundant because the expression is null here.",
                                assertionStatement));
                    }
                    break;
                }
            }

            if (!isKnownToBeNull)
            {
                switch (assertion)
                {
                case InlineAssertion inlineAssertion:
                    if (GetExpressionNullReferenceState(
                            nullabilityInspector,
                            inspector,
                            alwaysSuccessTryCastExpressions,
                            inlineAssertion.QualifierExpression) ==
                        CSharpControlFlowNullReferenceState.NOT_NULL)
                    {
                        context.AddHighlighting(
                            new RedundantInlineAssertionSuggestion(
                                "Assertion is redundant because the expression is not null here.",
                                inlineAssertion));
                    }
                    break;

                case NullForgivingOperation nullForgivingOperation:
                    Debug.Assert(nullForgivingOperation.SuppressNullableWarningExpression.Operand != null);

                    if (GetExpressionNullReferenceState(
                            nullabilityInspector,
                            inspector,
                            alwaysSuccessTryCastExpressions,
                            nullForgivingOperation.SuppressNullableWarningExpression.Operand) ==
                        CSharpControlFlowNullReferenceState.NOT_NULL)
                    {
                        context.AddHighlighting(
                            new RedundantNullForgivingOperatorSuggestion(
                                "Null-forgiving operator is redundant because the expression is not null here.",
                                nullForgivingOperation));
                    }
                    break;
                }
            }
        }
        void AnalyzeAssertions(
            [NotNull] ElementProblemAnalyzerData data,
            [NotNull] IHighlightingConsumer consumer,
            [NotNull] ICSharpTreeNode rootNode,
            [NotNull] ICSharpControlFlowGraph controlFlowGraph)
        {
            var assertions = Assertion.CollectAssertions(assertionMethodAnnotationProvider, assertionConditionAnnotationProvider, rootNode);

            assertions.ExceptWith(
                from highlightingInfo in consumer.Highlightings
                where highlightingInfo != null
                let redundantAssertionHighlighting = highlightingInfo.Highlighting as RedundantAssertionSuggestion
                                                     where redundantAssertionHighlighting != null
                                                     select redundantAssertionHighlighting.Assertion);

            if (assertions.Count == 0)
            {
                return; // no (new) assertions found
            }

            CSharpCompilerNullableInspector nullabilityInspector;
            CSharpControlFlowGraphInspector inspector;
            HashSet <IAsExpression>         alwaysSuccessTryCastExpressions;

            if (rootNode.IsNullableWarningsContextEnabled())
            {
                nullabilityInspector = (CSharpCompilerNullableInspector)CSharpCompilerNullableInspector.Inspect(
                    controlFlowGraph,
                    null,
                    ValueAnalysisMode.OFF); // wrong [NotNull] annotation in R# code
                inspector = null;
                alwaysSuccessTryCastExpressions = null;
            }
            else
            {
                nullabilityInspector            = null;
                inspector                       = CSharpControlFlowGraphInspector.Inspect(controlFlowGraph, data.GetValueAnalysisMode());
                alwaysSuccessTryCastExpressions =
                    new HashSet <IAsExpression>(inspector.AlwaysSuccessTryCastExpressions ?? Array.Empty <IAsExpression>());
            }

            foreach (var assertion in assertions)
            {
                switch (assertion.AssertionConditionType)
                {
                case AssertionConditionType.IS_TRUE:
                    AnalyzeWhenExpressionIsKnownToBeTrueOrFalse(
                        consumer,
                        nullabilityInspector,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        true);
                    break;

                case AssertionConditionType.IS_FALSE:
                    AnalyzeWhenExpressionIsKnownToBeTrueOrFalse(
                        consumer,
                        nullabilityInspector,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        false);
                    break;

                case AssertionConditionType.IS_NOT_NULL:
                    AnalyzeWhenExpressionIsKnownToBeNullOrNotNull(
                        consumer,
                        nullabilityInspector,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        false);
                    break;

                case AssertionConditionType.IS_NULL:
                    AnalyzeWhenExpressionIsKnownToBeNullOrNotNull(
                        consumer,
                        nullabilityInspector,
                        inspector,
                        alwaysSuccessTryCastExpressions,
                        assertion,
                        true);
                    break;
                }
            }
        }
        /// <summary>
        /// Gets the state of the expression null reference.
        /// </summary>
        /// <param name="treeNode">The element.</param>
        /// <param name="declaredElement">The declared element.</param>
        /// <param name="statement">The statement.</param>
        /// <returns>Returns the expression null reference state.</returns>
        private CodeAnnotationAttribute GetNullReferenceState(ITreeNode treeNode, IDeclaredElement declaredElement, IDeclarationStatement statement)
        {
            var project = treeNode.GetProject();

            if (project == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var projectFile = project.ProjectFile;

            if (projectFile == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var functionDeclaration = treeNode.GetContainingNode <ICSharpFunctionDeclaration>(true);

            if (functionDeclaration == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var builder = new CSharpControlFlowBuilder();
            var graph   = builder.GraphFromNode(functionDeclaration, null, true) as ICSharpControlFlowGraph;

            if (graph == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var graphInspector = CSharpControlFlowGraphInspector.Inspect(graph, ValueAnalysisMode.OPTIMISTIC);

            var position = this.FindPosition(graph.BodyElement.Children, statement);

            if (position == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            position = this.FindFollowing(position);
            if (position == null)
            {
                return(CodeAnnotationAttribute.Undefined);
            }

            var result = graphInspector.GetVariableStateAt(position, declaredElement);

            switch (result)
            {
            case CSharpControlFlowNullReferenceState.NOT_NULL:
                return(CodeAnnotationAttribute.NotNull);

            case CSharpControlFlowNullReferenceState.NULL:
                return(CodeAnnotationAttribute.CanBeNull);

            case CSharpControlFlowNullReferenceState.MAY_BE_NULL:
                return(CodeAnnotationAttribute.CanBeNull);
            }

            return(CodeAnnotationAttribute.Undefined);

            /*
             * var block = treeNode.GetContainingNode<IBlock>(true);
             * if (block == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var project = treeNode.GetProject();
             * if (project == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var projectFile = project.ProjectFile;
             * if (projectFile == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var factory = CSharpElementFactory.GetInstance(treeNode.GetPsiModule());
             * var statement = factory.CreateStatement("if(" + name + " == null) { }");
             *
             * var ifStatement = block.AddStatementAfter(statement, (ICSharpStatement)anchorStatement) as IIfStatement;
             * if (ifStatement == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var equalityExpression = ifStatement.Condition as IEqualityExpression;
             * if (equalityExpression == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var referenceExpression = equalityExpression.LeftOperand as IReferenceExpression;
             * if (referenceExpression == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var functionDeclaration = ifStatement.GetContainingNode<ICSharpFunctionDeclaration>(true);
             * if (functionDeclaration == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var graf = CSharpControlFlowBuilder.Build(functionDeclaration);
             * if (graf == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var inspect = graf.Inspect(HighlightingSettingsManager.Instance.GetValueAnalysisMode(projectFile));
             * if (inspect == null)
             * {
             * return CodeAnnotationAttribute.Undefined;
             * }
             *
             * var position = graf.AllElements.FirstOrDefault(e => e.SourceElement == treeNode);
             *
             * var result = inspect.GetVariableStateAt(position, declaredElement);
             *
             * result = inspect.GetExpressionNullReferenceState(referenceExpression, false);
             * switch (result)
             * {
             * case CSharpControlFlowNullReferenceState.NOT_NULL:
             *  return CodeAnnotationAttribute.NotNull;
             *
             * case CSharpControlFlowNullReferenceState.NULL:
             *  return CodeAnnotationAttribute.CanBeNull;
             *
             * case CSharpControlFlowNullReferenceState.MAY_BE_NULL:
             *  return CodeAnnotationAttribute.CanBeNull;
             * }
             *
             * return CodeAnnotationAttribute.Undefined;
             */
        }