fix: ignore comments when post-processing tokens - #979
Open
Jeremy-xuan wants to merge 1 commit into
Open
Jeremy-xuan wants to merge 1 commit into
Jeremy-xuan wants to merge 1 commit into
Conversation
The dialect postProcess() steps look at the tokens adjacent to the one they
are inspecting. Comments are tokens too, so a comment between two syntax
elements used to defeat these checks:
- BigQuery threw a Parse error on arr[/* c */ OFFSET(0)], because
detectArraySubscripts() only recognized OFFSET when the previous token was
literally "[", leaving OFFSET a clause token.
- ClickHouse formatted EXPLAIN AST /* c */ SELECT and
CHECK GRANT /* c */ SELECT differently than without the comment, because the
placement of SELECT looks at a neighbouring clause or comma.
- Spark formatted window /* c */ (time) as a WINDOW clause instead of a
function call, because the function check compares the next token with "(".
- MySQL/MariaDB/TiDB/SingleStoreDB stopped treating SET( and VALUES() as
functions, because the check compares the next token with "(".
These checks are about the surrounding syntax, so they now skip comment
tokens, using the same idea as the existing plsql postProcess which already
tracks the previous reserved token instead of the previous token.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: ignore comments when post-processing tokens
What's wrong
The dialect
postProcess()steps compare a token with its immediate neighbours, andcomments are tokens too — so a comment between two syntax elements defeats these
checks. Three symptoms, one cause.
1. BigQuery throws a
Parse error(comments beforeOFFSETinside an array subscript):A line comment does the same (
arr[-- c\nOFFSET(0)]).arr[OFFSET(/* c */ 0)]isunaffected — only a comment between
[andOFFSETbreaks.2. ClickHouse stops demoting
SELECTin privilege statements:Before:
CHECK GRANT\n /* c */\nSELECT\n ON db.tableAfter:
CHECK GRANT\n /* c */\n SELECT ON db.table— matches the comment-free output.3. Spark formats
window(...)as aWINDOWclause instead of a function call:4. MySQL/MariaDB/TiDB/SingleStoreDB and ClickHouse stop treating
SET(andVALUES()as functions(the tokenizer keeps them as clauses when a comment sits between the name and the parens):
Both are
RESERVED_FUNCTION_NAMEafter this change; before it, the commented variantstayed
RESERVED_CLAUSE/RESERVED_KEYWORDand was formatted as a statement.Root cause
These look at the literal neighbours, so any comment in between hides the token that
the check is actually about.
plsql.formatter.tsalready does this correctly — ittracks
previousReservedTokeninstead of the previous token — so the fix follows anexisting in-repo pattern.
The fix
Two small helpers in
src/lexer/token.ts, used by all four post-processing steps:Comment token types skipped:
LINE_COMMENT,BLOCK_COMMENT,DISABLE_COMMENT(the
sql-formatter-disableregion is also not syntax).plsql.formatter.tswas left alone: it already skips everything that is not a reservedtoken, so it was never affected.
Scope
This covers the four
postProcessimplementations. The same hazard exists inbigquery.formatter.ts'scombineParameterizedTypes(), which also compares itselfagainst the next token (
tokens[i + 1]?.text === '<') — but that one cannot be fixedthe same way, because it slices the token range it decided on and joins it with no
separator. Skipping comments there changes which tokens fall inside that range, so a
one-line change to the comparison makes things worse rather than better. It needs its
own change and is left out of this PR on purpose.
Tests
Regression tests in the test files that own each behaviour:
test/bigquery.test.ts—OFFSETafter a block comment and after a line comment (2)test/clickhouse.test.ts—EXPLAIN AST,CHECK GRANTandSET(with a comment (5)test/spark.test.ts—WINDOW()after a block comment and after a line comment (2)test/behavesLikeMariaDbFormatter.ts—VALUES()after a block and a line comment,which runs against MySQL, MariaDB, TiDB and SingleStoreDB through the shared suite (2 × 4 dialects)
test/mysql.test.ts—SET(with a comment (1)Every assertion fails on
masterand passes with this change (checked by revertingsrc/tomasterand re-running: 18 failures, all of them these tests).