prettier-java-next-line 2.11.2 → 2.11.4

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/dist/index.mjs CHANGED
@@ -178,18 +178,19 @@ function printArrayInitializer(path, print, options) {
178
178
  const { node } = path;
179
179
  const elements = node.namedChildren;
180
180
  const isNested = isNestedArray(path);
181
+ const nextLineLayout = options.braceStyle === "next-line" && node.type === "array_initializer" ? options.arrayInitializerLayout : void 0;
181
182
  if (elements.length === 0) {
182
183
  const danglingComments = printDanglingCommentsInList(path);
183
184
  if (!danglingComments) return "{}";
184
- const block = group$7([
185
+ const block = [
185
186
  "{",
186
187
  danglingComments,
187
188
  "}"
188
- ]);
189
- return options.braceStyle === "next-line" && !isNested ? [hardline$7, block] : block;
189
+ ];
190
+ if (isNested || nextLineLayout === void 0) return group$7(block);
191
+ return nextLineLayout === "fit" ? group$7([softline$3, ...block]) : [hardline$7, group$7(block)];
190
192
  }
191
193
  const groupId = Symbol("array");
192
- const nextLineLayout = options.braceStyle === "next-line" && node.type === "array_initializer" ? options.arrayInitializerLayout : void 0;
193
194
  const shouldBreak = node.comments?.some(({ type, leading, trailing }) => !leading && !trailing && type === "line_comment") || nextLineLayout !== "fit" && elements.length > 1 && elements.every((element, i, elements) => {
194
195
  if (element.type !== "array_initializer") return false;
195
196
  const elementType = element.type;
@@ -280,8 +281,34 @@ function printArrayElementsConcisely(path, options, print, trailingComma) {
280
281
  function isNestedArray(path) {
281
282
  return path.parent?.type === "array_initializer" || path.parent?.type === "element_value_array_initializer";
282
283
  }
284
+ /**
285
+ * Separates a header such as `void m()`, `try` or `class A` from the `{` of
286
+ * the block that follows it. Blocks never add their own leading separator.
287
+ */
288
+ function printBlockSeparator(options) {
289
+ return options.braceStyle === "next-line" ? hardline$7 : " ";
290
+ }
291
+ /**
292
+ * Separators between a declaration header and its body. With same-line braces,
293
+ * a non-empty body's `{` moves onto its own line when the `extends`,
294
+ * `implements` or `permits` clauses break, so that separator sits inside the
295
+ * clause group. With next-line braces, `{` always follows the whole header on
296
+ * its own line.
297
+ */
298
+ function printDeclarationBodySeparators(hasClauses, hasBody, options) {
299
+ if (options.braceStyle === "next-line") return {
300
+ afterClauses: "",
301
+ afterHeader: hardline$7
302
+ };
303
+ return hasClauses ? {
304
+ afterClauses: hasBody ? line$7 : " ",
305
+ afterHeader: ""
306
+ } : {
307
+ afterClauses: "",
308
+ afterHeader: " "
309
+ };
310
+ }
283
311
  function printBlock(path, contents, options) {
284
- if (options?.braceStyle === "next-line") return printBlockNextLine(path, contents);
285
312
  if (contents.length) return group$7([
286
313
  "{",
287
314
  indent$7([hardline$7, ...join$7(hardline$7, contents)]),
@@ -295,6 +322,11 @@ function printBlock(path, contents, options) {
295
322
  hardline$7,
296
323
  "}"
297
324
  ];
325
+ if (options?.braceStyle === "next-line") return [
326
+ "{",
327
+ hardline$7,
328
+ "}"
329
+ ];
298
330
  const parent = path.parent;
299
331
  const grandparent = path.grandparent;
300
332
  return parent?.type === "catch_clause" && (grandparent?.type === "try_statement" || grandparent?.type === "try_with_resources_statement") && grandparent.namedChildren.filter(({ type }) => type === "catch_clause").length === 1 && !grandparent.namedChildren.some(({ type }) => type === "finally_clause") || parent && [
@@ -322,42 +354,6 @@ function printBlock(path, contents, options) {
322
354
  "}"
323
355
  ];
324
356
  }
325
- function printBlockNextLine(path, contents) {
326
- const parentType = path.parent?.type;
327
- const isChildOfBodyDeclaration = parentType != null && [
328
- "annotation_type_body",
329
- "class_body",
330
- "enum_body",
331
- "interface_body"
332
- ].includes(parentType);
333
- const isBlockStatement = parentType != null && [
334
- "block",
335
- "constructor_body",
336
- "switch_block_statement_group"
337
- ].includes(parentType);
338
- const prefix = isChildOfBodyDeclaration || isBlockStatement ? [] : [hardline$7];
339
- if (contents.length) return [
340
- ...prefix,
341
- "{",
342
- indent$7([hardline$7, ...join$7(hardline$7, contents)]),
343
- hardline$7,
344
- "}"
345
- ];
346
- const danglingComments = printDanglingComments(path, { indent: true });
347
- if (danglingComments) return [
348
- ...prefix,
349
- "{",
350
- danglingComments,
351
- hardline$7,
352
- "}"
353
- ];
354
- return [
355
- ...prefix,
356
- "{",
357
- hardline$7,
358
- "}"
359
- ];
360
- }
361
357
  function printBlockStatements(path, print) {
362
358
  const parts = [];
363
359
  path.each((child) => {
@@ -402,7 +398,7 @@ function printTypeParameters(path, print, options) {
402
398
  return path.node.type === "type_arguments" ? group$7(parts) : parts;
403
399
  }
404
400
  function printVariableDeclaration(path, print) {
405
- const declaration = printModifiers(path, print);
401
+ const declaration = printModifiers(path, print, path.parent?.type === "for_statement" ? "noBreak" : void 0);
406
402
  declaration.push(path.call(print, "typeNode"), " ");
407
403
  const declarators = path.map(print, "declaratorNodes");
408
404
  if (declarators.length > 1 && path.node.declaratorNodes.some(({ valueNode }) => valueNode)) declaration.push(group$7(indent$7(join$7([",", line$7], declarators)), { shouldBreak: path.parent?.type !== "for_statement" }));
@@ -443,14 +439,18 @@ function isTextBlock(node) {
443
439
  return node.type === "string_literal" && node.children[0].value === "\"\"\"";
444
440
  }
445
441
  function embedTextBlock(path, options) {
446
- if (path.node.namedChildren.some(({ type }) => type === "string_interpolation") || path.node.children[0].value === "\"") return null;
442
+ if (path.node.namedChildren.some(({ type }) => type === "string_interpolation") || !isTextBlock(path.node)) return null;
447
443
  const language = findEmbeddedLanguage(path);
448
444
  if (!language) return null;
449
445
  const parser = inferParser(options, language);
450
446
  if (!parser) return null;
451
- const text = unescapeTextBlockContents(textBlockContents(path.node));
447
+ const contents = textBlockContents(path.node);
448
+ if (/[\uE000-\uF8FF]/.test(contents)) return null;
449
+ const preservedEscapes = [];
450
+ const text = unescapeTextBlockContents(contents, preservedEscapes);
451
+ if (preservedEscapes.length > 6400) return null;
452
452
  return async (textToDoc) => {
453
- return printTextBlock([escapeDocForTextBlock(await textToDoc(text, { parser })), hardline$7]);
453
+ return printTextBlock([escapeDocForTextBlock(await textToDoc(text, { parser }), preservedEscapes), hardline$7]);
454
454
  };
455
455
  }
456
456
  function textBlockContents(node) {
@@ -621,11 +621,19 @@ function findBaseIndent(lines) {
621
621
  function findEmbeddedLanguage(path) {
622
622
  return [path.node, ...path.ancestors].find(({ type, comments }) => type === "block" || comments?.some(({ leading }) => leading))?.comments?.filter(({ leading }) => leading).map(({ value }) => value.match(/^(?:\/\/|\/\*)\s*language\s*=\s*(\S+)/)?.[1]).findLast((language) => language)?.toLowerCase();
623
623
  }
624
- function escapeDocForTextBlock(doc) {
625
- return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? currentDoc.replace(/\\|"""/g, (match) => match === "\\" ? "\\\\" : "\"\"\\\"") : currentDoc);
624
+ function escapeDocForTextBlock(doc, preservedEscapes) {
625
+ return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? currentDoc.replace(/\\|"""|[\uE000-\uF8FF]/g, (match) => match === "\\" ? "\\\\" : match === "\"\"\"" ? "\"\"\\\"" : preservedEscapes[match.charCodeAt(0) - 57344] ?? match) : currentDoc);
626
626
  }
627
- function unescapeTextBlockContents(text) {
628
- return text.replace(/\\(?:([stnr"'\\])|\n|\r\n?)/g, (_, escaped) => {
627
+ /**
628
+ * Escapes with no safe unescaped form (\b, \f and octal) are swapped for
629
+ * private-use placeholders and restored verbatim by escapeDocForTextBlock.
630
+ */
631
+ function unescapeTextBlockContents(text, preservedEscapes) {
632
+ return text.replace(/\\(?:([stnr"'\\])|([bf]|[0-3][0-7]{0,2}|[4-7][0-7]?)|\n|\r\n?)/g, (match, escaped, preserved) => {
633
+ if (preserved) {
634
+ preservedEscapes.push(match);
635
+ return String.fromCharCode(57344 + preservedEscapes.length - 1);
636
+ }
629
637
  switch (escaped) {
630
638
  case "s": return " ";
631
639
  case "t": return " ";
@@ -698,6 +706,7 @@ function handleLineComment(commentNode, _, options) {
698
706
  handleLabeledStatementComments,
699
707
  handleLambdaExpressionComments,
700
708
  handleMemberChainComments,
709
+ handleMethodHeaderComments,
701
710
  handleModifiersComments,
702
711
  handleNameComments,
703
712
  handleTernaryExpressionComments,
@@ -799,6 +808,18 @@ function getMemberChainRoot(node) {
799
808
  }
800
809
  return current;
801
810
  }
811
+ /**
812
+ * With same-line braces, `{` follows the method header on the same line, so a
813
+ * comment between the header and the block moves into the block.
814
+ */
815
+ function handleMethodHeaderComments(commentNode, options) {
816
+ const { enclosingNode, followingNode } = commentNode;
817
+ if (options.braceStyle !== "same-line" || enclosingNode?.type !== "method_declaration" || followingNode?.type !== "block" || followingNode !== enclosingNode.bodyNode) return false;
818
+ const firstStatement = followingNode.namedChildren.at(0);
819
+ if (firstStatement) util.addLeadingComment(firstStatement, commentNode);
820
+ else util.addDanglingComment(followingNode, commentNode, void 0);
821
+ return true;
822
+ }
802
823
  function handleModifiersComments(commentNode) {
803
824
  const { precedingNode } = commentNode;
804
825
  if (precedingNode?.type === "annotation" || precedingNode?.type === "marker_annotation" || precedingNode?.type === "modifiers") {
@@ -946,12 +967,15 @@ function printComments(path, doc) {
946
967
  var parser_default = {
947
968
  async parse(text) {
948
969
  const tree = (await parser).parse(text);
949
- const { rootNode } = tree;
950
- if (rootNode.hasError) throw new Error("Failed to parse: " + rootNode);
951
- const ast = processTree(rootNode);
952
- determinePrettierIgnoreRanges(ast);
953
- tree.delete();
954
- return ast;
970
+ try {
971
+ const { rootNode } = tree;
972
+ if (rootNode.hasError) throw new Error("Failed to parse: " + rootNode);
973
+ const ast = processTree(rootNode);
974
+ determinePrettierIgnoreRanges(ast);
975
+ return ast;
976
+ } finally {
977
+ tree.delete();
978
+ }
955
979
  },
956
980
  astFormat: "java",
957
981
  hasPragma(text) {
@@ -1047,8 +1071,14 @@ var blocks_and_statements_default = {
1047
1071
  return printBlock(path, printBlockStatements(path, print), options);
1048
1072
  },
1049
1073
  local_variable_declaration: printVariableDeclaration,
1050
- labeled_statement(path, print) {
1051
- return join$6(": ", path.map(print, "namedChildren"));
1074
+ labeled_statement(path, print, options) {
1075
+ const [label, statement] = path.map(print, "namedChildren");
1076
+ return [
1077
+ label,
1078
+ ":",
1079
+ printStatementSeparator(path.node.namedChildren[1].type, options),
1080
+ statement
1081
+ ];
1052
1082
  },
1053
1083
  expression_statement(path, print) {
1054
1084
  const parentType = path.parent?.type;
@@ -1059,7 +1089,7 @@ var blocks_and_statements_default = {
1059
1089
  if_statement(path, print, options) {
1060
1090
  const statement = ["if ", path.call(print, "conditionNode")];
1061
1091
  if (path.node.consequenceNode.type === ";") statement.push(";");
1062
- else statement.push(" ", path.call(print, "consequenceNode"));
1092
+ else statement.push(printStatementSeparator(path.node.consequenceNode.type, options), path.call(print, "consequenceNode"));
1063
1093
  if (!hasChild(path, "alternativeNode")) return statement;
1064
1094
  const danglingComments = printDanglingComments(path);
1065
1095
  if (danglingComments) statement.push(hardline$5, danglingComments, hardline$5);
@@ -1070,7 +1100,7 @@ var blocks_and_statements_default = {
1070
1100
  }
1071
1101
  statement.push("else");
1072
1102
  if (path.node.alternativeNode.type === ";") statement.push(";");
1073
- else statement.push(" ", path.call(print, "alternativeNode"));
1103
+ else statement.push(printStatementSeparator(path.node.alternativeNode.type, options), path.call(print, "alternativeNode"));
1074
1104
  return statement;
1075
1105
  },
1076
1106
  assert_statement(path, print) {
@@ -1080,23 +1110,24 @@ var blocks_and_statements_default = {
1080
1110
  ";"
1081
1111
  ];
1082
1112
  },
1083
- switch_expression(path, print) {
1084
- return join$6(" ", [
1085
- "switch",
1113
+ switch_expression(path, print, options) {
1114
+ return [
1115
+ "switch ",
1086
1116
  path.call(print, "conditionNode"),
1117
+ printBlockSeparator(options),
1087
1118
  path.call(print, "bodyNode")
1088
- ]);
1119
+ ];
1089
1120
  },
1090
1121
  switch_block(path, print, options) {
1091
1122
  return printBlock(path, path.map(print, "namedChildren"), options);
1092
1123
  },
1093
- switch_block_statement_group(path, print) {
1124
+ switch_block_statement_group(path, print, options) {
1094
1125
  const parts = [];
1095
1126
  path.each((child) => {
1096
1127
  if (child.node.type === "switch_label") parts.push(print(child), ":");
1097
1128
  }, "namedChildren");
1098
1129
  const firstStatementIndex = path.node.namedChildren.findIndex(({ type }) => type !== "switch_label");
1099
- if (firstStatementIndex === path.node.namedChildren.length - 1 && path.node.namedChildren[firstStatementIndex].type === "block") parts.push(" ", path.call(print, "namedChildren", firstStatementIndex));
1130
+ if (firstStatementIndex === path.node.namedChildren.length - 1 && path.node.namedChildren[firstStatementIndex].type === "block") parts.push(printBlockSeparator(options), path.call(print, "namedChildren", firstStatementIndex));
1100
1131
  else if (firstStatementIndex !== -1) parts.push(indent$6([hardline$5, ...join$6(hardline$5, printBlockStatements(path, print))]));
1101
1132
  return parts;
1102
1133
  },
@@ -1111,22 +1142,22 @@ var blocks_and_statements_default = {
1111
1142
  const guardIndex = path.node.namedChildren.findIndex(({ type }) => type === "guard");
1112
1143
  return guardIndex !== -1 ? [group$6([...label, hasMultipleValues ? line$5 : " "]), path.call(print, "namedChildren", guardIndex)] : group$6(label);
1113
1144
  },
1114
- switch_rule(path, print) {
1145
+ switch_rule(path, print, options) {
1115
1146
  const bodyIndex = path.node.namedChildren.findIndex(({ type }) => type === "block" || type === "expression_statement" || type === "throw_statement");
1116
1147
  const body = path.call(print, "namedChildren", bodyIndex);
1117
1148
  const switchLabelIndex = path.node.namedChildren.findIndex(({ type }) => type === "switch_label");
1118
1149
  const parts = [path.call(print, "namedChildren", switchLabelIndex), " ->"];
1119
1150
  const bodyNode = path.node.namedChildren[bodyIndex];
1120
1151
  if (bodyNode.type !== "block" && hasLeadingComments(bodyNode)) parts.push(indent$6([hardline$5, body]));
1121
- else parts.push(" ", body);
1152
+ else parts.push(printStatementSeparator(bodyNode.type, options), body);
1122
1153
  return parts;
1123
1154
  },
1124
- while_statement(path, print) {
1155
+ while_statement(path, print, options) {
1125
1156
  const parts = ["while ", path.call(print, "conditionNode")];
1126
1157
  const body = path.call(print, "bodyNode");
1127
1158
  const bodyType = path.node.bodyNode.type;
1128
1159
  if (bodyType === "block") {
1129
- parts.push(" ", body);
1160
+ parts.push(printBlockSeparator(options), body);
1130
1161
  return parts;
1131
1162
  } else if (bodyType === ";") {
1132
1163
  parts.push(";");
@@ -1138,11 +1169,10 @@ var blocks_and_statements_default = {
1138
1169
  },
1139
1170
  do_statement(path, print, options) {
1140
1171
  const hasEmptyStatement = path.node.bodyNode.type === ";";
1141
- const isNextLine = options?.braceStyle === "next-line";
1142
- const whilePrefix = isNextLine ? [hardline$5, "while "] : " while ";
1172
+ const whilePrefix = options?.braceStyle === "next-line" ? [hardline$5, "while "] : " while ";
1143
1173
  return [
1144
1174
  "do",
1145
- hasEmptyStatement ? ";" : isNextLine ? path.call(print, "bodyNode") : [" ", path.call(print, "bodyNode")],
1175
+ hasEmptyStatement ? ";" : [printStatementSeparator(path.node.bodyNode.type, options), path.call(print, "bodyNode")],
1146
1176
  whilePrefix,
1147
1177
  path.call(print, "conditionNode"),
1148
1178
  ";"
@@ -1163,18 +1193,18 @@ var blocks_and_statements_default = {
1163
1193
  danglingComments && [danglingComments, hardline$5],
1164
1194
  "for ",
1165
1195
  hasInit || hasCondition || hasUpdate ? group$6(indentInParentheses([join$6(line$5, expressions.slice(0, 2)), expressions[2]], options)) : "(;;)",
1166
- hasEmptyStatement ? ";" : [" ", path.call(print, "bodyNode")]
1196
+ hasEmptyStatement ? ";" : [printStatementSeparator(path.node.bodyNode.type, options), path.call(print, "bodyNode")]
1167
1197
  ];
1168
1198
  },
1169
1199
  update_expression(path, print) {
1170
1200
  return path.map(print, "children");
1171
1201
  },
1172
- enhanced_for_statement(path, print) {
1202
+ enhanced_for_statement(path, print, options) {
1173
1203
  const danglingComments = printDanglingComments(path);
1174
1204
  const forStatement = [
1175
1205
  danglingComments && [danglingComments, hardline$5],
1176
1206
  "for (",
1177
- ...printModifiers(path, print),
1207
+ ...printModifiers(path, print, "noBreak"),
1178
1208
  path.call(print, "typeNode"),
1179
1209
  " ",
1180
1210
  path.call(print, "nameNode")
@@ -1185,7 +1215,7 @@ var blocks_and_statements_default = {
1185
1215
  if (bodyType === ";") forStatement.push(";");
1186
1216
  else {
1187
1217
  const body = path.call(print, "bodyNode");
1188
- forStatement.push(bodyType === "block" ? [" ", body] : indent$6([line$5, body]));
1218
+ forStatement.push(bodyType === "block" ? [printBlockSeparator(options), body] : indent$6([line$5, body]));
1189
1219
  }
1190
1220
  return group$6(forStatement);
1191
1221
  },
@@ -1206,38 +1236,30 @@ var blocks_and_statements_default = {
1206
1236
  },
1207
1237
  return_statement: printReturnOrThrowStatement,
1208
1238
  throw_statement: printReturnOrThrowStatement,
1209
- synchronized_statement(path, print) {
1239
+ synchronized_statement(path, print, options) {
1210
1240
  const parenthesizedExpressionIndex = path.node.namedChildren.findIndex(({ type }) => type === "parenthesized_expression");
1211
1241
  return [
1212
1242
  "synchronized ",
1213
1243
  path.call(print, "namedChildren", parenthesizedExpressionIndex),
1214
- " ",
1244
+ printBlockSeparator(options),
1215
1245
  path.call(print, "bodyNode")
1216
1246
  ];
1217
1247
  },
1218
1248
  try_statement(path, print, options) {
1219
- const parts = ["try", path.call(print, "bodyNode")];
1220
- path.each((child) => {
1221
- if (child.node.type === "catch_clause" || child.node.type === "finally_clause") parts.push(print(child));
1222
- }, "namedChildren");
1223
- if (options?.braceStyle === "next-line") return parts;
1224
- return join$6(" ", parts);
1249
+ return [
1250
+ "try",
1251
+ printBlockSeparator(options),
1252
+ path.call(print, "bodyNode"),
1253
+ ...printCatchAndFinallyClauses(path, print, options)
1254
+ ];
1225
1255
  },
1226
1256
  catch_clause(path, print, options) {
1227
1257
  const catchFormalParameterIndex = path.node.namedChildren.findIndex(({ type }) => type === "catch_formal_parameter");
1228
- const params = group$6(indentInParentheses(path.call(print, "namedChildren", catchFormalParameterIndex), options));
1229
- const body = path.call(print, "bodyNode");
1230
- if (options?.braceStyle === "next-line") return [
1231
- hardline$5,
1232
- "catch ",
1233
- params,
1234
- body
1235
- ];
1236
1258
  return [
1237
1259
  "catch ",
1238
- params,
1239
- " ",
1240
- body
1260
+ group$6(indentInParentheses(path.call(print, "namedChildren", catchFormalParameterIndex), options)),
1261
+ printBlockSeparator(options),
1262
+ path.call(print, "bodyNode")
1241
1263
  ];
1242
1264
  },
1243
1265
  catch_formal_parameter(path, print) {
@@ -1251,32 +1273,20 @@ var blocks_and_statements_default = {
1251
1273
  return join$6([line$5, "| "], path.map(print, "namedChildren"));
1252
1274
  },
1253
1275
  finally_clause(path, print, options) {
1254
- if (options?.braceStyle === "next-line") return [
1255
- hardline$5,
1276
+ return [
1256
1277
  "finally",
1278
+ printBlockSeparator(options),
1257
1279
  path.call(print, "namedChildren", 0)
1258
1280
  ];
1259
- return ["finally ", path.call(print, "namedChildren", 0)];
1260
1281
  },
1261
1282
  try_with_resources_statement(path, print, options) {
1262
- const resources = path.call(print, "resourcesNode");
1263
- const body = path.call(print, "bodyNode");
1264
- const clauses = [];
1265
- path.each((child) => {
1266
- if (child.node.type === "catch_clause" || child.node.type === "finally_clause") clauses.push(print(child));
1267
- }, "namedChildren");
1268
- if (options?.braceStyle === "next-line") return [
1283
+ return [
1269
1284
  "try ",
1270
- resources,
1271
- body,
1272
- ...clauses
1285
+ path.call(print, "resourcesNode"),
1286
+ printBlockSeparator(options),
1287
+ path.call(print, "bodyNode"),
1288
+ ...printCatchAndFinallyClauses(path, print, options)
1273
1289
  ];
1274
- return join$6(" ", [
1275
- "try",
1276
- resources,
1277
- body,
1278
- ...clauses
1279
- ]);
1280
1290
  },
1281
1291
  resource_specification(path, print, options) {
1282
1292
  const resources = [];
@@ -1293,7 +1303,7 @@ var blocks_and_statements_default = {
1293
1303
  },
1294
1304
  resource(path, print) {
1295
1305
  if (hasChild(path, "typeNode") && hasChild(path, "nameNode") && hasChild(path, "valueNode")) {
1296
- const parts = printModifiers(path, print);
1306
+ const parts = printModifiers(path, print, "noBreak");
1297
1307
  parts.push(path.call(print, "typeNode"), " ", path.call(print, "nameNode"));
1298
1308
  if (hasChild(path, "dimensionsNode")) parts.push(path.call(print, "dimensionsNode"));
1299
1309
  parts.push(" =");
@@ -1344,6 +1354,16 @@ function printReturnOrThrowStatement(path, print, options) {
1344
1354
  ";"
1345
1355
  ];
1346
1356
  }
1357
+ function printStatementSeparator(statementType, options) {
1358
+ return statementType === "block" ? printBlockSeparator(options) : " ";
1359
+ }
1360
+ function printCatchAndFinallyClauses(path, print, options) {
1361
+ const clauses = [];
1362
+ path.each((child) => {
1363
+ if (child.node.type === "catch_clause" || child.node.type === "finally_clause") clauses.push(printBlockSeparator(options), print(child));
1364
+ }, "namedChildren");
1365
+ return clauses;
1366
+ }
1347
1367
  // src/printers/classes.ts
1348
1368
  const { group: group$5, hardline: hardline$4, indent: indent$5, join: join$5, line: line$4 } = builders;
1349
1369
  var classes_default = {
@@ -1357,21 +1377,21 @@ var classes_default = {
1357
1377
  const hasMultipleClauses = definedClauses.length > 1;
1358
1378
  if (hasChild(path, "type_parametersNode")) {
1359
1379
  const typeParameters = path.call(print, "type_parametersNode");
1360
- parts.push(hasMultipleClauses ? group$5(indent$5(typeParameters)) : options?.braceStyle === "next-line" ? group$5(typeParameters) : typeParameters);
1380
+ parts.push(hasMultipleClauses ? group$5(indent$5(typeParameters)) : group$5(typeParameters));
1361
1381
  }
1382
+ const separators = printDeclarationBodySeparators(definedClauses.length > 0, path.node.bodyNode.namedChildren.length > 0, options);
1362
1383
  if (definedClauses.length) {
1363
1384
  const clauses = definedClauses.flatMap((clause) => {
1364
1385
  if (!hasChild(path, clause)) return [];
1365
1386
  return [clause === "superclassNode" || clause === "interfacesNode" ? hardline$4 : line$4, path.call(print, clause)];
1366
1387
  });
1367
- const hasBody = path.node.bodyNode.namedChildren.length > 0;
1368
- const afterClauses = options?.braceStyle === "next-line" ? "" : hasBody ? line$4 : " ";
1369
- const clauseGroup = [indent$5(clauses), afterClauses];
1388
+ const clauseGroup = [indent$5(clauses), separators.afterClauses];
1370
1389
  parts.push(hasMultipleClauses ? clauseGroup : group$5(clauseGroup));
1371
- } else if (options?.braceStyle !== "next-line") parts.push(" ");
1390
+ }
1372
1391
  return [
1373
1392
  ...printModifiers(path, print, "declarationOnly"),
1374
1393
  group$5(parts),
1394
+ separators.afterHeader,
1375
1395
  path.call(print, "bodyNode")
1376
1396
  ];
1377
1397
  },
@@ -1397,7 +1417,7 @@ var classes_default = {
1397
1417
  if (hasChild(path, "dimensionsNode")) leftDoc.push(path.call(print, "dimensionsNode"));
1398
1418
  return printAssignment(leftDoc, " =", hasChild(path, "valueNode") ? path.call(print, "valueNode") : void 0, path.node.valueNode);
1399
1419
  },
1400
- method_declaration(path, print) {
1420
+ method_declaration(path, print, options) {
1401
1421
  const modifiers = printModifiers(path, print);
1402
1422
  const declaration = [];
1403
1423
  if (hasChild(path, "type_parametersNode")) declaration.push(group$5(path.call(print, "type_parametersNode")), " ");
@@ -1412,7 +1432,7 @@ var classes_default = {
1412
1432
  return hasChild(path, "bodyNode") ? [
1413
1433
  modifiers,
1414
1434
  group$5(declaration),
1415
- " ",
1435
+ printBlockSeparator(options),
1416
1436
  path.call(print, "bodyNode")
1417
1437
  ] : [
1418
1438
  modifiers,
@@ -1450,10 +1470,14 @@ var classes_default = {
1450
1470
  const exceptions = path.map(print, "namedChildren");
1451
1471
  return exceptions.length === 1 ? ["throws ", exceptions[0]] : ["throws", group$5(indent$5([line$4, ...join$5([",", line$4], exceptions)]))];
1452
1472
  },
1453
- static_initializer(path, print) {
1454
- return ["static ", path.call(print, "namedChildren", 0)];
1473
+ static_initializer(path, print, options) {
1474
+ return [
1475
+ "static",
1476
+ printBlockSeparator(options),
1477
+ path.call(print, "namedChildren", 0)
1478
+ ];
1455
1479
  },
1456
- constructor_declaration(path, print) {
1480
+ constructor_declaration(path, print, options) {
1457
1481
  const modifiers = printModifiers(path, print, "declarationOnly");
1458
1482
  const declaration = [];
1459
1483
  if (hasChild(path, "type_parametersNode")) declaration.push(group$5(path.call(print, "type_parametersNode")), " ");
@@ -1463,7 +1487,7 @@ var classes_default = {
1463
1487
  return [
1464
1488
  modifiers,
1465
1489
  group$5(declaration),
1466
- " ",
1490
+ printBlockSeparator(options),
1467
1491
  path.call(print, "bodyNode")
1468
1492
  ];
1469
1493
  },
@@ -1503,13 +1527,13 @@ var classes_default = {
1503
1527
  enum_declaration(path, print, options) {
1504
1528
  const modifiers = printModifiers(path, print, "declarationOnly");
1505
1529
  const parts = ["enum ", path.call(print, "nameNode")];
1506
- if (hasChild(path, "interfacesNode")) {
1507
- const hasBody = path.node.bodyNode.namedChildren.length > 0;
1508
- parts.push(indent$5([hardline$4, path.call(print, "interfacesNode")]), options?.braceStyle === "next-line" ? "" : hasBody ? line$4 : " ");
1509
- } else parts.push(" ");
1530
+ const hasInterfaces = hasChild(path, "interfacesNode");
1531
+ const separators = printDeclarationBodySeparators(hasInterfaces, path.node.bodyNode.namedChildren.length > 0, options);
1532
+ if (hasInterfaces) parts.push(indent$5([hardline$4, path.call(print, "interfacesNode")]), separators.afterClauses);
1510
1533
  return [
1511
1534
  ...modifiers,
1512
1535
  group$5(parts),
1536
+ separators.afterHeader,
1513
1537
  path.call(print, "bodyNode")
1514
1538
  ];
1515
1539
  },
@@ -1533,35 +1557,37 @@ var classes_default = {
1533
1557
  if (declarations.length) contents.push(";", hardline$4, ...declarations);
1534
1558
  return printBlock(path, contents.length ? [contents] : [], options);
1535
1559
  },
1536
- enum_constant(path, print) {
1560
+ enum_constant(path, print, options) {
1537
1561
  const initializer = printModifiers(path, print);
1538
1562
  initializer.push(path.call(print, "nameNode"));
1539
1563
  if (hasChild(path, "argumentsNode")) initializer.push(path.call(print, "argumentsNode"));
1540
- if (hasChild(path, "bodyNode")) initializer.push(" ", path.call(print, "bodyNode"));
1564
+ if (hasChild(path, "bodyNode")) initializer.push(printBlockSeparator(options), path.call(print, "bodyNode"));
1541
1565
  return initializer;
1542
1566
  },
1543
1567
  enum_body_declarations(path, print) {
1544
1568
  return join$5(hardline$4, printBodyDeclarations(path, print));
1545
1569
  },
1546
- record_declaration(path, print) {
1570
+ record_declaration(path, print, options) {
1547
1571
  const modifiers = printModifiers(path, print, "declarationOnly");
1548
1572
  const parts = ["record ", path.call(print, "nameNode")];
1549
1573
  if (hasChild(path, "type_parametersNode")) parts.push(group$5(path.call(print, "type_parametersNode")));
1550
1574
  parts.push(group$5(path.call(print, "parametersNode")));
1551
- if (hasChild(path, "interfacesNode")) {
1552
- const hasBody = path.node.bodyNode.namedChildren.length > 0;
1575
+ const hasInterfaces = hasChild(path, "interfacesNode");
1576
+ const separators = printDeclarationBodySeparators(hasInterfaces, path.node.bodyNode.namedChildren.length > 0, options);
1577
+ if (hasInterfaces) {
1553
1578
  const interfaces = [hardline$4, path.call(print, "interfacesNode")];
1554
- parts.push(group$5([indent$5(interfaces), hasBody ? line$4 : " "]));
1555
- } else parts.push(" ");
1579
+ parts.push(group$5([indent$5(interfaces), separators.afterClauses]));
1580
+ }
1556
1581
  return [
1557
1582
  ...modifiers,
1558
1583
  group$5(parts),
1584
+ separators.afterHeader,
1559
1585
  path.call(print, "bodyNode")
1560
1586
  ];
1561
1587
  },
1562
- compact_constructor_declaration(path, print) {
1588
+ compact_constructor_declaration(path, print, options) {
1563
1589
  const parts = printModifiers(path, print, "declarationOnly");
1564
- parts.push(path.call(print, "nameNode"), " ", path.call(print, "bodyNode"));
1590
+ parts.push(path.call(print, "nameNode"), printBlockSeparator(options), path.call(print, "bodyNode"));
1565
1591
  return parts;
1566
1592
  }
1567
1593
  };
@@ -1612,6 +1638,7 @@ var expressions_default = {
1612
1638
  bodyDoc = printArrowFunctionBody(path, args, options, {
1613
1639
  bodyDoc,
1614
1640
  bodyComments,
1641
+ bodySeparator: functionBody.type === "block" ? printBlockSeparator(options) : " ",
1615
1642
  shouldPutBodyOnSameLine
1616
1643
  });
1617
1644
  return group$4([
@@ -1678,7 +1705,7 @@ var expressions_default = {
1678
1705
  const breakClosingParen = parent.type === "explicit_constructor_invocation" || parent.type === "field_access" || parent.type === "method_invocation" || parent.type === "method_reference" || parent.type === "object_creation_expression";
1679
1706
  const shouldExtraIndent = shouldExtraIndentForTernaryExpression(path);
1680
1707
  const result = maybeGroup([
1681
- printTernaryTest(path, print),
1708
+ printTernaryTest(path, print, operatorAtEnd),
1682
1709
  forceNoIndent && !operatorAtEnd ? parts : indent$4(parts),
1683
1710
  breakClosingParen && !shouldExtraIndent ? closingBracketLine(options) : ""
1684
1711
  ]);
@@ -1746,7 +1773,7 @@ var expressions_default = {
1746
1773
  ")"
1747
1774
  ]);
1748
1775
  },
1749
- cast_expression(path, print) {
1776
+ cast_expression(path, print, options) {
1750
1777
  const { node } = path;
1751
1778
  const parts = [
1752
1779
  group$4(node.typeNodes.length === 1 ? [
@@ -1756,20 +1783,20 @@ var expressions_default = {
1756
1783
  ] : [
1757
1784
  "(",
1758
1785
  indent$4([softline$1, join$4([" &", line$3], path.map(print, "typeNodes"))]),
1759
- softline$1,
1786
+ closingBracketLine(options),
1760
1787
  ")"
1761
1788
  ]),
1762
1789
  " ",
1763
1790
  path.call(print, "valueNode")
1764
1791
  ];
1765
1792
  const parent = path.parent;
1766
- if (parent?.type === "unary_expression" && !node.comments || parent?.type === "array_access" && parent.arrayNode === node || (parent?.type === "explicit_constructor_invocation" || parent?.type === "field_access" || parent?.type === "method_invocation") && parent.objectNode === node || parent?.type === "method_reference" || parent?.type === "object_creation_expression") return group$4([indent$4([softline$1, ...parts]), softline$1]);
1793
+ if (parent?.type === "unary_expression" && !node.comments || parent?.type === "array_access" && parent.arrayNode === node || (parent?.type === "explicit_constructor_invocation" || parent?.type === "field_access" || parent?.type === "method_invocation") && parent.objectNode === node || parent?.type === "method_reference" || parent?.type === "object_creation_expression") return group$4([indent$4([softline$1, ...parts]), closingBracketLine(options)]);
1767
1794
  return parts;
1768
1795
  },
1769
- object_creation_expression(path, print) {
1796
+ object_creation_expression(path, print, options) {
1770
1797
  const expression = [];
1771
1798
  path.each((child) => {
1772
- if (child.node.type === "class_body") expression.push(" ");
1799
+ if (child.node.type === "class_body") expression.push(printBlockSeparator(options));
1773
1800
  expression.push(print(child));
1774
1801
  if (child.node.type === "annotation" || child.node.type === "marker_annotation" || child.node.type === "new") expression.push(" ");
1775
1802
  }, "children");
@@ -1929,11 +1956,11 @@ var expressions_default = {
1929
1956
  record_pattern_component(path, print) {
1930
1957
  return join$4(" ", path.map(print, "children"));
1931
1958
  },
1932
- guard(path, print) {
1959
+ guard(path, print, options) {
1933
1960
  return ["when ", group$4([
1934
1961
  ifBreak("("),
1935
1962
  indent$4([softline$1, path.call(print, "namedChildren", 0)]),
1936
- softline$1,
1963
+ closingBracketLine(options),
1937
1964
  ifBreak(")")
1938
1965
  ])];
1939
1966
  }
@@ -1976,10 +2003,10 @@ function printArrowFunctionSignatures(path, { signatureDocs }) {
1976
2003
  if (node.fieldName === "object" && parent?.type === "method_invocation") return group$4(join$4([" ->", line$3], signatureDocs));
1977
2004
  return group$4(indent$4(join$4([" ->", line$3], signatureDocs)));
1978
2005
  }
1979
- function printArrowFunctionBody(path, args, options, { bodyDoc, bodyComments, shouldPutBodyOnSameLine }) {
2006
+ function printArrowFunctionBody(path, args, options, { bodyDoc, bodyComments, bodySeparator, shouldPutBodyOnSameLine }) {
1980
2007
  const trailingSpace = args && typeof args === "object" && "expandLastArg" in args && args.expandLastArg && !path.node.comments ? closingBracketLine(options) : "";
1981
2008
  return shouldPutBodyOnSameLine ? [
1982
- " ",
2009
+ bodySeparator,
1983
2010
  bodyDoc,
1984
2011
  bodyComments
1985
2012
  ] : [indent$4([
@@ -2285,7 +2312,7 @@ function isHopefullyShortCallArgument(node) {
2285
2312
  if (node.type === "binary_expression") return isSimpleCallArgument(node.leftNode, 1) && isSimpleCallArgument(node.rightNode, 1);
2286
2313
  return isSimpleCallArgument(node);
2287
2314
  }
2288
- function printTernaryTest(path, print) {
2315
+ function printTernaryTest(path, print, operatorAtEnd) {
2289
2316
  const { node, parent } = path;
2290
2317
  const printed = path.call(print, "conditionNode");
2291
2318
  /**
@@ -2297,8 +2324,10 @@ function printTernaryTest(path, print) {
2297
2324
  * ^^ align(2)
2298
2325
  * ? d
2299
2326
  * : e
2327
+ *
2328
+ * With operators at the end there is no `: ` prefix to align under.
2300
2329
  */
2301
- if (parent?.type === node.type && parent.alternativeNode === node) return align(2, printed);
2330
+ if (!operatorAtEnd && parent?.type === node.type && parent.alternativeNode === node) return align(2, printed);
2302
2331
  return printed;
2303
2332
  }
2304
2333
  function getExpressionChild(node) {
@@ -2331,7 +2360,7 @@ function shouldExtraIndentForTernaryExpression(path) {
2331
2360
  return getExpressionChild(parent) === child;
2332
2361
  }
2333
2362
  function isStringLiteral(node) {
2334
- return node.type === "string_literal" && node.children[0].value === "\"";
2363
+ return node.type === "string_literal" && !isTextBlock(node);
2335
2364
  }
2336
2365
  var ArgExpansionBailout = class extends Error {
2337
2366
  constructor(..._args) {
@@ -2350,19 +2379,20 @@ var interfaces_default = {
2350
2379
  const hasMultipleClauses = hasExtendsInterfaces && hasPermits;
2351
2380
  if (hasChild(path, "type_parametersNode")) {
2352
2381
  const typeParameters = path.call(print, "type_parametersNode");
2353
- parts.push(hasMultipleClauses ? group$3(indent$3(typeParameters)) : options?.braceStyle === "next-line" ? group$3(typeParameters) : typeParameters);
2382
+ parts.push(hasMultipleClauses ? group$3(indent$3(typeParameters)) : group$3(typeParameters));
2354
2383
  }
2384
+ const separators = printDeclarationBodySeparators(hasExtendsInterfaces || hasPermits, path.node.bodyNode.namedChildren.length > 0, options);
2355
2385
  if (hasExtendsInterfaces || hasPermits) {
2356
2386
  const clauses = [];
2357
2387
  if (hasExtendsInterfaces) clauses.push(hardline$2, path.call(print, "namedChildren", extendsInterfacesIndex));
2358
2388
  if (hasPermits) clauses.push(line$2, path.call(print, "permitsNode"));
2359
- const hasBody = path.node.bodyNode.namedChildren.length > 0;
2360
- const clauseGroup = [indent$3(clauses), options?.braceStyle === "next-line" ? "" : hasBody ? line$2 : " "];
2389
+ const clauseGroup = [indent$3(clauses), separators.afterClauses];
2361
2390
  parts.push(hasMultipleClauses ? clauseGroup : group$3(clauseGroup));
2362
- } else parts.push(" ");
2391
+ }
2363
2392
  return [
2364
2393
  ...printModifiers(path, print, "declarationOnly"),
2365
2394
  group$3(parts),
2395
+ separators.afterHeader,
2366
2396
  path.call(print, "bodyNode")
2367
2397
  ];
2368
2398
  },
@@ -2374,9 +2404,9 @@ var interfaces_default = {
2374
2404
  return printBlock(path, printBodyDeclarations(path, print), options);
2375
2405
  },
2376
2406
  constant_declaration: printVariableDeclaration,
2377
- annotation_type_declaration(path, print) {
2407
+ annotation_type_declaration(path, print, options) {
2378
2408
  const parts = printModifiers(path, print);
2379
- parts.push("@interface ", path.call(print, "nameNode"), " ", path.call(print, "bodyNode"));
2409
+ parts.push("@interface ", path.call(print, "nameNode"), printBlockSeparator(options), path.call(print, "bodyNode"));
2380
2410
  return parts;
2381
2411
  },
2382
2412
  annotation_type_body(path, print, options) {
@@ -2421,7 +2451,7 @@ var interfaces_default = {
2421
2451
  const { group: group$2, hardline: hardline$1, indent: indent$2, join: join$2, softline } = builders;
2422
2452
  var lexical_structure_default = {
2423
2453
  string_literal(path, print) {
2424
- if (path.node.namedChildren.some(({ type }) => type === "string_interpolation") || path.node.children[0].value === "\"") return path.map(print, "children");
2454
+ if (path.node.namedChildren.some(({ type }) => type === "string_interpolation") || !isTextBlock(path.node)) return path.map(print, "children");
2425
2455
  return printTextBlock(join$2(hardline$1, textBlockContents(path.node).split("\n")));
2426
2456
  },
2427
2457
  string_fragment: printValue,
@@ -2526,14 +2556,18 @@ var packages_and_modules_default = {
2526
2556
  declaration.push(";");
2527
2557
  return declaration;
2528
2558
  },
2529
- module_declaration(path, print) {
2559
+ module_declaration(path, print, options) {
2530
2560
  const parts = [];
2531
2561
  path.each((child) => {
2532
2562
  if (child.node.type === "annotation" || child.node.type === "marker_annotation") parts.push(print(child));
2533
2563
  }, "namedChildren");
2534
2564
  if (path.node.children.some(({ type }) => type === "open")) parts.push("open");
2535
- parts.push("module", path.call(print, "nameNode"), path.call(print, "bodyNode"));
2536
- return join$1(" ", parts);
2565
+ parts.push("module", path.call(print, "nameNode"));
2566
+ return [
2567
+ join$1(" ", parts),
2568
+ printBlockSeparator(options),
2569
+ path.call(print, "bodyNode")
2570
+ ];
2537
2571
  },
2538
2572
  module_body(path, print, options) {
2539
2573
  return printBlock(path, path.map((child) => child.previous && child.node.start.row > child.previous.end.row + 1 ? [hardline, print(child)] : print(child), "namedChildren"), options);
@@ -2583,7 +2617,12 @@ function groupImports(imports, importOrder) {
2583
2617
  for (const entry of imports) {
2584
2618
  const key = importKey(entry);
2585
2619
  const prefix = prefixes.filter((candidate) => key.startsWith(candidate)).reduce((best, candidate) => candidate.length > best.length ? candidate : best);
2586
- importsByPrefix.set(prefix, [...importsByPrefix.get(prefix) ?? [], {
2620
+ const bucket = importsByPrefix.get(prefix);
2621
+ if (bucket) bucket.push({
2622
+ key,
2623
+ entry
2624
+ });
2625
+ else importsByPrefix.set(prefix, [{
2587
2626
  key,
2588
2627
  entry
2589
2628
  }]);