-
Notifications
You must be signed in to change notification settings - Fork 15
Apply various formatting fixes #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
41a21c5
3301083
8af6980
9714459
120b664
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,6 +83,13 @@ export const exprMap: CstToDocMap<AllExprNodes> = { | |
| ) { | ||
| return print("expr"); | ||
| } | ||
| if ( | ||
| isEmptyParenContent(node.expr) && | ||
| !hasComments(node) && | ||
| !hasComments(node.expr) | ||
| ) { | ||
| return ["(", print("expr"), ")"]; | ||
| } | ||
| const lineStyle = | ||
| isCreateTableStmt(parent) && print.dynamicLine() === hardline | ||
| ? hardline | ||
|
|
@@ -101,7 +108,10 @@ export const exprMap: CstToDocMap<AllExprNodes> = { | |
| // Some operators are better formatted without spaces around them | ||
| return print(["left", "operator", "right"]); | ||
| } | ||
| return print.spaced(["left", "operator", "right"]); | ||
| return group([ | ||
| print("left"), | ||
| group([" ", print.spaced("operator"), indent([line, print("right")])]), | ||
| ]); | ||
| }, | ||
| prefix_op_expr: (print, node) => | ||
| (isString(node.operator) ? print : print.spaced)(["operator", "expr"]), | ||
|
|
@@ -117,11 +127,19 @@ export const exprMap: CstToDocMap<AllExprNodes> = { | |
| case_when: (print, node) => { | ||
| if (isProgram(node.result)) { | ||
| return [ | ||
| print.spaced(["whenKw", "condition", "thenKw"]), | ||
| group([ | ||
| group([print("whenKw"), indent([line, print("condition")])]), | ||
| line, | ||
| print("thenKw"), | ||
| ]), | ||
| indent([hardline, stripTrailingHardline(print("result"))]), | ||
| ]; | ||
| } | ||
| return print.spaced(["whenKw", "condition", "thenKw", "result"]); | ||
| return group([ | ||
| group([print("whenKw"), indent([line, print("condition")])]), | ||
| line, | ||
| group([print("thenKw"), indent([line, print("result")])]), | ||
| ]); | ||
| }, | ||
| case_else: (print, node) => { | ||
| if (isProgram(node.result)) { | ||
|
|
@@ -317,3 +335,23 @@ const isFunctionContext = ( | |
| const isBooleanOp = ({ name }: Keyword) => name === "AND" || name === "OR"; | ||
|
|
||
| const isCompactOp = (op: string) => op === "->" || op === "->>"; | ||
|
|
||
| const isEmptyParenContent = (expr: Node): boolean => { | ||
| if (isFuncArgs(expr)) { | ||
| return ( | ||
| expr.args.items.length === 0 && | ||
| !expr.distinctKw && | ||
| !expr.nullHandlingKw && | ||
| !expr.orderBy && | ||
| !expr.limit && | ||
| !expr.having | ||
|
Comment on lines
+343
to
+347
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to avoid handling each case individually here?
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment I think not much can be done here. This needs some changes on the parser side to make it easier to handle within the prettier plugin. |
||
| ); | ||
| } | ||
| if (isListExpr(expr)) { | ||
| return expr.items.length === 0; | ||
| } | ||
| return false; | ||
| }; | ||
|
|
||
| const hasComments = (node: Node): boolean => | ||
| Boolean((node as Node & { comments?: unknown[] }).comments?.length); | ||
|
Comment on lines
+356
to
+357
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A better way to implement this, would be: const hasComments = (node: Node): boolean =>
(node.leading?.length ?? 0) > 0 || (node.trailing?.length ?? 0) > 0;The Given that in here we really are interested from where the comments were in the original source code, we're better off using the |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,27 @@ describe("expr", () => { | |
| `); | ||
| }); | ||
|
|
||
| it(`keeps short binary expressions on one line`, async () => { | ||
| await test(dedent` | ||
| SELECT * | ||
| FROM foo | ||
| WHERE bar = short_func() | ||
| `); | ||
| }); | ||
|
|
||
| it(`breaks long binary expressions into multiple lines with indentation`, async () => { | ||
| await test( | ||
| dedent` | ||
| SELECT * | ||
| FROM foo | ||
| WHERE | ||
| bar = | ||
| my_func() | ||
| `, | ||
| { printWidth: 15 }, | ||
| ); | ||
| }); | ||
|
|
||
| it(`formats IN expressions`, async () => { | ||
| await test(`SELECT col1 IN (1, 2, 3), col2 NOT IN (4, 5, 6)`); | ||
| }); | ||
|
|
@@ -171,6 +192,65 @@ describe("expr", () => { | |
| END | ||
| `); | ||
| }); | ||
|
|
||
| it(`breaks long WHEN/THEN into separate lines`, async () => { | ||
| await test( | ||
| dedent` | ||
| SELECT | ||
| CASE | ||
| WHEN column_name = 1 | ||
| THEN result_name | ||
| END | ||
| `, | ||
| { printWidth: 40 }, | ||
| ); | ||
| }); | ||
|
|
||
| it(`breaks multiple long WHEN/THEN clauses without blank lines between them`, async () => { | ||
| await test( | ||
| dedent` | ||
| SELECT | ||
| CASE | ||
| WHEN column_name = 1 | ||
| THEN result_name | ||
| WHEN column_name = 2 | ||
| THEN other_result | ||
| ELSE foo | ||
|
Comment on lines
+212
to
+218
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find this not so easy to read, because It also doesn't match with how the procedural version of CASE expression gets formatted: CASE
WHEN column_name = 1 THEN
SELECT \good'
WHEN columne_name = 2 THEN
SELECT 'bad'
ELSE
SELECT 'other'
END CASESee case.test.ts I would go with similar indentation for the long WHEN..THEN blocks in general: CASE
WHEN column_name = 1 THEN
result_name
WHEN columne_name = 2 THEN
other_result
ELSE
foo
END CASE |
||
| END | ||
| `, | ||
| { printWidth: 40 }, | ||
| ); | ||
| }); | ||
|
|
||
| it(`indents multi-condition WHEN clauses and keeps ORs parenthesized`, async () => { | ||
| await test( | ||
| dedent` | ||
| SELECT | ||
| CASE | ||
| WHEN | ||
| column_name = 1 | ||
| AND (other_name = 2 OR other_name = 3) | ||
| THEN result_name | ||
| END | ||
| `, | ||
| { printWidth: 50 }, | ||
| ); | ||
| }); | ||
|
|
||
| it(`indents multi-expression THEN clauses and keeps ORs parenthesized`, async () => { | ||
| await test( | ||
| dedent` | ||
| SELECT | ||
| CASE | ||
| WHEN column_name = 1 | ||
| THEN | ||
| result_name = 1 | ||
| AND (other_name = 2 OR other_name = 3) | ||
| END | ||
| `, | ||
| { printWidth: 45 }, | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| it(`formats quantifier expressions`, async () => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would turn this function into:
Then all that logic for determining whether it's an empty parenthesis would live in one place, and also the name of the function would IMHO be easier to understand.