@Override
  public @NotNull PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder,
                                                 boolean isOnTheFly,
                                                 @NotNull LocalInspectionToolSession session) {
    return new JavaElementVisitor() {
      @Override
      public void visitJavaFile(@NotNull PsiJavaFile file) {
        if (!InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) {
          Runnable fix = getAttachAnnotationsJarFix(file.getProject());
          if (fix != null) {
            fix.run(); // try to attach automatically
          }
        }
      }

      @Override
      public void visitEnumConstant(@NotNull PsiEnumConstant enumConstant) {
        checkCall(enumConstant, holder);
      }

      @Override
      public void visitCallExpression(@NotNull PsiCallExpression callExpression) {
        checkCall(callExpression, holder);
      }

      @Override
      public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
        PsiExpression r = expression.getRExpression();
        if (r != null &&
            expression.getLExpression() instanceof PsiReferenceExpression ref &&
            ref.resolve() instanceof PsiModifierListOwner owner) {
          PsiType type = expression.getType();
          checkExpression(r, owner, type, holder);
        }
      }

      @Override
      public void visitVariable(@NotNull PsiVariable variable) {
        PsiExpression initializer = variable.getInitializer();
        if (initializer != null) {
            checkExpression(initializer, variable, variable.getType(), holder);
        }
      }

      @Override
      public void visitReturnStatement(@NotNull PsiReturnStatement statement) {
        PsiExpression value = statement.getReturnValue();
        if (value == null) return;
        PsiElement element = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class);
        PsiMethod method = element instanceof PsiMethod ? (PsiMethod)element : LambdaUtil.getFunctionalInterfaceMethod(element);
        if (method == null) return;
        checkExpression(value, method, value.getType(), holder);
      }

      @Override
      public void visitNameValuePair(@NotNull PsiNameValuePair pair) {
        PsiAnnotationMemberValue value = pair.getValue();
        if (!(value instanceof PsiExpression expression)) return;
        PsiReference ref = pair.getReference();
        if (ref == null) return;
        PsiMethod method = (PsiMethod)ref.resolve();
        if (method == null) return;
        checkExpression(expression, method, method.getReturnType(), holder);
      }

      @Override
      public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) {
        IElementType tokenType = expression.getOperationTokenType();
        if (tokenType != JavaTokenType.EQEQ && tokenType != JavaTokenType.NE) return;
        PsiExpression l = expression.getLOperand();
        PsiExpression r = expression.getROperand();
        if (r == null) return;
        checkBinary(l, r);
        checkBinary(r, l);
      }

      @Override
      public void visitCaseLabelElementList(@NotNull PsiCaseLabelElementList list) {
        PsiSwitchBlock switchBlock = PsiTreeUtil.getParentOfType(list, PsiSwitchBlock.class);
        if (switchBlock == null) return;
        PsiExpression selector = switchBlock.getExpression();
        PsiModifierListOwner owner = null;
        if (selector instanceof PsiReference ref) {
          owner = ObjectUtils.tryCast(ref.resolve(), PsiModifierListOwner.class);
        }
        else if (selector instanceof PsiMethodCallExpression call) {
          owner = call.resolveMethod();
        }
        if (owner == null) return;
        for (PsiCaseLabelElement element : list.getElements()) {
          if (element instanceof PsiExpression expression) {
            checkExpression(expression, owner, PsiUtil.getTypeByPsiElement(owner), holder);
          }
        }
      }

      private void checkBinary(@NotNull PsiExpression l, @NotNull PsiExpression r) {
        if (l instanceof PsiReference ref && ref.resolve() instanceof PsiModifierListOwner owner) {
          checkExpression(r, owner, PsiUtil.getTypeByPsiElement(owner), holder);
        }
        else if (l instanceof PsiMethodCallExpression call) {
          PsiMethod method = call.resolveMethod();
          if (method != null) {
            checkExpression(r, method, method.getReturnType(), holder);
            checkExpression(r, holder, SPECIAL_CASES.mapFirst(call));
          }
        }
      }
    };
  }
@Override
  public @NotNull PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder,
                                                 boolean isOnTheFly,
                                                 @NotNull LocalInspectionToolSession session)