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); } } }
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); }
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); }
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; } } }
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; */ }