mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[Java. Code Formatting] Add support to align last line in text block if there is no symbols
IDEA-351758 GitOrigin-RevId: fca446697ac8eb5f1c24fbb3a1bf72924a48a65a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
69c61c874b
commit
a87cef51de
@@ -1322,7 +1322,7 @@
|
||||
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.TypeOfVariableMacro"/>
|
||||
<codeInspection.InspectionExtension implementation="com.intellij.codeInspection.ex.JavaInspectionExtensionsFactory"/>
|
||||
<postFormatProcessor implementation="com.intellij.psi.impl.source.codeStyle.ImportPostFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.intellij.psi.formatter.java.AdjustWhitespaceLineTextBlockReformatPostProcessor"/>
|
||||
<!--<preFormatProcessor implementation="com.intellij.psi.formatter.java.AdjustWhitespaceLineTextBlockReformatPostProcessor"/>-->
|
||||
<postFormatProcessor implementation="com.intellij.psi.impl.source.codeStyle.BracePostFormatProcessor"/>
|
||||
<preFormatProcessor implementation="com.intellij.psi.impl.source.codeStyle.FormatCommentsProcessor"/>
|
||||
<elementSignatureProvider implementation="com.intellij.codeInsight.folding.impl.JavaElementSignatureProvider"/>
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiLiteralUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -57,7 +56,7 @@ public final class JavaFormatterUtil {
|
||||
* @param node1 node to check
|
||||
* @param node2 node to check
|
||||
* @return {@code true} if given nodes are binary expressions and have the same priority;
|
||||
* {@code false} otherwise
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public static boolean areSamePriorityBinaryExpressions(ASTNode node1, ASTNode node2) {
|
||||
if (node1 == null || node2 == null) {
|
||||
@@ -83,7 +82,7 @@ public final class JavaFormatterUtil {
|
||||
* if there's a line break after it and "keep line breaks" is on.
|
||||
*
|
||||
* @param settings The current settings
|
||||
* @param node The node to check.
|
||||
* @param node The node to check.
|
||||
* @return True for call chunk start.
|
||||
*/
|
||||
static boolean isStartOfCallChunk(@NotNull CommonCodeStyleSettings settings, @NotNull ASTNode node) {
|
||||
@@ -127,9 +126,9 @@ public final class JavaFormatterUtil {
|
||||
* @return wrap to use for the sub-blocks of the given block
|
||||
*/
|
||||
static @Nullable Wrap createDefaultWrap(ASTBlock block,
|
||||
CommonCodeStyleSettings settings,
|
||||
JavaCodeStyleSettings javaSettings,
|
||||
ReservedWrapsProvider reservedWrapsProvider) {
|
||||
CommonCodeStyleSettings settings,
|
||||
JavaCodeStyleSettings javaSettings,
|
||||
ReservedWrapsProvider reservedWrapsProvider) {
|
||||
ASTNode node = block.getNode();
|
||||
Wrap wrap = block.getWrap();
|
||||
if (node == null) return null;
|
||||
@@ -211,11 +210,11 @@ public final class JavaFormatterUtil {
|
||||
* {@code null} otherwise
|
||||
*/
|
||||
static @Nullable Wrap arrangeChildWrap(ASTNode child,
|
||||
ASTNode parent,
|
||||
CommonCodeStyleSettings settings,
|
||||
JavaCodeStyleSettings javaSettings,
|
||||
Wrap suggestedWrap,
|
||||
AbstractJavaBlock reservedWrapsProvider) {
|
||||
ASTNode parent,
|
||||
CommonCodeStyleSettings settings,
|
||||
JavaCodeStyleSettings javaSettings,
|
||||
Wrap suggestedWrap,
|
||||
AbstractJavaBlock reservedWrapsProvider) {
|
||||
ASTNode directParent = child.getTreeParent();
|
||||
int role = ((CompositeElement)directParent).getChildRole(child);
|
||||
|
||||
@@ -291,7 +290,8 @@ public final class JavaFormatterUtil {
|
||||
ASTNode last = prev.getLastChildNode();
|
||||
if (last != null && last.getElementType() == JavaElementType.ANNOTATION) {
|
||||
if (javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isModifierListWithSingleAnnotation(prev, JavaElementType.FIELD) ||
|
||||
javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION_IN_PARAMETER && isModifierListWithSingleAnnotation(prev, JavaElementType.PARAMETER) ||
|
||||
javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION_IN_PARAMETER &&
|
||||
isModifierListWithSingleAnnotation(prev, JavaElementType.PARAMETER) ||
|
||||
isAnnotationAfterKeyword(last)
|
||||
) {
|
||||
return Wrap.createWrap(WrapType.NONE, false);
|
||||
@@ -456,7 +456,10 @@ public final class JavaFormatterUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int getAnnotationWrapType(ASTNode parent, ASTNode child, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
|
||||
private static int getAnnotationWrapType(ASTNode parent,
|
||||
ASTNode child,
|
||||
CommonCodeStyleSettings settings,
|
||||
JavaCodeStyleSettings javaSettings) {
|
||||
IElementType nodeType = parent.getElementType();
|
||||
|
||||
if (nodeType == JavaElementType.METHOD) {
|
||||
@@ -528,9 +531,9 @@ public final class JavaFormatterUtil {
|
||||
* Traverses the children of the node and collects nodes with type method calls or reference expressions to the list.
|
||||
* If the quantity of the call expressions is greater than {@link JavaFormatterUtil#CALL_EXPRESSION_DEPTH}, call expressions will not be
|
||||
* collected, and you should not format them.
|
||||
* @param nodes List in which the method add nodes
|
||||
* @param node Node to traverse
|
||||
*
|
||||
* @param nodes List in which the method add nodes
|
||||
* @param node Node to traverse
|
||||
*/
|
||||
public static void collectCallExpressionNodes(@NotNull List<? super ASTNode> nodes, @NotNull ASTNode node) {
|
||||
ArrayDeque<ASTNode> stack = new ArrayDeque<>(CALL_EXPRESSION_DEPTH);
|
||||
@@ -541,51 +544,81 @@ public final class JavaFormatterUtil {
|
||||
return;
|
||||
}
|
||||
ASTNode currentNode = stack.removeLast();
|
||||
if (!FormatterUtil.containsWhiteSpacesOnly(currentNode)) {
|
||||
IElementType type = currentNode.getElementType();
|
||||
if (type == JavaElementType.METHOD_CALL_EXPRESSION ||
|
||||
type == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
ASTNode firstChild = currentNode.getFirstChildNode();
|
||||
currentNode = FormatterUtil.getNextNonWhitespaceSibling(currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, firstChild);
|
||||
}
|
||||
else {
|
||||
nodes.add(currentNode);
|
||||
currentNode = FormatterUtil.getNextNonWhitespaceSibling(currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, currentNode);
|
||||
}
|
||||
} else {
|
||||
if (!FormatterUtil.containsWhiteSpacesOnly(currentNode)) {
|
||||
IElementType type = currentNode.getElementType();
|
||||
if (type == JavaElementType.METHOD_CALL_EXPRESSION ||
|
||||
type == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
ASTNode firstChild = currentNode.getFirstChildNode();
|
||||
currentNode = FormatterUtil.getNextNonWhitespaceSibling(currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, firstChild);
|
||||
}
|
||||
else {
|
||||
nodes.add(currentNode);
|
||||
currentNode = FormatterUtil.getNextNonWhitespaceSibling(currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, currentNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentNode = FormatterUtil.getNextNonWhitespaceSibling(currentNode);
|
||||
ContainerUtil.addIfNotNull(stack, currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts text ranges corresponding to the lines in a given literal multiline text.
|
||||
*
|
||||
* @param text the literal text to extract text ranges from
|
||||
* @param indent the number of spaces used for indentation
|
||||
* @param shouldTreatWholeLine specifies whether the entire line should be treated as a text range or
|
||||
* @param text the literal text to extract text ranges from
|
||||
* @param indent the number of spaces used for indentation
|
||||
* @return a list of {@code TextRange} objects representing the extracted text ranges
|
||||
*/
|
||||
public static @NotNull List<TextRange> extractTextRangesFromLiteralText(@NotNull String text, int indent, boolean shouldTreatWholeLine) {
|
||||
public static @NotNull List<TextRange> extractTextRangesFromLiteralText(@NotNull String text, int indent) {
|
||||
List<TextRange> linesRanges = new ArrayList<>();
|
||||
|
||||
boolean isLastLine = false;
|
||||
int start = StringUtil.indexOf(text, '\n', 3);
|
||||
if (start == -1) return Collections.emptyList();
|
||||
linesRanges.add(new TextRange(0, start));
|
||||
start += 1;
|
||||
|
||||
while (start < text.length()) {
|
||||
int end = StringUtil.indexOf(text, '\n', start);
|
||||
if (end == -1) end = text.length();
|
||||
if (start + indent < end && !shouldTreatWholeLine) start += indent;
|
||||
if (start != end || shouldTreatWholeLine) linesRanges.add(new TextRange(start, end));
|
||||
if (end == -1) {
|
||||
isLastLine = true;
|
||||
end = text.length();
|
||||
}
|
||||
if (start + indent <= end) {
|
||||
int quoteStartIndex = end - 3;
|
||||
if (!isLastLine && allEmpty(start + indent, end, text)) {
|
||||
// todo here we can delete and the last \s\s\s"""
|
||||
start = end;
|
||||
}
|
||||
else if (isLastLine && allEmpty(start + indent, quoteStartIndex, text) && isEndsWithTripleQuote(quoteStartIndex, end, text)) {
|
||||
start = quoteStartIndex;
|
||||
}
|
||||
else {
|
||||
start += indent;
|
||||
}
|
||||
}
|
||||
else {
|
||||
start = end;
|
||||
}
|
||||
linesRanges.add(new TextRange(start, end));
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
return linesRanges;
|
||||
}
|
||||
|
||||
private static boolean isEndsWithTripleQuote(int start, int end, @NotNull String text) {
|
||||
if (end - start != 3 || start < 0) return false;
|
||||
String tripleQuote = text.substring(start, end);
|
||||
return tripleQuote.equals("\"\"\"");
|
||||
}
|
||||
|
||||
private static boolean allEmpty(int i, int end, @NotNull String text) {
|
||||
for (int j = i; j < end; j++) {
|
||||
if(!Character.isWhitespace(text.charAt(j))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.intellij.formatting.*;
|
||||
import com.intellij.formatting.alignment.AlignmentStrategy;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiLiteralExpression;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
|
||||
@@ -57,7 +56,7 @@ public class TextBlockBlock extends AbstractJavaBlock {
|
||||
if (indent == -1) return Collections.emptyList();
|
||||
String text = literal.getText();
|
||||
|
||||
return extractTextRangesFromLiteralText(text, indent, false);
|
||||
return extractTextRangesFromLiteralText(text, indent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
<caret>
|
||||
<caret>
|
||||
""";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
<caret>
|
||||
<caret>
|
||||
""";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
<caret>
|
||||
<caret>
|
||||
""";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
<caret>""";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
<caret>""";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
d d ds \t"""<caret>;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
d d ds \t"""<caret>;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
d d ds \t<caret>""";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
d d ds \t<caret>""";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
<caret> """;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
<caret>""";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
<caret>""";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Formatter {
|
||||
void foo() {
|
||||
String s2 = """
|
||||
a
|
||||
<caret>""";
|
||||
}
|
||||
}
|
||||
+21
-1
@@ -9,7 +9,7 @@ import com.intellij.psi.codeStyle.CommonCodeStyleSettings
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings
|
||||
import com.intellij.testFramework.LightPlatformCodeInsightTestCase
|
||||
|
||||
class AdjustWhitespaceLineTextBlockReformatPostProcessorTest : LightPlatformCodeInsightTestCase() {
|
||||
class TextBlockBlankLinesFormatterTest : LightPlatformCodeInsightTestCase() {
|
||||
override fun getTestDataPath(): String = "${JavaTestUtil.getJavaTestDataPath()}/psi/formatter/java/textBlock/"
|
||||
|
||||
fun testWhitespacesLessThanAlignment() = doTest()
|
||||
@@ -71,6 +71,26 @@ class AdjustWhitespaceLineTextBlockReformatPostProcessorTest : LightPlatformCode
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testLastLineWithoutSymbolsAfterAlignment() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testLastLineWithSymbolsAfterAlignment() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testLastLineWithoutSymbolsBeforeAlignment() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testLastLineWithSymbolsBeforeAlignment() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testEmptyLastLine() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
private fun getCommonSettings(): CommonCodeStyleSettings = currentCodeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user