public static HighlightInfo.Builder checkLiteralExpressionParsingError(@NotNull PsiLiteralExpression expression,
                                                                         @NotNull LanguageLevel level,
                                                                         @Nullable PsiFile file, @Nullable Ref<? super String> description) {
    PsiElement literal = expression.getFirstChild();
    assert literal instanceof PsiJavaToken : literal;
    IElementType type = ((PsiJavaToken)literal).getTokenType();
    if (type == JavaTokenType.TRUE_KEYWORD || type == JavaTokenType.FALSE_KEYWORD || type == JavaTokenType.NULL_KEYWORD) {
      return null;
    }

    boolean isInt = ElementType.INTEGER_LITERALS.contains(type);
    boolean isFP = ElementType.REAL_LITERALS.contains(type);
    String rawText = isInt || isFP ? StringUtil.toLowerCase(literal.getText()) : literal.getText();
    String text = parseUnicodeEscapes(rawText, null);
    Object value = expression.getValue();

    if (file != null) {
      if (isFP) {
        if (text.startsWith(PsiLiteralUtil.HEX_PREFIX)) {
          HighlightInfo.Builder info = checkFeature(expression, JavaFeature.HEX_FP_LITERALS, level, file);
          if (info != null) {
            if (description != null) {
              description.set(getUnsupportedFeatureMessage(JavaFeature.HEX_FP_LITERALS, level, file));
            }
            return info;
          }
        }
      }
      if (isInt) {
        if (text.startsWith(PsiLiteralUtil.BIN_PREFIX)) {
          HighlightInfo.Builder info = checkFeature(expression, JavaFeature.BIN_LITERALS, level, file);
          if (info != null) {
            if (description != null) {
              description.set(getUnsupportedFeatureMessage(JavaFeature.BIN_LITERALS, level, file));
            }
            return info;
          }
        }
      }
      if (isInt || isFP) {
        if (text.contains("_")) {
          HighlightInfo.Builder info = checkFeature(expression, JavaFeature.UNDERSCORES, level, file);
          if (info != null) {
            if (description != null) {
              description.set(getUnsupportedFeatureMessage(JavaFeature.UNDERSCORES, level, file));
            }
            return info;
          }
          info = checkUnderscores(expression, text, isInt);
          if (info != null) {
            if (description != null) {
              description.set(JavaErrorBundle.message("illegal.underscore"));
            }
            return info;
          }
        }
      }
    }

    PsiElement parent = expression.getParent();
    if (type == JavaTokenType.INTEGER_LITERAL) {
      String cleanText = StringUtil.replace(text, "_", "");
      //literal 2147483648 may appear only as the operand of the unary negation operator -.
      if (!(cleanText.equals(PsiLiteralUtil._2_IN_31) &&
            parent instanceof PsiPrefixExpression &&
            ((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.MINUS)) {
        if (cleanText.equals(PsiLiteralUtil.HEX_PREFIX)) {
          String message = JavaErrorBundle.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
        if (cleanText.equals(PsiLiteralUtil.BIN_PREFIX)) {
          String message = JavaErrorBundle.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
        if (value == null || cleanText.equals(PsiLiteralUtil._2_IN_31)) {
          String message = JavaErrorBundle.message("integer.number.too.large");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
      }
    }
    else if (type == JavaTokenType.LONG_LITERAL) {
      String cleanText = StringUtil.replace(StringUtil.trimEnd(text, 'l'), "_", "");
      //literal 9223372036854775808L may appear only as the operand of the unary negation operator -.
      if (!(cleanText.equals(PsiLiteralUtil._2_IN_63) &&
            parent instanceof PsiPrefixExpression &&
            ((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.MINUS)) {
        if (cleanText.equals(PsiLiteralUtil.HEX_PREFIX)) {
          String message = JavaErrorBundle.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
        if (cleanText.equals(PsiLiteralUtil.BIN_PREFIX)) {
          String message = JavaErrorBundle.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
        if (value == null || cleanText.equals(PsiLiteralUtil._2_IN_63)) {
          String message = JavaErrorBundle.message("long.number.too.large");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
      }
    }
    else if (isFP) {
      if (value == null) {
        String message = JavaErrorBundle.message("malformed.floating.point.literal");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
    }
    else if (type == JavaTokenType.CHARACTER_LITERAL) {
      if (!StringUtil.startsWithChar(text, '\'')) {
        return null;
      }
      if (!StringUtil.endsWithChar(text, '\'') || text.length() == 1) {
        String message = JavaErrorBundle.message("unclosed.char.literal");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
      int rawLength = rawText.length();
      StringBuilder chars = new StringBuilder(rawLength);
      int[] offsets = new int[rawLength + 1];
      final boolean success = CodeInsightUtilCore.parseStringCharacters(rawText, chars, offsets, false);
      if (!success) {
        String message = JavaErrorBundle.message("illegal.escape.character.in.character.literal");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
          .range(expression, calculateErrorRange(rawText, offsets[chars.length()]))
          .descriptionAndTooltip(message);
      }
      int length = chars.length();
      if (length > 3) {
        String message = JavaErrorBundle.message("too.many.characters.in.character.literal");
        HighlightInfo.Builder info =
          HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        IntentionAction action = getFixFactory().createConvertToStringLiteralAction();
        info.registerFix(action, null, null, null, null);
        if (description != null) {
          description.set(message);
        }
        return info;
      }
      else if (length == 2) {
        String message = JavaErrorBundle.message("empty.character.literal");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
      final HighlightInfo.Builder info = checkTextBlockEscapes(expression, rawText, level, file, description);
      if (info != null) return info;
    }
    else if (type == JavaTokenType.STRING_LITERAL || type == JavaTokenType.TEXT_BLOCK_LITERAL) {
      if (type == JavaTokenType.STRING_LITERAL) {
        for (PsiElement element = expression.getFirstChild(); element != null; element = element.getNextSibling()) {
          if (element instanceof OuterLanguageElement) {
            return null;
          }
        }

        if (!StringUtil.startsWithChar(text, '"')) return null;
        if (!StringUtil.endsWithChar(text, '"') || text.length() == 1) {
          String message = JavaErrorBundle.message("illegal.line.end.in.string.literal");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
        }
        int length = rawText.length();
        StringBuilder chars = new StringBuilder(length);
        int[] offsets = new int[length + 1];
        boolean success = CodeInsightUtilCore.parseStringCharacters(rawText, chars, offsets, false);
        if (!success) {
          String message = JavaErrorBundle.message("illegal.escape.character.in.string.literal");
          if (description != null) {
            description.set(message);
          }
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
            .range(expression, calculateErrorRange(rawText, offsets[chars.length()]))
            .descriptionAndTooltip(message);
        }
        final HighlightInfo.Builder info2 = checkTextBlockEscapes(expression, rawText, level, file, description);
        if (info2 != null) return info2;
      }
      else {
        if (!text.endsWith("\"\"\"")) {
          String message = JavaErrorBundle.message("text.block.unclosed");
          if (description != null) {
            description.set(message);
          }
          int p = expression.getTextRange().getEndOffset();
          return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(p, p).endOfLine().descriptionAndTooltip(message);
        }
        else if (text.length() > 3) {
          final HighlightInfo.Builder info = checkTextBlockNewlineAfterOpeningQuotes(expression, text, description);
          if (info != null) return info;
          final int rawLength = rawText.length();
          StringBuilder chars = new StringBuilder(rawLength);
          int[] offsets = new int[rawLength + 1];
          boolean success = CodeInsightUtilCore.parseStringCharacters(rawText, chars, offsets, true);
          if (!success) {
            String message = JavaErrorBundle.message("illegal.escape.character.in.string.literal");
            if (description != null) {
              description.set(message);
            }
            return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
              .range(expression, calculateErrorRange(rawText, offsets[chars.length()]))
              .descriptionAndTooltip(message);
          }
        }
      }
    }

    if (value instanceof Float number) {
      if (number.isInfinite()) {
        String message = JavaErrorBundle.message("floating.point.number.too.large");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
      if (number.floatValue() == 0 && !TypeConversionUtil.isFPZero(text)) {
        String message = JavaErrorBundle.message("floating.point.number.too.small");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
    }
    else if (value instanceof Double number) {
      if (number.isInfinite()) {
        String message = JavaErrorBundle.message("floating.point.number.too.large");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
      if (number.doubleValue() == 0 && !TypeConversionUtil.isFPZero(text)) {
        String message = JavaErrorBundle.message("floating.point.number.too.small");
        if (description != null) {
          description.set(message);
        }
        return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message);
      }
    }

    return null;
  }
public static HighlightInfo.Builder checkLiteralExpressionParsingError(@NotNull PsiLiteralExpression expression,
                                                                         @NotNull LanguageLevel level,
                                                                         @Nullable PsiFile file, @Nullable Ref<? super String> description)