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.
- package/index.d.ts +4 -17
- package/index.js +12 -545
- package/lib/configs/getFormatCodeSettings.d.ts +2 -3
- package/lib/configs/getUserPreferences.d.ts +1 -1
- package/lib/plugins/directiveComment.d.ts +3 -0
- package/lib/plugins/directiveComment.js +65 -0
- package/lib/plugins/docCommentTemplate.d.ts +3 -0
- package/lib/{features/completions/jsDoc.js → plugins/docCommentTemplate.js} +42 -30
- package/lib/plugins/semantic.d.ts +23 -0
- package/lib/plugins/semantic.js +706 -0
- package/lib/plugins/syntactic.d.ts +7 -0
- package/lib/plugins/syntactic.js +92 -0
- package/lib/{features → semanticFeatures}/codeAction.d.ts +3 -2
- package/lib/{features → semanticFeatures}/codeAction.js +14 -17
- package/lib/{features → semanticFeatures}/codeActionResolve.d.ts +1 -1
- package/lib/{features → semanticFeatures}/codeActionResolve.js +7 -7
- package/lib/semanticFeatures/semanticTokens.d.ts +5 -0
- package/lib/{features → semanticFeatures}/semanticTokens.js +4 -8
- package/lib/{types.d.ts → semanticFeatures/types.d.ts} +1 -2
- package/lib/shared.d.ts +1 -0
- package/lib/shared.js +5 -1
- package/lib/syntacticLanguageService.d.ts +7 -0
- package/lib/syntacticLanguageService.js +38 -0
- package/lib/utils/lspConverters.d.ts +27 -0
- package/lib/utils/lspConverters.js +782 -0
- package/lib/utils/previewer.d.ts +5 -11
- package/lib/utils/previewer.js +30 -35
- package/package.json +5 -6
- package/lib/features/callHierarchy.d.ts +0 -8
- package/lib/features/callHierarchy.js +0 -102
- package/lib/features/completions/basic.d.ts +0 -17
- package/lib/features/completions/basic.js +0 -326
- package/lib/features/completions/directiveComment.d.ts +0 -4
- package/lib/features/completions/directiveComment.js +0 -54
- package/lib/features/completions/jsDoc.d.ts +0 -4
- package/lib/features/completions/resolve.d.ts +0 -6
- package/lib/features/completions/resolve.js +0 -146
- package/lib/features/definition.d.ts +0 -4
- package/lib/features/definition.js +0 -20
- package/lib/features/diagnostics.d.ts +0 -11
- package/lib/features/diagnostics.js +0 -120
- package/lib/features/documentHighlight.d.ts +0 -4
- package/lib/features/documentHighlight.js +0 -32
- package/lib/features/documentSymbol.d.ts +0 -4
- package/lib/features/documentSymbol.js +0 -94
- package/lib/features/fileReferences.d.ts +0 -4
- package/lib/features/fileReferences.js +0 -19
- package/lib/features/fileRename.d.ts +0 -4
- package/lib/features/fileRename.js +0 -25
- package/lib/features/foldingRanges.d.ts +0 -4
- package/lib/features/foldingRanges.js +0 -55
- package/lib/features/formatting.d.ts +0 -8
- package/lib/features/formatting.js +0 -55
- package/lib/features/hover.d.ts +0 -4
- package/lib/features/hover.js +0 -43
- package/lib/features/implementation.d.ts +0 -4
- package/lib/features/implementation.js +0 -20
- package/lib/features/inlayHints.d.ts +0 -4
- package/lib/features/inlayHints.js +0 -34
- package/lib/features/prepareRename.d.ts +0 -9
- package/lib/features/prepareRename.js +0 -27
- package/lib/features/references.d.ts +0 -4
- package/lib/features/references.js +0 -35
- package/lib/features/rename.d.ts +0 -6
- package/lib/features/rename.js +0 -116
- package/lib/features/selectionRanges.d.ts +0 -4
- package/lib/features/selectionRanges.js +0 -32
- package/lib/features/semanticTokens.d.ts +0 -4
- package/lib/features/signatureHelp.d.ts +0 -4
- package/lib/features/signatureHelp.js +0 -63
- package/lib/features/typeDefinition.d.ts +0 -4
- package/lib/features/typeDefinition.js +0 -20
- package/lib/features/workspaceSymbol.d.ts +0 -4
- package/lib/features/workspaceSymbol.js +0 -63
- package/lib/utils/transforms.d.ts +0 -15
- package/lib/utils/transforms.js +0 -85
- /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
|