Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/formatter/Formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ export default class Formatter {

private formatAst(statements: StatementNode[]): string {
return statements
.map(stat => this.formatStatement(stat))
.map((stat, i) => this.formatStatement(stat, i > 0))
.join('\n'.repeat(this.cfg.linesBetweenQueries + 1));
}

private formatStatement(statement: StatementNode): string {
private formatStatement(statement: StatementNode, startsOnNewLine: boolean): string {
const layout = new ExpressionFormatter({
cfg: this.cfg,
dialectCfg: this.dialect.formatOptions,
params: this.params,
layout: new Layout(new Indentation(indentString(this.cfg))),
layout: new Layout(new Indentation(indentString(this.cfg)), startsOnNewLine),
}).format(statement.children);

if (!statement.hasSemicolon) {
Expand Down
12 changes: 7 additions & 5 deletions src/formatter/Layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type LayoutItem = WS.SPACE | WS.SINGLE_INDENT | WS.NEWLINE | WS.MANDATORY
export default class Layout {
private items: LayoutItem[] = [];

constructor(public indentation: Indentation) {}
constructor(public indentation: Indentation, private startsOnNewLine: boolean = false) {}

/**
* Appends token strings and whitespace modifications to SQL string.
Expand Down Expand Up @@ -123,9 +123,11 @@ export default class Layout {
}

/**
* True when some content has already been added and nothing but indentation
* has been emitted since the last newline, meaning the next token would be
* placed at the start of a fresh (non-first) line.
* True when nothing but indentation has been emitted since the last newline,
* meaning the next token would be placed at the start of a fresh line.
*
* An empty layout counts when the statement itself is preceded by others,
* since the formatter joins statements with newlines.
*/
public isAtStartOfLine(): boolean {
for (let i = this.items.length - 1; i >= 0; i--) {
Expand All @@ -135,7 +137,7 @@ export default class Layout {
}
return item === WS.NEWLINE || item === WS.MANDATORY_NEWLINE;
}
return false;
return this.startsOnNewLine;
}

private itemToString(item: LayoutItem): string {
Expand Down
13 changes: 13 additions & 0 deletions test/features/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ export default function supportsComments(format: FormatFn, opts: CommentsConfig
expect(format(result)).toBe(result);
});

it('keeps a block comment leading a later statement on its own line', () => {
const sql = 'SELECT 1; /* c */ COMMIT;';
const result = dedent`
SELECT
1;

/* c */
COMMIT;
`;
expect(format(sql)).toBe(result);
expect(format(result)).toBe(result);
});

it('keeps block comments in various CREATE TABLE statement positions idempotent', () => {
const sql =
'CREATE TABLE /* c */ tbl (/* c */ id INT, /* c */ first_name TEXT, last_name TEXT)';
Expand Down
Loading