From 6c1ecde6bb2d16a9eb0a1f99f8b77682b26e9926 Mon Sep 17 00:00:00 2001 From: cnbei Date: Sun, 30 Aug 2026 16:17:11 +0000 Subject: [PATCH] fix: support -- sql-formatter-disable line comments Recognize -- sql-formatter-disable / -- sql-formatter-enable the same way as block-comment disable markers, so formatting can be skipped without /* */ comments (issue #912). --- src/formatter/ExpressionFormatter.ts | 8 +- src/lexer/Tokenizer.ts | 5 ++ src/lexer/token.ts | 3 +- test/features/disableComment.ts | 110 +++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/formatter/ExpressionFormatter.ts b/src/formatter/ExpressionFormatter.ts index 2c1fdc634c..f8fda88590 100644 --- a/src/formatter/ExpressionFormatter.ts +++ b/src/formatter/ExpressionFormatter.ts @@ -406,7 +406,13 @@ export default class ExpressionFormatter { } private formatBlockComment(node: BlockCommentNode | DisableCommentNode) { - if (node.type === NodeType.block_comment && this.isStandaloneBlockComment(node)) { + if (node.type === NodeType.disable_comment) { + this.layout.add(node.text, WS.SPACE); + // Place following SQL on the next indented line after a multi-line region. + if (isMultiline(node.text)) { + this.layout.add(WS.NEWLINE, WS.INDENT); + } + } else if (this.isStandaloneBlockComment(node)) { this.splitBlockComment(node.text).forEach(line => { this.layout.add(WS.NEWLINE, WS.INDENT, line); }); diff --git a/src/lexer/Tokenizer.ts b/src/lexer/Tokenizer.ts index ba761de0ae..d92d500592 100644 --- a/src/lexer/Tokenizer.ts +++ b/src/lexer/Tokenizer.ts @@ -36,6 +36,11 @@ export default class Tokenizer { regex: /(\/\* *sql-formatter-disable *\*\/[\s\S]*?(?:\/\* *sql-formatter-enable *\*\/|$))/uy, }, + { + type: TokenType.DISABLE_COMMENT, + regex: + /(-- *sql-formatter-disable\b[^\n\r]*(?:(?:\r\n|\r|\n)[\s\S]*?(?:-- *sql-formatter-enable\b[^\n\r]*|$)|$))/uy, + }, { type: TokenType.BLOCK_COMMENT, regex: cfg.nestedBlockComments ? new NestedComment() : /(\/\*[^]*?\*\/)/uy, diff --git a/src/lexer/token.ts b/src/lexer/token.ts index 345a46e220..6716915fba 100644 --- a/src/lexer/token.ts +++ b/src/lexer/token.ts @@ -34,7 +34,8 @@ export enum TokenType { CLOSE_PAREN = 'CLOSE_PAREN', LINE_COMMENT = 'LINE_COMMENT', BLOCK_COMMENT = 'BLOCK_COMMENT', - // Text between /* sql-formatter-disable */ and /* sql-formatter-enable */ + // Text between sql-formatter-disable and sql-formatter-enable comments + // (either /* ... */ or -- ... line comments) DISABLE_COMMENT = 'DISABLE_COMMENT', NUMBER = 'NUMBER', NAMED_PARAMETER = 'NAMED_PARAMETER', diff --git a/test/features/disableComment.ts b/test/features/disableComment.ts index d1792efdad..30f0dc463f 100644 --- a/test/features/disableComment.ts +++ b/test/features/disableComment.ts @@ -83,4 +83,114 @@ export default function supportsDisableComment(format: FormatFn) { bar; `); }); + + it('does not format text between -- sql-formatter-disable and -- sql-formatter-enable', () => { + const result = format(dedent` + SELECT foo FROM bar; + -- sql-formatter-disable + SELECT foo FROM bar; + -- sql-formatter-enable + SELECT foo FROM bar; + `); + + expect(result).toBe(dedent` + SELECT + foo + FROM + bar; + + -- sql-formatter-disable + SELECT foo FROM bar; + -- sql-formatter-enable + SELECT + foo + FROM + bar; + `); + }); + + // Issue #912 + it('preserves indentation between -- sql-formatter-disable and -- sql-formatter-enable', () => { + const result = format(dedent` + -- sql-formatter-disable + SELECT + foo + FROM + bar; + -- sql-formatter-enable + `); + + expect(result).toBe(dedent` + -- sql-formatter-disable + SELECT + foo + FROM + bar; + -- sql-formatter-enable + `); + }); + + it('does not format text after -- sql-formatter-disable until end of file', () => { + const result = format(dedent` + SELECT foo FROM bar; + -- sql-formatter-disable + SELECT foo FROM bar; + + SELECT foo FROM bar; + `); + + expect(result).toBe(dedent` + SELECT + foo + FROM + bar; + + -- sql-formatter-disable + SELECT foo FROM bar; + + SELECT foo FROM bar; + `); + }); + + it('does not parse code between -- disable/enable comments', () => { + const result = format(dedent` + SELECT + -- sql-formatter-disable + ?!{}[] + -- sql-formatter-enable + FROM bar; + `); + + expect(result).toBe(dedent` + SELECT + -- sql-formatter-disable + ?!{}[] + -- sql-formatter-enable + FROM + bar; + `); + }); + + // Issue #912 + it('does not format sqlc.embed() between -- sql-formatter-disable comments', () => { + const result = format(dedent` + SELECT + -- sql-formatter-disable + sqlc.embed(users), + -- sql-formatter-enable + customers.id + FROM + customers + `); + + expect(result).toBe(dedent` + SELECT + -- sql-formatter-disable + sqlc.embed(users), + -- sql-formatter-enable + customers.id + FROM + customers + `); + }); }