Java: fix text block selection behaviour in text blocks with escaped newlines (IDEA-282073)

GitOrigin-RevId: 430c4c67698acdb46d1756c5ed3bc12d6b01a5bd
This commit is contained in:
Bas Leijdekkers
2023-10-30 10:30:22 +00:00
committed by intellij-monorepo-bot
parent 09d35674b1
commit 661fc8569c
6 changed files with 36 additions and 30 deletions
@@ -16,20 +16,12 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
import static com.intellij.psi.impl.source.BasicElementTypes.BASIC_STRING_LITERALS;
import static com.intellij.psi.impl.source.BasicJavaElementType.BASIC_LITERAL_EXPRESSION;
public class LiteralSelectioner extends AbstractBasicBackBasicSelectioner {
@Override
public boolean canSelect(@NotNull PsiElement e) {
PsiElement parent = e.getParent();
return isStringLiteral(e) || isStringLiteral(parent);
}
private static boolean isStringLiteral(PsiElement element) {
return BasicJavaAstTreeUtil.is(BasicJavaAstTreeUtil.toNode(element), BASIC_STRING_LITERALS)
&& element.getText().startsWith("\"")
&& element.getText().endsWith("\"");
return BasicJavaAstTreeUtil.is(BasicJavaAstTreeUtil.toNode(e), BASIC_STRING_LITERALS);
}
@Override
@@ -42,26 +34,19 @@ public class LiteralSelectioner extends AbstractBasicBackBasicSelectioner {
if (node == null) {
return null;
}
boolean textBlock = BasicJavaAstTreeUtil.isTextBlock(node);
StringLiteralLexer lexer = textBlock
? new StringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.TEXT_BLOCK_LITERAL, true, "s{")
: new StringLiteralLexer('"', JavaTokenType.STRING_LITERAL);
TextRange range = node.getTextRange();
SelectWordUtil.addWordHonoringEscapeSequences(editorText, range, cursorOffset,
new StringLiteralLexer('\"', JavaTokenType.STRING_LITERAL),
result);
ASTNode literalExpression = null;
if (BasicJavaAstTreeUtil.is(node, BASIC_LITERAL_EXPRESSION)) {
literalExpression = node;
}
if (literalExpression == null) {
ASTNode parent = node.getTreeParent();
if (BasicJavaAstTreeUtil.is(parent, BASIC_LITERAL_EXPRESSION)) {
literalExpression = parent;
}
}
PsiElement literalPsiExpression = BasicJavaAstTreeUtil.toPsi(literalExpression);
if (literalExpression != null && literalPsiExpression != null && BasicJavaAstTreeUtil.isTextBlock(literalExpression)) {
SelectWordUtil.addWordHonoringEscapeSequences(editorText, range, cursorOffset, lexer, result);
if (textBlock) {
int contentStart = StringUtil.indexOf(editorText, '\n', range.getStartOffset());
if (contentStart == -1) return result;
contentStart += 1;
int indent = BasicLiteralUtil.getTextBlockIndent(literalPsiExpression);
String[] lines = BasicLiteralUtil.getTextBlockLines(node.getText());
if (lines == null) return result;
int indent = BasicLiteralUtil.getTextBlockIndent(lines);
if (indent == -1) return result;
for (int i = 0; i < indent; i++) {
if (editorText.charAt(contentStart + i) == '\n') return result;
@@ -335,11 +335,10 @@ public final class BasicJavaAstTreeUtil {
return findParent(e, elementType);
}
public static boolean isTextBlock(@Nullable ASTNode expression) {
return findChildByType(expression, JavaTokenType.TEXT_BLOCK_LITERAL) != null;
public static boolean isTextBlock(@NotNull ASTNode node) {
return node.getElementType() == JavaTokenType.TEXT_BLOCK_LITERAL;
}
@Nullable
public static ASTNode getMethodExpression(@Nullable ASTNode element) {
if (!is(element, BASIC_METHOD_CALL_EXPRESSION)) {
@@ -348,7 +347,6 @@ public final class BasicJavaAstTreeUtil {
return element.getFirstChildNode();
}
@Nullable
public static ASTNode getExpressionList(@Nullable ASTNode element) {
return findChildByType(element, BASIC_EXPRESSION_LIST);
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight;
import com.intellij.BasicDefaultLightProjectDescriptor;
@@ -196,6 +196,8 @@ public abstract class AbstractBasicJavaSelectWordTest extends SelectWordTestBase
public void testTextBlockEmptyLines() { doTest("java"); }
public void testTextBlockEscapedLineEndings() { doTest("java"); }
public void testLineComments() { doTest("java"); }
public void testLineCommentsAtStart() { doTest("java"); }
@@ -0,0 +1,7 @@
class Test {
String textBlock = """
Info: \
<selection>textInSameLin<caret>eButEscapedInSourCode</selection> \
textInSameLineButEscapedInSourCode2 \
""";
}
@@ -0,0 +1,7 @@
class Test {
String textBlock = """
<selection>Info: \
textInSameLin<caret>eButEscapedInSourCode \
textInSameLineButEscapedInSourCode2 \</selection>
""";
}
@@ -0,0 +1,7 @@
class Test {
String textBlock = """
Info: \
textInSameLin<caret>eButEscapedInSourCode \
textInSameLineButEscapedInSourCode2 \
""";
}