prettier-plugin-java 2.7.7 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright 2018-2025 the original author or authors from the JHipster project
2
+ Copyright 2018-2026 the original author or authors from the JHipster project
3
3
 
4
4
  Apache License
5
5
  Version 2.0, January 2004
@@ -1,8 +1,8 @@
1
1
  import type { IToken } from "java-parser";
2
2
  import { type AstPath } from "prettier";
3
3
  import { type JavaNode, type JavaNonTerminal, type JavaParserOptions } from "./printers/helpers.js";
4
- export declare function determineFormatterOffOnRanges(cst: JavaNonTerminal): void;
5
- export declare function isFullyBetweenFormatterOffOn(path: AstPath<JavaNode>): boolean;
4
+ export declare function determinePrettierIgnoreRanges(cst: JavaNonTerminal): void;
5
+ export declare function isFullyBetweenPrettierIgnore(path: AstPath<JavaNode>): boolean;
6
6
  export declare function canAttachComment(node: JavaNode): boolean;
7
7
  export declare function handleLineComment(commentNode: JavaComment, _: string, options: JavaParserOptions): boolean;
8
8
  export declare function handleRemainingComment(commentNode: JavaComment): boolean;
package/dist/comments.js CHANGED
@@ -1,35 +1,35 @@
1
1
  import { util } from "prettier";
2
2
  import parser from "./parser.js";
3
3
  import { isEmptyStatement, isNonTerminal, isTerminal } from "./printers/helpers.js";
4
- const formatterOffOnRangesByCst = new WeakMap();
5
- export function determineFormatterOffOnRanges(cst) {
4
+ const prettierIgnoreRangesByCst = new WeakMap();
5
+ export function determinePrettierIgnoreRanges(cst) {
6
6
  const { comments } = cst;
7
7
  if (!comments) {
8
8
  return;
9
9
  }
10
10
  const ranges = comments
11
- .filter(({ image }) => /^(\/\/\s*@formatter:(off|on)\s*|\/\*\s*@formatter:(off|on)\s*\*\/)$/.test(image))
11
+ .filter(({ image }) => /^\/(?:\/\s*(?:prettier-ignore-(?:start|end)|@formatter:(?:off|on))\s*|\*\s*(?:prettier-ignore-(?:start|end)|@formatter:(?:off|on))\s*\*\/)$/.test(image))
12
12
  .reduce((ranges, { image, startOffset }) => {
13
13
  const previous = ranges.at(-1);
14
- if (image.endsWith("off")) {
15
- if ((previous === null || previous === void 0 ? void 0 : previous.on) !== Infinity) {
16
- ranges.push({ off: startOffset, on: Infinity });
14
+ if (image.includes("start") || image.includes("off")) {
15
+ if ((previous === null || previous === void 0 ? void 0 : previous.end) !== Infinity) {
16
+ ranges.push({ start: startOffset, end: Infinity });
17
17
  }
18
18
  }
19
- else if ((previous === null || previous === void 0 ? void 0 : previous.on) === Infinity) {
20
- previous.on = startOffset;
19
+ else if ((previous === null || previous === void 0 ? void 0 : previous.end) === Infinity) {
20
+ previous.end = startOffset;
21
21
  }
22
22
  return ranges;
23
23
  }, new Array());
24
- formatterOffOnRangesByCst.set(cst, ranges);
24
+ prettierIgnoreRangesByCst.set(cst, ranges);
25
25
  }
26
- export function isFullyBetweenFormatterOffOn(path) {
26
+ export function isFullyBetweenPrettierIgnore(path) {
27
27
  var _a;
28
28
  const { node, root } = path;
29
29
  const start = parser.locStart(node);
30
30
  const end = parser.locEnd(node);
31
- return (((_a = formatterOffOnRangesByCst
32
- .get(root)) === null || _a === void 0 ? void 0 : _a.some(range => range.off < start && end < range.on)) === true);
31
+ return (((_a = prettierIgnoreRangesByCst
32
+ .get(root)) === null || _a === void 0 ? void 0 : _a.some(range => range.start < start && end < range.end)) === true);
33
33
  }
34
34
  export function canAttachComment(node) {
35
35
  var _a, _b, _c;
@@ -72,7 +72,8 @@ export function handleLineComment(commentNode, _, options) {
72
72
  handleIfStatementComments,
73
73
  handleJumpStatementComments,
74
74
  handleLabeledStatementComments,
75
- handleNameComments
75
+ handleNameComments,
76
+ handleTryStatementComments
76
77
  ].some(fn => fn(commentNode, options));
77
78
  }
78
79
  export function handleRemainingComment(commentNode) {
@@ -192,6 +193,33 @@ function handleNameComments(commentNode) {
192
193
  }
193
194
  return false;
194
195
  }
196
+ function handleTryStatementComments(commentNode) {
197
+ var _a, _b;
198
+ const { enclosingNode, followingNode } = commentNode;
199
+ if (enclosingNode &&
200
+ ["catches", "tryStatement"].includes(enclosingNode.name) &&
201
+ followingNode &&
202
+ isNonTerminal(followingNode)) {
203
+ const block = (_a = (followingNode.name === "catches"
204
+ ? followingNode.children.catchClause[0]
205
+ : followingNode.name === "catchClause" ||
206
+ followingNode.name === "finally"
207
+ ? followingNode
208
+ : null)) === null || _a === void 0 ? void 0 : _a.children.block[0];
209
+ if (!block) {
210
+ return false;
211
+ }
212
+ const blockStatement = (_b = block.children.blockStatements) === null || _b === void 0 ? void 0 : _b[0].children.blockStatement[0];
213
+ if (blockStatement) {
214
+ util.addLeadingComment(blockStatement, commentNode);
215
+ }
216
+ else {
217
+ util.addDanglingComment(block, commentNode, undefined);
218
+ }
219
+ return true;
220
+ }
221
+ return false;
222
+ }
195
223
  function isBinaryOperator(node) {
196
224
  var _a;
197
225
  return (node !== undefined &&
package/dist/parser.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { parse } from "java-parser";
2
- import { determineFormatterOffOnRanges } from "./comments.js";
2
+ import { determinePrettierIgnoreRanges } from "./comments.js";
3
3
  import { isTerminal } from "./printers/helpers.js";
4
4
  export default {
5
5
  parse(text, options) {
@@ -8,7 +8,7 @@ export default {
8
8
  (_a = cst.comments) === null || _a === void 0 ? void 0 : _a.forEach(comment => {
9
9
  comment.value = comment.image;
10
10
  });
11
- determineFormatterOffOnRanges(cst);
11
+ determinePrettierIgnoreRanges(cst);
12
12
  return cst;
13
13
  },
14
14
  astFormat: "java",
package/dist/printer.js CHANGED
@@ -1,4 +1,4 @@
1
- import { canAttachComment, handleLineComment, handleRemainingComment, isFullyBetweenFormatterOffOn } from "./comments.js";
1
+ import { canAttachComment, handleLineComment, handleRemainingComment, isFullyBetweenPrettierIgnore } from "./comments.js";
2
2
  import { isNonTerminal, isTerminal, printComment } from "./printers/helpers.js";
3
3
  import { printerForNodeType } from "./printers/index.js";
4
4
  export default {
@@ -11,7 +11,7 @@ export default {
11
11
  var _a;
12
12
  const { node } = path;
13
13
  return (((_a = node.comments) === null || _a === void 0 ? void 0 : _a.some(({ image }) => /^(\/\/\s*prettier-ignore|\/\*\s*prettier-ignore\s*\*\/)$/.test(image))) === true ||
14
- (canAttachComment(node) && isFullyBetweenFormatterOffOn(path)));
14
+ (canAttachComment(node) && isFullyBetweenPrettierIgnore(path)));
15
15
  },
16
16
  canAttachComment,
17
17
  isBlockComment(node) {
@@ -12,7 +12,7 @@ declare const _default: {
12
12
  classModifier: typeof printSingle;
13
13
  typeParameters(path: AstPath<import("java-parser").TypeParametersCstNode & {
14
14
  comments?: import("../comments.js").JavaComment[];
15
- }>, print: JavaPrintFn): builders.Group;
15
+ }>, print: JavaPrintFn): (string | builders.Indent | builders.Softline)[];
16
16
  typeParameterList(path: AstPath<import("java-parser").TypeParameterListCstNode & {
17
17
  comments?: import("../comments.js").JavaComment[];
18
18
  }>, print: JavaPrintFn): builders.Doc[];
@@ -25,7 +25,7 @@ declare const _default: {
25
25
  classPermits: typeof printClassPermits;
26
26
  interfaceTypeList(path: AstPath<import("java-parser").InterfaceTypeListCstNode & {
27
27
  comments?: import("../comments.js").JavaComment[];
28
- }>, print: JavaPrintFn): builders.Group;
28
+ }>, print: JavaPrintFn): builders.Doc[];
29
29
  classBody(path: AstPath<ClassBodyCstNode & {
30
30
  comments?: import("../comments.js").JavaComment[];
31
31
  }>, print: JavaPrintFn): builders.Group | (string | builders.Indent | builders.Hardline)[] | "{}";
@@ -135,7 +135,7 @@ declare const _default: {
135
135
  }>, print: JavaPrintFn): builders.Doc[];
136
136
  recordHeader(path: AstPath<import("java-parser").RecordHeaderCstNode & {
137
137
  comments?: import("../comments.js").JavaComment[];
138
- }>, print: JavaPrintFn): builders.Group | "()";
138
+ }>, print: JavaPrintFn): builders.Group | (string | builders.Indent | builders.Softline)[] | "()";
139
139
  recordComponentList(path: AstPath<import("java-parser").RecordComponentListCstNode & {
140
140
  comments?: import("../comments.js").JavaComment[];
141
141
  }>, print: JavaPrintFn): builders.Doc[];
@@ -1,5 +1,5 @@
1
1
  import { builders } from "prettier/doc";
2
- import { call, each, hasDeclarationAnnotations, hasLeadingComments, indentInParentheses, isBinaryExpression, lineEndWithComments, lineStartWithComments, map, onlyDefinedKey, printBlock, printClassPermits, printClassType, printDanglingComments, printList, printSingle, printWithModifiers } from "./helpers.js";
2
+ import { call, definedKeys, each, hasDeclarationAnnotations, hasLeadingComments, hasNonAssignmentOperators, indentInParentheses, lineEndWithComments, lineStartWithComments, map, onlyDefinedKey, printBlock, printClassPermits, printClassType, printDanglingComments, printList, printSingle, printWithModifiers } from "./helpers.js";
3
3
  const { group, hardline, indent, indentIfBreak, join, line, softline } = builders;
4
4
  export default {
5
5
  classDeclaration(path, print) {
@@ -12,30 +12,45 @@ export default {
12
12
  return printWithModifiers(path, print, "classModifier", declaration, true);
13
13
  },
14
14
  normalClassDeclaration(path, print) {
15
- const { classExtends, classImplements, classPermits, typeParameters } = path.node.children;
16
- const header = ["class ", call(path, print, "typeIdentifier")];
17
- if (typeParameters) {
18
- header.push(call(path, print, "typeParameters"));
19
- }
20
- if (classExtends) {
21
- header.push(indent([line, call(path, print, "classExtends")]));
22
- }
23
- if (classImplements) {
24
- header.push(indent([line, call(path, print, "classImplements")]));
15
+ const { children } = path.node;
16
+ const definedClauses = definedKeys(children, [
17
+ "classExtends",
18
+ "classImplements",
19
+ "classPermits"
20
+ ]);
21
+ const hasMultipleClauses = definedClauses.length > 1;
22
+ const hasTypeParameters = children.typeParameters !== undefined;
23
+ const parts = ["class ", call(path, print, "typeIdentifier")];
24
+ if (hasTypeParameters) {
25
+ const typeParameters = call(path, print, "typeParameters");
26
+ parts.push(hasMultipleClauses ? group(indent(typeParameters)) : typeParameters);
27
+ }
28
+ if (definedClauses.length) {
29
+ const separator = hasTypeParameters && !hasMultipleClauses ? " " : line;
30
+ const clauses = definedClauses.flatMap(clause => [
31
+ separator,
32
+ call(path, print, clause)
33
+ ]);
34
+ const hasBody = children.classBody[0].children.classBodyDeclaration !== undefined;
35
+ const clauseGroup = [
36
+ hasTypeParameters && !hasMultipleClauses ? clauses : indent(clauses),
37
+ hasBody ? separator : " "
38
+ ];
39
+ parts.push(hasMultipleClauses ? clauseGroup : group(clauseGroup));
25
40
  }
26
- if (classPermits) {
27
- header.push(indent([line, call(path, print, "classPermits")]));
41
+ else {
42
+ parts.push(" ");
28
43
  }
29
- return [group(header), " ", call(path, print, "classBody")];
44
+ return [group(parts), call(path, print, "classBody")];
30
45
  },
31
46
  classModifier: printSingle,
32
47
  typeParameters(path, print) {
33
- return group([
48
+ return [
34
49
  "<",
35
50
  indent([softline, call(path, print, "typeParameterList")]),
36
51
  softline,
37
52
  ">"
38
- ]);
53
+ ];
39
54
  },
40
55
  typeParameterList(path, print) {
41
56
  return printList(path, print, "typeParameter");
@@ -51,7 +66,7 @@ export default {
51
66
  },
52
67
  classPermits: printClassPermits,
53
68
  interfaceTypeList(path, print) {
54
- return group(printList(path, print, "interfaceType"));
69
+ return printList(path, print, "interfaceType");
55
70
  },
56
71
  classBody(path, print) {
57
72
  return printBlock(path, printClassBodyDeclarations(path, print));
@@ -84,18 +99,18 @@ export default {
84
99
  : join(", ", declarators);
85
100
  },
86
101
  variableDeclarator(path, print) {
87
- var _a, _b;
102
+ var _a, _b, _c;
88
103
  const { children } = path.node;
89
104
  const variableInitializer = (_a = children.variableInitializer) === null || _a === void 0 ? void 0 : _a[0];
90
105
  const declaratorId = call(path, print, "variableDeclaratorId");
91
106
  if (!variableInitializer) {
92
107
  return declaratorId;
93
108
  }
94
- const expression = (_b = variableInitializer.children.expression) === null || _b === void 0 ? void 0 : _b[0];
109
+ const binaryExpression = (_c = (_b = variableInitializer.children.expression) === null || _b === void 0 ? void 0 : _b[0].children.conditionalExpression) === null || _c === void 0 ? void 0 : _c[0].children.binaryExpression[0];
95
110
  const declarator = [declaratorId, " ", call(path, print, "Equals")];
96
111
  const initializer = call(path, print, "variableInitializer");
97
112
  if (hasLeadingComments(variableInitializer) ||
98
- (expression && isBinaryExpression(expression))) {
113
+ (binaryExpression && hasNonAssignmentOperators(binaryExpression))) {
99
114
  declarator.push(group(indent([line, initializer])));
100
115
  }
101
116
  else {
@@ -140,7 +155,7 @@ export default {
140
155
  const { typeParameters, annotation, throws } = path.node.children;
141
156
  const header = [];
142
157
  if (typeParameters) {
143
- header.push(call(path, print, "typeParameters"));
158
+ header.push(group(call(path, print, "typeParameters")));
144
159
  }
145
160
  if (annotation) {
146
161
  header.push(join(line, map(path, print, "annotation")));
@@ -237,7 +252,7 @@ export default {
237
252
  ? indentInParentheses(join([",", line], parameters))
238
253
  : "()");
239
254
  return children.typeParameters
240
- ? [call(path, print, "typeParameters"), " ", ...header]
255
+ ? [group(call(path, print, "typeParameters")), " ", ...header]
241
256
  : header;
242
257
  },
243
258
  simpleTypeName: printSingle,
@@ -286,11 +301,18 @@ export default {
286
301
  return invocation;
287
302
  },
288
303
  enumDeclaration(path, print) {
289
- const header = ["enum", call(path, print, "typeIdentifier")];
290
- if (path.node.children.classImplements) {
291
- header.push(call(path, print, "classImplements"));
304
+ const { children } = path.node;
305
+ const parts = ["enum ", call(path, print, "typeIdentifier")];
306
+ if (children.classImplements) {
307
+ const body = children.enumBody[0].children;
308
+ const hasBody = body.enumBodyDeclarations !== undefined ||
309
+ body.enumConstantList !== undefined;
310
+ parts.push(indent([line, call(path, print, "classImplements")]), hasBody ? line : " ");
292
311
  }
293
- return join(" ", [...header, call(path, print, "enumBody")]);
312
+ else {
313
+ parts.push(" ");
314
+ }
315
+ return [group(parts), call(path, print, "enumBody")];
294
316
  },
295
317
  enumBody(path, print, options) {
296
318
  var _a;
@@ -337,19 +359,36 @@ export default {
337
359
  },
338
360
  recordDeclaration(path, print) {
339
361
  const { children } = path.node;
340
- const header = ["record ", call(path, print, "typeIdentifier")];
362
+ const parts = ["record ", call(path, print, "typeIdentifier")];
341
363
  if (children.typeParameters) {
342
- header.push(call(path, print, "typeParameters"));
364
+ parts.push(group(call(path, print, "typeParameters")));
343
365
  }
344
- header.push(call(path, print, "recordHeader"));
366
+ parts.push(call(path, print, "recordHeader"));
345
367
  if (children.classImplements) {
346
- header.push(" ", call(path, print, "classImplements"));
368
+ const hasComponents = children.recordHeader[0].children.recordComponentList !== undefined;
369
+ const hasBody = children.recordBody[0].children.recordBodyDeclaration !== undefined;
370
+ const classImplements = [
371
+ hasComponents ? " " : line,
372
+ call(path, print, "classImplements")
373
+ ];
374
+ parts.push(group([
375
+ hasComponents ? classImplements : indent(classImplements),
376
+ hasBody ? line : " "
377
+ ]));
378
+ }
379
+ else {
380
+ parts.push(" ");
347
381
  }
348
- return [group(header), " ", call(path, print, "recordBody")];
382
+ return [group(parts), call(path, print, "recordBody")];
349
383
  },
350
384
  recordHeader(path, print) {
351
385
  return path.node.children.recordComponentList
352
- ? indentInParentheses(call(path, print, "recordComponentList"))
386
+ ? [
387
+ "(",
388
+ indent([softline, call(path, print, "recordComponentList")]),
389
+ softline,
390
+ ")"
391
+ ]
353
392
  : indentInParentheses(printDanglingComments(path), { shouldBreak: true });
354
393
  },
355
394
  recordComponentList(path, print) {
@@ -1,4 +1,4 @@
1
- import type { StringTemplateCstNode, TextBlockTemplateCstNode } from "java-parser";
1
+ import type { BinaryExpressionCstNode, PrimaryCstNode, StringTemplateCstNode, TextBlockTemplateCstNode } from "java-parser";
2
2
  import type { AstPath } from "prettier";
3
3
  import { builders } from "prettier/doc";
4
4
  import type { JavaComment } from "../comments.js";
@@ -31,7 +31,7 @@ declare const _default: {
31
31
  conditionalExpression(path: AstPath<import("java-parser").ConditionalExpressionCstNode & {
32
32
  comments?: JavaComment[];
33
33
  }>, print: JavaPrintFn, options: import("./helpers.js").JavaParserOptions): builders.Doc;
34
- binaryExpression(path: AstPath<import("java-parser").BinaryExpressionCstNode & {
34
+ binaryExpression(path: AstPath<BinaryExpressionCstNode & {
35
35
  comments?: JavaComment[];
36
36
  }>, print: JavaPrintFn, options: import("./helpers.js").JavaParserOptions): builders.Doc;
37
37
  unaryExpression(path: AstPath<import("java-parser").UnaryExpressionCstNode & {
@@ -40,7 +40,7 @@ declare const _default: {
40
40
  unaryExpressionNotPlusMinus(path: AstPath<import("java-parser").UnaryExpressionNotPlusMinusCstNode & {
41
41
  comments?: JavaComment[];
42
42
  }>, print: JavaPrintFn): builders.Doc[];
43
- primary(path: AstPath<import("java-parser").PrimaryCstNode & {
43
+ primary(path: AstPath<PrimaryCstNode & {
44
44
  comments?: JavaComment[];
45
45
  }>, print: JavaPrintFn): builders.Doc;
46
46
  primaryPrefix: typeof printSingle;
@@ -61,7 +61,7 @@ declare const _default: {
61
61
  }>, print: JavaPrintFn): builders.Doc;
62
62
  parenthesisExpression(path: AstPath<import("java-parser").ParenthesisExpressionCstNode & {
63
63
  comments?: JavaComment[];
64
- }>, print: JavaPrintFn): builders.Group | builders.Doc[] | "()";
64
+ }>, print: JavaPrintFn): builders.Group | "()";
65
65
  castExpression: typeof printSingle;
66
66
  primitiveCastExpression(path: AstPath<import("java-parser").PrimitiveCastExpressionCstNode & {
67
67
  comments?: JavaComment[];
@@ -1,5 +1,5 @@
1
1
  import { builders, utils } from "prettier/doc";
2
- import { call, definedKeys, each, findBaseIndent, flatMap, hasLeadingComments, indentInParentheses, isBinaryExpression, isNonTerminal, isTerminal, map, onlyDefinedKey, printDanglingComments, printList, printName, printSingle } from "./helpers.js";
2
+ import { call, definedKeys, each, findBaseIndent, flatMap, hasAssignmentOperators, hasLeadingComments, hasNonAssignmentOperators, indentInParentheses, isNonTerminal, isTerminal, map, onlyDefinedKey, printDanglingComments, printList, printName, printSingle } from "./helpers.js";
3
3
  const { align, breakParent, conditionalGroup, group, hardline, ifBreak, indent, indentIfBreak, join, line, lineSuffixBoundary, softline } = builders;
4
4
  const { removeLines, willBreak } = utils;
5
5
  export default {
@@ -64,26 +64,32 @@ export default {
64
64
  conditionalExpression(path, print, options) {
65
65
  var _a;
66
66
  const binaryExpression = call(path, print, "binaryExpression");
67
+ const grandparentNodeName = (_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name;
68
+ const isInParentheses = grandparentNodeName === "parenthesisExpression";
67
69
  if (!path.node.children.QuestionMark) {
68
- return binaryExpression;
70
+ return isInParentheses ? binaryExpression : group(binaryExpression);
69
71
  }
72
+ const isInReturn = grandparentNodeName === "returnStatement";
73
+ const prefix = group(isInReturn ? indent(binaryExpression) : binaryExpression);
70
74
  const [consequent, alternate] = map(path, print, "expression");
71
- const parts = [binaryExpression];
72
- const part = [
75
+ const suffix = [
73
76
  line,
74
77
  ["? ", options.useTabs ? indent(consequent) : align(2, consequent)],
75
78
  line,
76
79
  [": ", options.useTabs ? indent(alternate) : align(2, alternate)]
77
80
  ];
78
- const isNestedTernary = ((_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name) ===
79
- "conditionalExpression";
80
- parts.push(!isNestedTernary || options.useTabs
81
- ? part
82
- : align(Math.max(0, options.tabWidth - 2), part));
83
- return isNestedTernary ? parts : group(indent(parts));
81
+ const isNestedTernary = grandparentNodeName === "conditionalExpression";
82
+ const alignedSuffix = !isNestedTernary || options.useTabs
83
+ ? suffix
84
+ : align(Math.max(0, options.tabWidth - 2), suffix);
85
+ if (isNestedTernary) {
86
+ return [prefix, alignedSuffix];
87
+ }
88
+ const parts = [prefix, indent(alignedSuffix)];
89
+ return isInParentheses ? parts : group(parts);
84
90
  },
85
91
  binaryExpression(path, print, options) {
86
- var _a, _b;
92
+ var _a, _b, _c, _d;
87
93
  const { children } = path.node;
88
94
  const operands = flatMap(path, print, definedKeys(children, [
89
95
  "expression",
@@ -110,13 +116,12 @@ export default {
110
116
  "Instanceof",
111
117
  "shiftOperator"
112
118
  ]));
113
- const hasNonAssignmentOperators = (operators.length > 0 && !children.AssignmentOperator) ||
114
- (children.expression !== undefined &&
115
- isBinaryExpression(children.expression[0]));
116
119
  const isInList = ((_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name) === "elementValue" ||
117
120
  ((_b = path.getNode(6)) === null || _b === void 0 ? void 0 : _b.name) === "argumentList";
121
+ const binaryExpression = (_d = (_c = children.expression) === null || _c === void 0 ? void 0 : _c[0].children.conditionalExpression) === null || _d === void 0 ? void 0 : _d[0].children.binaryExpression[0];
118
122
  return binary(operands, operators, {
119
- hasNonAssignmentOperators,
123
+ hasNonAssignmentOperators: (operators.length > 0 && !children.AssignmentOperator) ||
124
+ (binaryExpression && hasNonAssignmentOperators(binaryExpression)),
120
125
  isInList,
121
126
  isRoot: true,
122
127
  operatorPosition: options.experimentalOperatorPosition
@@ -265,20 +270,36 @@ export default {
265
270
  : keyword;
266
271
  },
267
272
  parenthesisExpression(path, print) {
268
- var _a;
269
273
  const expression = call(path, print, "expression");
270
- const ancestorName = (_a = path.getNode(14)) === null || _a === void 0 ? void 0 : _a.name;
271
- const binaryExpression = path.getNode(8);
274
+ const primaryAncestor = path.getNode(4);
275
+ const binaryExpressionAncestor = path.getNode(8);
276
+ const outerAncestor = path.getNode(14);
272
277
  const { conditionalExpression, lambdaExpression } = path.node.children.expression[0].children;
273
278
  const hasLambda = lambdaExpression !== undefined;
274
279
  const hasTernary = (conditionalExpression === null || conditionalExpression === void 0 ? void 0 : conditionalExpression[0].children.QuestionMark) !== undefined;
275
- return ancestorName &&
276
- ["guard", "returnStatement"].includes(ancestorName) &&
277
- binaryExpression &&
278
- binaryExpression.name === "binaryExpression" &&
279
- Object.keys(binaryExpression.children).length === 1
280
- ? indentInParentheses(expression)
281
- : ["(", hasLambda || hasTernary ? expression : indent(expression), ")"];
280
+ const hasSuffix = (primaryAncestor === null || primaryAncestor === void 0 ? void 0 : primaryAncestor.children.primarySuffix) !== undefined;
281
+ const isAssignment = ((outerAncestor === null || outerAncestor === void 0 ? void 0 : outerAncestor.name) === "binaryExpression" &&
282
+ hasAssignmentOperators(outerAncestor)) ||
283
+ (outerAncestor === null || outerAncestor === void 0 ? void 0 : outerAncestor.name) === "variableInitializer";
284
+ if (!hasLambda && hasSuffix && (!hasTernary || isAssignment)) {
285
+ return indentInParentheses(hasTernary ? group(expression) : expression);
286
+ }
287
+ else if (binaryExpressionAncestor &&
288
+ Object.keys(binaryExpressionAncestor.children).length === 1 &&
289
+ outerAncestor &&
290
+ ["guard", "returnStatement"].includes(outerAncestor.name)) {
291
+ return indentInParentheses(group(expression));
292
+ }
293
+ else if (hasTernary && hasSuffix && !isAssignment) {
294
+ return group(["(", expression, softline, ")"]);
295
+ }
296
+ else {
297
+ return group([
298
+ "(",
299
+ hasLambda || hasTernary ? expression : indent(expression),
300
+ ")"
301
+ ]);
302
+ }
282
303
  },
283
304
  castExpression: printSingle,
284
305
  primitiveCastExpression(path, print) {
@@ -510,8 +531,8 @@ function binary(operands, operators, { hasNonAssignmentOperators = false, isInLi
510
531
  const content = binary(operands, operators, { operatorPosition });
511
532
  operands.unshift(levelOperator !== undefined &&
512
533
  needsParentheses(nextOperator, levelOperator)
513
- ? ["(", indent(content), ")"]
514
- : content);
534
+ ? ["(", group(indent(content)), ")"]
535
+ : group(content));
515
536
  }
516
537
  }
517
538
  level.push(operands.shift());
@@ -519,17 +540,17 @@ function binary(operands, operators, { hasNonAssignmentOperators = false, isInLi
519
540
  (!isInList &&
520
541
  !isAssignmentOperator(levelOperator) &&
521
542
  levelOperator !== "instanceof")) {
522
- return group(level);
543
+ return level;
523
544
  }
524
545
  if (!isRoot || hasNonAssignmentOperators) {
525
- return group(indent(level));
546
+ return indent(level);
526
547
  }
527
548
  const groupId = Symbol("assignment");
528
- return group([
549
+ return [
529
550
  level[0],
530
551
  group(indent(level[1]), { id: groupId }),
531
552
  indentIfBreak(level[2], { groupId })
532
- ]);
553
+ ];
533
554
  }
534
555
  const precedencesByOperator = new Map([
535
556
  ["||"],
@@ -1,4 +1,4 @@
1
- import type { AnnotationCstNode, ClassPermitsCstNode, ClassTypeCtx, CstElement, CstNode, ExpressionCstNode, InterfacePermitsCstNode, IToken, StatementCstNode } from "java-parser";
1
+ import type { AnnotationCstNode, BinaryExpressionCstNode, ClassPermitsCstNode, ClassTypeCtx, CstElement, CstNode, ExpressionCstNode, InterfacePermitsCstNode, IToken, StatementCstNode } from "java-parser";
2
2
  import type { AstPath, Doc, ParserOptions } from "prettier";
3
3
  import { builders } from "prettier/doc";
4
4
  import type { JavaComment } from "../comments.js";
@@ -32,6 +32,8 @@ export declare function printClassType(path: AstPath<JavaNonTerminal & {
32
32
  children: ClassTypeCtx;
33
33
  }>, print: JavaPrintFn): builders.Doc[];
34
34
  export declare function isBinaryExpression(expression: ExpressionCstNode): boolean;
35
+ export declare function hasAssignmentOperators(binaryExpression: BinaryExpressionCstNode): boolean;
36
+ export declare function hasNonAssignmentOperators(binaryExpression: BinaryExpressionCstNode): boolean;
35
37
  export declare function findBaseIndent(lines: string[]): number;
36
38
  export declare function isEmptyStatement(statement: StatementCstNode): boolean;
37
39
  export declare function isNonTerminal(node: CstElement): node is JavaNonTerminal;
@@ -157,18 +157,52 @@ export function printArrayInitializer(path, print, options, child) {
157
157
  return list.length ? group(["{", indent([line, ...list]), line, "}"]) : "{}";
158
158
  }
159
159
  export function printBlock(path, contents) {
160
- if (!contents.length) {
161
- const danglingComments = printDanglingComments(path);
162
- return danglingComments.length
163
- ? ["{", indent([hardline, ...danglingComments]), hardline, "}"]
164
- : "{}";
160
+ if (contents.length) {
161
+ return group([
162
+ "{",
163
+ indent([hardline, ...join(hardline, contents)]),
164
+ hardline,
165
+ "}"
166
+ ]);
165
167
  }
166
- return group([
167
- "{",
168
- indent([hardline, ...join(hardline, contents)]),
169
- hardline,
170
- "}"
171
- ]);
168
+ const danglingComments = printDanglingComments(path);
169
+ if (danglingComments.length) {
170
+ return ["{", indent([hardline, ...danglingComments]), hardline, "}"];
171
+ }
172
+ const parent = path.grandparent;
173
+ const grandparent = path.getNode(4);
174
+ const greatGrandparent = path.getNode(6);
175
+ return ((grandparent === null || grandparent === void 0 ? void 0 : grandparent.name) === "catches" &&
176
+ grandparent.children.catchClause.length === 1 &&
177
+ ((greatGrandparent === null || greatGrandparent === void 0 ? void 0 : greatGrandparent.name) === "tryStatement" ||
178
+ (greatGrandparent === null || greatGrandparent === void 0 ? void 0 : greatGrandparent.name) === "tryWithResourcesStatement") &&
179
+ !greatGrandparent.children.finally) ||
180
+ (greatGrandparent &&
181
+ [
182
+ "basicForStatement",
183
+ "doStatement",
184
+ "enhancedForStatement",
185
+ "whileStatement"
186
+ ].includes(greatGrandparent.name)) ||
187
+ [
188
+ "annotationInterfaceBody",
189
+ "classBody",
190
+ "constructorBody",
191
+ "enumBody",
192
+ "interfaceBody",
193
+ "moduleDeclaration",
194
+ "recordBody"
195
+ ].includes(path.node.name) ||
196
+ (parent &&
197
+ [
198
+ "instanceInitializer",
199
+ "lambdaBody",
200
+ "methodBody",
201
+ "staticInitializer",
202
+ "synchronizedStatement"
203
+ ].includes(parent.name))
204
+ ? "{}"
205
+ : ["{", hardline, "}"];
172
206
  }
173
207
  export function printName(path, print) {
174
208
  return join(".", map(path, print, "Identifier"));
@@ -177,10 +211,7 @@ export function printList(path, print, child) {
177
211
  return join([",", line], map(path, print, child));
178
212
  }
179
213
  export function printClassPermits(path, print) {
180
- return group([
181
- "permits",
182
- indent([line, group(printList(path, print, "typeName"))])
183
- ]);
214
+ return group(["permits", indent([line, printList(path, print, "typeName")])]);
184
215
  }
185
216
  export function printClassType(path, print) {
186
217
  const { children } = path.node;
@@ -217,12 +248,13 @@ export function isBinaryExpression(expression) {
217
248
  if (isTernary) {
218
249
  return false;
219
250
  }
220
- const hasNonAssignmentOperators = Object.values(conditionalExpression.binaryExpression[0].children).some(child => {
221
- var _a;
222
- return isTerminal(child[0]) &&
223
- !((_a = child[0].tokenType.CATEGORIES) === null || _a === void 0 ? void 0 : _a.some(category => category.name === "AssignmentOperator"));
224
- });
225
- return hasNonAssignmentOperators;
251
+ return hasNonAssignmentOperators(conditionalExpression.binaryExpression[0]);
252
+ }
253
+ export function hasAssignmentOperators(binaryExpression) {
254
+ return binaryExpression.children.AssignmentOperator !== undefined;
255
+ }
256
+ export function hasNonAssignmentOperators(binaryExpression) {
257
+ return Object.keys(binaryExpression.children).some(name => ["BinaryOperator", "Instanceof", "shiftOperator"].includes(name));
226
258
  }
227
259
  export function findBaseIndent(lines) {
228
260
  return lines.length
@@ -1,5 +1,5 @@
1
1
  import { builders } from "prettier/doc";
2
- import { call, each, hasDeclarationAnnotations, indentInParentheses, lineEndWithComments, lineStartWithComments, onlyDefinedKey, printArrayInitializer, printBlock, printClassPermits, printList, printSingle, printWithModifiers } from "./helpers.js";
2
+ import { call, definedKeys, each, hasDeclarationAnnotations, indentInParentheses, lineEndWithComments, lineStartWithComments, onlyDefinedKey, printArrayInitializer, printBlock, printClassPermits, printList, printSingle, printWithModifiers } from "./helpers.js";
3
3
  const { group, hardline, indent, join, line } = builders;
4
4
  export default {
5
5
  interfaceDeclaration(path, print) {
@@ -10,18 +10,36 @@ export default {
10
10
  return printWithModifiers(path, print, "interfaceModifier", call(path, print, declarationKey), true);
11
11
  },
12
12
  normalInterfaceDeclaration(path, print) {
13
- const { interfaceExtends, interfacePermits, typeParameters } = path.node.children;
14
- const header = ["interface ", call(path, print, "typeIdentifier")];
15
- if (typeParameters) {
16
- header.push(call(path, print, "typeParameters"));
13
+ const { children } = path.node;
14
+ const definedClauses = definedKeys(children, [
15
+ "interfaceExtends",
16
+ "interfacePermits"
17
+ ]);
18
+ const hasMultipleClauses = definedClauses.length > 1;
19
+ const hasTypeParameters = children.typeParameters !== undefined;
20
+ const parts = ["interface ", call(path, print, "typeIdentifier")];
21
+ if (hasTypeParameters) {
22
+ const typeParameters = call(path, print, "typeParameters");
23
+ parts.push(hasMultipleClauses ? group(indent(typeParameters)) : typeParameters);
17
24
  }
18
- if (interfaceExtends) {
19
- header.push(indent([line, call(path, print, "interfaceExtends")]));
25
+ if (definedClauses.length) {
26
+ const separator = hasTypeParameters && !hasMultipleClauses ? " " : line;
27
+ const clauses = definedClauses.flatMap(clause => [
28
+ separator,
29
+ call(path, print, clause)
30
+ ]);
31
+ const hasBody = children.interfaceBody[0].children.interfaceMemberDeclaration !==
32
+ undefined;
33
+ const clauseGroup = [
34
+ hasTypeParameters && !hasMultipleClauses ? clauses : indent(clauses),
35
+ hasBody ? separator : " "
36
+ ];
37
+ parts.push(hasMultipleClauses ? clauseGroup : group(clauseGroup));
20
38
  }
21
- if (interfacePermits) {
22
- header.push(indent([line, call(path, print, "interfacePermits")]));
39
+ else {
40
+ parts.push(" ");
23
41
  }
24
- return [group(header), " ", call(path, print, "interfaceBody")];
42
+ return [group(parts), call(path, print, "interfaceBody")];
25
43
  },
26
44
  interfaceModifier: printSingle,
27
45
  interfaceExtends(path, print) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prettier-plugin-java",
3
- "version": "2.7.7",
3
+ "version": "2.8.1",
4
4
  "description": "Prettier Java Plugin",
5
5
  "type": "module",
6
6
  "exports": {
@@ -41,5 +41,5 @@
41
41
  "peerDependencies": {
42
42
  "prettier": "^3.0.0"
43
43
  },
44
- "gitHead": "dc42509e151ec718e2cb9812669906035a63a09b"
44
+ "gitHead": "f403f75d5f308e388ac5d27550a177bb0bd6bef4"
45
45
  }