IDEA-384355 [java]: fix text block character mapping in the presence of escaped newlines

GitOrigin-RevId: 1b2620ac1b6b9d0c82e6f0d6af5a4d55a9f16574
This commit is contained in:
Bas Leijdekkers
2026-02-11 14:32:13 +00:00
committed by intellij-monorepo-bot
parent 61498b7d65
commit 456620d16e
2 changed files with 42 additions and 8 deletions
@@ -712,13 +712,24 @@ public final class PsiLiteralUtil {
String line = lines[i];
boolean blank = line.chars().allMatch(Character::isWhitespace);
int prefix = blank ? line.length() : indent;
line = line.substring(prefix);
boolean last = i == lines.length - 1;
int suffix = findLineSuffixLength(line, last);
line = line.substring(0, line.length() - suffix);
if (!last) line += '\n';
offset += prefix;
if (prefix > 0) line = blank ? "" : line.substring(indent);
boolean last = i == lines.length - 1;
int suffix = last ? 0 : findLineSuffixLength(line);
if (suffix == 0) {
if (!last) {
if (countBackSlashes(line, line.length() - 1) % 2 != 0) {
line = line.substring(0, line.length() - 1);
suffix += 2;
}
else {
line += '\n';
}
}
}
else {
line = line.substring(0, line.length() - suffix) + '\n';
}
int charEnd = 0;
while (true) {
@@ -729,9 +740,11 @@ public final class PsiLiteralUtil {
return new TextRange(mappedFrom, offset + charEnd);
}
charEnd = getCharEndIndex(line, charEnd);
if (charEnd == -1) break;
if (charEnd == -1) {
offset += suffix;
break;
}
charsFound++;
if (charEnd == line.length()) offset += suffix;
}
offset += line.length();
}
@@ -51,6 +51,27 @@ public class MapBackTextBlockTextRangeTest extends LightPlatformCodeInsightTestC
doTest("\"\"\"\n\"\"\"", 0, 1, null, null);
}
public void testEscapedNewlines() {
//noinspection TextBlockMigration
String text = "\"\"\" \n" +
" %s\\\n" +
" %t\\\\\\\n" + // <- three back-slashes and a newline
" %u\\u0020\n" + // <- that's a space character
" %v\\\n" +
" \"\"\"";
doTest(text, 0, 2, new TextRange(11, 13), "%s");
doTest(text, 2, 4, new TextRange(19, 21), "%t");
doTest(text, 5, 7, new TextRange(29, 31), "%u");
doTest(text, 8, 10, new TextRange(42, 44), "%v");
}
public void testEscapedCharRange() {
String text = "\"\"\"\n" +
" XXX\\uuu0030" +
" \"\"\"";
doTest(text, 3, 4, new TextRange(11, 19), "\\uuu0030");
}
private void doTest(String blockText, int from, int to, TextRange expectedRange, String expectedRangeText) {
PsiElementFactory factory = JavaPsiFacade.getElementFactory(getProject());
PsiLiteralExpression textBlock = (PsiLiteralExpression)factory.createExpressionFromText(blockText, null);