diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiLiteralUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiLiteralUtil.java index afd1351369d9..cb6980fe6eab 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiLiteralUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiLiteralUtil.java @@ -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(); } diff --git a/java/java-tests/testSrc/com/intellij/psi/util/MapBackTextBlockTextRangeTest.java b/java/java-tests/testSrc/com/intellij/psi/util/MapBackTextBlockTextRangeTest.java index 099aa75a5670..69a1fa3e96a3 100644 --- a/java/java-tests/testSrc/com/intellij/psi/util/MapBackTextBlockTextRangeTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/util/MapBackTextBlockTextRangeTest.java @@ -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);