Skip to content

Commit 621f173

Browse files
committed
Add braceStyle option with same-line (default) and next-line choices.
1 parent db0f54b commit 621f173

File tree

10 files changed

+1005
-53
lines changed

10 files changed

+1005
-53
lines changed

src/options.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,21 @@ export default {
3131
{ value: "end", description: "" }
3232
],
3333
description: "Where to print operators when binary expressions wrap lines."
34+
},
35+
braceStyle: {
36+
type: "choice",
37+
category: "Java",
38+
default: "same-line",
39+
choices: [
40+
{
41+
value: "same-line",
42+
description: "Put opening braces on same line (K&R style)"
43+
},
44+
{
45+
value: "next-line",
46+
description: "Put opening braces on new lines (Allman style)"
47+
}
48+
],
49+
description: "Placement of opening braces."
3450
}
3551
} satisfies SupportOptions;

src/printers/blocks-and-statements.ts

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ const {
2525
} = builders;
2626

2727
export default {
28-
block(path, print) {
29-
return printBlock(path, printBlockStatements(path, print));
28+
block(path, print, options) {
29+
return printBlock(path, printBlockStatements(path, print), options);
3030
},
3131

3232
local_variable_declaration: printVariableDeclaration,
@@ -47,7 +47,7 @@ export default {
4747
: [expression, ";"];
4848
},
4949

50-
if_statement(path, print) {
50+
if_statement(path, print, options) {
5151
const statement = ["if ", path.call(print, "conditionNode")];
5252

5353
if (path.node.consequenceNode.type === ";") {
@@ -63,6 +63,8 @@ export default {
6363
const danglingComments = printDanglingComments(path);
6464
if (danglingComments.length) {
6565
statement.push(hardline, ...danglingComments, hardline);
66+
} else if (options?.braceStyle === "next-line") {
67+
statement.push(hardline);
6668
} else {
6769
const ifHasBlock = path.node.consequenceNode.type === SyntaxType.Block;
6870
statement.push(ifHasBlock ? " " : hardline);
@@ -91,8 +93,8 @@ export default {
9193
]);
9294
},
9395

94-
switch_block(path, print) {
95-
return printBlock(path, path.map(print, "namedChildren"));
96+
switch_block(path, print, options) {
97+
return printBlock(path, path.map(print, "namedChildren"), options);
9698
},
9799

98100
switch_block_statement_group(path, print) {
@@ -192,15 +194,16 @@ export default {
192194
}
193195
},
194196

195-
do_statement(path, print) {
197+
do_statement(path, print, options) {
196198
const hasEmptyStatement = path.node.bodyNode.type === ";";
197-
return [
198-
"do",
199-
hasEmptyStatement ? ";" : [" ", path.call(print, "bodyNode")],
200-
" while ",
201-
path.call(print, "conditionNode"),
202-
";"
203-
];
199+
const isNextLine = options?.braceStyle === "next-line";
200+
const whilePrefix = isNextLine ? [hardline, "while "] : " while ";
201+
const body = hasEmptyStatement
202+
? ";"
203+
: isNextLine
204+
? path.call(print, "bodyNode")
205+
: [" ", path.call(print, "bodyNode")];
206+
return ["do", body, whilePrefix, path.call(print, "conditionNode"), ";"];
204207
},
205208

206209
for_statement(path, print) {
@@ -330,7 +333,7 @@ export default {
330333
];
331334
},
332335

333-
try_statement(path, print) {
336+
try_statement(path, print, options) {
334337
const parts = ["try", path.call(print, "bodyNode")];
335338

336339
path.each(child => {
@@ -342,23 +345,26 @@ export default {
342345
}
343346
}, "namedChildren");
344347

348+
if (options?.braceStyle === "next-line") {
349+
return parts;
350+
}
345351
return join(" ", parts);
346352
},
347353

348-
catch_clause(path, print) {
354+
catch_clause(path, print, options) {
349355
const catchFormalParameterIndex = path.node.namedChildren.findIndex(
350356
({ type }) => type === SyntaxType.CatchFormalParameter
351357
);
352-
return [
353-
"catch ",
354-
group(
355-
indentInParentheses(
356-
path.call(print, "namedChildren", catchFormalParameterIndex)
357-
)
358-
),
359-
" ",
360-
path.call(print, "bodyNode")
361-
];
358+
const params = group(
359+
indentInParentheses(
360+
path.call(print, "namedChildren", catchFormalParameterIndex)
361+
)
362+
);
363+
const body = path.call(print, "bodyNode");
364+
if (options?.braceStyle === "next-line") {
365+
return [hardline, "catch ", params, body];
366+
}
367+
return ["catch ", params, " ", body];
362368
},
363369

364370
catch_formal_parameter(path, print) {
@@ -383,27 +389,31 @@ export default {
383389
return join([line, "| "], path.map(print, "namedChildren"));
384390
},
385391

386-
finally_clause(path, print) {
392+
finally_clause(path, print, options) {
393+
if (options?.braceStyle === "next-line") {
394+
return [hardline, "finally", path.call(print, "namedChildren", 0)];
395+
}
387396
return ["finally ", path.call(print, "namedChildren", 0)];
388397
},
389398

390-
try_with_resources_statement(path, print) {
391-
const parts = [
392-
"try",
393-
path.call(print, "resourcesNode"),
394-
path.call(print, "bodyNode")
395-
];
399+
try_with_resources_statement(path, print, options) {
400+
const resources = path.call(print, "resourcesNode");
401+
const body = path.call(print, "bodyNode");
402+
const clauses: Doc[] = [];
396403

397404
path.each(child => {
398405
if (
399406
child.node.type === SyntaxType.CatchClause ||
400407
child.node.type === SyntaxType.FinallyClause
401408
) {
402-
parts.push(print(child));
409+
clauses.push(print(child));
403410
}
404411
}, "namedChildren");
405412

406-
return join(" ", parts);
413+
if (options?.braceStyle === "next-line") {
414+
return ["try ", resources, body, ...clauses];
415+
}
416+
return join(" ", ["try", resources, body, ...clauses]);
407417
},
408418

409419
resource_specification(path, print) {

src/printers/classes.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const { group, hardline, indent, indentIfBreak, join, line, softline } =
1919
builders;
2020

2121
export default {
22-
class_declaration(path, print) {
22+
class_declaration(path, print, options) {
2323
const parts: Doc[] = ["class ", path.call(print, "nameNode")];
2424
const definedClauses = definedKeys(path.node, [
2525
"superclassNode",
@@ -42,12 +42,14 @@ export default {
4242
hasChild(path, clause) ? [separator, path.call(print, clause)] : []
4343
);
4444
const hasBody = path.node.bodyNode.namedChildren.length > 0;
45+
const afterClauses =
46+
options?.braceStyle === "next-line" ? "" : hasBody ? separator : " ";
4547
const clauseGroup = [
4648
hasTypeParameters && !hasMultipleClauses ? clauses : indent(clauses),
47-
hasBody ? separator : " "
49+
afterClauses
4850
];
4951
parts.push(hasMultipleClauses ? clauseGroup : group(clauseGroup));
50-
} else {
52+
} else if (options?.braceStyle !== "next-line") {
5153
parts.push(" ");
5254
}
5355

@@ -89,14 +91,16 @@ export default {
8991
return join([",", line], path.map(print, "namedChildren"));
9092
},
9193

92-
class_body(path, print) {
94+
class_body(path, print, options) {
9395
return printBlock(
9496
path,
9597
printBodyDeclarations(
9698
path,
9799
print,
98-
(path.parent as NamedNode | null)?.type === SyntaxType.ClassDeclaration
99-
)
100+
(path.parent as NamedNode | null)?.type ===
101+
SyntaxType.ClassDeclaration && options?.braceStyle !== "next-line"
102+
),
103+
options
100104
);
101105
},
102106

@@ -261,8 +265,8 @@ export default {
261265
return [modifiers, group(declaration), " ", path.call(print, "bodyNode")];
262266
},
263267

264-
constructor_body(path, print) {
265-
return printBlock(path, printBlockStatements(path, print));
268+
constructor_body(path, print, options) {
269+
return printBlock(path, printBlockStatements(path, print), options);
266270
},
267271

268272
explicit_constructor_invocation(path, print) {
@@ -379,7 +383,7 @@ export default {
379383
if (declarations.length) {
380384
contents.push(";", hardline, ...declarations);
381385
}
382-
return printBlock(path, contents.length ? [contents] : []);
386+
return printBlock(path, contents.length ? [contents] : [], options);
383387
},
384388

385389
enum_constant(path, print) {

src/printers/helpers.ts

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,22 @@ export function printArrayInitializer(
129129
) {
130130
if (!path.node.namedChildren.length) {
131131
const danglingComments = printDanglingComments(path);
132-
return danglingComments.length
133-
? ["{", indent([hardline, ...danglingComments]), hardline, "}"]
134-
: "{}";
132+
if (danglingComments.length) {
133+
if (options.braceStyle === "next-line") {
134+
const isNested =
135+
path.parent?.type === SyntaxType.ArrayInitializer ||
136+
path.parent?.type === SyntaxType.ElementValueArrayInitializer;
137+
const block = [
138+
"{",
139+
indent([hardline, ...danglingComments]),
140+
hardline,
141+
"}"
142+
];
143+
return isNested ? block : [hardline, ...block];
144+
}
145+
return ["{", indent([hardline, ...danglingComments]), hardline, "}"];
146+
}
147+
return "{}";
135148
}
136149

137150
const list = join([",", line], path.map(print, "namedChildren"));
@@ -140,10 +153,26 @@ export function printArrayInitializer(
140153
list.push(ifBreak(","));
141154
}
142155

156+
if (options.braceStyle === "next-line") {
157+
const isNested =
158+
path.parent?.type === SyntaxType.ArrayInitializer ||
159+
path.parent?.type === SyntaxType.ElementValueArrayInitializer;
160+
const block = ["{", indent([softline, ...list]), softline, "}"];
161+
return isNested ? block : [hardline, ...block];
162+
}
163+
143164
return group(["{", indent([softline, ...list]), softline, "}"]);
144165
}
145166

146-
export function printBlock(path: NamedNodePath, contents: Doc[]) {
167+
export function printBlock(
168+
path: NamedNodePath,
169+
contents: Doc[],
170+
options?: JavaParserOptions
171+
) {
172+
if (options?.braceStyle === "next-line") {
173+
return printBlockNextLine(path, contents);
174+
}
175+
147176
if (contents.length) {
148177
return group([
149178
"{",
@@ -195,6 +224,40 @@ export function printBlock(path: NamedNodePath, contents: Doc[]) {
195224
: ["{", hardline, "}"];
196225
}
197226

227+
function printBlockNextLine(path: NamedNodePath, contents: Doc[]) {
228+
const parentType = path.parent?.type;
229+
const isChildOfBodyDeclaration =
230+
parentType != null &&
231+
[
232+
SyntaxType.AnnotationTypeBody,
233+
SyntaxType.ClassBody,
234+
SyntaxType.EnumBody,
235+
SyntaxType.InterfaceBody
236+
].includes(parentType);
237+
const prefix = isChildOfBodyDeclaration ? [] : [hardline];
238+
239+
if (contents.length) {
240+
return [
241+
...prefix,
242+
"{",
243+
indent([hardline, ...join(hardline, contents)]),
244+
hardline,
245+
"}"
246+
];
247+
}
248+
const danglingComments = printDanglingComments(path);
249+
if (danglingComments.length) {
250+
return [
251+
...prefix,
252+
"{",
253+
indent([hardline, ...danglingComments]),
254+
hardline,
255+
"}"
256+
];
257+
}
258+
return [...prefix, "{", hardline, "}"];
259+
}
260+
198261
export function printBlockStatements(
199262
path: NamedNodePath<
200263
| SyntaxType.Block

src/printers/interfaces.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ export default {
7272
]);
7373
},
7474

75-
interface_body(path, print) {
76-
return printBlock(path, printBodyDeclarations(path, print));
75+
interface_body(path, print, options) {
76+
return printBlock(path, printBodyDeclarations(path, print), options);
7777
},
7878

7979
constant_declaration: printVariableDeclaration,
@@ -91,8 +91,8 @@ export default {
9191
return parts;
9292
},
9393

94-
annotation_type_body(path, print) {
95-
return printBlock(path, printBodyDeclarations(path, print));
94+
annotation_type_body(path, print, options) {
95+
return printBlock(path, printBodyDeclarations(path, print), options);
9696
},
9797

9898
annotation_type_element_declaration(path, print) {

src/printers/packages-and-modules.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export default {
134134
return join(" ", parts);
135135
},
136136

137-
module_body(path, print) {
137+
module_body(path, print, options) {
138138
return printBlock(
139139
path,
140140
path.map(
@@ -143,7 +143,8 @@ export default {
143143
? [hardline, print(child)]
144144
: print(child),
145145
"namedChildren"
146-
)
146+
),
147+
options
147148
);
148149
},
149150

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "braceStyle": "next-line" }

0 commit comments

Comments
 (0)