From 8ec1626beb00428bfff8506f42fd28894ad2c0bb Mon Sep 17 00:00:00 2001 From: Jordan Kiesel Date: Wed, 10 Jan 2024 00:04:57 -0700 Subject: [PATCH] fix: improve throws formatting --- .../src/printers/classes.ts | 36 ++-- .../src/printers/interfaces.ts | 11 +- .../src/printers/prettier-builder.ts | 6 +- .../test/unit-test/throws/_input.java | 52 ++++++ .../test/unit-test/throws/_output.java | 158 ++++++++++++++---- 5 files changed, 216 insertions(+), 47 deletions(-) diff --git a/packages/prettier-plugin-java/src/printers/classes.ts b/packages/prettier-plugin-java/src/printers/classes.ts index 78f3645e..f9f156d4 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/interfaces.ts b/packages/prettier-plugin-java/src/printers/interfaces.ts index 1daf4737..585e9214 100644 --- a/packages/prettier-plugin-java/src/printers/interfaces.ts +++ b/packages/prettier-plugin-java/src/printers/interfaces.ts @@ -1,4 +1,4 @@ -import { concat, group, indent } from "./prettier-builder.js"; +import { concat, group, ifBreak, indent } from "./prettier-builder.js"; import { printTokenWithComments } from "./comments/format-comments.js"; import { displaySemicolon, @@ -175,12 +175,17 @@ export class InterfacesPrettierVisitor extends BaseCstPrettierPrinter { interfaceMethodDeclaration(ctx: InterfaceMethodDeclarationCtx) { const modifiers = sortModifiers(ctx.interfaceMethodModifier); + const throwsGroupId = Symbol("throws"); const firstAnnotations = this.mapVisit(modifiers[0]); const otherModifiers = this.mapVisit(modifiers[1]); - const methodHeader = this.visit(ctx.methodHeader); + const methodHeader = this.visit(ctx.methodHeader, { throwsGroupId }); const methodBody = this.visit(ctx.methodBody); - const separator = isStatementEmptyStatement(methodBody) ? "" : " "; + const separator = isStatementEmptyStatement(methodBody) + ? "" + : ctx.methodHeader[0].children.throws + ? ifBreak(hardline, " ", { groupId: throwsGroupId }) + : " "; return rejectAndJoin(hardline, [ rejectAndJoin(hardline, firstAnnotations), 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/_input.java b/packages/prettier-plugin-java/test/unit-test/throws/_input.java index 387b0ef6..4d019e0c 100644 --- a/packages/prettier-plugin-java/test/unit-test/throws/_input.java +++ b/packages/prettier-plugin-java/test/unit-test/throws/_input.java @@ -87,3 +87,55 @@ public Throws(String string1, String string2, String string3, String string4, St System.out.println("Constructor with throws that should wrap"); } } + +interface Example { + void example1(String arg1, String arg2) + throws RuntimeException, RuntimeException, RuntimeException, RuntimeException; + + void example2( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) throws RuntimeException, RuntimeException, RuntimeException; + + void example3( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) + throws RuntimeException, RuntimeException, RuntimeException, RuntimeException; + + default void example1(String arg1, String arg2) + throws RuntimeException, RuntimeException, RuntimeException, RuntimeException { + throw new RuntimeException(); + } + + default void example2( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) throws RuntimeException, RuntimeException, RuntimeException { + throw new RuntimeException(); + } + + default void example3( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) + throws RuntimeException, RuntimeException, RuntimeException, RuntimeException { + throw new RuntimeException(); + } +} 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..274c0c10 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,78 @@ 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"); } } + +interface Example { + void example1(String arg1, String arg2) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException; + + void example2( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) throws RuntimeException, RuntimeException, RuntimeException; + + void example3( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException; + + default void example1(String arg1, String arg2) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException + { + throw new RuntimeException(); + } + + default void example2( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) throws RuntimeException, RuntimeException, RuntimeException { + throw new RuntimeException(); + } + + default void example3( + String arg1, + String arg2, + String arg3, + String arg4, + String arg5, + String arg6 + ) throws + RuntimeException, + RuntimeException, + RuntimeException, + RuntimeException + { + throw new RuntimeException(); + } +}