@Override
  public int tryJoinRawLines(@NotNull Document doc, @NotNull PsiFile file, int start, int endWithSpaces) {
    CharSequence text = doc.getCharsSequence();

    int end = getNextLineStart(start, text);
    start--;
    PsiJavaToken token = ObjectUtils.tryCast(file.findElementAt(start), PsiJavaToken.class);
    if (token == null) return CANNOT_JOIN;
    IElementType tokenType = token.getTokenType();
    if (!tokenType.equals(JavaTokenType.TEXT_BLOCK_LITERAL) &&
        !tokenType.equals(JavaTokenType.TEXT_BLOCK_TEMPLATE_BEGIN) &&
        !tokenType.equals(JavaTokenType.TEXT_BLOCK_TEMPLATE_END) &&
        !tokenType.equals(JavaTokenType.TEXT_BLOCK_TEMPLATE_MID)) {
      return CANNOT_JOIN;
    }
    TextRange tokenRange = token.getTextRange();
    int lineNumber = doc.getLineNumber(start);
    boolean atStartLine = (tokenType.equals(JavaTokenType.TEXT_BLOCK_LITERAL) || tokenType.equals(JavaTokenType.TEXT_BLOCK_TEMPLATE_BEGIN))
                          && lineNumber == doc.getLineNumber(tokenRange.getStartOffset());
    boolean atEmptyStartLine = atStartLine && TEXT_BLOCK_START.matcher(token.getText()).find();
    boolean singleSlash = false;
    int numSpaces = 0;
    char charAtStart = text.charAt(start);
    if (charAtStart == '\\') {
      int startOffset = Math.max(tokenRange.getStartOffset(), doc.getLineStartOffset(lineNumber));
      String substring = doc.getText(TextRange.create(startOffset, start)) + "\\\n";
      CharSequence parsed = CodeInsightUtilCore.parseStringCharacters(substring, null);
      singleSlash = parsed != null && parsed.charAt(parsed.length() - 1) != '\n';
    }
    else if (charAtStart == 's' && text.charAt(start - 1) == '\\') {
      int startOffset = Math.max(tokenRange.getStartOffset(), doc.getLineStartOffset(lineNumber));
      String substring = doc.getText(TextRange.create(startOffset, start + 1));
      CharSequence parsed = CodeInsightUtilCore.parseStringCharacters(substring, null);
      if (parsed != null) {
        while (text.charAt(start - numSpaces * 2) == 's' && text.charAt(start - numSpaces * 2 - 1) == '\\' &&
               parsed.charAt(parsed.length() - 1 - numSpaces) == ' ') {
          numSpaces++;
        }
      }
    }
    if (!singleSlash) {
      start++;
    }
    int indent = token instanceof PsiFragment fragment
                 ? PsiFragmentImpl.getTextBlockFragmentIndent(fragment)
                 : BasicLiteralUtil.getTextBlockIndent(token);
    while (indent > 0 && text.charAt(end) == ' ' || text.charAt(end) == '\t') {
      indent--;
      end++;
    }
    boolean fromStartTillEnd = atStartLine && tokenType.equals(JavaTokenType.TEXT_BLOCK_LITERAL) && 
                               doc.getLineNumber(tokenRange.getEndOffset()) == lineNumber + 1 &&
                               token.getText().endsWith("\"\"\"");
    int endOffset = tokenRange.getEndOffset();
    if (singleSlash || atEmptyStartLine) {
      doc.deleteString(start, end);
      endOffset += start - end;
    } else {
      doc.replaceString(start - numSpaces * 2, end, " ".repeat(numSpaces) + "\\n");
      start -= numSpaces;
      endOffset += start - end + 2;
    }
    if (fromStartTillEnd) {
      doc.replaceString(tokenRange.getStartOffset(), endOffset, 
                        convertToRegular(doc.getText().substring(tokenRange.getStartOffset(), endOffset)));
    }
    return start;
  }
@Override
  public int tryJoinRawLines(@NotNull Document doc, @NotNull PsiFile file, int start, int endWithSpaces)