@volar/language-core 1.0.16 → 1.0.18

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.
@@ -1,36 +1,22 @@
1
- import { Mapping, SourceMapBase } from '@volar/source-map';
2
- import { Teleport } from './sourceMaps';
3
- import type { EmbeddedFile, LanguageModule, SourceFile } from './types';
4
- export declare function forEachEmbeddeds(file: EmbeddedFile, cb: (embedded: EmbeddedFile) => void): void;
5
- export type DocumentRegistry = ReturnType<typeof createDocumentRegistry>;
6
- export declare function createDocumentRegistry(): {
7
- get: (fileName: string) => [SourceFile, LanguageModule] | undefined;
8
- delete: (fileName: string) => boolean;
9
- has: (fileName: string) => boolean;
10
- set: (fileName: string, vueFile: SourceFile, languageModule: LanguageModule) => [SourceFile, LanguageModule<SourceFile>];
11
- getFileNames: () => string[];
12
- getAll: () => [SourceFile, LanguageModule<SourceFile>][];
13
- getTeleport: (fileName: string) => Teleport | undefined;
14
- getAllEmbeddeds: () => Generator<{
15
- sourceFile: SourceFile;
16
- embedded: EmbeddedFile;
17
- }, void, unknown>;
18
- fromEmbeddedLocation: (fileName: string, offset: number, baseOnRight?: boolean) => Generator<{
19
- fileName: string;
20
- offset: number;
21
- mapping: Mapping<any>;
22
- sourceMap: SourceMapBase<any>;
23
- } | {
24
- fileName: string;
25
- offset: number;
26
- mapping?: undefined;
27
- sourceMap?: undefined;
28
- }, void, unknown>;
29
- fromEmbeddedFile: (file: EmbeddedFile) => SourceFile | undefined;
30
- fromEmbeddedFileName: (fileName: string) => {
31
- sourceFile: SourceFile;
32
- embedded: EmbeddedFile;
33
- } | undefined;
34
- getSourceMap: (file: SourceFile, mappings: Mapping<any>[]) => SourceMapBase<any>;
35
- onSourceFileUpdated(file: SourceFile): void;
1
+ import { SourceMap } from '@volar/source-map';
2
+ import { MirrorMap } from './sourceMaps';
3
+ import type { LanguageModule, FileRangeCapabilities, VirtualFile } from './types';
4
+ export type VirtualFiles = ReturnType<typeof createVirtualFiles>;
5
+ type Row = [
6
+ string,
7
+ ts.IScriptSnapshot,
8
+ VirtualFile,
9
+ LanguageModule
10
+ ];
11
+ export declare function createVirtualFiles(languageModules: LanguageModule[]): {
12
+ update(fileName: string, snapshot: ts.IScriptSnapshot): VirtualFile | undefined;
13
+ delete(fileName: string): void;
14
+ get(fileName: string): readonly [import("typescript/lib/tsserverlibrary").IScriptSnapshot, VirtualFile] | undefined;
15
+ hasSourceFile: (fileName: string) => boolean;
16
+ all: () => Row[];
17
+ getMirrorMap: (file: VirtualFile) => MirrorMap | undefined;
18
+ getMaps: (virtualFile: VirtualFile) => [string, SourceMap<FileRangeCapabilities>][];
19
+ getSourceByVirtualFileName(fileName: string): readonly [string, import("typescript/lib/tsserverlibrary").IScriptSnapshot, VirtualFile] | undefined;
36
20
  };
21
+ export declare function forEachEmbeddedFile(file: VirtualFile, cb: (embedded: VirtualFile) => void): void;
22
+ export {};
@@ -1,128 +1,108 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.createDocumentRegistry = exports.forEachEmbeddeds = void 0;
2
+ exports.forEachEmbeddedFile = exports.createVirtualFiles = void 0;
3
3
  const source_map_1 = require("@volar/source-map");
4
4
  const reactivity_1 = require("@vue/reactivity");
5
5
  const sourceMaps_1 = require("./sourceMaps");
6
- function forEachEmbeddeds(file, cb) {
7
- cb(file);
8
- for (const child of file.embeddeds) {
9
- forEachEmbeddeds(child, cb);
10
- }
11
- }
12
- exports.forEachEmbeddeds = forEachEmbeddeds;
13
- function createDocumentRegistry() {
14
- const files = (0, reactivity_1.shallowReactive)({});
15
- const all = (0, reactivity_1.computed)(() => Object.values(files));
16
- const fileNames = (0, reactivity_1.computed)(() => all.value.map(sourceFile => sourceFile === null || sourceFile === void 0 ? void 0 : sourceFile[0].fileName));
17
- const embeddedDocumentsMap = (0, reactivity_1.computed)(() => {
18
- const map = new WeakMap();
19
- for (const [sourceFile] of all.value) {
20
- forEachEmbeddeds(sourceFile, embedded => {
21
- map.set(embedded, sourceFile);
22
- });
23
- }
24
- return map;
25
- });
26
- const sourceMapsByFileName = (0, reactivity_1.computed)(() => {
6
+ function createVirtualFiles(languageModules) {
7
+ const sourceFileToRootVirtualFileMap = (0, reactivity_1.shallowReactive)({});
8
+ const all = (0, reactivity_1.computed)(() => Object.values(sourceFileToRootVirtualFileMap));
9
+ const virtualFileNameToSource = (0, reactivity_1.computed)(() => {
27
10
  const map = new Map();
28
- for (const [sourceFile] of all.value) {
29
- forEachEmbeddeds(sourceFile, embedded => {
30
- map.set(normalizePath(embedded.fileName), { sourceFile, embedded });
31
- });
32
- }
33
- return map;
34
- });
35
- const teleports = (0, reactivity_1.computed)(() => {
36
- const map = new Map();
37
- for (const key in files) {
38
- const [sourceFile] = files[key];
39
- forEachEmbeddeds(sourceFile, embedded => {
40
- if (embedded.teleportMappings) {
41
- map.set(normalizePath(embedded.fileName), getTeleport(sourceFile, embedded.teleportMappings));
42
- }
11
+ for (const row of all.value) {
12
+ forEachEmbeddedFile(row[2], file => {
13
+ map.set(normalizePath(file.fileName), [file, row]);
43
14
  });
44
15
  }
45
16
  return map;
46
17
  });
47
- const _sourceMaps = new WeakMap();
48
- const _teleports = new WeakMap();
18
+ const virtualFileToSourceMapsMap = new WeakMap();
19
+ const virtualFileToMirrorMap = new WeakMap();
49
20
  return {
50
- get: (fileName) => files[normalizePath(fileName)],
51
- delete: (fileName) => delete files[normalizePath(fileName)],
52
- has: (fileName) => !!files[normalizePath(fileName)],
53
- set: (fileName, vueFile, languageModule) => files[normalizePath(fileName)] = [vueFile, languageModule],
54
- getFileNames: () => fileNames.value,
55
- getAll: () => all.value,
56
- getTeleport: (fileName) => teleports.value.get(normalizePath(fileName)),
57
- getAllEmbeddeds: function* () {
58
- for (const sourceMap of sourceMapsByFileName.value) {
59
- yield sourceMap[1];
21
+ update(fileName, snapshot) {
22
+ const key = normalizePath(fileName);
23
+ if (sourceFileToRootVirtualFileMap[key]) {
24
+ const virtualFile = sourceFileToRootVirtualFileMap[key][2];
25
+ sourceFileToRootVirtualFileMap[key][1] = snapshot;
26
+ sourceFileToRootVirtualFileMap[key][3].updateFile(virtualFile, snapshot);
27
+ return virtualFile; // updated
60
28
  }
61
- },
62
- fromEmbeddedLocation: function* (fileName, offset, baseOnRight = false) {
63
- if (fileName.endsWith('/__VLS_types.ts')) { // TODO: monkey fix
64
- return;
65
- }
66
- const mapped = sourceMapsByFileName.value.get(normalizePath(fileName));
67
- if (mapped) {
68
- const sourceMap = getSourceMap(mapped.sourceFile, mapped.embedded.mappings);
69
- for (const vueRange of sourceMap.toSourceOffsets(offset, baseOnRight)) {
70
- yield {
71
- fileName: mapped.sourceFile.fileName,
72
- offset: vueRange[0],
73
- mapping: vueRange[1],
74
- sourceMap,
75
- };
29
+ for (const languageModule of languageModules) {
30
+ const virtualFile = languageModule.createFile(fileName, snapshot);
31
+ if (virtualFile) {
32
+ sourceFileToRootVirtualFileMap[key] = [fileName, snapshot, (0, reactivity_1.shallowReactive)(virtualFile), languageModule];
33
+ return virtualFile; // created
76
34
  }
77
35
  }
78
- else {
79
- yield {
80
- fileName,
81
- offset,
82
- };
83
- }
84
36
  },
85
- fromEmbeddedFile: function (file) {
86
- return embeddedDocumentsMap.value.get(file);
37
+ delete(fileName) {
38
+ var _a, _b;
39
+ const key = normalizePath(fileName);
40
+ if (sourceFileToRootVirtualFileMap[key]) {
41
+ const virtualFile = sourceFileToRootVirtualFileMap[key][2];
42
+ (_b = (_a = sourceFileToRootVirtualFileMap[key][3]).deleteFile) === null || _b === void 0 ? void 0 : _b.call(_a, virtualFile);
43
+ delete sourceFileToRootVirtualFileMap[key]; // deleted
44
+ }
87
45
  },
88
- fromEmbeddedFileName: function (fileName) {
89
- return sourceMapsByFileName.value.get(normalizePath(fileName));
46
+ get(fileName) {
47
+ const key = normalizePath(fileName);
48
+ if (sourceFileToRootVirtualFileMap[key]) {
49
+ return [
50
+ sourceFileToRootVirtualFileMap[key][1],
51
+ sourceFileToRootVirtualFileMap[key][2],
52
+ ];
53
+ }
90
54
  },
91
- getSourceMap,
92
- // TODO: unuse this
93
- onSourceFileUpdated(file) {
94
- _sourceMaps.delete(file);
95
- _teleports.delete(file);
55
+ hasSourceFile: (fileName) => !!sourceFileToRootVirtualFileMap[normalizePath(fileName)],
56
+ all: () => all.value,
57
+ getMirrorMap: getMirrorMap,
58
+ getMaps: getSourceMaps,
59
+ getSourceByVirtualFileName(fileName) {
60
+ const source = virtualFileNameToSource.value.get(normalizePath(fileName));
61
+ if (source) {
62
+ return [
63
+ source[1][0],
64
+ source[1][1],
65
+ source[0],
66
+ ];
67
+ }
96
68
  },
97
69
  };
98
- function getSourceMap(file, mappings) {
99
- let map1 = _sourceMaps.get(file);
100
- if (!map1) {
101
- map1 = new WeakMap();
102
- _sourceMaps.set(file, map1);
70
+ function getSourceMaps(virtualFile) {
71
+ let sourceMapsBySourceFileName = virtualFileToSourceMapsMap.get(virtualFile.snapshot);
72
+ if (!sourceMapsBySourceFileName) {
73
+ sourceMapsBySourceFileName = new Map();
74
+ virtualFileToSourceMapsMap.set(virtualFile.snapshot, sourceMapsBySourceFileName);
103
75
  }
104
- let map2 = map1.get(mappings);
105
- if (!map2) {
106
- map2 = new source_map_1.SourceMapBase(mappings);
107
- map1.set(mappings, map2);
76
+ const sources = new Set();
77
+ for (const map of virtualFile.mappings) {
78
+ sources.add(map.source);
108
79
  }
109
- return map2;
110
- }
111
- function getTeleport(file, mappings) {
112
- let map1 = _teleports.get(file);
113
- if (!map1) {
114
- map1 = new WeakMap();
115
- _teleports.set(file, map1);
80
+ for (const source of sources) {
81
+ const sourceFileName = source !== null && source !== void 0 ? source : virtualFileNameToSource.value.get(normalizePath(virtualFile.fileName))[1][0];
82
+ if (!sourceMapsBySourceFileName.has(sourceFileName)) {
83
+ sourceMapsBySourceFileName.set(sourceFileName, [
84
+ sourceFileName,
85
+ new source_map_1.SourceMap(virtualFile.mappings.filter(mapping => mapping.source === source)),
86
+ ]);
87
+ }
116
88
  }
117
- let map2 = map1.get(mappings);
118
- if (!map2) {
119
- map2 = new sourceMaps_1.Teleport(mappings);
120
- map1.set(mappings, map2);
89
+ return [...sourceMapsBySourceFileName.values()];
90
+ }
91
+ function getMirrorMap(file) {
92
+ if (!virtualFileToMirrorMap.has(file.snapshot)) {
93
+ virtualFileToMirrorMap.set(file.snapshot, file.mirrorBehaviorMappings ? new sourceMaps_1.MirrorMap(file.mirrorBehaviorMappings) : undefined);
121
94
  }
122
- return map2;
95
+ return virtualFileToMirrorMap.get(file.snapshot);
96
+ }
97
+ }
98
+ exports.createVirtualFiles = createVirtualFiles;
99
+ function forEachEmbeddedFile(file, cb) {
100
+ cb(file);
101
+ for (const embeddedFile of file.embeddedFiles) {
102
+ forEachEmbeddedFile(embeddedFile, cb);
123
103
  }
124
104
  }
125
- exports.createDocumentRegistry = createDocumentRegistry;
105
+ exports.forEachEmbeddedFile = forEachEmbeddedFile;
126
106
  function normalizePath(fileName) {
127
107
  return fileName.replace(/\\/g, '/').toLowerCase();
128
108
  }
@@ -1,37 +1,18 @@
1
1
  import type * as ts from 'typescript/lib/tsserverlibrary';
2
- import { LanguageModule, SourceFile, LanguageServiceHost } from './types';
3
- export type EmbeddedLanguageContext = ReturnType<typeof createEmbeddedLanguageServiceHost>;
4
- export declare function createEmbeddedLanguageServiceHost(host: LanguageServiceHost, languageModules: LanguageModule[]): {
5
- typescriptLanguageServiceHost: ts.LanguageServiceHost;
6
- mapper: {
7
- get: (fileName: string) => [SourceFile, LanguageModule<SourceFile>] | undefined;
8
- delete: (fileName: string) => boolean;
9
- has: (fileName: string) => boolean;
10
- set: (fileName: string, vueFile: SourceFile, languageModule: LanguageModule<SourceFile>) => [SourceFile, LanguageModule<SourceFile>];
11
- getFileNames: () => string[];
12
- getAll: () => [SourceFile, LanguageModule<SourceFile>][];
13
- getTeleport: (fileName: string) => import("./sourceMaps").Teleport | undefined;
14
- getAllEmbeddeds: () => Generator<{
15
- sourceFile: SourceFile;
16
- embedded: import("./types").EmbeddedFile;
17
- }, void, unknown>;
18
- fromEmbeddedLocation: (fileName: string, offset: number, baseOnRight?: boolean) => Generator<{
19
- fileName: string;
20
- offset: number;
21
- mapping: import("@volar/source-map").Mapping<any>;
22
- sourceMap: import("@volar/source-map").SourceMapBase<any>;
23
- } | {
24
- fileName: string;
25
- offset: number;
26
- mapping?: undefined;
27
- sourceMap?: undefined;
28
- }, void, unknown>;
29
- fromEmbeddedFile: (file: import("./types").EmbeddedFile) => SourceFile | undefined;
30
- fromEmbeddedFileName: (fileName: string) => {
31
- sourceFile: SourceFile;
32
- embedded: import("./types").EmbeddedFile;
33
- } | undefined;
34
- getSourceMap: (file: SourceFile, mappings: import("@volar/source-map").Mapping<any>[]) => import("@volar/source-map").SourceMapBase<any>;
35
- onSourceFileUpdated(file: SourceFile): void;
2
+ import { LanguageModule, LanguageServiceHost } from './types';
3
+ export type LanguageContext = ReturnType<typeof createLanguageContext>;
4
+ export declare function createLanguageContext(host: LanguageServiceHost, languageModules: LanguageModule[]): {
5
+ typescript: {
6
+ languageServiceHost: ts.LanguageServiceHost;
7
+ };
8
+ virtualFiles: {
9
+ update(fileName: string, snapshot: ts.IScriptSnapshot): import("./types").VirtualFile | undefined;
10
+ delete(fileName: string): void;
11
+ get(fileName: string): readonly [ts.IScriptSnapshot, import("./types").VirtualFile] | undefined;
12
+ hasSourceFile: (fileName: string) => boolean;
13
+ all: () => [string, ts.IScriptSnapshot, import("./types").VirtualFile, LanguageModule<import("./types").VirtualFile>][];
14
+ getMirrorMap: (file: import("./types").VirtualFile) => import("./sourceMaps").MirrorMap | undefined;
15
+ getMaps: (virtualFile: import("./types").VirtualFile) => [string, import("@volar/source-map").SourceMap<import("./types").FileRangeCapabilities>][];
16
+ getSourceByVirtualFileName(fileName: string): readonly [string, ts.IScriptSnapshot, import("./types").VirtualFile] | undefined;
36
17
  };
37
18
  };
@@ -1,9 +1,9 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.createEmbeddedLanguageServiceHost = void 0;
2
+ exports.createLanguageContext = void 0;
3
3
  const path_1 = require("path");
4
4
  const documentRegistry_1 = require("./documentRegistry");
5
- const reactivity_1 = require("@vue/reactivity");
6
- function createEmbeddedLanguageServiceHost(host, languageModules) {
5
+ const types_1 = require("./types");
6
+ function createLanguageContext(host, languageModules) {
7
7
  for (const languageModule of languageModules.reverse()) {
8
8
  if (languageModule.proxyLanguageServiceHost) {
9
9
  const proxyApis = languageModule.proxyLanguageServiceHost(host);
@@ -19,11 +19,11 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
19
19
  }
20
20
  let lastProjectVersion;
21
21
  let tsProjectVersion = 0;
22
- const documentRegistry = (0, documentRegistry_1.createDocumentRegistry)();
22
+ const virtualFiles = (0, documentRegistry_1.createVirtualFiles)(languageModules);
23
23
  const ts = host.getTypeScriptModule();
24
24
  const scriptSnapshots = new Map();
25
25
  const sourceTsFileVersions = new Map();
26
- const sourceVueFileVersions = new Map();
26
+ const sourceFileVersions = new Map();
27
27
  const virtualFileVersions = new Map();
28
28
  const _tsHost = {
29
29
  fileExists: host.fileExists
@@ -33,20 +33,14 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
33
33
  // .vue.ts -> .vue
34
34
  // .vue.d.ts -> [ignored]
35
35
  const vueFileName = fileName.substring(0, fileName.lastIndexOf('.'));
36
- if (!documentRegistry.get(vueFileName)) {
36
+ if (!virtualFiles.hasSourceFile(vueFileName)) {
37
37
  // create virtual files
38
38
  const scriptSnapshot = host.getScriptSnapshot(vueFileName);
39
39
  if (scriptSnapshot) {
40
- for (const languageModule of languageModules) {
41
- const sourceFile = languageModule.createSourceFile(vueFileName, scriptSnapshot);
42
- if (sourceFile) {
43
- documentRegistry.set(vueFileName, (0, reactivity_1.shallowReactive)(sourceFile), languageModule);
44
- break;
45
- }
46
- }
40
+ virtualFiles.update(vueFileName, scriptSnapshot);
47
41
  }
48
42
  }
49
- if (!!documentRegistry.fromEmbeddedFileName(fileName)) {
43
+ if (virtualFiles.getSourceByVirtualFileName(fileName)) {
50
44
  return true;
51
45
  }
52
46
  return !!((_a = host.fileExists) === null || _a === void 0 ? void 0 : _a.call(host, fileName));
@@ -61,12 +55,12 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
61
55
  readDirectory: (_path, extensions, exclude, include, depth) => {
62
56
  var _a, _b;
63
57
  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 : [];
64
- for (const vuePath of documentRegistry.getFileNames()) {
65
- const vuePath2 = path_1.posix.join(_path, path_1.posix.basename(vuePath));
66
- if (path_1.posix.relative(_path.toLowerCase(), vuePath.toLowerCase()).startsWith('..')) {
58
+ for (const [fileName] of virtualFiles.all()) {
59
+ const vuePath2 = path_1.posix.join(_path, path_1.posix.basename(fileName));
60
+ if (path_1.posix.relative(_path.toLowerCase(), fileName.toLowerCase()).startsWith('..')) {
67
61
  continue;
68
62
  }
69
- if (!depth && vuePath.toLowerCase() === vuePath2.toLowerCase()) {
63
+ if (!depth && fileName.toLowerCase() === vuePath2.toLowerCase()) {
70
64
  result.push(vuePath2);
71
65
  }
72
66
  else if (depth) {
@@ -76,7 +70,7 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
76
70
  return result;
77
71
  },
78
72
  getScriptKind(fileName) {
79
- if (documentRegistry.has(fileName))
73
+ if (virtualFiles.hasSourceFile(fileName))
80
74
  return ts.ScriptKind.Deferred;
81
75
  switch (path_1.posix.extname(fileName)) {
82
76
  case '.js': return ts.ScriptKind.JS;
@@ -89,13 +83,15 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
89
83
  },
90
84
  };
91
85
  return {
92
- typescriptLanguageServiceHost: new Proxy(_tsHost, {
93
- get: (target, property) => {
94
- update();
95
- return target[property] || host[property];
96
- },
97
- }),
98
- mapper: new Proxy(documentRegistry, {
86
+ typescript: {
87
+ languageServiceHost: new Proxy(_tsHost, {
88
+ get: (target, property) => {
89
+ update();
90
+ return target[property] || host[property];
91
+ },
92
+ }),
93
+ },
94
+ virtualFiles: new Proxy(virtualFiles, {
99
95
  get: (target, property) => {
100
96
  update();
101
97
  return target[property];
@@ -109,42 +105,38 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
109
105
  lastProjectVersion = newProjectVersion;
110
106
  if (!shouldUpdate)
111
107
  return;
112
- let tsFileUpdated = false;
113
- const checkRemains = new Set(host.getScriptFileNames());
114
- const sourceFilesShouldUpdate = [];
108
+ let shouldUpdateTsProject = false;
109
+ let virtualFilesUpdatedNum = 0;
110
+ const remainRootFiles = new Set(host.getScriptFileNames());
115
111
  // .vue
116
- for (const [sourceFile, languageModule] of documentRegistry.getAll()) {
117
- checkRemains.delete(sourceFile.fileName);
118
- const snapshot = host.getScriptSnapshot(sourceFile.fileName);
112
+ for (const [fileName] of virtualFiles.all()) {
113
+ remainRootFiles.delete(fileName);
114
+ const snapshot = host.getScriptSnapshot(fileName);
119
115
  if (!snapshot) {
120
116
  // delete
121
- documentRegistry.delete(sourceFile.fileName);
122
- tsFileUpdated = true;
117
+ virtualFiles.delete(fileName);
118
+ shouldUpdateTsProject = true;
123
119
  continue;
124
120
  }
125
- const newVersion = host.getScriptVersion(sourceFile.fileName);
126
- if (sourceVueFileVersions.get(sourceFile.fileName) !== newVersion) {
121
+ const newVersion = host.getScriptVersion(fileName);
122
+ if (sourceFileVersions.get(fileName) !== newVersion) {
127
123
  // update
128
- sourceVueFileVersions.set(sourceFile.fileName, newVersion);
129
- sourceFilesShouldUpdate.push([sourceFile, languageModule, snapshot]);
124
+ sourceFileVersions.set(fileName, newVersion);
125
+ virtualFiles.update(fileName, snapshot);
126
+ virtualFilesUpdatedNum++;
130
127
  }
131
128
  }
132
129
  // no any vue file version change, it mean project version was update by ts file change at this time
133
- if (!sourceFilesShouldUpdate.length) {
134
- tsFileUpdated = true;
130
+ if (!virtualFilesUpdatedNum) {
131
+ shouldUpdateTsProject = true;
135
132
  }
136
133
  // add
137
- for (const fileName of [...checkRemains]) {
134
+ for (const fileName of [...remainRootFiles]) {
138
135
  const snapshot = host.getScriptSnapshot(fileName);
139
136
  if (snapshot) {
140
- for (const languageModule of languageModules) {
141
- const sourceFile = languageModule.createSourceFile(fileName, snapshot);
142
- if (sourceFile) {
143
- sourceVueFileVersions.set(sourceFile.fileName, host.getScriptVersion(fileName));
144
- documentRegistry.set(fileName, (0, reactivity_1.shallowReactive)(sourceFile), languageModule);
145
- checkRemains.delete(fileName);
146
- break;
147
- }
137
+ const virtualFile = virtualFiles.update(fileName, snapshot);
138
+ if (virtualFile) {
139
+ remainRootFiles.delete(fileName);
148
140
  }
149
141
  }
150
142
  }
@@ -152,7 +144,7 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
152
144
  for (const [oldTsFileName, oldTsFileVersion] of [...sourceTsFileVersions]) {
153
145
  const newVersion = host.getScriptVersion(oldTsFileName);
154
146
  if (oldTsFileVersion !== newVersion) {
155
- if (!checkRemains.has(oldTsFileName) && !host.getScriptSnapshot(oldTsFileName)) {
147
+ if (!remainRootFiles.has(oldTsFileName) && !host.getScriptSnapshot(oldTsFileName)) {
156
148
  // delete
157
149
  sourceTsFileVersions.delete(oldTsFileName);
158
150
  }
@@ -160,79 +152,69 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
160
152
  // update
161
153
  sourceTsFileVersions.set(oldTsFileName, newVersion);
162
154
  }
163
- tsFileUpdated = true;
155
+ shouldUpdateTsProject = true;
164
156
  }
165
157
  }
166
- for (const nowFileName of checkRemains) {
158
+ for (const nowFileName of remainRootFiles) {
167
159
  if (!sourceTsFileVersions.has(nowFileName)) {
168
160
  // add
169
161
  const newVersion = host.getScriptVersion(nowFileName);
170
162
  sourceTsFileVersions.set(nowFileName, newVersion);
171
- tsFileUpdated = true;
163
+ shouldUpdateTsProject = true;
172
164
  }
173
165
  }
174
- for (const [sourceFile, languageModule, snapshot] of sourceFilesShouldUpdate) {
175
- (0, documentRegistry_1.forEachEmbeddeds)(sourceFile, embedded => {
176
- virtualFileVersions.delete(embedded.fileName);
177
- });
178
- const oldScripts = {};
179
- const newScripts = {};
180
- if (!tsFileUpdated) {
181
- (0, documentRegistry_1.forEachEmbeddeds)(sourceFile, embedded => {
182
- if (embedded.kind) {
183
- oldScripts[embedded.fileName] = embedded.text;
184
- }
185
- });
186
- }
187
- languageModule.updateSourceFile(sourceFile, snapshot);
188
- documentRegistry.onSourceFileUpdated(sourceFile);
189
- if (!tsFileUpdated) {
190
- (0, documentRegistry_1.forEachEmbeddeds)(sourceFile, embedded => {
191
- if (embedded.kind) {
192
- newScripts[embedded.fileName] = embedded.text;
166
+ for (const [_1, _2, virtualFile] of virtualFiles.all()) {
167
+ if (!shouldUpdateTsProject) {
168
+ (0, documentRegistry_1.forEachEmbeddedFile)(virtualFile, embedded => {
169
+ var _a;
170
+ if (embedded.kind === types_1.FileKind.TypeScriptHostFile) {
171
+ if (virtualFileVersions.has(embedded.fileName) && ((_a = virtualFileVersions.get(embedded.fileName)) === null || _a === void 0 ? void 0 : _a.virtualFileSnapshot) !== embedded.snapshot) {
172
+ shouldUpdateTsProject = true;
173
+ }
193
174
  }
194
175
  });
195
176
  }
196
- if (!tsFileUpdated
197
- && Object.keys(oldScripts).length !== Object.keys(newScripts).length
198
- || Object.keys(oldScripts).some(fileName => oldScripts[fileName] !== newScripts[fileName])) {
199
- tsFileUpdated = true;
200
- }
201
177
  }
202
- if (tsFileUpdated) {
178
+ if (shouldUpdateTsProject) {
203
179
  tsProjectVersion++;
204
180
  }
205
181
  }
206
182
  function getScriptFileNames() {
207
183
  const tsFileNames = new Set();
208
- for (const mapped of documentRegistry.getAllEmbeddeds()) {
209
- if (mapped.embedded.kind) {
210
- tsFileNames.add(mapped.embedded.fileName); // virtual .ts
211
- }
184
+ for (const [_1, _2, sourceFile] of virtualFiles.all()) {
185
+ (0, documentRegistry_1.forEachEmbeddedFile)(sourceFile, embedded => {
186
+ if (embedded.kind === types_1.FileKind.TypeScriptHostFile) {
187
+ tsFileNames.add(embedded.fileName); // virtual .ts
188
+ }
189
+ });
212
190
  }
213
191
  for (const fileName of host.getScriptFileNames()) {
214
- if (!documentRegistry.has(fileName)) {
192
+ if (!virtualFiles.hasSourceFile(fileName)) {
215
193
  tsFileNames.add(fileName); // .ts
216
194
  }
217
195
  }
218
196
  return [...tsFileNames];
219
197
  }
220
198
  function getScriptVersion(fileName) {
221
- var _a, _b, _c;
222
- let mapped = documentRegistry.fromEmbeddedFileName(fileName);
223
- if (mapped) {
224
- if (virtualFileVersions.has(mapped.embedded.fileName)) {
225
- return virtualFileVersions.get(mapped.embedded.fileName);
199
+ let source = virtualFiles.getSourceByVirtualFileName(fileName);
200
+ if (source) {
201
+ let version = virtualFileVersions.get(source[2].fileName);
202
+ if (!version) {
203
+ version = {
204
+ value: 0,
205
+ virtualFileSnapshot: source[2].snapshot,
206
+ sourceFileSnapshot: source[1],
207
+ };
208
+ virtualFileVersions.set(source[2].fileName, version);
226
209
  }
227
- else {
228
- 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;
229
- if (host.isTsc) {
230
- // fix https://github.com/johnsoncodehk/volar/issues/1082
231
- version = host.getScriptVersion(mapped.sourceFile.fileName) + ':' + version;
232
- }
233
- virtualFileVersions.set(mapped.embedded.fileName, version);
234
- return version;
210
+ else if (version.virtualFileSnapshot !== source[2].snapshot
211
+ || (host.isTsc && version.sourceFileSnapshot !== source[1]) // fix https://github.com/johnsoncodehk/volar/issues/1082
212
+ ) {
213
+ version.value++;
214
+ version.virtualFileSnapshot = source[2].snapshot;
215
+ version.sourceFileSnapshot = source[1];
235
216
  }
217
+ return version.value.toString();
236
218
  }
237
219
  return host.getScriptVersion(fileName);
238
220
  }
@@ -242,9 +224,9 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
242
224
  if (cache && cache[0] === version) {
243
225
  return cache[1];
244
226
  }
245
- const mapped = documentRegistry.fromEmbeddedFileName(fileName);
246
- if (mapped) {
247
- const snapshot = ts.ScriptSnapshot.fromString(mapped.embedded.text);
227
+ const source = virtualFiles.getSourceByVirtualFileName(fileName);
228
+ if (source) {
229
+ const snapshot = source[2].snapshot;
248
230
  scriptSnapshots.set(fileName.toLowerCase(), [version, snapshot]);
249
231
  return snapshot;
250
232
  }
@@ -255,5 +237,5 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
255
237
  }
256
238
  }
257
239
  }
258
- exports.createEmbeddedLanguageServiceHost = createEmbeddedLanguageServiceHost;
240
+ exports.createLanguageContext = createLanguageContext;
259
241
  //# sourceMappingURL=languageContext.js.map
@@ -1,5 +1,5 @@
1
1
  import * as SourceMaps from '@volar/source-map';
2
- import { TeleportCapabilities, TeleportMappingData } from './types';
3
- export declare class Teleport extends SourceMaps.SourceMapBase<TeleportMappingData> {
4
- findTeleports(start: number, filter?: (data: TeleportCapabilities) => boolean): Generator<number, void, unknown>;
2
+ import { MirrorBehaviorCapabilities } from './types';
3
+ export declare class MirrorMap extends SourceMaps.SourceMap<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]> {
4
+ findMirrorOffsets(start: number): Generator<readonly [number, MirrorBehaviorCapabilities], void, unknown>;
5
5
  }
package/out/sourceMaps.js CHANGED
@@ -1,19 +1,15 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.Teleport = void 0;
2
+ exports.MirrorMap = void 0;
3
3
  const SourceMaps = require("@volar/source-map");
4
- class Teleport extends SourceMaps.SourceMapBase {
5
- *findTeleports(start, filter) {
4
+ class MirrorMap extends SourceMaps.SourceMap {
5
+ *findMirrorOffsets(start) {
6
6
  for (const mapped of this.toGeneratedOffsets(start)) {
7
- if (!filter || filter(mapped[1].data.toSourceCapabilities)) {
8
- yield mapped[0];
9
- }
7
+ yield [mapped[0], mapped[1].data[1]];
10
8
  }
11
9
  for (const mapped of this.toSourceOffsets(start)) {
12
- if (!filter || filter(mapped[1].data.toGenedCapabilities)) {
13
- yield mapped[0];
14
- }
10
+ yield [mapped[0], mapped[1].data[0]];
15
11
  }
16
12
  }
17
13
  }
18
- exports.Teleport = Teleport;
14
+ exports.MirrorMap = MirrorMap;
19
15
  //# sourceMappingURL=sourceMaps.js.map
package/out/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Mapping } from '@volar/source-map';
2
2
  import type * as ts from 'typescript/lib/tsserverlibrary';
3
- export interface DocumentCapabilities {
3
+ export interface FileCapabilities {
4
4
  diagnostic?: boolean;
5
5
  foldingRange?: boolean;
6
6
  documentFormatting?: boolean | {
@@ -10,7 +10,7 @@ export interface DocumentCapabilities {
10
10
  codeAction?: boolean;
11
11
  inlayHint?: boolean;
12
12
  }
13
- export interface PositionCapabilities {
13
+ export interface FileRangeCapabilities {
14
14
  hover?: boolean;
15
15
  references?: boolean;
16
16
  definition?: boolean;
@@ -27,40 +27,31 @@ export interface PositionCapabilities {
27
27
  referencesCodeLens?: boolean;
28
28
  displayWithLink?: boolean;
29
29
  }
30
- export interface TeleportCapabilities {
30
+ export interface MirrorBehaviorCapabilities {
31
31
  references?: boolean;
32
32
  definition?: boolean;
33
33
  rename?: boolean;
34
34
  }
35
- export interface TeleportMappingData {
36
- toSourceCapabilities: TeleportCapabilities;
37
- toGenedCapabilities: TeleportCapabilities;
38
- }
39
- export interface TextRange {
40
- start: number;
41
- end: number;
42
- }
43
- export interface SourceFile extends EmbeddedFile {
44
- }
45
- export declare enum EmbeddedFileKind {
35
+ export declare enum FileKind {
46
36
  TextFile = 0,
47
37
  TypeScriptHostFile = 1
48
38
  }
49
- export interface EmbeddedFile {
39
+ export interface VirtualFile {
50
40
  fileName: string;
51
- text: string;
52
- kind: EmbeddedFileKind;
53
- capabilities: DocumentCapabilities;
54
- mappings: Mapping<PositionCapabilities>[];
55
- teleportMappings?: Mapping<TeleportMappingData>[];
56
- embeddeds: EmbeddedFile[];
57
- }
58
- export interface LanguageModule<T extends SourceFile = SourceFile> {
59
- createSourceFile(fileName: string, snapshot: ts.IScriptSnapshot): T | undefined;
60
- updateSourceFile(sourceFile: T, snapshot: ts.IScriptSnapshot): void;
41
+ snapshot: ts.IScriptSnapshot;
42
+ kind: FileKind;
43
+ capabilities: FileCapabilities;
44
+ mappings: Mapping<FileRangeCapabilities>[];
45
+ mirrorBehaviorMappings?: Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[];
46
+ embeddedFiles: VirtualFile[];
47
+ }
48
+ export interface LanguageModule<T extends VirtualFile = VirtualFile> {
49
+ createFile(fileName: string, snapshot: ts.IScriptSnapshot): T | undefined;
50
+ updateFile(virtualFile: T, snapshot: ts.IScriptSnapshot): void;
51
+ deleteFile?(virtualFile: T): void;
61
52
  proxyLanguageServiceHost?(host: LanguageServiceHost): Partial<LanguageServiceHost>;
62
53
  }
63
- export type LanguageServiceHost = ts.LanguageServiceHost & {
54
+ export interface LanguageServiceHost extends ts.LanguageServiceHost {
64
55
  getTypeScriptModule(): typeof import('typescript/lib/tsserverlibrary');
65
56
  isTsc?: boolean;
66
- };
57
+ }
package/out/types.js CHANGED
@@ -1,8 +1,9 @@
1
1
  Object.defineProperty(exports, "__esModule", { value: true });
2
- exports.EmbeddedFileKind = void 0;
3
- var EmbeddedFileKind;
4
- (function (EmbeddedFileKind) {
5
- EmbeddedFileKind[EmbeddedFileKind["TextFile"] = 0] = "TextFile";
6
- EmbeddedFileKind[EmbeddedFileKind["TypeScriptHostFile"] = 1] = "TypeScriptHostFile";
7
- })(EmbeddedFileKind = exports.EmbeddedFileKind || (exports.EmbeddedFileKind = {}));
2
+ exports.FileKind = void 0;
3
+ var FileKind;
4
+ (function (FileKind) {
5
+ FileKind[FileKind["TextFile"] = 0] = "TextFile";
6
+ FileKind[FileKind["TypeScriptHostFile"] = 1] = "TypeScriptHostFile";
7
+ })(FileKind = exports.FileKind || (exports.FileKind = {}));
8
+ ;
8
9
  //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volar/language-core",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "main": "out/index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -13,9 +13,9 @@
13
13
  "directory": "packages/language-core"
14
14
  },
15
15
  "dependencies": {
16
- "@volar/source-map": "1.0.16",
16
+ "@volar/source-map": "1.0.18",
17
17
  "@vue/reactivity": "^3.2.45",
18
18
  "muggle-string": "^0.1.0"
19
19
  },
20
- "gitHead": "af476047d8859652254ed36f8aee184f1972a97a"
20
+ "gitHead": "f102ee7bfc96792c63746a5dcb9742e3346d5cc7"
21
21
  }