@volar/language-core 2.3.0-alpha.4 → 2.3.0-alpha.6
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/index.d.ts +2 -5
- package/index.js +84 -68
- package/lib/linkedCodeMap.d.ts +1 -1
- package/lib/types.d.ts +55 -38
- package/package.json +3 -3
package/index.d.ts
CHANGED
|
@@ -3,9 +3,6 @@ export * from './lib/editorFeatures';
|
|
|
3
3
|
export * from './lib/linkedCodeMap';
|
|
4
4
|
export * from './lib/types';
|
|
5
5
|
export * from './lib/utils';
|
|
6
|
-
import {
|
|
7
|
-
import type * as ts from 'typescript';
|
|
8
|
-
import type { CodeInformation, Language, LanguagePlugin, SourceScript, VirtualCode } from './lib/types';
|
|
6
|
+
import type { Language, LanguagePlugin, SourceScript, VirtualCode } from './lib/types';
|
|
9
7
|
export declare function createLanguage<T>(plugins: LanguagePlugin<T>[], scriptRegistry: Map<T, SourceScript<T>>, sync: (id: T) => void): Language<T>;
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function forEachEmbeddedCode(virtualCode: VirtualCode): Generator<VirtualCode>;
|
|
8
|
+
export declare function forEachEmbeddedCode<T>(virtualCode: VirtualCode<T>): Generator<VirtualCode<T>>;
|
package/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.forEachEmbeddedCode = exports.
|
|
17
|
+
exports.forEachEmbeddedCode = exports.createLanguage = void 0;
|
|
18
18
|
__exportStar(require("@volar/source-map"), exports);
|
|
19
19
|
__exportStar(require("./lib/editorFeatures"), exports);
|
|
20
20
|
__exportStar(require("./lib/linkedCodeMap"), exports);
|
|
@@ -23,12 +23,15 @@ __exportStar(require("./lib/utils"), exports);
|
|
|
23
23
|
const source_map_1 = require("@volar/source-map");
|
|
24
24
|
const linkedCodeMap_1 = require("./lib/linkedCodeMap");
|
|
25
25
|
function createLanguage(plugins, scriptRegistry, sync) {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
26
|
+
const virtualCodeToSourceScriptMap = new WeakMap();
|
|
27
|
+
const virtualCodeToSourceMap = new WeakMap();
|
|
28
28
|
const virtualCodeToLinkedCodeMap = new WeakMap();
|
|
29
29
|
return {
|
|
30
30
|
plugins,
|
|
31
31
|
scripts: {
|
|
32
|
+
fromVirtualCode(virtualCode) {
|
|
33
|
+
return virtualCodeToSourceScriptMap.get(virtualCode);
|
|
34
|
+
},
|
|
32
35
|
get(id) {
|
|
33
36
|
sync(id);
|
|
34
37
|
return scriptRegistry.get(id);
|
|
@@ -53,16 +56,20 @@ function createLanguage(plugins, scriptRegistry, sync) {
|
|
|
53
56
|
this.delete(id);
|
|
54
57
|
return this.set(id, snapshot, languageId);
|
|
55
58
|
}
|
|
56
|
-
else if (sourceScript.snapshot !== snapshot) {
|
|
59
|
+
else if (sourceScript.isAssociationDirty || sourceScript.snapshot !== snapshot) {
|
|
57
60
|
// snapshot updated
|
|
58
61
|
sourceScript.snapshot = snapshot;
|
|
62
|
+
const codegenCtx = prepareCreateVirtualCode(sourceScript);
|
|
59
63
|
if (sourceScript.generated) {
|
|
60
|
-
const
|
|
64
|
+
const { updateVirtualCode, createVirtualCode } = sourceScript.generated.languagePlugin;
|
|
65
|
+
const newVirtualCode = updateVirtualCode
|
|
66
|
+
? updateVirtualCode(id, sourceScript.generated.root, snapshot, codegenCtx)
|
|
67
|
+
: createVirtualCode?.(id, languageId, snapshot, codegenCtx);
|
|
61
68
|
if (newVirtualCode) {
|
|
62
69
|
sourceScript.generated.root = newVirtualCode;
|
|
63
70
|
sourceScript.generated.embeddedCodes.clear();
|
|
64
71
|
for (const code of forEachEmbeddedCode(sourceScript.generated.root)) {
|
|
65
|
-
|
|
72
|
+
virtualCodeToSourceScriptMap.set(code, sourceScript);
|
|
66
73
|
sourceScript.generated.embeddedCodes.set(code.id, code);
|
|
67
74
|
}
|
|
68
75
|
return sourceScript;
|
|
@@ -72,6 +79,7 @@ function createLanguage(plugins, scriptRegistry, sync) {
|
|
|
72
79
|
return;
|
|
73
80
|
}
|
|
74
81
|
}
|
|
82
|
+
triggerTargetsDirty(sourceScript);
|
|
75
83
|
}
|
|
76
84
|
else {
|
|
77
85
|
// not changed
|
|
@@ -80,10 +88,16 @@ function createLanguage(plugins, scriptRegistry, sync) {
|
|
|
80
88
|
}
|
|
81
89
|
else {
|
|
82
90
|
// created
|
|
83
|
-
const sourceScript = {
|
|
91
|
+
const sourceScript = {
|
|
92
|
+
id: id,
|
|
93
|
+
languageId,
|
|
94
|
+
snapshot,
|
|
95
|
+
associatedIds: new Set(),
|
|
96
|
+
targetIds: new Set(),
|
|
97
|
+
};
|
|
84
98
|
scriptRegistry.set(id, sourceScript);
|
|
85
99
|
for (const languagePlugin of _plugins) {
|
|
86
|
-
const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot);
|
|
100
|
+
const virtualCode = languagePlugin.createVirtualCode?.(id, languageId, snapshot, prepareCreateVirtualCode(sourceScript));
|
|
87
101
|
if (virtualCode) {
|
|
88
102
|
sourceScript.generated = {
|
|
89
103
|
root: virtualCode,
|
|
@@ -91,7 +105,7 @@ function createLanguage(plugins, scriptRegistry, sync) {
|
|
|
91
105
|
embeddedCodes: new Map(),
|
|
92
106
|
};
|
|
93
107
|
for (const code of forEachEmbeddedCode(virtualCode)) {
|
|
94
|
-
|
|
108
|
+
virtualCodeToSourceScriptMap.set(code, sourceScript);
|
|
95
109
|
sourceScript.generated.embeddedCodes.set(code.id, code);
|
|
96
110
|
}
|
|
97
111
|
break;
|
|
@@ -101,86 +115,88 @@ function createLanguage(plugins, scriptRegistry, sync) {
|
|
|
101
115
|
}
|
|
102
116
|
},
|
|
103
117
|
delete(id) {
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
value.generated.languagePlugin.disposeVirtualCode?.(id, value.generated.root);
|
|
108
|
-
}
|
|
118
|
+
const sourceScript = scriptRegistry.get(id);
|
|
119
|
+
if (sourceScript) {
|
|
120
|
+
sourceScript.generated?.languagePlugin.disposeVirtualCode?.(id, sourceScript.generated.root);
|
|
109
121
|
scriptRegistry.delete(id);
|
|
122
|
+
triggerTargetsDirty(sourceScript);
|
|
110
123
|
}
|
|
111
124
|
},
|
|
112
125
|
},
|
|
113
126
|
maps: {
|
|
114
|
-
get(virtualCode
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!sourceScript) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
scriptId = sourceScript.id;
|
|
121
|
-
}
|
|
122
|
-
for (const [id, [_snapshot, map]] of this.forEach(virtualCode)) {
|
|
123
|
-
if (id === scriptId) {
|
|
124
|
-
return map;
|
|
125
|
-
}
|
|
127
|
+
get(virtualCode) {
|
|
128
|
+
for (const map of this.forEach(virtualCode)) {
|
|
129
|
+
return map[2];
|
|
126
130
|
}
|
|
131
|
+
throw `no map found for ${virtualCode.id}`;
|
|
127
132
|
},
|
|
128
|
-
forEach(virtualCode) {
|
|
129
|
-
let
|
|
130
|
-
if (!
|
|
131
|
-
|
|
132
|
-
virtualCodeToMaps.set(virtualCode.snapshot, map);
|
|
133
|
+
*forEach(virtualCode) {
|
|
134
|
+
let mapCache = virtualCodeToSourceMap.get(virtualCode.snapshot);
|
|
135
|
+
if (!mapCache) {
|
|
136
|
+
virtualCodeToSourceMap.set(virtualCode.snapshot, mapCache = new WeakMap());
|
|
133
137
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
138
|
+
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
|
|
139
|
+
if (!mapCache.has(sourceScript.snapshot)) {
|
|
140
|
+
mapCache.set(sourceScript.snapshot, new source_map_1.SourceMap(virtualCode.mappings));
|
|
141
|
+
}
|
|
142
|
+
yield [sourceScript.id, sourceScript.snapshot, mapCache.get(sourceScript.snapshot)];
|
|
143
|
+
if (virtualCode.associatedScriptMappings) {
|
|
144
|
+
for (const [relatedScriptId, relatedMappings] of virtualCode.associatedScriptMappings) {
|
|
145
|
+
const relatedSourceScript = scriptRegistry.get(relatedScriptId);
|
|
146
|
+
if (relatedSourceScript) {
|
|
147
|
+
if (!mapCache.has(relatedSourceScript.snapshot)) {
|
|
148
|
+
mapCache.set(relatedSourceScript.snapshot, new source_map_1.SourceMap(relatedMappings));
|
|
149
|
+
}
|
|
150
|
+
yield [relatedSourceScript.id, relatedSourceScript.snapshot, mapCache.get(relatedSourceScript.snapshot)];
|
|
151
|
+
}
|
|
143
152
|
}
|
|
144
|
-
}
|
|
145
|
-
return map;
|
|
153
|
+
}
|
|
146
154
|
},
|
|
147
155
|
},
|
|
148
156
|
linkedCodeMaps: {
|
|
149
157
|
get(virtualCode) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
const sourceScript = virtualCodeToSourceScriptMap.get(virtualCode);
|
|
159
|
+
let mapCache = virtualCodeToLinkedCodeMap.get(virtualCode.snapshot);
|
|
160
|
+
if (mapCache?.[0] !== sourceScript.snapshot) {
|
|
161
|
+
virtualCodeToLinkedCodeMap.set(virtualCode.snapshot, mapCache = [
|
|
162
|
+
sourceScript.snapshot,
|
|
163
|
+
virtualCode.linkedCodeMappings
|
|
164
|
+
? new linkedCodeMap_1.LinkedCodeMap(virtualCode.linkedCodeMappings)
|
|
165
|
+
: undefined,
|
|
166
|
+
]);
|
|
154
167
|
}
|
|
155
|
-
return
|
|
168
|
+
return mapCache[1];
|
|
156
169
|
},
|
|
157
170
|
},
|
|
158
171
|
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
mapOfMap.set(source[0], [source[1], new source_map_1.SourceMap([])]);
|
|
167
|
-
}
|
|
172
|
+
function triggerTargetsDirty(sourceScript) {
|
|
173
|
+
sourceScript.targetIds.forEach(id => {
|
|
174
|
+
const sourceScript = scriptRegistry.get(id);
|
|
175
|
+
if (sourceScript) {
|
|
176
|
+
sourceScript.isAssociationDirty = true;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
168
179
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
sources.add(mapping.source);
|
|
174
|
-
const source = getSourceSnapshot(mapping.source);
|
|
175
|
-
if (!source) {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
if (!mapOfMap.has(source[0]) || mapOfMap.get(source[0])[0] !== source[1]) {
|
|
179
|
-
mapOfMap.set(source[0], [source[1], new source_map_1.SourceMap(virtualCode.mappings.filter(mapping2 => mapping2.source === mapping.source))]);
|
|
180
|
+
function prepareCreateVirtualCode(sourceScript) {
|
|
181
|
+
for (const id of sourceScript.associatedIds) {
|
|
182
|
+
scriptRegistry.get(id)?.targetIds.delete(sourceScript.id);
|
|
180
183
|
}
|
|
184
|
+
sourceScript.associatedIds.clear();
|
|
185
|
+
sourceScript.isAssociationDirty = false;
|
|
186
|
+
return {
|
|
187
|
+
getAssociatedScript(id) {
|
|
188
|
+
sync(id);
|
|
189
|
+
const relatedSourceScript = scriptRegistry.get(id);
|
|
190
|
+
if (relatedSourceScript) {
|
|
191
|
+
relatedSourceScript.targetIds.add(sourceScript.id);
|
|
192
|
+
sourceScript.associatedIds.add(relatedSourceScript.id);
|
|
193
|
+
}
|
|
194
|
+
return relatedSourceScript;
|
|
195
|
+
},
|
|
196
|
+
};
|
|
181
197
|
}
|
|
182
198
|
}
|
|
183
|
-
exports.
|
|
199
|
+
exports.createLanguage = createLanguage;
|
|
184
200
|
function* forEachEmbeddedCode(virtualCode) {
|
|
185
201
|
yield virtualCode;
|
|
186
202
|
if (virtualCode.embeddedCodes) {
|
package/lib/linkedCodeMap.d.ts
CHANGED
package/lib/types.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import type { Mapping, SourceMap } from '@volar/source-map';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
3
|
import type { LinkedCodeMap } from './linkedCodeMap';
|
|
4
|
-
export interface Language<T> {
|
|
4
|
+
export interface Language<T = unknown> {
|
|
5
5
|
plugins: LanguagePlugin<T>[];
|
|
6
6
|
scripts: {
|
|
7
7
|
get(id: T): SourceScript<T> | undefined;
|
|
8
8
|
set(id: T, snapshot: ts.IScriptSnapshot, languageId?: string, plugins?: LanguagePlugin<T>[]): SourceScript<T> | undefined;
|
|
9
9
|
delete(id: T): void;
|
|
10
|
+
fromVirtualCode(virtualCode: VirtualCode<T>): SourceScript<T>;
|
|
10
11
|
};
|
|
11
12
|
maps: {
|
|
12
|
-
get(virtualCode: VirtualCode
|
|
13
|
-
forEach(virtualCode: VirtualCode):
|
|
13
|
+
get(virtualCode: VirtualCode<T>): SourceMap<CodeInformation>;
|
|
14
|
+
forEach(virtualCode: VirtualCode<T>): Generator<[id: T, snapshot: ts.IScriptSnapshot, map: SourceMap<CodeInformation>]>;
|
|
14
15
|
};
|
|
15
16
|
linkedCodeMaps: {
|
|
16
|
-
get(virtualCode: VirtualCode): LinkedCodeMap | undefined;
|
|
17
|
+
get(virtualCode: VirtualCode<T>): LinkedCodeMap | undefined;
|
|
17
18
|
};
|
|
18
19
|
typescript?: {
|
|
19
20
|
configFileName: string | undefined;
|
|
@@ -22,28 +23,32 @@ export interface Language<T> {
|
|
|
22
23
|
sync?(): Promise<number>;
|
|
23
24
|
};
|
|
24
25
|
languageServiceHost: ts.LanguageServiceHost;
|
|
25
|
-
getExtraServiceScript(fileName: string):
|
|
26
|
+
getExtraServiceScript(fileName: string): TypeScriptExtraServiceScript<T> | undefined;
|
|
26
27
|
asScriptId(fileName: string): T;
|
|
27
28
|
asFileName(scriptId: T): string;
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
export interface SourceScript<T> {
|
|
31
|
+
export interface SourceScript<T = unknown> {
|
|
31
32
|
id: T;
|
|
32
33
|
languageId: string;
|
|
33
34
|
snapshot: ts.IScriptSnapshot;
|
|
35
|
+
targetIds: Set<T>;
|
|
36
|
+
associatedIds: Set<T>;
|
|
37
|
+
isAssociationDirty?: boolean;
|
|
34
38
|
generated?: {
|
|
35
|
-
root: VirtualCode
|
|
39
|
+
root: VirtualCode<T>;
|
|
36
40
|
languagePlugin: LanguagePlugin<T>;
|
|
37
|
-
embeddedCodes: Map<string, VirtualCode
|
|
41
|
+
embeddedCodes: Map<string, VirtualCode<T>>;
|
|
38
42
|
};
|
|
39
43
|
}
|
|
40
44
|
export type CodeMapping = Mapping<CodeInformation>;
|
|
41
|
-
export interface VirtualCode {
|
|
45
|
+
export interface VirtualCode<T = unknown> {
|
|
42
46
|
id: string;
|
|
43
47
|
languageId: string;
|
|
44
48
|
snapshot: ts.IScriptSnapshot;
|
|
45
49
|
mappings: CodeMapping[];
|
|
46
|
-
|
|
50
|
+
associatedScriptMappings?: Map<T, CodeMapping[]>;
|
|
51
|
+
embeddedCodes?: VirtualCode<T>[];
|
|
47
52
|
linkedCodeMappings?: Mapping[];
|
|
48
53
|
}
|
|
49
54
|
export interface CodeInformation {
|
|
@@ -71,39 +76,51 @@ export interface CodeInformation {
|
|
|
71
76
|
/** virtual code is expected correctly reflect the format information of the source code */
|
|
72
77
|
format?: boolean;
|
|
73
78
|
}
|
|
74
|
-
export interface TypeScriptServiceScript {
|
|
75
|
-
code: VirtualCode
|
|
79
|
+
export interface TypeScriptServiceScript<T = unknown> {
|
|
80
|
+
code: VirtualCode<T>;
|
|
76
81
|
extension: '.ts' | '.js' | '.mts' | '.mjs' | '.cjs' | '.cts' | '.d.ts' | string;
|
|
77
82
|
scriptKind: ts.ScriptKind;
|
|
83
|
+
/** See #188 */
|
|
84
|
+
preventLeadingOffset?: boolean;
|
|
78
85
|
}
|
|
79
|
-
export interface TypeScriptExtraServiceScript extends TypeScriptServiceScript {
|
|
86
|
+
export interface TypeScriptExtraServiceScript<T = unknown> extends TypeScriptServiceScript<T> {
|
|
80
87
|
fileName: string;
|
|
81
88
|
}
|
|
82
|
-
export interface LanguagePlugin<T, K extends VirtualCode = VirtualCode
|
|
89
|
+
export interface LanguagePlugin<T = unknown, K extends VirtualCode<T> = VirtualCode<T>> {
|
|
90
|
+
/**
|
|
91
|
+
* For files that are not opened in the IDE, the language ID will not be synchronized to the language server, so a hook is needed to parse the language ID of files that are known extension but not opened in the IDE.
|
|
92
|
+
*/
|
|
83
93
|
getLanguageId(scriptId: T): string | undefined;
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Generate a virtual code.
|
|
96
|
+
*/
|
|
97
|
+
createVirtualCode?(scriptId: T, languageId: string, snapshot: ts.IScriptSnapshot, ctx: CodegenContext<T>): K | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Incremental update a virtual code. If not provide, call createVirtualCode again.
|
|
100
|
+
*/
|
|
101
|
+
updateVirtualCode?(scriptId: T, virtualCode: K, newSnapshot: ts.IScriptSnapshot, ctx: CodegenContext<T>): K | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Cleanup a virtual code.
|
|
104
|
+
*/
|
|
86
105
|
disposeVirtualCode?(scriptId: T, virtualCode: K): void;
|
|
87
|
-
typescript?:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
*/
|
|
107
|
-
resolveLanguageServiceHost?(host: ts.LanguageServiceHost): ts.LanguageServiceHost;
|
|
108
|
-
};
|
|
106
|
+
typescript?: TypeScriptGenericOptions<T, K> & TypeScriptNonTSPluginOptions<T, K>;
|
|
107
|
+
}
|
|
108
|
+
export interface CodegenContext<T = unknown> {
|
|
109
|
+
getAssociatedScript(scriptId: T): SourceScript<T> | undefined;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The following options available to all situations.
|
|
113
|
+
*/
|
|
114
|
+
interface TypeScriptGenericOptions<T, K> {
|
|
115
|
+
extraFileExtensions: ts.FileExtensionInfo[];
|
|
116
|
+
resolveHiddenExtensions?: boolean;
|
|
117
|
+
getServiceScript(root: K): TypeScriptServiceScript<T> | undefined;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The following options will not be available in TS plugin.
|
|
121
|
+
*/
|
|
122
|
+
interface TypeScriptNonTSPluginOptions<T, K> {
|
|
123
|
+
getExtraServiceScripts?(fileName: string, rootVirtualCode: K): TypeScriptExtraServiceScript<T>[];
|
|
124
|
+
resolveLanguageServiceHost?(host: ts.LanguageServiceHost): ts.LanguageServiceHost;
|
|
109
125
|
}
|
|
126
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volar/language-core",
|
|
3
|
-
"version": "2.3.0-alpha.
|
|
3
|
+
"version": "2.3.0-alpha.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"directory": "packages/language-core"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@volar/source-map": "2.3.0-alpha.
|
|
15
|
+
"@volar/source-map": "2.3.0-alpha.6"
|
|
16
16
|
},
|
|
17
|
-
"gitHead": "
|
|
17
|
+
"gitHead": "f3103e86be8d80cb36f66be4c054ef9a255c29b1"
|
|
18
18
|
}
|