@Nullable
  private Collection<DfaMemoryState> createInitialStates(
      @NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
    PsiElement container =
        PsiTreeUtil.getParentOfType(psiBlock, PsiClass.class, PsiLambdaExpression.class);
    if (container != null
        && (!(container instanceof PsiClass)
            || PsiUtil.isLocalOrAnonymousClass((PsiClass) container))) {
      final PsiElement parent = container.getParent();
      final PsiCodeBlock block = DfaPsiUtil.getTopmostBlockInSameClass(parent);
      if (block != null) {
        final RunnerResult result = analyzeMethod(block, visitor);
        if (result == RunnerResult.OK) {
          final Collection<DfaMemoryState> closureStates =
              myNestedClosures.get(DfaPsiUtil.getTopmostBlockInSameClass(psiBlock));
          if (!closureStates.isEmpty()) {
            return closureStates;
          }
        }
        return null;
      }
    }

    return Collections.singletonList(createMemoryState());
  }
  @Nullable
  private static Map<PsiExpression, PsiType> buildDataflowTypeMap(PsiExpression forPlace) {
    PsiElement scope = DfaPsiUtil.getTopmostBlockInSameClass(forPlace);
    if (scope == null) {
      PsiFile file = forPlace.getContainingFile();
      if (!(file instanceof PsiCodeFragment)) {
        return Collections.emptyMap();
      }

      scope = file;
    }

    DataFlowRunner runner =
        new DataFlowRunner() {
          @NotNull
          @Override
          protected DfaMemoryState createMemoryState() {
            return new ExpressionTypeMemoryState(getFactory());
          }
        };

    final ExpressionTypeInstructionVisitor visitor = new ExpressionTypeInstructionVisitor(forPlace);
    if (runner.analyzeMethod(scope, visitor) == RunnerResult.OK) {
      return visitor.getResult();
    }
    return null;
  }
        @Override
        protected Nullness create(MethodCallInstruction key) {
          final PsiCallExpression callExpression = key.getCallExpression();
          if (callExpression instanceof PsiNewExpression) {
            return Nullness.NOT_NULL;
          }

          return callExpression != null
              ? DfaPsiUtil.getElementNullability(
                  key.getResultType(), callExpression.resolveMethod())
              : null;
        }
  @Nullable
  private Collection<DfaMemoryState> createInitialStates(
      @NotNull PsiElement psiBlock, InstructionVisitor visitor) {
    PsiClass containingClass = PsiTreeUtil.getParentOfType(psiBlock, PsiClass.class);
    if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass)) {
      final PsiElement parent = containingClass.getParent();
      final PsiCodeBlock block = DfaPsiUtil.getTopmostBlockInSameClass(parent);
      if ((parent instanceof PsiNewExpression || parent instanceof PsiDeclarationStatement)
          && block != null) {
        final RunnerResult result = analyzeMethod(block, visitor);
        if (result == RunnerResult.OK) {
          final Collection<DfaMemoryState> closureStates =
              myNestedClosures.get(DfaPsiUtil.getTopmostBlockInSameClass(psiBlock));
          if (!closureStates.isEmpty()) {
            return closureStates;
          }
        }
        return null;
      }
    }

    return Arrays.asList(createMemoryState());
  }
  @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;
  }
 @NotNull
 public static Collection<? extends PsiElement> getPossibleInitializationElements(
     final PsiElement qualifierExpression) {
   if (qualifierExpression instanceof PsiMethodCallExpression) {
     return Collections.singletonList(qualifierExpression);
   }
   if (qualifierExpression instanceof PsiReferenceExpression) {
     final PsiElement targetElement = ((PsiReferenceExpression) qualifierExpression).resolve();
     if (!(targetElement instanceof PsiVariable)) {
       return Collections.emptyList();
     }
     final Collection<? extends PsiElement> variableValues =
         getCachedVariableValues((PsiVariable) targetElement, qualifierExpression);
     if (variableValues == null || variableValues.isEmpty()) {
       return DfaPsiUtil.getVariableAssignmentsInFile(
           (PsiVariable) targetElement, false, qualifierExpression);
     }
     return variableValues;
   }
   if (qualifierExpression instanceof PsiLiteralExpression) {
     return Collections.singletonList(qualifierExpression);
   }
   return Collections.emptyList();
 }