@@ -203,6 +203,13 @@ export abstract class BasicSQL<
203203 return this . _parseErrors ;
204204 }
205205
206+ /**
207+ * Get the input string that has been parsed.
208+ */
209+ public getParsedInput ( ) : string {
210+ return this . _parsedInput ;
211+ }
212+
206213 /**
207214 * Get all Tokens of input string,'<EOF>' is not included.
208215 * @param input source string
@@ -252,35 +259,35 @@ export abstract class BasicSQL<
252259 }
253260
254261 /**
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
259267 */
260- public getSuggestionAtCaretPosition (
268+ public getMinimumParserInfo (
261269 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+ }
274277
275- if ( ! caretTokenIndex && caretTokenIndex !== 0 ) return null ;
278+ if ( ! originParseTree || ! input ?. length ) return null ;
276279
280+ const splitListener = this . splitListener ;
277281 /**
278282 * Split sql by statement.
279283 * Try to collect candidates in as small a range as possible.
280284 */
281- this . listen ( splitListener , this . _parseTree ) ;
285+ this . listen ( splitListener , originParseTree ) ;
282286 const statementCount = splitListener . statementsContext ?. length ;
283287 const statementsContext = splitListener . statementsContext ;
288+ let tokenIndexOffset = 0 ;
289+ let sqlParserIns = this . _parser ;
290+ let parseTree = originParseTree ;
284291
285292 // If there are multiple statements.
286293 if ( statementCount > 1 ) {
@@ -305,14 +312,14 @@ export abstract class BasicSQL<
305312 const isNextCtxValid =
306313 index === statementCount - 1 || ! statementsContext [ index + 1 ] ?. exception ;
307314
308- if ( ctx . stop && ctx . stop . tokenIndex < caretTokenIndex && isPrevCtxValid ) {
315+ if ( ctx . stop && ctx . stop . tokenIndex < tokenIndex && isPrevCtxValid ) {
309316 startStatement = ctx ;
310317 }
311318
312319 if (
313320 ctx . start &&
314321 ! stopStatement &&
315- ctx . start . tokenIndex > caretTokenIndex &&
322+ ctx . start . tokenIndex > tokenIndex &&
316323 isNextCtxValid
317324 ) {
318325 stopStatement = ctx ;
@@ -329,7 +336,7 @@ export abstract class BasicSQL<
329336 * compared to the tokenIndex in the whole input
330337 */
331338 tokenIndexOffset = startStatement ?. start ?. tokenIndex ?? 0 ;
332- caretTokenIndex = caretTokenIndex - tokenIndexOffset ;
339+ tokenIndex = tokenIndex - tokenIndexOffset ;
333340
334341 /**
335342 * Reparse the input fragment,
@@ -349,17 +356,54 @@ export abstract class BasicSQL<
349356 parser . errorHandler = new ErrorStrategy ( ) ;
350357
351358 sqlParserIns = parser ;
352- c3Context = parser . program ( ) ;
359+ parseTree = parser . program ( ) ;
353360 }
354361
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 ;
355399 const core = new CodeCompletionCore ( sqlParserIns ) ;
356400 core . preferredRules = this . preferredRules ;
357401
358- const candidates = core . collectCandidates ( caretTokenIndex , c3Context ) ;
402+ const candidates = core . collectCandidates ( newTokenIndex , c3Context ) ;
359403 const originalSuggestions = this . processCandidates (
360404 candidates ,
361405 allTokens ,
362- caretTokenIndex ,
406+ newTokenIndex ,
363407 tokenIndexOffset
364408 ) ;
365409
0 commit comments