volar-service-typescript 0.0.31-patch.1 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/index.d.ts +4 -17
  2. package/index.js +12 -545
  3. package/lib/configs/getFormatCodeSettings.d.ts +2 -3
  4. package/lib/configs/getUserPreferences.d.ts +1 -1
  5. package/lib/plugins/directiveComment.d.ts +3 -0
  6. package/lib/plugins/directiveComment.js +65 -0
  7. package/lib/plugins/docCommentTemplate.d.ts +3 -0
  8. package/lib/{features/completions/jsDoc.js → plugins/docCommentTemplate.js} +42 -30
  9. package/lib/plugins/semantic.d.ts +23 -0
  10. package/lib/plugins/semantic.js +706 -0
  11. package/lib/plugins/syntactic.d.ts +7 -0
  12. package/lib/plugins/syntactic.js +92 -0
  13. package/lib/{features → semanticFeatures}/codeAction.d.ts +3 -2
  14. package/lib/{features → semanticFeatures}/codeAction.js +14 -17
  15. package/lib/{features → semanticFeatures}/codeActionResolve.d.ts +1 -1
  16. package/lib/{features → semanticFeatures}/codeActionResolve.js +7 -7
  17. package/lib/semanticFeatures/semanticTokens.d.ts +5 -0
  18. package/lib/{features → semanticFeatures}/semanticTokens.js +4 -8
  19. package/lib/{types.d.ts → semanticFeatures/types.d.ts} +1 -2
  20. package/lib/shared.d.ts +1 -0
  21. package/lib/shared.js +5 -1
  22. package/lib/syntacticLanguageService.d.ts +7 -0
  23. package/lib/syntacticLanguageService.js +38 -0
  24. package/lib/utils/lspConverters.d.ts +27 -0
  25. package/lib/utils/lspConverters.js +782 -0
  26. package/lib/utils/previewer.d.ts +5 -11
  27. package/lib/utils/previewer.js +30 -35
  28. package/package.json +5 -6
  29. package/lib/features/callHierarchy.d.ts +0 -8
  30. package/lib/features/callHierarchy.js +0 -102
  31. package/lib/features/completions/basic.d.ts +0 -17
  32. package/lib/features/completions/basic.js +0 -326
  33. package/lib/features/completions/directiveComment.d.ts +0 -4
  34. package/lib/features/completions/directiveComment.js +0 -54
  35. package/lib/features/completions/jsDoc.d.ts +0 -4
  36. package/lib/features/completions/resolve.d.ts +0 -6
  37. package/lib/features/completions/resolve.js +0 -146
  38. package/lib/features/definition.d.ts +0 -4
  39. package/lib/features/definition.js +0 -20
  40. package/lib/features/diagnostics.d.ts +0 -11
  41. package/lib/features/diagnostics.js +0 -120
  42. package/lib/features/documentHighlight.d.ts +0 -4
  43. package/lib/features/documentHighlight.js +0 -32
  44. package/lib/features/documentSymbol.d.ts +0 -4
  45. package/lib/features/documentSymbol.js +0 -94
  46. package/lib/features/fileReferences.d.ts +0 -4
  47. package/lib/features/fileReferences.js +0 -19
  48. package/lib/features/fileRename.d.ts +0 -4
  49. package/lib/features/fileRename.js +0 -25
  50. package/lib/features/foldingRanges.d.ts +0 -4
  51. package/lib/features/foldingRanges.js +0 -55
  52. package/lib/features/formatting.d.ts +0 -8
  53. package/lib/features/formatting.js +0 -55
  54. package/lib/features/hover.d.ts +0 -4
  55. package/lib/features/hover.js +0 -43
  56. package/lib/features/implementation.d.ts +0 -4
  57. package/lib/features/implementation.js +0 -20
  58. package/lib/features/inlayHints.d.ts +0 -4
  59. package/lib/features/inlayHints.js +0 -34
  60. package/lib/features/prepareRename.d.ts +0 -9
  61. package/lib/features/prepareRename.js +0 -27
  62. package/lib/features/references.d.ts +0 -4
  63. package/lib/features/references.js +0 -35
  64. package/lib/features/rename.d.ts +0 -6
  65. package/lib/features/rename.js +0 -116
  66. package/lib/features/selectionRanges.d.ts +0 -4
  67. package/lib/features/selectionRanges.js +0 -32
  68. package/lib/features/semanticTokens.d.ts +0 -4
  69. package/lib/features/signatureHelp.d.ts +0 -4
  70. package/lib/features/signatureHelp.js +0 -63
  71. package/lib/features/typeDefinition.d.ts +0 -4
  72. package/lib/features/typeDefinition.js +0 -20
  73. package/lib/features/workspaceSymbol.d.ts +0 -4
  74. package/lib/features/workspaceSymbol.js +0 -63
  75. package/lib/utils/transforms.d.ts +0 -15
  76. package/lib/utils/transforms.js +0 -85
  77. /package/lib/{types.js → semanticFeatures/types.js} +0 -0
@@ -0,0 +1,706 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.create = void 0;
4
+ const path = require("path-browserify");
5
+ const semver = require("semver");
6
+ const tsWithImportCache = require("typescript-auto-import-cache");
7
+ const getFormatCodeSettings_1 = require("../configs/getFormatCodeSettings");
8
+ const getUserPreferences_1 = require("../configs/getUserPreferences");
9
+ const shared_1 = require("../shared");
10
+ const lspConverters_1 = require("../utils/lspConverters");
11
+ const snippetForFunctionCall_1 = require("../utils/snippetForFunctionCall");
12
+ const codeActions = require("../semanticFeatures/codeAction");
13
+ const codeActionResolve = require("../semanticFeatures/codeActionResolve");
14
+ const semanticTokens = require("../semanticFeatures/semanticTokens");
15
+ const documentRegistries = [];
16
+ function getDocumentRegistry(ts, useCaseSensitiveFileNames, currentDirectory) {
17
+ let documentRegistry = documentRegistries.find(item => item[0] === useCaseSensitiveFileNames && item[1] === currentDirectory)?.[2];
18
+ if (!documentRegistry) {
19
+ documentRegistry = ts.createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory);
20
+ documentRegistries.push([useCaseSensitiveFileNames, currentDirectory, documentRegistry]);
21
+ }
22
+ return documentRegistry;
23
+ }
24
+ function create(ts, { isValidationEnabled = async (document, context) => {
25
+ return await context.env.getConfiguration?.((0, shared_1.getConfigTitle)(document) + '.validate.enable') ?? true;
26
+ }, isSuggestionsEnabled = async (document, context) => {
27
+ return await context.env.getConfiguration?.((0, shared_1.getConfigTitle)(document) + '.suggest.enabled') ?? true;
28
+ }, } = {}) {
29
+ return {
30
+ name: 'typescript-semantic',
31
+ triggerCharacters: getBasicTriggerCharacters(ts.version),
32
+ signatureHelpTriggerCharacters: ['(', ',', '<'],
33
+ signatureHelpRetriggerCharacters: [')'],
34
+ create(context) {
35
+ if (!context.language.typescript) {
36
+ return {};
37
+ }
38
+ const { sys, languageServiceHost } = context.language.typescript;
39
+ const created = tsWithImportCache.createLanguageService(ts, sys, languageServiceHost, proxiedHost => ts.createLanguageService(proxiedHost, getDocumentRegistry(ts, sys.useCaseSensitiveFileNames, languageServiceHost.getCurrentDirectory())));
40
+ const { languageService } = created;
41
+ if (created.setPreferences && context.env.getConfiguration) {
42
+ updatePreferences();
43
+ context.env.onDidChangeConfiguration?.(updatePreferences);
44
+ async function updatePreferences() {
45
+ const preferences = await context.env.getConfiguration?.('typescript.preferences');
46
+ if (preferences) {
47
+ created.setPreferences?.(preferences);
48
+ }
49
+ }
50
+ }
51
+ if (created.projectUpdated) {
52
+ const sourceScriptNames = new Set();
53
+ const normalizeFileName = sys.useCaseSensitiveFileNames
54
+ ? (id) => id
55
+ : (id) => id.toLowerCase();
56
+ updateSourceScriptFileNames();
57
+ context.env.onDidChangeWatchedFiles?.((params) => {
58
+ const someFileCreateOrDeiete = params.changes.some(change => change.type !== 2);
59
+ if (someFileCreateOrDeiete) {
60
+ updateSourceScriptFileNames();
61
+ }
62
+ for (const change of params.changes) {
63
+ const fileName = context.env.typescript.uriToFileName(change.uri);
64
+ if (sourceScriptNames.has(normalizeFileName(fileName))) {
65
+ created.projectUpdated?.(languageServiceHost.getCurrentDirectory());
66
+ }
67
+ }
68
+ });
69
+ function updateSourceScriptFileNames() {
70
+ sourceScriptNames.clear();
71
+ for (const fileName of languageServiceHost.getScriptFileNames()) {
72
+ const uri = context.env.typescript.fileNameToUri(fileName);
73
+ const sourceFile = context.language.files.get(uri);
74
+ if (sourceFile?.generated) {
75
+ const tsCode = sourceFile.generated.languagePlugin.typescript?.getScript(sourceFile.generated.code);
76
+ if (tsCode) {
77
+ sourceScriptNames.add(normalizeFileName(fileName));
78
+ }
79
+ }
80
+ else if (sourceFile) {
81
+ sourceScriptNames.add(normalizeFileName(fileName));
82
+ }
83
+ }
84
+ }
85
+ }
86
+ const ctx = {
87
+ ...context,
88
+ languageServiceHost,
89
+ languageService,
90
+ uriToFileName(uri) {
91
+ const virtualScript = getVirtualScriptByUri(uri);
92
+ if (virtualScript) {
93
+ return virtualScript.fileName;
94
+ }
95
+ return context.env.typescript.uriToFileName(uri);
96
+ },
97
+ fileNameToUri(fileName) {
98
+ const uri = context.env.typescript.fileNameToUri(fileName);
99
+ const sourceFile = context.language.files.get(uri);
100
+ const extraScript = context.language.typescript.getExtraScript(fileName);
101
+ let virtualCode = extraScript?.code;
102
+ if (!virtualCode && sourceFile?.generated?.languagePlugin.typescript) {
103
+ const mainScript = sourceFile.generated.languagePlugin.typescript.getScript(sourceFile.generated.code);
104
+ if (mainScript) {
105
+ virtualCode = mainScript.code;
106
+ }
107
+ }
108
+ if (virtualCode) {
109
+ const sourceFile = context.language.files.getByVirtualCode(virtualCode);
110
+ return context.documents.getVirtualCodeUri(sourceFile.id, virtualCode.id);
111
+ }
112
+ return uri;
113
+ },
114
+ getTextDocument(uri) {
115
+ const virtualCode = context.documents.getVirtualCodeByUri(uri)[0];
116
+ if (virtualCode) {
117
+ return context.documents.get(uri, virtualCode.languageId, virtualCode.snapshot);
118
+ }
119
+ const sourceFile = context.language.files.get(uri);
120
+ if (sourceFile) {
121
+ return context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
122
+ }
123
+ throw new Error(`getTextDocument: uri not found: ${uri}`);
124
+ },
125
+ };
126
+ const getCodeActions = codeActions.register(ctx);
127
+ const doCodeActionResolve = codeActionResolve.register(ctx);
128
+ const getDocumentSemanticTokens = semanticTokens.register(ts, ctx);
129
+ /* typescript-language-features is hardcode true */
130
+ const renameInfoOptions = { allowRenameOfImportPath: true };
131
+ return {
132
+ provide: {
133
+ 'typescript/languageService': () => languageService,
134
+ 'typescript/languageServiceHost': () => languageServiceHost,
135
+ },
136
+ dispose() {
137
+ languageService.dispose();
138
+ },
139
+ async provideCompletionItems(document, position, completeContext, token) {
140
+ if (!isSemanticDocument(document))
141
+ return;
142
+ if (!await isSuggestionsEnabled(document, context))
143
+ return;
144
+ return await worker(token, async () => {
145
+ const preferences = await (0, getUserPreferences_1.getUserPreferences)(ctx, document);
146
+ const fileName = ctx.uriToFileName(document.uri);
147
+ const offset = document.offsetAt(position);
148
+ const info = (0, shared_1.safeCall)(() => ctx.languageService.getCompletionsAtPosition(fileName, offset, {
149
+ ...preferences,
150
+ triggerCharacter: completeContext.triggerCharacter,
151
+ triggerKind: completeContext.triggerKind,
152
+ }));
153
+ if (info) {
154
+ return (0, lspConverters_1.convertCompletionInfo)(ts, info, document, position, tsEntry => ({
155
+ uri: document.uri,
156
+ fileName,
157
+ offset,
158
+ originalItem: {
159
+ name: tsEntry.name,
160
+ source: tsEntry.source,
161
+ data: tsEntry.data,
162
+ labelDetails: tsEntry.labelDetails,
163
+ },
164
+ }));
165
+ }
166
+ });
167
+ },
168
+ async resolveCompletionItem(item, token) {
169
+ return await worker(token, async () => {
170
+ const data = item.data;
171
+ if (!data) {
172
+ return item;
173
+ }
174
+ const { fileName, offset } = data;
175
+ const document = ctx.getTextDocument(data.uri);
176
+ const [formatOptions, preferences] = await Promise.all([
177
+ (0, getFormatCodeSettings_1.getFormatCodeSettings)(ctx, document),
178
+ (0, getUserPreferences_1.getUserPreferences)(ctx, document),
179
+ ]);
180
+ const details = (0, shared_1.safeCall)(() => ctx.languageService.getCompletionEntryDetails(fileName, offset, data.originalItem.name, formatOptions, data.originalItem.source, preferences, data.originalItem.data));
181
+ if (!details) {
182
+ return item;
183
+ }
184
+ if (data.originalItem.labelDetails) {
185
+ item.labelDetails ??= {};
186
+ Object.assign(item.labelDetails, data.originalItem.labelDetails);
187
+ }
188
+ (0, lspConverters_1.applyCompletionEntryDetails)(ts, item, details, document, ctx.fileNameToUri, ctx.getTextDocument);
189
+ const useCodeSnippetsOnMethodSuggest = await ctx.env.getConfiguration?.((0, shared_1.getConfigTitle)(document) + '.suggest.completeFunctionCalls') ?? false;
190
+ const useCodeSnippet = useCodeSnippetsOnMethodSuggest
191
+ && (item.kind === 3
192
+ || item.kind === 2);
193
+ if (useCodeSnippet) {
194
+ const shouldCompleteFunction = isValidFunctionCompletionContext(ctx.languageService, fileName, offset, document);
195
+ if (shouldCompleteFunction) {
196
+ const { snippet, parameterCount } = (0, snippetForFunctionCall_1.snippetForFunctionCall)({
197
+ insertText: item.insertText ?? item.textEdit?.newText, // insertText is dropped by LSP in some case: https://github.com/microsoft/vscode-languageserver-node/blob/9b742021fb04ad081aa3676a9eecf4fa612084b4/client/src/common/codeConverter.ts#L659-L664
198
+ label: item.label,
199
+ }, details.displayParts);
200
+ if (item.textEdit) {
201
+ item.textEdit.newText = snippet;
202
+ }
203
+ if (item.insertText) {
204
+ item.insertText = snippet;
205
+ }
206
+ item.insertTextFormat = 2;
207
+ if (parameterCount > 0) {
208
+ //Fix for https://github.com/microsoft/vscode/issues/104059
209
+ //Don't show parameter hints if "editor.parameterHints.enabled": false
210
+ // if (await getConfiguration('editor.parameterHints.enabled', document.uri)) {
211
+ // item.command = {
212
+ // title: 'triggerParameterHints',
213
+ // command: 'editor.action.triggerParameterHints',
214
+ // };
215
+ // }
216
+ }
217
+ }
218
+ }
219
+ return item;
220
+ function isValidFunctionCompletionContext(client, filepath, offset, document) {
221
+ // Workaround for https://github.com/microsoft/TypeScript/issues/12677
222
+ // Don't complete function calls inside of destructive assignments or imports
223
+ try {
224
+ const response = client.getQuickInfoAtPosition(filepath, offset);
225
+ if (response) {
226
+ switch (response.kind) {
227
+ case 'var':
228
+ case 'let':
229
+ case 'const':
230
+ case 'alias':
231
+ return false;
232
+ }
233
+ }
234
+ }
235
+ catch {
236
+ // Noop
237
+ }
238
+ // Don't complete function call if there is already something that looks like a function call
239
+ // https://github.com/microsoft/vscode/issues/18131
240
+ const position = document.positionAt(offset);
241
+ const after = (0, lspConverters_1.getLineText)(document, position.line).slice(position.character);
242
+ return after.match(/^[a-z_$0-9]*\s*\(/gi) === null;
243
+ }
244
+ }) ?? item;
245
+ },
246
+ provideRenameRange(document, position, token) {
247
+ if (!isSemanticDocument(document))
248
+ return;
249
+ return worker(token, () => {
250
+ const fileName = ctx.uriToFileName(document.uri);
251
+ const offset = document.offsetAt(position);
252
+ const renameInfo = (0, shared_1.safeCall)(() => ctx.languageService.getRenameInfo(fileName, offset, renameInfoOptions));
253
+ if (!renameInfo) {
254
+ return;
255
+ }
256
+ if (!renameInfo.canRename) {
257
+ return { message: renameInfo.localizedErrorMessage };
258
+ }
259
+ return (0, lspConverters_1.convertTextSpan)(renameInfo.triggerSpan, document);
260
+ });
261
+ },
262
+ provideRenameEdits(document, position, newName, token) {
263
+ if (!isSemanticDocument(document, true))
264
+ return;
265
+ return worker(token, async () => {
266
+ const fileName = ctx.uriToFileName(document.uri);
267
+ const offset = document.offsetAt(position);
268
+ const renameInfo = (0, shared_1.safeCall)(() => ctx.languageService.getRenameInfo(fileName, offset, renameInfoOptions));
269
+ if (!renameInfo?.canRename) {
270
+ return;
271
+ }
272
+ if (renameInfo.fileToRename) {
273
+ const [formatOptions, preferences] = await Promise.all([
274
+ (0, getFormatCodeSettings_1.getFormatCodeSettings)(ctx, document),
275
+ (0, getUserPreferences_1.getUserPreferences)(ctx, document),
276
+ ]);
277
+ return renameFile(renameInfo.fileToRename, newName, formatOptions, preferences);
278
+ }
279
+ const { providePrefixAndSuffixTextForRename } = await (0, getUserPreferences_1.getUserPreferences)(ctx, document);
280
+ const entries = ctx.languageService.findRenameLocations(fileName, offset, false, false, providePrefixAndSuffixTextForRename);
281
+ if (!entries) {
282
+ return;
283
+ }
284
+ return (0, lspConverters_1.convertRenameLocations)(newName, entries, ctx.fileNameToUri, ctx.getTextDocument);
285
+ function renameFile(fileToRename, newName, formatOptions, preferences) {
286
+ // Make sure we preserve file extension if none provided
287
+ if (!path.extname(newName)) {
288
+ newName += path.extname(fileToRename);
289
+ }
290
+ const dirname = path.dirname(fileToRename);
291
+ const newFilePath = path.join(dirname, newName);
292
+ const response = (0, shared_1.safeCall)(() => ctx.languageService.getEditsForFileRename(fileToRename, newFilePath, formatOptions, preferences));
293
+ if (!response) {
294
+ return;
295
+ }
296
+ const edits = (0, lspConverters_1.convertFileTextChanges)(response, ctx.fileNameToUri, ctx.getTextDocument);
297
+ if (!edits.documentChanges) {
298
+ edits.documentChanges = [];
299
+ }
300
+ edits.documentChanges.push({
301
+ kind: 'rename',
302
+ oldUri: ctx.fileNameToUri(fileToRename),
303
+ newUri: ctx.fileNameToUri(newFilePath),
304
+ });
305
+ return edits;
306
+ }
307
+ });
308
+ },
309
+ provideCodeActions(document, range, context, token) {
310
+ if (!isSemanticDocument(document))
311
+ return;
312
+ return worker(token, () => {
313
+ return getCodeActions(document, range, context);
314
+ });
315
+ },
316
+ async resolveCodeAction(codeAction, token) {
317
+ return await worker(token, () => {
318
+ return doCodeActionResolve(codeAction);
319
+ }) ?? codeAction;
320
+ },
321
+ provideInlayHints(document, range, token) {
322
+ if (!isSemanticDocument(document))
323
+ return;
324
+ return worker(token, async () => {
325
+ const preferences = await (0, getUserPreferences_1.getUserPreferences)(ctx, document);
326
+ const fileName = ctx.uriToFileName(document.uri);
327
+ const start = document.offsetAt(range.start);
328
+ const end = document.offsetAt(range.end);
329
+ const inlayHints = (0, shared_1.safeCall)(() => 'provideInlayHints' in ctx.languageService
330
+ ? ctx.languageService.provideInlayHints(fileName, { start, length: end - start }, preferences)
331
+ : []);
332
+ if (!inlayHints) {
333
+ return [];
334
+ }
335
+ return inlayHints.map(hint => (0, lspConverters_1.convertInlayHint)(hint, document));
336
+ });
337
+ },
338
+ provideCallHierarchyItems(document, position, token) {
339
+ if (!isSemanticDocument(document))
340
+ return;
341
+ return worker(token, () => {
342
+ const fileName = ctx.uriToFileName(document.uri);
343
+ const offset = document.offsetAt(position);
344
+ const calls = (0, shared_1.safeCall)(() => ctx.languageService.prepareCallHierarchy(fileName, offset));
345
+ if (!calls) {
346
+ return [];
347
+ }
348
+ const items = Array.isArray(calls) ? calls : [calls];
349
+ return items.map(item => (0, lspConverters_1.convertCallHierarchyItem)(item, ctx));
350
+ });
351
+ },
352
+ async provideCallHierarchyIncomingCalls(item, token) {
353
+ return await worker(token, () => {
354
+ const document = ctx.getTextDocument(item.uri);
355
+ const fileName = ctx.uriToFileName(item.uri);
356
+ const offset = document.offsetAt(item.selectionRange.start);
357
+ const calls = (0, shared_1.safeCall)(() => ctx.languageService.provideCallHierarchyIncomingCalls(fileName, offset));
358
+ if (!calls) {
359
+ return [];
360
+ }
361
+ const items = Array.isArray(calls) ? calls : [calls];
362
+ return items.map(item => (0, lspConverters_1.convertCallHierarchyIncomingCall)(item, ctx));
363
+ }) ?? [];
364
+ },
365
+ async provideCallHierarchyOutgoingCalls(item, token) {
366
+ return await worker(token, () => {
367
+ const document = ctx.getTextDocument(item.uri);
368
+ const fileName = ctx.uriToFileName(item.uri);
369
+ const offset = document.offsetAt(item.selectionRange.start);
370
+ const calls = (0, shared_1.safeCall)(() => ctx.languageService.provideCallHierarchyOutgoingCalls(fileName, offset));
371
+ if (!calls) {
372
+ return [];
373
+ }
374
+ const items = Array.isArray(calls) ? calls : [calls];
375
+ return items.map(item => (0, lspConverters_1.convertCallHierarchyOutgoingCall)(item, document, ctx));
376
+ }) ?? [];
377
+ },
378
+ provideDefinition(document, position, token) {
379
+ if (!isSemanticDocument(document))
380
+ return;
381
+ return worker(token, () => {
382
+ const fileName = ctx.uriToFileName(document.uri);
383
+ const offset = document.offsetAt(position);
384
+ const info = (0, shared_1.safeCall)(() => ctx.languageService.getDefinitionAndBoundSpan(fileName, offset));
385
+ if (!info) {
386
+ return [];
387
+ }
388
+ return (0, lspConverters_1.convertDefinitionInfoAndBoundSpan)(info, document, ctx);
389
+ });
390
+ },
391
+ provideTypeDefinition(document, position, token) {
392
+ if (!isSemanticDocument(document))
393
+ return;
394
+ return worker(token, () => {
395
+ const fileName = ctx.uriToFileName(document.uri);
396
+ const offset = document.offsetAt(position);
397
+ const entries = (0, shared_1.safeCall)(() => ctx.languageService.getTypeDefinitionAtPosition(fileName, offset));
398
+ if (!entries) {
399
+ return [];
400
+ }
401
+ return entries.map(entry => (0, lspConverters_1.convertDocumentSpantoLocationLink)(entry, ctx));
402
+ });
403
+ },
404
+ async provideDiagnostics(document, token) {
405
+ return provideDiagnosticsWorker(document, token, 'syntactic');
406
+ },
407
+ async provideSemanticDiagnostics(document, token) {
408
+ return provideDiagnosticsWorker(document, token, 'semantic');
409
+ },
410
+ provideHover(document, position, token) {
411
+ if (!isSemanticDocument(document))
412
+ return;
413
+ return worker(token, () => {
414
+ const fileName = ctx.uriToFileName(document.uri);
415
+ const offset = document.offsetAt(position);
416
+ const info = (0, shared_1.safeCall)(() => ctx.languageService.getQuickInfoAtPosition(fileName, offset));
417
+ if (!info) {
418
+ return;
419
+ }
420
+ return (0, lspConverters_1.convertQuickInfo)(ts, info, document, ctx.fileNameToUri, ctx.getTextDocument);
421
+ });
422
+ },
423
+ provideImplementation(document, position, token) {
424
+ if (!isSemanticDocument(document))
425
+ return;
426
+ return worker(token, () => {
427
+ const fileName = ctx.uriToFileName(document.uri);
428
+ const offset = document.offsetAt(position);
429
+ const entries = (0, shared_1.safeCall)(() => ctx.languageService.getImplementationAtPosition(fileName, offset));
430
+ if (!entries) {
431
+ return [];
432
+ }
433
+ return entries.map(entry => (0, lspConverters_1.convertDocumentSpantoLocationLink)(entry, ctx));
434
+ });
435
+ },
436
+ provideReferences(document, position, referenceContext, token) {
437
+ if (!isSemanticDocument(document, true))
438
+ return;
439
+ return worker(token, () => {
440
+ const fileName = ctx.uriToFileName(document.uri);
441
+ const offset = document.offsetAt(position);
442
+ const references = (0, shared_1.safeCall)(() => ctx.languageService.findReferences(fileName, offset));
443
+ if (!references) {
444
+ return [];
445
+ }
446
+ const result = [];
447
+ for (const reference of references) {
448
+ if (referenceContext.includeDeclaration) {
449
+ const definition = (0, lspConverters_1.convertDocumentSpanToLocation)(reference.definition, ctx);
450
+ if (definition) {
451
+ result.push(definition);
452
+ }
453
+ }
454
+ for (const referenceEntry of reference.references) {
455
+ const reference = (0, lspConverters_1.convertDocumentSpanToLocation)(referenceEntry, ctx);
456
+ if (reference) {
457
+ result.push(reference);
458
+ }
459
+ }
460
+ }
461
+ return result;
462
+ });
463
+ },
464
+ provideFileReferences(document, token) {
465
+ if (!isSemanticDocument(document, true))
466
+ return;
467
+ return worker(token, () => {
468
+ const fileName = ctx.uriToFileName(document.uri);
469
+ const entries = (0, shared_1.safeCall)(() => ctx.languageService.getFileReferences(fileName));
470
+ if (!entries) {
471
+ return [];
472
+ }
473
+ return entries.map(entry => (0, lspConverters_1.convertDocumentSpanToLocation)(entry, ctx));
474
+ });
475
+ },
476
+ provideDocumentHighlights(document, position, token) {
477
+ if (!isSemanticDocument(document))
478
+ return;
479
+ return worker(token, () => {
480
+ const fileName = ctx.uriToFileName(document.uri);
481
+ const offset = document.offsetAt(position);
482
+ const highlights = (0, shared_1.safeCall)(() => ctx.languageService.getDocumentHighlights(fileName, offset, [fileName]));
483
+ if (!highlights) {
484
+ return [];
485
+ }
486
+ const results = [];
487
+ for (const highlight of highlights) {
488
+ for (const span of highlight.highlightSpans) {
489
+ results.push((0, lspConverters_1.convertHighlightSpan)(span, document));
490
+ }
491
+ }
492
+ return results;
493
+ });
494
+ },
495
+ provideDocumentSemanticTokens(document, range, legend, token) {
496
+ if (!isSemanticDocument(document))
497
+ return;
498
+ return worker(token, () => {
499
+ return getDocumentSemanticTokens(document, range, legend);
500
+ });
501
+ },
502
+ provideWorkspaceSymbols(query, token) {
503
+ return worker(token, () => {
504
+ const items = (0, shared_1.safeCall)(() => ctx.languageService.getNavigateToItems(query));
505
+ if (!items) {
506
+ return [];
507
+ }
508
+ return items
509
+ .filter(item => item.containerName || item.kind !== 'alias')
510
+ .map(item => (0, lspConverters_1.convertNavigateToItem)(item, ctx.getTextDocument(ctx.fileNameToUri(item.fileName))))
511
+ .filter(shared_1.notEmpty);
512
+ });
513
+ },
514
+ provideFileRenameEdits(oldUri, newUri, token) {
515
+ return worker(token, async () => {
516
+ const document = ctx.getTextDocument(oldUri);
517
+ const [formatOptions, preferences] = await Promise.all([
518
+ (0, getFormatCodeSettings_1.getFormatCodeSettings)(ctx, document),
519
+ (0, getUserPreferences_1.getUserPreferences)(ctx, document),
520
+ ]);
521
+ const fileToRename = ctx.uriToFileName(oldUri);
522
+ const newFilePath = ctx.uriToFileName(newUri);
523
+ const response = (0, shared_1.safeCall)(() => ctx.languageService.getEditsForFileRename(fileToRename, newFilePath, formatOptions, preferences));
524
+ if (!response?.length) {
525
+ return;
526
+ }
527
+ return (0, lspConverters_1.convertFileTextChanges)(response, ctx.fileNameToUri, ctx.getTextDocument);
528
+ });
529
+ },
530
+ provideSelectionRanges(document, positions, token) {
531
+ if (!isSemanticDocument(document))
532
+ return;
533
+ return worker(token, () => {
534
+ return positions
535
+ .map(position => {
536
+ const fileName = ctx.uriToFileName(document.uri);
537
+ const offset = document.offsetAt(position);
538
+ const range = (0, shared_1.safeCall)(() => ctx.languageService.getSmartSelectionRange(fileName, offset));
539
+ if (!range) {
540
+ return;
541
+ }
542
+ return (0, lspConverters_1.convertSelectionRange)(range, document);
543
+ })
544
+ .filter(shared_1.notEmpty);
545
+ });
546
+ },
547
+ provideSignatureHelp(document, position, context, token) {
548
+ if (!isSemanticDocument(document))
549
+ return;
550
+ return worker(token, () => {
551
+ const options = {};
552
+ if (context?.triggerKind === 1) {
553
+ options.triggerReason = {
554
+ kind: 'invoked'
555
+ };
556
+ }
557
+ else if (context?.triggerKind === 2) {
558
+ options.triggerReason = {
559
+ kind: 'characterTyped',
560
+ triggerCharacter: context.triggerCharacter,
561
+ };
562
+ }
563
+ else if (context?.triggerKind === 3) {
564
+ options.triggerReason = {
565
+ kind: 'retrigger',
566
+ triggerCharacter: context.triggerCharacter,
567
+ };
568
+ }
569
+ const fileName = ctx.uriToFileName(document.uri);
570
+ const offset = document.offsetAt(position);
571
+ const helpItems = (0, shared_1.safeCall)(() => ctx.languageService.getSignatureHelpItems(fileName, offset, options));
572
+ if (!helpItems) {
573
+ return;
574
+ }
575
+ return {
576
+ activeSignature: helpItems.selectedItemIndex,
577
+ activeParameter: helpItems.argumentIndex,
578
+ signatures: helpItems.items.map(item => {
579
+ const signature = {
580
+ label: '',
581
+ documentation: undefined,
582
+ parameters: []
583
+ };
584
+ signature.label += ts.displayPartsToString(item.prefixDisplayParts);
585
+ item.parameters.forEach((p, i, a) => {
586
+ const label = ts.displayPartsToString(p.displayParts);
587
+ const parameter = {
588
+ label,
589
+ documentation: ts.displayPartsToString(p.documentation)
590
+ };
591
+ signature.label += label;
592
+ signature.parameters.push(parameter);
593
+ if (i < a.length - 1) {
594
+ signature.label += ts.displayPartsToString(item.separatorDisplayParts);
595
+ }
596
+ });
597
+ signature.label += ts.displayPartsToString(item.suffixDisplayParts);
598
+ return signature;
599
+ }),
600
+ };
601
+ });
602
+ },
603
+ };
604
+ async function provideDiagnosticsWorker(document, token, mode) {
605
+ if (!isSemanticDocument(document))
606
+ return;
607
+ if (!await isValidationEnabled(document, context))
608
+ return;
609
+ return await worker(token, () => {
610
+ const fileName = ctx.uriToFileName(document.uri);
611
+ const program = ctx.languageService.getProgram();
612
+ const sourceFile = program?.getSourceFile(fileName);
613
+ if (!program || !sourceFile) {
614
+ return [];
615
+ }
616
+ const token = {
617
+ isCancellationRequested() {
618
+ return ctx.language.typescript?.languageServiceHost.getCancellationToken?.().isCancellationRequested() ?? false;
619
+ },
620
+ throwIfCancellationRequested() { },
621
+ };
622
+ if (mode === 'syntactic') {
623
+ const syntacticDiagnostics = (0, shared_1.safeCall)(() => program.getSyntacticDiagnostics(sourceFile, token)) ?? [];
624
+ const suggestionDiagnostics = (0, shared_1.safeCall)(() => ctx.languageService.getSuggestionDiagnostics(fileName)) ?? [];
625
+ return [...syntacticDiagnostics, ...suggestionDiagnostics]
626
+ .map(diagnostic => (0, lspConverters_1.convertDiagnostic)(diagnostic, document, ctx.fileNameToUri, ctx.getTextDocument))
627
+ .filter(shared_1.notEmpty);
628
+ }
629
+ else if (mode === 'semantic') {
630
+ const semanticDiagnostics = (0, shared_1.safeCall)(() => program.getSemanticDiagnostics(sourceFile, token)) ?? [];
631
+ const declarationDiagnostics = getEmitDeclarations(program.getCompilerOptions())
632
+ ? (0, shared_1.safeCall)(() => program.getDeclarationDiagnostics(sourceFile, token)) ?? []
633
+ : [];
634
+ return [...semanticDiagnostics, ...declarationDiagnostics]
635
+ .map(diagnostic => (0, lspConverters_1.convertDiagnostic)(diagnostic, document, ctx.fileNameToUri, ctx.getTextDocument))
636
+ .filter(shared_1.notEmpty);
637
+ }
638
+ });
639
+ }
640
+ function getEmitDeclarations(compilerOptions) {
641
+ return !!(compilerOptions.declaration || compilerOptions.composite);
642
+ }
643
+ function isSemanticDocument(document, withJson = false) {
644
+ const virtualScript = getVirtualScriptByUri(document.uri);
645
+ if (virtualScript) {
646
+ return true;
647
+ }
648
+ if (withJson && (0, shared_1.isJsonDocument)(document)) {
649
+ return true;
650
+ }
651
+ return (0, shared_1.isTsDocument)(document);
652
+ }
653
+ async function worker(token, fn) {
654
+ let result;
655
+ let oldSysVersion;
656
+ let newSysVersion = await sys.sync?.();
657
+ do {
658
+ oldSysVersion = newSysVersion;
659
+ try {
660
+ result = await fn();
661
+ }
662
+ catch (err) {
663
+ console.warn(err);
664
+ break;
665
+ }
666
+ newSysVersion = await sys.sync?.();
667
+ } while (newSysVersion !== oldSysVersion && !token.isCancellationRequested);
668
+ return result;
669
+ }
670
+ function getVirtualScriptByUri(uri) {
671
+ const [virtualCode, sourceFile] = context.documents.getVirtualCodeByUri(uri);
672
+ if (virtualCode && sourceFile.generated?.languagePlugin.typescript) {
673
+ const { getScript, getExtraScripts } = sourceFile.generated?.languagePlugin.typescript;
674
+ const sourceFileName = context.env.typescript.uriToFileName(sourceFile.id);
675
+ if (getScript(sourceFile.generated.code)?.code === virtualCode) {
676
+ return {
677
+ fileName: sourceFileName,
678
+ code: virtualCode,
679
+ };
680
+ }
681
+ for (const extraScript of getExtraScripts?.(sourceFileName, sourceFile.generated.code) ?? []) {
682
+ if (extraScript.code === virtualCode) {
683
+ return extraScript;
684
+ }
685
+ }
686
+ }
687
+ }
688
+ },
689
+ };
690
+ }
691
+ exports.create = create;
692
+ function getBasicTriggerCharacters(tsVersion) {
693
+ const triggerCharacters = ['.', '"', '\'', '`', '/', '<'];
694
+ // https://github.com/microsoft/vscode/blob/8e65ae28d5fb8b3c931135da1a41edb9c80ae46f/extensions/typescript-language-features/src/languageFeatures/completions.ts#L811-L833
695
+ if (semver.lt(tsVersion, '3.1.0') || semver.gte(tsVersion, '3.2.0')) {
696
+ triggerCharacters.push('@');
697
+ }
698
+ if (semver.gte(tsVersion, '3.8.1')) {
699
+ triggerCharacters.push('#');
700
+ }
701
+ if (semver.gte(tsVersion, '4.3.0')) {
702
+ triggerCharacters.push(' ');
703
+ }
704
+ return triggerCharacters;
705
+ }
706
+ //# sourceMappingURL=semantic.js.map