@volar/language-core 1.0.0-alpha.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/LICENSE +21 -0
- package/out/documentRegistry.d.ts +46 -0
- package/out/documentRegistry.js +139 -0
- package/out/index.d.ts +4 -0
- package/out/index.js +20 -0
- package/out/languageContext.d.ts +47 -0
- package/out/languageContext.js +258 -0
- package/out/sourceMaps.d.ts +10 -0
- package/out/sourceMaps.js +18 -0
- package/out/types.d.ts +65 -0
- package/out/types.js +2 -0
- package/package.json +20 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-present Johnson Chu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { EmbeddedFile, EmbeddedLanguageModule, DocumentCapabilities, PositionCapabilities, SourceFile } from './types';
|
|
2
|
+
import { Teleport } from './sourceMaps';
|
|
3
|
+
import { Mapping, SourceMapBase } from '@volar/source-map';
|
|
4
|
+
export declare function forEachEmbeddeds(input: EmbeddedFile[], cb: (embedded: EmbeddedFile) => void): void;
|
|
5
|
+
export declare type DocumentRegistry = ReturnType<typeof createDocumentRegistry>;
|
|
6
|
+
export declare function createDocumentRegistry(): {
|
|
7
|
+
get: (fileName: string) => [SourceFile, EmbeddedLanguageModule] | undefined;
|
|
8
|
+
delete: (fileName: string) => boolean;
|
|
9
|
+
has: (fileName: string) => boolean;
|
|
10
|
+
set: (fileName: string, vueFile: SourceFile, languageModule: EmbeddedLanguageModule) => [SourceFile, EmbeddedLanguageModule<SourceFile>];
|
|
11
|
+
getFileNames: () => string[];
|
|
12
|
+
getAll: () => [SourceFile, EmbeddedLanguageModule<SourceFile>][];
|
|
13
|
+
getTeleport: (fileName: string) => Teleport | undefined;
|
|
14
|
+
getAllEmbeddeds: () => Generator<{
|
|
15
|
+
vueFile: SourceFile;
|
|
16
|
+
embedded: EmbeddedFile;
|
|
17
|
+
}, void, unknown>;
|
|
18
|
+
fromEmbeddedLocation: (fileName: string, start: number, end?: number, filter?: ((data: PositionCapabilities) => boolean) | undefined, sourceMapFilter?: ((sourceMap: DocumentCapabilities) => boolean) | undefined) => Generator<{
|
|
19
|
+
fileName: string;
|
|
20
|
+
range: {
|
|
21
|
+
start: number;
|
|
22
|
+
end: number;
|
|
23
|
+
};
|
|
24
|
+
mapped: {
|
|
25
|
+
vueFile: SourceFile;
|
|
26
|
+
embedded: EmbeddedFile;
|
|
27
|
+
};
|
|
28
|
+
data: any;
|
|
29
|
+
} | {
|
|
30
|
+
fileName: string;
|
|
31
|
+
range: {
|
|
32
|
+
start: number;
|
|
33
|
+
end: number;
|
|
34
|
+
};
|
|
35
|
+
mapped?: undefined;
|
|
36
|
+
data?: undefined;
|
|
37
|
+
}, void, unknown>;
|
|
38
|
+
fromEmbeddedFile: (file: EmbeddedFile) => SourceFile | undefined;
|
|
39
|
+
fromEmbeddedFileName: (fileName: string) => {
|
|
40
|
+
vueFile: SourceFile;
|
|
41
|
+
embedded: EmbeddedFile;
|
|
42
|
+
} | undefined;
|
|
43
|
+
getSourceMap: (file: SourceFile, mappings: Mapping<any>[]) => SourceMapBase<any>;
|
|
44
|
+
getTeleportSourceMap: (file: SourceFile, mappings: Mapping<any>[]) => Teleport;
|
|
45
|
+
onSourceFileUpdated(file: SourceFile): void;
|
|
46
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
exports.createDocumentRegistry = exports.forEachEmbeddeds = void 0;
|
|
3
|
+
const reactivity_1 = require("@vue/reactivity");
|
|
4
|
+
const sourceMaps_1 = require("./sourceMaps");
|
|
5
|
+
const source_map_1 = require("@volar/source-map");
|
|
6
|
+
function forEachEmbeddeds(input, cb) {
|
|
7
|
+
for (const child of input) {
|
|
8
|
+
if (child) {
|
|
9
|
+
cb(child);
|
|
10
|
+
}
|
|
11
|
+
forEachEmbeddeds(child.embeddeds, cb);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.forEachEmbeddeds = forEachEmbeddeds;
|
|
15
|
+
function createDocumentRegistry() {
|
|
16
|
+
const files = (0, reactivity_1.shallowReactive)({});
|
|
17
|
+
const all = (0, reactivity_1.computed)(() => Object.values(files));
|
|
18
|
+
const fileNames = (0, reactivity_1.computed)(() => all.value.map(sourceFile => sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile[0].fileName));
|
|
19
|
+
const embeddedDocumentsMap = (0, reactivity_1.computed)(() => {
|
|
20
|
+
const map = new WeakMap();
|
|
21
|
+
for (const [sourceFile] of all.value) {
|
|
22
|
+
forEachEmbeddeds(sourceFile.embeddeds, embedded => {
|
|
23
|
+
map.set(embedded, sourceFile);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return map;
|
|
27
|
+
});
|
|
28
|
+
const sourceMapsByFileName = (0, reactivity_1.computed)(() => {
|
|
29
|
+
const map = new Map();
|
|
30
|
+
for (const [sourceFile] of all.value) {
|
|
31
|
+
forEachEmbeddeds(sourceFile.embeddeds, embedded => {
|
|
32
|
+
map.set(normalizePath(embedded.fileName), { vueFile: sourceFile, embedded });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return map;
|
|
36
|
+
});
|
|
37
|
+
const teleports = (0, reactivity_1.computed)(() => {
|
|
38
|
+
const map = new Map();
|
|
39
|
+
for (const key in files) {
|
|
40
|
+
const [sourceFile] = files[key];
|
|
41
|
+
forEachEmbeddeds(sourceFile.embeddeds, embedded => {
|
|
42
|
+
if (embedded.teleportMappings) {
|
|
43
|
+
map.set(normalizePath(embedded.fileName), getTeleport(sourceFile, embedded.teleportMappings));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return map;
|
|
48
|
+
});
|
|
49
|
+
const _sourceMaps = new WeakMap();
|
|
50
|
+
const _teleports = new WeakMap();
|
|
51
|
+
return {
|
|
52
|
+
get: (fileName) => files[normalizePath(fileName)],
|
|
53
|
+
delete: (fileName) => delete files[normalizePath(fileName)],
|
|
54
|
+
has: (fileName) => !!files[normalizePath(fileName)],
|
|
55
|
+
set: (fileName, vueFile, languageModule) => files[normalizePath(fileName)] = [vueFile, languageModule],
|
|
56
|
+
getFileNames: () => fileNames.value,
|
|
57
|
+
getAll: () => all.value,
|
|
58
|
+
getTeleport: (fileName) => teleports.value.get(normalizePath(fileName)),
|
|
59
|
+
getAllEmbeddeds: function* () {
|
|
60
|
+
for (const sourceMap of sourceMapsByFileName.value) {
|
|
61
|
+
yield sourceMap[1];
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
fromEmbeddedLocation: function* (fileName, start, end, filter, sourceMapFilter) {
|
|
65
|
+
if (fileName.endsWith('/__VLS_types.ts')) { // TODO: monkey fix
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (end === undefined)
|
|
69
|
+
end = start;
|
|
70
|
+
const mapped = sourceMapsByFileName.value.get(normalizePath(fileName));
|
|
71
|
+
if (mapped) {
|
|
72
|
+
if (sourceMapFilter && !sourceMapFilter(mapped.embedded.capabilities))
|
|
73
|
+
return;
|
|
74
|
+
const sourceMap = getSourceMap(mapped.vueFile, mapped.embedded.mappings);
|
|
75
|
+
for (const vueRange of sourceMap.getSourceRanges(start, end, filter)) {
|
|
76
|
+
yield {
|
|
77
|
+
fileName: mapped.vueFile.fileName,
|
|
78
|
+
range: vueRange[0],
|
|
79
|
+
mapped: mapped,
|
|
80
|
+
data: vueRange[1],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
yield {
|
|
86
|
+
fileName,
|
|
87
|
+
range: {
|
|
88
|
+
start,
|
|
89
|
+
end,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
fromEmbeddedFile: function (file) {
|
|
95
|
+
return embeddedDocumentsMap.value.get(file);
|
|
96
|
+
},
|
|
97
|
+
fromEmbeddedFileName: function (fileName) {
|
|
98
|
+
return sourceMapsByFileName.value.get(normalizePath(fileName));
|
|
99
|
+
},
|
|
100
|
+
getSourceMap,
|
|
101
|
+
getTeleportSourceMap: getTeleport,
|
|
102
|
+
// TODO: unuse this
|
|
103
|
+
onSourceFileUpdated(file) {
|
|
104
|
+
_sourceMaps.delete(file);
|
|
105
|
+
_teleports.delete(file);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
function getSourceMap(file, mappings) {
|
|
109
|
+
let map1 = _sourceMaps.get(file);
|
|
110
|
+
if (!map1) {
|
|
111
|
+
map1 = new WeakMap();
|
|
112
|
+
_sourceMaps.set(file, map1);
|
|
113
|
+
}
|
|
114
|
+
let map2 = map1.get(mappings);
|
|
115
|
+
if (!map2) {
|
|
116
|
+
map2 = new source_map_1.SourceMapBase(mappings);
|
|
117
|
+
map1.set(mappings, map2);
|
|
118
|
+
}
|
|
119
|
+
return map2;
|
|
120
|
+
}
|
|
121
|
+
function getTeleport(file, mappings) {
|
|
122
|
+
let map1 = _teleports.get(file);
|
|
123
|
+
if (!map1) {
|
|
124
|
+
map1 = new WeakMap();
|
|
125
|
+
_teleports.set(file, map1);
|
|
126
|
+
}
|
|
127
|
+
let map2 = map1.get(mappings);
|
|
128
|
+
if (!map2) {
|
|
129
|
+
map2 = new sourceMaps_1.Teleport(mappings);
|
|
130
|
+
map1.set(mappings, map2);
|
|
131
|
+
}
|
|
132
|
+
return map2;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.createDocumentRegistry = createDocumentRegistry;
|
|
136
|
+
function normalizePath(fileName) {
|
|
137
|
+
return fileName.replace(/\\/g, '/').toLowerCase();
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=documentRegistry.js.map
|
package/out/index.d.ts
ADDED
package/out/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
2
|
+
if (k2 === undefined) k2 = k;
|
|
3
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
4
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
5
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
6
|
+
}
|
|
7
|
+
Object.defineProperty(o, k2, desc);
|
|
8
|
+
}) : (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
o[k2] = m[k];
|
|
11
|
+
}));
|
|
12
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
13
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
__exportStar(require("./documentRegistry"), exports);
|
|
17
|
+
__exportStar(require("./languageContext"), exports);
|
|
18
|
+
__exportStar(require("./sourceMaps"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import { EmbeddedLanguageModule, SourceFile, LanguageServiceHost } from './types';
|
|
3
|
+
export declare type EmbeddedLanguageContext = ReturnType<typeof createEmbeddedLanguageServiceHost>;
|
|
4
|
+
export declare function createEmbeddedLanguageServiceHost(host: LanguageServiceHost, languageModules: EmbeddedLanguageModule[]): {
|
|
5
|
+
typescriptLanguageServiceHost: ts.LanguageServiceHost;
|
|
6
|
+
mapper: {
|
|
7
|
+
get: (fileName: string) => [SourceFile, EmbeddedLanguageModule<SourceFile>] | undefined;
|
|
8
|
+
delete: (fileName: string) => boolean;
|
|
9
|
+
has: (fileName: string) => boolean;
|
|
10
|
+
set: (fileName: string, vueFile: SourceFile, languageModule: EmbeddedLanguageModule<SourceFile>) => [SourceFile, EmbeddedLanguageModule<SourceFile>];
|
|
11
|
+
getFileNames: () => string[];
|
|
12
|
+
getAll: () => [SourceFile, EmbeddedLanguageModule<SourceFile>][];
|
|
13
|
+
getTeleport: (fileName: string) => import("./sourceMaps").Teleport | undefined;
|
|
14
|
+
getAllEmbeddeds: () => Generator<{
|
|
15
|
+
vueFile: SourceFile;
|
|
16
|
+
embedded: import("./types").EmbeddedFile;
|
|
17
|
+
}, void, unknown>;
|
|
18
|
+
fromEmbeddedLocation: (fileName: string, start: number, end?: number | undefined, filter?: ((data: import("./types").PositionCapabilities) => boolean) | undefined, sourceMapFilter?: ((sourceMap: import("./types").DocumentCapabilities) => boolean) | undefined) => Generator<{
|
|
19
|
+
fileName: string;
|
|
20
|
+
range: {
|
|
21
|
+
start: number;
|
|
22
|
+
end: number;
|
|
23
|
+
};
|
|
24
|
+
mapped: {
|
|
25
|
+
vueFile: SourceFile;
|
|
26
|
+
embedded: import("./types").EmbeddedFile;
|
|
27
|
+
};
|
|
28
|
+
data: any;
|
|
29
|
+
} | {
|
|
30
|
+
fileName: string;
|
|
31
|
+
range: {
|
|
32
|
+
start: number;
|
|
33
|
+
end: number;
|
|
34
|
+
};
|
|
35
|
+
mapped?: undefined;
|
|
36
|
+
data?: undefined;
|
|
37
|
+
}, void, unknown>;
|
|
38
|
+
fromEmbeddedFile: (file: import("./types").EmbeddedFile) => SourceFile | undefined;
|
|
39
|
+
fromEmbeddedFileName: (fileName: string) => {
|
|
40
|
+
vueFile: SourceFile;
|
|
41
|
+
embedded: import("./types").EmbeddedFile;
|
|
42
|
+
} | undefined;
|
|
43
|
+
getSourceMap: (file: SourceFile, mappings: import("@volar/source-map").Mapping<any>[]) => import("@volar/source-map").SourceMapBase<any>;
|
|
44
|
+
getTeleportSourceMap: (file: SourceFile, mappings: import("@volar/source-map").Mapping<any>[]) => import("./sourceMaps").Teleport;
|
|
45
|
+
onSourceFileUpdated(file: SourceFile): void;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
exports.createEmbeddedLanguageServiceHost = void 0;
|
|
3
|
+
const path_1 = require("path");
|
|
4
|
+
const documentRegistry_1 = require("./documentRegistry");
|
|
5
|
+
const reactivity_1 = require("@vue/reactivity");
|
|
6
|
+
function createEmbeddedLanguageServiceHost(host, languageModules) {
|
|
7
|
+
for (const languageModule of languageModules.reverse()) {
|
|
8
|
+
if (languageModule.proxyLanguageServiceHost) {
|
|
9
|
+
const proxyApis = languageModule.proxyLanguageServiceHost(host);
|
|
10
|
+
host = new Proxy(host, {
|
|
11
|
+
get(target, key) {
|
|
12
|
+
if (key in proxyApis) {
|
|
13
|
+
return proxyApis[key];
|
|
14
|
+
}
|
|
15
|
+
return target[key];
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
let lastProjectVersion;
|
|
21
|
+
let tsProjectVersion = 0;
|
|
22
|
+
const documentRegistry = (0, documentRegistry_1.createDocumentRegistry)();
|
|
23
|
+
const ts = host.getTypeScriptModule();
|
|
24
|
+
const tsFileVersions = new Map();
|
|
25
|
+
const scriptSnapshots = new Map();
|
|
26
|
+
const fileVersions = new Map();
|
|
27
|
+
const _tsHost = {
|
|
28
|
+
fileExists: host.fileExists
|
|
29
|
+
? fileName => {
|
|
30
|
+
var _a;
|
|
31
|
+
// .vue.js -> .vue
|
|
32
|
+
// .vue.ts -> .vue
|
|
33
|
+
// .vue.d.ts (never)
|
|
34
|
+
const vueFileName = fileName.substring(0, fileName.lastIndexOf('.'));
|
|
35
|
+
if (!documentRegistry.get(vueFileName)) {
|
|
36
|
+
// create virtual files
|
|
37
|
+
const scriptSnapshot = host.getScriptSnapshot(vueFileName);
|
|
38
|
+
if (scriptSnapshot) {
|
|
39
|
+
for (const langaugeModule of languageModules) {
|
|
40
|
+
const sourceFile = langaugeModule.createSourceFile(vueFileName, scriptSnapshot);
|
|
41
|
+
if (sourceFile) {
|
|
42
|
+
documentRegistry.set(vueFileName, (0, reactivity_1.shallowReactive)(sourceFile), langaugeModule);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!!documentRegistry.fromEmbeddedFileName(fileName)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return !!((_a = host.fileExists) === null || _a === void 0 ? void 0 : _a.call(host, fileName));
|
|
52
|
+
}
|
|
53
|
+
: undefined,
|
|
54
|
+
getProjectVersion: () => {
|
|
55
|
+
return tsProjectVersion.toString();
|
|
56
|
+
},
|
|
57
|
+
getScriptFileNames,
|
|
58
|
+
getScriptVersion,
|
|
59
|
+
getScriptSnapshot,
|
|
60
|
+
readDirectory: (_path, extensions, exclude, include, depth) => {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
const result = (_b = (_a = host.readDirectory) === null || _a === void 0 ? void 0 : _a.call(host, _path, extensions, exclude, include, depth)) !== null && _b !== void 0 ? _b : [];
|
|
63
|
+
for (const vuePath of documentRegistry.getFileNames()) {
|
|
64
|
+
const vuePath2 = path_1.posix.join(_path, path_1.posix.basename(vuePath));
|
|
65
|
+
if (path_1.posix.relative(_path.toLowerCase(), vuePath.toLowerCase()).startsWith('..')) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (!depth && vuePath.toLowerCase() === vuePath2.toLowerCase()) {
|
|
69
|
+
result.push(vuePath2);
|
|
70
|
+
}
|
|
71
|
+
else if (depth) {
|
|
72
|
+
result.push(vuePath2); // TODO: depth num
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
},
|
|
77
|
+
getScriptKind(fileName) {
|
|
78
|
+
if (documentRegistry.has(fileName))
|
|
79
|
+
return ts.ScriptKind.TSX; // can't use External, Unknown
|
|
80
|
+
switch (path_1.posix.extname(fileName)) {
|
|
81
|
+
case '.js': return ts.ScriptKind.JS;
|
|
82
|
+
case '.jsx': return ts.ScriptKind.JSX;
|
|
83
|
+
case '.ts': return ts.ScriptKind.TS;
|
|
84
|
+
case '.tsx': return ts.ScriptKind.TSX;
|
|
85
|
+
case '.json': return ts.ScriptKind.JSON;
|
|
86
|
+
default: return ts.ScriptKind.Unknown;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
typescriptLanguageServiceHost: new Proxy(_tsHost, {
|
|
92
|
+
get: (target, property) => {
|
|
93
|
+
update();
|
|
94
|
+
return target[property] || host[property];
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
mapper: new Proxy(documentRegistry, {
|
|
98
|
+
get: (target, property) => {
|
|
99
|
+
update();
|
|
100
|
+
return target[property];
|
|
101
|
+
},
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
function update() {
|
|
105
|
+
var _a;
|
|
106
|
+
const newProjectVersion = (_a = host.getProjectVersion) === null || _a === void 0 ? void 0 : _a.call(host);
|
|
107
|
+
const sholdUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
|
|
108
|
+
lastProjectVersion = newProjectVersion;
|
|
109
|
+
if (!sholdUpdate)
|
|
110
|
+
return;
|
|
111
|
+
let tsFileUpdated = false;
|
|
112
|
+
const remainFileNames = new Set(host.getScriptFileNames());
|
|
113
|
+
const sourceFilesToUpdate = [];
|
|
114
|
+
// .vue
|
|
115
|
+
for (const [sourceFile, languageModule] of documentRegistry.getAll()) {
|
|
116
|
+
remainFileNames.delete(sourceFile.fileName);
|
|
117
|
+
const newVersion = host.getScriptVersion(sourceFile.fileName);
|
|
118
|
+
if (fileVersions.get(sourceFile.fileName) !== newVersion) {
|
|
119
|
+
fileVersions.set(sourceFile.fileName, newVersion);
|
|
120
|
+
const snapshot = host.getScriptSnapshot(sourceFile.fileName);
|
|
121
|
+
if (snapshot) {
|
|
122
|
+
// update
|
|
123
|
+
sourceFilesToUpdate.push([sourceFile, languageModule, snapshot]);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// delete
|
|
127
|
+
if (documentRegistry.delete(sourceFile.fileName)) {
|
|
128
|
+
tsFileUpdated = true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// add
|
|
134
|
+
for (const fileName of [...remainFileNames]) {
|
|
135
|
+
const snapshot = host.getScriptSnapshot(fileName);
|
|
136
|
+
if (snapshot) {
|
|
137
|
+
for (const languageModule of languageModules) {
|
|
138
|
+
const sourceFile = languageModule.createSourceFile(fileName, snapshot);
|
|
139
|
+
if (sourceFile) {
|
|
140
|
+
documentRegistry.set(fileName, (0, reactivity_1.shallowReactive)(sourceFile), languageModule);
|
|
141
|
+
remainFileNames.delete(fileName);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// .ts / .js / .d.ts / .json ...
|
|
148
|
+
for (const [oldTsFileName, oldTsFileVersion] of [...tsFileVersions]) {
|
|
149
|
+
const newVersion = host.getScriptVersion(oldTsFileName);
|
|
150
|
+
if (oldTsFileVersion !== newVersion) {
|
|
151
|
+
if (!remainFileNames.has(oldTsFileName) && !host.getScriptSnapshot(oldTsFileName)) {
|
|
152
|
+
// delete
|
|
153
|
+
tsFileVersions.delete(oldTsFileName);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// update
|
|
157
|
+
tsFileVersions.set(oldTsFileName, newVersion);
|
|
158
|
+
}
|
|
159
|
+
tsFileUpdated = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (const nowFileName of remainFileNames) {
|
|
163
|
+
if (!tsFileVersions.has(nowFileName)) {
|
|
164
|
+
// add
|
|
165
|
+
const newVersion = host.getScriptVersion(nowFileName);
|
|
166
|
+
tsFileVersions.set(nowFileName, newVersion);
|
|
167
|
+
tsFileUpdated = true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const [sourceFile, languageModule, snapshot] of sourceFilesToUpdate) {
|
|
171
|
+
(0, documentRegistry_1.forEachEmbeddeds)(sourceFile.embeddeds, embedded => {
|
|
172
|
+
fileVersions.delete(embedded.fileName);
|
|
173
|
+
});
|
|
174
|
+
const oldScripts = {};
|
|
175
|
+
const newScripts = {};
|
|
176
|
+
if (!tsFileUpdated) {
|
|
177
|
+
(0, documentRegistry_1.forEachEmbeddeds)(sourceFile.embeddeds, embedded => {
|
|
178
|
+
if (embedded.isTsHostFile) {
|
|
179
|
+
oldScripts[embedded.fileName] = embedded.text;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
languageModule.updateSourceFile(sourceFile, snapshot);
|
|
184
|
+
documentRegistry.onSourceFileUpdated(sourceFile);
|
|
185
|
+
if (!tsFileUpdated) {
|
|
186
|
+
(0, documentRegistry_1.forEachEmbeddeds)(sourceFile.embeddeds, embedded => {
|
|
187
|
+
if (embedded.isTsHostFile) {
|
|
188
|
+
newScripts[embedded.fileName] = embedded.text;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (!tsFileUpdated
|
|
193
|
+
&& Object.keys(oldScripts).length !== Object.keys(newScripts).length
|
|
194
|
+
|| Object.keys(oldScripts).some(fileName => oldScripts[fileName] !== newScripts[fileName])) {
|
|
195
|
+
tsFileUpdated = true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (tsFileUpdated) {
|
|
199
|
+
tsProjectVersion++;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function getScriptFileNames() {
|
|
203
|
+
const tsFileNames = [];
|
|
204
|
+
for (const mapped of documentRegistry.getAllEmbeddeds()) {
|
|
205
|
+
if (mapped.embedded.isTsHostFile) {
|
|
206
|
+
tsFileNames.push(mapped.embedded.fileName); // virtual .ts
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const fileName of host.getScriptFileNames()) {
|
|
210
|
+
if (host.isTsPlugin) {
|
|
211
|
+
tsFileNames.push(fileName); // .vue + .ts
|
|
212
|
+
}
|
|
213
|
+
else if (!documentRegistry.has(fileName)) {
|
|
214
|
+
tsFileNames.push(fileName); // .ts
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return tsFileNames;
|
|
218
|
+
}
|
|
219
|
+
function getScriptVersion(fileName) {
|
|
220
|
+
var _a, _b, _c;
|
|
221
|
+
let mapped = documentRegistry.fromEmbeddedFileName(fileName);
|
|
222
|
+
if (mapped) {
|
|
223
|
+
if (fileVersions.has(mapped.embedded.fileName)) {
|
|
224
|
+
return fileVersions.get(mapped.embedded.fileName);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
let version = (_c = (_b = (_a = ts.sys) === null || _a === void 0 ? void 0 : _a.createHash) === null || _b === void 0 ? void 0 : _b.call(_a, mapped.embedded.text)) !== null && _c !== void 0 ? _c : mapped.embedded.text;
|
|
228
|
+
if (host.isTsc) {
|
|
229
|
+
// fix https://github.com/johnsoncodehk/volar/issues/1082
|
|
230
|
+
version = host.getScriptVersion(mapped.vueFile.fileName) + ':' + version;
|
|
231
|
+
}
|
|
232
|
+
fileVersions.set(mapped.embedded.fileName, version);
|
|
233
|
+
return version;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return host.getScriptVersion(fileName);
|
|
237
|
+
}
|
|
238
|
+
function getScriptSnapshot(fileName) {
|
|
239
|
+
const version = getScriptVersion(fileName);
|
|
240
|
+
const cache = scriptSnapshots.get(fileName.toLowerCase());
|
|
241
|
+
if (cache && cache[0] === version) {
|
|
242
|
+
return cache[1];
|
|
243
|
+
}
|
|
244
|
+
const mapped = documentRegistry.fromEmbeddedFileName(fileName);
|
|
245
|
+
if (mapped) {
|
|
246
|
+
const snapshot = ts.ScriptSnapshot.fromString(mapped.embedded.text);
|
|
247
|
+
scriptSnapshots.set(fileName.toLowerCase(), [version, snapshot]);
|
|
248
|
+
return snapshot;
|
|
249
|
+
}
|
|
250
|
+
let tsScript = host.getScriptSnapshot(fileName);
|
|
251
|
+
if (tsScript) {
|
|
252
|
+
scriptSnapshots.set(fileName.toLowerCase(), [version, tsScript]);
|
|
253
|
+
return tsScript;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
exports.createEmbeddedLanguageServiceHost = createEmbeddedLanguageServiceHost;
|
|
258
|
+
//# sourceMappingURL=languageContext.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as SourceMaps from '@volar/source-map';
|
|
2
|
+
import { PositionCapabilities, TeleportMappingData, TeleportCapabilities } from './types';
|
|
3
|
+
export declare class EmbeddedFileSourceMap extends SourceMaps.SourceMapBase<PositionCapabilities> {
|
|
4
|
+
}
|
|
5
|
+
export declare class Teleport extends SourceMaps.SourceMapBase<TeleportMappingData> {
|
|
6
|
+
findTeleports(start: number, end?: number, filter?: (data: TeleportCapabilities) => boolean): Generator<readonly [{
|
|
7
|
+
start: number;
|
|
8
|
+
end: number;
|
|
9
|
+
}, TeleportCapabilities], void, unknown>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
exports.Teleport = exports.EmbeddedFileSourceMap = void 0;
|
|
3
|
+
const SourceMaps = require("@volar/source-map");
|
|
4
|
+
class EmbeddedFileSourceMap extends SourceMaps.SourceMapBase {
|
|
5
|
+
}
|
|
6
|
+
exports.EmbeddedFileSourceMap = EmbeddedFileSourceMap;
|
|
7
|
+
class Teleport extends SourceMaps.SourceMapBase {
|
|
8
|
+
*findTeleports(start, end, filter) {
|
|
9
|
+
for (const [teleRange, data] of this.getMappedRanges(start, end, filter ? data => filter(data.toGenedCapabilities) : undefined)) {
|
|
10
|
+
yield [teleRange, data.toGenedCapabilities];
|
|
11
|
+
}
|
|
12
|
+
for (const [teleRange, data] of this.getSourceRanges(start, end, filter ? data => filter(data.toGenedCapabilities) : undefined)) {
|
|
13
|
+
yield [teleRange, data.toGenedCapabilities];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.Teleport = Teleport;
|
|
18
|
+
//# sourceMappingURL=sourceMaps.js.map
|
package/out/types.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Mapping } from '@volar/source-map';
|
|
2
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
|
+
export interface DocumentCapabilities {
|
|
4
|
+
diagnostics?: boolean;
|
|
5
|
+
foldingRanges?: boolean;
|
|
6
|
+
formatting?: boolean | {
|
|
7
|
+
initialIndentBracket?: [string, string];
|
|
8
|
+
};
|
|
9
|
+
documentSymbol?: boolean;
|
|
10
|
+
codeActions?: boolean;
|
|
11
|
+
inlayHints?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface PositionCapabilities {
|
|
14
|
+
hover?: boolean;
|
|
15
|
+
references?: boolean;
|
|
16
|
+
definitions?: boolean;
|
|
17
|
+
rename?: boolean | {
|
|
18
|
+
normalize?(newName: string): string;
|
|
19
|
+
apply?(oldName: string, newName: string): string;
|
|
20
|
+
};
|
|
21
|
+
completion?: boolean | {
|
|
22
|
+
additional: boolean;
|
|
23
|
+
};
|
|
24
|
+
diagnostic?: boolean;
|
|
25
|
+
semanticTokens?: boolean;
|
|
26
|
+
referencesCodeLens?: boolean;
|
|
27
|
+
displayWithLink?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface TeleportCapabilities {
|
|
30
|
+
references?: boolean;
|
|
31
|
+
definitions?: boolean;
|
|
32
|
+
rename?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface TeleportMappingData {
|
|
35
|
+
toSourceCapabilities: TeleportCapabilities;
|
|
36
|
+
toGenedCapabilities: TeleportCapabilities;
|
|
37
|
+
}
|
|
38
|
+
export interface TextRange {
|
|
39
|
+
start: number;
|
|
40
|
+
end: number;
|
|
41
|
+
}
|
|
42
|
+
export interface SourceFile {
|
|
43
|
+
fileName: string;
|
|
44
|
+
text: string;
|
|
45
|
+
embeddeds: EmbeddedFile[];
|
|
46
|
+
}
|
|
47
|
+
export interface EmbeddedFile {
|
|
48
|
+
fileName: string;
|
|
49
|
+
text: string;
|
|
50
|
+
isTsHostFile: boolean;
|
|
51
|
+
capabilities: DocumentCapabilities;
|
|
52
|
+
mappings: Mapping<PositionCapabilities>[];
|
|
53
|
+
teleportMappings?: Mapping<TeleportMappingData>[];
|
|
54
|
+
embeddeds: EmbeddedFile[];
|
|
55
|
+
}
|
|
56
|
+
export interface EmbeddedLanguageModule<T extends SourceFile = SourceFile> {
|
|
57
|
+
createSourceFile(fileName: string, snapshot: ts.IScriptSnapshot): T | undefined;
|
|
58
|
+
updateSourceFile(sourceFile: T, snapshot: ts.IScriptSnapshot): void;
|
|
59
|
+
proxyLanguageServiceHost?(host: LanguageServiceHost): Partial<LanguageServiceHost>;
|
|
60
|
+
}
|
|
61
|
+
export declare type LanguageServiceHost = ts.LanguageServiceHost & {
|
|
62
|
+
getTypeScriptModule(): typeof import('typescript/lib/tsserverlibrary');
|
|
63
|
+
isTsPlugin?: boolean;
|
|
64
|
+
isTsc?: boolean;
|
|
65
|
+
};
|
package/out/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@volar/language-core",
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
|
+
"main": "out/index.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"files": [
|
|
7
|
+
"out/**/*.js",
|
|
8
|
+
"out/**/*.d.ts"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/johnsoncodehk/volar.git",
|
|
13
|
+
"directory": "packages/language-core"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@volar/code-gen": "1.0.0-alpha.0",
|
|
17
|
+
"@volar/source-map": "1.0.0-alpha.0",
|
|
18
|
+
"@vue/reactivity": "^3.2.38"
|
|
19
|
+
}
|
|
20
|
+
}
|