@@ -203,6 +203,13 @@ export abstract class BasicSQL<
203
203
return this . _parseErrors ;
204
204
}
205
205
206
+ /**
207
+ * Get the input string that has been parsed.
208
+ */
209
+ public getParsedInput ( ) : string {
210
+ return this . _parsedInput ;
211
+ }
212
+
206
213
/**
207
214
* Get all Tokens of input string,'<EOF>' is not included.
208
215
* @param input source string
@@ -252,35 +259,35 @@ export abstract class BasicSQL<
252
259
}
253
260
254
261
/**
255
- * Get suggestions of syntax and token at caretPosition
256
- * @param input source string
257
- * @param caretPosition caret position, such as cursor position
258
- * @returns suggestion
262
+ * Get a minimum boundary parser near tokenIndex.
263
+ * @param input source string.
264
+ * @param tokenIndex start from which index to minimize the boundary.
265
+ * @param originParseTree the parse tree need to be minimized, default value is the result of parsing `input`.
266
+ * @returns minimum parser info
259
267
*/
260
- public getSuggestionAtCaretPosition (
268
+ public getMinimumParserInfo (
261
269
input : string ,
262
- caretPosition : CaretPosition
263
- ) : Suggestions | null {
264
- const splitListener = this . splitListener ;
265
-
266
- this . parseWithCache ( input ) ;
267
- if ( ! this . _parseTree ) return null ;
268
-
269
- let sqlParserIns = this . _parser ;
270
- const allTokens = this . getAllTokens ( input ) ;
271
- let caretTokenIndex = findCaretTokenIndex ( caretPosition , allTokens ) ;
272
- let c3Context : ParserRuleContext = this . _parseTree ;
273
- let tokenIndexOffset : number = 0 ;
270
+ tokenIndex : number ,
271
+ originParseTree ?: ParserRuleContext | null
272
+ ) {
273
+ if ( arguments . length <= 2 ) {
274
+ this . parseWithCache ( input ) ;
275
+ originParseTree = this . _parseTree ;
276
+ }
274
277
275
- if ( ! caretTokenIndex && caretTokenIndex !== 0 ) return null ;
278
+ if ( ! originParseTree || ! input ?. length ) return null ;
276
279
280
+ const splitListener = this . splitListener ;
277
281
/**
278
282
* Split sql by statement.
279
283
* Try to collect candidates in as small a range as possible.
280
284
*/
281
- this . listen ( splitListener , this . _parseTree ) ;
285
+ this . listen ( splitListener , originParseTree ) ;
282
286
const statementCount = splitListener . statementsContext ?. length ;
283
287
const statementsContext = splitListener . statementsContext ;
288
+ let tokenIndexOffset = 0 ;
289
+ let sqlParserIns = this . _parser ;
290
+ let parseTree = originParseTree ;
284
291
285
292
// If there are multiple statements.
286
293
if ( statementCount > 1 ) {
@@ -305,14 +312,14 @@ export abstract class BasicSQL<
305
312
const isNextCtxValid =
306
313
index === statementCount - 1 || ! statementsContext [ index + 1 ] ?. exception ;
307
314
308
- if ( ctx . stop && ctx . stop . tokenIndex < caretTokenIndex && isPrevCtxValid ) {
315
+ if ( ctx . stop && ctx . stop . tokenIndex < tokenIndex && isPrevCtxValid ) {
309
316
startStatement = ctx ;
310
317
}
311
318
312
319
if (
313
320
ctx . start &&
314
321
! stopStatement &&
315
- ctx . start . tokenIndex > caretTokenIndex &&
322
+ ctx . start . tokenIndex > tokenIndex &&
316
323
isNextCtxValid
317
324
) {
318
325
stopStatement = ctx ;
@@ -329,7 +336,7 @@ export abstract class BasicSQL<
329
336
* compared to the tokenIndex in the whole input
330
337
*/
331
338
tokenIndexOffset = startStatement ?. start ?. tokenIndex ?? 0 ;
332
- caretTokenIndex = caretTokenIndex - tokenIndexOffset ;
339
+ tokenIndex = tokenIndex - tokenIndexOffset ;
333
340
334
341
/**
335
342
* Reparse the input fragment,
@@ -349,17 +356,54 @@ export abstract class BasicSQL<
349
356
parser . errorHandler = new ErrorStrategy ( ) ;
350
357
351
358
sqlParserIns = parser ;
352
- c3Context = parser . program ( ) ;
359
+ parseTree = parser . program ( ) ;
353
360
}
354
361
362
+ return {
363
+ parser : sqlParserIns ,
364
+ parseTree,
365
+ tokenIndexOffset,
366
+ newTokenIndex : tokenIndex ,
367
+ } ;
368
+ }
369
+
370
+ /**
371
+ * Get suggestions of syntax and token at caretPosition
372
+ * @param input source string
373
+ * @param caretPosition caret position, such as cursor position
374
+ * @returns suggestion
375
+ */
376
+ public getSuggestionAtCaretPosition (
377
+ input : string ,
378
+ caretPosition : CaretPosition
379
+ ) : Suggestions | null {
380
+ this . parseWithCache ( input ) ;
381
+
382
+ if ( ! this . _parseTree ) return null ;
383
+
384
+ const allTokens = this . getAllTokens ( input ) ;
385
+ let caretTokenIndex = findCaretTokenIndex ( caretPosition , allTokens ) ;
386
+
387
+ if ( ! caretTokenIndex && caretTokenIndex !== 0 ) return null ;
388
+
389
+ const minimumParser = this . getMinimumParserInfo ( input , caretTokenIndex ) ;
390
+
391
+ if ( ! minimumParser ) return null ;
392
+
393
+ const {
394
+ parser : sqlParserIns ,
395
+ tokenIndexOffset,
396
+ newTokenIndex,
397
+ parseTree : c3Context ,
398
+ } = minimumParser ;
355
399
const core = new CodeCompletionCore ( sqlParserIns ) ;
356
400
core . preferredRules = this . preferredRules ;
357
401
358
- const candidates = core . collectCandidates ( caretTokenIndex , c3Context ) ;
402
+ const candidates = core . collectCandidates ( newTokenIndex , c3Context ) ;
359
403
const originalSuggestions = this . processCandidates (
360
404
candidates ,
361
405
allTokens ,
362
- caretTokenIndex ,
406
+ newTokenIndex ,
363
407
tokenIndexOffset
364
408
) ;
365
409
0 commit comments