@Override
  public void visitMethodReferenceExpression(@NotNull PsiMethodReferenceExpression expression) {
    add(checkFeature(expression, JavaFeature.METHOD_REFERENCES));
    PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
    if (toReportFunctionalExpressionProblemOnParent(parent)) return;
    PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
    if (functionalInterfaceType != null && !PsiTypesUtil.allTypeParametersResolved(expression, functionalInterfaceType)) return;

    JavaResolveResult result;
    JavaResolveResult[] results;
    try {
      results = expression.multiResolve(true);
      result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
    }
    catch (IndexNotReadyException e) {
      return;
    }
    PsiElement method = result.getElement();
    if (method instanceof PsiJvmMember && !result.isAccessible()) {
      String accessProblem = HighlightUtil.accessProblemDescription(expression, method, result);
      HighlightInfo.Builder info =
        HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem);
      HighlightFixUtil.registerAccessQuickFixAction(info, expression.getTextRange(), (PsiJvmMember)method, expression,
                                                    result.getCurrentFileResolveScope(), null);
      add(info);
    }

    if (!LambdaUtil.isValidLambdaContext(parent)) {
      String description = JavaErrorBundle.message("method.reference.expression.is.not.expected");
      add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description));
    }

    if (!hasErrorResults()) {
      PsiElement referenceNameElement = expression.getReferenceNameElement();
      if (referenceNameElement instanceof PsiKeyword) {
        if (!PsiMethodReferenceUtil.isValidQualifier(expression)) {
          PsiElement qualifier = expression.getQualifier();
          if (qualifier != null) {
            boolean pending = qualifier instanceof PsiJavaCodeReferenceElement ref &&
                              IncompleteModelUtil.isIncompleteModel(expression) &&
                              IncompleteModelUtil.canBePendingReference(ref);
            if (!pending) {
              String description = JavaErrorBundle.message("cannot.find.class", qualifier.getText());
              add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description));
            }
          }
        }
      }
    }

    if (functionalInterfaceType != null) {
      if (!hasErrorResults()) {
        add(HighlightClassUtil.checkExtendsSealedClass(expression, functionalInterfaceType));
      }
      if (!hasErrorResults()) {
        boolean isFunctional = LambdaUtil.isFunctionalType(functionalInterfaceType);
        if (!isFunctional && !(IncompleteModelUtil.isIncompleteModel(expression) &&
                               IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType))) {
          String description =
            JavaErrorBundle.message("not.a.functional.interface", functionalInterfaceType.getPresentableText());
          add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description));
        }
      }
      if (!hasErrorResults()) {
        add(LambdaHighlightingUtil.checkFunctionalInterfaceTypeAccessible(myFile.getProject(), expression, functionalInterfaceType));
      }
      if (!hasErrorResults()) {
        String errorMessage = PsiMethodReferenceHighlightingUtil.checkMethodReferenceContext(expression);
        if (errorMessage != null) {
          HighlightInfo.Builder info =
            HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(errorMessage);
          if (method instanceof PsiMethod &&
              !((PsiMethod)method).isConstructor() &&
              !((PsiMethod)method).hasModifierProperty(PsiModifier.ABSTRACT)) {
            boolean shouldHave = !((PsiMethod)method).hasModifierProperty(PsiModifier.STATIC);
            QuickFixAction.registerQuickFixActions(info, null, JvmElementActionFactories.createModifierActions(
              (JvmModifiersOwner)method, MemberRequestsKt.modifierRequest(JvmModifier.STATIC, shouldHave)));
          }
          add(info);
        }
      }
    }

    if (!hasErrorResults()) {
      PsiElement qualifier = expression.getQualifier();
      if (qualifier instanceof PsiTypeElement) {
        PsiType psiType = ((PsiTypeElement)qualifier).getType();
        HighlightInfo.Builder genericArrayCreationInfo = GenericsHighlightUtil.checkGenericArrayCreation(qualifier, psiType);
        if (genericArrayCreationInfo != null) {
          add(genericArrayCreationInfo);
        }
        else {
          String wildcardMessage = PsiMethodReferenceUtil.checkTypeArguments((PsiTypeElement)qualifier, psiType);
          if (wildcardMessage != null) {
            add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(wildcardMessage));
          }
        }
      }
    }

    if (method instanceof PsiMethod && ((PsiMethod)method).hasModifierProperty(PsiModifier.STATIC)) {
      if (!hasErrorResults() && ((PsiMethod)method).hasTypeParameters()) {
        add(GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(method, expression, result.getSubstitutor(), myJavaSdkVersion));
      }

      PsiClass containingClass = ((PsiMethod)method).getContainingClass();
      if (!hasErrorResults() && containingClass != null && containingClass.isInterface()) {
        add(HighlightMethodUtil.checkStaticInterfaceCallQualifier(expression, result, expression, containingClass));
      }
    }

    if (!hasErrorResults()) {
      add(PsiMethodReferenceHighlightingUtil.checkRawConstructorReference(expression));
    }

    if (!hasErrorResults()) {
      add(HighlightUtil.checkUnhandledExceptions(expression));
    }

    if (!hasErrorResults()) {
      if (results.length == 0 || results[0] instanceof MethodCandidateInfo &&
                                 !((MethodCandidateInfo)results[0]).isApplicable() &&
                                 functionalInterfaceType != null || results.length > 1) {
        String description = null;
        if (results.length == 1) {
          description = ((MethodCandidateInfo)results[0]).getInferenceErrorMessage();
        }
        if (expression.isConstructor()) {
          PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass();

          if (containingClass != null) {
            if (!add(HighlightClassUtil.checkInstantiationOfAbstractClass(containingClass, expression)) &&
                !add(GenericsHighlightUtil.checkEnumInstantiation(expression, containingClass)) &&
                containingClass.isPhysical() &&
                description == null) {
              description = JavaErrorBundle.message("cannot.resolve.constructor", containingClass.getName());
            }
          }
        }
        else if (description == null) {
          if (results.length > 1) {
            if (IncompleteModelUtil.isIncompleteModel(expression) &&
                IncompleteModelUtil.isUnresolvedClassType(functionalInterfaceType)) {
              return;
            }
            String t1 = HighlightUtil.format(Objects.requireNonNull(results[0].getElement()));
            String t2 = HighlightUtil.format(Objects.requireNonNull(results[1].getElement()));
            description = JavaErrorBundle.message("ambiguous.reference", expression.getReferenceName(), t1, t2);
          }
          else {
            if (IncompleteModelUtil.isIncompleteModel(expression) && IncompleteModelUtil.canBePendingReference(expression)) {
              PsiElement referenceNameElement = expression.getReferenceNameElement();
              if (referenceNameElement != null) {
                add(HighlightUtil.getPendingReferenceHighlightInfo(referenceNameElement));
              }
              return;
            }
            description = JavaErrorBundle.message("cannot.resolve.method", expression.getReferenceName());
          }
        }

        if (description != null) {
          PsiElement referenceNameElement = ObjectUtils.notNull(expression.getReferenceNameElement(), expression);
          HighlightInfoType type = results.length == 0 ? HighlightInfoType.WRONG_REF : HighlightInfoType.ERROR;
          HighlightInfo.Builder highlightInfo =
            HighlightInfo.newHighlightInfo(type).descriptionAndTooltip(description).range(referenceNameElement);
          TextRange fixRange = HighlightMethodUtil.getFixRange(referenceNameElement);
          IntentionAction action = QuickFixFactory.getInstance().createCreateMethodFromUsageFix(expression);
          highlightInfo.registerFix(action, null, null, fixRange, null);
          add(highlightInfo);
        }
      }
    }

    if (!hasErrorResults()) {
      String badReturnTypeMessage = PsiMethodReferenceUtil.checkReturnType(expression, result, functionalInterfaceType);
      if (badReturnTypeMessage != null) {
        HighlightInfo.Builder info =
          HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(badReturnTypeMessage);
        IntentionAction action = AdjustFunctionContextFix.createFix(expression);
        if (action != null) {
          info.registerFix(action, null, null, null, null);
        }
        add(info);
      }
    }
    if (!hasErrorResults() && method instanceof PsiModifierListOwner) {
      PreviewFeatureUtil.checkPreviewFeature(expression, myPreviewFeatureVisitor);
    }
  }
@Override
  public void visitMethodReferenceExpression(@NotNull PsiMethodReferenceExpression expression)