@volar/typescript 2.3.0-alpha.1 → 2.3.0-alpha.11

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.
@@ -64,7 +64,7 @@ function decorateLanguageServiceHost(ts, language, languageServiceHost) {
64
64
  languageServiceHost.getScriptKind = fileName => {
65
65
  const virtualScript = updateVirtualScript(fileName);
66
66
  if (virtualScript) {
67
- return virtualScript.kind;
67
+ return virtualScript.scriptKind;
68
68
  }
69
69
  return getScriptKind(fileName);
70
70
  };
@@ -92,14 +92,23 @@ function decorateLanguageServiceHost(ts, language, languageServiceHost) {
92
92
  if (sourceScript?.generated) {
93
93
  const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
94
94
  if (serviceScript) {
95
- const sourceContents = sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength());
96
- let virtualContents = sourceContents.split('\n').map(line => ' '.repeat(line.length)).join('\n');
97
- virtualContents += serviceScript.code.snapshot.getText(0, serviceScript.code.snapshot.getLength());
98
- script[1] = {
99
- extension: serviceScript.extension,
100
- kind: serviceScript.scriptKind,
101
- snapshot: ts.ScriptSnapshot.fromString(virtualContents),
102
- };
95
+ if (serviceScript.preventLeadingOffset) {
96
+ script[1] = {
97
+ extension: serviceScript.extension,
98
+ scriptKind: serviceScript.scriptKind,
99
+ snapshot: serviceScript.code.snapshot,
100
+ };
101
+ }
102
+ else {
103
+ const sourceContents = sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength());
104
+ const virtualContents = sourceContents.split('\n').map(line => ' '.repeat(line.length)).join('\n')
105
+ + serviceScript.code.snapshot.getText(0, serviceScript.code.snapshot.getLength());
106
+ script[1] = {
107
+ extension: serviceScript.extension,
108
+ scriptKind: serviceScript.scriptKind,
109
+ snapshot: ts.ScriptSnapshot.fromString(virtualContents),
110
+ };
111
+ }
103
112
  }
104
113
  if (sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts) {
105
114
  console.warn('getExtraServiceScripts() is not available in TS plugin.');
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.decorateProgram = void 0;
4
- const utils_1 = require("./utils");
5
4
  const transform_1 = require("./transform");
5
+ const utils_1 = require("./utils");
6
6
  function decorateProgram(language, program) {
7
7
  const emit = program.emit;
8
8
  // for tsc --noEmit
@@ -18,30 +18,57 @@ function decorateProgram(language, program) {
18
18
  return {
19
19
  ...result,
20
20
  diagnostics: result.diagnostics
21
- .map(d => (0, transform_1.transformDiagnostic)(language, d, true))
21
+ .map(d => (0, transform_1.transformDiagnostic)(undefined, language, d, program, true))
22
22
  .filter(utils_1.notEmpty),
23
23
  };
24
24
  };
25
25
  program.getSyntacticDiagnostics = (sourceFile, cancellationToken) => {
26
- return getSyntacticDiagnostics(sourceFile, cancellationToken)
27
- .map(d => (0, transform_1.transformDiagnostic)(language, d, true))
28
- .filter(utils_1.notEmpty);
26
+ if (!sourceFile) {
27
+ return getSyntacticDiagnostics(undefined, cancellationToken)
28
+ .map(d => (0, transform_1.transformDiagnostic)(undefined, language, d, program, true))
29
+ .filter(utils_1.notEmpty);
30
+ }
31
+ else {
32
+ const [_serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
33
+ const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
34
+ return getSyntacticDiagnostics(actualSourceFile, cancellationToken)
35
+ .map(d => (0, transform_1.transformDiagnostic)(sourceScript, language, d, program, true))
36
+ .filter(utils_1.notEmpty);
37
+ }
29
38
  };
30
39
  program.getSemanticDiagnostics = (sourceFile, cancellationToken) => {
31
- return getSemanticDiagnostics(sourceFile, cancellationToken)
32
- .map(d => (0, transform_1.transformDiagnostic)(language, d, true))
33
- .filter(utils_1.notEmpty);
40
+ if (!sourceFile) {
41
+ return getSemanticDiagnostics(undefined, cancellationToken)
42
+ .map(d => (0, transform_1.transformDiagnostic)(undefined, language, d, program, true))
43
+ .filter(utils_1.notEmpty);
44
+ }
45
+ else {
46
+ const [_serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
47
+ const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
48
+ return getSemanticDiagnostics(actualSourceFile, cancellationToken)
49
+ .map(d => (0, transform_1.transformDiagnostic)(sourceScript, language, d, program, true))
50
+ .filter(utils_1.notEmpty);
51
+ }
34
52
  };
35
53
  program.getGlobalDiagnostics = cancellationToken => {
36
54
  return getGlobalDiagnostics(cancellationToken)
37
- .map(d => (0, transform_1.transformDiagnostic)(language, d, true))
55
+ .map(d => (0, transform_1.transformDiagnostic)(undefined, language, d, program, true))
38
56
  .filter(utils_1.notEmpty);
39
57
  };
40
58
  // @ts-ignore
41
59
  program.getBindAndCheckDiagnostics = (sourceFile, cancellationToken) => {
42
- return getBindAndCheckDiagnostics(sourceFile, cancellationToken)
43
- .map(d => (0, transform_1.transformDiagnostic)(language, d, true))
44
- .filter(utils_1.notEmpty);
60
+ if (!sourceFile) {
61
+ return getBindAndCheckDiagnostics(undefined, cancellationToken)
62
+ .map(d => (0, transform_1.transformDiagnostic)(undefined, language, d, program, true))
63
+ .filter(utils_1.notEmpty);
64
+ }
65
+ else {
66
+ const [_serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
67
+ const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
68
+ return getBindAndCheckDiagnostics(actualSourceFile, cancellationToken)
69
+ .map(d => (0, transform_1.transformDiagnostic)(sourceScript, language, d, program, true))
70
+ .filter(utils_1.notEmpty);
71
+ }
45
72
  };
46
73
  // fix https://github.com/vuejs/language-tools/issues/4099 with `incremental`
47
74
  program.getSourceFileByPath = path => {
@@ -50,11 +50,7 @@ function proxyCreateProgram(ts, original, getLanguagePlugins) {
50
50
  languagePlugins = getLanguagePlugins(ts, options);
51
51
  language = (0, language_core_1.createLanguage)([
52
52
  ...languagePlugins,
53
- {
54
- getLanguageId(fileName) {
55
- return (0, common_1.resolveFileLanguageId)(fileName);
56
- },
57
- },
53
+ { getLanguageId: common_1.resolveFileLanguageId },
58
54
  ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => {
59
55
  if (!sourceFileSnapshots.has(fileName)) {
60
56
  const sourceFileText = originalHost.readFile(fileName);
@@ -116,11 +112,11 @@ function proxyCreateProgram(ts, original, getLanguagePlugins) {
116
112
  if (!parsedSourceFiles.has(originalSourceFile)) {
117
113
  const sourceScript = language.scripts.get(fileName);
118
114
  assert(!!sourceScript, '!!sourceScript');
119
- parsedSourceFiles.set(originalSourceFile, originalSourceFile);
115
+ parsedSourceFiles.set(originalSourceFile, undefined);
120
116
  if (sourceScript.generated?.languagePlugin.typescript) {
121
117
  const { getServiceScript, getExtraServiceScripts } = sourceScript.generated.languagePlugin.typescript;
122
118
  const serviceScript = getServiceScript(sourceScript.generated.root);
123
- if (serviceScript) {
119
+ if (serviceScript && !serviceScript.preventLeadingOffset) {
124
120
  let patchedText = originalSourceFile.text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
125
121
  let scriptKind = ts.ScriptKind.TS;
126
122
  scriptKind = serviceScript.scriptKind;
@@ -135,7 +131,7 @@ function proxyCreateProgram(ts, original, getLanguagePlugins) {
135
131
  }
136
132
  }
137
133
  }
138
- return parsedSourceFiles.get(originalSourceFile);
134
+ return parsedSourceFiles.get(originalSourceFile) ?? originalSourceFile;
139
135
  };
140
136
  if (extensions.length) {
141
137
  options.options.allowArbitraryExtensions = true;
@@ -1,17 +1,19 @@
1
- import type { CodeInformation, SourceMap, SourceScript } from '@volar/language-core';
1
+ import type { CodeInformation, SourceScript, TypeScriptServiceScript } from '@volar/language-core';
2
2
  import { Language } from '@volar/language-core';
3
3
  import type * as ts from 'typescript';
4
4
  export declare function transformCallHierarchyItem(language: Language<string>, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
5
- export declare function transformDiagnostic<T extends ts.Diagnostic>(language: Language<string>, diagnostic: T, isTsc: boolean): T | undefined;
5
+ export declare function transformDiagnostic<T extends ts.Diagnostic>(sourceScript: SourceScript<string> | undefined, language: Language<string>, diagnostic: T, program: ts.Program | undefined, isTsc: boolean): T | undefined;
6
6
  export declare function fillSourceFileText(language: Language<string>, sourceFile: ts.SourceFile): void;
7
- export declare function transformFileTextChanges(language: Language<string>, changes: ts.FileTextChanges, filter: (data: CodeInformation) => boolean): ts.FileTextChanges | undefined;
7
+ export declare function transformFileTextChanges(language: Language<string>, changes: readonly ts.FileTextChanges[], filter: (data: CodeInformation) => boolean): ts.FileTextChanges[];
8
8
  export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language<string>, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
9
9
  export declare function transformSpan(language: Language<string>, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): {
10
10
  fileName: string;
11
11
  textSpan: ts.TextSpan;
12
12
  } | undefined;
13
- export declare function transformTextChange(sourceScript: SourceScript<string>, map: SourceMap<CodeInformation>, textChange: ts.TextChange, filter: (data: CodeInformation) => boolean): ts.TextChange | undefined;
14
- export declare function transformTextSpan(sourceScript: SourceScript<string>, map: SourceMap<CodeInformation>, textSpan: ts.TextSpan, filter: (data: CodeInformation) => boolean): ts.TextSpan | undefined;
15
- export declare function toSourceOffset(sourceScript: SourceScript<string>, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
16
- export declare function toGeneratedOffset(sourceScript: SourceScript<string>, map: SourceMap, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
17
- export declare function toGeneratedOffsets(sourceScript: SourceScript<string>, map: SourceMap<CodeInformation>, position: number): Generator<readonly [number, import("@volar/language-core").Mapping<CodeInformation>], void, unknown>;
13
+ export declare function transformTextChange(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, textChange: ts.TextChange, filter: (data: CodeInformation) => boolean): [string, ts.TextChange] | undefined;
14
+ export declare function transformTextSpan(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, textSpan: ts.TextSpan, filter: (data: CodeInformation) => boolean): [string, ts.TextSpan] | undefined;
15
+ export declare function toSourceOffset(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, position: number, filter: (data: CodeInformation) => boolean): [fileName: string, offset: number] | undefined;
16
+ export declare function toSourceOffsets(sourceScript: SourceScript<string> | undefined, language: Language<string>, serviceScript: TypeScriptServiceScript, position: number, filter: (data: CodeInformation) => boolean): Generator<[fileName: string, offset: number]>;
17
+ export declare function toGeneratedOffset(language: Language, serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>, position: number, filter: (data: CodeInformation) => boolean): number | undefined;
18
+ export declare function toGeneratedOffsets(language: Language, serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>, position: number, filter: (data: CodeInformation) => boolean): Generator<readonly [number, import("@volar/language-core").Mapping<CodeInformation>], void, unknown>;
19
+ export declare function getMappingOffset(language: Language, serviceScript: TypeScriptServiceScript): number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toGeneratedOffsets = exports.toGeneratedOffset = exports.toSourceOffset = exports.transformTextSpan = exports.transformTextChange = exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.fillSourceFileText = exports.transformDiagnostic = exports.transformCallHierarchyItem = void 0;
3
+ exports.getMappingOffset = exports.toGeneratedOffsets = exports.toGeneratedOffset = exports.toSourceOffsets = exports.toSourceOffset = exports.transformTextSpan = exports.transformTextChange = exports.transformSpan = exports.transformDocumentSpan = exports.transformFileTextChanges = exports.fillSourceFileText = 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();
@@ -10,32 +10,42 @@ function transformCallHierarchyItem(language, item, filter) {
10
10
  const selectionSpan = transformSpan(language, item.file, item.selectionSpan, filter);
11
11
  return {
12
12
  ...item,
13
+ file: span?.fileName ?? item.file,
13
14
  span: span?.textSpan ?? { start: 0, length: 0 },
14
15
  selectionSpan: selectionSpan?.textSpan ?? { start: 0, length: 0 },
15
16
  };
16
17
  }
17
18
  exports.transformCallHierarchyItem = transformCallHierarchyItem;
18
- function transformDiagnostic(language, diagnostic, isTsc) {
19
+ function transformDiagnostic(sourceScript, language, diagnostic, program, isTsc) {
19
20
  if (!transformedDiagnostics.has(diagnostic)) {
20
21
  transformedDiagnostics.set(diagnostic, undefined);
21
22
  const { relatedInformation } = diagnostic;
22
23
  if (relatedInformation) {
23
24
  diagnostic.relatedInformation = relatedInformation
24
- .map(d => transformDiagnostic(language, d, isTsc))
25
+ .map(d => transformDiagnostic(undefined, language, d, program, isTsc))
25
26
  .filter(utils_1.notEmpty);
26
27
  }
27
28
  if (diagnostic.file !== undefined
28
29
  && diagnostic.start !== undefined
29
30
  && diagnostic.length !== undefined) {
30
- const [serviceScript, sourceScript, map] = (0, utils_1.getServiceScript)(language, diagnostic.file.fileName);
31
+ const [serviceScript] = (0, utils_1.getServiceScript)(language, diagnostic.file.fileName);
31
32
  if (serviceScript) {
32
- const sourceSpan = transformTextSpan(sourceScript, map, { start: diagnostic.start, length: diagnostic.length }, language_core_1.shouldReportDiagnostics);
33
- if (sourceSpan) {
33
+ const [sourceSpanFileName, sourceSpan] = transformTextSpan(sourceScript, language, serviceScript, {
34
+ start: diagnostic.start,
35
+ length: diagnostic.length
36
+ }, language_core_1.shouldReportDiagnostics) ?? [];
37
+ const actualDiagnosticFile = sourceSpanFileName
38
+ ? diagnostic.file.fileName === sourceSpanFileName
39
+ ? diagnostic.file
40
+ : program?.getSourceFile(sourceSpanFileName)
41
+ : undefined;
42
+ if (sourceSpan && actualDiagnosticFile) {
34
43
  if (isTsc) {
35
44
  fillSourceFileText(language, diagnostic.file);
36
45
  }
37
46
  transformedDiagnostics.set(diagnostic, {
38
47
  ...diagnostic,
48
+ file: actualDiagnosticFile,
39
49
  start: sourceSpan.start,
40
50
  length: sourceSpan.length,
41
51
  });
@@ -58,32 +68,46 @@ function fillSourceFileText(language, sourceFile) {
58
68
  return;
59
69
  }
60
70
  transformedSourceFile.add(sourceFile);
61
- const [serviceScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
62
- if (serviceScript) {
71
+ const [serviceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
72
+ if (serviceScript && !serviceScript.preventLeadingOffset) {
73
+ const sourceScript = language.scripts.fromVirtualCode(serviceScript.code);
63
74
  sourceFile.text = sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength())
64
75
  + sourceFile.text.substring(sourceScript.snapshot.getLength());
65
76
  }
66
77
  }
67
78
  exports.fillSourceFileText = fillSourceFileText;
68
79
  function transformFileTextChanges(language, changes, filter) {
69
- const [_, source] = (0, utils_1.getServiceScript)(language, changes.fileName);
70
- if (source) {
71
- return {
72
- ...changes,
73
- textChanges: changes.textChanges.map(c => {
74
- const span = transformSpan(language, changes.fileName, c.span, filter);
75
- if (span) {
76
- return {
77
- ...c,
78
- span: span.textSpan,
79
- };
80
+ const changesPerFile = {};
81
+ const newFiles = new Set();
82
+ for (const fileChanges of changes) {
83
+ const [_, source] = (0, utils_1.getServiceScript)(language, fileChanges.fileName);
84
+ if (source) {
85
+ fileChanges.textChanges.forEach(c => {
86
+ const { fileName, textSpan } = transformSpan(language, fileChanges.fileName, c.span, filter) ?? {};
87
+ if (fileName && textSpan) {
88
+ (changesPerFile[fileName] ?? (changesPerFile[fileName] = [])).push({ ...c, span: textSpan });
80
89
  }
81
- }).filter(utils_1.notEmpty),
82
- };
90
+ });
91
+ }
92
+ else {
93
+ const list = (changesPerFile[fileChanges.fileName] ?? (changesPerFile[fileChanges.fileName] = []));
94
+ fileChanges.textChanges.forEach(c => {
95
+ list.push(c);
96
+ });
97
+ if (fileChanges.isNewFile) {
98
+ newFiles.add(fileChanges.fileName);
99
+ }
100
+ }
83
101
  }
84
- else {
85
- return changes;
102
+ const result = [];
103
+ for (const fileName in changesPerFile) {
104
+ result.push({
105
+ fileName,
106
+ isNewFile: newFiles.has(fileName),
107
+ textChanges: changesPerFile[fileName]
108
+ });
86
109
  }
110
+ return result;
87
111
  }
88
112
  exports.transformFileTextChanges = transformFileTextChanges;
89
113
  function transformDocumentSpan(language, documentSpan, filter, shouldFallback) {
@@ -115,12 +139,12 @@ function transformSpan(language, fileName, textSpan, filter) {
115
139
  if (!fileName || !textSpan) {
116
140
  return;
117
141
  }
118
- const [virtualFile, sourceScript, map] = (0, utils_1.getServiceScript)(language, fileName);
119
- if (virtualFile) {
120
- const sourceSpan = transformTextSpan(sourceScript, map, textSpan, filter);
121
- if (sourceSpan) {
142
+ const [serviceScript] = (0, utils_1.getServiceScript)(language, fileName);
143
+ if (serviceScript) {
144
+ const [sourceSpanFileName, sourceSpan] = transformTextSpan(undefined, language, serviceScript, textSpan, filter) ?? [];
145
+ if (sourceSpan && sourceSpanFileName) {
122
146
  return {
123
- fileName,
147
+ fileName: sourceSpanFileName,
124
148
  textSpan: sourceSpan,
125
149
  };
126
150
  }
@@ -133,49 +157,80 @@ function transformSpan(language, fileName, textSpan, filter) {
133
157
  }
134
158
  }
135
159
  exports.transformSpan = transformSpan;
136
- function transformTextChange(sourceScript, map, textChange, filter) {
137
- const sourceSpan = transformTextSpan(sourceScript, map, textChange.span, filter);
138
- if (sourceSpan) {
139
- return {
140
- newText: textChange.newText,
141
- span: sourceSpan,
142
- };
160
+ function transformTextChange(sourceScript, language, serviceScript, textChange, filter) {
161
+ const [sourceSpanFileName, sourceSpan] = transformTextSpan(sourceScript, language, serviceScript, textChange.span, filter) ?? [];
162
+ if (sourceSpan && sourceSpanFileName) {
163
+ return [sourceSpanFileName, {
164
+ newText: textChange.newText,
165
+ span: sourceSpan,
166
+ }];
143
167
  }
168
+ return undefined;
144
169
  }
145
170
  exports.transformTextChange = transformTextChange;
146
- function transformTextSpan(sourceScript, map, textSpan, filter) {
171
+ function transformTextSpan(sourceScript, language, serviceScript, textSpan, filter) {
147
172
  const start = textSpan.start;
148
173
  const end = textSpan.start + textSpan.length;
149
- const sourceStart = toSourceOffset(sourceScript, map, start, filter);
150
- const sourceEnd = toSourceOffset(sourceScript, map, end, filter);
151
- if (sourceStart !== undefined && sourceEnd !== undefined && sourceEnd >= sourceStart) {
152
- return {
153
- start: sourceStart,
154
- length: sourceEnd - sourceStart,
155
- };
174
+ for (const sourceStart of toSourceOffsets(sourceScript, language, serviceScript, start, filter)) {
175
+ for (const sourceEnd of toSourceOffsets(sourceScript, language, serviceScript, end, filter)) {
176
+ if (sourceStart[0] === sourceEnd[0]
177
+ && sourceEnd[1] >= sourceStart[1]) {
178
+ return [sourceStart[0], {
179
+ start: sourceStart[1],
180
+ length: sourceEnd[1] - sourceStart[1],
181
+ }];
182
+ }
183
+ }
156
184
  }
157
185
  }
158
186
  exports.transformTextSpan = transformTextSpan;
159
- function toSourceOffset(sourceScript, map, position, filter) {
160
- for (const [sourceOffset, mapping] of map.getSourceOffsets(position - sourceScript.snapshot.getLength())) {
161
- if (filter(mapping.data)) {
162
- return sourceOffset;
163
- }
187
+ function toSourceOffset(sourceScript, language, serviceScript, position, filter) {
188
+ for (const source of toSourceOffsets(sourceScript, language, serviceScript, position, filter)) {
189
+ return source;
164
190
  }
165
191
  }
166
192
  exports.toSourceOffset = toSourceOffset;
167
- function toGeneratedOffset(sourceScript, map, position, filter) {
168
- for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
169
- if (filter(mapping.data)) {
170
- return generateOffset + sourceScript.snapshot.getLength();
193
+ function* toSourceOffsets(sourceScript, language, serviceScript, position, filter) {
194
+ if (sourceScript) {
195
+ const map = language.maps.get(serviceScript.code, sourceScript);
196
+ for (const [sourceOffset, mapping] of map.getSourceOffsets(position - getMappingOffset(language, serviceScript))) {
197
+ if (filter(mapping.data)) {
198
+ yield [sourceScript.id, sourceOffset];
199
+ }
200
+ }
201
+ }
202
+ else {
203
+ for (const [fileName, _snapshot, map] of language.maps.forEach(serviceScript.code)) {
204
+ for (const [sourceOffset, mapping] of map.getSourceOffsets(position - getMappingOffset(language, serviceScript))) {
205
+ if (filter(mapping.data)) {
206
+ yield [fileName, sourceOffset];
207
+ }
208
+ }
171
209
  }
172
210
  }
173
211
  }
212
+ exports.toSourceOffsets = toSourceOffsets;
213
+ function toGeneratedOffset(language, serviceScript, sourceScript, position, filter) {
214
+ for (const [generateOffset] of toGeneratedOffsets(language, serviceScript, sourceScript, position, filter)) {
215
+ return generateOffset;
216
+ }
217
+ }
174
218
  exports.toGeneratedOffset = toGeneratedOffset;
175
- function* toGeneratedOffsets(sourceScript, map, position) {
219
+ function* toGeneratedOffsets(language, serviceScript, sourceScript, position, filter) {
220
+ const map = language.maps.get(serviceScript.code, sourceScript);
176
221
  for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
177
- yield [generateOffset + sourceScript.snapshot.getLength(), mapping];
222
+ if (filter(mapping.data)) {
223
+ yield [generateOffset + getMappingOffset(language, serviceScript), mapping];
224
+ }
178
225
  }
179
226
  }
180
227
  exports.toGeneratedOffsets = toGeneratedOffsets;
228
+ function getMappingOffset(language, serviceScript) {
229
+ if (serviceScript.preventLeadingOffset) {
230
+ return 0;
231
+ }
232
+ const sourceScript = language.scripts.fromVirtualCode(serviceScript.code);
233
+ return sourceScript.snapshot.getLength();
234
+ }
235
+ exports.getMappingOffset = getMappingOffset;
181
236
  //# sourceMappingURL=transform.js.map
@@ -1,3 +1,3 @@
1
- import type { Language } from '@volar/language-core';
1
+ import type { Language, SourceScript, TypeScriptServiceScript } from '@volar/language-core';
2
2
  export declare function notEmpty<T>(value: T | null | undefined): value is T;
3
- export declare function getServiceScript(language: Language<string>, fileName: string): readonly [import("@volar/language-core").TypeScriptServiceScript, import("@volar/language-core").SourceScript<string>, import("@volar/language-core").SourceMap<import("@volar/language-core").CodeInformation>] | readonly [undefined, undefined, undefined];
3
+ export declare function getServiceScript(language: Language<string>, fileName: string): [serviceScript: TypeScriptServiceScript, targetScript: SourceScript<string>, sourceScript: SourceScript<string>] | [serviceScript: undefined, sourceScript: SourceScript<string>, sourceScript: SourceScript<string>] | [serviceScript: undefined, sourceScript: undefined, targetScript: undefined];
package/lib/node/utils.js CHANGED
@@ -7,13 +7,24 @@ function notEmpty(value) {
7
7
  exports.notEmpty = notEmpty;
8
8
  function getServiceScript(language, fileName) {
9
9
  const sourceScript = language.scripts.get(fileName);
10
+ if (sourceScript?.targetIds.size) {
11
+ for (const targetId of sourceScript.targetIds) {
12
+ const targetScript = language.scripts.get(targetId);
13
+ if (targetScript?.generated) {
14
+ const serviceScript = targetScript.generated.languagePlugin.typescript?.getServiceScript(targetScript.generated.root);
15
+ if (serviceScript) {
16
+ return [serviceScript, sourceScript, targetScript];
17
+ }
18
+ }
19
+ }
20
+ }
21
+ if (sourceScript?.associatedOnly) {
22
+ return [undefined, sourceScript, sourceScript];
23
+ }
10
24
  if (sourceScript?.generated) {
11
25
  const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
12
26
  if (serviceScript) {
13
- const map = language.maps.get(serviceScript.code, sourceScript.id);
14
- if (map) {
15
- return [serviceScript, sourceScript, map];
16
- }
27
+ return [serviceScript, sourceScript, sourceScript];
17
28
  }
18
29
  }
19
30
  return [undefined, undefined, undefined];
@@ -1,9 +1,9 @@
1
- import { Language, SourceScript, TypeScriptExtraServiceScript } from '@volar/language-core';
1
+ import { Language, TypeScriptExtraServiceScript } from '@volar/language-core';
2
2
  import type * as ts from 'typescript';
3
3
  import type { createSys } from './createSys';
4
4
  export interface TypeScriptProjectHost extends Pick<ts.LanguageServiceHost, 'getLocalizedDiagnosticMessages' | 'getCurrentDirectory' | 'getCompilationSettings' | 'getProjectReferences' | 'getScriptFileNames' | 'getProjectVersion' | 'getScriptSnapshot'> {
5
5
  }
6
6
  export declare function createLanguageServiceHost<T>(ts: typeof import('typescript'), sys: ReturnType<typeof createSys> | ts.System, language: Language<T>, asScrpitId: (fileName: string) => T, projectHost: TypeScriptProjectHost): {
7
7
  languageServiceHost: ts.LanguageServiceHost;
8
- getExtraServiceScript: (fileName: string) => [SourceScript<T>, TypeScriptExtraServiceScript] | undefined;
8
+ getExtraServiceScript: (fileName: string) => TypeScriptExtraServiceScript | undefined;
9
9
  };
@@ -80,7 +80,7 @@ function createLanguageServiceHost(ts, sys, language, asScrpitId, projectHost) {
80
80
  getScriptKind(fileName) {
81
81
  sync();
82
82
  if (extraScriptRegistry.has(fileName)) {
83
- return extraScriptRegistry.get(fileName)[1].scriptKind;
83
+ return extraScriptRegistry.get(fileName).scriptKind;
84
84
  }
85
85
  const sourceScript = language.scripts.get(asScrpitId(fileName));
86
86
  if (sourceScript?.generated) {
@@ -170,7 +170,7 @@ function createLanguageServiceHost(ts, sys, language, asScrpitId, projectHost) {
170
170
  for (const extraServiceScript of sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts?.(fileName, sourceScript.generated.root) ?? []) {
171
171
  newTsVirtualFileSnapshots.add(extraServiceScript.code.snapshot);
172
172
  tsFileNamesSet.add(extraServiceScript.fileName);
173
- extraScriptRegistry.set(extraServiceScript.fileName, [sourceScript, extraServiceScript]);
173
+ extraScriptRegistry.set(extraServiceScript.fileName, extraServiceScript);
174
174
  }
175
175
  for (const code of (0, language_core_1.forEachEmbeddedCode)(sourceScript.generated.root)) {
176
176
  newOtherVirtualFileSnapshots.add(code.snapshot);
@@ -197,7 +197,7 @@ function createLanguageServiceHost(ts, sys, language, asScrpitId, projectHost) {
197
197
  function getScriptSnapshot(fileName) {
198
198
  sync();
199
199
  if (extraScriptRegistry.has(fileName)) {
200
- return extraScriptRegistry.get(fileName)[1].code.snapshot;
200
+ return extraScriptRegistry.get(fileName).code.snapshot;
201
201
  }
202
202
  const sourceScript = language.scripts.get(asScrpitId(fileName));
203
203
  if (sourceScript?.generated) {
@@ -217,7 +217,7 @@ function createLanguageServiceHost(ts, sys, language, asScrpitId, projectHost) {
217
217
  }
218
218
  const version = scriptVersions.get(fileName);
219
219
  if (extraScriptRegistry.has(fileName)) {
220
- const snapshot = extraScriptRegistry.get(fileName)[1].code.snapshot;
220
+ const snapshot = extraScriptRegistry.get(fileName).code.snapshot;
221
221
  if (!version.map.has(snapshot)) {
222
222
  version.map.set(snapshot, version.lastVersion++);
223
223
  }
@@ -56,11 +56,7 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
56
56
  const syncedScriptVersions = new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames);
57
57
  const language = (0, language_core_1.createLanguage)([
58
58
  ...languagePlugins,
59
- {
60
- getLanguageId(fileName) {
61
- return (0, common_1.resolveFileLanguageId)(fileName);
62
- },
63
- },
59
+ { getLanguageId: common_1.resolveFileLanguageId },
64
60
  ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => {
65
61
  const version = getScriptVersion(fileName);
66
62
  if (syncedScriptVersions.get(fileName) === version) {
@@ -87,7 +83,7 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
87
83
  if (updateLevel >= (1)
88
84
  || !externalFiles.has(project)) {
89
85
  const oldFiles = externalFiles.get(project);
90
- const newFiles = (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions);
86
+ const newFiles = extensions.length ? (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions) : [];
91
87
  externalFiles.set(project, newFiles);
92
88
  if (oldFiles && !(0, createLanguageServicePlugin_1.arrayItemsEqual)(oldFiles, newFiles)) {
93
89
  project.refreshDiagnostics();
@@ -28,11 +28,7 @@ function createLanguageServicePlugin(loadLanguagePlugins) {
28
28
  const syncedScriptVersions = new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames);
29
29
  const language = (0, language_core_1.createLanguage)([
30
30
  ...languagePlugins,
31
- {
32
- getLanguageId(fileName) {
33
- return (0, common_1.resolveFileLanguageId)(fileName);
34
- },
35
- },
31
+ { getLanguageId: common_1.resolveFileLanguageId },
36
32
  ], new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => {
37
33
  const version = getScriptVersion(fileName);
38
34
  if (syncedScriptVersions.get(fileName) === version) {
@@ -56,7 +52,8 @@ function createLanguageServicePlugin(loadLanguagePlugins) {
56
52
  if (updateLevel >= (1)
57
53
  || !externalFiles.has(project)) {
58
54
  const oldFiles = externalFiles.get(project);
59
- const newFiles = (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, projectExternalFileExtensions.get(project));
55
+ const extensions = projectExternalFileExtensions.get(project);
56
+ const newFiles = extensions?.length ? (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions) : [];
60
57
  externalFiles.set(project, newFiles);
61
58
  if (oldFiles && !arrayItemsEqual(oldFiles, newFiles)) {
62
59
  project.refreshDiagnostics();
@@ -44,6 +44,24 @@ function createResolveModuleName(ts, host, languagePlugins, getSourceScript) {
44
44
  }
45
45
  }
46
46
  }
47
+ if (typescript.resolveHiddenExtensions && fileName.endsWith(`.d.ts`)) {
48
+ for (const { extension } of typescript.extraFileExtensions) {
49
+ const sourceFileName = fileName.slice(0, -`.d.ts`.length) + `.${extension}`;
50
+ if (fileExists(sourceFileName)) {
51
+ const sourceScript = getSourceScript(sourceFileName);
52
+ if (sourceScript?.generated) {
53
+ const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
54
+ if (serviceScript) {
55
+ toSourceFileInfo.set(fileName, {
56
+ sourceFileName,
57
+ extension: serviceScript.extension,
58
+ });
59
+ return true;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
47
65
  }
48
66
  return host.fileExists(fileName);
49
67
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volar/typescript",
3
- "version": "2.3.0-alpha.1",
3
+ "version": "2.3.0-alpha.11",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -12,14 +12,14 @@
12
12
  "directory": "packages/typescript"
13
13
  },
14
14
  "dependencies": {
15
- "@volar/language-core": "2.3.0-alpha.1",
15
+ "@volar/language-core": "2.3.0-alpha.11",
16
16
  "path-browserify": "^1.0.1",
17
17
  "vscode-uri": "^3.0.8"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@types/node": "latest",
21
21
  "@types/path-browserify": "latest",
22
- "@volar/language-service": "2.3.0-alpha.1"
22
+ "@volar/language-service": "2.3.0-alpha.11"
23
23
  },
24
- "gitHead": "173be13e1d51c62cfe5ddc9926933d30a7aa1d11"
24
+ "gitHead": "c83f835629496d3a4cc38f4b789bb676d07a2118"
25
25
  }