Skip to content

Commit af36054

Browse files
authored
Merge pull request #175 from openjavaformat/fix/comment-after-opening-delimiter
Indent a comment after an opening delimiter like the code after it
2 parents 05b43c8 + 06edc5b commit af36054

8 files changed

Lines changed: 247 additions & 1 deletion

‎open-java-format/src/main/java/com/palantir/javaformat/OpsBuilder.java‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,26 @@ public void close() {
309309
add(CloseOp.make());
310310
}
311311

312+
/**
313+
* Keep the comments before the next token inside the level just opened. {@link #build} puts the comments before a
314+
* token ahead of the {@link OpenOp}s right before it, so that a comment before a statement or an expression stays
315+
* out of their levels. Right after an opening delimiter, such as the {@code (} of a for loop, that takes the
316+
* comment, and the line break after it, out of the level that indents what follows the delimiter.
317+
*/
318+
public void fenceComments() {
319+
add(CommentFence.FENCE);
320+
}
321+
322+
/** Where {@link #build} stops looking back over {@link OpenOp}s for the place of a token's comments. */
323+
private enum CommentFence implements Op {
324+
FENCE;
325+
326+
@Override
327+
public void add(DocBuilder builder) {
328+
throw new IllegalStateException("build() drops comment fences");
329+
}
330+
}
331+
312332
/** Return the text of the next {@link Input.Token}, or absent if there is none. */
313333
public Optional<String> peekToken() {
314334
return peekToken(0);
@@ -523,7 +543,7 @@ public OpsOutput build() {
523543
* when possible.
524544
*/
525545
Input.Token token = tokenOp.getToken();
526-
int j = i; // Where to insert toksBefore before.
546+
int j = i; // Where to insert toksBefore before: ahead of the OpenOps before the token, up to a fence.
527547
while (0 < j && ops.get(j - 1) instanceof OpenOp) {
528548
--j;
529549
}
@@ -669,6 +689,9 @@ public OpsOutput build() {
669689
}
670690
}
671691
Op op = ops.get(i);
692+
if (op == CommentFence.FENCE) {
693+
continue;
694+
}
672695
if (afterForcedBreak
673696
&& (op instanceof NonBreakingSpace
674697
|| (op instanceof Break b

‎open-java-format/src/main/java/com/palantir/javaformat/java/JavaInputAstVisitor.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ public Void visitAssert(AssertTree node, Void unused) {
605605
token("assert");
606606
builder.space();
607607
builder.open(node.getDetail() == null ? ZERO : plusFour);
608+
builder.fenceComments();
608609
scan(node.getCondition(), null);
609610
if (node.getDetail() != null) {
610611
builder.breakOp(" ");
@@ -912,6 +913,7 @@ public boolean visitEnumDeclaration(ClassTree node) {
912913
builder.close();
913914
if (builder.peekToken().equals(Optional.of(";"))) {
914915
builder.open(plusTwo);
916+
builder.fenceComments();
915917
token(";");
916918
builder.forcedBreak();
917919
dropEmptyDeclarations();
@@ -1010,6 +1012,7 @@ public Void visitForLoop(ForLoopTree node, Void unused) {
10101012
builder.space();
10111013
token("(");
10121014
builder.open(plusFour);
1015+
builder.fenceComments();
10131016
builder.open(
10141017
node.getInitializer().size() > 1 && node.getInitializer().get(0) instanceof ExpressionStatementTree
10151018
? plusFour
@@ -1942,6 +1945,7 @@ public Void visitTry(TryTree node, Void unused) {
19421945
if (!node.getResources().isEmpty()) {
19431946
token("(");
19441947
builder.open(node.getResources().size() > 1 ? plusFour : ZERO);
1948+
builder.fenceComments();
19451949
boolean first = true;
19461950
for (Tree resource : node.getResources()) {
19471951
if (!first) {
@@ -2382,6 +2386,7 @@ private void visitCatchClause(CatchTree node, AllowTrailingBlankLine allowTraili
23822386
builder.space();
23832387
token("(");
23842388
builder.open(plusFour);
2389+
builder.fenceComments();
23852390
VariableTree ex = node.getParameter();
23862391
if (ex.getType() instanceof UnionTypeTree) {
23872392
builder.open(ZERO);
@@ -3179,6 +3184,7 @@ void addTypeArguments(List<? extends Tree> typeArguments, Indent plusIndent) {
31793184
}
31803185
token("<");
31813186
builder.open(plusIndent);
3187+
builder.fenceComments();
31823188
boolean first = true;
31833189
for (Tree typeArgument : typeArguments) {
31843190
if (!first) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# A comment on its own line right after `assert` stays inside the condition at the continuation indent, together
2+
# with the code after it, when the assertion has a detail message (google-java-format#1501, #171).
3+
----------
4+
class T {
5+
void f(int x, int y) {
6+
assert
7+
// comment
8+
x > 0 : "positive";
9+
assert
10+
// comment
11+
x > 0 : "positive";
12+
assert
13+
/* why */
14+
x <
15+
y :
16+
"x below " + "y";
17+
}
18+
}
19+
----------
20+
class T {
21+
void f(int x, int y) {
22+
assert
23+
// comment
24+
x > 0
25+
: "positive";
26+
assert
27+
// comment
28+
x > 0
29+
: "positive";
30+
assert
31+
/* why */
32+
x < y
33+
: "x below " + "y";
34+
}
35+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# A comment on its own line before the `;` that ends the constants of an enum stays at the indent of the constants,
2+
# and so does the `;` (google-java-format#1501, #171).
3+
----------
4+
enum E1 {
5+
A,
6+
// comment
7+
;
8+
}
9+
10+
enum E2 {
11+
A, B
12+
// comment
13+
;
14+
void f() {}
15+
}
16+
17+
enum E3 { A
18+
/* comment */
19+
;
20+
}
21+
----------
22+
enum E1 {
23+
A,
24+
// comment
25+
;
26+
}
27+
28+
enum E2 {
29+
A,
30+
B
31+
// comment
32+
;
33+
34+
void f() {}
35+
}
36+
37+
enum E3 {
38+
A
39+
/* comment */
40+
;
41+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# A comment on its own line right after the `(` of a for loop stays inside the header at the continuation indent,
2+
# which breaks the header, so the condition and the update get a line each (google-java-format#1501, #171). A block
3+
# comment that shares its line with the initializer stays with it, on the line of the header when that fits.
4+
----------
5+
class T {
6+
void f(int n) {
7+
for (
8+
// comment
9+
int i = 0; i < n; i++) {}
10+
for (
11+
/* comment */
12+
int i = 0; i < n; i++) {}
13+
for (
14+
/* c */ int i = 0;
15+
i < n;
16+
i++) {}
17+
}
18+
}
19+
----------
20+
class T {
21+
void f(int n) {
22+
for (
23+
// comment
24+
int i = 0;
25+
i < n;
26+
i++) {}
27+
for (
28+
/* comment */
29+
int i = 0;
30+
i < n;
31+
i++) {}
32+
for (/* c */ int i = 0; i < n; i++) {}
33+
}
34+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# A comment on its own line right after the `(` of a multi-catch clause stays inside the clause at the continuation
2+
# indent, with the caught types after it (google-java-format#1501, #171).
3+
----------
4+
class T {
5+
void f() {
6+
try {
7+
g();
8+
} catch (
9+
// comment
10+
IllegalArgumentException | IllegalStateException e) {
11+
}
12+
try { g(); } catch (
13+
/* comment */
14+
IllegalArgumentException
15+
| IllegalStateException e) { h(e); }
16+
}
17+
}
18+
----------
19+
class T {
20+
void f() {
21+
try {
22+
g();
23+
} catch (
24+
// comment
25+
IllegalArgumentException | IllegalStateException e) {
26+
}
27+
try {
28+
g();
29+
} catch (
30+
/* comment */
31+
IllegalArgumentException | IllegalStateException e) {
32+
h(e);
33+
}
34+
}
35+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# A comment on its own line right after the `(` of a try with several resources stays inside the resources at the
2+
# continuation indent, with the first resource after it (google-java-format#1501, #171).
3+
----------
4+
class T {
5+
void f(AutoCloseable a, AutoCloseable b) throws Exception {
6+
try (
7+
// comment
8+
AutoCloseable r1 = a; AutoCloseable r2 = b) {}
9+
try (
10+
/* comment */
11+
AutoCloseable r1 = a;
12+
AutoCloseable r2 = b) {
13+
use(r1, r2);
14+
}
15+
}
16+
}
17+
----------
18+
class T {
19+
void f(AutoCloseable a, AutoCloseable b) throws Exception {
20+
try (
21+
// comment
22+
AutoCloseable r1 = a;
23+
AutoCloseable r2 = b) {}
24+
try (
25+
/* comment */
26+
AutoCloseable r1 = a;
27+
AutoCloseable r2 = b) {
28+
use(r1, r2);
29+
}
30+
}
31+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# A comment on its own line right after the `<` of explicit type arguments stays inside them at the continuation
2+
# indent, with the type after it, in a constructor call and in a method reference (google-java-format#1501, #171).
3+
----------
4+
class T {
5+
<U> T() {}
6+
7+
static <U> void g() {}
8+
9+
void f() {
10+
new <
11+
// comment
12+
String>T();
13+
Runnable r =
14+
T
15+
::<
16+
// comment
17+
String>g;
18+
new <
19+
/* comment */
20+
String> T();
21+
}
22+
}
23+
----------
24+
class T {
25+
<U> T() {}
26+
27+
static <U> void g() {}
28+
29+
void f() {
30+
new <
31+
// comment
32+
String>T();
33+
Runnable r = T
34+
::<
35+
// comment
36+
String>g;
37+
new <
38+
/* comment */
39+
String>T();
40+
}
41+
}

0 commit comments

Comments
 (0)