@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    return new JavaElementVisitor() {
      @Override
      public void visitMethod(PsiMethod method) {
        PsiDocComment comment = method.getDocComment();
        if (comment == null) {
          return;
        }
        List<ReturnItem> items = extractValues(comment);
        String commentText = comment.getText();
        for (ReturnItem item : items) {
          String valueText = item.range.substring(commentText);
          String incompatibleMessage = getIncompatibleMessage(valueText, item.kind, method);
          if (incompatibleMessage != null) {
            holder.registerProblem(comment, item.range, incompatibleMessage);
          }
        }
      }

      private static @Nls @Nullable String getIncompatibleMessage(@NotNull String text, @NotNull Kind kind, @NotNull PsiMethod method) {
        PsiType returnType = method.getReturnType();
        if (returnType == null || PsiTypes.voidType().equals(returnType)) return null;
        PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(returnType);
        if (kind == Kind.MAYBE_TYPE || kind == Kind.MAYBE_TYPE_SINGULAR) {
          String typeName = text.toLowerCase(Locale.ROOT);
          String normalized = typeName.equals("count") || typeName.equals("amount") ? "number" : typeName;
          if (TYPE_SIMPLE_NAMES.containsKey(normalized)) {
            for (Map.Entry<String, Predicate<PsiType>> entry : TYPE_SIMPLE_NAMES.entrySet()) {
              if (!normalized.equals(entry.getKey()) && entry.getValue().test(returnType)) {
                return InspectionsBundle.message("inspection.mismatch.javadoc.reason.different.type", typeName, entry.getKey());
              }
            }
          }
          if (kind == Kind.MAYBE_TYPE_SINGULAR) {
            PsiType type = PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_COLLECTION, 0, false);
            if (type instanceof PsiClassType && type.getPresentableText().equalsIgnoreCase(typeName) &&
                !((PsiClassType)type).rawType().isAssignableFrom(returnType)) {
              return InspectionsBundle.message("inspection.mismatch.javadoc.reason.single.collection", type.getPresentableText());
            }
          }
          return null;
        }
        if (text.equals("null")) {
          if (returnType instanceof PsiPrimitiveType) {
            return InspectionsBundle.message("inspection.mismatch.javadoc.reason.null.primitive");
          }
          NullabilityAnnotationInfo info = NullableNotNullManager.getInstance(method.getProject()).findEffectiveNullabilityInfo(method);
          if (info != null && info.getNullability() == Nullability.NOT_NULL) {
            PsiClass psiClass = info.getAnnotation().resolveAnnotationType();
            if (psiClass != null) {
              return InspectionsBundle.message("inspection.mismatch.javadoc.reason.null.annotated", psiClass.getName());
            }
          }
        }
        if (StringUtil.isJavaIdentifier(text) &&
            (text.equals("true") || text.equals("false") || text.equals(text.toUpperCase(Locale.ROOT)))) {
          if (aClass != null && aClass.isEnum()) {
            if (StreamEx.of(aClass.getFields()).select(PsiEnumConstant.class)
              .map(PsiEnumConstant::getName).noneMatch(name -> name.equalsIgnoreCase(text))) {
              return InspectionsBundle.message("inspection.mismatch.javadoc.reason.enum", text, aClass.getName());
            }
          }
        }
        if (text.equals("true") || text.equals("false")) {
          if (!TypeConversionUtil.isBooleanType(returnType)) {
            if (kind == Kind.MAYBE_VALUE) {
              if (InheritanceUtil.isInheritor(returnType, CommonClassNames.JAVA_UTIL_FUNCTION_PREDICATE) ||
                  returnType instanceof PsiClassType && ContainerUtil.exists(((PsiClassType)returnType).getParameters(),
                                                                             TypeConversionUtil::isBooleanType)) {
                return null;
              }
            }
            return InspectionsBundle.message("inspection.mismatch.javadoc.reason.boolean", text);
          }
        }
        return null;
      }

      private List<ReturnItem> extractValues(PsiDocComment comment) {
        List<ReturnItem> ranges = new ArrayList<>();
        for (PsiElement child : comment.getChildren()) {
          if (child instanceof PsiDocTag && ((PsiDocTag)child).getName().equals("return")) {
            processLine(RETURN_LINE_START, child, Kind.LIKELY_VALUE, ranges);
            processLine(RETURN_LINE_MIDDLE, child, Kind.MAYBE_VALUE, ranges);
            processLine(RETURN_LINE_START_TYPE, child, Kind.MAYBE_TYPE, ranges);
            processLine(RETURN_LINE_START_TYPE_SINGULAR, child, Kind.MAYBE_TYPE_SINGULAR, ranges);
          }
          else if (child instanceof PsiDocToken && ((PsiDocToken)child).getTokenType() == JavaDocTokenType.DOC_COMMENT_DATA) {
            processLine(DESCRIPTION, child, Kind.LIKELY_VALUE, ranges);
          }
        }
        return ranges;
      }

      private static void processLine(Pattern pattern, PsiElement child, Kind kind, List<ReturnItem> ranges) {
        String text = child.getText();
        Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
          int start = matcher.start(1);
          int end = matcher.end(1);
          ranges.add(new ReturnItem(kind, TextRange.create(start, end).shiftRight(child.getStartOffsetInParent())));
        }
      }
    };
  }
@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly)