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,782 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertTextSpan = exports.convertDocumentSpantoLocationLink = exports.convertDefinitionInfoAndBoundSpan = exports.convertDocumentSpanToLocation = exports.convertCallHierarchyItem = exports.convertCallHierarchyOutgoingCall = exports.convertCallHierarchyIncomingCall = exports.convertTextChange = exports.convertOutliningSpanKind = exports.convertOutliningSpan = exports.convertNavTree = exports.convertQuickInfo = exports.convertRenameLocations = exports.convertFileTextChanges = exports.convertSelectionRange = exports.convertHighlightSpan = exports.convertInlayHint = exports.convertNavigateToItem = exports.getLineText = exports.convertCompletionInfo = exports.applyCompletionEntryDetails = exports.convertDiagnostic = void 0;
4
+ const path = require("path-browserify");
5
+ const PConst = require("../protocol.const");
6
+ const shared_1 = require("../shared");
7
+ const modifiers_1 = require("../utils/modifiers");
8
+ const previewer = require("../utils/previewer");
9
+ const typeConverters = require("../utils/typeConverters");
10
+ const semver = require("semver");
11
+ // diagnostics
12
+ function convertDiagnostic(diag, document, fileNameToUri, getTextDocument) {
13
+ if (diag.start === undefined)
14
+ return;
15
+ if (diag.length === undefined)
16
+ return;
17
+ const diagnostic = {
18
+ range: {
19
+ start: document.positionAt(diag.start),
20
+ end: document.positionAt(diag.start + diag.length),
21
+ },
22
+ severity: convertDiagnosticCategory(diag.category),
23
+ source: 'ts',
24
+ code: diag.code,
25
+ message: getMessageText(diag),
26
+ };
27
+ if (diag.relatedInformation) {
28
+ diagnostic.relatedInformation = diag.relatedInformation
29
+ .map(rErr => convertDiagnosticRelatedInformation(rErr, fileNameToUri, getTextDocument))
30
+ .filter((v) => !!v);
31
+ }
32
+ if (diag.reportsUnnecessary) {
33
+ if (diagnostic.tags === undefined)
34
+ diagnostic.tags = [];
35
+ diagnostic.tags.push(1);
36
+ }
37
+ if (diag.reportsDeprecated) {
38
+ if (diagnostic.tags === undefined)
39
+ diagnostic.tags = [];
40
+ diagnostic.tags.push(2);
41
+ }
42
+ return diagnostic;
43
+ }
44
+ exports.convertDiagnostic = convertDiagnostic;
45
+ function convertDiagnosticRelatedInformation(diag, fileNameToUri, getTextDocument) {
46
+ if (diag.start === undefined)
47
+ return;
48
+ if (diag.length === undefined)
49
+ return;
50
+ let document;
51
+ if (diag.file) {
52
+ document = getTextDocument(fileNameToUri(diag.file.fileName));
53
+ }
54
+ if (!document)
55
+ return;
56
+ const diagnostic = {
57
+ location: {
58
+ uri: document.uri,
59
+ range: {
60
+ start: document.positionAt(diag.start),
61
+ end: document.positionAt(diag.start + diag.length),
62
+ },
63
+ },
64
+ message: getMessageText(diag),
65
+ };
66
+ return diagnostic;
67
+ }
68
+ function convertDiagnosticCategory(input) {
69
+ switch (input) {
70
+ case 0: return 2;
71
+ case 1: return 1;
72
+ case 2: return 4;
73
+ case 3: return 3;
74
+ }
75
+ return 1;
76
+ }
77
+ function getMessageText(diag, level = 0) {
78
+ let messageText = ' '.repeat(level);
79
+ if (typeof diag.messageText === 'string') {
80
+ messageText += diag.messageText;
81
+ }
82
+ else {
83
+ messageText += diag.messageText.messageText;
84
+ if (diag.messageText.next) {
85
+ for (const info of diag.messageText.next) {
86
+ messageText += '\n' + getMessageText(info, level + 1);
87
+ }
88
+ }
89
+ }
90
+ return messageText;
91
+ }
92
+ // completion resolve
93
+ function applyCompletionEntryDetails(ts, item, data, document, fileNameToUri, getTextDocument) {
94
+ const { sourceDisplay } = data;
95
+ if (sourceDisplay) {
96
+ item.labelDetails ??= {};
97
+ item.labelDetails.description = ts.displayPartsToString(sourceDisplay);
98
+ }
99
+ const detailTexts = [];
100
+ if (data.codeActions) {
101
+ item.additionalTextEdits ??= [];
102
+ for (const action of data.codeActions) {
103
+ detailTexts.push(action.description);
104
+ for (const changes of action.changes) {
105
+ const ranges = changes.textChanges.map(change => convertTextSpan(change.span, document));
106
+ ranges.forEach((range, index) => {
107
+ item.additionalTextEdits?.push({ range, newText: changes.textChanges[index].newText });
108
+ });
109
+ }
110
+ }
111
+ }
112
+ if (data.displayParts) {
113
+ detailTexts.push(previewer.plainWithLinks(data.displayParts, fileNameToUri, getTextDocument));
114
+ }
115
+ if (detailTexts.length) {
116
+ item.detail = detailTexts.join('\n');
117
+ }
118
+ item.documentation = {
119
+ kind: 'markdown',
120
+ value: previewer.markdownDocumentation(data.documentation, data.tags, fileNameToUri, getTextDocument),
121
+ };
122
+ if (data) {
123
+ handleKindModifiers(item, data);
124
+ }
125
+ }
126
+ exports.applyCompletionEntryDetails = applyCompletionEntryDetails;
127
+ // completion
128
+ function convertCompletionInfo(ts, completionContext, document, position, createData) {
129
+ const lt_320 = semver.lt(ts.version, '3.2.0');
130
+ const gte_300 = semver.gte(ts.version, '3.0.0');
131
+ const wordRange = completionContext.optionalReplacementSpan
132
+ ? convertTextSpan(completionContext.optionalReplacementSpan, document)
133
+ : undefined;
134
+ const line = getLineText(document, position.line);
135
+ const dotAccessorContext = getDotAccessorContext(document);
136
+ const entries = completionContext.entries
137
+ .map(tsEntry => ({
138
+ ...convertCompletionEntry(tsEntry, document),
139
+ data: createData(tsEntry),
140
+ }));
141
+ return {
142
+ isIncomplete: !!completionContext.isIncomplete,
143
+ items: entries,
144
+ };
145
+ function convertCompletionEntry(tsEntry, document) {
146
+ const item = { label: tsEntry.name };
147
+ item.kind = convertCompletionItemKind(tsEntry.kind);
148
+ if (tsEntry.source && tsEntry.hasAction) {
149
+ // De-prioritize auto-imports
150
+ // https://github.com/microsoft/vscode/issues/40311
151
+ item.sortText = '\uffff' + tsEntry.sortText;
152
+ }
153
+ else {
154
+ item.sortText = tsEntry.sortText;
155
+ }
156
+ const { sourceDisplay, isSnippet, labelDetails } = tsEntry;
157
+ if (sourceDisplay) {
158
+ item.labelDetails ??= {};
159
+ item.labelDetails.description = ts.displayPartsToString(sourceDisplay);
160
+ }
161
+ if (labelDetails) {
162
+ item.labelDetails ??= {};
163
+ Object.assign(item.labelDetails, labelDetails);
164
+ }
165
+ item.preselect = tsEntry.isRecommended;
166
+ let range = getRangeFromReplacementSpan(tsEntry, document);
167
+ item.commitCharacters = getCommitCharacters(tsEntry, {
168
+ isNewIdentifierLocation: completionContext.isNewIdentifierLocation,
169
+ isInValidCommitCharacterContext: isInValidCommitCharacterContext(document, position),
170
+ enableCallCompletions: true, // TODO: suggest.completeFunctionCalls
171
+ });
172
+ item.insertText = tsEntry.insertText;
173
+ item.insertTextFormat = isSnippet ? 2 : 1;
174
+ item.filterText = getFilterText(tsEntry, wordRange, line, tsEntry.insertText);
175
+ if (completionContext?.isMemberCompletion && dotAccessorContext && !isSnippet) {
176
+ item.filterText = dotAccessorContext.text + (item.insertText || item.label);
177
+ if (!range) {
178
+ const replacementRange = wordRange;
179
+ if (replacementRange) {
180
+ range = {
181
+ inserting: dotAccessorContext.range,
182
+ replacing: rangeUnion(dotAccessorContext.range, replacementRange),
183
+ };
184
+ }
185
+ else {
186
+ range = dotAccessorContext.range;
187
+ }
188
+ item.insertText = item.filterText;
189
+ }
190
+ }
191
+ handleKindModifiers(item, tsEntry);
192
+ if (!range && wordRange) {
193
+ range = {
194
+ inserting: { start: wordRange.start, end: position },
195
+ replacing: wordRange,
196
+ };
197
+ }
198
+ if (range) {
199
+ if ('start' in range) {
200
+ item.textEdit = {
201
+ range,
202
+ newText: item.insertText || item.label,
203
+ };
204
+ }
205
+ else {
206
+ item.textEdit = {
207
+ insert: range.inserting,
208
+ replace: range.replacing,
209
+ newText: item.insertText || item.label,
210
+ };
211
+ }
212
+ }
213
+ return item;
214
+ }
215
+ function getDotAccessorContext(document) {
216
+ let dotAccessorContext;
217
+ if (gte_300) {
218
+ if (!completionContext)
219
+ return;
220
+ const isMemberCompletion = completionContext.isMemberCompletion;
221
+ if (isMemberCompletion) {
222
+ const dotMatch = line.slice(0, position.character).match(/\??\.\s*$/) || undefined;
223
+ if (dotMatch) {
224
+ const range = {
225
+ start: { line: position.line, character: position.character - dotMatch[0].length },
226
+ end: position,
227
+ };
228
+ const text = document.getText(range);
229
+ dotAccessorContext = { range, text };
230
+ }
231
+ }
232
+ }
233
+ return dotAccessorContext;
234
+ }
235
+ // from vscode typescript
236
+ function getRangeFromReplacementSpan(tsEntry, document) {
237
+ if (!tsEntry.replacementSpan) {
238
+ return;
239
+ }
240
+ let replaceRange = {
241
+ start: document.positionAt(tsEntry.replacementSpan.start),
242
+ end: document.positionAt(tsEntry.replacementSpan.start + tsEntry.replacementSpan.length),
243
+ };
244
+ // Make sure we only replace a single line at most
245
+ if (replaceRange.start.line !== replaceRange.end.line) {
246
+ replaceRange = {
247
+ start: {
248
+ line: replaceRange.start.line,
249
+ character: replaceRange.start.character,
250
+ },
251
+ end: {
252
+ line: replaceRange.start.line,
253
+ character: document.positionAt(document.offsetAt({ line: replaceRange.start.line + 1, character: 0 }) - 1).character,
254
+ },
255
+ };
256
+ }
257
+ // If TS returns an explicit replacement range, we should use it for both types of completion
258
+ return {
259
+ inserting: replaceRange,
260
+ replacing: replaceRange,
261
+ };
262
+ }
263
+ function getFilterText(tsEntry, wordRange, line, insertText) {
264
+ // Handle private field completions
265
+ if (tsEntry.name.startsWith('#')) {
266
+ const wordStart = wordRange ? line.charAt(wordRange.start.character) : undefined;
267
+ if (insertText) {
268
+ if (insertText.startsWith('this.#')) {
269
+ return wordStart === '#' ? insertText : insertText.replace(/^this\.#/, '');
270
+ }
271
+ else {
272
+ return insertText;
273
+ }
274
+ }
275
+ else {
276
+ return wordStart === '#' ? undefined : tsEntry.name.replace(/^#/, '');
277
+ }
278
+ }
279
+ // For `this.` completions, generally don't set the filter text since we don't want them to be overly prioritized. #74164
280
+ if (insertText?.startsWith('this.')) {
281
+ return undefined;
282
+ }
283
+ // Handle the case:
284
+ // ```
285
+ // const xyz = { 'ab c': 1 };
286
+ // xyz.ab|
287
+ // ```
288
+ // In which case we want to insert a bracket accessor but should use `.abc` as the filter text instead of
289
+ // the bracketed insert text.
290
+ else if (insertText?.startsWith('[')) {
291
+ return insertText.replace(/^\[['"](.+)[['"]\]$/, '.$1');
292
+ }
293
+ // In all other cases, fallback to using the insertText
294
+ return insertText;
295
+ }
296
+ function getCommitCharacters(entry, context) {
297
+ if (entry.kind === PConst.Kind.warning) { // Ambient JS word based suggestion
298
+ return undefined;
299
+ }
300
+ if (context.isNewIdentifierLocation || !context.isInValidCommitCharacterContext) {
301
+ return undefined;
302
+ }
303
+ const commitCharacters = ['.', ',', ';'];
304
+ if (context.enableCallCompletions) {
305
+ commitCharacters.push('(');
306
+ }
307
+ return commitCharacters;
308
+ }
309
+ function isInValidCommitCharacterContext(document, position) {
310
+ if (lt_320) {
311
+ // Workaround for https://github.com/microsoft/TypeScript/issues/27742
312
+ // Only enable dot completions when the previous character is not a dot preceded by whitespace.
313
+ // Prevents incorrectly completing while typing spread operators.
314
+ if (position.character > 1) {
315
+ const preText = document.getText({
316
+ start: { line: position.line, character: 0 },
317
+ end: position,
318
+ });
319
+ return preText.match(/(\s|^)\.$/ig) === null;
320
+ }
321
+ }
322
+ return true;
323
+ }
324
+ }
325
+ exports.convertCompletionInfo = convertCompletionInfo;
326
+ function convertCompletionItemKind(kind) {
327
+ switch (kind) {
328
+ case PConst.Kind.primitiveType:
329
+ case PConst.Kind.keyword:
330
+ return 14;
331
+ case PConst.Kind.const:
332
+ case PConst.Kind.let:
333
+ case PConst.Kind.variable:
334
+ case PConst.Kind.localVariable:
335
+ case PConst.Kind.alias:
336
+ case PConst.Kind.parameter:
337
+ return 6;
338
+ case PConst.Kind.memberVariable:
339
+ case PConst.Kind.memberGetAccessor:
340
+ case PConst.Kind.memberSetAccessor:
341
+ return 5;
342
+ case PConst.Kind.function:
343
+ case PConst.Kind.localFunction:
344
+ return 3;
345
+ case PConst.Kind.method:
346
+ case PConst.Kind.constructSignature:
347
+ case PConst.Kind.callSignature:
348
+ case PConst.Kind.indexSignature:
349
+ return 2;
350
+ case PConst.Kind.enum:
351
+ return 13;
352
+ case PConst.Kind.enumMember:
353
+ return 20;
354
+ case PConst.Kind.module:
355
+ case PConst.Kind.externalModuleName:
356
+ return 9;
357
+ case PConst.Kind.class:
358
+ case PConst.Kind.type:
359
+ return 7;
360
+ case PConst.Kind.interface:
361
+ return 8;
362
+ case PConst.Kind.warning:
363
+ return 1;
364
+ case PConst.Kind.script:
365
+ return 17;
366
+ case PConst.Kind.directory:
367
+ return 19;
368
+ case PConst.Kind.string:
369
+ return 21;
370
+ default:
371
+ return 10;
372
+ }
373
+ }
374
+ function handleKindModifiers(item, tsEntry) {
375
+ if (tsEntry.kindModifiers) {
376
+ const kindModifiers = (0, modifiers_1.parseKindModifier)(tsEntry.kindModifiers);
377
+ if (kindModifiers.has(PConst.KindModifiers.optional)) {
378
+ if (!item.insertText) {
379
+ item.insertText = item.label;
380
+ }
381
+ if (!item.filterText) {
382
+ item.filterText = item.label;
383
+ }
384
+ item.label += '?';
385
+ }
386
+ if (kindModifiers.has(PConst.KindModifiers.deprecated)) {
387
+ item.tags = [1];
388
+ }
389
+ if (kindModifiers.has(PConst.KindModifiers.color)) {
390
+ item.kind = 16;
391
+ }
392
+ if (tsEntry.kind === PConst.Kind.script) {
393
+ for (const extModifier of PConst.KindModifiers.fileExtensionKindModifiers) {
394
+ if (kindModifiers.has(extModifier)) {
395
+ if (tsEntry.name.toLowerCase().endsWith(extModifier)) {
396
+ item.detail = tsEntry.name;
397
+ }
398
+ else {
399
+ item.detail = tsEntry.name + extModifier;
400
+ }
401
+ break;
402
+ }
403
+ }
404
+ }
405
+ }
406
+ }
407
+ function rangeUnion(a, b) {
408
+ const start = (a.start.line < b.start.line || (a.start.line === b.start.line && a.start.character < b.start.character)) ? a.start : b.start;
409
+ const end = (a.end.line > b.end.line || (a.end.line === b.end.line && a.end.character > b.end.character)) ? a.end : b.end;
410
+ return { start, end };
411
+ }
412
+ function getLineText(document, line) {
413
+ const endOffset = document.offsetAt({ line: line + 1, character: 0 });
414
+ const end = document.positionAt(endOffset);
415
+ const text = document.getText({
416
+ start: { line: line, character: 0 },
417
+ end: end.line === line ? end : document.positionAt(endOffset - 1),
418
+ });
419
+ return text;
420
+ }
421
+ exports.getLineText = getLineText;
422
+ // workspaceSymbol
423
+ function convertNavigateToItem(item, document) {
424
+ const info = {
425
+ name: getLabel(item),
426
+ kind: convertScriptElementKind(item.kind),
427
+ location: {
428
+ uri: document.uri,
429
+ range: convertTextSpan(item.textSpan, document),
430
+ },
431
+ };
432
+ const kindModifiers = item.kindModifiers ? (0, modifiers_1.parseKindModifier)(item.kindModifiers) : undefined;
433
+ if (kindModifiers?.has(PConst.KindModifiers.deprecated)) {
434
+ info.tags = [1];
435
+ }
436
+ return info;
437
+ }
438
+ exports.convertNavigateToItem = convertNavigateToItem;
439
+ function getLabel(item) {
440
+ const label = item.name;
441
+ if (item.kind === 'method' || item.kind === 'function') {
442
+ return label + '()';
443
+ }
444
+ return label;
445
+ }
446
+ function convertScriptElementKind(kind) {
447
+ switch (kind) {
448
+ case PConst.Kind.method: return 6;
449
+ case PConst.Kind.enum: return 10;
450
+ case PConst.Kind.enumMember: return 22;
451
+ case PConst.Kind.function: return 12;
452
+ case PConst.Kind.class: return 5;
453
+ case PConst.Kind.interface: return 11;
454
+ case PConst.Kind.type: return 5;
455
+ case PConst.Kind.memberVariable: return 8;
456
+ case PConst.Kind.memberGetAccessor: return 8;
457
+ case PConst.Kind.memberSetAccessor: return 8;
458
+ case PConst.Kind.variable: return 13;
459
+ default: return 13;
460
+ }
461
+ }
462
+ // inlayHints
463
+ function convertInlayHint(hint, document) {
464
+ const result = {
465
+ position: document.positionAt(hint.position),
466
+ label: hint.text,
467
+ kind: hint.kind === 'Type' ? 1
468
+ : hint.kind === 'Parameter' ? 2
469
+ : undefined,
470
+ };
471
+ result.paddingLeft = hint.whitespaceBefore;
472
+ result.paddingRight = hint.whitespaceAfter;
473
+ return result;
474
+ }
475
+ exports.convertInlayHint = convertInlayHint;
476
+ // documentHighlight
477
+ function convertHighlightSpan(span, document) {
478
+ return {
479
+ kind: span.kind === 'writtenReference'
480
+ ? 3
481
+ : 2,
482
+ range: convertTextSpan(span.textSpan, document),
483
+ };
484
+ }
485
+ exports.convertHighlightSpan = convertHighlightSpan;
486
+ // selectionRanges
487
+ function convertSelectionRange(range, document) {
488
+ return {
489
+ parent: range.parent
490
+ ? convertSelectionRange(range.parent, document)
491
+ : undefined,
492
+ range: convertTextSpan(range.textSpan, document),
493
+ };
494
+ }
495
+ exports.convertSelectionRange = convertSelectionRange;
496
+ // rename
497
+ function convertFileTextChanges(changes, fileNameToUri, getTextDocument) {
498
+ const workspaceEdit = {};
499
+ for (const change of changes) {
500
+ if (!workspaceEdit.documentChanges) {
501
+ workspaceEdit.documentChanges = [];
502
+ }
503
+ const uri = fileNameToUri(change.fileName);
504
+ let doc = getTextDocument(uri);
505
+ if (change.isNewFile) {
506
+ workspaceEdit.documentChanges.push({ kind: 'create', uri });
507
+ }
508
+ if (!change.isNewFile)
509
+ continue;
510
+ workspaceEdit.documentChanges.push({
511
+ textDocument: {
512
+ uri,
513
+ version: null, // fix https://github.com/johnsoncodehk/volar/issues/2025
514
+ },
515
+ edits: change.textChanges.map(edit => convertTextChange(edit, doc)),
516
+ });
517
+ }
518
+ return workspaceEdit;
519
+ }
520
+ exports.convertFileTextChanges = convertFileTextChanges;
521
+ // rename file
522
+ function convertRenameLocations(newText, locations, fileNameToUri, getTextDocument) {
523
+ const workspaceEdit = {};
524
+ for (const location of locations) {
525
+ if (!workspaceEdit.changes) {
526
+ workspaceEdit.changes = {};
527
+ }
528
+ const uri = fileNameToUri(location.fileName);
529
+ const doc = getTextDocument(uri);
530
+ if (!workspaceEdit.changes[uri]) {
531
+ workspaceEdit.changes[uri] = [];
532
+ }
533
+ let _newText = newText;
534
+ if (location.prefixText)
535
+ _newText = location.prefixText + _newText;
536
+ if (location.suffixText)
537
+ _newText = _newText + location.suffixText;
538
+ workspaceEdit.changes[uri].push({
539
+ newText: _newText,
540
+ range: convertTextSpan(location.textSpan, doc),
541
+ });
542
+ }
543
+ return workspaceEdit;
544
+ }
545
+ exports.convertRenameLocations = convertRenameLocations;
546
+ // hover
547
+ function convertQuickInfo(ts, info, document, fileNameToUri, getTextDocument) {
548
+ const parts = [];
549
+ const displayString = ts.displayPartsToString(info.displayParts);
550
+ const documentation = previewer.markdownDocumentation(info.documentation ?? [], info.tags, fileNameToUri, getTextDocument);
551
+ if (displayString) {
552
+ parts.push(['```typescript', displayString, '```'].join('\n'));
553
+ }
554
+ if (documentation) {
555
+ parts.push(documentation);
556
+ }
557
+ const markdown = {
558
+ kind: 'markdown',
559
+ value: parts.join('\n\n'),
560
+ };
561
+ return {
562
+ contents: markdown,
563
+ range: convertTextSpan(info.textSpan, document),
564
+ };
565
+ }
566
+ exports.convertQuickInfo = convertQuickInfo;
567
+ // documentSymbol
568
+ function convertNavTree(item, document) {
569
+ if (!shouldIncludeEntry(item)) {
570
+ return [];
571
+ }
572
+ let remain = item.childItems ?? [];
573
+ return item.spans.map(span => {
574
+ const childItems = [];
575
+ remain = remain.filter(child => {
576
+ const childStart = child.spans[0].start;
577
+ const childEnd = child.spans[child.spans.length - 1].start + child.spans[child.spans.length - 1].length;
578
+ if (childStart >= span.start && childEnd <= span.start + span.length) {
579
+ childItems.push(child);
580
+ return false;
581
+ }
582
+ return true;
583
+ });
584
+ const nameSpan = item.spans.length === 1
585
+ ? (item.nameSpan ?? span)
586
+ : span;
587
+ const fullRange = {
588
+ start: Math.min(span.start, nameSpan.start),
589
+ end: Math.max(span.start + span.length, nameSpan.start + nameSpan.length),
590
+ };
591
+ const symbol = {
592
+ name: item.text,
593
+ kind: getSymbolKind(item.kind),
594
+ range: convertTextSpan({
595
+ start: fullRange.start,
596
+ length: fullRange.end - fullRange.start,
597
+ }, document),
598
+ selectionRange: convertTextSpan(nameSpan, document),
599
+ children: childItems.map(item => convertNavTree(item, document)).flat(),
600
+ };
601
+ const kindModifiers = (0, modifiers_1.parseKindModifier)(item.kindModifiers);
602
+ if (kindModifiers.has(PConst.KindModifiers.deprecated)) {
603
+ symbol.deprecated = true;
604
+ symbol.tags ??= [];
605
+ symbol.tags.push(1);
606
+ }
607
+ return symbol;
608
+ });
609
+ }
610
+ exports.convertNavTree = convertNavTree;
611
+ const getSymbolKind = (kind) => {
612
+ switch (kind) {
613
+ case PConst.Kind.module: return 2;
614
+ case PConst.Kind.class: return 5;
615
+ case PConst.Kind.enum: return 10;
616
+ case PConst.Kind.interface: return 11;
617
+ case PConst.Kind.method: return 6;
618
+ case PConst.Kind.memberVariable: return 7;
619
+ case PConst.Kind.memberGetAccessor: return 7;
620
+ case PConst.Kind.memberSetAccessor: return 7;
621
+ case PConst.Kind.variable: return 13;
622
+ case PConst.Kind.const: return 13;
623
+ case PConst.Kind.localVariable: return 13;
624
+ case PConst.Kind.function: return 12;
625
+ case PConst.Kind.localFunction: return 12;
626
+ case PConst.Kind.constructSignature: return 9;
627
+ case PConst.Kind.constructorImplementation: return 9;
628
+ }
629
+ return 13;
630
+ };
631
+ function shouldIncludeEntry(item) {
632
+ if (item.kind === PConst.Kind.alias) {
633
+ return false;
634
+ }
635
+ return !!(item.text && item.text !== '<function>' && item.text !== '<class>');
636
+ }
637
+ // foldingRanges
638
+ function convertOutliningSpan(outliningSpan, document) {
639
+ const start = document.positionAt(outliningSpan.textSpan.start);
640
+ const end = adjustFoldingEnd(start, document.positionAt(outliningSpan.textSpan.start + outliningSpan.textSpan.length), document);
641
+ return {
642
+ startLine: start.line,
643
+ endLine: end.line,
644
+ startCharacter: start.character,
645
+ endCharacter: end.character,
646
+ kind: convertOutliningSpanKind(outliningSpan.kind),
647
+ };
648
+ }
649
+ exports.convertOutliningSpan = convertOutliningSpan;
650
+ function convertOutliningSpanKind(kind) {
651
+ switch (kind) {
652
+ case 'comment': return 'comment';
653
+ case 'region': return 'region';
654
+ case 'imports': return 'imports';
655
+ case 'code':
656
+ default: return undefined;
657
+ }
658
+ }
659
+ exports.convertOutliningSpanKind = convertOutliningSpanKind;
660
+ const foldEndPairCharacters = ['}', ']', ')', '`'];
661
+ // https://github.com/microsoft/vscode/blob/bed61166fb604e519e82e4d1d1ed839bc45d65f8/extensions/typescript-language-features/src/languageFeatures/folding.ts#L61-L73
662
+ function adjustFoldingEnd(start, end, document) {
663
+ // workaround for #47240
664
+ if (end.character > 0) {
665
+ const foldEndCharacter = document.getText({
666
+ start: { line: end.line, character: end.character - 1 },
667
+ end,
668
+ });
669
+ if (foldEndPairCharacters.includes(foldEndCharacter)) {
670
+ const endOffset = Math.max(document.offsetAt({ line: end.line, character: 0 }) - 1, document.offsetAt(start));
671
+ return document.positionAt(endOffset);
672
+ }
673
+ }
674
+ return end;
675
+ }
676
+ // formatting
677
+ function convertTextChange(edit, document) {
678
+ return {
679
+ range: convertTextSpan(edit.span, document),
680
+ newText: edit.newText,
681
+ };
682
+ }
683
+ exports.convertTextChange = convertTextChange;
684
+ // callHierarchy
685
+ function convertCallHierarchyIncomingCall(item, ctx) {
686
+ const uri = ctx.fileNameToUri(item.from.file);
687
+ const document = ctx.getTextDocument(uri);
688
+ return {
689
+ from: convertCallHierarchyItem(item.from, ctx),
690
+ fromRanges: item.fromSpans
691
+ .map(span => convertTextSpan(span, document))
692
+ .filter(shared_1.notEmpty),
693
+ };
694
+ }
695
+ exports.convertCallHierarchyIncomingCall = convertCallHierarchyIncomingCall;
696
+ function convertCallHierarchyOutgoingCall(item, fromDocument, ctx) {
697
+ return {
698
+ to: convertCallHierarchyItem(item.to, ctx),
699
+ fromRanges: item.fromSpans
700
+ .map(span => convertTextSpan(span, fromDocument))
701
+ .filter(shared_1.notEmpty),
702
+ };
703
+ }
704
+ exports.convertCallHierarchyOutgoingCall = convertCallHierarchyOutgoingCall;
705
+ function convertCallHierarchyItem(item, ctx) {
706
+ const rootPath = ctx.languageService.getProgram()?.getCompilerOptions().rootDir ?? '';
707
+ const uri = ctx.fileNameToUri(item.file);
708
+ const document = ctx.getTextDocument(uri);
709
+ const useFileName = isSourceFileItem(item);
710
+ const name = useFileName ? path.basename(item.file) : item.name;
711
+ const detail = useFileName ? path.relative(rootPath, path.dirname(item.file)) : item.containerName ?? '';
712
+ const result = {
713
+ kind: typeConverters.SymbolKind.fromProtocolScriptElementKind(item.kind),
714
+ name,
715
+ detail,
716
+ uri,
717
+ range: convertTextSpan(item.span, document),
718
+ selectionRange: convertTextSpan(item.selectionSpan, document),
719
+ };
720
+ const kindModifiers = item.kindModifiers ? (0, modifiers_1.parseKindModifier)(item.kindModifiers) : undefined;
721
+ if (kindModifiers?.has(PConst.KindModifiers.deprecated)) {
722
+ result.tags = [1];
723
+ }
724
+ return result;
725
+ }
726
+ exports.convertCallHierarchyItem = convertCallHierarchyItem;
727
+ function isSourceFileItem(item) {
728
+ return item.kind === PConst.Kind.script || item.kind === PConst.Kind.module && item.selectionSpan.start === 0;
729
+ }
730
+ // base
731
+ function convertDocumentSpanToLocation(documentSpan, ctx) {
732
+ const uri = ctx.fileNameToUri(documentSpan.fileName);
733
+ const document = ctx.getTextDocument(uri);
734
+ const range = convertTextSpan(documentSpan.textSpan, document);
735
+ return {
736
+ uri,
737
+ range,
738
+ };
739
+ }
740
+ exports.convertDocumentSpanToLocation = convertDocumentSpanToLocation;
741
+ function convertDefinitionInfoAndBoundSpan(info, document, ctx) {
742
+ if (!info.definitions) {
743
+ return [];
744
+ }
745
+ const originSelectionRange = convertTextSpan(info.textSpan, document);
746
+ return info.definitions
747
+ .map(entry => {
748
+ const link = convertDocumentSpantoLocationLink(entry, ctx);
749
+ if (link) {
750
+ link.originSelectionRange ??= originSelectionRange;
751
+ return link;
752
+ }
753
+ })
754
+ .filter(shared_1.notEmpty);
755
+ }
756
+ exports.convertDefinitionInfoAndBoundSpan = convertDefinitionInfoAndBoundSpan;
757
+ function convertDocumentSpantoLocationLink(documentSpan, ctx) {
758
+ const targetUri = ctx.fileNameToUri(documentSpan.fileName);
759
+ const document = ctx.getTextDocument(targetUri);
760
+ const targetSelectionRange = convertTextSpan(documentSpan.textSpan, document);
761
+ const targetRange = documentSpan.contextSpan
762
+ ? convertTextSpan(documentSpan.contextSpan, document)
763
+ : targetSelectionRange;
764
+ const originSelectionRange = documentSpan.originalTextSpan
765
+ ? convertTextSpan(documentSpan.originalTextSpan, document)
766
+ : undefined;
767
+ return {
768
+ targetUri,
769
+ targetRange,
770
+ targetSelectionRange,
771
+ originSelectionRange,
772
+ };
773
+ }
774
+ exports.convertDocumentSpantoLocationLink = convertDocumentSpantoLocationLink;
775
+ function convertTextSpan(textSpan, document) {
776
+ return {
777
+ start: document.positionAt(textSpan.start),
778
+ end: document.positionAt(textSpan.start + textSpan.length),
779
+ };
780
+ }
781
+ exports.convertTextSpan = convertTextSpan;
782
+ //# sourceMappingURL=lspConverters.js.map