Skip to content

Commit 4b9aa93

Browse files
authored
feat: add reference and definition provider (#145)
* feat: add get references and definitions ability for entity * ci(format): format code * feat(optimize reference and definition feat): optimize reference and definition feat * ci(format): format prettier * feat(add comment for DefinitionAdapter and ReferenceAdapter): add comment --------- Co-authored-by: zhaoge <>
1 parent 9ed40bf commit 4b9aa93

11 files changed

+234
-36
lines changed

Diff for: src/languageFeatures.ts

+153-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
import type { ParseError } from 'dt-sql-parser';
2+
import { EntityContext } from 'dt-sql-parser/dist/parser/common/entityCollector';
3+
import { WordPosition } from 'dt-sql-parser/dist/parser/common/textAndWord';
4+
import * as monaco from 'monaco-editor';
5+
6+
import { BaseSQLWorker } from './baseSQLWorker';
7+
import { debounce } from './common/utils';
18
import {
9+
CancellationToken,
210
editor,
3-
Uri,
411
IDisposable,
5-
MarkerSeverity,
6-
Range,
712
languages,
13+
MarkerSeverity,
814
Position,
9-
CancellationToken
15+
Range,
16+
Uri
1017
} from './fillers/monaco-editor-core';
11-
import { debounce } from './common/utils';
12-
import { BaseSQLWorker } from './baseSQLWorker';
13-
import type { ParseError } from 'dt-sql-parser';
1418
import type { LanguageServiceDefaults } from './monaco.contribution';
1519

1620
export interface WorkerAccessor<T extends BaseSQLWorker> {
@@ -197,3 +201,145 @@ export class CompletionAdapter<T extends BaseSQLWorker>
197201
});
198202
}
199203
}
204+
/**
205+
* The adapter is for the definition of the symbol at the given position and document.
206+
**/
207+
export class DefinitionAdapter<T extends BaseSQLWorker> implements languages.DefinitionProvider {
208+
constructor(
209+
private readonly _worker: WorkerAccessor<T>,
210+
private readonly _defaults: LanguageServiceDefaults
211+
) {}
212+
/**
213+
* Provide the definition of the symbol at the given position and document.
214+
**/
215+
provideDefinition(
216+
model: editor.IReadOnlyModel,
217+
position: Position,
218+
_token: CancellationToken
219+
): languages.ProviderResult<languages.Definition | languages.LocationLink[]> {
220+
const resource = model.uri;
221+
const lineContent = model.getLineContent(position.lineNumber);
222+
if (lineContent.startsWith('--')) return null;
223+
return this._worker(resource)
224+
.then((worker) => {
225+
let code = model?.getValue() || '';
226+
if (typeof this._defaults.preprocessCode === 'function') {
227+
code = this._defaults.preprocessCode(code);
228+
}
229+
return worker.getAllEntities(code);
230+
})
231+
.then((entities) => {
232+
const word = model.getWordAtPosition(position);
233+
let pos: WordPosition = {
234+
line: -1,
235+
startIndex: -1,
236+
endIndex: -1,
237+
startColumn: -1,
238+
endColumn: -1
239+
};
240+
const curEntity = entities?.find((entity: EntityContext) => {
241+
const entityPosition = entity.position;
242+
if (
243+
entityPosition.startColumn === word?.startColumn &&
244+
entityPosition.endColumn === word?.endColumn &&
245+
entityPosition.line === position.lineNumber
246+
) {
247+
return entity;
248+
}
249+
return null;
250+
});
251+
if (curEntity) {
252+
for (let k in entities) {
253+
const entity = entities[Number(k)];
254+
if (
255+
entity.entityContextType.includes('Create') &&
256+
word?.word &&
257+
entity.text === word?.word &&
258+
entity.entityContextType.includes(curEntity.entityContextType)
259+
) {
260+
pos = entity.position;
261+
break;
262+
}
263+
}
264+
}
265+
if (pos && pos.line !== -1) {
266+
return {
267+
uri: model.uri,
268+
range: new monaco.Range(
269+
pos?.line,
270+
pos?.startColumn,
271+
pos?.line,
272+
pos?.endColumn
273+
)
274+
};
275+
}
276+
});
277+
}
278+
}
279+
/**
280+
* The adapter is for the references of the symbol at the given position and document.
281+
**/
282+
export class ReferenceAdapter<T extends BaseSQLWorker> implements languages.ReferenceProvider {
283+
constructor(
284+
private readonly _worker: WorkerAccessor<T>,
285+
private readonly _defaults: LanguageServiceDefaults
286+
) {}
287+
/**
288+
* Provide a set of project-wide references for the given position and document.
289+
**/
290+
provideReferences(
291+
model: editor.IReadOnlyModel,
292+
position: Position,
293+
_context: languages.ReferenceContext,
294+
_token: CancellationToken
295+
): languages.ProviderResult<languages.Location[]> {
296+
const resource = model.uri;
297+
const lineContent = model.getLineContent(position.lineNumber);
298+
if (!lineContent.startsWith('CREATE')) return;
299+
return this._worker(resource)
300+
.then((worker) => {
301+
let code = model?.getValue() || '';
302+
if (typeof this._defaults.preprocessCode === 'function') {
303+
code = this._defaults.preprocessCode(code);
304+
}
305+
return worker.getAllEntities(model?.getValue());
306+
})
307+
.then((entities) => {
308+
const word = model.getWordAtPosition(position);
309+
const arr: languages.Location[] = [];
310+
const curEntity = entities?.find((entity: EntityContext) => {
311+
const entityPosition = entity.position;
312+
if (
313+
entityPosition.startColumn === word?.startColumn &&
314+
entityPosition.endColumn === word?.endColumn &&
315+
entityPosition.line === position.lineNumber
316+
) {
317+
return entity;
318+
}
319+
return null;
320+
});
321+
if (curEntity) {
322+
entities?.forEach((entity) => {
323+
if (
324+
word?.word &&
325+
entity.text === word?.word &&
326+
curEntity.entityContextType.includes(entity.entityContextType)
327+
) {
328+
let pos: WordPosition | null = null;
329+
pos = entity.position;
330+
arr.push({
331+
uri: model.uri,
332+
range: new monaco.Range(
333+
pos?.line,
334+
pos?.startColumn,
335+
pos?.line,
336+
pos?.endColumn
337+
)
338+
});
339+
}
340+
});
341+
}
342+
return arr;
343+
});
344+
}
345+
}

Diff for: src/languages/flink/flink.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { registerLanguage } from '../../_.contribution';
7-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
87
import { LanguageIdEnum } from '../../common/constants';
8+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
99

1010
registerLanguage({
1111
id: LanguageIdEnum.FLINK,
@@ -16,5 +16,7 @@ registerLanguage({
1616

1717
setupLanguageFeatures(LanguageIdEnum.FLINK, {
1818
completionItems: true,
19-
diagnostics: true
19+
diagnostics: true,
20+
references: true,
21+
definitions: true
2022
});

Diff for: src/languages/hive/hive.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { registerLanguage } from '../../_.contribution';
7-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
87
import { LanguageIdEnum } from '../../common/constants';
8+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
99

1010
registerLanguage({
1111
id: LanguageIdEnum.HIVE,
@@ -16,5 +16,7 @@ registerLanguage({
1616

1717
setupLanguageFeatures(LanguageIdEnum.HIVE, {
1818
completionItems: true,
19-
diagnostics: true
19+
diagnostics: true,
20+
references: true,
21+
definitions: true
2022
});

Diff for: src/languages/impala/impala.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { registerLanguage } from '../../_.contribution';
7-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
87
import { LanguageIdEnum } from '../../common/constants';
8+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
99

1010
registerLanguage({
1111
id: LanguageIdEnum.IMPALA,
@@ -16,5 +16,7 @@ registerLanguage({
1616

1717
setupLanguageFeatures(LanguageIdEnum.IMPALA, {
1818
completionItems: true,
19-
diagnostics: true
19+
diagnostics: true,
20+
references: true,
21+
definitions: true
2022
});

Diff for: src/languages/mysql/mysql.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { registerLanguage } from '../../_.contribution';
7-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
87
import { LanguageIdEnum } from '../../common/constants';
8+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
99

1010
registerLanguage({
1111
id: LanguageIdEnum.MYSQL,
@@ -16,5 +16,7 @@ registerLanguage({
1616

1717
setupLanguageFeatures(LanguageIdEnum.MYSQL, {
1818
completionItems: true,
19-
diagnostics: true
19+
diagnostics: true,
20+
references: true,
21+
definitions: true
2022
});

Diff for: src/languages/pgsql/pgsql.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { registerLanguage } from '../../_.contribution';
7-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
87
import { LanguageIdEnum } from '../../common/constants';
8+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
99

1010
registerLanguage({
1111
id: LanguageIdEnum.PG,
@@ -16,5 +16,7 @@ registerLanguage({
1616

1717
setupLanguageFeatures(LanguageIdEnum.PG, {
1818
completionItems: true,
19-
diagnostics: true
19+
diagnostics: true,
20+
references: true,
21+
definitions: true
2022
});

Diff for: src/languages/spark/spark.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { registerLanguage } from '../../_.contribution';
7-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
87
import { LanguageIdEnum } from '../../common/constants';
8+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
99

1010
registerLanguage({
1111
id: LanguageIdEnum.SPARK,
@@ -16,5 +16,7 @@ registerLanguage({
1616

1717
setupLanguageFeatures(LanguageIdEnum.SPARK, {
1818
completionItems: true,
19-
diagnostics: true
19+
diagnostics: true,
20+
references: true,
21+
definitions: true
2022
});

Diff for: src/languages/trino/trino.contribution.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { registerLanguage } from '../../_.contribution';
2-
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
32
import { LanguageIdEnum } from '../../common/constants';
3+
import { setupLanguageFeatures } from '../../setupLanguageFeatures';
44

55
registerLanguage({
66
id: LanguageIdEnum.TRINO,
@@ -11,5 +11,7 @@ registerLanguage({
1111

1212
setupLanguageFeatures(LanguageIdEnum.TRINO, {
1313
completionItems: true,
14-
diagnostics: true
14+
diagnostics: true,
15+
references: true,
16+
definitions: true
1517
});

Diff for: src/monaco.contribution.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { languages, Emitter, IEvent, editor, Position, IRange } from './fillers/monaco-editor-core';
21
import { EntityContext, Suggestions } from 'dt-sql-parser';
32

3+
import { editor, Emitter, IEvent, IRange, languages, Position } from './fillers/monaco-editor-core';
4+
45
/**
56
* A completion item.
67
* ICompletionItem is pretty much the same as {@link languages.CompletionItem},
@@ -65,7 +66,7 @@ export interface ModeConfiguration {
6566
/**
6667
* Defines whether the built-in definitions provider is enabled.
6768
*/
68-
// readonly definitions?: boolean;
69+
readonly definitions?: boolean;
6970

7071
/**
7172
* Defines whether the built-in rename provider is enabled.
@@ -75,7 +76,7 @@ export interface ModeConfiguration {
7576
/**
7677
* Defines whether the built-in references provider is enabled.
7778
*/
78-
// readonly references?: boolean;
79+
readonly references?: boolean;
7980
}
8081

8182
/**
@@ -171,5 +172,7 @@ export const modeConfigurationDefault: Required<ModeConfiguration> = {
171172
completionService: defaultCompletionService,
172173
triggerCharacters: ['.', ' ']
173174
},
174-
diagnostics: true
175+
diagnostics: true,
176+
definitions: true,
177+
references: true
175178
};

Diff for: src/setupLanguageFeatures.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
import { LanguageIdEnum } from './common/constants';
2+
import { IDisposable, languages } from './fillers/monaco-editor-core';
13
import {
2-
PreprocessCode,
4+
CompletionOptions,
35
LanguageServiceDefaults,
46
LanguageServiceDefaultsImpl,
5-
modeConfigurationDefault,
67
ModeConfiguration,
7-
CompletionOptions
8+
modeConfigurationDefault,
9+
PreprocessCode
810
} from './monaco.contribution';
9-
import { languages, IDisposable } from './fillers/monaco-editor-core';
10-
import { LanguageIdEnum } from './common/constants';
1111

1212
export interface FeatureConfiguration {
1313
/**
@@ -20,6 +20,14 @@ export interface FeatureConfiguration {
2020
* Defaults to true.
2121
*/
2222
diagnostics?: boolean;
23+
/**
24+
* Defines whether the built-in definitions provider is enabled.
25+
*/
26+
definitions?: boolean;
27+
/**
28+
* Defines whether the built-in references provider is enabled.
29+
*/
30+
references?: boolean;
2331
/**
2432
* Define a function to preprocess code.
2533
* By default, do not something.
@@ -110,13 +118,23 @@ function processConfiguration(
110118
? configuration.completionItems!.triggerCharacters
111119
: (defaults?.modeConfiguration.completionItems.triggerCharacters ??
112120
modeConfigurationDefault.completionItems.triggerCharacters);
121+
const references =
122+
typeof configuration.references === 'boolean'
123+
? configuration.references
124+
: (defaults?.modeConfiguration.references ?? modeConfigurationDefault.references);
125+
const definitions =
126+
typeof configuration.definitions === 'boolean'
127+
? configuration.definitions
128+
: (defaults?.modeConfiguration.definitions ?? modeConfigurationDefault.definitions);
113129

114130
return {
115131
diagnostics,
116132
completionItems: {
117133
enable: completionEnable,
118134
completionService,
119135
triggerCharacters
120-
}
136+
},
137+
references,
138+
definitions
121139
};
122140
}

0 commit comments

Comments
 (0)