1
1
import 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' ;
3
3
import type Monaco from 'monaco-editor' ;
4
4
5
5
import {
@@ -27,8 +27,6 @@ import type {
27
27
} from './types' ;
28
28
import { getEntitiesToFetchColumns } from './utils' ;
29
29
30
- const prefixRegexp = / ( [ ^ \s ] + ) $ / ;
31
-
32
30
function getCursorPosition ( input : string , offset : number ) : CursorPosition {
33
31
const lines = input . slice ( 0 , offset ) . split ( '\n' ) ;
34
32
// parser suggest to get cursor position where lineNumber and column starts from 1
@@ -38,19 +36,23 @@ function getCursorPosition(input: string, offset: number): CursorPosition {
38
36
} ;
39
37
}
40
38
41
- function getCursorPrefix ( input : string , offset : number ) {
39
+ const prefixRegexp = / ( [ ^ \s ] + ) $ / ;
40
+
41
+ function getCursorPrefix ( input : string , offset : number , re = prefixRegexp ) {
42
42
const prevText = input . slice ( 0 , offset ) ;
43
43
44
- const match = prevText . match ( prefixRegexp ) ;
44
+ const match = prevText . match ( re ) ;
45
45
if ( match && match [ 1 ] ) {
46
46
return match [ 1 ] ;
47
47
}
48
48
return '' ;
49
49
}
50
50
51
+ const prefixToReplaceRegexp = / ( [ ^ \\ / \s ` ] + ) $ / ;
52
+
51
53
function getRangeToInsertSuggestion ( input : string , offset : number ) {
52
54
const cursorPosition = getCursorPosition ( input , offset ) ;
53
- const cursorPrefix = getCursorPrefix ( input , offset ) ;
55
+ const cursorPrefix = getCursorPrefix ( input , offset , prefixToReplaceRegexp ) ;
54
56
return {
55
57
startColumn : cursorPosition . column - cursorPrefix . length ,
56
58
startLineNumber : cursorPosition . lineNumber ,
@@ -59,6 +61,12 @@ function getRangeToInsertSuggestion(input: string, offset: number) {
59
61
} ;
60
62
}
61
63
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
+ */
62
70
export abstract class YQLAutocomplete {
63
71
private readonly constants : AutocompleteConstants = { } ;
64
72
@@ -82,21 +90,8 @@ export abstract class YQLAutocomplete {
82
90
} ) ;
83
91
}
84
92
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
-
97
93
async getSuggestions ( input : string , offset : number ) {
98
94
const parseResult = await this . parseInput ( input , offset ) ;
99
-
100
95
let entitiesSuggestions : Monaco . languages . CompletionItem [ ] = [ ] ;
101
96
let functionsSuggestions : Monaco . languages . CompletionItem [ ] = [ ] ;
102
97
let aggregateFunctionsSuggestions : Monaco . languages . CompletionItem [ ] = [ ] ;
@@ -111,23 +106,24 @@ export abstract class YQLAutocomplete {
111
106
112
107
const rangeToInsertSuggestion = getRangeToInsertSuggestion ( input , offset ) ;
113
108
109
+ const cursorPrefix = getCursorPrefix ( input , offset ) ;
110
+
114
111
if ( parseResult . suggestSimpleTypes ) {
112
+ const simpleTypes = await this . getSimpleTypes ( cursorPrefix ) ;
115
113
simpleTypesSuggestions = await generateSimpleTypesSuggestion (
116
114
rangeToInsertSuggestion ,
117
- this . constants . types ,
115
+ simpleTypes ,
118
116
) ;
119
117
}
120
118
if ( parseResult . suggestEntity ) {
121
- const entityNamePrefix = getCursorPrefix ( input , offset ) ;
122
-
123
119
const fetchedEntities = await this . fetchEntities (
124
- entityNamePrefix ,
120
+ cursorPrefix ,
125
121
parseResult . suggestEntity ,
126
122
) ;
127
123
entitiesSuggestions = await generateEntitiesSuggestion (
128
124
rangeToInsertSuggestion ,
129
125
fetchedEntities ,
130
- entityNamePrefix ,
126
+ cursorPrefix ,
131
127
) ;
132
128
}
133
129
if ( parseResult . suggestVariables ) {
@@ -138,41 +134,41 @@ export abstract class YQLAutocomplete {
138
134
}
139
135
140
136
if ( parseResult . suggestFunctions ) {
137
+ const simpleFunctions = await this . getSimpleFunctions ( cursorPrefix ) ;
141
138
functionsSuggestions = await generateSimpleFunctionsSuggestion (
142
139
rangeToInsertSuggestion ,
143
- this . constants . simpleFunctions ,
140
+ simpleFunctions ,
144
141
) ;
145
142
}
146
143
if ( parseResult . suggestAggregateFunctions ) {
144
+ const aggregateFunctions = await this . getAggregateFunctions ( cursorPrefix ) ;
147
145
aggregateFunctionsSuggestions = await generateAggregateFunctionsSuggestion (
148
146
rangeToInsertSuggestion ,
149
- this . constants . aggregateFunctions ,
147
+ aggregateFunctions ,
150
148
) ;
151
149
}
152
150
if ( parseResult . suggestWindowFunctions ) {
151
+ const windowFunctions = await this . getWindowFunctions ( cursorPrefix ) ;
153
152
windowFunctionsSuggestions = await generateWindowFunctionsSuggestion (
154
153
rangeToInsertSuggestion ,
155
- this . constants . windowFunctions ,
154
+ windowFunctions ,
156
155
) ;
157
156
}
158
157
if ( parseResult . suggestTableFunctions ) {
158
+ const tableFunctions = await this . getTableFunctions ( cursorPrefix ) ;
159
159
tableFunctionsSuggestions = await generateTableFunctionsSuggestion (
160
160
rangeToInsertSuggestion ,
161
- this . constants . tableFunctions ,
161
+ tableFunctions ,
162
162
) ;
163
163
}
164
164
165
165
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 ) ;
170
168
}
171
169
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 ) ;
176
172
}
177
173
if ( parseResult . suggestEntitySettings ) {
178
174
const entitySettings = await this . getEntitySettings ( parseResult . suggestEntitySettings ) ;
@@ -193,19 +189,12 @@ export abstract class YQLAutocomplete {
193
189
) ;
194
190
195
191
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 ) ;
204
193
const fetchedColumns = await this . fetchEntityColumns ( entities ) ;
205
194
206
195
columnsSuggestions = await generateColumnsSuggestion (
207
196
rangeToInsertSuggestion ,
208
- normalizedSuggestions ,
197
+ parseResult . suggestColumns ,
209
198
parseResult . suggestVariables ,
210
199
fetchedColumns ,
211
200
) ;
@@ -233,24 +222,65 @@ export abstract class YQLAutocomplete {
233
222
async parseInput ( input : string , offset : number ) {
234
223
const cursorPosition = getCursorPosition ( input , offset ) ;
235
224
236
- const { parseYqlQuery } = await import ( '@gravity-ui/websql-autocomplete/yql' ) ;
225
+ const parseQuery = await this . getQueryParser ( ) ;
237
226
const cursorForParsing : BaseCursorPosition = {
238
227
line : cursorPosition . lineNumber ,
239
228
column : cursorPosition . column ,
240
229
} ;
241
- return parseYqlQuery ( input , cursorForParsing ) ;
230
+ return parseQuery ( input , cursorForParsing ) ;
242
231
}
243
232
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
+ }
245
252
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
+ */
246
276
abstract fetchEntities (
247
277
prefix : string ,
248
278
neededEntityTypes : YQLEntity [ ] ,
249
279
) : 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
+ */
251
285
abstract fetchEntityColumns ( entityNames : string [ ] ) : Promise < FetchedColumn [ ] > ;
252
-
253
- normalizeTableName ( value : string ) {
254
- return this . removeBackticks ( value ) ;
255
- }
256
286
}
0 commit comments