@volar/typescript 2.2.0-alpha.0 → 2.2.0-alpha.10
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/documentRegistry.d.ts +2 -0
- package/lib/documentRegistry.js +14 -0
- package/lib/node/decorateLanguageService.js +216 -139
- package/lib/node/decorateLanguageServiceHost.d.ts +2 -2
- package/lib/node/decorateLanguageServiceHost.js +55 -60
- package/lib/node/decorateProgram.js +14 -5
- package/lib/node/dedupe.d.ts +0 -1
- package/lib/node/dedupe.js +1 -9
- package/lib/node/proxyCreateProgram.d.ts +2 -2
- package/lib/node/proxyCreateProgram.js +138 -94
- package/lib/node/transform.d.ts +11 -6
- package/lib/node/transform.js +83 -47
- package/lib/protocol/createProject.js +1 -1
- package/lib/quickstart/createAsyncLanguageServicePlugin.d.ts +1 -1
- package/lib/quickstart/createAsyncLanguageServicePlugin.js +3 -3
- package/lib/quickstart/createLanguageServicePlugin.d.ts +1 -1
- package/lib/quickstart/createLanguageServicePlugin.js +3 -3
- package/lib/quickstart/runTsc.d.ts +2 -1
- package/lib/quickstart/runTsc.js +11 -6
- package/lib/resolveModuleName.d.ts +1 -1
- package/lib/resolveModuleName.js +41 -24
- package/package.json +4 -4
|
@@ -1,25 +1,23 @@
|
|
|
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
|
|
7
|
-
|
|
8
|
-
const exts = language.plugins
|
|
5
|
+
function decorateLanguageServiceHost(ts, language, languageServiceHost) {
|
|
6
|
+
const extensions = language.plugins
|
|
9
7
|
.map(plugin => plugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? [])
|
|
10
8
|
.flat();
|
|
11
9
|
const scripts = new Map();
|
|
10
|
+
const crashFileNames = new Set();
|
|
12
11
|
const readDirectory = languageServiceHost.readDirectory?.bind(languageServiceHost);
|
|
13
12
|
const resolveModuleNameLiterals = languageServiceHost.resolveModuleNameLiterals?.bind(languageServiceHost);
|
|
14
13
|
const resolveModuleNames = languageServiceHost.resolveModuleNames?.bind(languageServiceHost);
|
|
15
|
-
const getProjectVersion = languageServiceHost.getProjectVersion?.bind(languageServiceHost);
|
|
16
14
|
const getScriptSnapshot = languageServiceHost.getScriptSnapshot.bind(languageServiceHost);
|
|
17
15
|
const getScriptKind = languageServiceHost.getScriptKind?.bind(languageServiceHost);
|
|
18
16
|
// path completion
|
|
19
17
|
if (readDirectory) {
|
|
20
18
|
languageServiceHost.readDirectory = (path, extensions, exclude, include, depth) => {
|
|
21
19
|
if (extensions) {
|
|
22
|
-
for (const ext of
|
|
20
|
+
for (const ext of extensions) {
|
|
23
21
|
if (!extensions.includes(ext)) {
|
|
24
22
|
extensions = [...extensions, ...ext];
|
|
25
23
|
}
|
|
@@ -28,91 +26,88 @@ function decorateLanguageServiceHost(language, languageServiceHost, ts) {
|
|
|
28
26
|
return readDirectory(path, extensions, exclude, include, depth);
|
|
29
27
|
};
|
|
30
28
|
}
|
|
31
|
-
if (
|
|
29
|
+
if (extensions.length) {
|
|
32
30
|
const resolveModuleName = (0, resolveModuleName_1.createResolveModuleName)(ts, languageServiceHost, language.plugins, fileName => language.scripts.get(fileName));
|
|
31
|
+
const getCanonicalFileName = languageServiceHost.useCaseSensitiveFileNames?.()
|
|
32
|
+
? (fileName) => fileName
|
|
33
|
+
: (fileName) => fileName.toLowerCase();
|
|
34
|
+
const moduleResolutionCache = ts.createModuleResolutionCache(languageServiceHost.getCurrentDirectory(), getCanonicalFileName, languageServiceHost.getCompilationSettings());
|
|
33
35
|
if (resolveModuleNameLiterals) {
|
|
34
36
|
languageServiceHost.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, options, ...rest) => {
|
|
35
|
-
if (moduleLiterals.every(name => !
|
|
37
|
+
if (moduleLiterals.every(name => !extensions.some(ext => name.text.endsWith(ext)))) {
|
|
36
38
|
return resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options, ...rest);
|
|
37
39
|
}
|
|
38
40
|
return moduleLiterals.map(moduleLiteral => {
|
|
39
|
-
return resolveModuleName(moduleLiteral.text, containingFile, options,
|
|
41
|
+
return resolveModuleName(moduleLiteral.text, containingFile, options, moduleResolutionCache, redirectedReference);
|
|
40
42
|
});
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
if (resolveModuleNames) {
|
|
44
46
|
languageServiceHost.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, options, containingSourceFile) => {
|
|
45
|
-
if (moduleNames.every(name => !
|
|
47
|
+
if (moduleNames.every(name => !extensions.some(ext => name.endsWith(ext)))) {
|
|
46
48
|
return resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, options, containingSourceFile);
|
|
47
49
|
}
|
|
48
50
|
return moduleNames.map(moduleName => {
|
|
49
|
-
return resolveModuleName(moduleName, containingFile, options,
|
|
51
|
+
return resolveModuleName(moduleName, containingFile, options, moduleResolutionCache, redirectedReference).resolvedModule;
|
|
50
52
|
});
|
|
51
53
|
};
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
|
-
if (getProjectVersion) {
|
|
55
|
-
languageServiceHost.getProjectVersion = () => {
|
|
56
|
-
return getProjectVersion() + ':' + extraProjectVersion;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
56
|
languageServiceHost.getScriptSnapshot = fileName => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return
|
|
57
|
+
const virtualScript = updateVirtualScript(fileName);
|
|
58
|
+
if (virtualScript) {
|
|
59
|
+
return virtualScript.snapshot;
|
|
63
60
|
}
|
|
64
61
|
return getScriptSnapshot(fileName);
|
|
65
62
|
};
|
|
66
63
|
if (getScriptKind) {
|
|
67
64
|
languageServiceHost.getScriptKind = fileName => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (script) {
|
|
72
|
-
return script.kind;
|
|
73
|
-
}
|
|
74
|
-
return ts.ScriptKind.Deferred;
|
|
65
|
+
const virtualScript = updateVirtualScript(fileName);
|
|
66
|
+
if (virtualScript) {
|
|
67
|
+
return virtualScript.kind;
|
|
75
68
|
}
|
|
76
69
|
return getScriptKind(fileName);
|
|
77
70
|
};
|
|
78
71
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
72
|
+
function updateVirtualScript(fileName) {
|
|
73
|
+
if (crashFileNames.has(fileName)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
let version;
|
|
77
|
+
try {
|
|
78
|
+
version = languageServiceHost.getScriptVersion(fileName);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// fix https://github.com/vuejs/language-tools/issues/4278
|
|
82
|
+
crashFileNames.add(fileName);
|
|
83
|
+
}
|
|
84
|
+
if (version === undefined) {
|
|
85
|
+
// somehow getScriptVersion returns undefined
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
let script = scripts.get(fileName);
|
|
89
|
+
if (!script || script[0] !== version) {
|
|
90
|
+
script = [version];
|
|
91
|
+
const sourceScript = language.scripts.get(fileName);
|
|
92
|
+
if (sourceScript?.generated) {
|
|
93
|
+
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
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
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (sourceScript.generated.languagePlugin.typescript?.getExtraServiceScripts) {
|
|
105
|
+
console.warn('getExtraServiceScripts() is not available in TS plugin.');
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
|
-
|
|
105
|
-
extraProjectVersion++;
|
|
106
|
-
language.scripts.delete(fileName);
|
|
107
|
-
}
|
|
108
|
-
scripts.set(fileName, {
|
|
109
|
-
version,
|
|
110
|
-
extension,
|
|
111
|
-
snapshot: snapshotSnapshot,
|
|
112
|
-
kind: scriptKind,
|
|
113
|
-
});
|
|
108
|
+
scripts.set(fileName, script);
|
|
114
109
|
}
|
|
115
|
-
return
|
|
110
|
+
return script[1];
|
|
116
111
|
}
|
|
117
112
|
}
|
|
118
113
|
exports.decorateLanguageServiceHost = decorateLanguageServiceHost;
|
|
@@ -9,6 +9,7 @@ function decorateProgram(language, program) {
|
|
|
9
9
|
const getSyntacticDiagnostics = program.getSyntacticDiagnostics;
|
|
10
10
|
const getSemanticDiagnostics = program.getSemanticDiagnostics;
|
|
11
11
|
const getGlobalDiagnostics = program.getGlobalDiagnostics;
|
|
12
|
+
const getSourceFileByPath = program.getSourceFileByPath;
|
|
12
13
|
// for tsc --noEmit --watch
|
|
13
14
|
// @ts-ignore
|
|
14
15
|
const getBindAndCheckDiagnostics = program.getBindAndCheckDiagnostics;
|
|
@@ -17,31 +18,39 @@ function decorateProgram(language, program) {
|
|
|
17
18
|
return {
|
|
18
19
|
...result,
|
|
19
20
|
diagnostics: result.diagnostics
|
|
20
|
-
.map(d => (0, transform_1.transformDiagnostic)(language, d))
|
|
21
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, true))
|
|
21
22
|
.filter(utils_1.notEmpty),
|
|
22
23
|
};
|
|
23
24
|
};
|
|
24
25
|
program.getSyntacticDiagnostics = (sourceFile, cancellationToken) => {
|
|
25
26
|
return getSyntacticDiagnostics(sourceFile, cancellationToken)
|
|
26
|
-
.map(d => (0, transform_1.transformDiagnostic)(language, d))
|
|
27
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, true))
|
|
27
28
|
.filter(utils_1.notEmpty);
|
|
28
29
|
};
|
|
29
30
|
program.getSemanticDiagnostics = (sourceFile, cancellationToken) => {
|
|
30
31
|
return getSemanticDiagnostics(sourceFile, cancellationToken)
|
|
31
|
-
.map(d => (0, transform_1.transformDiagnostic)(language, d))
|
|
32
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, true))
|
|
32
33
|
.filter(utils_1.notEmpty);
|
|
33
34
|
};
|
|
34
35
|
program.getGlobalDiagnostics = cancellationToken => {
|
|
35
36
|
return getGlobalDiagnostics(cancellationToken)
|
|
36
|
-
.map(d => (0, transform_1.transformDiagnostic)(language, d))
|
|
37
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, true))
|
|
37
38
|
.filter(utils_1.notEmpty);
|
|
38
39
|
};
|
|
39
40
|
// @ts-ignore
|
|
40
41
|
program.getBindAndCheckDiagnostics = (sourceFile, cancellationToken) => {
|
|
41
42
|
return getBindAndCheckDiagnostics(sourceFile, cancellationToken)
|
|
42
|
-
.map(d => (0, transform_1.transformDiagnostic)(language, d))
|
|
43
|
+
.map(d => (0, transform_1.transformDiagnostic)(language, d, true))
|
|
43
44
|
.filter(utils_1.notEmpty);
|
|
44
45
|
};
|
|
46
|
+
// fix https://github.com/vuejs/language-tools/issues/4099 with `incremental`
|
|
47
|
+
program.getSourceFileByPath = path => {
|
|
48
|
+
const sourceFile = getSourceFileByPath(path);
|
|
49
|
+
if (sourceFile) {
|
|
50
|
+
(0, transform_1.fillSourceFileText)(language, sourceFile);
|
|
51
|
+
}
|
|
52
|
+
return sourceFile;
|
|
53
|
+
};
|
|
45
54
|
}
|
|
46
55
|
exports.decorateProgram = decorateProgram;
|
|
47
56
|
//# sourceMappingURL=decorateProgram.js.map
|
package/lib/node/dedupe.d.ts
CHANGED
package/lib/node/dedupe.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dedupeDocumentSpans =
|
|
4
|
-
function dedupeReferencedSymbols(items) {
|
|
5
|
-
return dedupe(items, item => [
|
|
6
|
-
item.definition.fileName,
|
|
7
|
-
item.definition.textSpan.start,
|
|
8
|
-
item.definition.textSpan.length,
|
|
9
|
-
].join(':'));
|
|
10
|
-
}
|
|
11
|
-
exports.dedupeReferencedSymbols = dedupeReferencedSymbols;
|
|
3
|
+
exports.dedupeDocumentSpans = void 0;
|
|
12
4
|
function dedupeDocumentSpans(items) {
|
|
13
5
|
return dedupe(items, item => [
|
|
14
6
|
item.fileName,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type * as ts from 'typescript';
|
|
2
1
|
import { LanguagePlugin } from '@volar/language-core';
|
|
3
|
-
|
|
2
|
+
import type * as ts from 'typescript';
|
|
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;
|
|
@@ -1,117 +1,161 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.proxyCreateProgram = void 0;
|
|
4
|
-
const decorateProgram_1 = require("./decorateProgram");
|
|
5
4
|
const language_core_1 = require("@volar/language-core");
|
|
6
|
-
|
|
5
|
+
const resolveModuleName_1 = require("../resolveModuleName");
|
|
6
|
+
const decorateProgram_1 = require("./decorateProgram");
|
|
7
|
+
const arrayEqual = (a, b) => {
|
|
8
|
+
if (a.length !== b.length) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
for (let i = 0; i < a.length; i++) {
|
|
12
|
+
if (a[i] !== b[i]) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
};
|
|
18
|
+
const objectEqual = (a, b) => {
|
|
19
|
+
const keysA = Object.keys(a);
|
|
20
|
+
const keysB = Object.keys(b);
|
|
21
|
+
if (keysA.length !== keysB.length) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
for (const key of keysA) {
|
|
25
|
+
if (a[key] !== b[key]) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
function proxyCreateProgram(ts, original, getLanguagePlugins, getLanguageId) {
|
|
32
|
+
const sourceFileSnapshots = new Map();
|
|
33
|
+
const parsedSourceFiles = new WeakMap();
|
|
34
|
+
let lastOptions;
|
|
35
|
+
let languagePlugins;
|
|
36
|
+
let language;
|
|
37
|
+
let moduleResolutionCache;
|
|
7
38
|
return new Proxy(original, {
|
|
8
39
|
apply: (target, thisArg, args) => {
|
|
9
40
|
const options = args[0];
|
|
10
41
|
assert(!!options.host, '!!options.host');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
language.scripts.delete(fileName);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
const originalSourceFiles = new Map();
|
|
41
|
-
const parsedSourceFiles = new WeakMap();
|
|
42
|
-
const arbitraryExtensions = extensions.map(ext => `.d${ext}.ts`);
|
|
43
|
-
const originalHost = options.host;
|
|
44
|
-
const moduleResolutionHost = {
|
|
45
|
-
...originalHost,
|
|
46
|
-
fileExists(fileName) {
|
|
47
|
-
for (let i = 0; i < arbitraryExtensions.length; i++) {
|
|
48
|
-
if (fileName.endsWith(arbitraryExtensions[i])) {
|
|
49
|
-
return originalHost.fileExists(fileName.slice(0, -arbitraryExtensions[i].length) + extensions[i]);
|
|
42
|
+
if (!lastOptions
|
|
43
|
+
|| !languagePlugins
|
|
44
|
+
|| !language
|
|
45
|
+
|| !arrayEqual(options.rootNames, lastOptions.rootNames)
|
|
46
|
+
|| !objectEqual(options.options, lastOptions.options)) {
|
|
47
|
+
moduleResolutionCache = ts.createModuleResolutionCache(options.host.getCurrentDirectory(), options.host.getCanonicalFileName, options.options);
|
|
48
|
+
lastOptions = options;
|
|
49
|
+
languagePlugins = getLanguagePlugins(ts, options);
|
|
50
|
+
language = (0, language_core_1.createLanguage)(languagePlugins, ts.sys.useCaseSensitiveFileNames, fileName => {
|
|
51
|
+
if (!sourceFileSnapshots.has(fileName)) {
|
|
52
|
+
const sourceFileText = originalHost.readFile(fileName);
|
|
53
|
+
if (sourceFileText !== undefined) {
|
|
54
|
+
sourceFileSnapshots.set(fileName, [undefined, {
|
|
55
|
+
getChangeRange() {
|
|
56
|
+
return undefined;
|
|
57
|
+
},
|
|
58
|
+
getLength() {
|
|
59
|
+
return sourceFileText.length;
|
|
60
|
+
},
|
|
61
|
+
getText(start, end) {
|
|
62
|
+
return sourceFileText.substring(start, end);
|
|
63
|
+
},
|
|
64
|
+
}]);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
sourceFileSnapshots.set(fileName, [undefined, undefined]);
|
|
50
68
|
}
|
|
51
69
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
70
|
+
const snapshot = sourceFileSnapshots.get(fileName)?.[1];
|
|
71
|
+
if (snapshot) {
|
|
72
|
+
language.scripts.set(fileName, getLanguageId(fileName), snapshot);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
language.scripts.delete(fileName);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const originalHost = options.host;
|
|
80
|
+
const extensions = languagePlugins
|
|
81
|
+
.map(plugin => plugin.typescript?.extraFileExtensions.map(({ extension }) => `.${extension}`) ?? [])
|
|
82
|
+
.flat();
|
|
55
83
|
options.host = { ...originalHost };
|
|
56
|
-
options.options.allowArbitraryExtensions = true;
|
|
57
84
|
options.host.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
|
|
58
85
|
const originalSourceFile = originalHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
if (!sourceFileSnapshots.has(fileName)
|
|
87
|
+
|| sourceFileSnapshots.get(fileName)?.[0] !== originalSourceFile) {
|
|
88
|
+
if (originalSourceFile) {
|
|
89
|
+
sourceFileSnapshots.set(fileName, [originalSourceFile, {
|
|
90
|
+
getChangeRange() {
|
|
91
|
+
return undefined;
|
|
92
|
+
},
|
|
93
|
+
getLength() {
|
|
94
|
+
return originalSourceFile.text.length;
|
|
95
|
+
},
|
|
96
|
+
getText(start, end) {
|
|
97
|
+
return originalSourceFile.text.substring(start, end);
|
|
98
|
+
},
|
|
99
|
+
}]);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
sourceFileSnapshots.set(fileName, [undefined, undefined]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!originalSourceFile) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (!parsedSourceFiles.has(originalSourceFile)) {
|
|
109
|
+
const sourceScript = language.scripts.get(fileName);
|
|
110
|
+
assert(!!sourceScript, '!!sourceScript');
|
|
111
|
+
parsedSourceFiles.set(originalSourceFile, originalSourceFile);
|
|
112
|
+
if (sourceScript.generated?.languagePlugin.typescript) {
|
|
113
|
+
const { getServiceScript, getExtraServiceScripts } = sourceScript.generated.languagePlugin.typescript;
|
|
114
|
+
const serviceScript = getServiceScript(sourceScript.generated.root);
|
|
115
|
+
if (serviceScript) {
|
|
116
|
+
let patchedText = originalSourceFile.text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
|
|
117
|
+
let scriptKind = ts.ScriptKind.TS;
|
|
118
|
+
scriptKind = serviceScript.scriptKind;
|
|
119
|
+
patchedText += serviceScript.code.snapshot.getText(0, serviceScript.code.snapshot.getLength());
|
|
120
|
+
const parsedSourceFile = ts.createSourceFile(fileName, patchedText, languageVersionOrOptions, undefined, scriptKind);
|
|
121
|
+
// @ts-expect-error
|
|
122
|
+
parsedSourceFile.version = originalSourceFile.version;
|
|
123
|
+
parsedSourceFiles.set(originalSourceFile, parsedSourceFile);
|
|
124
|
+
}
|
|
125
|
+
if (getExtraServiceScripts) {
|
|
126
|
+
console.warn('getExtraServiceScripts() is not available in this use case.');
|
|
77
127
|
}
|
|
78
|
-
sourceFile2 = ts.createSourceFile(fileName, patchedText, 99, true, scriptKind);
|
|
79
|
-
// @ts-expect-error
|
|
80
|
-
sourceFile2.version = originalSourceFile.version;
|
|
81
|
-
parsedSourceFiles.set(originalSourceFile, sourceFile2);
|
|
82
128
|
}
|
|
83
|
-
return sourceFile2;
|
|
84
129
|
}
|
|
85
|
-
return originalSourceFile;
|
|
86
|
-
};
|
|
87
|
-
options.host.resolveModuleNameLiterals = (moduleNames, containingFile, redirectedReference, options) => {
|
|
88
|
-
return moduleNames.map(name => {
|
|
89
|
-
return resolveModuleName(name.text, containingFile, options, redirectedReference);
|
|
90
|
-
});
|
|
130
|
+
return parsedSourceFiles.get(originalSourceFile);
|
|
91
131
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
132
|
+
if (extensions.length) {
|
|
133
|
+
options.options.allowArbitraryExtensions = true;
|
|
134
|
+
const resolveModuleName = (0, resolveModuleName_1.createResolveModuleName)(ts, originalHost, language.plugins, fileName => language.scripts.get(fileName));
|
|
135
|
+
const resolveModuleNameLiterals = originalHost.resolveModuleNameLiterals;
|
|
136
|
+
const resolveModuleNames = originalHost.resolveModuleNames;
|
|
137
|
+
options.host.resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, compilerOptions, ...rest) => {
|
|
138
|
+
if (resolveModuleNameLiterals && moduleLiterals.every(name => !extensions.some(ext => name.text.endsWith(ext)))) {
|
|
139
|
+
return resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, compilerOptions, ...rest);
|
|
140
|
+
}
|
|
141
|
+
return moduleLiterals.map(moduleLiteral => {
|
|
142
|
+
return resolveModuleName(moduleLiteral.text, containingFile, compilerOptions, moduleResolutionCache, redirectedReference);
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
options.host.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions, containingSourceFile) => {
|
|
146
|
+
if (resolveModuleNames && moduleNames.every(name => !extensions.some(ext => name.endsWith(ext)))) {
|
|
147
|
+
return resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions, containingSourceFile);
|
|
148
|
+
}
|
|
149
|
+
return moduleNames.map(moduleName => {
|
|
150
|
+
return resolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionCache, redirectedReference).resolvedModule;
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const program = Reflect.apply(target, thisArg, args);
|
|
98
155
|
(0, decorateProgram_1.decorateProgram)(language, program);
|
|
99
156
|
// TODO: #128
|
|
100
|
-
program.__volar__ = {
|
|
157
|
+
program.__volar__ = { language };
|
|
101
158
|
return program;
|
|
102
|
-
function resolveModuleName(name, containingFile, options, redirectedReference) {
|
|
103
|
-
const resolved = ts.resolveModuleName(name, containingFile, options, moduleResolutionHost, originalHost.getModuleResolutionCache?.(), redirectedReference);
|
|
104
|
-
if (resolved.resolvedModule) {
|
|
105
|
-
for (let i = 0; i < arbitraryExtensions.length; i++) {
|
|
106
|
-
if (resolved.resolvedModule.resolvedFileName.endsWith(arbitraryExtensions[i])) {
|
|
107
|
-
const sourceFileName = resolved.resolvedModule.resolvedFileName.slice(0, -arbitraryExtensions[i].length) + extensions[i];
|
|
108
|
-
resolved.resolvedModule.resolvedFileName = sourceFileName;
|
|
109
|
-
resolved.resolvedModule.extension = extensions[i];
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return resolved;
|
|
114
|
-
}
|
|
115
159
|
},
|
|
116
160
|
});
|
|
117
161
|
}
|
package/lib/node/transform.d.ts
CHANGED
|
@@ -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(
|
|
4
|
-
export declare function transformDiagnostic<T extends ts.Diagnostic>(
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
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, isTsc: boolean): T | undefined;
|
|
5
|
+
export declare function fillSourceFileText(language: Language, sourceFile: ts.SourceFile): void;
|
|
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;
|