@volar/language-core 1.0.14 → 1.0.17

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,33 +19,28 @@ 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
- const tsFileVersions = new Map();
25
24
  const scriptSnapshots = new Map();
26
- const fileVersions = new Map();
25
+ const sourceTsFileVersions = new Map();
26
+ const sourceFileVersions = new Map();
27
+ const virtualFileVersions = new Map();
27
28
  const _tsHost = {
28
29
  fileExists: host.fileExists
29
30
  ? fileName => {
30
31
  var _a;
31
32
  // .vue.js -> .vue
32
33
  // .vue.ts -> .vue
33
- // .vue.d.ts (never)
34
+ // .vue.d.ts -> [ignored]
34
35
  const vueFileName = fileName.substring(0, fileName.lastIndexOf('.'));
35
- if (!documentRegistry.get(vueFileName)) {
36
+ if (!virtualFiles.hasSourceFile(vueFileName)) {
36
37
  // create virtual files
37
38
  const scriptSnapshot = host.getScriptSnapshot(vueFileName);
38
39
  if (scriptSnapshot) {
39
- for (const languageModule of languageModules) {
40
- const sourceFile = languageModule.createSourceFile(vueFileName, scriptSnapshot);
41
- if (sourceFile) {
42
- documentRegistry.set(vueFileName, (0, reactivity_1.shallowReactive)(sourceFile), languageModule);
43
- break;
44
- }
45
- }
40
+ virtualFiles.update(vueFileName, scriptSnapshot);
46
41
  }
47
42
  }
48
- if (!!documentRegistry.fromEmbeddedFileName(fileName)) {
43
+ if (virtualFiles.getSourceByVirtualFileName(fileName)) {
49
44
  return true;
50
45
  }
51
46
  return !!((_a = host.fileExists) === null || _a === void 0 ? void 0 : _a.call(host, fileName));
@@ -60,12 +55,12 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
60
55
  readDirectory: (_path, extensions, exclude, include, depth) => {
61
56
  var _a, _b;
62
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 : [];
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('..')) {
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('..')) {
66
61
  continue;
67
62
  }
68
- if (!depth && vuePath.toLowerCase() === vuePath2.toLowerCase()) {
63
+ if (!depth && fileName.toLowerCase() === vuePath2.toLowerCase()) {
69
64
  result.push(vuePath2);
70
65
  }
71
66
  else if (depth) {
@@ -75,7 +70,7 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
75
70
  return result;
76
71
  },
77
72
  getScriptKind(fileName) {
78
- if (documentRegistry.has(fileName))
73
+ if (virtualFiles.hasSourceFile(fileName))
79
74
  return ts.ScriptKind.Deferred;
80
75
  switch (path_1.posix.extname(fileName)) {
81
76
  case '.js': return ts.ScriptKind.JS;
@@ -88,13 +83,15 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
88
83
  },
89
84
  };
90
85
  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, {
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, {
98
95
  get: (target, property) => {
99
96
  update();
100
97
  return target[property];
@@ -104,139 +101,120 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
104
101
  function update() {
105
102
  var _a;
106
103
  const newProjectVersion = (_a = host.getProjectVersion) === null || _a === void 0 ? void 0 : _a.call(host);
107
- const sholdUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
104
+ const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
108
105
  lastProjectVersion = newProjectVersion;
109
- if (!sholdUpdate)
106
+ if (!shouldUpdate)
110
107
  return;
111
- let tsFileUpdated = false;
112
- const remainFileNames = new Set(host.getScriptFileNames());
113
- const sourceFilesToUpdate = [];
108
+ let shouldUpdateTsProject = false;
109
+ let virtualFilesUpdatedNum = 0;
110
+ const remainRootFiles = new Set(host.getScriptFileNames());
114
111
  // .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
- }
112
+ for (const [fileName] of virtualFiles.all()) {
113
+ remainRootFiles.delete(fileName);
114
+ const snapshot = host.getScriptSnapshot(fileName);
115
+ if (!snapshot) {
116
+ // delete
117
+ virtualFiles.delete(fileName);
118
+ shouldUpdateTsProject = true;
119
+ continue;
120
+ }
121
+ const newVersion = host.getScriptVersion(fileName);
122
+ if (sourceFileVersions.get(fileName) !== newVersion) {
123
+ // update
124
+ sourceFileVersions.set(fileName, newVersion);
125
+ virtualFiles.update(fileName, snapshot);
126
+ virtualFilesUpdatedNum++;
131
127
  }
132
128
  }
133
129
  // no any vue file version change, it mean project version was update by ts file change at this time
134
- if (!sourceFilesToUpdate.length) {
135
- tsFileUpdated = true;
130
+ if (!virtualFilesUpdatedNum) {
131
+ shouldUpdateTsProject = true;
136
132
  }
137
133
  // add
138
- for (const fileName of [...remainFileNames]) {
134
+ for (const fileName of [...remainRootFiles]) {
139
135
  const snapshot = host.getScriptSnapshot(fileName);
140
136
  if (snapshot) {
141
- for (const languageModule of languageModules) {
142
- const sourceFile = languageModule.createSourceFile(fileName, snapshot);
143
- if (sourceFile) {
144
- fileVersions.set(sourceFile.fileName, host.getScriptVersion(fileName));
145
- documentRegistry.set(fileName, (0, reactivity_1.shallowReactive)(sourceFile), languageModule);
146
- remainFileNames.delete(fileName);
147
- break;
148
- }
137
+ const virtualFile = virtualFiles.update(fileName, snapshot);
138
+ if (virtualFile) {
139
+ remainRootFiles.delete(fileName);
149
140
  }
150
141
  }
151
142
  }
152
143
  // .ts / .js / .d.ts / .json ...
153
- for (const [oldTsFileName, oldTsFileVersion] of [...tsFileVersions]) {
144
+ for (const [oldTsFileName, oldTsFileVersion] of [...sourceTsFileVersions]) {
154
145
  const newVersion = host.getScriptVersion(oldTsFileName);
155
146
  if (oldTsFileVersion !== newVersion) {
156
- if (!remainFileNames.has(oldTsFileName) && !host.getScriptSnapshot(oldTsFileName)) {
147
+ if (!remainRootFiles.has(oldTsFileName) && !host.getScriptSnapshot(oldTsFileName)) {
157
148
  // delete
158
- tsFileVersions.delete(oldTsFileName);
149
+ sourceTsFileVersions.delete(oldTsFileName);
159
150
  }
160
151
  else {
161
152
  // update
162
- tsFileVersions.set(oldTsFileName, newVersion);
153
+ sourceTsFileVersions.set(oldTsFileName, newVersion);
163
154
  }
164
- tsFileUpdated = true;
155
+ shouldUpdateTsProject = true;
165
156
  }
166
157
  }
167
- for (const nowFileName of remainFileNames) {
168
- if (!tsFileVersions.has(nowFileName)) {
158
+ for (const nowFileName of remainRootFiles) {
159
+ if (!sourceTsFileVersions.has(nowFileName)) {
169
160
  // add
170
161
  const newVersion = host.getScriptVersion(nowFileName);
171
- tsFileVersions.set(nowFileName, newVersion);
172
- tsFileUpdated = true;
162
+ sourceTsFileVersions.set(nowFileName, newVersion);
163
+ shouldUpdateTsProject = true;
173
164
  }
174
165
  }
175
- for (const [sourceFile, languageModule, snapshot] of sourceFilesToUpdate) {
176
- (0, documentRegistry_1.forEachEmbeddeds)(sourceFile, embedded => {
177
- fileVersions.delete(embedded.fileName);
178
- });
179
- const oldScripts = {};
180
- const newScripts = {};
181
- if (!tsFileUpdated) {
182
- (0, documentRegistry_1.forEachEmbeddeds)(sourceFile, embedded => {
183
- if (embedded.kind) {
184
- oldScripts[embedded.fileName] = embedded.text;
185
- }
186
- });
187
- }
188
- languageModule.updateSourceFile(sourceFile, snapshot);
189
- documentRegistry.onSourceFileUpdated(sourceFile);
190
- if (!tsFileUpdated) {
191
- (0, documentRegistry_1.forEachEmbeddeds)(sourceFile, embedded => {
192
- if (embedded.kind) {
193
- 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
+ }
194
174
  }
195
175
  });
196
176
  }
197
- if (!tsFileUpdated
198
- && Object.keys(oldScripts).length !== Object.keys(newScripts).length
199
- || Object.keys(oldScripts).some(fileName => oldScripts[fileName] !== newScripts[fileName])) {
200
- tsFileUpdated = true;
201
- }
202
177
  }
203
- if (tsFileUpdated) {
178
+ if (shouldUpdateTsProject) {
204
179
  tsProjectVersion++;
205
180
  }
206
181
  }
207
182
  function getScriptFileNames() {
208
183
  const tsFileNames = new Set();
209
- for (const mapped of documentRegistry.getAllEmbeddeds()) {
210
- if (mapped.embedded.kind) {
211
- tsFileNames.add(mapped.embedded.fileName); // virtual .ts
212
- }
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
+ });
213
190
  }
214
191
  for (const fileName of host.getScriptFileNames()) {
215
- if (host.isTsPlugin) {
216
- tsFileNames.add(fileName); // .vue + .ts
217
- }
218
- else if (!documentRegistry.has(fileName)) {
192
+ if (!virtualFiles.hasSourceFile(fileName)) {
219
193
  tsFileNames.add(fileName); // .ts
220
194
  }
221
195
  }
222
196
  return [...tsFileNames];
223
197
  }
224
198
  function getScriptVersion(fileName) {
225
- var _a, _b, _c;
226
- let mapped = documentRegistry.fromEmbeddedFileName(fileName);
227
- if (mapped) {
228
- if (fileVersions.has(mapped.embedded.fileName)) {
229
- return fileVersions.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);
230
209
  }
231
- else {
232
- 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;
233
- if (host.isTsc) {
234
- // fix https://github.com/johnsoncodehk/volar/issues/1082
235
- version = host.getScriptVersion(mapped.sourceFile.fileName) + ':' + version;
236
- }
237
- fileVersions.set(mapped.embedded.fileName, version);
238
- 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];
239
216
  }
217
+ return version.value.toString();
240
218
  }
241
219
  return host.getScriptVersion(fileName);
242
220
  }
@@ -246,9 +224,9 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
246
224
  if (cache && cache[0] === version) {
247
225
  return cache[1];
248
226
  }
249
- const mapped = documentRegistry.fromEmbeddedFileName(fileName);
250
- if (mapped) {
251
- const snapshot = ts.ScriptSnapshot.fromString(mapped.embedded.text);
227
+ const source = virtualFiles.getSourceByVirtualFileName(fileName);
228
+ if (source) {
229
+ const snapshot = source[2].snapshot;
252
230
  scriptSnapshots.set(fileName.toLowerCase(), [version, snapshot]);
253
231
  return snapshot;
254
232
  }
@@ -259,5 +237,5 @@ function createEmbeddedLanguageServiceHost(host, languageModules) {
259
237
  }
260
238
  }
261
239
  }
262
- exports.createEmbeddedLanguageServiceHost = createEmbeddedLanguageServiceHost;
240
+ exports.createLanguageContext = createLanguageContext;
263
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,41 +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
- isTsPlugin?: boolean;
66
56
  isTsc?: boolean;
67
- };
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.14",
3
+ "version": "1.0.17",
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.14",
16
+ "@volar/source-map": "1.0.17",
17
17
  "@vue/reactivity": "^3.2.45",
18
18
  "muggle-string": "^0.1.0"
19
19
  },
20
- "gitHead": "ce4d48b37db784400e15fe08282edc836e24d4cd"
20
+ "gitHead": "b66b64f579b5cafee9b8d70aa9f9303f39b6df49"
21
21
  }