11import type { CursorPosition as BaseCursorPosition } from '@gravity-ui/websql-autocomplete/shared' ;
2- import type { YQLEntity , YqlAutocompleteResult } from '@gravity-ui/websql-autocomplete/yql' ;
2+ import type { YQLEntity } from '@gravity-ui/websql-autocomplete/yql' ;
33import type Monaco from 'monaco-editor' ;
44
55import {
@@ -27,8 +27,6 @@ import type {
2727} from './types' ;
2828import { getEntitiesToFetchColumns } from './utils' ;
2929
30- const prefixRegexp = / ( [ ^ \s ] + ) $ / ;
31-
3230function getCursorPosition ( input : string , offset : number ) : CursorPosition {
3331 const lines = input . slice ( 0 , offset ) . split ( '\n' ) ;
3432 // parser suggest to get cursor position where lineNumber and column starts from 1
@@ -38,19 +36,23 @@ function getCursorPosition(input: string, offset: number): CursorPosition {
3836 } ;
3937}
4038
41- function getCursorPrefix ( input : string , offset : number ) {
39+ const prefixRegexp = / ( [ ^ \s ] + ) $ / ;
40+
41+ function getCursorPrefix ( input : string , offset : number , re = prefixRegexp ) {
4242 const prevText = input . slice ( 0 , offset ) ;
4343
44- const match = prevText . match ( prefixRegexp ) ;
44+ const match = prevText . match ( re ) ;
4545 if ( match && match [ 1 ] ) {
4646 return match [ 1 ] ;
4747 }
4848 return '' ;
4949}
5050
51+ const prefixToReplaceRegexp = / ( [ ^ \\ / \s ` ] + ) $ / ;
52+
5153function getRangeToInsertSuggestion ( input : string , offset : number ) {
5254 const cursorPosition = getCursorPosition ( input , offset ) ;
53- const cursorPrefix = getCursorPrefix ( input , offset ) ;
55+ const cursorPrefix = getCursorPrefix ( input , offset , prefixToReplaceRegexp ) ;
5456 return {
5557 startColumn : cursorPosition . column - cursorPrefix . length ,
5658 startLineNumber : cursorPosition . lineNumber ,
@@ -59,6 +61,12 @@ function getRangeToInsertSuggestion(input: string, offset: number) {
5961 } ;
6062}
6163
64+ /**
65+ * YQLAutocomplete class provides autocompletion suggestions for YQL queries.
66+ * It uses a set of constants to generate suggestions for various YQL elements.
67+ * The class is abstract and needs to be extended to provide implementation for
68+ * fetching entities and columns.
69+ */
6270export abstract class YQLAutocomplete {
6371 private readonly constants : AutocompleteConstants = { } ;
6472
@@ -82,21 +90,8 @@ export abstract class YQLAutocomplete {
8290 } ) ;
8391 }
8492
85- removeBackticks ( value : string ) {
86- let sliceStart = 0 ;
87- let sliceEnd = value . length ;
88- if ( value . startsWith ( '`' ) ) {
89- sliceStart = 1 ;
90- }
91- if ( value . endsWith ( '`' ) ) {
92- sliceEnd = - 1 ;
93- }
94- return value . slice ( sliceStart , sliceEnd ) ;
95- }
96-
9793 async getSuggestions ( input : string , offset : number ) {
9894 const parseResult = await this . parseInput ( input , offset ) ;
99-
10095 let entitiesSuggestions : Monaco . languages . CompletionItem [ ] = [ ] ;
10196 let functionsSuggestions : Monaco . languages . CompletionItem [ ] = [ ] ;
10297 let aggregateFunctionsSuggestions : Monaco . languages . CompletionItem [ ] = [ ] ;
@@ -111,23 +106,24 @@ export abstract class YQLAutocomplete {
111106
112107 const rangeToInsertSuggestion = getRangeToInsertSuggestion ( input , offset ) ;
113108
109+ const cursorPrefix = getCursorPrefix ( input , offset ) ;
110+
114111 if ( parseResult . suggestSimpleTypes ) {
112+ const simpleTypes = await this . getSimpleTypes ( cursorPrefix ) ;
115113 simpleTypesSuggestions = await generateSimpleTypesSuggestion (
116114 rangeToInsertSuggestion ,
117- this . constants . types ,
115+ simpleTypes ,
118116 ) ;
119117 }
120118 if ( parseResult . suggestEntity ) {
121- const entityNamePrefix = getCursorPrefix ( input , offset ) ;
122-
123119 const fetchedEntities = await this . fetchEntities (
124- entityNamePrefix ,
120+ cursorPrefix ,
125121 parseResult . suggestEntity ,
126122 ) ;
127123 entitiesSuggestions = await generateEntitiesSuggestion (
128124 rangeToInsertSuggestion ,
129125 fetchedEntities ,
130- entityNamePrefix ,
126+ cursorPrefix ,
131127 ) ;
132128 }
133129 if ( parseResult . suggestVariables ) {
@@ -138,41 +134,41 @@ export abstract class YQLAutocomplete {
138134 }
139135
140136 if ( parseResult . suggestFunctions ) {
137+ const simpleFunctions = await this . getSimpleFunctions ( cursorPrefix ) ;
141138 functionsSuggestions = await generateSimpleFunctionsSuggestion (
142139 rangeToInsertSuggestion ,
143- this . constants . simpleFunctions ,
140+ simpleFunctions ,
144141 ) ;
145142 }
146143 if ( parseResult . suggestAggregateFunctions ) {
144+ const aggregateFunctions = await this . getAggregateFunctions ( cursorPrefix ) ;
147145 aggregateFunctionsSuggestions = await generateAggregateFunctionsSuggestion (
148146 rangeToInsertSuggestion ,
149- this . constants . aggregateFunctions ,
147+ aggregateFunctions ,
150148 ) ;
151149 }
152150 if ( parseResult . suggestWindowFunctions ) {
151+ const windowFunctions = await this . getWindowFunctions ( cursorPrefix ) ;
153152 windowFunctionsSuggestions = await generateWindowFunctionsSuggestion (
154153 rangeToInsertSuggestion ,
155- this . constants . windowFunctions ,
154+ windowFunctions ,
156155 ) ;
157156 }
158157 if ( parseResult . suggestTableFunctions ) {
158+ const tableFunctions = await this . getTableFunctions ( cursorPrefix ) ;
159159 tableFunctionsSuggestions = await generateTableFunctionsSuggestion (
160160 rangeToInsertSuggestion ,
161- this . constants . tableFunctions ,
161+ tableFunctions ,
162162 ) ;
163163 }
164164
165165 if ( parseResult . suggestUdfs ) {
166- udfsSuggestions = await generateUdfSuggestion (
167- rangeToInsertSuggestion ,
168- this . constants . udfs ,
169- ) ;
166+ const udfs = await this . getUdfs ( cursorPrefix ) ;
167+ udfsSuggestions = await generateUdfSuggestion ( rangeToInsertSuggestion , udfs ) ;
170168 }
171169 if ( parseResult . suggestPragmas ) {
172- pragmasSuggestions = await generatePragmasSuggestion (
173- rangeToInsertSuggestion ,
174- this . constants . pragmas ,
175- ) ;
170+ const pragmas = await this . getPragmas ( cursorPrefix ) ;
171+ pragmasSuggestions = await generatePragmasSuggestion ( rangeToInsertSuggestion , pragmas ) ;
176172 }
177173 if ( parseResult . suggestEntitySettings ) {
178174 const entitySettings = await this . getEntitySettings ( parseResult . suggestEntitySettings ) ;
@@ -193,19 +189,12 @@ export abstract class YQLAutocomplete {
193189 ) ;
194190
195191 if ( parseResult . suggestColumns ) {
196- const normalizedSuggestions : YqlAutocompleteResult [ 'suggestColumns' ] = {
197- ...parseResult . suggestColumns ,
198- tables : parseResult . suggestColumns . tables ?. map ( ( table ) => ( {
199- ...table ,
200- name : this . normalizeTableName ( table . name ) ,
201- } ) ) ,
202- } ;
203- const entities = getEntitiesToFetchColumns ( normalizedSuggestions ) ;
192+ const entities = getEntitiesToFetchColumns ( parseResult . suggestColumns ) ;
204193 const fetchedColumns = await this . fetchEntityColumns ( entities ) ;
205194
206195 columnsSuggestions = await generateColumnsSuggestion (
207196 rangeToInsertSuggestion ,
208- normalizedSuggestions ,
197+ parseResult . suggestColumns ,
209198 parseResult . suggestVariables ,
210199 fetchedColumns ,
211200 ) ;
@@ -233,24 +222,65 @@ export abstract class YQLAutocomplete {
233222 async parseInput ( input : string , offset : number ) {
234223 const cursorPosition = getCursorPosition ( input , offset ) ;
235224
236- const { parseYqlQuery } = await import ( '@gravity-ui/websql-autocomplete/yql' ) ;
225+ const parseQuery = await this . getQueryParser ( ) ;
237226 const cursorForParsing : BaseCursorPosition = {
238227 line : cursorPosition . lineNumber ,
239228 column : cursorPosition . column ,
240229 } ;
241- return parseYqlQuery ( input , cursorForParsing ) ;
230+ return parseQuery ( input , cursorForParsing ) ;
242231 }
243232
244- abstract getEntitySettings ( entityType : YQLEntity ) : string [ ] | Promise < string [ ] > ;
233+ async getQueryParser ( ) {
234+ const { parseYqlQuery : parseQuery } = await import ( '@gravity-ui/websql-autocomplete/yql' ) ;
235+ return parseQuery ;
236+ }
237+
238+ async getSimpleTypes ( _prefix ?: string ) {
239+ return this . constants . types ;
240+ }
241+
242+ async getUdfs ( _prefix ?: string ) {
243+ return this . constants . udfs ;
244+ }
245+
246+ async getPragmas ( _prefix ?: string ) {
247+ return this . constants . pragmas ;
248+ }
249+ async getWindowFunctions ( _prefix ?: string ) {
250+ return this . constants . windowFunctions ;
251+ }
245252
253+ async getTableFunctions ( _prefix ?: string ) {
254+ return this . constants . tableFunctions ;
255+ }
256+ async getAggregateFunctions ( _prefix ?: string ) {
257+ return this . constants . aggregateFunctions ;
258+ }
259+
260+ async getSimpleFunctions ( _prefix ?: string ) {
261+ return this . constants . simpleFunctions ;
262+ }
263+
264+ /**
265+ * Fetches entity settings based on provided entity type.
266+ * @param entityType
267+ * @returns A promise that resolves to an array of entity settings.
268+ */
269+ abstract getEntitySettings ( entityType : YQLEntity ) : Promise < string [ ] > ;
270+ /**
271+ * Fetches entities based on the provided prefix and needed entity types.
272+ * @param prefix - The prefix to filter entities.
273+ * @param neededEntityTypes - An array of entity types to fetch.
274+ * @returns A promise that resolves to an array of fetched entities.
275+ */
246276 abstract fetchEntities (
247277 prefix : string ,
248278 neededEntityTypes : YQLEntity [ ] ,
249279 ) : Promise < FetchedEntity [ ] > ;
250-
280+ /**
281+ * Fetches columns for the specified entities.
282+ * @param entityNames - An array of entity names to fetch columns for.
283+ * @returns A promise that resolves to an array of fetched columns.
284+ */
251285 abstract fetchEntityColumns ( entityNames : string [ ] ) : Promise < FetchedColumn [ ] > ;
252-
253- normalizeTableName ( value : string ) {
254- return this . removeBackticks ( value ) ;
255- }
256286}
0 commit comments