IDEA-378172 [java]: put elements on separate lines for annotations and array initializers

GitOrigin-RevId: 5278e8f5a9bcc8ec6bb88a897c414242a9f19048
This commit is contained in:
Bas Leijdekkers
2026-06-10 19:42:11 +00:00
committed by intellij-monorepo-bot
parent 22f19b1823
commit cb3c8df171
25 changed files with 313 additions and 6 deletions
@@ -944,6 +944,10 @@
implementationClass="com.intellij.codeInsight.intention.impl.lists.JavaSplitJoinParametersContext"/>
<listSplitJoinContext language="JAVA"
implementationClass="com.intellij.codeInsight.intention.impl.lists.JavaSplitJoinRecordComponentsContext"/>
<listSplitJoinContext language="JAVA"
implementationClass="com.intellij.codeInsight.intention.impl.lists.JavaSplitJoinArrayInitializerContext"/>
<listSplitJoinContext language="JAVA"
implementationClass="com.intellij.codeInsight.intention.impl.lists.JavaSplitJoinAnnotationAttributesContext"/>
<regExpModifierProvider language="JAVA" implementationClass="com.intellij.codeInsight.JavaRegExpModifierProvider"/>
<colorProvider implementation="com.intellij.codeInsight.daemon.impl.JavaColorProvider"/>
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.intellij.codeInsight.daemon.impl.JavaLineMarkerProvider"/>
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.intention.impl.lists
import com.intellij.application.options.CodeStyle
@@ -18,15 +18,14 @@ import com.intellij.psi.PsiParameterList
import com.intellij.psi.PsiRecordHeader
import com.intellij.psi.util.PsiTreeUtil
public abstract class AbstractJavaSplitJoinContext : CommaListSplitJoinContext() {
internal abstract class AbstractJavaSplitJoinContext : CommaListSplitJoinContext() {
override fun isValidIntermediateElement(data: ListWithElements, element: PsiElement): Boolean {
return super.isValidIntermediateElement(data, element) ||
element is PsiComment && element.tokenType === JavaTokenType.C_STYLE_COMMENT
}
}
public class JavaSplitJoinArgumentsContext : AbstractJavaSplitJoinContext() {
internal class JavaSplitJoinArgumentsContext : AbstractJavaSplitJoinContext() {
override fun extractData(context: PsiElement): ListWithElements? =
getCallArgumentsList(context)?.let { ListWithElements(it, it.expressions.asList()) }
@@ -51,7 +50,7 @@ public class JavaSplitJoinArgumentsContext : AbstractJavaSplitJoinContext() {
override fun getSplitText(data: ListWithElements): String = JavaBundle.message("intention.family.put.arguments.on.separate.lines")
}
public class JavaSplitJoinParametersContext : AbstractJavaSplitJoinContext() {
internal class JavaSplitJoinParametersContext : AbstractJavaSplitJoinContext() {
override fun extractData(context: PsiElement): ListWithElements? =
PsiTreeUtil.getParentOfType(context, PsiParameterList::class.java, false)?.let { ListWithElements(it, it.parameters.toList()) }
@@ -65,7 +64,7 @@ public class JavaSplitJoinParametersContext : AbstractJavaSplitJoinContext() {
override fun getJoinText(data: ListWithElements): String = JavaBundle.message("intention.family.put.parameters.on.one.line")
}
public class JavaSplitJoinRecordComponentsContext : AbstractJavaSplitJoinContext() {
internal class JavaSplitJoinRecordComponentsContext : AbstractJavaSplitJoinContext() {
override fun extractData(context: PsiElement): ListWithElements? =
PsiTreeUtil.getParentOfType(context, PsiRecordHeader::class.java, false, PsiCodeBlock::class.java, PsiExpression::class.java)
?.let { ListWithElements(it, it.recordComponents.toList()) }
@@ -0,0 +1,62 @@
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.intention.impl.lists;
import com.intellij.application.options.CodeStyle;
import com.intellij.java.JavaBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.actions.lists.JoinOrSplit;
import com.intellij.openapi.editor.actions.lists.ListWithElements;
import com.intellij.psi.PsiAnnotationParameterList;
import com.intellij.psi.PsiArrayInitializerMemberValue;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Bas Leijdekkers
*/
final class JavaSplitJoinAnnotationAttributesContext extends AbstractJavaSplitJoinContext {
@Override
public @Nullable ListWithElements extractData(@NotNull PsiElement context) {
PsiElement parent = PsiTreeUtil.getParentOfType(context, PsiAnnotationParameterList.class, PsiArrayInitializerMemberValue.class);
return switch (parent) {
case PsiAnnotationParameterList list -> new ListWithElements(parent, List.of(list.getAttributes()));
case PsiArrayInitializerMemberValue value -> new ListWithElements(parent, List.of(value.getInitializers()));
case null, default -> null;
};
}
@Override
public boolean needHeadBreak(@NotNull ListWithElements data, @NotNull PsiElement firstElement, @NotNull JoinOrSplit mode) {
if (mode == JoinOrSplit.JOIN) return false;
return data.getList() instanceof PsiArrayInitializerMemberValue
? CodeStyle.getLanguageSettings(firstElement.getContainingFile(), JavaLanguage.INSTANCE).ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE
: CodeStyle.getCustomSettings(firstElement.getContainingFile(), JavaCodeStyleSettings.class).NEW_LINE_AFTER_LPAREN_IN_ANNOTATION;
}
@Override
public boolean needTailBreak(@NotNull ListWithElements data, @NotNull PsiElement lastElement, @NotNull JoinOrSplit mode) {
if (mode == JoinOrSplit.JOIN) return false;
return data.getList() instanceof PsiArrayInitializerMemberValue
? CodeStyle.getLanguageSettings(lastElement.getContainingFile(), JavaLanguage.INSTANCE).ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE
: CodeStyle.getCustomSettings(lastElement.getContainingFile(), JavaCodeStyleSettings.class).RPAREN_ON_NEW_LINE_IN_ANNOTATION;
}
@Override
public @NotNull String getJoinText(@NotNull ListWithElements data) {
return data.getList() instanceof PsiArrayInitializerMemberValue
? JavaBundle.message("intention.family.put.array.initializer.expressions.on.one.line")
: JavaBundle.message("intention.family.put.annotation.attributes.on.one.line");
}
@Override
public @NotNull String getSplitText(@NotNull ListWithElements data) {
return data.getList() instanceof PsiArrayInitializerMemberValue
? JavaBundle.message("intention.family.put.array.initializer.expressions.on.separate.lines")
: JavaBundle.message("intention.family.put.annotation.attributes.on.separate.lines");
}
}
@@ -0,0 +1,49 @@
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.intention.impl.lists;
import com.intellij.application.options.CodeStyle;
import com.intellij.java.JavaBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.actions.lists.JoinOrSplit;
import com.intellij.openapi.editor.actions.lists.ListWithElements;
import com.intellij.psi.PsiArrayInitializerExpression;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Bas Leijdekkers
*/
final class JavaSplitJoinArrayInitializerContext extends AbstractJavaSplitJoinContext {
@Override
public @Nullable ListWithElements extractData(@NotNull PsiElement context) {
PsiArrayInitializerExpression expression = PsiTreeUtil.getParentOfType(context, PsiArrayInitializerExpression.class, false);
return expression == null ? null : new ListWithElements(expression, List.of(expression.getInitializers()));
}
@Override
public boolean needHeadBreak(@NotNull ListWithElements data, @NotNull PsiElement firstElement, @NotNull JoinOrSplit mode) {
return mode == JoinOrSplit.SPLIT &&
CodeStyle.getLanguageSettings(firstElement.getContainingFile(), JavaLanguage.INSTANCE).ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE;
}
@Override
public boolean needTailBreak(@NotNull ListWithElements data, @NotNull PsiElement lastElement, @NotNull JoinOrSplit mode) {
return mode == JoinOrSplit.SPLIT &&
CodeStyle.getLanguageSettings(lastElement.getContainingFile(), JavaLanguage.INSTANCE).ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE;
}
@Override
public @NotNull String getSplitText(@NotNull ListWithElements data) {
return JavaBundle.message("intention.family.put.array.initializer.expressions.on.separate.lines");
}
@Override
public @NotNull String getJoinText(@NotNull ListWithElements data) {
return JavaBundle.message("intention.family.put.array.initializer.expressions.on.one.line");
}
}
@@ -0,0 +1,11 @@
// "Put annotation attributes on one line" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,8 @@
// "Put array elements on one line" "true-preview"
class X {
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))), @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))})
void x() {}
}
@@ -0,0 +1,6 @@
// "Put array elements on one line" "true-preview"
class X {
String[] ss = new String[] {"one", "two", "three"};
}
@@ -0,0 +1,13 @@
// "Put annotation attributes on separate lines" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "Success response",
content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,15 @@
// "Put annotation attributes on separate lines" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Success response",
content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))
),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,9 @@
// "Put array elements on separate lines" "true-preview"
class X {
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))})
void x() {}
}
@@ -0,0 +1,11 @@
// "Put array elements on separate lines" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,8 @@
// "Put array elements on separate lines" "true-preview"
class X {
String[] ss = new String[] {"one",
"two",
"three"};
}
@@ -0,0 +1,8 @@
// "Put array elements on separate lines" "true-preview"
class X {
String[] ss = {"one",
"two",
"three"};
}
@@ -0,0 +1,10 @@
// "Put array elements on separate lines" "true-preview"
class X {
String[] ss = new String[] {
"one",
"two",
"three"
};
}
@@ -0,0 +1,15 @@
// "Put annotation attributes on one line" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(<caret>
responseCode = "200",
description = "Success response",
content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))
),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,11 @@
// "Put array elements on one line" "true-preview"
class X {
@ApiResponses(value = {<caret>
@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,8 @@
// "Put array elements on one line" "true-preview"
class X {
String[] ss = new String[] {<caret>"one",
"two",
"three"};
}
@@ -0,0 +1,11 @@
// "Put annotation attributes on separate lines" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(responseCode = "200"<caret>, description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,11 @@
// "Put annotation attributes on separate lines" "true-preview"
class X {
@ApiResponses(value = {
@ApiResponse(responseCode = "200"<caret>, description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))),
@ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))
})
void x() {}
}
@@ -0,0 +1,8 @@
// "Put array elements on separate lines" "true-preview"
class X {
@ApiResponses(value = {<caret>@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))), @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))})
void x() {}
}
@@ -0,0 +1,8 @@
// "Put array elements on separate lines" "true-preview"
class X {
@ApiResponses(value = {<caret>@ApiResponse(responseCode = "200", description = "Success response", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON, schema = @Schema(implementation = Procedure.class, type = "array"))), @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = PageAttributes.MediaType.APPLICATION_JSON))})
void x() {}
}
@@ -0,0 +1,6 @@
// "Put array elements on separate lines" "true-preview"
class X {
String[] ss = new String[] {<caret>"one", "two", "three"};
}
@@ -0,0 +1,6 @@
// "Put array elements on separate lines" "true-preview"
class X {
String[] ss = {<caret>"one", "two", "three"};
}
@@ -0,0 +1,6 @@
// "Put array elements on separate lines" "true-preview"
class X {
String[] ss = new String[] {<caret>"one", "two", "three"};
}
@@ -877,6 +877,10 @@ intention.family.put.parameters.on.one.line=Put parameters on one line
intention.family.put.parameters.on.separate.lines=Put parameters on separate lines
intention.family.put.record.components.on.one.line=Put record components on one line
intention.family.put.record.components.on.separate.lines=Put record components on separate lines
intention.family.put.array.initializer.expressions.on.one.line=Put array elements on one line
intention.family.put.array.initializer.expressions.on.separate.lines=Put array elements on separate lines
intention.family.put.annotation.attributes.on.one.line=Put annotation attributes on one line
intention.family.put.annotation.attributes.on.separate.lines=Put annotation attributes on separate lines
intention.family.replace.optional.ispresent.condition.with.functional.style.expression=Replace Optional presence condition with functional style expression
intention.family.sort.content=Sort content
intention.family.swap.if.statements=Swap 'if' statements