Skip to content

Commit cbb2abf

Browse files
authored
Added MethodDeclaration wrapping options (#6208)
* Added MethodDeclaration wrapping options * add license * public API generalization * renamed method * Improved based on Sam's WIP * comments bot * refactored for referential equality usage * compare by id * review comments * review comments * show calculation with modified elements
1 parent 93db9c4 commit cbb2abf

13 files changed

Lines changed: 2621 additions & 139 deletions

File tree

rewrite-groovy/src/main/java/org/openrewrite/groovy/format/AutoFormatVisitor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ public J visit(@Nullable Tree tree, P p, Cursor cursor) {
5454
t = new BlankLinesVisitor<>(Style.from(BlankLinesStyle.class, cu, IntelliJ::blankLines), stopAfter)
5555
.visit(t, p, cursor.fork());
5656

57-
t = new WrappingAndBracesVisitor<>(Style.from(WrappingAndBracesStyle.class, cu, IntelliJ::wrappingAndBraces), stopAfter)
58-
.visit(t, p, cursor.fork());
59-
6057
WrappingAndBracesStyle wrappingAndBracesStyle = Style.from(WrappingAndBracesStyle.class, cu, IntelliJ::wrappingAndBraces);
6158
TabsAndIndentsStyle tabsAndIndentsStyle = Style.from(TabsAndIndentsStyle.class, cu, IntelliJ::tabsAndIndents);
6259
SpacesStyle spacesStyle = Style.from(SpacesStyle.class, cu, IntelliJ::spaces);
6360

61+
t = new WrappingAndBracesVisitor<>(spacesStyle, wrappingAndBracesStyle, stopAfter)
62+
.visit(t, p, cursor.fork());
63+
6464
t = new SpacesVisitor<>(
6565
spacesStyle,
6666
Style.from(EmptyForInitializerPadStyle.class, cu),

rewrite-java-test/src/test/java/org/openrewrite/java/format/WrappingAndBracesTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public void defaults(RecipeSpec spec) {
4747
120,
4848
new WrappingAndBracesStyle.IfStatement(false),
4949
new WrappingAndBracesStyle.ChainedMethodCalls(WrapAlways, Arrays.asList("builder", "newBuilder"), false),
50+
new WrappingAndBracesStyle.MethodDeclarationParameters(WrapAlways, false, false, false),
5051
new WrappingAndBracesStyle.Annotations(WrapAlways),
5152
new WrappingAndBracesStyle.Annotations(WrapAlways),
5253
new WrappingAndBracesStyle.Annotations(WrapAlways),
@@ -929,6 +930,7 @@ void annotationWrappingWithNulls() {
929930
120,
930931
new WrappingAndBracesStyle.IfStatement(false),
931932
new WrappingAndBracesStyle.ChainedMethodCalls(DoNotWrap, emptyList(), false),
933+
new WrappingAndBracesStyle.MethodDeclarationParameters(WrapAlways, false, false, false),
932934
null,
933935
null,
934936
null,

rewrite-java/src/main/java/org/openrewrite/java/format/AutoFormatVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public J visit(@Nullable Tree tree, P p, Cursor cursor) {
8080
SpacesStyle spacesStyle = getStyle(SpacesStyle.class, styles, cu, IntelliJ::spaces);
8181
TabsAndIndentsStyle tabsAndIndentsStyle = getStyle(TabsAndIndentsStyle.class, styles, cu, IntelliJ::tabsAndIndents);
8282

83-
t = new WrappingAndBracesVisitor<>(wrappingAndBracesStyle, stopAfter)
83+
t = new WrappingAndBracesVisitor<>(spacesStyle, wrappingAndBracesStyle, stopAfter)
8484
.visitNonNull(t, p, cursor.fork());
8585

8686
t = new SpacesVisitor<>(spacesStyle, getStyle(EmptyForInitializerPadStyle.class, styles, cu), getStyle(EmptyForIteratorPadStyle.class, styles, cu), stopAfter)
@@ -128,7 +128,7 @@ public J visit(@Nullable Tree tree, P p) {
128128
t = (JavaSourceFile) new SpacesVisitor<P>(spacesStyle, getStyle(EmptyForInitializerPadStyle.class, styles, cu), getStyle(EmptyForIteratorPadStyle.class, styles, cu), stopAfter)
129129
.visitNonNull(t, p);
130130

131-
t = (JavaSourceFile) new WrappingAndBracesVisitor<>(wrappingAndBracesStyle, stopAfter)
131+
t = (JavaSourceFile) new WrappingAndBracesVisitor<>(spacesStyle, wrappingAndBracesStyle, stopAfter)
132132
.visitNonNull(t, p);
133133

134134
t = (JavaSourceFile) new NormalizeTabsOrSpacesVisitor<>(tabsAndIndentsStyle, stopAfter)
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.format;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.Value;
20+
import org.jspecify.annotations.Nullable;
21+
import org.openrewrite.Cursor;
22+
import org.openrewrite.internal.ListUtils;
23+
import org.openrewrite.java.JavaIsoVisitor;
24+
import org.openrewrite.java.service.SourcePositionService;
25+
import org.openrewrite.java.style.SpacesStyle;
26+
import org.openrewrite.java.style.WrappingAndBracesStyle;
27+
import org.openrewrite.java.tree.J;
28+
import org.openrewrite.java.tree.JRightPadded;
29+
import org.openrewrite.java.tree.JavaSourceFile;
30+
import org.openrewrite.java.tree.Space;
31+
import org.openrewrite.style.LineWrapSetting;
32+
33+
import java.util.Objects;
34+
35+
@Value
36+
@EqualsAndHashCode(callSuper = false)
37+
public class WrapMethodDeclarationParameters<P> extends JavaIsoVisitor<P> {
38+
39+
SpacesStyle spacesStyle;
40+
WrappingAndBracesStyle style;
41+
42+
@Override
43+
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, P ctx) {
44+
J.MethodDeclaration m = super.visitMethodDeclaration(method, ctx);
45+
46+
try {
47+
// styles are parent loaded, so the getters may or may not be present and they may or may not return null
48+
if (style != null && style.getMethodDeclarationParameters() != null && style.getMethodDeclarationParameters().getWrap() != LineWrapSetting.DoNotWrap) {
49+
if (m.getParameters().size() <= 1) {
50+
return m;
51+
}
52+
JavaSourceFile sourceFile = getCursor().firstEnclosing(JavaSourceFile.class);
53+
if (style.getMethodDeclarationParameters().getWrap() == LineWrapSetting.ChopIfTooLong) {
54+
if (sourceFile == null) {
55+
return m;
56+
}
57+
Cursor minimized = minimize(getCursor(), ctx);
58+
if (sourceFile.service(SourcePositionService.class).positionOf(minimized, ((J.MethodDeclaration)minimized.getValue()).getPadding().getParameters()).getMaxColumn() <= style.getHardWrapAt()) {
59+
return m;
60+
}
61+
}
62+
63+
if (style.getMethodDeclarationParameters().getCloseNewLine()) {
64+
m = m.getPadding().withParameters(m.getPadding().getParameters().getPadding().withElements(ListUtils.mapLast(m.getPadding().getParameters().getPadding().getElements(), rightPaddedParam -> {
65+
Space after = rightPaddedParam.getAfter();
66+
if (after.getWhitespace().contains("\n")) {
67+
return rightPaddedParam;
68+
}
69+
if (after.getComments().isEmpty()) {
70+
after = after.withWhitespace("\n");
71+
} else {
72+
after = after.withComments(ListUtils.mapLast(after.getComments(), comment -> comment.withSuffix("\n")));
73+
}
74+
return rightPaddedParam.withAfter(after);
75+
})));
76+
}
77+
78+
m = m.withParameters(ListUtils.map(m.getParameters(), (paramIndex, param) -> {
79+
if (param instanceof J.Empty) {
80+
return param;
81+
}
82+
Space prefix = param.getPrefix();
83+
if (prefix.getComments().isEmpty()) {
84+
if ((paramIndex != 0 || style.getMethodDeclarationParameters().getOpenNewLine()) && !prefix.getWhitespace().contains("\n")) {
85+
prefix = prefix.withWhitespace("\n");
86+
}
87+
} else {
88+
int index = -1;
89+
for (int i = prefix.getComments().size() - 1; i >= 0; i--) {
90+
if (prefix.getComments().get(i).getSuffix().contains("\n")) {
91+
index = i;
92+
break;
93+
}
94+
}
95+
if (index == -1 && (paramIndex != 0 || style.getMethodDeclarationParameters().getOpenNewLine())) {
96+
if (!prefix.getWhitespace().contains("\n")) {
97+
prefix = prefix.withWhitespace("\n");
98+
}
99+
}
100+
}
101+
return param.withPrefix(prefix);
102+
}));
103+
}
104+
} catch (NoSuchMethodError | NoSuchFieldError ignore) {
105+
// Styles are parent-first loaded and this can happen if the style is from a older version of the runtime. Can be removed in future releases.
106+
}
107+
108+
return m;
109+
}
110+
111+
public Cursor minimize(Cursor cursor, P ctx) {
112+
if (cursor.getValue() instanceof J) {
113+
J cursorValue = cursor.getValue();
114+
J j = new JavaIsoVisitor<P>() {
115+
@Override
116+
public @Nullable <T> JRightPadded<T> visitRightPadded(@Nullable JRightPadded<T> right, JRightPadded.Location loc, P ctx) {
117+
switch (loc) {
118+
case METHOD_DECLARATION_PARAMETER:
119+
case RECORD_STATE_VECTOR: {
120+
if (right != null && right.getElement() instanceof J) {
121+
//noinspection unchecked
122+
right = right
123+
.withAfter(minimized(right.getAfter()))
124+
.withElement(((J) right.getElement()).withPrefix(minimized(((J) right.getElement()).getPrefix())));
125+
}
126+
break;
127+
}
128+
}
129+
return super.visitRightPadded(right, loc, ctx);
130+
}
131+
132+
@Override
133+
public Space visitSpace(@Nullable Space space, Space.Location loc, P ctx) {
134+
if (space == null) {
135+
return super.visitSpace(space, loc, ctx);
136+
}
137+
if (space == cursorValue.getPrefix()) {
138+
return space;
139+
}
140+
switch (loc) {
141+
case BLOCK_PREFIX:
142+
case MODIFIER_PREFIX:
143+
case METHOD_DECLARATION_PARAMETER_SUFFIX:
144+
case METHOD_DECLARATION_PARAMETERS:
145+
case METHOD_SELECT_SUFFIX:
146+
case METHOD_INVOCATION_ARGUMENTS:
147+
case METHOD_INVOCATION_ARGUMENT_SUFFIX:
148+
case METHOD_INVOCATION_NAME:
149+
case RECORD_STATE_VECTOR_SUFFIX: {
150+
space = minimized(space);
151+
break;
152+
}
153+
}
154+
return super.visitSpace(space, loc, ctx);
155+
}
156+
157+
//IntelliJ does not format when comments are present.
158+
private Space minimized(Space space) {
159+
if (space.getComments().isEmpty()) {
160+
return space.getWhitespace().isEmpty() ? space : Space.EMPTY;
161+
}
162+
return space;
163+
}
164+
}.visit(cursorValue, ctx);
165+
if (j != cursor.getValue()) {
166+
j = new MinimumViableSpacingVisitor<>(null).visit(j, ctx);
167+
j = new SpacesVisitor<>(spacesStyle, null, null).visit(j, ctx);
168+
}
169+
return new Cursor(cursor.getParent(), Objects.requireNonNull(j));
170+
}
171+
throw new IllegalArgumentException("Can only minimize J elements.");
172+
}
173+
}

rewrite-java/src/main/java/org/openrewrite/java/format/WrappingAndBracesVisitor.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.openrewrite.Tree;
2121
import org.openrewrite.internal.ListUtils;
2222
import org.openrewrite.java.JavaIsoVisitor;
23+
import org.openrewrite.java.style.IntelliJ;
24+
import org.openrewrite.java.style.SpacesStyle;
2325
import org.openrewrite.java.style.WrappingAndBracesStyle;
2426
import org.openrewrite.java.tree.*;
2527

@@ -36,13 +38,15 @@ public class WrappingAndBracesVisitor<P> extends JavaIsoVisitor<P> {
3638
private final Tree stopAfter;
3739

3840
@SuppressWarnings({"FieldCanBeLocal", "unused"})
41+
private final SpacesStyle spacesStyle;
3942
private final WrappingAndBracesStyle style;
4043

4144
public WrappingAndBracesVisitor(WrappingAndBracesStyle style) {
42-
this(style, null);
45+
this(IntelliJ.spaces(), style, null);
4346
}
4447

45-
public WrappingAndBracesVisitor(WrappingAndBracesStyle style, @Nullable Tree stopAfter) {
48+
public WrappingAndBracesVisitor(SpacesStyle spacesStyle, WrappingAndBracesStyle style, @Nullable Tree stopAfter) {
49+
this.spacesStyle = spacesStyle;
4650
this.style = style;
4751
this.stopAfter = stopAfter;
4852
}
@@ -114,7 +118,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, P
114118
);
115119
}
116120
}
117-
return m;
121+
return (J.MethodDeclaration) new WrapMethodDeclarationParameters<>(spacesStyle, style).visit(m, p, getCursor().getParentTreeCursor());
118122
}
119123

120124
@Override

0 commit comments

Comments
 (0)