@volar/typescript 2.3.0-alpha.8 → 2.3.0
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/lib/node/decorateLanguageService.js +136 -132
- package/lib/node/decorateProgram.js +35 -20
- package/lib/node/transform.d.ts +13 -17
- package/lib/node/transform.js +44 -48
- package/lib/node/utils.d.ts +2 -2
- package/lib/node/utils.js +8 -17
- package/lib/quickstart/createAsyncLanguageServicePlugin.d.ts +5 -2
- package/lib/quickstart/createAsyncLanguageServicePlugin.js +11 -13
- package/lib/quickstart/createLanguageServicePlugin.d.ts +9 -2
- package/lib/quickstart/createLanguageServicePlugin.js +18 -17
- package/package.json +4 -4
|
@@ -18,45 +18,60 @@ function decorateProgram(language, program) {
|
|
|
18
18
|
return {
|
|
19
19
|
...result,
|
|
20
20
|
diagnostics: result.diagnostics
|
|
21
|
-
.map(d => (0, transform_1.transformDiagnostic)(
|
|
21
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
|
|
22
22
|
.filter(utils_1.notEmpty),
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
25
|
program.getSyntacticDiagnostics = (sourceFile, cancellationToken) => {
|
|
26
26
|
if (!sourceFile) {
|
|
27
|
-
return
|
|
27
|
+
return getSyntacticDiagnostics(undefined, cancellationToken)
|
|
28
|
+
.map(d => (0, transform_1.transformDiagnostic)(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)(language, d, program, true))
|
|
36
|
+
.filter(utils_1.notEmpty)
|
|
37
|
+
.filter(d => !serviceScript || !d.file || language.scripts.get(d.file.fileName) === sourceScript);
|
|
28
38
|
}
|
|
29
|
-
const [_serviceScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
|
|
30
|
-
const actualSourceFile = sourceScript ? program.getSourceFile(sourceScript.id) : sourceFile;
|
|
31
|
-
return getSyntacticDiagnostics(actualSourceFile, cancellationToken)
|
|
32
|
-
.map(d => (0, transform_1.transformDiagnostic)(transform_1.ToSourceMode.SkipAssciated, language, d, program, true))
|
|
33
|
-
.filter(utils_1.notEmpty);
|
|
34
39
|
};
|
|
35
40
|
program.getSemanticDiagnostics = (sourceFile, cancellationToken) => {
|
|
36
41
|
if (!sourceFile) {
|
|
37
|
-
return
|
|
42
|
+
return getSemanticDiagnostics(undefined, cancellationToken)
|
|
43
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
|
|
44
|
+
.filter(utils_1.notEmpty);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
|
|
48
|
+
const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
|
|
49
|
+
return getSemanticDiagnostics(actualSourceFile, cancellationToken)
|
|
50
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
|
|
51
|
+
.filter(utils_1.notEmpty)
|
|
52
|
+
.filter(d => !serviceScript || !d.file || language.scripts.get(d.file.fileName) === sourceScript);
|
|
38
53
|
}
|
|
39
|
-
const [_serviceScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
|
|
40
|
-
const actualSourceFile = sourceScript ? program.getSourceFile(sourceScript.id) : sourceFile;
|
|
41
|
-
return getSemanticDiagnostics(actualSourceFile, cancellationToken)
|
|
42
|
-
.map(d => (0, transform_1.transformDiagnostic)(transform_1.ToSourceMode.SkipAssciated, language, d, program, true))
|
|
43
|
-
.filter(utils_1.notEmpty);
|
|
44
54
|
};
|
|
45
55
|
program.getGlobalDiagnostics = cancellationToken => {
|
|
46
56
|
return getGlobalDiagnostics(cancellationToken)
|
|
47
|
-
.map(d => (0, transform_1.transformDiagnostic)(
|
|
57
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
|
|
48
58
|
.filter(utils_1.notEmpty);
|
|
49
59
|
};
|
|
50
60
|
// @ts-ignore
|
|
51
61
|
program.getBindAndCheckDiagnostics = (sourceFile, cancellationToken) => {
|
|
52
62
|
if (!sourceFile) {
|
|
53
|
-
return
|
|
63
|
+
return getBindAndCheckDiagnostics(undefined, cancellationToken)
|
|
64
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
|
|
65
|
+
.filter(utils_1.notEmpty);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const [serviceScript, targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
|
|
69
|
+
const actualSourceFile = targetScript ? program.getSourceFile(targetScript.id) : sourceFile;
|
|
70
|
+
return getBindAndCheckDiagnostics(actualSourceFile, cancellationToken)
|
|
71
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, program, true))
|
|
72
|
+
.filter(utils_1.notEmpty)
|
|
73
|
+
.filter(d => !serviceScript || language.scripts.get(d.file.fileName) === sourceScript);
|
|
54
74
|
}
|
|
55
|
-
const [_serviceScript, sourceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
|
|
56
|
-
const actualSourceFile = sourceScript ? program.getSourceFile(sourceScript.id) : sourceFile;
|
|
57
|
-
return getBindAndCheckDiagnostics(actualSourceFile, cancellationToken)
|
|
58
|
-
.map(d => (0, transform_1.transformDiagnostic)(transform_1.ToSourceMode.SkipAssciated, language, d, program, true))
|
|
59
|
-
.filter(utils_1.notEmpty);
|
|
60
75
|
};
|
|
61
76
|
// fix https://github.com/vuejs/language-tools/issues/4099 with `incremental`
|
|
62
77
|
program.getSourceFileByPath = path => {
|
package/lib/node/transform.d.ts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import type { CodeInformation,
|
|
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
|
-
export declare
|
|
5
|
-
|
|
6
|
-
SkipAssciated = 1
|
|
7
|
-
}
|
|
8
|
-
export declare function transformCallHierarchyItem(mode: ToSourceMode, language: Language<string>, item: ts.CallHierarchyItem, filter: (data: CodeInformation) => boolean): ts.CallHierarchyItem;
|
|
9
|
-
export declare function transformDiagnostic<T extends ts.Diagnostic>(mode: ToSourceMode, language: Language<string>, diagnostic: T, program: ts.Program | undefined, isTsc: boolean): T | undefined;
|
|
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, program: ts.Program | undefined, isTsc: boolean): T | undefined;
|
|
10
6
|
export declare function fillSourceFileText(language: Language<string>, sourceFile: ts.SourceFile): void;
|
|
11
|
-
export declare function transformFileTextChanges(
|
|
12
|
-
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(
|
|
13
|
-
export declare function transformSpan(
|
|
7
|
+
export declare function transformFileTextChanges(language: Language<string>, changes: readonly ts.FileTextChanges[], filter: (data: CodeInformation) => boolean): ts.FileTextChanges[];
|
|
8
|
+
export declare function transformDocumentSpan<T extends ts.DocumentSpan>(language: Language<string>, documentSpan: T, filter: (data: CodeInformation) => boolean, shouldFallback?: boolean): T | undefined;
|
|
9
|
+
export declare function transformSpan(language: Language<string>, fileName: string | undefined, textSpan: ts.TextSpan | undefined, filter: (data: CodeInformation) => boolean): {
|
|
14
10
|
fileName: string;
|
|
15
11
|
textSpan: ts.TextSpan;
|
|
16
12
|
} | undefined;
|
|
17
|
-
export declare function transformTextChange(
|
|
18
|
-
export declare function transformTextSpan(
|
|
19
|
-
export declare function toSourceOffset(
|
|
20
|
-
export declare function toSourceOffsets(
|
|
21
|
-
export declare function toGeneratedOffset(serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>,
|
|
22
|
-
export declare function toGeneratedOffsets(serviceScript: TypeScriptServiceScript, sourceScript: SourceScript<string>,
|
|
23
|
-
export declare function getMappingOffset(
|
|
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;
|
package/lib/node/transform.js
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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 =
|
|
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
|
-
var ToSourceMode;
|
|
7
|
-
(function (ToSourceMode) {
|
|
8
|
-
ToSourceMode[ToSourceMode["IncludeAssciated"] = 0] = "IncludeAssciated";
|
|
9
|
-
ToSourceMode[ToSourceMode["SkipAssciated"] = 1] = "SkipAssciated";
|
|
10
|
-
})(ToSourceMode || (exports.ToSourceMode = ToSourceMode = {}));
|
|
11
6
|
const transformedDiagnostics = new WeakMap();
|
|
12
7
|
const transformedSourceFile = new WeakSet();
|
|
13
|
-
function transformCallHierarchyItem(
|
|
14
|
-
const span = transformSpan(
|
|
15
|
-
const selectionSpan = transformSpan(
|
|
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);
|
|
16
11
|
return {
|
|
17
12
|
...item,
|
|
18
13
|
file: span?.fileName ?? item.file,
|
|
@@ -21,21 +16,21 @@ function transformCallHierarchyItem(mode, language, item, filter) {
|
|
|
21
16
|
};
|
|
22
17
|
}
|
|
23
18
|
exports.transformCallHierarchyItem = transformCallHierarchyItem;
|
|
24
|
-
function transformDiagnostic(
|
|
19
|
+
function transformDiagnostic(language, diagnostic, program, isTsc) {
|
|
25
20
|
if (!transformedDiagnostics.has(diagnostic)) {
|
|
26
21
|
transformedDiagnostics.set(diagnostic, undefined);
|
|
27
22
|
const { relatedInformation } = diagnostic;
|
|
28
23
|
if (relatedInformation) {
|
|
29
24
|
diagnostic.relatedInformation = relatedInformation
|
|
30
|
-
.map(d => transformDiagnostic(
|
|
25
|
+
.map(d => transformDiagnostic(language, d, program, isTsc))
|
|
31
26
|
.filter(utils_1.notEmpty);
|
|
32
27
|
}
|
|
33
28
|
if (diagnostic.file !== undefined
|
|
34
29
|
&& diagnostic.start !== undefined
|
|
35
30
|
&& diagnostic.length !== undefined) {
|
|
36
|
-
const [serviceScript
|
|
31
|
+
const [serviceScript] = (0, utils_1.getServiceScript)(language, diagnostic.file.fileName);
|
|
37
32
|
if (serviceScript) {
|
|
38
|
-
const [sourceSpanFileName, sourceSpan] = transformTextSpan(
|
|
33
|
+
const [sourceSpanFileName, sourceSpan] = transformTextSpan(undefined, language, serviceScript, {
|
|
39
34
|
start: diagnostic.start,
|
|
40
35
|
length: diagnostic.length
|
|
41
36
|
}, language_core_1.shouldReportDiagnostics) ?? [];
|
|
@@ -73,21 +68,22 @@ function fillSourceFileText(language, sourceFile) {
|
|
|
73
68
|
return;
|
|
74
69
|
}
|
|
75
70
|
transformedSourceFile.add(sourceFile);
|
|
76
|
-
const [serviceScript
|
|
71
|
+
const [serviceScript] = (0, utils_1.getServiceScript)(language, sourceFile.fileName);
|
|
77
72
|
if (serviceScript && !serviceScript.preventLeadingOffset) {
|
|
73
|
+
const sourceScript = language.scripts.fromVirtualCode(serviceScript.code);
|
|
78
74
|
sourceFile.text = sourceScript.snapshot.getText(0, sourceScript.snapshot.getLength())
|
|
79
75
|
+ sourceFile.text.substring(sourceScript.snapshot.getLength());
|
|
80
76
|
}
|
|
81
77
|
}
|
|
82
78
|
exports.fillSourceFileText = fillSourceFileText;
|
|
83
|
-
function transformFileTextChanges(
|
|
79
|
+
function transformFileTextChanges(language, changes, filter) {
|
|
84
80
|
const changesPerFile = {};
|
|
85
81
|
const newFiles = new Set();
|
|
86
82
|
for (const fileChanges of changes) {
|
|
87
83
|
const [_, source] = (0, utils_1.getServiceScript)(language, fileChanges.fileName);
|
|
88
84
|
if (source) {
|
|
89
85
|
fileChanges.textChanges.forEach(c => {
|
|
90
|
-
const { fileName, textSpan } = transformSpan(
|
|
86
|
+
const { fileName, textSpan } = transformSpan(language, fileChanges.fileName, c.span, filter) ?? {};
|
|
91
87
|
if (fileName && textSpan) {
|
|
92
88
|
(changesPerFile[fileName] ?? (changesPerFile[fileName] = [])).push({ ...c, span: textSpan });
|
|
93
89
|
}
|
|
@@ -114,8 +110,8 @@ function transformFileTextChanges(mode, language, changes, filter) {
|
|
|
114
110
|
return result;
|
|
115
111
|
}
|
|
116
112
|
exports.transformFileTextChanges = transformFileTextChanges;
|
|
117
|
-
function transformDocumentSpan(
|
|
118
|
-
let textSpan = transformSpan(
|
|
113
|
+
function transformDocumentSpan(language, documentSpan, filter, shouldFallback) {
|
|
114
|
+
let textSpan = transformSpan(language, documentSpan.fileName, documentSpan.textSpan, filter);
|
|
119
115
|
if (!textSpan && shouldFallback) {
|
|
120
116
|
textSpan = {
|
|
121
117
|
fileName: documentSpan.fileName,
|
|
@@ -125,9 +121,9 @@ function transformDocumentSpan(mode, language, documentSpan, filter, shouldFallb
|
|
|
125
121
|
if (!textSpan) {
|
|
126
122
|
return;
|
|
127
123
|
}
|
|
128
|
-
const contextSpan = transformSpan(
|
|
129
|
-
const originalTextSpan = transformSpan(
|
|
130
|
-
const originalContextSpan = transformSpan(
|
|
124
|
+
const contextSpan = transformSpan(language, documentSpan.fileName, documentSpan.contextSpan, filter);
|
|
125
|
+
const originalTextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalTextSpan, filter);
|
|
126
|
+
const originalContextSpan = transformSpan(language, documentSpan.originalFileName, documentSpan.originalContextSpan, filter);
|
|
131
127
|
return {
|
|
132
128
|
...documentSpan,
|
|
133
129
|
fileName: textSpan.fileName,
|
|
@@ -139,16 +135,13 @@ function transformDocumentSpan(mode, language, documentSpan, filter, shouldFallb
|
|
|
139
135
|
};
|
|
140
136
|
}
|
|
141
137
|
exports.transformDocumentSpan = transformDocumentSpan;
|
|
142
|
-
function transformSpan(
|
|
138
|
+
function transformSpan(language, fileName, textSpan, filter) {
|
|
143
139
|
if (!fileName || !textSpan) {
|
|
144
140
|
return;
|
|
145
141
|
}
|
|
146
|
-
const [serviceScript
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
else if (serviceScript) {
|
|
151
|
-
const [sourceSpanFileName, sourceSpan] = transformTextSpan(mode, language, serviceScript, sourceScript, textSpan, filter) ?? [];
|
|
142
|
+
const [serviceScript] = (0, utils_1.getServiceScript)(language, fileName);
|
|
143
|
+
if (serviceScript) {
|
|
144
|
+
const [sourceSpanFileName, sourceSpan] = transformTextSpan(undefined, language, serviceScript, textSpan, filter) ?? [];
|
|
152
145
|
if (sourceSpan && sourceSpanFileName) {
|
|
153
146
|
return {
|
|
154
147
|
fileName: sourceSpanFileName,
|
|
@@ -164,8 +157,8 @@ function transformSpan(mode, language, fileName, textSpan, filter) {
|
|
|
164
157
|
}
|
|
165
158
|
}
|
|
166
159
|
exports.transformSpan = transformSpan;
|
|
167
|
-
function transformTextChange(
|
|
168
|
-
const [sourceSpanFileName, sourceSpan] = transformTextSpan(
|
|
160
|
+
function transformTextChange(sourceScript, language, serviceScript, textChange, filter) {
|
|
161
|
+
const [sourceSpanFileName, sourceSpan] = transformTextSpan(sourceScript, language, serviceScript, textChange.span, filter) ?? [];
|
|
169
162
|
if (sourceSpan && sourceSpanFileName) {
|
|
170
163
|
return [sourceSpanFileName, {
|
|
171
164
|
newText: textChange.newText,
|
|
@@ -175,11 +168,11 @@ function transformTextChange(mode, language, serviceScript, sourceScript, textCh
|
|
|
175
168
|
return undefined;
|
|
176
169
|
}
|
|
177
170
|
exports.transformTextChange = transformTextChange;
|
|
178
|
-
function transformTextSpan(
|
|
171
|
+
function transformTextSpan(sourceScript, language, serviceScript, textSpan, filter) {
|
|
179
172
|
const start = textSpan.start;
|
|
180
173
|
const end = textSpan.start + textSpan.length;
|
|
181
|
-
for (const sourceStart of toSourceOffsets(
|
|
182
|
-
for (const sourceEnd of toSourceOffsets(
|
|
174
|
+
for (const sourceStart of toSourceOffsets(sourceScript, language, serviceScript, start, filter)) {
|
|
175
|
+
for (const sourceEnd of toSourceOffsets(sourceScript, language, serviceScript, end, filter)) {
|
|
183
176
|
if (sourceStart[0] === sourceEnd[0]
|
|
184
177
|
&& sourceEnd[1] >= sourceStart[1]) {
|
|
185
178
|
return [sourceStart[0], {
|
|
@@ -191,16 +184,16 @@ function transformTextSpan(mode, language, serviceScript, sourceScript, textSpan
|
|
|
191
184
|
}
|
|
192
185
|
}
|
|
193
186
|
exports.transformTextSpan = transformTextSpan;
|
|
194
|
-
function toSourceOffset(
|
|
195
|
-
for (const source of toSourceOffsets(
|
|
187
|
+
function toSourceOffset(sourceScript, language, serviceScript, position, filter) {
|
|
188
|
+
for (const source of toSourceOffsets(sourceScript, language, serviceScript, position, filter)) {
|
|
196
189
|
return source;
|
|
197
190
|
}
|
|
198
191
|
}
|
|
199
192
|
exports.toSourceOffset = toSourceOffset;
|
|
200
|
-
function* toSourceOffsets(
|
|
201
|
-
if (
|
|
202
|
-
const map = language.maps.get(serviceScript.code);
|
|
203
|
-
for (const [sourceOffset, mapping] of map.getSourceOffsets(position - getMappingOffset(
|
|
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))) {
|
|
204
197
|
if (filter(mapping.data)) {
|
|
205
198
|
yield [sourceScript.id, sourceOffset];
|
|
206
199
|
}
|
|
@@ -208,7 +201,7 @@ function* toSourceOffsets(mode, language, serviceScript, sourceScript, position,
|
|
|
208
201
|
}
|
|
209
202
|
else {
|
|
210
203
|
for (const [fileName, _snapshot, map] of language.maps.forEach(serviceScript.code)) {
|
|
211
|
-
for (const [sourceOffset, mapping] of map.getSourceOffsets(position - getMappingOffset(
|
|
204
|
+
for (const [sourceOffset, mapping] of map.getSourceOffsets(position - getMappingOffset(language, serviceScript))) {
|
|
212
205
|
if (filter(mapping.data)) {
|
|
213
206
|
yield [fileName, sourceOffset];
|
|
214
207
|
}
|
|
@@ -217,24 +210,27 @@ function* toSourceOffsets(mode, language, serviceScript, sourceScript, position,
|
|
|
217
210
|
}
|
|
218
211
|
}
|
|
219
212
|
exports.toSourceOffsets = toSourceOffsets;
|
|
220
|
-
function toGeneratedOffset(serviceScript, sourceScript,
|
|
221
|
-
for (const [generateOffset] of toGeneratedOffsets(serviceScript, sourceScript,
|
|
213
|
+
function toGeneratedOffset(language, serviceScript, sourceScript, position, filter) {
|
|
214
|
+
for (const [generateOffset] of toGeneratedOffsets(language, serviceScript, sourceScript, position, filter)) {
|
|
222
215
|
return generateOffset;
|
|
223
216
|
}
|
|
224
217
|
}
|
|
225
218
|
exports.toGeneratedOffset = toGeneratedOffset;
|
|
226
|
-
function* toGeneratedOffsets(serviceScript, sourceScript,
|
|
219
|
+
function* toGeneratedOffsets(language, serviceScript, sourceScript, position, filter) {
|
|
220
|
+
const map = language.maps.get(serviceScript.code, sourceScript);
|
|
227
221
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
228
222
|
if (filter(mapping.data)) {
|
|
229
|
-
yield [generateOffset + getMappingOffset(
|
|
223
|
+
yield [generateOffset + getMappingOffset(language, serviceScript), mapping];
|
|
230
224
|
}
|
|
231
225
|
}
|
|
232
226
|
}
|
|
233
227
|
exports.toGeneratedOffsets = toGeneratedOffsets;
|
|
234
|
-
function getMappingOffset(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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();
|
|
238
234
|
}
|
|
239
235
|
exports.getMappingOffset = getMappingOffset;
|
|
240
236
|
//# sourceMappingURL=transform.js.map
|
package/lib/node/utils.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
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): [TypeScriptServiceScript, SourceScript<string>,
|
|
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
|
@@ -6,34 +6,25 @@ function notEmpty(value) {
|
|
|
6
6
|
}
|
|
7
7
|
exports.notEmpty = notEmpty;
|
|
8
8
|
function getServiceScript(language, fileName) {
|
|
9
|
-
|
|
10
|
-
if (sourceScript?.targetIds
|
|
11
|
-
const sourceId = sourceScript.id;
|
|
9
|
+
const sourceScript = language.scripts.get(fileName);
|
|
10
|
+
if (sourceScript?.targetIds.size) {
|
|
12
11
|
for (const targetId of sourceScript.targetIds) {
|
|
13
|
-
|
|
14
|
-
if (
|
|
15
|
-
const serviceScript =
|
|
12
|
+
const targetScript = language.scripts.get(targetId);
|
|
13
|
+
if (targetScript?.generated) {
|
|
14
|
+
const serviceScript = targetScript.generated.languagePlugin.typescript?.getServiceScript(targetScript.generated.root);
|
|
16
15
|
if (serviceScript) {
|
|
17
|
-
|
|
18
|
-
if (id === sourceId) {
|
|
19
|
-
return [serviceScript, sourceScript, map];
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
break;
|
|
16
|
+
return [serviceScript, targetScript, sourceScript];
|
|
23
17
|
}
|
|
24
18
|
}
|
|
25
19
|
}
|
|
26
20
|
}
|
|
27
21
|
if (sourceScript?.associatedOnly) {
|
|
28
|
-
return [undefined, sourceScript,
|
|
22
|
+
return [undefined, sourceScript, sourceScript];
|
|
29
23
|
}
|
|
30
24
|
if (sourceScript?.generated) {
|
|
31
25
|
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
32
26
|
if (serviceScript) {
|
|
33
|
-
|
|
34
|
-
if (map) {
|
|
35
|
-
return [serviceScript, sourceScript, map];
|
|
36
|
-
}
|
|
27
|
+
return [serviceScript, sourceScript, sourceScript];
|
|
37
28
|
}
|
|
38
29
|
}
|
|
39
30
|
return [undefined, undefined, undefined];
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import { LanguagePlugin } from '@volar/language-core';
|
|
1
|
+
import { Language, LanguagePlugin } from '@volar/language-core';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind,
|
|
3
|
+
export declare function createAsyncLanguageServicePlugin(extensions: string[], scriptKind: ts.ScriptKind, create: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => Promise<{
|
|
4
|
+
languagePlugins: LanguagePlugin<string>[];
|
|
5
|
+
setup?: (language: Language<string>) => void;
|
|
6
|
+
}>): ts.server.PluginModuleFactory;
|
|
@@ -6,18 +6,15 @@ const common_1 = require("../common");
|
|
|
6
6
|
const decorateLanguageService_1 = require("../node/decorateLanguageService");
|
|
7
7
|
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost");
|
|
8
8
|
const createLanguageServicePlugin_1 = require("./createLanguageServicePlugin");
|
|
9
|
-
|
|
10
|
-
const decoratedLanguageServices = new WeakSet();
|
|
11
|
-
const decoratedLanguageServiceHosts = new WeakSet();
|
|
12
|
-
function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePlugins) {
|
|
9
|
+
function createAsyncLanguageServicePlugin(extensions, scriptKind, create) {
|
|
13
10
|
return modules => {
|
|
14
11
|
const { typescript: ts } = modules;
|
|
15
12
|
const pluginModule = {
|
|
16
13
|
create(info) {
|
|
17
|
-
if (!decoratedLanguageServices.has(info.languageService)
|
|
18
|
-
&& !decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
|
|
19
|
-
decoratedLanguageServices.add(info.languageService);
|
|
20
|
-
decoratedLanguageServiceHosts.add(info.languageServiceHost);
|
|
14
|
+
if (!createLanguageServicePlugin_1.decoratedLanguageServices.has(info.languageService)
|
|
15
|
+
&& !createLanguageServicePlugin_1.decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
|
|
16
|
+
createLanguageServicePlugin_1.decoratedLanguageServices.add(info.languageService);
|
|
17
|
+
createLanguageServicePlugin_1.decoratedLanguageServiceHosts.add(info.languageServiceHost);
|
|
21
18
|
const emptySnapshot = ts.ScriptSnapshot.fromString('');
|
|
22
19
|
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
|
|
23
20
|
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
|
|
@@ -52,7 +49,7 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
|
|
|
52
49
|
return getProjectVersion();
|
|
53
50
|
};
|
|
54
51
|
}
|
|
55
|
-
|
|
52
|
+
create(ts, info).then(({ languagePlugins, setup }) => {
|
|
56
53
|
const syncedScriptVersions = new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames);
|
|
57
54
|
const language = (0, language_core_1.createLanguage)([
|
|
58
55
|
...languagePlugins,
|
|
@@ -73,6 +70,7 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
|
|
|
73
70
|
});
|
|
74
71
|
(0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService);
|
|
75
72
|
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost);
|
|
73
|
+
setup?.(language);
|
|
76
74
|
info.project.markAsDirty();
|
|
77
75
|
initialized = true;
|
|
78
76
|
});
|
|
@@ -81,15 +79,15 @@ function createAsyncLanguageServicePlugin(extensions, scriptKind, loadLanguagePl
|
|
|
81
79
|
},
|
|
82
80
|
getExternalFiles(project, updateLevel = 0) {
|
|
83
81
|
if (updateLevel >= (1)
|
|
84
|
-
|| !externalFiles.has(project)) {
|
|
85
|
-
const oldFiles = externalFiles.get(project);
|
|
82
|
+
|| !createLanguageServicePlugin_1.externalFiles.has(project)) {
|
|
83
|
+
const oldFiles = createLanguageServicePlugin_1.externalFiles.get(project);
|
|
86
84
|
const newFiles = extensions.length ? (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions) : [];
|
|
87
|
-
externalFiles.set(project, newFiles);
|
|
85
|
+
createLanguageServicePlugin_1.externalFiles.set(project, newFiles);
|
|
88
86
|
if (oldFiles && !(0, createLanguageServicePlugin_1.arrayItemsEqual)(oldFiles, newFiles)) {
|
|
89
87
|
project.refreshDiagnostics();
|
|
90
88
|
}
|
|
91
89
|
}
|
|
92
|
-
return externalFiles.get(project);
|
|
90
|
+
return createLanguageServicePlugin_1.externalFiles.get(project);
|
|
93
91
|
},
|
|
94
92
|
};
|
|
95
93
|
return pluginModule;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import { LanguagePlugin } from '@volar/language-core';
|
|
1
|
+
import { Language, LanguagePlugin } from '@volar/language-core';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
export declare
|
|
3
|
+
export declare const externalFiles: WeakMap<ts.server.Project, string[]>;
|
|
4
|
+
export declare const projectExternalFileExtensions: WeakMap<ts.server.Project, string[]>;
|
|
5
|
+
export declare const decoratedLanguageServices: WeakSet<ts.LanguageService>;
|
|
6
|
+
export declare const decoratedLanguageServiceHosts: WeakSet<ts.LanguageServiceHost>;
|
|
7
|
+
export declare function createLanguageServicePlugin(create: (ts: typeof import('typescript'), info: ts.server.PluginCreateInfo) => {
|
|
8
|
+
languagePlugins: LanguagePlugin<string>[];
|
|
9
|
+
setup?: (language: Language<string>) => void;
|
|
10
|
+
}): ts.server.PluginModuleFactory;
|
|
4
11
|
export declare function arrayItemsEqual(a: string[], b: string[]): boolean;
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.arrayItemsEqual = exports.createLanguageServicePlugin = void 0;
|
|
3
|
+
exports.arrayItemsEqual = exports.createLanguageServicePlugin = exports.decoratedLanguageServiceHosts = exports.decoratedLanguageServices = exports.projectExternalFileExtensions = exports.externalFiles = void 0;
|
|
4
4
|
const language_core_1 = require("@volar/language-core");
|
|
5
5
|
const common_1 = require("../common");
|
|
6
6
|
const decorateLanguageService_1 = require("../node/decorateLanguageService");
|
|
7
7
|
const decorateLanguageServiceHost_1 = require("../node/decorateLanguageServiceHost");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function createLanguageServicePlugin(
|
|
8
|
+
exports.externalFiles = new WeakMap();
|
|
9
|
+
exports.projectExternalFileExtensions = new WeakMap();
|
|
10
|
+
exports.decoratedLanguageServices = new WeakSet();
|
|
11
|
+
exports.decoratedLanguageServiceHosts = new WeakSet();
|
|
12
|
+
function createLanguageServicePlugin(create) {
|
|
13
13
|
return modules => {
|
|
14
14
|
const { typescript: ts } = modules;
|
|
15
15
|
const pluginModule = {
|
|
16
16
|
create(info) {
|
|
17
|
-
if (!decoratedLanguageServices.has(info.languageService)
|
|
18
|
-
&& !decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
|
|
19
|
-
decoratedLanguageServices.add(info.languageService);
|
|
20
|
-
decoratedLanguageServiceHosts.add(info.languageServiceHost);
|
|
21
|
-
const languagePlugins =
|
|
17
|
+
if (!exports.decoratedLanguageServices.has(info.languageService)
|
|
18
|
+
&& !exports.decoratedLanguageServiceHosts.has(info.languageServiceHost)) {
|
|
19
|
+
exports.decoratedLanguageServices.add(info.languageService);
|
|
20
|
+
exports.decoratedLanguageServiceHosts.add(info.languageServiceHost);
|
|
21
|
+
const { languagePlugins, setup } = create(ts, info);
|
|
22
22
|
const extensions = languagePlugins
|
|
23
23
|
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
|
|
24
24
|
.flat();
|
|
25
|
-
projectExternalFileExtensions.set(info.project, extensions);
|
|
25
|
+
exports.projectExternalFileExtensions.set(info.project, extensions);
|
|
26
26
|
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
|
|
27
27
|
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
|
|
28
28
|
const syncedScriptVersions = new language_core_1.FileMap(ts.sys.useCaseSensitiveFileNames);
|
|
@@ -45,21 +45,22 @@ function createLanguageServicePlugin(loadLanguagePlugins) {
|
|
|
45
45
|
});
|
|
46
46
|
(0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService);
|
|
47
47
|
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost);
|
|
48
|
+
setup?.(language);
|
|
48
49
|
}
|
|
49
50
|
return info.languageService;
|
|
50
51
|
},
|
|
51
52
|
getExternalFiles(project, updateLevel = 0) {
|
|
52
53
|
if (updateLevel >= (1)
|
|
53
|
-
|| !externalFiles.has(project)) {
|
|
54
|
-
const oldFiles = externalFiles.get(project);
|
|
55
|
-
const extensions = projectExternalFileExtensions.get(project);
|
|
54
|
+
|| !exports.externalFiles.has(project)) {
|
|
55
|
+
const oldFiles = exports.externalFiles.get(project);
|
|
56
|
+
const extensions = exports.projectExternalFileExtensions.get(project);
|
|
56
57
|
const newFiles = extensions?.length ? (0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, extensions) : [];
|
|
57
|
-
externalFiles.set(project, newFiles);
|
|
58
|
+
exports.externalFiles.set(project, newFiles);
|
|
58
59
|
if (oldFiles && !arrayItemsEqual(oldFiles, newFiles)) {
|
|
59
60
|
project.refreshDiagnostics();
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
|
-
return externalFiles.get(project);
|
|
63
|
+
return exports.externalFiles.get(project);
|
|
63
64
|
},
|
|
64
65
|
};
|
|
65
66
|
return pluginModule;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volar/typescript",
|
|
3
|
-
"version": "2.3.0
|
|
3
|
+
"version": "2.3.0",
|
|
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
|
|
15
|
+
"@volar/language-core": "2.3.0",
|
|
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
|
|
22
|
+
"@volar/language-service": "2.3.0"
|
|
23
23
|
},
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "4f6488605e22e0f76ea877460848a443fd3e8762"
|
|
25
25
|
}
|