private CauseItem findNullabilityCause(MemoryStateChange factUse, DfaNullability nullability) {
    PsiExpression expression = factUse.getExpression();
    if (expression instanceof PsiTypeCastExpression) {
      MemoryStateChange operandPush = factUse.findSubExpressionPush(((PsiTypeCastExpression)expression).getOperand());
      if (operandPush != null) {
        return findNullabilityCause(operandPush, nullability);
      }
    }
    if (expression instanceof PsiMethodCallExpression call) {
      PsiMethod method = call.resolveMethod();
      CauseItem causeItem = fromMemberNullability(nullability, method, JavaElementKind.METHOD,
                                                  call.getMethodExpression().getReferenceNameElement());
      if (causeItem == null) {
        causeItem = switch (nullability) {
          case NULL, NULLABLE -> fromCallContract(factUse, call, ContractReturnValue.returnNull());
          case NOT_NULL -> fromCallContract(factUse, call, ContractReturnValue.returnNotNull());
          default -> null;
        };
      }
      if (causeItem != null) {
        return causeItem;
      }
    }
    if (expression instanceof PsiReferenceExpression) {
      PsiVariable variable = ObjectUtils.tryCast(((PsiReferenceExpression)expression).resolve(), PsiVariable.class);
      if (variable != null) {
        CauseItem causeItem = fromMemberNullability(nullability, variable, JavaElementKind.fromElement(variable), expression);
        if (causeItem != null) {
          return causeItem;
        }
      }
    }
    FactDefinition<DfaNullability> info = factUse.findFact(factUse.myTopOfStack, FactExtractor.nullability());
    MemoryStateChange factDef = info.myFact == nullability ? info.myChange : null;
    if (nullability == DfaNullability.NOT_NULL) {
      String explanation = getObviouslyNonNullExplanation(expression);
      if (explanation != null) {
        return new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.obviously.non.null.expression", explanation), expression);
      }
      if (factDef != null) {
        if (factDef.myInstruction instanceof CheckNotNullInstruction) {
          NullabilityProblemKind.NullabilityProblem<?> problem = ((CheckNotNullInstruction)factDef.myInstruction).getProblem();
          PsiExpression dereferenced = problem.getDereferencedExpression();
          String text = dereferenced == null ? factUse.myTopOfStack.toString() : dereferenced.getText();
          if (dereferenced != null && problem.getKind() == NullabilityProblemKind.passingToNotNullParameter) {
            PsiExpression arg = dereferenced;
            while (arg.getParent() instanceof PsiParenthesizedExpression) {
              arg = (PsiExpression)arg.getParent();
            }
            PsiParameter parameter = MethodCallUtils.getParameterForArgument(dereferenced);
            if (parameter != null) {
              CauseItem item =
                new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.was.passed.as.non.null.parameter", text), dereferenced);
              item.addChildren(fromMemberNullability(DfaNullability.NOT_NULL, parameter, JavaElementKind.PARAMETER, dereferenced));
              return item;
            }
          }
          return new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.was.dereferenced", text), dereferenced);
        }
        if (factDef.myInstruction instanceof InstanceofInstruction) {
          DfaAnchor anchor = ((InstanceofInstruction)factDef.myInstruction).getDfaAnchor();
          if (anchor instanceof JavaExpressionAnchor) {
            PsiExpression operand = ((JavaExpressionAnchor)anchor).getExpression();
            return new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.instanceof.implies.non.nullity"), operand);
          }
        }
      }
    }
    if (factDef != null && expression != null) {
      DfaValue value = factUse.myTopOfStack;
      if (factDef.myInstruction instanceof AssignInstruction && factDef.myTopOfStack == value) {
        PsiExpression rExpression = ((AssignInstruction)factDef.myInstruction).getRExpression();
        if (rExpression != null) {
          MemoryStateChange rValuePush = factDef.findSubExpressionPush(rExpression);
          if (rValuePush != null) {
            CauseItem assignmentItem = createAssignmentCause((AssignInstruction)factDef.myInstruction, value);
            MemoryStateChange previous = factDef.getPrevious();
            if (previous != null && previous.myInstruction instanceof WrapDerivedVariableInstruction instruction) {
              DerivedVariableDescriptor descriptor = instruction.getDerivedVariableDescriptor();
              if (descriptor == SpecialField.UNBOX) {
                DfaAnchor anchor = instruction.getDfaAnchor();
                assignmentItem.addChildren(
                  new CauseItem(JavaAnalysisBundle.message("dfa.find.cause.primitive.boxed"),
                                anchor instanceof JavaExpressionAnchor ? ((JavaExpressionAnchor)anchor).getExpression() : rExpression));
              }
            }
            assignmentItem.addChildren(findNullabilityCause(rValuePush, nullability));
            return assignmentItem;
          }
        }
      }
      PsiExpression defExpression = factDef.getExpression();
      if (defExpression != null) {
        return new CauseItem(
          JavaAnalysisBundle.message("dfa.find.cause.value.is.known.from.place", expression.getText(), nullability.getPresentationName()),
          defExpression);
      }
    }
    return null;
  }
private CauseItem findNullabilityCause(MemoryStateChange factUse, DfaNullability nullability)