|
| 1 | +/** |
| 2 | + * Utility function for processing SQL tokens and generating keyword suggestions |
| 3 | + */ |
| 4 | + |
| 5 | +import { Parser } from 'antlr4ng'; |
| 6 | +import { CandidatesCollection } from 'antlr4-c3'; |
| 7 | + |
| 8 | +/** |
| 9 | + * Process token candidates and generate a list of keyword suggestions |
| 10 | + * @param parser SQL parser instance |
| 11 | + * @param tokens token candidates |
| 12 | + * @returns list of keyword suggestions |
| 13 | + */ |
| 14 | +export function processTokenCandidates( |
| 15 | + parser: Parser, |
| 16 | + tokens: CandidatesCollection['tokens'] |
| 17 | +): string[] { |
| 18 | + const keywords: string[] = []; |
| 19 | + |
| 20 | + const cleanDisplayName = (displayName: string | null): string => { |
| 21 | + return displayName && displayName.startsWith("'") && displayName.endsWith("'") |
| 22 | + ? displayName.slice(1, -1) |
| 23 | + : displayName || ''; |
| 24 | + }; |
| 25 | + |
| 26 | + const isKeywordToken = (token: number): boolean => { |
| 27 | + const symbolicName = parser.vocabulary.getSymbolicName(token); |
| 28 | + return Boolean(symbolicName?.startsWith('KW_')); |
| 29 | + }; |
| 30 | + |
| 31 | + for (const [token, followSets] of tokens) { |
| 32 | + const displayName = parser.vocabulary.getDisplayName(token); |
| 33 | + |
| 34 | + if (!displayName || !isKeywordToken(token)) continue; |
| 35 | + |
| 36 | + const keyword = cleanDisplayName(displayName); |
| 37 | + keywords.push(keyword); |
| 38 | + |
| 39 | + if (followSets.length && followSets.every((s) => isKeywordToken(s))) { |
| 40 | + const followKeywords = followSets |
| 41 | + .map((s) => cleanDisplayName(parser.vocabulary.getDisplayName(s))) |
| 42 | + .filter(Boolean); |
| 43 | + |
| 44 | + if (followKeywords.length) { |
| 45 | + const combinedKeyword = [keyword, ...followKeywords].join(' '); |
| 46 | + keywords.push(combinedKeyword); |
| 47 | + } |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + return keywords; |
| 52 | +} |
0 commit comments