rawsql-ts 0.11.29-beta → 0.11.31-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/esm/index.js +1 -0
  2. package/dist/esm/index.js.map +1 -1
  3. package/dist/esm/index.min.js +18 -16
  4. package/dist/esm/index.min.js.map +4 -4
  5. package/dist/esm/src/index.d.ts +2 -0
  6. package/dist/esm/src/index.js +1 -0
  7. package/dist/esm/src/index.js.map +1 -1
  8. package/dist/esm/src/parsers/SelectQueryParser.d.ts +51 -0
  9. package/dist/esm/src/parsers/SelectQueryParser.js +55 -0
  10. package/dist/esm/src/parsers/SelectQueryParser.js.map +1 -1
  11. package/dist/esm/src/transformers/SelectableColumnCollector.d.ts +5 -0
  12. package/dist/esm/src/transformers/SelectableColumnCollector.js +18 -2
  13. package/dist/esm/src/transformers/SelectableColumnCollector.js.map +1 -1
  14. package/dist/esm/src/utils/CTERegionDetector.d.ts +254 -0
  15. package/dist/esm/src/utils/CTERegionDetector.js +457 -0
  16. package/dist/esm/src/utils/CTERegionDetector.js.map +1 -0
  17. package/dist/esm/src/utils/LexemeCursor.d.ts +41 -10
  18. package/dist/esm/src/utils/LexemeCursor.js +46 -16
  19. package/dist/esm/src/utils/LexemeCursor.js.map +1 -1
  20. package/dist/esm/tsconfig.browser.tsbuildinfo +1 -1
  21. package/dist/index.min.js +18 -16
  22. package/dist/index.min.js.map +4 -4
  23. package/dist/src/index.d.ts +2 -0
  24. package/dist/src/index.js +1 -0
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/parsers/SelectQueryParser.d.ts +51 -0
  27. package/dist/src/parsers/SelectQueryParser.js +55 -0
  28. package/dist/src/parsers/SelectQueryParser.js.map +1 -1
  29. package/dist/src/transformers/SelectableColumnCollector.d.ts +5 -0
  30. package/dist/src/transformers/SelectableColumnCollector.js +18 -2
  31. package/dist/src/transformers/SelectableColumnCollector.js.map +1 -1
  32. package/dist/src/utils/CTERegionDetector.d.ts +254 -0
  33. package/dist/src/utils/CTERegionDetector.js +464 -0
  34. package/dist/src/utils/CTERegionDetector.js.map +1 -0
  35. package/dist/src/utils/LexemeCursor.d.ts +41 -10
  36. package/dist/src/utils/LexemeCursor.js +46 -16
  37. package/dist/src/utils/LexemeCursor.js.map +1 -1
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +1 -1
@@ -0,0 +1,464 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CTERegionDetector = void 0;
4
+ const Lexeme_1 = require("../models/Lexeme");
5
+ const LexemeCursor_1 = require("./LexemeCursor");
6
+ /**
7
+ * Utility class for detecting CTE (Common Table Expression) regions and extracting executable SQL.
8
+ *
9
+ * Designed for SQL editor features where users want to execute specific CTE parts based on cursor position.
10
+ * This enables editors to provide "run current section" functionality that intelligently executes
11
+ * either the CTE the cursor is in, or the main query.
12
+ *
13
+ * @example Basic usage - Analyze cursor position
14
+ * ```typescript
15
+ * const sql = `
16
+ * WITH users_cte AS (
17
+ * SELECT id, name FROM users WHERE active = true
18
+ * )
19
+ * SELECT * FROM users_cte ORDER BY name
20
+ * `;
21
+ *
22
+ * const cursorPosition = 50; // Inside the CTE
23
+ * const analysis = CTERegionDetector.analyzeCursorPosition(sql, cursorPosition);
24
+ *
25
+ * if (analysis.isInCTE) {
26
+ * console.log(`Execute CTE: ${analysis.cteRegion.name}`);
27
+ * executeSQL(analysis.executableSQL); // Runs just the CTE SELECT
28
+ * }
29
+ * ```
30
+ *
31
+ * @example Get all executable sections
32
+ * ```typescript
33
+ * const positions = CTERegionDetector.getCTEPositions(sql);
34
+ * // Returns: [
35
+ * // { name: 'users_cte', startPosition: 17, type: 'CTE' },
36
+ * // { name: 'MAIN_QUERY', startPosition: 120, type: 'MAIN_QUERY' }
37
+ * // ]
38
+ * ```
39
+ */
40
+ class CTERegionDetector {
41
+ /**
42
+ * Analyze cursor position and return information about the current context.
43
+ *
44
+ * This is the main method for SQL editor integration. It determines whether the cursor
45
+ * is inside a CTE or the main query, and provides the appropriate executable SQL.
46
+ *
47
+ * @param sql - The complete SQL string to analyze
48
+ * @param cursorPosition - The cursor position (0-based character offset)
49
+ * @returns Analysis result containing context information and executable SQL
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const sql = `WITH users AS (SELECT * FROM table) SELECT * FROM users`;
54
+ * const analysis = CTERegionDetector.analyzeCursorPosition(sql, 25);
55
+ *
56
+ * if (analysis.isInCTE) {
57
+ * console.log(`Cursor is in CTE: ${analysis.cteRegion.name}`);
58
+ * executeSQL(analysis.executableSQL); // Execute just the CTE
59
+ * } else {
60
+ * console.log('Cursor is in main query');
61
+ * executeSQL(analysis.executableSQL); // Execute the full query
62
+ * }
63
+ * ```
64
+ */
65
+ static analyzeCursorPosition(sql, cursorPosition) {
66
+ const cteRegions = this.extractCTERegions(sql);
67
+ const extendedRegions = this.calculateExtendedCTEBoundaries(sql, cteRegions);
68
+ // Find which CTE region contains the cursor using extended boundaries
69
+ const currentCTE = extendedRegions.find(region => cursorPosition >= region.startPosition && cursorPosition < region.extendedEndPosition);
70
+ if (currentCTE) {
71
+ return {
72
+ isInCTE: true,
73
+ cteRegion: {
74
+ name: currentCTE.name,
75
+ startPosition: currentCTE.startPosition,
76
+ endPosition: currentCTE.endPosition,
77
+ sqlContent: currentCTE.sqlContent
78
+ },
79
+ executableSQL: currentCTE.sqlContent
80
+ };
81
+ }
82
+ else {
83
+ // Cursor is in main query - return full SQL or main SELECT part
84
+ const mainSQL = this.extractMainQuery(sql, cteRegions);
85
+ return {
86
+ isInCTE: false,
87
+ cteRegion: null,
88
+ executableSQL: mainSQL
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Get the CTE name at the specified cursor position (simplified interface).
94
+ *
95
+ * This method provides a simple interface for retrieving just the CTE name
96
+ * without additional context information.
97
+ *
98
+ * @param sql - The SQL string to analyze
99
+ * @param cursorPosition - The cursor position (0-based character offset)
100
+ * @returns The CTE name if cursor is in a CTE, null otherwise
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const sql = `WITH users AS (SELECT * FROM table) SELECT * FROM users`;
105
+ * const cteName = CTERegionDetector.getCursorCte(sql, 25);
106
+ * console.log(cteName); // "users"
107
+ * ```
108
+ */
109
+ static getCursorCte(sql, cursorPosition) {
110
+ var _a;
111
+ try {
112
+ const analysis = this.analyzeCursorPosition(sql, cursorPosition);
113
+ return analysis.isInCTE ? ((_a = analysis.cteRegion) === null || _a === void 0 ? void 0 : _a.name) || null : null;
114
+ }
115
+ catch (error) {
116
+ return null;
117
+ }
118
+ }
119
+ /**
120
+ * Get the CTE name at the specified 2D coordinates (line, column).
121
+ *
122
+ * This method provides a convenient interface for editor integrations
123
+ * that work with line/column coordinates instead of character positions.
124
+ *
125
+ * @param sql - The SQL string to analyze
126
+ * @param line - The line number (1-based)
127
+ * @param column - The column number (1-based)
128
+ * @returns The CTE name if cursor is in a CTE, null otherwise
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const sql = `WITH users AS (\n SELECT * FROM table\n) SELECT * FROM users`;
133
+ * const cteName = CTERegionDetector.getCursorCteAt(sql, 2, 5);
134
+ * console.log(cteName); // "users"
135
+ * ```
136
+ */
137
+ static getCursorCteAt(sql, line, column) {
138
+ try {
139
+ const position = this.lineColumnToPosition(sql, line, column);
140
+ if (position === -1) {
141
+ return null;
142
+ }
143
+ return this.getCursorCte(sql, position);
144
+ }
145
+ catch (error) {
146
+ return null;
147
+ }
148
+ }
149
+ /**
150
+ * Convert line/column coordinates to character position.
151
+ *
152
+ * @param text - The text to analyze
153
+ * @param line - The line number (1-based)
154
+ * @param column - The column number (1-based)
155
+ * @returns The character position (0-based), or -1 if invalid coordinates
156
+ */
157
+ static lineColumnToPosition(text, line, column) {
158
+ if (line < 1 || column < 1) {
159
+ return -1;
160
+ }
161
+ const lines = text.split('\n');
162
+ if (line > lines.length) {
163
+ return -1;
164
+ }
165
+ const targetLine = lines[line - 1];
166
+ if (column > targetLine.length + 1) { // +1 to allow position at end of line
167
+ return -1;
168
+ }
169
+ // Calculate position by summing lengths of previous lines plus newlines
170
+ let position = 0;
171
+ for (let i = 0; i < line - 1; i++) {
172
+ position += lines[i].length + 1; // +1 for the newline character
173
+ }
174
+ position += column - 1; // column is 1-based, position is 0-based
175
+ return position;
176
+ }
177
+ /**
178
+ * Convert character position to line/column coordinates.
179
+ *
180
+ * @param text - The text to analyze
181
+ * @param position - The character position (0-based)
182
+ * @returns Object with line and column (1-based), or null if invalid position
183
+ */
184
+ static positionToLineColumn(text, position) {
185
+ if (position < 0 || position > text.length) {
186
+ return null;
187
+ }
188
+ const beforePosition = text.substring(0, position);
189
+ const lines = beforePosition.split('\n');
190
+ return {
191
+ line: lines.length,
192
+ column: lines[lines.length - 1].length + 1
193
+ };
194
+ }
195
+ /**
196
+ * Extract all CTE regions from SQL text with their boundaries and executable content.
197
+ *
198
+ * Parses the SQL to identify all Common Table Expressions and their locations,
199
+ * providing the information needed for syntax highlighting, code folding, and selective execution.
200
+ *
201
+ * @param sql - The SQL string to analyze
202
+ * @returns Array of CTE regions with their boundaries and content
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const sql = `
207
+ * WITH
208
+ * users AS (SELECT * FROM people),
209
+ * orders AS (SELECT * FROM purchases)
210
+ * SELECT * FROM users JOIN orders
211
+ * `;
212
+ *
213
+ * const regions = CTERegionDetector.extractCTERegions(sql);
214
+ * // Returns: [
215
+ * // { name: 'users', startPosition: 23, endPosition: 45, sqlContent: 'SELECT * FROM people' },
216
+ * // { name: 'orders', startPosition: 55, endPosition: 80, sqlContent: 'SELECT * FROM purchases' }
217
+ * // ]
218
+ * ```
219
+ */
220
+ static extractCTERegions(sql) {
221
+ const lexemes = LexemeCursor_1.LexemeCursor.getAllLexemesWithPosition(sql);
222
+ const cteRegions = [];
223
+ let i = 0;
224
+ let inWithClause = false;
225
+ while (i < lexemes.length) {
226
+ const lexeme = lexemes[i];
227
+ // Detect WITH clause start
228
+ if (lexeme.value.toLowerCase() === 'with' && !inWithClause) {
229
+ inWithClause = true;
230
+ i++;
231
+ continue;
232
+ }
233
+ // Skip RECURSIVE keyword if present
234
+ if (inWithClause && lexeme.value.toLowerCase() === 'recursive') {
235
+ i++;
236
+ continue;
237
+ }
238
+ // Detect CTE definition (identifier followed by AS)
239
+ if (inWithClause &&
240
+ lexeme.type === Lexeme_1.TokenType.Identifier &&
241
+ i + 1 < lexemes.length &&
242
+ lexemes[i + 1].value.toLowerCase() === 'as') {
243
+ const cteName = lexeme.value;
244
+ const cteStartPos = lexeme.position.startPosition;
245
+ // Find the opening parenthesis after AS
246
+ let parenIndex = i + 2;
247
+ while (parenIndex < lexemes.length && lexemes[parenIndex].value !== '(') {
248
+ parenIndex++;
249
+ }
250
+ if (parenIndex < lexemes.length) {
251
+ // Find matching closing parenthesis
252
+ const cteEndInfo = this.findMatchingParen(lexemes, parenIndex);
253
+ if (cteEndInfo) {
254
+ const cteEndPos = cteEndInfo.endPosition;
255
+ const sqlContent = this.extractCTESQL(sql, lexemes, parenIndex, cteEndInfo.index);
256
+ cteRegions.push({
257
+ name: cteName,
258
+ startPosition: cteStartPos,
259
+ endPosition: cteEndPos,
260
+ sqlContent: sqlContent
261
+ });
262
+ i = cteEndInfo.index + 1;
263
+ continue;
264
+ }
265
+ }
266
+ }
267
+ // Check if we've reached the main SELECT (end of WITH clause)
268
+ if (inWithClause && lexeme.value.toLowerCase() === 'select') {
269
+ // Verify this is not a SELECT inside a CTE by checking context
270
+ if (this.isMainQuerySelect(lexemes, i)) {
271
+ break;
272
+ }
273
+ }
274
+ i++;
275
+ }
276
+ return cteRegions;
277
+ }
278
+ /**
279
+ * Find matching closing parenthesis for CTE definition
280
+ */
281
+ static findMatchingParen(lexemes, openParenIndex) {
282
+ let depth = 1;
283
+ let i = openParenIndex + 1;
284
+ while (i < lexemes.length && depth > 0) {
285
+ if (lexemes[i].value === '(') {
286
+ depth++;
287
+ }
288
+ else if (lexemes[i].value === ')') {
289
+ depth--;
290
+ }
291
+ if (depth === 0) {
292
+ return {
293
+ index: i,
294
+ endPosition: lexemes[i].position.endPosition
295
+ };
296
+ }
297
+ i++;
298
+ }
299
+ return null;
300
+ }
301
+ /**
302
+ * Extract the SQL content of a CTE (the SELECT statement inside parentheses)
303
+ */
304
+ static extractCTESQL(sql, lexemes, openParenIndex, closeParenIndex) {
305
+ const startPos = lexemes[openParenIndex + 1].position.startPosition;
306
+ const endPos = lexemes[closeParenIndex - 1].position.endPosition;
307
+ return sql.substring(startPos, endPos).trim();
308
+ }
309
+ /**
310
+ * Check if a SELECT lexeme is the main query SELECT (not inside a CTE)
311
+ */
312
+ static isMainQuerySelect(lexemes, selectIndex) {
313
+ // Look backwards to see if we're still in a parenthesized context
314
+ let depth = 0;
315
+ for (let i = selectIndex - 1; i >= 0; i--) {
316
+ if (lexemes[i].value === ')') {
317
+ depth++;
318
+ }
319
+ else if (lexemes[i].value === '(') {
320
+ depth--;
321
+ }
322
+ }
323
+ return depth === 0; // We're at top level if depth is 0
324
+ }
325
+ /**
326
+ * Calculate extended CTE boundaries for better cursor position detection.
327
+ * Extended boundaries include the space between CTEs and before the main query.
328
+ */
329
+ static calculateExtendedCTEBoundaries(sql, cteRegions) {
330
+ if (cteRegions.length === 0) {
331
+ return [];
332
+ }
333
+ return cteRegions.map((region, index) => {
334
+ let extendedEndPosition;
335
+ if (index < cteRegions.length - 1) {
336
+ // Not the last CTE - extend to the start of the next CTE
337
+ extendedEndPosition = cteRegions[index + 1].startPosition;
338
+ }
339
+ else {
340
+ // Last CTE - extend to the start of the main query
341
+ const mainQueryStart = this.findMainQueryStart(sql, region.endPosition);
342
+ extendedEndPosition = mainQueryStart;
343
+ }
344
+ return {
345
+ ...region,
346
+ extendedEndPosition
347
+ };
348
+ });
349
+ }
350
+ /**
351
+ * Find the start position of the main query after the last CTE
352
+ */
353
+ static findMainQueryStart(sql, afterPosition) {
354
+ // Look for the main SELECT keyword after the CTE definitions
355
+ let pos = afterPosition;
356
+ while (pos < sql.length) {
357
+ const remaining = sql.substring(pos).toLowerCase().trim();
358
+ if (remaining.startsWith('select')) {
359
+ // Find the actual position of SELECT in the original text
360
+ const selectIndex = sql.toLowerCase().indexOf('select', pos);
361
+ return selectIndex !== -1 ? selectIndex : pos;
362
+ }
363
+ pos++;
364
+ }
365
+ return sql.length; // If no main query found, extend to end of string
366
+ }
367
+ /**
368
+ * Extract the main query part (non-CTE SQL)
369
+ */
370
+ static extractMainQuery(sql, cteRegions) {
371
+ if (cteRegions.length === 0) {
372
+ return sql.trim();
373
+ }
374
+ // Find the end of the last CTE
375
+ const lastCTE = cteRegions[cteRegions.length - 1];
376
+ const mainQueryStart = lastCTE.endPosition;
377
+ // Find the main SELECT
378
+ let selectPos = mainQueryStart;
379
+ while (selectPos < sql.length) {
380
+ const remaining = sql.substring(selectPos).toLowerCase().trim();
381
+ if (remaining.startsWith('select')) {
382
+ break;
383
+ }
384
+ selectPos++;
385
+ }
386
+ return sql.substring(selectPos).trim();
387
+ }
388
+ /**
389
+ * Get a list of all executable sections (CTEs and main query) with their start positions.
390
+ *
391
+ * This method is particularly useful for building editor UI features such as:
392
+ * - Dropdown menus for section selection
393
+ * - Sidebar navigation for large queries
394
+ * - Quick jump functionality
395
+ * - "Run section" buttons
396
+ *
397
+ * @param sql - The SQL string to analyze
398
+ * @returns Array of executable sections with their names, positions, and types
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * const sql = `
403
+ * WITH monthly_sales AS (SELECT ...),
404
+ * yearly_summary AS (SELECT ...)
405
+ * SELECT * FROM yearly_summary
406
+ * `;
407
+ *
408
+ * const positions = CTERegionDetector.getCTEPositions(sql);
409
+ * // Returns: [
410
+ * // { name: 'monthly_sales', startPosition: 17, type: 'CTE' },
411
+ * // { name: 'yearly_summary', startPosition: 55, type: 'CTE' },
412
+ * // { name: 'MAIN_QUERY', startPosition: 120, type: 'MAIN_QUERY' }
413
+ * // ]
414
+ *
415
+ * // Use for editor UI
416
+ * positions.forEach(section => {
417
+ * addMenuItem(`${section.type}: ${section.name}`, () => {
418
+ * jumpToPosition(section.startPosition);
419
+ * });
420
+ * });
421
+ * ```
422
+ */
423
+ static getCTEPositions(sql) {
424
+ const cteRegions = this.extractCTERegions(sql);
425
+ const results = [];
426
+ // Add CTE regions
427
+ cteRegions.forEach(region => {
428
+ results.push({
429
+ name: region.name,
430
+ startPosition: region.startPosition,
431
+ type: 'CTE'
432
+ });
433
+ });
434
+ // Add main query position
435
+ if (cteRegions.length > 0) {
436
+ const lastCTE = cteRegions[cteRegions.length - 1];
437
+ let mainQueryPos = lastCTE.endPosition;
438
+ // Find the SELECT keyword
439
+ while (mainQueryPos < sql.length) {
440
+ const remaining = sql.substring(mainQueryPos).toLowerCase().trim();
441
+ if (remaining.startsWith('select')) {
442
+ results.push({
443
+ name: 'MAIN_QUERY',
444
+ startPosition: mainQueryPos,
445
+ type: 'MAIN_QUERY'
446
+ });
447
+ break;
448
+ }
449
+ mainQueryPos++;
450
+ }
451
+ }
452
+ else {
453
+ // No CTEs, entire SQL is main query
454
+ results.push({
455
+ name: 'MAIN_QUERY',
456
+ startPosition: 0,
457
+ type: 'MAIN_QUERY'
458
+ });
459
+ }
460
+ return results;
461
+ }
462
+ }
463
+ exports.CTERegionDetector = CTERegionDetector;
464
+ //# sourceMappingURL=CTERegionDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CTERegionDetector.js","sourceRoot":"","sources":["../../../src/utils/CTERegionDetector.ts"],"names":[],"mappings":";;;AAAA,6CAAqD;AACrD,iDAA8C;AAiD9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAa,iBAAiB;IAC1B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACI,MAAM,CAAC,qBAAqB,CAAC,GAAW,EAAE,cAAsB;QACnE,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,8BAA8B,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAE7E,sEAAsE;QACtE,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAC7C,cAAc,IAAI,MAAM,CAAC,aAAa,IAAI,cAAc,GAAG,MAAM,CAAC,mBAAmB,CACxF,CAAC;QAEF,IAAI,UAAU,EAAE,CAAC;YACb,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE;oBACP,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,aAAa,EAAE,UAAU,CAAC,aAAa;oBACvC,WAAW,EAAE,UAAU,CAAC,WAAW;oBACnC,UAAU,EAAE,UAAU,CAAC,UAAU;iBACpC;gBACD,aAAa,EAAE,UAAU,CAAC,UAAU;aACvC,CAAC;QACN,CAAC;aAAM,CAAC;YACJ,gEAAgE;YAChE,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YACvD,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,IAAI;gBACf,aAAa,EAAE,OAAO;aACzB,CAAC;QACN,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACI,MAAM,CAAC,YAAY,CAAC,GAAW,EAAE,cAAsB;;QAC1D,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YACjE,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA,MAAA,QAAQ,CAAC,SAAS,0CAAE,IAAI,KAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACI,MAAM,CAAC,cAAc,CAAC,GAAW,EAAE,IAAY,EAAE,MAAc;QAClE,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9D,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACK,MAAM,CAAC,oBAAoB,CAAC,IAAY,EAAE,IAAY,EAAE,MAAc;QAC1E,IAAI,IAAI,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,CAAC,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACnC,IAAI,MAAM,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,sCAAsC;YACxE,OAAO,CAAC,CAAC,CAAC;QACd,CAAC;QAED,wEAAwE;QACxE,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,+BAA+B;QACpE,CAAC;QACD,QAAQ,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,yCAAyC;QAEjE,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,oBAAoB,CAAC,IAAY,EAAE,QAAgB;QAC7D,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,OAAO;YACH,IAAI,EAAE,KAAK,CAAC,MAAM;YAClB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;SAC7C,CAAC;IACN,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACI,MAAM,CAAC,iBAAiB,CAAC,GAAW;QACvC,MAAM,OAAO,GAAG,2BAAY,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,IAAI,YAAY,GAAG,KAAK,CAAC;QAEzB,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAE1B,2BAA2B;YAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;gBACzD,YAAY,GAAG,IAAI,CAAC;gBACpB,CAAC,EAAE,CAAC;gBACJ,SAAS;YACb,CAAC;YAED,oCAAoC;YACpC,IAAI,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,WAAW,EAAE,CAAC;gBAC7D,CAAC,EAAE,CAAC;gBACJ,SAAS;YACb,CAAC;YAED,oDAAoD;YACpD,IAAI,YAAY;gBACZ,MAAM,CAAC,IAAI,KAAK,kBAAS,CAAC,UAAU;gBACpC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM;gBACtB,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;gBAE9C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;gBAC7B,MAAM,WAAW,GAAG,MAAM,CAAC,QAAS,CAAC,aAAa,CAAC;gBAEnD,wCAAwC;gBACxC,IAAI,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;oBACtE,UAAU,EAAE,CAAC;gBACjB,CAAC;gBAED,IAAI,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC9B,oCAAoC;oBACpC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;oBAC/D,IAAI,UAAU,EAAE,CAAC;wBACb,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC;wBACzC,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;wBAElF,UAAU,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,OAAO;4BACb,aAAa,EAAE,WAAW;4BAC1B,WAAW,EAAE,SAAS;4BACtB,UAAU,EAAE,UAAU;yBACzB,CAAC,CAAC;wBAEH,CAAC,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC;wBACzB,SAAS;oBACb,CAAC;gBACL,CAAC;YACL,CAAC;YAED,8DAA8D;YAC9D,IAAI,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC1D,+DAA+D;gBAC/D,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC;oBACrC,MAAM;gBACV,CAAC;YACL,CAAC;YAED,CAAC,EAAE,CAAC;QACR,CAAC;QAED,OAAO,UAAU,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,iBAAiB,CAAC,OAAiB,EAAE,cAAsB;QACtE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC;QAE3B,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;gBAC3B,KAAK,EAAE,CAAC;YACZ,CAAC;iBAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;gBAClC,KAAK,EAAE,CAAC;YACZ,CAAC;YAED,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBACd,OAAO;oBACH,KAAK,EAAE,CAAC;oBACR,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAS,CAAC,WAAW;iBAChD,CAAC;YACN,CAAC;YACD,CAAC,EAAE,CAAC;QACR,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,aAAa,CAAC,GAAW,EAAE,OAAiB,EAAE,cAAsB,EAAE,eAAuB;QACxG,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,QAAS,CAAC,aAAa,CAAC;QACrE,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,QAAS,CAAC,WAAW,CAAC;QAElE,OAAO,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,iBAAiB,CAAC,OAAiB,EAAE,WAAmB;QACnE,kEAAkE;QAClE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;gBAC3B,KAAK,EAAE,CAAC;YACZ,CAAC;iBAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;gBAClC,KAAK,EAAE,CAAC;YACZ,CAAC;QACL,CAAC;QAED,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,mCAAmC;IAC3D,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,8BAA8B,CAAC,GAAW,EAAE,UAAuB;QAC9E,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACd,CAAC;QAED,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACpC,IAAI,mBAA2B,CAAC;YAEhC,IAAI,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,yDAAyD;gBACzD,mBAAmB,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACJ,mDAAmD;gBACnD,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;gBACxE,mBAAmB,GAAG,cAAc,CAAC;YACzC,CAAC;YAED,OAAO;gBACH,GAAG,MAAM;gBACT,mBAAmB;aACtB,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,kBAAkB,CAAC,GAAW,EAAE,aAAqB;QAChE,6DAA6D;QAC7D,IAAI,GAAG,GAAG,aAAa,CAAC;QACxB,OAAO,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;YAC1D,IAAI,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,0DAA0D;gBAC1D,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBAC7D,OAAO,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC;YAClD,CAAC;YACD,GAAG,EAAE,CAAC;QACV,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,kDAAkD;IACzE,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,gBAAgB,CAAC,GAAW,EAAE,UAAuB;QAChE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;QAED,+BAA+B;QAC/B,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClD,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;QAE3C,uBAAuB;QACvB,IAAI,SAAS,GAAG,cAAc,CAAC;QAC/B,OAAO,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;YAChE,IAAI,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,MAAM;YACV,CAAC;YACD,SAAS,EAAE,CAAC;QAChB,CAAC;QAED,OAAO,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACI,MAAM,CAAC,eAAe,CAAC,GAAW;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,OAAO,GAA+E,EAAE,CAAC;QAE/F,kBAAkB;QAClB,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACxB,OAAO,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,IAAI,EAAE,KAAK;aACd,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,0BAA0B;QAC1B,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClD,IAAI,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;YAEvC,0BAA0B;YAC1B,OAAO,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;gBACnE,IAAI,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACjC,OAAO,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,YAAY;wBAClB,aAAa,EAAE,YAAY;wBAC3B,IAAI,EAAE,YAAY;qBACrB,CAAC,CAAC;oBACH,MAAM;gBACV,CAAC;gBACD,YAAY,EAAE,CAAC;YACnB,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,oCAAoC;YACpC,OAAO,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,YAAY;gBAClB,aAAa,EAAE,CAAC;gBAChB,IAAI,EAAE,YAAY;aACrB,CAAC,CAAC;QACP,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ;AAhdD,8CAgdC"}
@@ -1,27 +1,58 @@
1
1
  import { Lexeme } from '../models/Lexeme';
2
2
  /**
3
- * Utility class for cursor-to-lexeme mapping in SQL text
4
- * Provides functionality to find lexemes at specific cursor positions for IDE integration
3
+ * Utility class for cursor-to-lexeme mapping in SQL text.
4
+ *
5
+ * Provides functionality to find lexemes at specific cursor positions for IDE integration.
6
+ * Handles SQL parsing with proper comment and whitespace handling for editor features.
7
+ *
8
+ * @example Basic usage
9
+ * ```typescript
10
+ * const sql = "SELECT id FROM users WHERE active = true";
11
+ * const lexeme = LexemeCursor.findLexemeAtPosition(sql, 7); // position at 'id'
12
+ * console.log(lexeme?.value); // 'id'
13
+ * ```
5
14
  */
6
15
  export declare class LexemeCursor {
7
16
  private static readonly SQL_COMMANDS;
8
17
  /**
9
- * Find the lexeme at the specified cursor position
10
- * @param sql The SQL string
11
- * @param cursorPosition The cursor position (0-based)
18
+ * Find the lexeme at the specified cursor position.
19
+ *
20
+ * Performs intelligent SQL parsing with proper comment and whitespace handling.
21
+ * Returns null if cursor is in whitespace or comments.
22
+ *
23
+ * @param sql - The SQL string to analyze
24
+ * @param cursorPosition - The cursor position (0-based character offset)
12
25
  * @returns The lexeme at the position, or null if not found
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const sql = "SELECT user_id FROM orders";
30
+ * const lexeme = LexemeCursor.findLexemeAtPosition(sql, 7);
31
+ * console.log(lexeme?.value); // 'user_id'
32
+ * ```
13
33
  */
14
34
  static findLexemeAtPosition(sql: string, cursorPosition: number): Lexeme | null;
15
35
  /**
16
- * Get all lexemes with position information
17
- * @param sql The SQL string
18
- * @returns Array of lexemes with position information
36
+ * Get all lexemes with position information from SQL text.
37
+ *
38
+ * Tokenizes the entire SQL string with precise position information.
39
+ * Useful for syntax highlighting, code analysis, and editor features.
40
+ *
41
+ * @param sql - The SQL string to tokenize
42
+ * @returns Array of lexemes with position information (excludes comments/whitespace)
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const sql = "SELECT id FROM users";
47
+ * const lexemes = LexemeCursor.getAllLexemesWithPosition(sql);
48
+ * lexemes.forEach(l => console.log(`${l.value} at ${l.position.startPosition}`));
49
+ * ```
19
50
  */
20
51
  static getAllLexemesWithPosition(sql: string): Lexeme[];
21
52
  /**
22
- * Skip whitespace characters
53
+ * Skip whitespace and comments, returning new position
23
54
  */
24
- private static skipWhitespace;
55
+ private static skipWhitespaceAndComments;
25
56
  /**
26
57
  * Parse the next token starting at the given position
27
58
  */
@@ -2,16 +2,37 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LexemeCursor = void 0;
4
4
  const Lexeme_1 = require("../models/Lexeme");
5
+ const stringUtils_1 = require("./stringUtils");
5
6
  /**
6
- * Utility class for cursor-to-lexeme mapping in SQL text
7
- * Provides functionality to find lexemes at specific cursor positions for IDE integration
7
+ * Utility class for cursor-to-lexeme mapping in SQL text.
8
+ *
9
+ * Provides functionality to find lexemes at specific cursor positions for IDE integration.
10
+ * Handles SQL parsing with proper comment and whitespace handling for editor features.
11
+ *
12
+ * @example Basic usage
13
+ * ```typescript
14
+ * const sql = "SELECT id FROM users WHERE active = true";
15
+ * const lexeme = LexemeCursor.findLexemeAtPosition(sql, 7); // position at 'id'
16
+ * console.log(lexeme?.value); // 'id'
17
+ * ```
8
18
  */
9
19
  class LexemeCursor {
10
20
  /**
11
- * Find the lexeme at the specified cursor position
12
- * @param sql The SQL string
13
- * @param cursorPosition The cursor position (0-based)
21
+ * Find the lexeme at the specified cursor position.
22
+ *
23
+ * Performs intelligent SQL parsing with proper comment and whitespace handling.
24
+ * Returns null if cursor is in whitespace or comments.
25
+ *
26
+ * @param sql - The SQL string to analyze
27
+ * @param cursorPosition - The cursor position (0-based character offset)
14
28
  * @returns The lexeme at the position, or null if not found
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const sql = "SELECT user_id FROM orders";
33
+ * const lexeme = LexemeCursor.findLexemeAtPosition(sql, 7);
34
+ * console.log(lexeme?.value); // 'user_id'
35
+ * ```
15
36
  */
16
37
  static findLexemeAtPosition(sql, cursorPosition) {
17
38
  if (cursorPosition < 0 || cursorPosition >= sql.length) {
@@ -28,9 +49,20 @@ class LexemeCursor {
28
49
  return null;
29
50
  }
30
51
  /**
31
- * Get all lexemes with position information
32
- * @param sql The SQL string
33
- * @returns Array of lexemes with position information
52
+ * Get all lexemes with position information from SQL text.
53
+ *
54
+ * Tokenizes the entire SQL string with precise position information.
55
+ * Useful for syntax highlighting, code analysis, and editor features.
56
+ *
57
+ * @param sql - The SQL string to tokenize
58
+ * @returns Array of lexemes with position information (excludes comments/whitespace)
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const sql = "SELECT id FROM users";
63
+ * const lexemes = LexemeCursor.getAllLexemesWithPosition(sql);
64
+ * lexemes.forEach(l => console.log(`${l.value} at ${l.position.startPosition}`));
65
+ * ```
34
66
  */
35
67
  static getAllLexemesWithPosition(sql) {
36
68
  if (!(sql === null || sql === void 0 ? void 0 : sql.trim())) {
@@ -40,7 +72,7 @@ class LexemeCursor {
40
72
  const lexemes = [];
41
73
  let position = 0;
42
74
  while (position < sql.length) {
43
- position = this.skipWhitespace(sql, position);
75
+ position = this.skipWhitespaceAndComments(sql, position);
44
76
  if (position >= sql.length) {
45
77
  break;
46
78
  }
@@ -60,13 +92,11 @@ class LexemeCursor {
60
92
  }
61
93
  }
62
94
  /**
63
- * Skip whitespace characters
95
+ * Skip whitespace and comments, returning new position
64
96
  */
65
- static skipWhitespace(sql, position) {
66
- while (position < sql.length && /\s/.test(sql[position])) {
67
- position++;
68
- }
69
- return position;
97
+ static skipWhitespaceAndComments(sql, position) {
98
+ const result = stringUtils_1.StringUtils.readWhiteSpaceAndComment(sql, position);
99
+ return result.position;
70
100
  }
71
101
  /**
72
102
  * Parse the next token starting at the given position
@@ -153,7 +183,7 @@ class LexemeCursor {
153
183
  return Lexeme_1.TokenType.Command;
154
184
  }
155
185
  // Check if it's followed by parentheses (function)
156
- const nextNonWhitespacePos = this.skipWhitespace(sql, position);
186
+ const nextNonWhitespacePos = this.skipWhitespaceAndComments(sql, position);
157
187
  if (nextNonWhitespacePos < sql.length && sql[nextNonWhitespacePos] === '(') {
158
188
  return Lexeme_1.TokenType.Function;
159
189
  }