Skip to content

Commit a1d0cce

Browse files
committed
refactor: use library scanSync directly, remove block comment support
- Remove all block comment (/* */) handling — only -- line comments supported - Simplify scanner.ts to use @libpg-query/parser scanSync directly - Add pnpm patch for upstream scanSync JSON serialization bug (control chars in token text) - Update types.ts: RawComment.type is now just 'line' - Update deparse.ts: remove block comment case - Update index.ts: re-export loadModule from @libpg-query/parser directly - Remove block comment tests from scanner.test.ts and parse.test.ts - All 28 tests passing
1 parent c5781e6 commit a1d0cce

9 files changed

Lines changed: 86 additions & 297 deletions

File tree

packages/parse/__tests__/parse.test.ts

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,6 @@ describe('parse (enhanced)', () => {
2222
expect(comments[0].RawComment.text).toBe(' this is a comment');
2323
});
2424

25-
it('preserves block comments before statements', () => {
26-
const sql = '/* block comment */\nSELECT 1;';
27-
const result = parseSync(sql);
28-
const comments = result.stmts.filter(isRawComment);
29-
expect(comments).toHaveLength(1);
30-
expect(comments[0].RawComment.type).toBe('block');
31-
expect(comments[0].RawComment.text).toBe(' block comment ');
32-
});
33-
3425
it('preserves vertical whitespace between statements', () => {
3526
const sql = 'SELECT 1;\n\n\nSELECT 2;';
3627
const result = parseSync(sql);
@@ -70,14 +61,6 @@ COMMIT;`;
7061
expect(comments[1].RawComment.text).toContain('requires');
7162
});
7263

73-
it('handles nested block comments', () => {
74-
const sql = '/* outer /* inner */ still outer */ SELECT 1;';
75-
const result = parseSync(sql);
76-
const comments = result.stmts.filter(isRawComment);
77-
expect(comments).toHaveLength(1);
78-
expect(comments[0].RawComment.text).toContain('inner');
79-
});
80-
8164
it('does not pick up comments inside string literals', () => {
8265
const sql = "SELECT '-- not a comment';";
8366
const result = parseSync(sql);
@@ -125,14 +108,6 @@ describe('deparseEnhanced', () => {
125108
expect(output).toContain('SELECT 1');
126109
});
127110

128-
it('deparses with block comments preserved', () => {
129-
const sql = '/* block */ SELECT 1;';
130-
const result = parseSync(sql);
131-
const output = deparseEnhanced(result);
132-
expect(output).toContain('/* block */');
133-
expect(output).toContain('SELECT 1');
134-
});
135-
136111
it('round-trips comments through parse→deparse', () => {
137112
const sql = `-- header comment
138113
SELECT 1;
@@ -147,28 +122,6 @@ SELECT 2;`;
147122
expect(output).toContain('SELECT 2');
148123
});
149124

150-
it('round-trips block comments through parse→deparse', () => {
151-
const sql = `/* header */
152-
SELECT 1;
153-
154-
/* footer */
155-
SELECT 2;`;
156-
const result = parseSync(sql);
157-
const output = deparseEnhanced(result);
158-
expect(output).toContain('/* header */');
159-
expect(output).toContain('/* footer */');
160-
});
161-
162-
it('preserves multiple comment types', () => {
163-
const sql = `-- line comment
164-
/* block comment */
165-
SELECT 1;`;
166-
const result = parseSync(sql);
167-
const output = deparseEnhanced(result);
168-
expect(output).toContain('-- line comment');
169-
expect(output).toContain('/* block comment */');
170-
});
171-
172125
it('idempotent: parse→deparse→parse→deparse produces same output', () => {
173126
const sql = `-- Deploy schemas/test/tables/foo to pg
174127
-- requires: schemas/test/schema
@@ -189,15 +142,10 @@ COMMIT;`;
189142
});
190143

191144
describe('kitchen sink', () => {
192-
it('handles a complex SQL file with all comment types', () => {
145+
it('handles a complex SQL file with line comments', () => {
193146
const sql = `-- Deploy schemas/my-app/tables/users to pg
194147
-- requires: schemas/my-app/schema
195148
196-
/*
197-
* This file creates the users table
198-
* with all required columns.
199-
*/
200-
201149
BEGIN;
202150
203151
-- Create the main users table
@@ -207,7 +155,7 @@ CREATE TABLE my_app.users (
207155
email text UNIQUE
208156
);
209157
210-
/* Add an index for lookups */
158+
-- Add an index for lookups
211159
CREATE INDEX idx_users_email ON my_app.users (email);
212160
213161
-- Grant permissions
@@ -221,9 +169,8 @@ COMMIT;`;
221169
// All comments should survive
222170
expect(output).toContain('-- Deploy schemas/my-app/tables/users to pg');
223171
expect(output).toContain('-- requires: schemas/my-app/schema');
224-
expect(output).toContain('This file creates the users table');
225172
expect(output).toContain('-- Create the main users table');
226-
expect(output).toContain('/* Add an index for lookups */');
173+
expect(output).toContain('-- Add an index for lookups');
227174
expect(output).toContain('-- Grant permissions');
228175

229176
// All statements should survive

packages/parse/__tests__/scanner.test.ts

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { scanComments, ScannedElement, initWasm } from '../src/scanner';
1+
import { scanComments, ScannedElement } from '../src/scanner';
2+
import { loadModule } from '@libpg-query/parser';
23

34
describe('scanComments', () => {
45
beforeAll(async () => {
5-
await initWasm();
6+
await loadModule();
67
});
78
describe('line comments', () => {
89
it('extracts a simple line comment', () => {
@@ -36,38 +37,6 @@ describe('scanComments', () => {
3637
});
3738
});
3839

39-
describe('block comments', () => {
40-
it('extracts a simple block comment', () => {
41-
const sql = '/* block */ SELECT 1;';
42-
const elements = scanComments(sql);
43-
const comments = elements.filter(e => e.kind === 'comment');
44-
expect(comments).toHaveLength(1);
45-
expect(comments[0].value).toMatchObject({
46-
type: 'block',
47-
text: ' block ',
48-
start: 0,
49-
end: 11,
50-
});
51-
});
52-
53-
it('handles nested block comments', () => {
54-
const sql = '/* outer /* inner */ still outer */ SELECT 1;';
55-
const elements = scanComments(sql);
56-
const comments = elements.filter(e => e.kind === 'comment');
57-
expect(comments).toHaveLength(1);
58-
expect(comments[0].value.text).toBe(' outer /* inner */ still outer ');
59-
});
60-
61-
it('handles multi-line block comments', () => {
62-
const sql = '/*\n multi\n line\n*/ SELECT 1;';
63-
const elements = scanComments(sql);
64-
const comments = elements.filter(e => e.kind === 'comment');
65-
expect(comments).toHaveLength(1);
66-
expect(comments[0].value.text).toContain('multi');
67-
expect(comments[0].value.text).toContain('line');
68-
});
69-
});
70-
7140
describe('string literals (should be skipped)', () => {
7241
it('ignores -- inside a string literal', () => {
7342
const sql = "SELECT '-- not a comment';";

packages/parse/src/deparse.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@ import {
2121
* Deparse a single RawComment node back to SQL comment text.
2222
*/
2323
function deparseComment(comment: RawComment): string {
24-
if (comment.type === 'line') {
25-
return `--${comment.text}`;
26-
}
27-
// Block comment
28-
return `/*${comment.text}*/`;
24+
return `--${comment.text}`;
2925
}
3026

3127
/**

packages/parse/src/index.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/**
22
* pgsql-parse — Comment and whitespace preserving PostgreSQL parser.
33
*
4-
* Drop-in enhancement over pgsql-parser that preserves SQL comments
5-
* (-- line and /* block *​/) and vertical whitespace (blank lines)
6-
* through parse→deparse round trips.
4+
* Drop-in enhancement over pgsql-parser that preserves SQL -- line
5+
* comments and vertical whitespace (blank lines) through
6+
* parse→deparse round trips.
77
*
88
* Synthetic AST nodes:
99
* - RawComment: represents a SQL comment
@@ -22,14 +22,8 @@ export { deparseEnhanced, deparseEnhancedSync, Deparser, DeparserOptions } from
2222
// Re-export standard deparse for non-enhanced use
2323
export { deparse, deparseSync } from 'pgsql-deparser';
2424

25-
// Unified loadModule that initializes both the library's WASM
26-
// (for parse/deparse) and our scanner's WASM (for _wasm_scan).
27-
import { loadModule as libLoadModule } from '@libpg-query/parser';
28-
import { initWasm } from './scanner';
29-
30-
export async function loadModule(): Promise<void> {
31-
await Promise.all([libLoadModule(), initWasm()]);
32-
}
25+
// Re-export loadModule from @libpg-query/parser
26+
export { loadModule } from '@libpg-query/parser';
3327

3428
// Types
3529
export {

0 commit comments

Comments
 (0)