mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
TextBlockMigrationInspection: preserve meaningful spaces at the beginning of each line (IDEA-226395)
GitOrigin-RevId: a204f736a29271ebe83fd5f5222d0b1ebd28ddbf
This commit is contained in:
committed by
intellij-monorepo-bot
parent
325f22705f
commit
7a86f1e752
@@ -46,6 +46,7 @@ public class TextBlockMigrationInspection extends AbstractBaseJavaLocalInspectio
|
||||
for (PsiExpression operand : operands) {
|
||||
PsiLiteralExpressionImpl literal = getLiteralExpression(operand);
|
||||
if (literal == null) return;
|
||||
if (nNewLines > 1) continue;
|
||||
String text = literal.getText();
|
||||
int newLineIdx = getNewLineIndex(text, 0);
|
||||
if (newLineIdx == -1) continue;
|
||||
@@ -57,7 +58,6 @@ public class TextBlockMigrationInspection extends AbstractBaseJavaLocalInspectio
|
||||
nNewLines++;
|
||||
newLineIdx = getNewLineIndex(text, newLineIdx + 1);
|
||||
}
|
||||
if (nNewLines > 1) break;
|
||||
}
|
||||
if (nNewLines <= 1) return;
|
||||
holder.registerProblem(expression, firstNewLineTextRange,
|
||||
@@ -106,22 +106,55 @@ public class TextBlockMigrationInspection extends AbstractBaseJavaLocalInspectio
|
||||
}
|
||||
|
||||
private static void replaceWithTextBlock(@NotNull PsiExpression[] operands, @NotNull PsiExpression toReplace) {
|
||||
StringBuilder textBlock = new StringBuilder();
|
||||
textBlock.append("\"\"\"\n");
|
||||
String[] lines = getContentLines(operands);
|
||||
if (lines == null) return;
|
||||
String textBlock = getTextBlock(lines);
|
||||
PsiReplacementUtil.replaceExpression(toReplace, textBlock, new CommentTracker());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getTextBlock(@NotNull String[] lines) {
|
||||
int indent = PsiLiteralUtil.getTextBlockIndent(lines);
|
||||
// we need additional indent call only when significant trailing line is missing
|
||||
if (indent > 0 && lines.length > 0 && lines[lines.length - 1].endsWith("\n")) indent = 0;
|
||||
String content = getTextBlockContent(lines, indent);
|
||||
return "\"\"\"\n" + content + "\"\"\"" + (indent > 0 ? ".indent(" + indent + ")" : "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getTextBlockContent(@NotNull String[] lines, int indent) {
|
||||
StringBuilder content = new StringBuilder();
|
||||
boolean escapeStartQuote = false;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
boolean isLastLine = i == lines.length - 1;
|
||||
if (indent < line.length()) line = line.substring(indent);
|
||||
line = PsiLiteralUtil.escapeTextBlockCharacters(line, escapeStartQuote, isLastLine, isLastLine);
|
||||
escapeStartQuote = line.endsWith("\"");
|
||||
content.append(line);
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String[] getContentLines(@NotNull PsiExpression[] operands) {
|
||||
String[] lines = new String[operands.length];
|
||||
for (int i = 0; i < operands.length; i++) {
|
||||
PsiExpression operand = operands[i];
|
||||
PsiLiteralExpressionImpl literal = getLiteralExpression(operand);
|
||||
if (literal == null) return;
|
||||
String text = getLiteralText(literal);
|
||||
if (text == null) return;
|
||||
boolean isLastLine = i == operands.length - 1;
|
||||
text = PsiLiteralUtil.escapeTextBlockCharacters(text, escapeStartQuote, isLastLine, isLastLine);
|
||||
escapeStartQuote = text.endsWith("\"");
|
||||
textBlock.append(text);
|
||||
if (literal == null) return null;
|
||||
String line = getLiteralText(literal);
|
||||
if (line == null) return null;
|
||||
lines[i] = line;
|
||||
}
|
||||
textBlock.append("\"\"\"");
|
||||
PsiReplacementUtil.replaceExpression(toReplace, textBlock.toString(), new CommentTracker());
|
||||
return lines;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getLiteralText(@NotNull PsiLiteralExpressionImpl literal) {
|
||||
if (literal.getLiteralElementType() == JavaTokenType.STRING_LITERAL) return literal.getInnerText();
|
||||
Object value = literal.getValue();
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,11 +184,4 @@ public class TextBlockMigrationInspection extends AbstractBaseJavaLocalInspectio
|
||||
if (literal == null || literal.getLiteralElementType() == JavaTokenType.TEXT_BLOCK_LITERAL) return null;
|
||||
return literal;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getLiteralText(@NotNull PsiLiteralExpressionImpl literal) {
|
||||
if (literal.getLiteralElementType() == JavaTokenType.STRING_LITERAL) return literal.getInnerText();
|
||||
Object value = literal.getValue();
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public class PsiLiteralUtil {
|
||||
* <li>All escaped quotes are unescaped.</li>
|
||||
* <li>Every third quote is escaped. If escapeStartQuote / escapeEndQuote is set then start / end quote is also escaped.</li>
|
||||
* <li>All spaces before \n are converted to \040 escape sequence.
|
||||
* This is required since spaces in the end of the line are trimmed by default (see JEP 355).
|
||||
* This is required since spaces in the end of the line are trimmed by default (see JEP 368).
|
||||
* If escapeSpacesInTheEnd is set, then all spaces before the end of the line are converted even if new line in the end is missing. </li>
|
||||
* <li> All new line escape sequences are interpreted. </li>
|
||||
* <li>Rest of the content is processed as is.</li>
|
||||
@@ -372,4 +372,22 @@ public class PsiLiteralUtil {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines how many whitespaces would be excluded at the beginning of each line of text block content.
|
||||
* See JEP 368 for more details.
|
||||
*
|
||||
* @param lines text block content
|
||||
*/
|
||||
public static int getTextBlockIndent(@NotNull String[] lines) {
|
||||
int prefix = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
int indent = 0;
|
||||
while (indent < line.length() && Character.isWhitespace(line.charAt(indent))) indent++;
|
||||
if (indent == line.length() && i < lines.length - 1) lines[i] = "";
|
||||
else if (indent < prefix) prefix = indent;
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
+2
-14
@@ -158,7 +158,7 @@ public class PsiLiteralExpressionImpl
|
||||
String[] lines = getTextBlockLines();
|
||||
if (lines == null) return null;
|
||||
|
||||
int prefix = getTextBlockIndent(lines);
|
||||
int prefix = PsiLiteralUtil.getTextBlockIndent(lines);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
@@ -176,19 +176,7 @@ public class PsiLiteralExpressionImpl
|
||||
public int getTextBlockIndent() {
|
||||
String[] lines = getTextBlockLines();
|
||||
if (lines == null) return -1;
|
||||
return getTextBlockIndent(lines);
|
||||
}
|
||||
|
||||
private static int getTextBlockIndent(String[] lines) {
|
||||
int prefix = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
int indent = 0;
|
||||
while (indent < line.length() && Character.isWhitespace(line.charAt(indent))) indent++;
|
||||
if (indent == line.length() && i < lines.length - 1) lines[i] = "";
|
||||
else if (indent < prefix) prefix = indent;
|
||||
}
|
||||
return prefix;
|
||||
return PsiLiteralUtil.getTextBlockIndent(lines);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// "Replace with text block" "true"
|
||||
|
||||
class TextBlockMigration {
|
||||
|
||||
void concatenationWithSpacesAtTheBeginning() {
|
||||
String body = """
|
||||
<body>
|
||||
<p>
|
||||
</p>
|
||||
</body>""".indent(2);
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Replace with text block" "true"
|
||||
|
||||
class TextBlockMigration {
|
||||
|
||||
void concatenationWithSpacesAtTheBeginning() {
|
||||
String body = " <body>\n<caret>" +
|
||||
" <p>\n" +
|
||||
" </p>\n" +
|
||||
" </body>";
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Fix all 'Text block can be used' problems in file" "false"
|
||||
|
||||
class TextBlockMigration {
|
||||
|
||||
void concatenationWithTextBlock() {
|
||||
String concat = "foo\n<caret>" + "bar\n" +
|
||||
"""
|
||||
baz""";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user