static HighlightInfo.Builder checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression,
                                                                            @Nullable PsiElement resolved,
                                                                            @NotNull Function<? super PsiElement, ? extends PsiMethod> surroundingConstructor) {
    PsiMethod constructor = surroundingConstructor.apply(expression);
    if (constructor == null) {
      // not inside expression inside constructor
      return null;
    }
    PsiMethodCallExpression constructorCall = JavaPsiConstructorUtil.findThisOrSuperCallInConstructor(constructor);
    if (constructorCall == null) {
      return null;
    }
    if (expression.getTextOffset() > constructorCall.getTextOffset() + constructorCall.getTextLength()) {
      return null;
    }
    // is in or before this() or super() call

    PsiClass referencedClass;
    String resolvedName;
    PsiType type;
    PsiElement parent = expression.getParent();
    if (expression instanceof PsiJavaCodeReferenceElement) {
      // redirected ctr
      if (PsiKeyword.THIS.equals(((PsiJavaCodeReferenceElement)expression).getReferenceName())
          && resolved instanceof PsiMethod
          && ((PsiMethod)resolved).isConstructor()) {
        return null;
      }
      PsiElement qualifier = ((PsiJavaCodeReferenceElement)expression).getQualifier();
      type = qualifier instanceof PsiExpression ? ((PsiExpression)qualifier).getType() : null;
      referencedClass = PsiUtil.resolveClassInType(type);

      boolean isSuperCall = JavaPsiConstructorUtil.isSuperConstructorCall(parent);
      if (resolved == null && isSuperCall) {
        if (qualifier instanceof PsiReferenceExpression) {
          resolved = ((PsiReferenceExpression)qualifier).resolve();
          expression = qualifier;
          type = ((PsiReferenceExpression)qualifier).getType();
          referencedClass = PsiUtil.resolveClassInType(type);
        }
        else if (qualifier == null) {
          resolved = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiMember.class);
          if (resolved != null) {
            referencedClass = ((PsiMethod)resolved).getContainingClass();
          }
        }
        else if (qualifier instanceof PsiThisExpression) {
          referencedClass = PsiUtil.resolveClassInType(((PsiThisExpression)qualifier).getType());
        }
      }
      if (resolved instanceof PsiField referencedField) {
        if (referencedField.hasModifierProperty(PsiModifier.STATIC)) return null;
        resolvedName = PsiFormatUtil
          .formatVariable(referencedField, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME, PsiSubstitutor.EMPTY);
        referencedClass = referencedField.getContainingClass();
      }
      else if (resolved instanceof PsiMethod method) {
        if (method.hasModifierProperty(PsiModifier.STATIC)) return null;
        PsiElement nameElement =
          expression instanceof PsiThisExpression ? expression : ((PsiJavaCodeReferenceElement)expression).getReferenceNameElement();
        String name = nameElement == null ? null : nameElement.getText();
        if (isSuperCall) {
          if (referencedClass == null) return null;
          if (qualifier == null) {
            PsiClass superClass = referencedClass.getSuperClass();
            if (superClass != null
                && PsiUtil.isInnerClass(superClass)
                && InheritanceUtil.isInheritorOrSelf(referencedClass, superClass.getContainingClass(), true)) {
              // by default super() is considered "this"-qualified
              resolvedName = PsiKeyword.THIS;
            }
            else {
              return null;
            }
          }
          else {
            resolvedName = qualifier.getText();
          }
        }
        else if (PsiKeyword.THIS.equals(name)) {
          resolvedName = PsiKeyword.THIS;
        }
        else {
          resolvedName = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
                                                                                  PsiFormatUtilBase.SHOW_NAME, 0);
          if (referencedClass == null) referencedClass = method.getContainingClass();
        }
      }
      else if (resolved instanceof PsiClass aClass) {
        if (expression instanceof PsiReferenceExpression) return null;
        if (aClass.hasModifierProperty(PsiModifier.STATIC)) return null;
        referencedClass = aClass.getContainingClass();
        if (referencedClass == null) return null;
        resolvedName = PsiFormatUtil.formatClass(aClass, PsiFormatUtilBase.SHOW_NAME);
      }
      else {
        return null;
      }
    }
    else if (expression instanceof PsiThisExpression thisExpression) {
      type = thisExpression.getType();
      referencedClass = PsiUtil.resolveClassInType(type);
      if (thisExpression.getQualifier() != null) {
        resolvedName = referencedClass == null
                       ? null
                       : PsiFormatUtil.formatClass(referencedClass, PsiFormatUtilBase.SHOW_NAME) + "." + PsiKeyword.THIS;
      }
      else {
        resolvedName = PsiKeyword.THIS;
      }
    }
    else {
      return null;
    }

    if (referencedClass == null ||
        PsiTreeUtil.getParentOfType(expression, PsiReferenceParameterList.class, true, PsiExpression.class) != null) {
      return null;
    }

    PsiClass parentClass = constructor.getContainingClass();
    if (parentClass == null) {
      return null;
    }

    // references to private methods from the outer class are not calls to super methods
    // even if the outer class is the super class
    if (resolved instanceof PsiMember member && member.hasModifierProperty(PsiModifier.PRIVATE) && referencedClass != parentClass) {
      return null;
    }
    // field or method should be declared in this class or super
    if (!InheritanceUtil.isInheritorOrSelf(parentClass, referencedClass, true)) return null;
    // and point to our instance
    if (expression instanceof PsiReferenceExpression ref) {
      PsiExpression qualifier = ref.getQualifierExpression();
      if (!isThisOrSuperReference(qualifier, parentClass)) {
        return null;
      }
      else if (qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) {
        if (((PsiQualifiedExpression)qualifier).getQualifier() != null) return null;
      }
    }

    if (expression instanceof PsiThisExpression || expression instanceof PsiSuperExpression) {
      if (referencedClass != parentClass) return null;
    }

    if (expression instanceof PsiJavaCodeReferenceElement) {
      if (!parentClass.equals(PsiTreeUtil.getParentOfType(expression, PsiClass.class)) &&
          PsiTreeUtil.getParentOfType(expression, PsiTypeElement.class) != null) {
        return null;
      }

      if (PsiTreeUtil.getParentOfType(expression, PsiClassObjectAccessExpression.class) != null) {
        return null;
      }

      if (parent instanceof PsiNewExpression newExpression &&
          newExpression.isArrayCreation() &&
          newExpression.getClassOrAnonymousClassReference() == expression) {
        return null;
      }
      if (parent instanceof PsiThisExpression || parent instanceof PsiSuperExpression) return null;
    }
    if (!(expression instanceof PsiThisExpression) && !(expression instanceof PsiSuperExpression) ||
        ((PsiQualifiedExpression)expression).getQualifier() == null) {
      PsiClass expressionClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class, true);
      while (expressionClass != null && parentClass != expressionClass) {
        if (InheritanceUtil.isInheritorOrSelf(expressionClass, referencedClass, true)) {
          return null;
        }
        expressionClass = PsiTreeUtil.getParentOfType(expressionClass, PsiClass.class, true);
      }
    }

    HighlightInfo.Builder builder = createMemberReferencedError(resolvedName, expression.getTextRange());
    if (expression instanceof PsiReferenceExpression ref && PsiUtil.isInnerClass(parentClass)) {
      String referenceName = ref.getReferenceName();
      PsiClass containingClass = parentClass.getContainingClass();
      LOG.assertTrue(containingClass != null);
      PsiField fieldInContainingClass = containingClass.findFieldByName(referenceName, true);
      if (fieldInContainingClass != null && ref.getQualifierExpression() == null) {
        builder.registerFix(new QualifyWithThisFix(containingClass, ref), null, null, null, null);
      }
    }

    return builder;
  }
static HighlightInfo.Builder checkMemberReferencedBeforeConstructorCalled(@NotNull PsiElement expression,
                                                                            @Nullable PsiElement resolved,
                                                                            @NotNull Function<? super PsiElement, ? extends PsiMethod> surroundingConstructor)