mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
TextBlockMigration: support two new escape sequences (IDEA-230758)
GitOrigin-RevId: ab4d06cd4d6c198fcfc94d67e1e758de291648c1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b32d7fc5ac
commit
5136d5999f
+10
-3
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -56,9 +57,15 @@ public class ConcatenationToMessageFormatAction implements IntentionAction {
|
||||
boolean textBlocks = Arrays.stream(concatenation.getOperands())
|
||||
.anyMatch(operand -> operand instanceof PsiLiteralExpressionImpl &&
|
||||
((PsiLiteralExpressionImpl)operand).getLiteralElementType() == JavaTokenType.TEXT_BLOCK_LITERAL);
|
||||
final String expressionText = textBlocks
|
||||
? "\"\"\"\n" + PsiLiteralUtil.escapeTextBlockCharacters(formatString) + "\"\"\""
|
||||
: "\"" + StringUtil.escapeStringCharacters(formatString) + "\"";
|
||||
final String expressionText;
|
||||
if (textBlocks) {
|
||||
expressionText = Arrays.stream(formatString.split("\n"))
|
||||
.map(s -> PsiLiteralUtil.escapeTextBlockCharacters(s))
|
||||
.collect(Collectors.joining("\n", "\"\"\"\n", "\"\"\""));
|
||||
}
|
||||
else {
|
||||
expressionText = "\"" + StringUtil.escapeStringCharacters(formatString) + "\"";
|
||||
}
|
||||
PsiExpression formatArgument = factory.createExpressionFromText(expressionText, null);
|
||||
argumentList.add(formatArgument);
|
||||
if (PsiUtil.isLanguageLevel5OrHigher(file)) {
|
||||
|
||||
+74
-3
@@ -5,6 +5,7 @@ import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
@@ -69,15 +70,85 @@ public class TextBlockBackwardMigrationInspection extends AbstractBaseJavaLocalI
|
||||
private static String convertToConcatenation(@NotNull String text) {
|
||||
if (text.isEmpty()) return "\"\"";
|
||||
StringJoiner joiner = new StringJoiner(" +\n");
|
||||
String[] lines = text.split("\n", -1);
|
||||
String[] lines = getTextBlockLines(text).split("\n", -1);
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
boolean addNewLine = i != lines.length - 1;
|
||||
if (!addNewLine && line.isEmpty()) break;
|
||||
line = line.replaceAll("\\\\040", " ");
|
||||
joiner.add("\"" + PsiLiteralUtil.escapeQuotes(line) + (addNewLine ? "\\n\"" : "\""));
|
||||
joiner.add("\"" + line + (addNewLine ? "\\n\"" : "\""));
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getTextBlockLines(@NotNull String text) {
|
||||
int length = text.length();
|
||||
StringBuilder result = new StringBuilder(length);
|
||||
int i = 0;
|
||||
while (i < length) {
|
||||
int nSlashes = 0;
|
||||
int next = i;
|
||||
while ((next = PsiLiteralUtil.parseBackSlash(text, next)) != -1) {
|
||||
nSlashes++;
|
||||
i = next;
|
||||
}
|
||||
next = parseQuote(i, text, nSlashes, result);
|
||||
if (next != -1) {
|
||||
i = next;
|
||||
continue;
|
||||
}
|
||||
if (nSlashes != 0) {
|
||||
i = parseEscapedChar(i, text, nSlashes, result);
|
||||
}
|
||||
else {
|
||||
result.append(text.charAt(i));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static int parseEscapedChar(int i, @NotNull String text, int nSlashes, @NotNull StringBuilder result) {
|
||||
if (i > text.length()) {
|
||||
result.append(StringUtil.repeatSymbol('\\', nSlashes));
|
||||
return i;
|
||||
}
|
||||
int next = parseEscapedSpace(i, text, nSlashes, result);
|
||||
if (next != -1) return next;
|
||||
next = parseEscapedLineBreak(i, text, nSlashes, result);
|
||||
if (next != -1) return next;
|
||||
result.append(StringUtil.repeatSymbol('\\', nSlashes)).append(text.charAt(i));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
private static int parseEscapedSpace(int i, @NotNull String text, int nSlashes, @NotNull StringBuilder result) {
|
||||
char c = text.charAt(i);
|
||||
if (c == 's' && nSlashes % 2 != 0) {
|
||||
result.append(StringUtil.repeatSymbol('\\', nSlashes - 1)).append(' ');
|
||||
return i + 1;
|
||||
}
|
||||
if (StringUtil.startsWith(text, i, "040") && nSlashes % 2 != 0) {
|
||||
result.append(StringUtil.repeatSymbol('\\', nSlashes - 1)).append(' ');
|
||||
return i + 3;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int parseEscapedLineBreak(int i, @NotNull String text, int nSlashes, @NotNull StringBuilder result) {
|
||||
char c = text.charAt(i);
|
||||
if (c == '\n' && nSlashes % 2 != 0) {
|
||||
result.append(StringUtil.repeatSymbol('\\', nSlashes - 1));
|
||||
return i + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int parseQuote(int i, @NotNull String text, int nSlashes, @NotNull StringBuilder result) {
|
||||
char c = text.charAt(i);
|
||||
if (c != '"') return -1;
|
||||
if (nSlashes % 2 == 0) nSlashes++;
|
||||
result.append(StringUtil.repeatSymbol('\\', nSlashes)).append(c);
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,16 +128,8 @@ public class TextBlockMigrationInspection extends AbstractBaseJavaLocalInspectio
|
||||
}
|
||||
|
||||
private static String @NotNull [] getTextBlockLines(String @NotNull [] lines) {
|
||||
StringBuilder blockLines = new StringBuilder();
|
||||
boolean escapeStartQuote = false;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
boolean isLastLine = i == lines.length - 1;
|
||||
line = PsiLiteralUtil.escapeTextBlockCharacters(line, escapeStartQuote, isLastLine, isLastLine);
|
||||
escapeStartQuote = line.endsWith("\"");
|
||||
blockLines.append(line);
|
||||
}
|
||||
return blockLines.toString().split("(?<=\n)");
|
||||
String blockLines = PsiLiteralUtil.escapeTextBlockCharacters(StringUtil.join(lines), true, true, true);
|
||||
return blockLines.split("(?<=\n)");
|
||||
}
|
||||
|
||||
private static String concatenateTextBlockLines(String @NotNull [] lines, int indent) {
|
||||
|
||||
@@ -29,9 +29,9 @@ public class PsiConcatenationUtil {
|
||||
|
||||
/**
|
||||
* @deprecated use {@code buildUnescapedFormatString} instead and use either
|
||||
* {@code com.intellij.openapi.util.text.StringUtil#escapeStringCharacters(java.lang.String)}
|
||||
* {@link StringUtil#escapeStringCharacters(String)}
|
||||
* or
|
||||
* {@code com.intellij.openapi.util.text.StringUtil#escapeTextBlockCharacters(java.lang.String)}
|
||||
* {@link PsiLiteralUtil#escapeTextBlockCharacters(String)}
|
||||
* to escape the resulting string.
|
||||
*/
|
||||
@Deprecated
|
||||
|
||||
@@ -180,7 +180,7 @@ public class PsiLiteralUtil {
|
||||
* @param s original text
|
||||
* @param escapeStartQuote true if first quote should be escaped (e.g. when copy-pasting into text block after two quotes)
|
||||
* @param escapeEndQuote true if last quote should be escaped (e.g. inserting text into text block before closing quotes)
|
||||
* @param escapeSpacesInTheEnd true if spaces in the end of the line should be converted to \040 even if no new line in the end is present
|
||||
* @param escapeSpacesInTheEnd true if spaces in the end of the line should be preserved even if no new line in the end is present
|
||||
*/
|
||||
@NotNull
|
||||
public static String escapeTextBlockCharacters(@NotNull String s, boolean escapeStartQuote,
|
||||
@@ -246,12 +246,12 @@ public class PsiLiteralUtil {
|
||||
i++;
|
||||
}
|
||||
if (i >= s.length() && escapeSpacesInTheEnd) {
|
||||
result.append(StringUtil.repeat("\\040", nSpaces));
|
||||
result.append(StringUtil.repeat(" ", nSpaces - 1)).append("\\s");
|
||||
return i;
|
||||
}
|
||||
int nextIdx = i >= s.length() ? -1 : parseBackSlash(s, i);
|
||||
if (nextIdx != -1 && nextIdx < s.length() && s.charAt(nextIdx) == 'n') {
|
||||
result.append(StringUtil.repeat("\\040", nSpaces));
|
||||
result.append(StringUtil.repeat(" ", nSpaces - 1)).append("\\s");
|
||||
return i;
|
||||
}
|
||||
result.append(StringUtil.repeatSymbol(' ', nSpaces));
|
||||
@@ -324,35 +324,13 @@ public class PsiLiteralUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all unescaped quotes with escaped ones.
|
||||
* If text contains backslash escape sequence it's replaced with a regular backslash.
|
||||
* The rest of the symbols are left unchanged.
|
||||
* Parse backslash at given index. It will be parsed even in case when backslash is represented as unicode escape sequence.
|
||||
*
|
||||
* @param str text
|
||||
* @param idx parse from
|
||||
* @return index where next char starts, -1 otherwise
|
||||
*/
|
||||
@NotNull
|
||||
public static String escapeQuotes(@NotNull String str) {
|
||||
StringBuilder sb = new StringBuilder(str.length());
|
||||
int nSlashes = 0;
|
||||
int idx = 0;
|
||||
while (idx < str.length()) {
|
||||
char c = str.charAt(idx);
|
||||
int nextIdx = parseBackSlash(str, idx);
|
||||
if (nextIdx > 0) {
|
||||
nSlashes++;
|
||||
}
|
||||
else {
|
||||
if (c == '\"' && nSlashes % 2 == 0) {
|
||||
sb.append('\\');
|
||||
}
|
||||
nSlashes = 0;
|
||||
nextIdx = idx + 1;
|
||||
}
|
||||
sb.append(c);
|
||||
idx = nextIdx;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static int parseBackSlash(@NotNull String str, int idx) {
|
||||
public static int parseBackSlash(@NotNull String str, int idx) {
|
||||
char c = str.charAt(idx);
|
||||
if (c != '\\') return -1;
|
||||
int nextIdx = parseEscapedBackSlash(str, idx);
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ class C {
|
||||
void x(int a, int b) {
|
||||
//keep me
|
||||
String s = java.text.MessageFormat.format("""
|
||||
the text
|
||||
the text\s
|
||||
block
|
||||
line2
|
||||
{0}{1} "to" be""", a, b);
|
||||
|
||||
@@ -2,7 +2,7 @@ class C {
|
||||
|
||||
void x(int a, int b) {
|
||||
String s = """
|
||||
the text\n block
|
||||
the text \n block
|
||||
line2
|
||||
""" +
|
||||
a + b + <caret>//keep me
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
class C {
|
||||
String empty = """
|
||||
<html>
|
||||
<html> \s
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
</html> \s
|
||||
""";
|
||||
}
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
class TextBlockMigration {
|
||||
|
||||
void escapeSpaces() {
|
||||
String block = "text \n" +
|
||||
"block\n";
|
||||
String block = "text block \n" +
|
||||
" ";
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Replace with regular string literal" "true"
|
||||
|
||||
class TextBlockMigration {
|
||||
|
||||
void oneLineNoNewLine() {
|
||||
String json = "foobar\n";
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -4,7 +4,8 @@ class TextBlockMigration {
|
||||
|
||||
void escapeSequence() {
|
||||
String oneLineTextBlock = """
|
||||
\u005c"this is one "line"\n text <caret>block\134\u005c\\"
|
||||
\u005c"this is one "line"\n\s\
|
||||
text <caret>block\134\u005c\\"
|
||||
""";
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@ class TextBlockMigration {
|
||||
|
||||
void escapeSpaces() {
|
||||
String block = """
|
||||
text\040\040
|
||||
block<caret>
|
||||
""";
|
||||
text\040\040\
|
||||
block \s<caret>
|
||||
\s""";
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace with regular string literal" "true"
|
||||
|
||||
class TextBlockMigration {
|
||||
|
||||
void oneLineNoNewLine() {
|
||||
String json = """
|
||||
fo<caret>o\
|
||||
bar
|
||||
""";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@ class TextBlockMigration {
|
||||
String string = """
|
||||
foo
|
||||
bar
|
||||
baz\040""".indent(2);
|
||||
baz\s""".indent(2);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -4,10 +4,10 @@ class TextBlockMigration {
|
||||
|
||||
void concatenationWithExtraSpaces() {
|
||||
String code = """
|
||||
<html>\040\040
|
||||
<html> \s
|
||||
<body>
|
||||
</body>
|
||||
</html>\040\040""";
|
||||
</html> \s""";
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -7,7 +7,7 @@ class TextBlockMigration {
|
||||
this concatenation contains
|
||||
three quotes
|
||||
one after another
|
||||
"\"\"""";
|
||||
""\"""";
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -32,7 +32,7 @@ class JavaTextBlocksHighlightingTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
|
||||
fun testPasteNewline() = doTestPaste("\n\n")
|
||||
|
||||
fun testPasteMultilineText() = doTestPaste("<html>\n <body>\n </body>\n</html>")
|
||||
fun testPasteMultilineText() = doTestPaste("<html> \n <body>\n </body>\n</html> ")
|
||||
|
||||
fun testBadEscape() = doTestPaste("\\");
|
||||
|
||||
|
||||
+1
-1
@@ -23,6 +23,6 @@ public class TextBlockBackwardMigrationInspectionTest extends LightQuickFixParam
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_13_PREVIEW;
|
||||
return LanguageLevel.JDK_14_PREVIEW;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@ public class TextBlockMigrationInspectionTest extends LightQuickFixParameterized
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_13_PREVIEW;
|
||||
return LanguageLevel.JDK_14_PREVIEW;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-22
@@ -45,7 +45,7 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_13;
|
||||
return JAVA_14;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,8 +86,8 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
MigrationInvoker migrationInvoker = new MigrationInvoker();
|
||||
BackwardMigrationInvoker backwardMigrationInvoker = new BackwardMigrationInvoker();
|
||||
for (PsiPolyadicExpression concatenation : concatenations) {
|
||||
if (SuppressionUtil.isSuppressed(concatenation, migrationInvoker.getToolId()) ||
|
||||
SuppressionUtil.isSuppressed(concatenation, backwardMigrationInvoker.getToolId())) {
|
||||
if (SuppressionUtil.isSuppressed(concatenation, MigrationInvoker.getToolId()) ||
|
||||
SuppressionUtil.isSuppressed(concatenation, BackwardMigrationInvoker.getToolId())) {
|
||||
continue;
|
||||
}
|
||||
PsiExpression[] operands = concatenation.getOperands();
|
||||
@@ -142,7 +142,6 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
}
|
||||
// IDEA-226395
|
||||
String[] textBlockLines = getTextBlockLines(lines);
|
||||
if (textBlockLines == null) return null;
|
||||
int indent = PsiLiteralUtil.getTextBlockIndent(textBlockLines, true, true);
|
||||
if (indent > 0 && textBlockLines.length > 0 && textBlockLines[textBlockLines.length - 1].endsWith("\n")) indent = 0;
|
||||
if (indent > 0) return null;
|
||||
@@ -150,17 +149,10 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
return StringUtil.join(lines);
|
||||
}
|
||||
|
||||
private static String @Nullable [] getTextBlockLines(String @NotNull [] lines) {
|
||||
String[] blockLines = new String[lines.length];
|
||||
boolean escapeStartQuote = false;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
boolean isLastLine = i == lines.length - 1;
|
||||
line = PsiLiteralUtil.escapeTextBlockCharacters(line, escapeStartQuote, isLastLine, isLastLine);
|
||||
escapeStartQuote = line.endsWith("\"");
|
||||
blockLines[i] = line;
|
||||
}
|
||||
return blockLines;
|
||||
@NotNull
|
||||
private static String @NotNull [] getTextBlockLines(String @NotNull [] lines) {
|
||||
String blockLines = PsiLiteralUtil.escapeTextBlockCharacters(StringUtil.join(lines), true, true, true);
|
||||
return blockLines.split("(?<=\n)");
|
||||
}
|
||||
|
||||
private static <T extends PsiElement> void invokeIntention(@NotNull T element,
|
||||
@@ -206,9 +198,6 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
|
||||
@NotNull
|
||||
String getFixHint();
|
||||
|
||||
@NotNull
|
||||
String getToolId();
|
||||
}
|
||||
|
||||
private static class MigrationInvoker implements ActionInvoker<PsiPolyadicExpression> {
|
||||
@@ -230,8 +219,7 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getToolId() {
|
||||
private static String getToolId() {
|
||||
return "TextBlockMigration";
|
||||
}
|
||||
}
|
||||
@@ -249,8 +237,7 @@ public class JavaTextBlockMigrationPropertyTest extends LightJavaCodeInsightFixt
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getToolId() {
|
||||
private static String getToolId() {
|
||||
return "TextBlockBackwardMigration";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ public class PsiLiteralUtilTest {
|
||||
|
||||
@Test
|
||||
public void testEscapeTextBlockCharacters() {
|
||||
assertEquals("foo\\040\\040\n", PsiLiteralUtil.escapeTextBlockCharacters("foo \\n"));
|
||||
assertEquals("foo \\s\n", PsiLiteralUtil.escapeTextBlockCharacters("foo \\n"));
|
||||
// escapes after 'bar' should be escaped since it's the last line in a text block
|
||||
assertEquals("foo\\040\\040\nbar\\040\\040", PsiLiteralUtil.escapeTextBlockCharacters("foo \\nbar "));
|
||||
assertEquals("foo \\s\nbar \\s", PsiLiteralUtil.escapeTextBlockCharacters("foo \\nbar "));
|
||||
|
||||
assertEquals("", PsiLiteralUtil.escapeTextBlockCharacters(""));
|
||||
// last in line quote should be escaped
|
||||
|
||||
+5
-1
@@ -16,6 +16,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ReplaceConcatenationWithFormatStringIntention extends Intention {
|
||||
|
||||
@@ -111,7 +112,10 @@ public class ReplaceConcatenationWithFormatStringIntention extends Intention {
|
||||
((PsiLiteralExpressionImpl)operand).getLiteralElementType() == JavaTokenType.TEXT_BLOCK_LITERAL);
|
||||
if (textBlocks) {
|
||||
newExpression.append("\"\"\"\n");
|
||||
newExpression.append(PsiLiteralUtil.escapeTextBlockCharacters(formatString));
|
||||
formatString = Arrays.stream(formatString.split("\n"))
|
||||
.map(s -> PsiLiteralUtil.escapeTextBlockCharacters(s))
|
||||
.collect(Collectors.joining("\n"));
|
||||
newExpression.append(formatString);
|
||||
if (insertNewline) {
|
||||
newExpression.append('\n');
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
class TextBlocks {
|
||||
static {
|
||||
System.out.println("""
|
||||
first
|
||||
second
|
||||
first \s\
|
||||
second
|
||||
third""" + <caret>//c1
|
||||
"""
|
||||
_no space
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ class TextBlocks {
|
||||
System.out.println("""
|
||||
first
|
||||
second
|
||||
third
|
||||
third\
|
||||
""" + <caret>//c1
|
||||
" \\forth\"" );
|
||||
}
|
||||
|
||||
+1
-2
@@ -4,7 +4,6 @@ class TextBlocks {
|
||||
System.out.println("""
|
||||
first
|
||||
second
|
||||
third
|
||||
\\for<caret>th\"""");
|
||||
third \\forth\""<caret>"");
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -2,9 +2,8 @@ class TextBlocks {
|
||||
static {
|
||||
//c1
|
||||
System.out.println("""
|
||||
first
|
||||
second
|
||||
third_no sp<caret>ace
|
||||
""");
|
||||
first second
|
||||
third_no space
|
||||
<caret> """);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
class C {
|
||||
String s = """
|
||||
the text\n block
|
||||
the text \n block
|
||||
line2
|
||||
""" +
|
||||
1 + 2 +<caret>//keep me
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
class C {
|
||||
//keep me
|
||||
String s = String.format("""
|
||||
the text
|
||||
the text\s
|
||||
block
|
||||
line2
|
||||
%d%d t<caret>o be""", 1, 2);
|
||||
%d%d <caret>to be""", 1, 2);
|
||||
}
|
||||
Reference in New Issue
Block a user