Skip to content

Commit 4a8fbbb

Browse files
committed
Add braceStyle option with same-line (default) and next-line choices.
1 parent 2cc5bb1 commit 4a8fbbb

96 files changed

Lines changed: 1389 additions & 278 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/prettier-plugin-java/src/options.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,5 +283,21 @@ export default {
283283
{ value: "end", description: "" }
284284
],
285285
description: "Where to print operators when binary expressions wrap lines."
286+
},
287+
braceStyle: {
288+
type: "choice",
289+
category: "Java",
290+
default: "same-line",
291+
choices: [
292+
{
293+
value: "same-line",
294+
description: "Put opening braces on same line (K&R style)"
295+
},
296+
{
297+
value: "next-line",
298+
description: "Put opening braces on new lines (Allman style)"
299+
}
300+
],
301+
description: "Placement of opening braces."
286302
}
287303
} satisfies SupportOptions;

packages/prettier-plugin-java/src/printers/arrays.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import {
22
printArrayInitializer,
33
printList,
4+
map,
45
type JavaNodePrinters
56
} from "./helpers.js";
7+
import { builders } from "prettier/doc";
8+
9+
const { join, softline } = builders;
610

711
export default {
812
arrayInitializer(path, print, options) {
@@ -14,7 +18,11 @@ export default {
1418
);
1519
},
1620

17-
variableInitializerList(path, print) {
21+
variableInitializerList(path, print, options) {
22+
const items = map(path, print, "variableInitializer");
23+
if (options?.braceStyle === "next-line") {
24+
return join([",", softline], items);
25+
}
1826
return printList(path, print, "variableInitializer");
1927
}
2028
} satisfies Partial<JavaNodePrinters>;

packages/prettier-plugin-java/src/printers/blocks-and-statements.ts

Lines changed: 122 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
map,
1212
onlyDefinedKey,
1313
printBlock,
14+
formatWithBraces,
1415
printDanglingComments,
1516
printSingle,
1617
printWithModifiers,
@@ -20,11 +21,11 @@ import {
2021
const { group, hardline, ifBreak, indent, join, line, softline } = builders;
2122

2223
export default {
23-
block(path, print) {
24+
block(path, print, options) {
2425
const statements = path.node.children.blockStatements
2526
? (call(path, print, "blockStatements") as Doc[])
2627
: [];
27-
return printBlock(path, statements.length ? [statements] : []);
28+
return printBlock(path, statements.length ? [statements] : [], options);
2829
},
2930

3031
blockStatements(path, print) {
@@ -81,29 +82,47 @@ export default {
8182

8283
statementExpression: printSingle,
8384

84-
ifStatement(path, print) {
85+
ifStatement(path, print, options) {
8586
const { children } = path.node;
8687
const hasEmptyStatement = isEmptyStatement(children.statement[0]);
88+
const ifHasBlock =
89+
children.statement[0].children.statementWithoutTrailingSubstatement?.[0]
90+
.children.block !== undefined;
91+
const ifSpacing =
92+
options.braceStyle === "next-line" && !ifHasBlock ? hardline : " ";
8793
const statement: Doc[] = [
8894
"if ",
8995
indentInParentheses(call(path, print, "expression")),
90-
hasEmptyStatement ? ";" : [" ", call(path, print, "statement", 0)]
96+
hasEmptyStatement ? ";" : [ifSpacing, call(path, print, "statement", 0)]
9197
];
9298
if (children.Else) {
9399
const danglingComments = printDanglingComments(path);
94100
if (danglingComments.length) {
95101
statement.push(hardline, ...danglingComments, hardline);
96102
} else {
97-
const elseHasBlock =
98-
children.statement[0].children
99-
.statementWithoutTrailingSubstatement?.[0].children.block !==
100-
undefined;
101-
statement.push(elseHasBlock ? " " : hardline);
103+
statement.push(
104+
options.braceStyle === "next-line"
105+
? hardline
106+
: ifHasBlock
107+
? " "
108+
: hardline
109+
);
102110
}
103111
const elseHasEmptyStatement = isEmptyStatement(children.statement[1]);
112+
const elseHasBlock =
113+
children.statement[1].children.statementWithoutTrailingSubstatement?.[0]
114+
.children.block !== undefined;
115+
const elseBodyIsIf =
116+
children.statement[1].children.ifStatement !== undefined;
117+
const elseSpacing =
118+
options.braceStyle === "next-line" && !elseHasBlock && !elseBodyIsIf
119+
? hardline
120+
: " ";
104121
statement.push(
105122
"else",
106-
elseHasEmptyStatement ? ";" : [" ", call(path, print, "statement", 1)]
123+
elseHasEmptyStatement
124+
? ";"
125+
: [elseSpacing, call(path, print, "statement", 1)]
107126
);
108127
}
109128
return statement;
@@ -121,14 +140,14 @@ export default {
121140
]);
122141
},
123142

124-
switchBlock(path, print) {
143+
switchBlock(path, print, options) {
125144
const { children } = path.node;
126145
const caseKeys = definedKeys(children, [
127146
"switchBlockStatementGroup",
128147
"switchRule"
129148
]);
130149
const cases = caseKeys.length === 1 ? map(path, print, caseKeys[0]) : [];
131-
return printBlock(path, cases);
150+
return printBlock(path, cases, options);
132151
},
133152

134153
switchBlockStatementGroup(path, print) {
@@ -203,30 +222,42 @@ export default {
203222
caseConstant: printSingle,
204223
casePattern: printSingle,
205224

206-
whileStatement(path, print) {
207-
const statement = call(path, print, "statement");
225+
whileStatement(path, print, options) {
208226
const hasEmptyStatement = isEmptyStatement(path.node.children.statement[0]);
227+
const hasBlock =
228+
path.node.children.statement[0].children
229+
.statementWithoutTrailingSubstatement?.[0].children.block !== undefined;
230+
const spacing =
231+
options.braceStyle === "next-line" && !hasBlock ? hardline : " ";
209232
return [
210233
"while ",
211234
indentInParentheses(call(path, print, "expression")),
212-
...[hasEmptyStatement ? ";" : " ", statement]
235+
hasEmptyStatement ? ";" : [spacing, call(path, print, "statement")]
213236
];
214237
},
215238

216-
doStatement(path, print) {
239+
doStatement(path, print, options) {
217240
const hasEmptyStatement = isEmptyStatement(path.node.children.statement[0]);
241+
const hasBlock =
242+
path.node.children.statement[0].children
243+
.statementWithoutTrailingSubstatement?.[0].children.block !== undefined;
244+
const spacing =
245+
options.braceStyle === "next-line" && !hasBlock ? hardline : " ";
246+
const whileSpacing =
247+
options.braceStyle === "next-line" && !hasEmptyStatement ? hardline : " ";
218248
return [
219249
"do",
220-
hasEmptyStatement ? ";" : [" ", call(path, print, "statement")],
221-
" while ",
250+
hasEmptyStatement ? ";" : [spacing, call(path, print, "statement")],
251+
whileSpacing,
252+
"while ",
222253
indentInParentheses(call(path, print, "expression")),
223254
";"
224255
];
225256
},
226257

227258
forStatement: printSingle,
228259

229-
basicForStatement(path, print) {
260+
basicForStatement(path, print, options) {
230261
const { children } = path.node;
231262
const danglingComments = printDanglingComments(path);
232263
if (danglingComments.length) {
@@ -237,13 +268,19 @@ export default {
237268
expressionKey in children ? call(path, print, expressionKey) : ""
238269
);
239270
const hasEmptyStatement = isEmptyStatement(children.statement[0]);
271+
const hasBlock =
272+
children.statement[0].children.statementWithoutTrailingSubstatement?.[0]
273+
.children.block !== undefined;
274+
const spacing =
275+
options.braceStyle === "next-line" && !hasBlock ? hardline : " ";
276+
240277
return [
241278
...danglingComments,
242279
"for ",
243280
expressions.some(expression => expression !== "")
244281
? indentInParentheses(join([";", line], expressions))
245282
: "(;;)",
246-
hasEmptyStatement ? ";" : [" ", call(path, print, "statement")]
283+
hasEmptyStatement ? ";" : [spacing, call(path, print, "statement")]
247284
];
248285
},
249286

@@ -258,9 +295,9 @@ export default {
258295
);
259296
},
260297

261-
enhancedForStatement(path, print) {
298+
enhancedForStatement(path, print, options) {
262299
const statementNode = path.node.children.statement[0];
263-
const forStatement = [
300+
const forStatement: Doc[] = [
264301
printDanglingComments(path),
265302
"for ",
266303
"(",
@@ -276,9 +313,15 @@ export default {
276313
statementNode.children.statementWithoutTrailingSubstatement?.[0]
277314
.children.block !== undefined;
278315
const statement = call(path, print, "statement");
279-
forStatement.push(
280-
hasStatementBlock ? [" ", statement] : indent([line, statement])
281-
);
316+
if (options.braceStyle === "next-line") {
317+
forStatement.push(
318+
hasStatementBlock ? statement : [hardline, statement]
319+
);
320+
} else {
321+
forStatement.push(
322+
hasStatementBlock ? [" ", statement] : indent([line, statement])
323+
);
324+
}
282325
}
283326
return group(forStatement);
284327
},
@@ -331,32 +374,52 @@ export default {
331374
];
332375
},
333376

334-
tryStatement(path, print) {
377+
tryStatement(path, print, options) {
335378
const { children } = path.node;
336379
if (children.tryWithResourcesStatement) {
337380
return call(path, print, "tryWithResourcesStatement");
338381
}
339-
const blocks = ["try", call(path, print, "block")];
382+
const tryBlock = formatWithBraces(
383+
"try",
384+
call(path, print, "block"),
385+
options
386+
);
387+
const blocks: Doc[] = [tryBlock];
340388
if (children.catches) {
389+
if (options.braceStyle === "next-line") {
390+
blocks.push(hardline);
391+
}
341392
blocks.push(call(path, print, "catches"));
342393
}
343394
if (children.finally) {
395+
if (options.braceStyle === "next-line") {
396+
blocks.push(hardline);
397+
}
344398
blocks.push(call(path, print, "finally"));
345399
}
346-
return join(" ", blocks);
400+
return blocks;
347401
},
348402

349-
catches(path, print) {
350-
return join(" ", map(path, print, "catchClause"));
403+
catches(path, print, options) {
404+
const catchClauses = map(path, print, "catchClause");
405+
return catchClauses.map((catchClause, index) => {
406+
if (options.braceStyle === "next-line") {
407+
return index === 0 ? catchClause : [hardline, catchClause];
408+
}
409+
return [" ", catchClause];
410+
});
351411
},
352412

353-
catchClause(path, print) {
354-
return [
413+
catchClause(path, print, options) {
414+
const catchDeclaration = [
355415
"catch ",
356-
indentInParentheses(call(path, print, "catchFormalParameter")),
357-
" ",
358-
call(path, print, "block")
416+
indentInParentheses(call(path, print, "catchFormalParameter"))
359417
];
418+
return formatWithBraces(
419+
catchDeclaration,
420+
call(path, print, "block"),
421+
options
422+
);
360423
},
361424

362425
catchFormalParameter(path, print) {
@@ -374,24 +437,39 @@ export default {
374437
);
375438
},
376439

377-
finally(path, print) {
378-
return ["finally ", call(path, print, "block")];
440+
finally(path, print, options) {
441+
const finallyParts = formatWithBraces(
442+
"finally",
443+
call(path, print, "block"),
444+
options
445+
);
446+
return options.braceStyle === "next-line"
447+
? finallyParts
448+
: [" ", ...finallyParts];
379449
},
380450

381-
tryWithResourcesStatement(path, print) {
451+
tryWithResourcesStatement(path, print, options) {
382452
const { children } = path.node;
383-
const blocks = [
384-
"try",
385-
call(path, print, "resourceSpecification"),
386-
call(path, print, "block")
387-
];
453+
const tryDeclaration = ["try", call(path, print, "resourceSpecification")];
454+
const tryBlock = formatWithBraces(
455+
tryDeclaration,
456+
call(path, print, "block"),
457+
options
458+
);
459+
const blocks: Doc[] = [tryBlock];
388460
if (children.catches) {
461+
if (options.braceStyle === "next-line") {
462+
blocks.push(hardline);
463+
}
389464
blocks.push(call(path, print, "catches"));
390465
}
391466
if (children.finally) {
467+
if (options.braceStyle === "next-line") {
468+
blocks.push(hardline);
469+
}
392470
blocks.push(call(path, print, "finally"));
393471
}
394-
return join(" ", blocks);
472+
return blocks;
395473
},
396474

397475
resourceSpecification(path, print) {

0 commit comments

Comments
 (0)