diff --git a/packages/prettier-plugin-java/src/printers/classes.ts b/packages/prettier-plugin-java/src/printers/classes.ts index 8e19acb8..c03c85d8 100644 --- a/packages/prettier-plugin-java/src/printers/classes.ts +++ b/packages/prettier-plugin-java/src/printers/classes.ts @@ -15,6 +15,7 @@ import { import { concat, group, + ifBreak, indent, join, indentIfBreak @@ -515,18 +516,23 @@ export class ClassesPrettierVisitor extends BaseCstPrettierPrinter { methodDeclaration(ctx: MethodDeclarationCtx) { const modifiers = sortModifiers(ctx.methodModifier); + const throwsGroupId = Symbol("throws"); const firstAnnotations = this.mapVisit(modifiers[0]); const otherModifiers = this.mapVisit(modifiers[1]); - const header = this.visit(ctx.methodHeader); + const header = this.visit(ctx.methodHeader, { throwsGroupId }); const body = this.visit(ctx.methodBody); - const headerBodySeparator = isStatementEmptyStatement(body) ? "" : " "; + const headerBodySeparator = isStatementEmptyStatement(body) + ? "" + : ctx.methodHeader[0].children.throws + ? ifBreak(hardline, " ", { groupId: throwsGroupId }) + : " "; return rejectAndJoin(hardline, [ - rejectAndJoin(hardline, firstAnnotations), + ...firstAnnotations, rejectAndJoin(" ", [ - rejectAndJoin(" ", otherModifiers), + ...otherModifiers, rejectAndJoin(headerBodySeparator, [header, body]) ]) ]); @@ -540,12 +546,12 @@ export class ClassesPrettierVisitor extends BaseCstPrettierPrinter { return printTokenWithComments(this.getSingle(ctx) as IToken); } - methodHeader(ctx: MethodHeaderCtx) { + methodHeader(ctx: MethodHeaderCtx, opts?: { throwsGroupId?: symbol }) { const typeParameters = this.visit(ctx.typeParameters); const annotations = this.mapVisit(ctx.annotation); const result = this.visit(ctx.result); const declarator = this.visit(ctx.methodDeclarator); - const throws = this.visit(ctx.throws); + const throws = this.visit(ctx.throws, opts); return group( concat([ @@ -652,15 +658,16 @@ export class ClassesPrettierVisitor extends BaseCstPrettierPrinter { return printTokenWithComments(this.getSingle(ctx) as IToken); } - throws(ctx: ThrowsCtx) { + throws(ctx: ThrowsCtx, opts?: { throwsGroupId?: symbol }) { const exceptionTypeList = this.visit(ctx.exceptionTypeList); - const throwsDeclaration = join(" ", [ctx.Throws[0], exceptionTypeList]); - return group(indent(rejectAndConcat([softline, throwsDeclaration]))); + return group(indent(join(line, [ctx.Throws[0], exceptionTypeList])), { + id: opts?.throwsGroupId + }); } exceptionTypeList(ctx: ExceptionTypeListCtx) { const exceptionTypes = this.mapVisit(ctx.exceptionType); - const commas = ctx.Comma ? ctx.Comma.map(elt => concat([elt, " "])) : []; + const commas = ctx.Comma?.map(comma => concat([comma, line])); return rejectAndJoinSeps(commas, exceptionTypes); } @@ -687,25 +694,26 @@ export class ClassesPrettierVisitor extends BaseCstPrettierPrinter { } constructorDeclaration(ctx: ConstructorDeclarationCtx) { + const throwsGroupId = Symbol("throws"); const modifiers = sortModifiers(ctx.constructorModifier); const firstAnnotations = this.mapVisit(modifiers[0]); const otherModifiers = this.mapVisit(modifiers[1]); - const constructorDeclarator = this.visit(ctx.constructorDeclarator); - const throws = this.visit(ctx.throws); + const throws = this.visit(ctx.throws, { throwsGroupId }); const constructorBody = this.visit(ctx.constructorBody); - return rejectAndJoin(" ", [ + return concat([ group( rejectAndJoin(hardline, [ rejectAndJoin(hardline, firstAnnotations), rejectAndJoin(" ", [ - join(" ", otherModifiers), + rejectAndJoin(" ", otherModifiers), constructorDeclarator, throws ]) ]) ), + ctx.throws ? ifBreak(hardline, " ", { groupId: throwsGroupId }) : " ", constructorBody ]); } diff --git a/packages/prettier-plugin-java/src/printers/prettier-builder.ts b/packages/prettier-plugin-java/src/printers/prettier-builder.ts index 613c2dee..7bde7bbc 100644 --- a/packages/prettier-plugin-java/src/printers/prettier-builder.ts +++ b/packages/prettier-plugin-java/src/printers/prettier-builder.ts @@ -53,11 +53,13 @@ export function dedent(doc: Doc | IToken) { export function ifBreak( breakContents: Doc | IToken, - flatContents: Doc | IToken + flatContents: Doc | IToken, + options?: { groupId?: symbol | undefined } ) { return builders.ifBreak( processComments(breakContents), - processComments(flatContents) + processComments(flatContents), + options ); } diff --git a/packages/prettier-plugin-java/test/unit-test/throws/_output.java b/packages/prettier-plugin-java/test/unit-test/throws/_output.java index 2fa9b037..904f1340 100644 --- a/packages/prettier-plugin-java/test/unit-test/throws/_output.java +++ b/packages/prettier-plugin-java/test/unit-test/throws/_output.java @@ -8,23 +8,33 @@ void throwException2(String string) throws RuntimeException { throw new RuntimeException(); } - void throwException3(String string1, String string2, String string3) - throws RuntimeException { + void throwException3(String string1, String string2, String string3) throws + RuntimeException + { throw new RuntimeException(); } - void throwException4() - throws RuntimeException, RuntimeException, RuntimeException { + void throwException4() throws + RuntimeException, + RuntimeException, + RuntimeException + { throw new RuntimeException(); } - void throwException5(String string) - throws RuntimeException, RuntimeException, RuntimeException { + void throwException5(String string) throws + RuntimeException, + RuntimeException, + RuntimeException + { throw new RuntimeException(); } - void throwException6(String string1, String string2, String string3) - throws RuntimeException, RuntimeException, RuntimeException { + void throwException6(String string1, String string2, String string3) throws + RuntimeException, + RuntimeException, + RuntimeException + { throw new RuntimeException(); } @@ -51,19 +61,33 @@ void throwException9( String string2, String string3, String string4 - ) - throws RuntimeException, RuntimeException, RuntimeException, RuntimeException { + ) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException + { throw new RuntimeException(); } - void aVeryLongNameForAMethodWichShouldBreakTheExpression() - throws aVeryLongException {} - - void aVeryLongNameForAMethodWichShouldBreakTheExpression() - throws aVeryLongException, aVeryLongException {} - - void aVeryLongNameForAMethodWichShouldBreakTheExpression() - throws Exception, Exception, Exception, Exception, Exception, Exception, Exception {} + void aVeryLongNameForAMethodWichShouldBreakTheExpression() throws + aVeryLongException + {} + + void aVeryLongNameForAMethodWichShouldBreakTheExpression() throws + aVeryLongException, + aVeryLongException + {} + + void aVeryLongNameForAMethodWichShouldBreakTheExpression() throws + Exception, + Exception, + Exception, + Exception, + Exception, + Exception, + Exception + {} abstract void absThrowException1() throws RuntimeException; @@ -75,11 +99,15 @@ abstract void absThrowException3( String string3 ) throws RuntimeException; - abstract void absThrowException4() - throws RuntimeException, RuntimeException, RuntimeException; + abstract void absThrowException4() throws + RuntimeException, + RuntimeException, + RuntimeException; - abstract void absThrowException5(String string) - throws RuntimeException, RuntimeException, RuntimeException; + abstract void absThrowException5(String string) throws + RuntimeException, + RuntimeException, + RuntimeException; abstract void absThrowException6( String string1, @@ -99,15 +127,19 @@ abstract void absThrowException8( String string2, String string3, String string4 - ) - throws RuntimeException, RuntimeException, RuntimeException, RuntimeException; + ) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException; public Throws(String string1) throws RuntimeException { System.out.println("Constructor with throws that should not wrap"); } - public Throws(String string1, String string2, String string3) - throws RuntimeException { + public Throws(String string1, String string2, String string3) throws + RuntimeException + { System.out.println("Constructor with throws that should wrap"); } @@ -127,8 +159,12 @@ public Throws( String string3, String string4, String string5 - ) - throws RuntimeException, RuntimeException, RuntimeException, RuntimeException { + ) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException + { System.out.println("Constructor with throws that should wrap"); } }