Skip to content

Commit 020b09e

Browse files
committed
fix: stable format for if/for/while/do/catch/switch with trailing comment
closes #592
1 parent b1b9e7c commit 020b09e

File tree

17 files changed

+819
-69
lines changed

17 files changed

+819
-69
lines changed

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

Lines changed: 105 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
"use strict";
22

33
import { builders } from "prettier/doc";
4-
import { concat, dedent, group, indent, join } from "./prettier-builder";
4+
import { concat, group, indent, join } from "./prettier-builder";
55
import { printTokenWithComments } from "./comments/format-comments";
6+
import {
7+
handleCommentsBasicForStatement,
8+
handleCommentsCatchClauseOrSwitchStatement,
9+
handleCommentsDoStatement,
10+
handleCommentsEnhancedForOrIfOrWhileStatement
11+
} from "./comments/handle-comments";
612
import {
713
hasLeadingLineComments,
814
hasTrailingLineComments
@@ -192,12 +198,19 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
192198
}
193199

194200
ifStatement(ctx: IfStatementCtx) {
201+
handleCommentsEnhancedForOrIfOrWhileStatement(ctx);
202+
195203
const expression = this.visit(ctx.expression);
196204

197205
const ifStatement = this.visit(ctx.statement[0], {
198206
allowEmptyStatement: true
199207
});
200-
const ifSeparator = isStatementEmptyStatement(ifStatement) ? "" : " ";
208+
const ifStatementCtx =
209+
ctx.statement[0].children.statementWithoutTrailingSubstatement?.[0]
210+
.children;
211+
const emptyIfStatement = ifStatementCtx?.emptyStatement !== undefined;
212+
const hasIfBlock = ifStatementCtx?.block !== undefined;
213+
const ifSeparator = emptyIfStatement ? "" : hasIfBlock ? " " : indent(line);
201214

202215
let elsePart: Doc = "";
203216
if (ctx.Else !== undefined) {
@@ -208,7 +221,9 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
208221

209222
const elseOnSameLine =
210223
hasTrailingLineComments(ctx.statement[0]) ||
211-
hasLeadingLineComments(ctx.Else[0])
224+
hasLeadingLineComments(ctx.Else[0]) ||
225+
emptyIfStatement ||
226+
!hasIfBlock
212227
? hardline
213228
: " ";
214229

@@ -226,7 +241,7 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
226241
ifSeparator
227242
])
228243
]),
229-
ifStatement,
244+
hasIfBlock ? ifStatement : indent(ifStatement),
230245
elsePart
231246
]);
232247
}
@@ -242,6 +257,8 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
242257
}
243258

244259
switchStatement(ctx: SwitchStatementCtx) {
260+
handleCommentsCatchClauseOrSwitchStatement(ctx);
261+
245262
const expression = this.visit(ctx.expression);
246263
const switchBlock = this.visit(ctx.switchBlock);
247264

@@ -340,22 +357,36 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
340357
}
341358

342359
whileStatement(ctx: WhileStatementCtx) {
360+
handleCommentsEnhancedForOrIfOrWhileStatement(ctx);
361+
343362
const expression = this.visit(ctx.expression);
344363
const statement = this.visit(ctx.statement[0], {
345364
allowEmptyStatement: true
346365
});
347-
const statementSeparator = isStatementEmptyStatement(statement) ? "" : " ";
348366

349-
return rejectAndJoin(" ", [
350-
ctx.While[0],
351-
rejectAndJoin(statementSeparator, [
352-
putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]),
353-
statement
367+
const hasBlock =
368+
ctx.statement[0].children.statementWithoutTrailingSubstatement?.[0]
369+
.children.block !== undefined;
370+
const statementSeparator = isStatementEmptyStatement(statement)
371+
? ""
372+
: hasBlock
373+
? " "
374+
: indent(line);
375+
376+
return group(
377+
rejectAndJoin(" ", [
378+
ctx.While[0],
379+
rejectAndJoin(statementSeparator, [
380+
putIntoBraces(expression, softline, ctx.LBrace[0], ctx.RBrace[0]),
381+
hasBlock ? statement : indent(statement)
382+
])
354383
])
355-
]);
384+
);
356385
}
357386

358387
doStatement(ctx: DoStatementCtx) {
388+
handleCommentsDoStatement(ctx);
389+
359390
const statement = this.visit(ctx.statement[0], {
360391
allowEmptyStatement: true
361392
});
@@ -378,31 +409,44 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
378409
}
379410

380411
basicForStatement(ctx: BasicForStatementCtx) {
412+
handleCommentsBasicForStatement(ctx);
413+
381414
const forInit = this.visit(ctx.forInit);
382415
const expression = this.visit(ctx.expression);
383416
const forUpdate = this.visit(ctx.forUpdate);
384417
const statement = this.visit(ctx.statement[0], {
385418
allowEmptyStatement: true
386419
});
387-
const statementSeparator = isStatementEmptyStatement(statement) ? "" : " ";
388420

389-
return rejectAndConcat([
390-
rejectAndJoin(" ", [
421+
const headerSeparator =
422+
ctx.forInit || ctx.expression || ctx.forUpdate ? line : "";
423+
const hasBlock =
424+
ctx.statement[0].children.statementWithoutTrailingSubstatement?.[0]
425+
.children.block !== undefined;
426+
const statementSeparator = isStatementEmptyStatement(statement)
427+
? ""
428+
: hasBlock
429+
? " "
430+
: indent(line);
431+
432+
return group(
433+
join(" ", [
391434
ctx.For[0],
392-
putIntoBraces(
393-
rejectAndConcat([
394-
forInit,
395-
rejectAndJoin(line, [ctx.Semicolon[0], expression]),
396-
rejectAndJoin(line, [ctx.Semicolon[1], forUpdate])
397-
]),
398-
softline,
399-
ctx.LBrace[0],
400-
ctx.RBrace[0]
401-
)
402-
]),
403-
statementSeparator,
404-
statement
405-
]);
435+
join(statementSeparator, [
436+
putIntoBraces(
437+
join(headerSeparator, [
438+
rejectAndConcat([forInit, ctx.Semicolon[0]]),
439+
rejectAndConcat([expression, ctx.Semicolon[1]]),
440+
forUpdate
441+
]),
442+
softline,
443+
ctx.LBrace[0],
444+
ctx.RBrace[0]
445+
),
446+
hasBlock ? statement : indent(statement)
447+
])
448+
])
449+
);
406450
}
407451

408452
forInit(ctx: ForInitCtx) {
@@ -424,27 +468,45 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
424468
}
425469

426470
enhancedForStatement(ctx: EnhancedForStatementCtx) {
471+
handleCommentsEnhancedForOrIfOrWhileStatement(ctx);
472+
427473
const variableModifiers = this.mapVisit(ctx.variableModifier);
428474
const localVariableType = this.visit(ctx.localVariableType);
429475
const variableDeclaratorId = this.visit(ctx.variableDeclaratorId);
430476
const expression = this.visit(ctx.expression);
431477
const statement = this.visit(ctx.statement[0], {
432478
allowEmptyStatement: true
433479
});
434-
const statementSeparator = isStatementEmptyStatement(statement) ? "" : " ";
435480

436-
return rejectAndConcat([
437-
rejectAndJoin(" ", [ctx.For[0], ctx.LBrace[0]]),
438-
rejectAndJoin(" ", [
439-
rejectAndJoin(" ", variableModifiers),
440-
localVariableType,
441-
variableDeclaratorId
442-
]),
443-
concat([" ", ctx.Colon[0], " "]),
444-
expression,
445-
concat([ctx.RBrace[0], statementSeparator]),
446-
statement
447-
]);
481+
const hasBlock =
482+
ctx.statement[0].children.statementWithoutTrailingSubstatement?.[0]
483+
.children.block !== undefined;
484+
const statementSeparator = isStatementEmptyStatement(statement)
485+
? ""
486+
: hasBlock
487+
? " "
488+
: indent(line);
489+
490+
return group(
491+
join(" ", [
492+
ctx.For[0],
493+
join(statementSeparator, [
494+
putIntoBraces(
495+
join(" ", [
496+
...variableModifiers,
497+
localVariableType,
498+
variableDeclaratorId,
499+
ctx.Colon[0],
500+
expression
501+
]),
502+
"",
503+
ctx.LBrace[0],
504+
ctx.RBrace[0]
505+
),
506+
hasBlock ? statement : indent(statement)
507+
])
508+
])
509+
);
448510
}
449511

450512
breakStatement(ctx: BreakStatementCtx) {
@@ -534,6 +596,8 @@ export class BlocksAndStatementPrettierVisitor extends BaseCstPrettierPrinter {
534596
}
535597

536598
catchClause(ctx: CatchClauseCtx) {
599+
handleCommentsCatchClauseOrSwitchStatement(ctx);
600+
537601
const catchFormalParameter = this.visit(ctx.catchFormalParameter);
538602
const block = this.visit(ctx.block);
539603

0 commit comments

Comments
 (0)