@volar/typescript 2.2.0-alpha.0 → 2.2.0-alpha.2

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.
@@ -0,0 +1,2 @@
1
+ import type * as ts from 'typescript';
2
+ export declare function getDocumentRegistry(ts: typeof import('typescript'), useCaseSensitiveFileNames: boolean, currentDirectory: string): ts.DocumentRegistry;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDocumentRegistry = void 0;
4
+ const documentRegistries = [];
5
+ function getDocumentRegistry(ts, useCaseSensitiveFileNames, currentDirectory) {
6
+ let documentRegistry = documentRegistries.find(item => item[0] === useCaseSensitiveFileNames && item[1] === currentDirectory)?.[2];
7
+ if (!documentRegistry) {
8
+ documentRegistry = ts.createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory);
9
+ documentRegistries.push([useCaseSensitiveFileNames, currentDirectory, documentRegistry]);
10
+ }
11
+ return documentRegistry;
12
+ }
13
+ exports.getDocumentRegistry = getDocumentRegistry;
14
+ //# sourceMappingURL=documentRegistry.js.map
@@ -29,19 +29,92 @@ function decorateLanguageService(language, languageService) {
29
29
  }
30
30
  };
31
31
  // methods
32
- const { findReferences, findRenameLocations, getCompletionEntryDetails, getCompletionsAtPosition, getDefinitionAndBoundSpan, getDefinitionAtPosition, getFileReferences, getImplementationAtPosition, getQuickInfoAtPosition, getReferencesAtPosition, getSemanticDiagnostics, getSyntacticDiagnostics, getSuggestionDiagnostics, getTypeDefinitionAtPosition, getEncodedSemanticClassifications, getDocumentHighlights, getApplicableRefactors, getEditsForRefactor, getRenameInfo, getCodeFixesAtPosition, prepareCallHierarchy, provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls, provideInlayHints, organizeImports, } = languageService;
32
+ const { findReferences, findRenameLocations, getCompletionEntryDetails, getCompletionsAtPosition, getDefinitionAndBoundSpan, getDefinitionAtPosition, getFileReferences, getFormattingEditsForDocument, getFormattingEditsForRange, getFormattingEditsAfterKeystroke, getImplementationAtPosition, getLinkedEditingRangeAtPosition, getQuickInfoAtPosition, getReferencesAtPosition, getSemanticDiagnostics, getSyntacticDiagnostics, getSuggestionDiagnostics, getTypeDefinitionAtPosition, getEncodedSemanticClassifications, getDocumentHighlights, getApplicableRefactors, getEditsForFileRename, getEditsForRefactor, getRenameInfo, getCodeFixesAtPosition, prepareCallHierarchy, provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls, provideInlayHints, organizeImports, } = languageService;
33
+ languageService.getFormattingEditsForDocument = (fileName, options) => {
34
+ const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
35
+ if (serviceScript) {
36
+ if (!map.mappings.some(mapping => (0, language_core_1.isFormattingEnabled)(mapping.data))) {
37
+ return [];
38
+ }
39
+ const edits = getFormattingEditsForDocument(fileName, options);
40
+ return edits
41
+ .map(edit => (0, transform_1.transformTextChange)(sourceScript, map, edit, language_core_1.isFormattingEnabled))
42
+ .filter(utils_1.notEmpty);
43
+ }
44
+ else {
45
+ return getFormattingEditsForDocument(fileName, options);
46
+ }
47
+ };
48
+ languageService.getFormattingEditsForRange = (fileName, start, end, options) => {
49
+ const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
50
+ if (serviceScript) {
51
+ const generateStart = (0, transform_1.toGeneratedOffset)(sourceScript, map, start, language_core_1.isFormattingEnabled);
52
+ const generateEnd = (0, transform_1.toGeneratedOffset)(sourceScript, map, end, language_core_1.isFormattingEnabled);
53
+ if (generateStart !== undefined && generateEnd !== undefined) {
54
+ const edits = getFormattingEditsForRange(fileName, generateStart, generateEnd, options);
55
+ return edits
56
+ .map(edit => (0, transform_1.transformTextChange)(sourceScript, map, edit, language_core_1.isFormattingEnabled))
57
+ .filter(utils_1.notEmpty);
58
+ }
59
+ return [];
60
+ }
61
+ else {
62
+ return getFormattingEditsForRange(fileName, start, end, options);
63
+ }
64
+ };
65
+ languageService.getFormattingEditsAfterKeystroke = (fileName, position, key, options) => {
66
+ const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
67
+ if (serviceScript) {
68
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isFormattingEnabled);
69
+ if (generatePosition !== undefined) {
70
+ const edits = getFormattingEditsAfterKeystroke(fileName, generatePosition, key, options);
71
+ return edits
72
+ .map(edit => (0, transform_1.transformTextChange)(sourceScript, map, edit, language_core_1.isFormattingEnabled))
73
+ .filter(utils_1.notEmpty);
74
+ }
75
+ return [];
76
+ }
77
+ else {
78
+ return getFormattingEditsAfterKeystroke(fileName, position, key, options);
79
+ }
80
+ };
81
+ languageService.getEditsForFileRename = (oldFilePath, newFilePath, formatOptions, preferences) => {
82
+ const edits = getEditsForFileRename(oldFilePath, newFilePath, formatOptions, preferences);
83
+ return edits
84
+ .map(edit => (0, transform_1.transformFileTextChanges)(language, edit, language_core_1.isRenameEnabled))
85
+ .filter(utils_1.notEmpty);
86
+ };
87
+ languageService.getLinkedEditingRangeAtPosition = (fileName, position) => {
88
+ const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
89
+ if (serviceScript) {
90
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isLinkedEditingEnabled);
91
+ if (generatePosition !== undefined) {
92
+ const info = getLinkedEditingRangeAtPosition(fileName, generatePosition);
93
+ if (info) {
94
+ return {
95
+ ranges: info.ranges
96
+ .map(span => (0, transform_1.transformTextSpan)(sourceScript, map, span, language_core_1.isLinkedEditingEnabled))
97
+ .filter(utils_1.notEmpty),
98
+ wordPattern: info.wordPattern,
99
+ };
100
+ }
101
+ }
102
+ }
103
+ else {
104
+ return getLinkedEditingRangeAtPosition(fileName, position);
105
+ }
106
+ };
33
107
  languageService.prepareCallHierarchy = (fileName, position) => {
34
108
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
35
109
  if (serviceScript) {
36
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
37
- if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
38
- const item = prepareCallHierarchy(fileName, generateOffset + sourceScript.snapshot.getLength());
39
- if (Array.isArray(item)) {
40
- return item.map(item => (0, transform_1.transformCallHierarchyItem)(language, item, language_core_1.isCallHierarchyEnabled));
41
- }
42
- else if (item) {
43
- return (0, transform_1.transformCallHierarchyItem)(language, item, language_core_1.isCallHierarchyEnabled);
44
- }
110
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCallHierarchyEnabled);
111
+ if (generatePosition !== undefined) {
112
+ const item = prepareCallHierarchy(fileName, generatePosition);
113
+ if (Array.isArray(item)) {
114
+ return item.map(item => (0, transform_1.transformCallHierarchyItem)(language, item, language_core_1.isCallHierarchyEnabled));
115
+ }
116
+ else if (item) {
117
+ return (0, transform_1.transformCallHierarchyItem)(language, item, language_core_1.isCallHierarchyEnabled);
45
118
  }
46
119
  }
47
120
  }
@@ -53,10 +126,9 @@ function decorateLanguageService(language, languageService) {
53
126
  let calls = [];
54
127
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
55
128
  if (serviceScript) {
56
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
57
- if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
58
- calls = provideCallHierarchyIncomingCalls(fileName, generateOffset + sourceScript.snapshot.getLength());
59
- }
129
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCallHierarchyEnabled);
130
+ if (generatePosition !== undefined) {
131
+ calls = provideCallHierarchyIncomingCalls(fileName, generatePosition);
60
132
  }
61
133
  }
62
134
  else {
@@ -78,10 +150,9 @@ function decorateLanguageService(language, languageService) {
78
150
  let calls = [];
79
151
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
80
152
  if (serviceScript) {
81
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
82
- if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
83
- calls = provideCallHierarchyOutgoingCalls(fileName, generateOffset + sourceScript.snapshot.getLength());
84
- }
153
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCallHierarchyEnabled);
154
+ if (generatePosition !== undefined) {
155
+ calls = provideCallHierarchyOutgoingCalls(fileName, generatePosition);
85
156
  }
86
157
  }
87
158
  else {
@@ -91,7 +162,9 @@ function decorateLanguageService(language, languageService) {
91
162
  .map(call => {
92
163
  const to = (0, transform_1.transformCallHierarchyItem)(language, call.to, language_core_1.isCallHierarchyEnabled);
93
164
  const fromSpans = call.fromSpans
94
- .map(span => (0, transform_1.transformSpan)(language, fileName, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
165
+ .map(span => sourceScript
166
+ ? (0, transform_1.transformTextSpan)(sourceScript, map, span, language_core_1.isCallHierarchyEnabled)
167
+ : span)
95
168
  .filter(utils_1.notEmpty);
96
169
  return {
97
170
  to,
@@ -109,17 +182,16 @@ function decorateLanguageService(language, languageService) {
109
182
  languageService.getQuickInfoAtPosition = (fileName, position) => {
110
183
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
111
184
  if (serviceScript) {
112
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
113
- if ((0, language_core_1.isHoverEnabled)(mapping.data)) {
114
- const result = getQuickInfoAtPosition(fileName, generateOffset + sourceScript.snapshot.getLength());
115
- if (result) {
116
- const textSpan = (0, transform_1.transformSpan)(language, fileName, result.textSpan, language_core_1.isHoverEnabled)?.textSpan;
117
- if (textSpan) {
118
- return {
119
- ...result,
120
- textSpan,
121
- };
122
- }
185
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isHoverEnabled);
186
+ if (generatePosition !== undefined) {
187
+ const result = getQuickInfoAtPosition(fileName, generatePosition);
188
+ if (result) {
189
+ const textSpan = (0, transform_1.transformTextSpan)(sourceScript, map, result.textSpan, language_core_1.isHoverEnabled);
190
+ if (textSpan) {
191
+ return {
192
+ ...result,
193
+ textSpan,
194
+ };
123
195
  }
124
196
  }
125
197
  }
@@ -160,16 +232,15 @@ function decorateLanguageService(language, languageService) {
160
232
  languageService.getApplicableRefactors = (fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) => {
161
233
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
162
234
  if (serviceScript) {
163
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
164
- if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
165
- const por = typeof positionOrRange === 'number'
166
- ? generateOffset + sourceScript.snapshot.getLength()
167
- : {
168
- pos: generateOffset + sourceScript.snapshot.getLength(),
169
- end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceScript.snapshot.getLength(),
170
- };
171
- return getApplicableRefactors(fileName, por, preferences, triggerReason, kind, includeInteractiveActions);
172
- }
235
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos, language_core_1.isCodeActionsEnabled);
236
+ if (generatePosition !== undefined) {
237
+ const por = typeof positionOrRange === 'number'
238
+ ? generatePosition
239
+ : {
240
+ pos: generatePosition,
241
+ end: generatePosition + positionOrRange.end - positionOrRange.pos,
242
+ };
243
+ return getApplicableRefactors(fileName, por, preferences, triggerReason, kind, includeInteractiveActions);
173
244
  }
174
245
  return [];
175
246
  }
@@ -181,16 +252,17 @@ function decorateLanguageService(language, languageService) {
181
252
  let edits;
182
253
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
183
254
  if (serviceScript) {
184
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
185
- if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
186
- const por = typeof positionOrRange === 'number'
187
- ? generateOffset + sourceScript.snapshot.getLength()
188
- : {
189
- pos: generateOffset + sourceScript.snapshot.getLength(),
190
- end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceScript.snapshot.getLength(),
191
- };
192
- edits = getEditsForRefactor(fileName, formatOptions, por, refactorName, actionName, preferences);
193
- }
255
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, typeof positionOrRange === 'number'
256
+ ? positionOrRange
257
+ : positionOrRange.pos, language_core_1.isCodeActionsEnabled);
258
+ if (generatePosition !== undefined) {
259
+ const por = typeof positionOrRange === 'number'
260
+ ? generatePosition
261
+ : {
262
+ pos: generatePosition,
263
+ end: generatePosition + positionOrRange.end - positionOrRange.pos,
264
+ };
265
+ edits = getEditsForRefactor(fileName, formatOptions, por, refactorName, actionName, preferences);
194
266
  }
195
267
  }
196
268
  else {
@@ -206,20 +278,19 @@ function decorateLanguageService(language, languageService) {
206
278
  languageService.getRenameInfo = (fileName, position, options) => {
207
279
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
208
280
  if (serviceScript) {
209
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
210
- if ((0, language_core_1.isRenameEnabled)(mapping.data)) {
211
- const info = getRenameInfo(fileName, generateOffset + sourceScript.snapshot.getLength(), options);
212
- if (info.canRename) {
213
- const span = (0, transform_1.transformSpan)(language, fileName, info.triggerSpan, language_core_1.isRenameEnabled);
214
- if (span) {
215
- info.triggerSpan = span.textSpan;
216
- return info;
217
- }
218
- }
219
- else {
281
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isRenameEnabled);
282
+ if (generatePosition !== undefined) {
283
+ const info = getRenameInfo(fileName, generatePosition, options);
284
+ if (info.canRename) {
285
+ const span = (0, transform_1.transformTextSpan)(sourceScript, map, info.triggerSpan, language_core_1.isRenameEnabled);
286
+ if (span) {
287
+ info.triggerSpan = span;
220
288
  return info;
221
289
  }
222
290
  }
291
+ else {
292
+ return info;
293
+ }
223
294
  }
224
295
  return {
225
296
  canRename: false,
@@ -234,16 +305,10 @@ function decorateLanguageService(language, languageService) {
234
305
  let fixes = [];
235
306
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
236
307
  if (serviceScript) {
237
- for (const [generateStart, mapping] of map.getGeneratedOffsets(start)) {
238
- if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
239
- for (const [generateEnd, mapping] of map.getGeneratedOffsets(end)) {
240
- if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
241
- fixes = getCodeFixesAtPosition(fileName, generateStart + sourceScript.snapshot.getLength(), generateEnd + sourceScript.snapshot.getLength(), errorCodes, formatOptions, preferences);
242
- break;
243
- }
244
- }
245
- break;
246
- }
308
+ const generateStart = (0, transform_1.toGeneratedOffset)(sourceScript, map, start, language_core_1.isCodeActionsEnabled);
309
+ const generateEnd = (0, transform_1.toGeneratedOffset)(sourceScript, map, end, language_core_1.isCodeActionsEnabled);
310
+ if (generateStart !== undefined && generateEnd !== undefined) {
311
+ fixes = getCodeFixesAtPosition(fileName, generateStart, generateEnd, errorCodes, formatOptions, preferences);
247
312
  }
248
313
  }
249
314
  else {
@@ -261,32 +326,25 @@ function decorateLanguageService(language, languageService) {
261
326
  let start;
262
327
  let end;
263
328
  for (const mapping of map.mappings) {
329
+ // TODO reuse the logic from language service
264
330
  if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data) && mapping.sourceOffsets[0] >= span.start && mapping.sourceOffsets[0] <= span.start + span.length) {
265
331
  start ??= mapping.generatedOffsets[0];
266
- end ??= mapping.generatedOffsets[mapping.generatedOffsets.length - 1];
332
+ end ??= mapping.generatedOffsets[mapping.generatedOffsets.length - 1] + mapping.lengths[mapping.lengths.length - 1];
267
333
  start = Math.min(start, mapping.generatedOffsets[0]);
268
- end = Math.max(end, mapping.generatedOffsets[mapping.generatedOffsets.length - 1]);
334
+ end = Math.max(end, mapping.generatedOffsets[mapping.generatedOffsets.length - 1] + mapping.lengths[mapping.lengths.length - 1]);
269
335
  }
270
336
  }
271
- if (start === undefined || end === undefined) {
272
- start = 0;
273
- end = 0;
274
- }
337
+ start ??= 0;
338
+ end ??= sourceScript.snapshot.getLength();
275
339
  start += sourceScript.snapshot.getLength();
276
340
  end += sourceScript.snapshot.getLength();
277
341
  const result = getEncodedSemanticClassifications(fileName, { start, length: end - start }, format);
278
342
  const spans = [];
279
343
  for (let i = 0; i < result.spans.length; i += 3) {
280
- for (const [sourceStart, mapping] of map.getSourceOffsets(result.spans[i] - sourceScript.snapshot.getLength())) {
281
- if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
282
- for (const [sourceEnd, mapping] of map.getSourceOffsets(result.spans[i] + result.spans[i + 1] - sourceScript.snapshot.getLength())) {
283
- if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
284
- spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
285
- break;
286
- }
287
- }
288
- break;
289
- }
344
+ const sourceStart = (0, transform_1.toSourceOffset)(sourceScript, map, result.spans[i], language_core_1.isSemanticTokensEnabled);
345
+ const sourceEnd = (0, transform_1.toSourceOffset)(sourceScript, map, result.spans[i] + result.spans[i + 1], language_core_1.isSemanticTokensEnabled);
346
+ if (sourceStart !== undefined && sourceEnd !== undefined) {
347
+ spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
290
348
  }
291
349
  }
292
350
  result.spans = spans;
@@ -423,24 +481,29 @@ function decorateLanguageService(language, languageService) {
423
481
  if (serviceScript) {
424
482
  let mainResult;
425
483
  let additionalResults = [];
426
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
427
- if ((0, language_core_1.isCompletionEnabled)(mapping.data)) {
428
- const isAdditional = typeof mapping.data.completion === 'object' && mapping.data.completion.isAdditional;
429
- if (!isAdditional && mainResult) {
430
- continue;
484
+ let isAdditional;
485
+ const generatedOffset = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, data => {
486
+ if (!(0, language_core_1.isCompletionEnabled)(data)) {
487
+ return false;
488
+ }
489
+ isAdditional = typeof data.completion === 'object' && data.completion.isAdditional;
490
+ if (!isAdditional && mainResult) {
491
+ return false;
492
+ }
493
+ return true;
494
+ });
495
+ if (generatedOffset !== undefined) {
496
+ const result = getCompletionsAtPosition(fileName, generatedOffset, options, formattingSettings);
497
+ if (result) {
498
+ for (const entry of result.entries) {
499
+ entry.replacementSpan = entry.replacementSpan && (0, transform_1.transformTextSpan)(sourceScript, map, entry.replacementSpan, language_core_1.isCompletionEnabled);
431
500
  }
432
- const result = getCompletionsAtPosition(fileName, generateOffset + sourceScript.snapshot.getLength(), options, formattingSettings);
433
- if (result) {
434
- for (const entry of result.entries) {
435
- entry.replacementSpan = (0, transform_1.transformSpan)(language, fileName, entry.replacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
436
- }
437
- result.optionalReplacementSpan = (0, transform_1.transformSpan)(language, fileName, result.optionalReplacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
438
- if (isAdditional) {
439
- additionalResults.push(result);
440
- }
441
- else {
442
- mainResult = result;
443
- }
501
+ result.optionalReplacementSpan = result.optionalReplacementSpan && (0, transform_1.transformTextSpan)(sourceScript, map, result.optionalReplacementSpan, language_core_1.isCompletionEnabled);
502
+ if (isAdditional) {
503
+ additionalResults.push(result);
504
+ }
505
+ else {
506
+ mainResult = result;
444
507
  }
445
508
  }
446
509
  }
@@ -465,11 +528,9 @@ function decorateLanguageService(language, languageService) {
465
528
  let details;
466
529
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
467
530
  if (serviceScript) {
468
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
469
- if ((0, language_core_1.isCompletionEnabled)(mapping.data)) {
470
- details = getCompletionEntryDetails(fileName, generateOffset + sourceScript.snapshot.getLength(), entryName, formatOptions, source, preferences, data);
471
- break;
472
- }
531
+ const generatePosition = (0, transform_1.toGeneratedOffset)(sourceScript, map, position, language_core_1.isCompletionEnabled);
532
+ if (generatePosition !== undefined) {
533
+ details = getCompletionEntryDetails(fileName, generatePosition, entryName, formatOptions, source, preferences, data);
473
534
  }
474
535
  }
475
536
  else {
@@ -504,14 +565,12 @@ function decorateLanguageService(language, languageService) {
504
565
  const result = provideInlayHints(fileName, { start, length: end - start }, preferences);
505
566
  const hints = [];
506
567
  for (const hint of result) {
507
- for (const [sourcePosition, mapping] of map.getSourceOffsets(hint.position - sourceScript.snapshot.getLength())) {
508
- if ((0, language_core_1.isInlayHintsEnabled)(mapping.data)) {
509
- hints.push({
510
- ...hint,
511
- position: sourcePosition,
512
- });
513
- break;
514
- }
568
+ const sourcePosition = (0, transform_1.toSourceOffset)(sourceScript, map, hint.position, language_core_1.isInlayHintsEnabled);
569
+ if (sourcePosition !== undefined) {
570
+ hints.push({
571
+ ...hint,
572
+ position: sourcePosition,
573
+ });
515
574
  }
516
575
  }
517
576
  return hints;
@@ -532,9 +591,9 @@ function decorateLanguageService(language, languageService) {
532
591
  const processedFilePositions = new Set();
533
592
  const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
534
593
  if (serviceScript) {
535
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
594
+ for (const [generatedOffset, mapping] of map.getGeneratedOffsets(position)) {
536
595
  if (filter(mapping.data)) {
537
- process(fileName, generateOffset + sourceScript.snapshot.getLength());
596
+ process(fileName, generatedOffset + sourceScript.snapshot.getLength());
538
597
  }
539
598
  }
540
599
  }
@@ -554,11 +613,11 @@ function decorateLanguageService(language, languageService) {
554
613
  results = results.concat(result);
555
614
  for (const ref of getLinkedCodes(result)) {
556
615
  processedFilePositions.add(ref[0] + ':' + ref[1]);
557
- const [serviceScript, sourceScript] = (0, utils_1.getServiceScript)(language, ref[0]);
558
- if (!serviceScript) {
616
+ const [virtualFile, sourceScript] = (0, utils_1.getServiceScript)(language, ref[0]);
617
+ if (!virtualFile) {
559
618
  continue;
560
619
  }
561
- const linkedCodeMap = language.linkedCodeMaps.get(serviceScript.code);
620
+ const linkedCodeMap = language.linkedCodeMaps.get(virtualFile.code);
562
621
  if (!linkedCodeMap) {
563
622
  continue;
564
623
  }
@@ -1,4 +1,4 @@
1
- import { type Language } from '@volar/language-core';
1
+ import type { Language } from '@volar/language-core';
2
2
  import type * as ts from 'typescript';
3
- export declare function decorateLanguageServiceHost(language: Language, languageServiceHost: ts.LanguageServiceHost, ts: typeof import('typescript')): void;
3
+ export declare function decorateLanguageServiceHost(ts: typeof import('typescript'), language: Language, languageServiceHost: ts.LanguageServiceHost, getLanguageId: (fileName: string) => string): void;
4
4
  export declare function searchExternalFiles(ts: typeof import('typescript'), project: ts.server.Project, exts: string[]): string[];
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.searchExternalFiles = exports.decorateLanguageServiceHost = void 0;
4
- const language_core_1 = require("@volar/language-core");
5
4
  const resolveModuleName_1 = require("../resolveModuleName");
6
- function decorateLanguageServiceHost(language, languageServiceHost, ts) {
5
+ function decorateLanguageServiceHost(ts, language, languageServiceHost, getLanguageId) {
7
6
  let extraProjectVersion = 0;
8
7
  const exts = language.plugins
9
8
  .map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
@@ -57,35 +56,31 @@ function decorateLanguageServiceHost(language, languageServiceHost, ts) {
57
56
  };
58
57
  }
59
58
  languageServiceHost.getScriptSnapshot = fileName => {
60
- if (exts.some(ext => fileName.endsWith(ext))) {
61
- updateScript(fileName);
62
- return scripts.get(fileName)?.snapshot;
59
+ const virtualScript = updateVirtualScript(fileName);
60
+ if (virtualScript) {
61
+ return virtualScript.snapshot;
63
62
  }
64
63
  return getScriptSnapshot(fileName);
65
64
  };
66
65
  if (getScriptKind) {
67
66
  languageServiceHost.getScriptKind = fileName => {
68
- if (exts.some(ext => fileName.endsWith(ext))) {
69
- updateScript(fileName);
70
- const script = scripts.get(fileName);
71
- if (script) {
72
- return script.kind;
73
- }
74
- return ts.ScriptKind.Deferred;
67
+ const virtualScript = updateVirtualScript(fileName);
68
+ if (virtualScript) {
69
+ return virtualScript.kind;
75
70
  }
76
71
  return getScriptKind(fileName);
77
72
  };
78
73
  }
79
- function updateScript(fileName) {
74
+ function updateVirtualScript(fileName) {
80
75
  const version = languageServiceHost.getScriptVersion(fileName);
81
- if (version !== scripts.get(fileName)?.version) {
76
+ if (version !== scripts.get(fileName)?.[0]) {
82
77
  let extension = '.ts';
83
78
  let snapshotSnapshot;
84
79
  let scriptKind = ts.ScriptKind.TS;
85
80
  const snapshot = getScriptSnapshot(fileName);
86
81
  if (snapshot) {
87
82
  extraProjectVersion++;
88
- const sourceScript = language.scripts.set(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
83
+ const sourceScript = language.scripts.set(fileName, getLanguageId(fileName), snapshot);
89
84
  if (sourceScript.generated) {
90
85
  const text = snapshot.getText(0, snapshot.getLength());
91
86
  let patchedText = text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
@@ -105,14 +100,18 @@ function decorateLanguageServiceHost(language, languageServiceHost, ts) {
105
100
  extraProjectVersion++;
106
101
  language.scripts.delete(fileName);
107
102
  }
108
- scripts.set(fileName, {
109
- version,
110
- extension,
111
- snapshot: snapshotSnapshot,
112
- kind: scriptKind,
113
- });
103
+ if (snapshotSnapshot) {
104
+ scripts.set(fileName, [
105
+ version,
106
+ {
107
+ extension,
108
+ snapshot: snapshotSnapshot,
109
+ kind: scriptKind,
110
+ }
111
+ ]);
112
+ }
114
113
  }
115
- return scripts.get(fileName);
114
+ return scripts.get(fileName)?.[1];
116
115
  }
117
116
  }
118
117
  exports.decorateLanguageServiceHost = decorateLanguageServiceHost;
@@ -1,3 +1,3 @@
1
1
  import type * as ts from 'typescript';
2
2
  import { LanguagePlugin } from '@volar/language-core';
3
- export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], extensions: string[], getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[]): typeof import("typescript").createProgram;
3
+ export declare function proxyCreateProgram(ts: typeof import('typescript'), original: typeof ts['createProgram'], getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[], getLanguageId: (fileName: string) => string): typeof import("typescript").createProgram;
@@ -3,13 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.proxyCreateProgram = void 0;
4
4
  const decorateProgram_1 = require("./decorateProgram");
5
5
  const language_core_1 = require("@volar/language-core");
6
- function proxyCreateProgram(ts, original, extensions, getLanguagePlugins) {
6
+ function proxyCreateProgram(ts, original, getLanguagePlugins, getLanguageId) {
7
7
  return new Proxy(original, {
8
8
  apply: (target, thisArg, args) => {
9
9
  const options = args[0];
10
10
  assert(!!options.host, '!!options.host');
11
+ const languagePlugins = getLanguagePlugins(ts, options);
12
+ const extensions = languagePlugins
13
+ .map(plugin => plugin.typescript?.extraFileExtensions.map(({ extension }) => `.${extension}`) ?? [])
14
+ .flat();
11
15
  const sourceFileToSnapshotMap = new WeakMap();
12
- const language = (0, language_core_1.createLanguage)(getLanguagePlugins(ts, options), ts.sys.useCaseSensitiveFileNames, fileName => {
16
+ const language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
13
17
  let snapshot;
14
18
  assert(originalSourceFiles.has(fileName), `originalSourceFiles.has(${fileName})`);
15
19
  const sourceFile = originalSourceFiles.get(fileName);
@@ -31,7 +35,7 @@ function proxyCreateProgram(ts, original, extensions, getLanguagePlugins) {
31
35
  }
32
36
  }
33
37
  if (snapshot) {
34
- language.scripts.set(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
38
+ language.scripts.set(fileName, getLanguageId(fileName), snapshot);
35
39
  }
36
40
  else {
37
41
  language.scripts.delete(fileName);
@@ -97,7 +101,7 @@ function proxyCreateProgram(ts, original, extensions, getLanguagePlugins) {
97
101
  const program = Reflect.apply(target, thisArg, [options]);
98
102
  (0, decorateProgram_1.decorateProgram)(language, program);
99
103
  // TODO: #128
100
- program.__volar__ = { files: language };
104
+ program.__volar__ = { language };
101
105
  return program;
102
106
  function resolveModuleName(name, containingFile, options, redirectedReference) {
103
107
  const resolved = ts.resolveModuleName(name, containingFile, options, moduleResolutionHost, originalHost.getModuleResolutionCache?.(), redirectedReference);
@@ -1,10 +1,15 @@
1
- import { Language, CodeInformation } from '@volar/language-core';
1
+ import { Language, CodeInformation, SourceMap, SourceScript } from '@volar/language-core';
2
2
  import type * as ts from 'typescript';
3
- export declare function transformCallHierarchyItem(files: Language, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
4
- export declare function transformDiagnostic<T extends ts.Diagnostic>(files: Language, diagnostic: T): T | undefined;
5
- export declare function transformFileTextChanges(files: Language, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined;
6
- export declare function transformDocumentSpan<T extends ts.DocumentSpan>(files: Language, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
7
- export declare function transformSpan(files: Language, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): {
3
+ export declare function transformCallHierarchyItem(language: Language, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
4
+ export declare function transformDiagnostic<T extends ts.Diagnostic>(language: Language, diagnostic: T): T | undefined;
5
+ export declare function transformSourceFile(sourceFile: ts.SourceFile, sourceText: string): ts.SourceFile;
6
+ export declare function transformFileTextChanges(language: Language, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined;
7
+ export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
8
+ export declare function transformSpan(language: Language, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): {
8
9
  fileName: string;
9
10
  textSpan: ts.TextSpan;
10
11
  } | undefined;
12
+ export declare function transformTextChange(sourceScript: SourceScript, map: SourceMap<CodeInformation>, textChange: ts.TextChange, filter: (data: CodeInformation) => boolean): ts.TextChange | undefined;
13
+ export declare function transformTextSpan(sourceScript: SourceScript, map: SourceMap<CodeInformation>, textSpan: ts.TextSpan, filter: (data: CodeInformation) => boolean): ts.TextSpan | undefined;
14
+ export declare function toSourceOffset(sourceScript: SourceScript, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
15
+ export declare function toGeneratedOffset(sourceScript: SourceScript, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.transformDiagnostic = exports.transformCallHierarchyItem = void 0;
3
+ exports.toGeneratedOffset = exports.toSourceOffset = exports.transformTextSpan = exports.transformTextChange = exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.transformSourceFile = exports.transformDiagnostic = exports.transformCallHierarchyItem = void 0;
4
4
  const language_core_1 = require("@volar/language-core");
5
5
  const utils_1 = require("./utils");
6
6
  const transformedDiagnostics = new WeakMap();
7
- function transformCallHierarchyItem(files, item, filter) {
8
- const span = transformSpan(files, item.file, item.span, filter);
9
- const selectionSpan = transformSpan(files, item.file, item.selectionSpan, filter);
7
+ const transformedSourceFiles = new WeakMap();
8
+ function transformCallHierarchyItem(language, item, filter) {
9
+ const span = transformSpan(language, item.file, item.span, filter);
10
+ const selectionSpan = transformSpan(language, item.file, item.selectionSpan, filter);
10
11
  return {
11
12
  ...item,
12
13
  span: span?.textSpan ?? { start: 0, length: 0 },
@@ -14,26 +15,27 @@ function transformCallHierarchyItem(files, item, filter) {
14
15
  };
15
16
  }
16
17
  exports.transformCallHierarchyItem = transformCallHierarchyItem;
17
- function transformDiagnostic(files, diagnostic) {
18
+ function transformDiagnostic(language, diagnostic) {
18
19
  if (!transformedDiagnostics.has(diagnostic)) {
19
20
  transformedDiagnostics.set(diagnostic, undefined);
20
21
  const { relatedInformation } = diagnostic;
21
22
  if (relatedInformation) {
22
23
  diagnostic.relatedInformation = relatedInformation
23
- .map(d => transformDiagnostic(files, d))
24
+ .map(d => transformDiagnostic(language, d))
24
25
  .filter(utils_1.notEmpty);
25
26
  }
26
27
  if (diagnostic.file !== undefined
27
28
  && diagnostic.start !== undefined
28
29
  && diagnostic.length !== undefined) {
29
- const [virtualCode, sourceScript, map] = (0, utils_1.getServiceScript)(files, diagnostic.file.fileName);
30
- if (virtualCode) {
31
- const sourceRange = transformRange(sourceScript, map, diagnostic.start, diagnostic.start + diagnostic.length, language_core_1.shouldReportDiagnostics);
32
- if (sourceRange) {
30
+ const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, diagnostic.file.fileName);
31
+ if (serviceScript) {
32
+ const sourceSpan = transformTextSpan(sourceScript, map, { start: diagnostic.start, length: diagnostic.length }, language_core_1.shouldReportDiagnostics);
33
+ if (sourceSpan) {
33
34
  transformedDiagnostics.set(diagnostic, {
34
35
  ...diagnostic,
35
- start: sourceRange[0],
36
- length: sourceRange[1] - sourceRange[0],
36
+ start: sourceSpan.start,
37
+ length: sourceSpan.length,
38
+ file: transformSourceFile(diagnostic.file, sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength())),
37
39
  });
38
40
  }
39
41
  }
@@ -48,13 +50,23 @@ function transformDiagnostic(files, diagnostic) {
48
50
  return transformedDiagnostics.get(diagnostic);
49
51
  }
50
52
  exports.transformDiagnostic = transformDiagnostic;
51
- function transformFileTextChanges(files, changes, filter) {
52
- const [_, source] = (0, utils_1.getServiceScript)(files, changes.fileName);
53
+ function transformSourceFile(sourceFile, sourceText) {
54
+ if (!transformedSourceFiles.has(sourceFile)) {
55
+ transformedSourceFiles.set(sourceFile, {
56
+ ...sourceFile,
57
+ text: sourceText,
58
+ });
59
+ }
60
+ return transformedSourceFiles.get(sourceFile);
61
+ }
62
+ exports.transformSourceFile = transformSourceFile;
63
+ function transformFileTextChanges(language, changes, filter) {
64
+ const [_, source] = (0, utils_1.getServiceScript)(language, changes.fileName);
53
65
  if (source) {
54
66
  return {
55
67
  ...changes,
56
68
  textChanges: changes.textChanges.map(c => {
57
- const span = transformSpan(files, changes.fileName, c.span, filter);
69
+ const span = transformSpan(language, changes.fileName, c.span, filter);
58
70
  if (span) {
59
71
  return {
60
72
  ...c,
@@ -69,11 +81,11 @@ function transformFileTextChanges(files, changes, filter) {
69
81
  }
70
82
  }
71
83
  exports.transformFileTextChanges = transformFileTextChanges;
72
- function transformDocumentSpan(files, documentSpan, filter, shouldFallback) {
73
- let textSpan = transformSpan(files, documentSpan.fileName, documentSpan.textSpan, filter);
84
+ function transformDocumentSpan(language, documentSpan, filter, shouldFallback) {
85
+ let textSpan = transformSpan(language, documentSpan.fileName, documentSpan.textSpan, filter);
74
86
  if (!textSpan && shouldFallback) {
75
- const [virtualCode] = (0, utils_1.getServiceScript)(files, documentSpan.fileName);
76
- if (virtualCode) {
87
+ const [serviceScript] = (0, utils_1.getServiceScript)(language, documentSpan.fileName);
88
+ if (serviceScript) {
77
89
  textSpan = {
78
90
  fileName: documentSpan.fileName,
79
91
  textSpan: { start: 0, length: 0 },
@@ -83,9 +95,9 @@ function transformDocumentSpan(files, documentSpan, filter, shouldFallback) {
83
95
  if (!textSpan) {
84
96
  return;
85
97
  }
86
- const contextSpan = transformSpan(files, documentSpan.fileName, documentSpan.contextSpan, filter);
87
- const originalTextSpan = transformSpan(files, documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
88
- const originalContextSpan = transformSpan(files, documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
98
+ const contextSpan = transformSpan(language, documentSpan.fileName, documentSpan.contextSpan, filter);
99
+ const originalTextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
100
+ const originalContextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
89
101
  return {
90
102
  ...documentSpan,
91
103
  fileName: textSpan.fileName,
@@ -97,23 +109,17 @@ function transformDocumentSpan(files, documentSpan, filter, shouldFallback) {
97
109
  };
98
110
  }
99
111
  exports.transformDocumentSpan = transformDocumentSpan;
100
- function transformSpan(files, fileName, textSpan, filter) {
101
- if (!fileName) {
102
- return;
103
- }
104
- if (!textSpan) {
112
+ function transformSpan(language, fileName, textSpan, filter) {
113
+ if (!fileName || !textSpan) {
105
114
  return;
106
115
  }
107
- const [virtualFile, sourceScript, map] = (0, utils_1.getServiceScript)(files, fileName);
116
+ const [virtualFile, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
108
117
  if (virtualFile) {
109
- const sourceRange = transformRange(sourceScript, map, textSpan.start, textSpan.start + textSpan.length, filter);
110
- if (sourceRange) {
118
+ const sourceSpan = transformTextSpan(sourceScript, map, textSpan, filter);
119
+ if (sourceSpan) {
111
120
  return {
112
121
  fileName,
113
- textSpan: {
114
- start: sourceRange[0],
115
- length: sourceRange[1] - sourceRange[0],
116
- },
122
+ textSpan: sourceSpan,
117
123
  };
118
124
  }
119
125
  }
@@ -125,15 +131,43 @@ function transformSpan(files, fileName, textSpan, filter) {
125
131
  }
126
132
  }
127
133
  exports.transformSpan = transformSpan;
128
- function transformRange(sourceScript, map, start, end, filter) {
129
- for (const sourceStart of map.getSourceOffsets(start - sourceScript.snapshot.getLength())) {
130
- if (filter(sourceStart[1].data)) {
131
- for (const sourceEnd of map.getSourceOffsets(end - sourceScript.snapshot.getLength())) {
132
- if (sourceEnd[0] >= sourceStart[0] && filter(sourceEnd[1].data)) {
133
- return [sourceStart[0], sourceEnd[0]];
134
- }
135
- }
134
+ function transformTextChange(sourceScript, map, textChange, filter) {
135
+ const sourceSpan = transformTextSpan(sourceScript, map, textChange.span, filter);
136
+ if (sourceSpan) {
137
+ return {
138
+ newText: textChange.newText,
139
+ span: sourceSpan,
140
+ };
141
+ }
142
+ }
143
+ exports.transformTextChange = transformTextChange;
144
+ function transformTextSpan(sourceScript, map, textSpan, filter) {
145
+ const start = textSpan.start;
146
+ const end = textSpan.start + textSpan.length;
147
+ const sourceStart = toSourceOffset(sourceScript, map, start, filter);
148
+ const sourceEnd = toSourceOffset(sourceScript, map, end, filter);
149
+ if (sourceStart !== undefined && sourceEnd !== undefined && sourceEnd >= sourceStart) {
150
+ return {
151
+ start: sourceStart,
152
+ length: sourceEnd - sourceStart,
153
+ };
154
+ }
155
+ }
156
+ exports.transformTextSpan = transformTextSpan;
157
+ function toSourceOffset(sourceScript, map, position, filter) {
158
+ for (const [sourceOffset, mapping] of map.getSourceOffsets(position - sourceScript.snapshot.getLength())) {
159
+ if (filter(mapping.data)) {
160
+ return sourceOffset;
161
+ }
162
+ }
163
+ }
164
+ exports.toSourceOffset = toSourceOffset;
165
+ function toGeneratedOffset(sourceScript, map, position, filter) {
166
+ for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
167
+ if (filter(mapping.data)) {
168
+ return generateOffset + sourceScript.snapshot.getLength();
136
169
  }
137
170
  }
138
171
  }
172
+ exports.toGeneratedOffset = toGeneratedOffset;
139
173
  //# sourceMappingURL=transform.js.map
@@ -1,3 +1,3 @@
1
1
  import type * as ts from 'typescript';
2
2
  import { LanguagePlugin } from '@volar/language-core';
3
- export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>): ts.server.PluginModuleFactory;
3
+ export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<LanguagePlugin[]>, getLanguageId: (fileName: string) => string): ts.server.PluginModuleFactory;
@@ -8,7 +8,7 @@ const createLanguageServicePlugin_1 = require("./createLanguageServicePlugin");
8
8
  const externalFiles = new WeakMap();
9
9
  const decoratedLanguageServices = new WeakSet();
10
10
  const decoratedLanguageServiceHosts = new WeakSet();
11
- function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePlugins) {
11
+ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePlugins, getLanguageId) {
12
12
  return modules => {
13
13
  const { typescript: ts } = modules;
14
14
  const pluginModule = {
@@ -55,14 +55,14 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
55
55
  const language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
56
56
  const snapshot = getScriptSnapshot(fileName);
57
57
  if (snapshot) {
58
- language.scripts.set(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
58
+ language.scripts.set(fileName, getLanguageId(fileName), snapshot);
59
59
  }
60
60
  else {
61
61
  language.scripts.delete(fileName);
62
62
  }
63
63
  });
64
64
  (0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService);
65
- (0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(language, info.languageServiceHost, ts);
65
+ (0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost, getLanguageId);
66
66
  info.project.markAsDirty();
67
67
  initialized = true;
68
68
  });
@@ -1,4 +1,4 @@
1
1
  import type * as ts from 'typescript';
2
2
  import { LanguagePlugin } from '@volar/language-core';
3
- export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin[]): ts.server.PluginModuleFactory;
3
+ export declare function createLanguageServicePlugin(loadLanguagePlugins: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => LanguagePlugin[], getLanguageId: (fileName: string) => string): ts.server.PluginModuleFactory;
4
4
  export declare function arrayItemsEqual(a: string[], b: string[]): boolean;
@@ -8,7 +8,7 @@ const externalFiles = new WeakMap();
8
8
  const projectExternalFileExtensions = new WeakMap();
9
9
  const decoratedLanguageServices = new WeakSet();
10
10
  const decoratedLanguageServiceHosts = new WeakSet();
11
- function createLanguageServicePlugin(loadLanguagePlugins) {
11
+ function createLanguageServicePlugin(loadLanguagePlugins, getLanguageId) {
12
12
  return modules => {
13
13
  const { typescript: ts } = modules;
14
14
  const pluginModule = {
@@ -26,14 +26,14 @@ function createLanguageServicePlugin(loadLanguagePlugins) {
26
26
  const language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
27
27
  const snapshot = getScriptSnapshot(fileName);
28
28
  if (snapshot) {
29
- language.scripts.set(fileName, (0, language_core_1.resolveCommonLanguageId)(fileName), snapshot);
29
+ language.scripts.set(fileName, getLanguageId(fileName), snapshot);
30
30
  }
31
31
  else {
32
32
  language.scripts.delete(fileName);
33
33
  }
34
34
  });
35
35
  (0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService);
36
- (0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(language, info.languageServiceHost, ts);
36
+ (0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost, getLanguageId);
37
37
  }
38
38
  return info.languageService;
39
39
  },
@@ -1,4 +1,5 @@
1
1
  import type * as ts from 'typescript';
2
2
  import type { LanguagePlugin } from '@volar/language-core';
3
3
  export declare let getLanguagePlugins: (ts: typeof import('typescript'), options: ts.CreateProgramOptions) => LanguagePlugin[];
4
- export declare function runTsc(tscPath: string, extensions: string[], _getLanguagePlugins: typeof getLanguagePlugins): void;
4
+ export declare let getLanguageId: (fileName: string) => string;
5
+ export declare function runTsc(tscPath: string, extensions: string[], _getLanguagePlugins: typeof getLanguagePlugins, _getLanguageId: typeof getLanguageId): void;
@@ -1,11 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runTsc = exports.getLanguagePlugins = void 0;
3
+ exports.runTsc = exports.getLanguageId = exports.getLanguagePlugins = void 0;
4
4
  const fs = require("fs");
5
5
  let getLanguagePlugins = () => [];
6
6
  exports.getLanguagePlugins = getLanguagePlugins;
7
- function runTsc(tscPath, extensions, _getLanguagePlugins) {
7
+ let getLanguageId = () => 'ts';
8
+ exports.getLanguageId = getLanguageId;
9
+ function runTsc(tscPath, extensions, _getLanguagePlugins, _getLanguageId) {
8
10
  exports.getLanguagePlugins = _getLanguagePlugins;
11
+ exports.getLanguageId = _getLanguageId;
9
12
  const proxyApiPath = require.resolve('../node/proxyCreateProgram');
10
13
  const readFileSync = fs.readFileSync;
11
14
  fs.readFileSync = (...args) => {
@@ -18,10 +21,12 @@ function runTsc(tscPath, extensions, _getLanguagePlugins) {
18
21
  tsc = replace(tsc, /allSupportedExtensions = .*(?=;)/, s => s + `.concat([[${extsText}]])`);
19
22
  // proxy createProgram
20
23
  tsc = replace(tsc, /function createProgram\(.+\) {/, s => `var createProgram = require(${JSON.stringify(proxyApiPath)}).proxyCreateProgram(`
21
- + `new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } ), `
22
- + `_createProgram, `
23
- + `[${extsText}], `
24
- + `require(${JSON.stringify(__filename)}).getLanguagePlugins`
24
+ + [
25
+ `new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } )`,
26
+ `_createProgram`,
27
+ `require(${JSON.stringify(__filename)}).getLanguagePlugins`,
28
+ `require(${JSON.stringify(__filename)}).getLanguageId`,
29
+ ].join(', ')
25
30
  + `);\n`
26
31
  + s.replace('createProgram', '_createProgram'));
27
32
  return tsc;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volar/typescript",
3
- "version": "2.2.0-alpha.0",
3
+ "version": "2.2.0-alpha.2",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,13 +12,13 @@
12
12
  "directory": "packages/typescript"
13
13
  },
14
14
  "dependencies": {
15
- "@volar/language-core": "2.2.0-alpha.0",
15
+ "@volar/language-core": "2.2.0-alpha.2",
16
16
  "path-browserify": "^1.0.1"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/node": "latest",
20
20
  "@types/path-browserify": "latest",
21
- "@volar/language-service": "2.2.0-alpha.0"
21
+ "@volar/language-service": "2.2.0-alpha.2"
22
22
  },
23
- "gitHead": "95ffe51f944ee87f570be113541e17ddfe75f588"
23
+ "gitHead": "c6a538c915cc8b32ad9a7ca1092a29a326d49161"
24
24
  }