@NotNull public static Nullness checkNullness( @Nullable final PsiVariable variable, @Nullable final PsiElement context) { if (variable == null || context == null) return Nullness.UNKNOWN; final PsiElement codeBlock = DfaPsiUtil.getEnclosingCodeBlock(variable, context); if (codeBlock == null) { return Nullness.UNKNOWN; } final ValuableInstructionVisitor visitor = new ValuableInstructionVisitor(context); RunnerResult result = new ValuableDataFlowRunner().analyzeMethod(codeBlock, visitor); if (result != RunnerResult.OK) { return Nullness.UNKNOWN; } if (visitor.myNulls.contains(variable) && !visitor.myNotNulls.contains(variable)) return Nullness.NULLABLE; if (visitor.myNotNulls.contains(variable) && !visitor.myNulls.contains(variable)) return Nullness.NOT_NULL; return Nullness.UNKNOWN; }
@Nullable("null means DFA analysis has failed (too complex to analyze)") public static Collection<PsiExpression> getCachedVariableValues( @Nullable final PsiVariable variable, @Nullable final PsiElement context) { if (variable == null || context == null) return Collections.emptyList(); CachedValue<MultiValuesMap<PsiVariable, PsiExpression>> cachedValue = context.getUserData(DFA_VARIABLE_INFO_KEY); if (cachedValue == null) { final PsiElement codeBlock = DfaPsiUtil.getEnclosingCodeBlock(variable, context); cachedValue = CachedValuesManager.getManager(context.getProject()) .createCachedValue( new CachedValueProvider<MultiValuesMap<PsiVariable, PsiExpression>>() { @Override public Result<MultiValuesMap<PsiVariable, PsiExpression>> compute() { final MultiValuesMap<PsiVariable, PsiExpression> result; if (codeBlock == null) { result = null; } else { final ValuableInstructionVisitor visitor = new ValuableInstructionVisitor(context); RunnerResult runnerResult = new ValuableDataFlowRunner().analyzeMethod(codeBlock, visitor); if (runnerResult == RunnerResult.OK) { result = visitor.myValues; } else { result = TOO_COMPLEX; } } return new Result<MultiValuesMap<PsiVariable, PsiExpression>>( result, variable); } }, false); context.putUserData(DFA_VARIABLE_INFO_KEY, cachedValue); } final MultiValuesMap<PsiVariable, PsiExpression> value = cachedValue.getValue(); if (value == TOO_COMPLEX) return null; final Collection<PsiExpression> expressions = value == null ? null : value.get(variable); return expressions == null ? Collections.<PsiExpression>emptyList() : expressions; }