@NotNull
      @Override
      public Result<Set<PsiField>> compute() {
        PsiClass containingClass = PsiTreeUtil.getContextOfType(body, PsiClass.class);
        LOG.assertTrue(containingClass != null);
        DfaValueFactory factory = new DfaValueFactory(body.getProject());
        ControlFlow flow = ControlFlowAnalyzer.buildFlow(body, factory, true);
        if (flow == null) {
          return Result.create(Set.of(), body, PsiModificationTracker.MODIFICATION_COUNT);
        }
        var interpreter = new StandardDataFlowInterpreter(flow, DfaListener.EMPTY) {
          final Map<PsiField, Boolean> map = new HashMap<>();
          private boolean isCallExposingNonInitializedFields(Instruction instruction) {
            if (!(instruction instanceof MethodCallInstruction)) {
              return false;
            }

            PsiCall call = ((MethodCallInstruction)instruction).getCallExpression();
            if (call == null) return false;

            if (call instanceof PsiNewExpression && canAccessFields((PsiExpression)call)) {
              return true;
            }

            if (call instanceof PsiMethodCallExpression) {
              PsiExpression qualifier = ((PsiMethodCallExpression)call).getMethodExpression().getQualifierExpression();
              if (qualifier == null || canAccessFields(qualifier)) {
                return true;
              }
            }

            PsiExpressionList argumentList = call.getArgumentList();
            if (argumentList != null) {
              for (PsiExpression expression : argumentList.getExpressions()) {
                if (canAccessFields(expression)) return true;
              }
            }

            return false;
          }

          private boolean canAccessFields(PsiExpression expression) {
            PsiClass type = PsiUtil.resolveClassInClassTypeOnly(expression.getType());
            JBIterable<PsiClass> typeContainers =
              JBIterable.generate(type, PsiClass::getContainingClass).takeWhile(c -> !c.hasModifierProperty(PsiModifier.STATIC));
            return typeContainers.contains(containingClass);
          }

          @Override
          protected DfaInstructionState @NotNull [] acceptInstruction(@NotNull DfaInstructionState instructionState) {
            Instruction instruction = instructionState.getInstruction();
            if (instruction instanceof FinishElementInstruction) {
              Set<DfaVariableValue> vars = ((FinishElementInstruction)instruction).getVarsToFlush();
              vars.removeIf(v -> {
                PsiElement variable = v.getPsiVariable();
                return variable instanceof PsiField && ((PsiField)variable).getContainingClass() == containingClass;
              });
            }
            if ((isCallExposingNonInitializedFields(instruction) || instruction instanceof ReturnInstruction)) {
              for (PsiField field : containingClass.getFields()) {
                DfaVariableValue value = PlainDescriptor.createVariableValue(getFactory(), field);
                DfType dfType = instructionState.getMemoryState().getDfType(value);
                if (dfType.isSuperType(DfTypes.NULL)) {
                  map.put(field, false);
                }
                else if (!map.containsKey(field)) {
                  map.put(field, true);
                }
              }
              return DfaInstructionState.EMPTY_ARRAY;
            }
            return super.acceptInstruction(instructionState);
          }
        };
        DfaMemoryState state = DfaUtil.createStateWithEnabledAssertions(factory);
        final RunnerResult rc = interpreter.interpret(state);
        Set<PsiField> notNullFields = new HashSet<>();
        if (rc == RunnerResult.OK) {
          interpreter.map.forEach((key, value) -> {
            if (value) {
              notNullFields.add(key);
            }
          });
        }
        return Result.create(notNullFields, body, PsiModificationTracker.MODIFICATION_COUNT);
      }
@NotNull
      @Override
      public Result<Set<PsiField>> compute()