@volar/monaco 2.0.0-alpha.9 → 2.0.1

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/README.md CHANGED
@@ -22,15 +22,22 @@ We assume you already know:
22
22
  // my-lang.worker.ts
23
23
  import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker';
24
24
  import type * as monaco from 'monaco-editor-core';
25
- import { createLanguageService } from '@volar/monaco/worker';
25
+ import { createSimpleWorkerService, ServiceEnvironment } from '@volar/monaco/worker';
26
26
 
27
27
  self.onmessage = () => {
28
28
  worker.initialize((ctx: monaco.worker.IWorkerContext) => {
29
- return createLanguageService({
29
+ const env: ServiceEnvironment = {
30
+ workspaceFolder: 'file:///',
31
+ };
32
+ return createSimpleWorkerService({
30
33
  workerContext: ctx,
31
- config: {
32
- // ...Language Service Config of my-lang language support
33
- },
34
+ env,
35
+ languagePlugins: [
36
+ // ...
37
+ ],
38
+ servicePlugins: [
39
+ // ...
40
+ ],
34
41
  });
35
42
  });
36
43
  };
@@ -41,29 +48,80 @@ self.onmessage = () => {
41
48
  ```diff
42
49
  import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker';
43
50
  import type * as monaco from 'monaco-editor-core';
44
- import { createLanguageService } from '@volar/monaco/worker';
51
+ -import { createSimpleWorkerService, ServiceEnvironment } from '@volar/monaco/worker';
52
+ +import {
53
+ + createTypeScriptWorkerService,
54
+ + ServiceEnvironment,
55
+ +} from '@volar/monaco/worker';
45
56
  +import * as ts from 'typescript';
46
- +import createTypeScriptService, { createJsDelivrDtsHost } from 'volar-service-typescript';
57
+ +import { create as createTypeScriptService } from 'volar-service-typescript';
47
58
 
48
59
  self.onmessage = () => {
49
60
  worker.initialize((ctx: monaco.worker.IWorkerContext) => {
50
- return createLanguageService({
51
- workerContext: ctx,
52
- config: {
53
- // ...Language Service Config of my-lang language support
54
- + services: {
55
- + typescript: createTypeScriptService({
56
- + // Enable auto fetch node_modules types
57
- + dtsHost: createJsDelivrDtsHost({ typescript: '4.9.5' }),
58
- + })
59
- + },
60
- },
61
+ const env: ServiceEnvironment = {
62
+ workspaceFolder: 'file:///',
61
63
  + typescript: {
62
- + module: ts,
63
- + compilerOptions: {
64
- + // ...tsconfig options
65
- + },
64
+ + uriToFileName: uri => uri.substring('file://'.length),
65
+ + fileNameToUri: fileName => 'file://' + fileName,
66
66
  + },
67
+ };
68
+ - return createSimpleWorkerService({
69
+ + return createTypeScriptWorkerService({
70
+ + typescript: ts,
71
+ + compilerOptions: {
72
+ + // ...
73
+ + },
74
+ workerContext: ctx,
75
+ env,
76
+ languagePlugins: [
77
+ // ...
78
+ ],
79
+ servicePlugins: [
80
+ // ...
81
+ + createTypeScriptService(ts),
82
+ ],
83
+ });
84
+ });
85
+ };
86
+ ```
87
+
88
+ #### Add ATA Support for TypeScript
89
+
90
+ ```diff
91
+ import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker';
92
+ import type * as monaco from 'monaco-editor-core';
93
+ import {
94
+ createTypeScriptWorkerService,
95
+ ServiceEnvironment,
96
+ + activateAutomaticTypeAcquisition,
97
+ } from '@volar/monaco/worker';
98
+ import * as ts from 'typescript';
99
+ import { create as createTypeScriptService } from 'volar-service-typescript';
100
+
101
+ self.onmessage = () => {
102
+ worker.initialize((ctx: monaco.worker.IWorkerContext) => {
103
+ const env: ServiceEnvironment = {
104
+ workspaceFolder: 'file:///',
105
+ typescript: {
106
+ uriToFileName: uri => uri.substring('file://'.length),
107
+ fileNameToUri: fileName => 'file://' + fileName,
108
+ },
109
+ };
110
+ + activateAutomaticTypeAcquisition(env);
111
+ return createTypeScriptWorkerService({
112
+ typescript: ts,
113
+ compilerOptions: {
114
+ // ...
115
+ },
116
+ workerContext: ctx,
117
+ env,
118
+ languagePlugins: [
119
+ // ...
120
+ ],
121
+ servicePlugins: [
122
+ // ...
123
+ createTypeScriptService(ts),
124
+ ],
67
125
  });
68
126
  });
69
127
  };
@@ -90,7 +148,7 @@ import myWorker from './my-lang.worker?worker';
90
148
  ```ts
91
149
  import type { LanguageService } from '@volar/language-service';
92
150
  import { editor, languages, Uri } from 'monaco-editor-core';
93
- import * as VolarMonaco from '@volar/monaco';
151
+ import { activateMarkers, activateAutoInsertion, registerProviders } from '@volar/monaco';
94
152
 
95
153
  languages.register({ id: 'my-lang', extensions: ['.my-lang'] });
96
154
 
@@ -99,7 +157,7 @@ languages.onLanguage('my-lang', () => {
99
157
  moduleId: 'vs/language/my-lang/myLangWorker',
100
158
  label: 'my-lang',
101
159
  });
102
- VolarMonaco.editor.activateMarkers(
160
+ activateMarkers(
103
161
  worker,
104
162
  ['my-lang'],
105
163
  'my-lang-markers-owner',
@@ -108,14 +166,14 @@ languages.onLanguage('my-lang', () => {
108
166
  editor
109
167
  );
110
168
  // auto close tags
111
- VolarMonaco.editor.activateAutoInsertion(
169
+ activateAutoInsertion(
112
170
  worker,
113
171
  ['my-lang'],
114
172
  // sync files
115
173
  () => [Uri.file('/Foo.my-lang'), Uri.file('/Bar.my-lang')],
116
174
  editor
117
175
  );
118
- VolarMonaco.languages.registerProviders(worker, ['my-lang'], languages)
176
+ registerProviders(worker, ['my-lang'], languages)
119
177
  });
120
178
  ```
121
179
 
package/lib/ata.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { ServiceEnvironment } from '@volar/language-service';
2
+ export declare function activateAutomaticTypeAcquisition(env: ServiceEnvironment, onFetch?: (path: string, content: string) => void): void;
package/lib/ata.js ADDED
@@ -0,0 +1,228 @@
1
+ export function activateAutomaticTypeAcquisition(env, onFetch) {
2
+ const textCache = new Map();
3
+ const jsonCache = new Map();
4
+ const npmFs = createJsDelivrNpmFileSystem();
5
+ const _fs = env.fs;
6
+ env.fs = {
7
+ async stat(uri) {
8
+ return await npmFs.stat(uri) ?? await _fs?.stat(uri);
9
+ },
10
+ async readDirectory(uri) {
11
+ return [
12
+ ...await npmFs.readDirectory(uri),
13
+ ...await _fs?.readDirectory(uri) ?? [],
14
+ ];
15
+ },
16
+ async readFile(uri) {
17
+ return await npmFs.readFile(uri) ?? await _fs?.readFile(uri);
18
+ },
19
+ };
20
+ function createJsDelivrNpmFileSystem() {
21
+ const fetchResults = new Map();
22
+ const flatResults = new Map();
23
+ return {
24
+ async stat(uri) {
25
+ const fileName = env.typescript.uriToFileName(uri);
26
+ if (fileName === '/node_modules') {
27
+ return {
28
+ type: 2,
29
+ size: -1,
30
+ ctime: -1,
31
+ mtime: -1,
32
+ };
33
+ }
34
+ if (fileName.startsWith('/node_modules/')) {
35
+ const path = uri.substring('/node_modules/'.length);
36
+ return await _stat(path);
37
+ }
38
+ },
39
+ async readFile(uri) {
40
+ const fileName = env.typescript.uriToFileName(uri);
41
+ if (fileName.startsWith('/node_modules/')) {
42
+ const path = uri.substring('/node_modules/'.length);
43
+ return await _readFile(path);
44
+ }
45
+ },
46
+ async readDirectory(uri) {
47
+ const fileName = env.typescript.uriToFileName(uri);
48
+ if (fileName.startsWith('/node_modules/')) {
49
+ const path = uri.substring('/node_modules/'.length);
50
+ return _readDirectory(path);
51
+ }
52
+ return [];
53
+ },
54
+ };
55
+ async function _stat(path) {
56
+ const pkgName = getPackageName(path);
57
+ if (!pkgName || !await isValidPackageName(pkgName)) {
58
+ return;
59
+ }
60
+ if (!flatResults.has(pkgName)) {
61
+ flatResults.set(pkgName, flat(pkgName));
62
+ }
63
+ const flatResult = await flatResults.get(pkgName);
64
+ const filePath = path.slice(pkgName.length);
65
+ const file = flatResult.find(file => file.name === filePath);
66
+ if (file) {
67
+ return {
68
+ type: 1,
69
+ ctime: new Date(file.time).valueOf(),
70
+ mtime: new Date(file.time).valueOf(),
71
+ size: file.size,
72
+ };
73
+ }
74
+ else if (flatResult.some(file => file.name.startsWith(filePath + '/'))) {
75
+ return {
76
+ type: 2,
77
+ ctime: -1,
78
+ mtime: -1,
79
+ size: -1,
80
+ };
81
+ }
82
+ }
83
+ async function _readDirectory(path) {
84
+ const pkgName = getPackageName(path);
85
+ if (!pkgName || !await isValidPackageName(pkgName)) {
86
+ return [];
87
+ }
88
+ if (!flatResults.has(pkgName)) {
89
+ flatResults.set(pkgName, flat(pkgName));
90
+ }
91
+ const flatResult = await flatResults.get(pkgName);
92
+ const dirPath = path.slice(pkgName.length);
93
+ const files = flatResult
94
+ .filter(f => f.name.substring(0, f.name.lastIndexOf('/')) === dirPath)
95
+ .map(f => f.name.slice(dirPath.length + 1));
96
+ const dirs = flatResult
97
+ .filter(f => f.name.startsWith(dirPath + '/') && f.name.substring(dirPath.length + 1).split('/').length >= 2)
98
+ .map(f => f.name.slice(dirPath.length + 1).split('/')[0]);
99
+ return [
100
+ ...files.map(f => [f, 1]),
101
+ ...[...new Set(dirs)].map(f => [f, 2]),
102
+ ];
103
+ }
104
+ async function _readFile(path) {
105
+ const pkgName = getPackageName(path);
106
+ if (!pkgName || !await isValidPackageName(pkgName)) {
107
+ return;
108
+ }
109
+ if (!fetchResults.has(path)) {
110
+ fetchResults.set(path, (async () => {
111
+ if ((await _stat(path))?.type !== 1) {
112
+ return;
113
+ }
114
+ const text = await fetchText(`https://cdn.jsdelivr.net/npm/${path}`);
115
+ if (text !== undefined) {
116
+ onFetch?.(path, text);
117
+ }
118
+ return text;
119
+ })());
120
+ }
121
+ return await fetchResults.get(path);
122
+ }
123
+ async function flat(pkgNameWithVersion) {
124
+ let pkgName = pkgNameWithVersion;
125
+ let version = 'latest';
126
+ if (pkgNameWithVersion.substring(1).includes('@')) {
127
+ pkgName = pkgNameWithVersion.substring(0, pkgNameWithVersion.lastIndexOf('@'));
128
+ version = pkgNameWithVersion.substring(pkgNameWithVersion.lastIndexOf('@') + 1);
129
+ }
130
+ // resolve tag version
131
+ if (version === 'latest') {
132
+ const data = await fetchJson(`https://data.jsdelivr.com/v1/package/resolve/npm/${pkgName}@latest`);
133
+ if (!data?.version) {
134
+ return [];
135
+ }
136
+ version = data.version;
137
+ }
138
+ const flat = await fetchJson(`https://data.jsdelivr.com/v1/package/npm/${pkgName}@${version}/flat`);
139
+ if (!flat) {
140
+ return [];
141
+ }
142
+ return flat.files;
143
+ }
144
+ async function isValidPackageName(pkgName) {
145
+ // @aaa/bbb@latest -> @aaa/bbb
146
+ if (pkgName.substring(1).includes('@')) {
147
+ pkgName = pkgName.substring(0, pkgName.lastIndexOf('@'));
148
+ }
149
+ // ignore @aaa/node_modules
150
+ if (pkgName.endsWith('/node_modules')) {
151
+ return false;
152
+ }
153
+ // hard code for known invalid package
154
+ if (pkgName.startsWith('@typescript/') || pkgName.startsWith('@types/typescript__')) {
155
+ return false;
156
+ }
157
+ // don't check @types if original package already having types
158
+ if (pkgName.startsWith('@types/')) {
159
+ let originalPkgName = pkgName.slice('@types/'.length);
160
+ if (originalPkgName.indexOf('__') >= 0) {
161
+ originalPkgName = '@' + originalPkgName.replace('__', '/');
162
+ }
163
+ const packageJson = await _readFile(`${originalPkgName}/package.json`);
164
+ if (packageJson) {
165
+ const packageJsonObj = JSON.parse(packageJson);
166
+ if (packageJsonObj.types || packageJsonObj.typings) {
167
+ return false;
168
+ }
169
+ const indexDts = await _stat(`${originalPkgName}/index.d.ts`);
170
+ if (indexDts?.type === 1) {
171
+ return false;
172
+ }
173
+ }
174
+ }
175
+ return true;
176
+ }
177
+ }
178
+ /**
179
+ * @example
180
+ * "a/b/c" -> "a"
181
+ * "@a/b/c" -> "@a/b"
182
+ * "@a/b@1.2.3/c" -> "@a/b@1.2.3"
183
+ */
184
+ function getPackageName(path) {
185
+ const parts = path.split('/');
186
+ let pkgName = parts[0];
187
+ if (pkgName.startsWith('@')) {
188
+ if (parts.length < 2 || !parts[1]) {
189
+ return undefined;
190
+ }
191
+ pkgName += '/' + parts[2];
192
+ }
193
+ return pkgName;
194
+ }
195
+ async function fetchText(url) {
196
+ if (!textCache.has(url)) {
197
+ textCache.set(url, (async () => {
198
+ try {
199
+ const res = await fetch(url);
200
+ if (res.status === 200) {
201
+ return await res.text();
202
+ }
203
+ }
204
+ catch {
205
+ // ignore
206
+ }
207
+ })());
208
+ }
209
+ return await textCache.get(url);
210
+ }
211
+ async function fetchJson(url) {
212
+ if (!jsonCache.has(url)) {
213
+ jsonCache.set(url, (async () => {
214
+ try {
215
+ const res = await fetch(url);
216
+ if (res.status === 200) {
217
+ return await res.json();
218
+ }
219
+ }
220
+ catch {
221
+ // ignore
222
+ }
223
+ })());
224
+ }
225
+ return await jsonCache.get(url);
226
+ }
227
+ }
228
+ //# sourceMappingURL=ata.js.map
package/lib/editor.js CHANGED
@@ -3,7 +3,7 @@ import { markers } from './markers.js';
3
3
  export function activateMarkers(worker, languages, markersOwn, getSyncUris, editor) {
4
4
  const disposables = [];
5
5
  const listener = new Map();
6
- disposables.push(editor.onDidCreateModel((model) => hostingMarkers(model)), editor.onWillDisposeModel(stopHostingMarkers), editor.onDidChangeModelLanguage((event) => {
6
+ disposables.push(editor.onDidCreateModel(model => hostingMarkers(model)), editor.onWillDisposeModel(stopHostingMarkers), editor.onDidChangeModelLanguage(event => {
7
7
  stopHostingMarkers(event.model);
8
8
  hostingMarkers(event.model);
9
9
  }), {
@@ -16,7 +16,7 @@ export function activateMarkers(worker, languages, markersOwn, getSyncUris, edit
16
16
  for (const model of editor.getModels()) {
17
17
  hostingMarkers(model);
18
18
  }
19
- return { dispose: () => disposables.forEach((d) => d.dispose()) };
19
+ return { dispose: () => disposables.forEach(d => d.dispose()) };
20
20
  function stopHostingMarkers(model) {
21
21
  editor.setModelMarkers(model, markersOwn, []);
22
22
  const key = model.uri.toString();
@@ -76,7 +76,7 @@ export function activateAutoInsertion(worker, languages, getSyncUris, editor) {
76
76
  const disposables = [];
77
77
  const listener = new Map();
78
78
  let timeout;
79
- disposables.push(editor.onDidCreateModel((model) => hostingAutoInsertion(model)), editor.onWillDisposeModel(stopHostingAutoInsertion), editor.onDidChangeModelLanguage((event) => {
79
+ disposables.push(editor.onDidCreateModel(model => hostingAutoInsertion(model)), editor.onWillDisposeModel(stopHostingAutoInsertion), editor.onDidChangeModelLanguage(event => {
80
80
  stopHostingAutoInsertion(event.model);
81
81
  hostingAutoInsertion(event.model);
82
82
  }), {
@@ -90,7 +90,7 @@ export function activateAutoInsertion(worker, languages, getSyncUris, editor) {
90
90
  for (const model of editor.getModels()) {
91
91
  hostingAutoInsertion(model);
92
92
  }
93
- return { dispose: () => disposables.forEach((d) => d.dispose()) };
93
+ return { dispose: () => disposables.forEach(d => d.dispose()) };
94
94
  function stopHostingAutoInsertion(model) {
95
95
  if (listener.has(model)) {
96
96
  listener.get(model)?.dispose();
@@ -101,7 +101,7 @@ export function activateAutoInsertion(worker, languages, getSyncUris, editor) {
101
101
  if (!languages.includes(model.getLanguageId?.() ?? model.getModeId?.())) {
102
102
  return;
103
103
  }
104
- listener.set(model, model.onDidChangeContent((e) => {
104
+ listener.set(model, model.onDidChangeContent(e => {
105
105
  if (model.isDisposed()) {
106
106
  return;
107
107
  }
@@ -137,7 +137,7 @@ export function activateAutoInsertion(worker, languages, getSyncUris, editor) {
137
137
  if (model.getVersionId() !== version) {
138
138
  return;
139
139
  }
140
- const codeEditor = editor.getEditors().find((e) => e.getModel() === model);
140
+ const codeEditor = editor.getEditors().find(e => e.getModel() === model);
141
141
  if (codeEditor && edit && model.getVersionId() === version) {
142
142
  if (typeof edit === 'string') {
143
143
  codeEditor?.getContribution('snippetController2')?.insert(edit);
package/lib/languages.js CHANGED
@@ -27,6 +27,6 @@ export async function registerProviders(worker, language, getSyncUris, languages
27
27
  languages.registerDocumentSemanticTokensProvider(language, provider),
28
28
  languages.registerDocumentRangeSemanticTokensProvider(language, provider),
29
29
  ];
30
- return { dispose: () => disposables.forEach((d) => d.dispose()) };
30
+ return { dispose: () => disposables.forEach(d => d.dispose()) };
31
31
  }
32
32
  //# sourceMappingURL=languages.js.map
package/lib/provider.js CHANGED
@@ -245,8 +245,8 @@ export async function createLanguageFeaturesProvider(worker, getSyncUris) {
245
245
  },
246
246
  async provideSelectionRanges(model, positions) {
247
247
  const languageService = await worker.withSyncedResources(getSyncUris());
248
- const codeResults = await Promise.all(positions.map((position) => languageService.getSelectionRanges(model.uri.toString(), [fromPosition(position)])));
249
- return codeResults.map((codeResult) => codeResult?.map(toSelectionRange) ?? []);
248
+ const codeResults = await Promise.all(positions.map(position => languageService.getSelectionRanges(model.uri.toString(), [fromPosition(position)])));
249
+ return codeResults.map(codeResult => codeResult?.map(toSelectionRange) ?? []);
250
250
  },
251
251
  async provideSignatureHelp(model, position, _token, context) {
252
252
  const languageService = await worker.withSyncedResources(getSyncUris());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volar/monaco",
3
- "version": "2.0.0-alpha.9",
3
+ "version": "2.0.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "files": [
@@ -13,8 +13,8 @@
13
13
  "directory": "packages/monaco"
14
14
  },
15
15
  "dependencies": {
16
- "@volar/language-service": "2.0.0-alpha.9",
17
- "@volar/typescript": "2.0.0-alpha.9",
16
+ "@volar/language-service": "2.0.1",
17
+ "@volar/typescript": "2.0.1",
18
18
  "monaco-languageserver-types": "^0.3.2",
19
19
  "monaco-types": "^0.1.0",
20
20
  "vscode-uri": "^3.0.8"
@@ -22,5 +22,5 @@
22
22
  "devDependencies": {
23
23
  "monaco-editor-core": "latest"
24
24
  },
25
- "gitHead": "dcd70c78b0b6901901dc0e68223e34dd922f5fdc"
25
+ "gitHead": "b1fbf6eed522624ccccfb17a8999edfbc1d8d9bb"
26
26
  }
package/worker.d.ts CHANGED
@@ -1,7 +1,15 @@
1
- import { LanguagePlugin, ServicePlugin } from '@volar/language-service';
1
+ import { LanguagePlugin, ServicePlugin, type ServiceEnvironment } from '@volar/language-service';
2
2
  import type * as monaco from 'monaco-types';
3
- import type * as ts from 'typescript/lib/tsserverlibrary.js';
4
- export declare function createSimpleWorkerService<T = {}>(languages: LanguagePlugin[], services: ServicePlugin[], getMirrorModels: monaco.worker.IWorkerContext<any>['getMirrorModels'], extraApis?: T): {
3
+ import type * as ts from 'typescript';
4
+ export * from '@volar/language-service';
5
+ export * from './lib/ata.js';
6
+ export declare function createSimpleWorkerService<T = {}>({ env, workerContext, languagePlugins, servicePlugins, extraApis }: {
7
+ env: ServiceEnvironment;
8
+ workerContext: monaco.worker.IWorkerContext<any>;
9
+ languagePlugins?: LanguagePlugin[];
10
+ servicePlugins?: ServicePlugin[];
11
+ extraApis?: T;
12
+ }): {
5
13
  getTriggerCharacters: () => string[];
6
14
  getAutoFormatTriggerCharacters: () => string[];
7
15
  getSignatureHelpTriggerCharacters: () => string[];
@@ -58,7 +66,15 @@ export declare function createSimpleWorkerService<T = {}>(languages: LanguagePlu
58
66
  dispose: () => void;
59
67
  context: import("@volar/language-service").ServiceContext;
60
68
  } & T;
61
- export declare function createTypeScriptWorkerService<T = {}>(ts: typeof import('typescript/lib/tsserverlibrary.js'), languages: LanguagePlugin[], services: ServicePlugin[], getMirrorModels: monaco.worker.IWorkerContext<any>['getMirrorModels'], compilerOptions: ts.CompilerOptions, extraApis?: T): {
69
+ export declare function createTypeScriptWorkerService<T = {}>({ typescript: ts, compilerOptions, env, workerContext, languagePlugins, servicePlugins, extraApis }: {
70
+ typescript: typeof import('typescript');
71
+ compilerOptions: ts.CompilerOptions;
72
+ env: ServiceEnvironment;
73
+ workerContext: monaco.worker.IWorkerContext<any>;
74
+ languagePlugins?: LanguagePlugin[];
75
+ servicePlugins?: ServicePlugin[];
76
+ extraApis?: T;
77
+ }): {
62
78
  getTriggerCharacters: () => string[];
63
79
  getAutoFormatTriggerCharacters: () => string[];
64
80
  getSignatureHelpTriggerCharacters: () => string[];
package/worker.js CHANGED
@@ -1,104 +1,88 @@
1
- import { createLanguageService as _createLanguageService, createFileProvider, resolveCommonLanguageId, } from '@volar/language-service';
2
- import { URI } from 'vscode-uri';
1
+ import { createLanguageService as _createLanguageService, createFileRegistry, resolveCommonLanguageId, } from '@volar/language-service';
3
2
  import { createLanguage, createSys } from '@volar/typescript';
4
- export function createSimpleWorkerService(languages, services, getMirrorModels, extraApis = {}) {
5
- return createWorkerService(services, env => {
6
- const snapshots = new Map();
7
- const files = createFileProvider(languages, false, fileName => {
8
- const uri = env.fileNameToUri(fileName);
9
- const model = getMirrorModels().find(model => model.uri.toString(true) === uri);
3
+ export * from '@volar/language-service';
4
+ export * from './lib/ata.js';
5
+ export function createSimpleWorkerService({ env, workerContext, languagePlugins = [], servicePlugins = [], extraApis = {} }) {
6
+ const snapshots = new Map();
7
+ const files = createFileRegistry(languagePlugins, false, uri => {
8
+ const model = workerContext.getMirrorModels().find(model => model.uri.toString() === uri);
9
+ if (model) {
10
+ const cache = snapshots.get(model);
11
+ if (cache && cache[0] === model.version) {
12
+ return;
13
+ }
14
+ const text = model.getValue();
15
+ const snapshot = {
16
+ getText: (start, end) => text.substring(start, end),
17
+ getLength: () => text.length,
18
+ getChangeRange: () => undefined,
19
+ };
20
+ snapshots.set(model, [model.version, snapshot]);
21
+ files.set(uri, resolveCommonLanguageId(uri), snapshot);
22
+ }
23
+ else {
24
+ files.delete(uri);
25
+ }
26
+ });
27
+ return createWorkerService({ files }, servicePlugins, env, extraApis);
28
+ }
29
+ export function createTypeScriptWorkerService({ typescript: ts, compilerOptions, env, workerContext, languagePlugins = [], servicePlugins = [], extraApis = {} }) {
30
+ let projectVersion = 0;
31
+ const modelSnapshot = new WeakMap();
32
+ const modelVersions = new Map();
33
+ const host = {
34
+ getCurrentDirectory() {
35
+ return env.typescript.uriToFileName(env.workspaceFolder);
36
+ },
37
+ getScriptFileNames() {
38
+ return workerContext.getMirrorModels().map(model => env.typescript.uriToFileName(model.uri.toString()));
39
+ },
40
+ getProjectVersion() {
41
+ const models = workerContext.getMirrorModels();
42
+ if (modelVersions.size === workerContext.getMirrorModels().length) {
43
+ if (models.every(model => modelVersions.get(model) === model.version)) {
44
+ return projectVersion.toString();
45
+ }
46
+ }
47
+ modelVersions.clear();
48
+ for (const model of workerContext.getMirrorModels()) {
49
+ modelVersions.set(model, model.version);
50
+ }
51
+ projectVersion++;
52
+ return projectVersion.toString();
53
+ },
54
+ getScriptSnapshot(fileName) {
55
+ const uri = env.typescript.fileNameToUri(fileName);
56
+ const model = workerContext.getMirrorModels().find(model => model.uri.toString() === uri);
10
57
  if (model) {
11
- const cache = snapshots.get(model);
58
+ const cache = modelSnapshot.get(model);
12
59
  if (cache && cache[0] === model.version) {
13
- return;
60
+ return cache[1];
14
61
  }
15
62
  const text = model.getValue();
16
- const snapshot = {
17
- getText: (start, end) => text.substring(start, end),
18
- getLength: () => text.length,
19
- getChangeRange: () => undefined,
20
- };
21
- snapshots.set(model, [model.version, snapshot]);
22
- files.updateSourceFile(fileName, resolveCommonLanguageId(fileName), snapshot);
63
+ modelSnapshot.set(model, [model.version, {
64
+ getText: (start, end) => text.substring(start, end),
65
+ getLength: () => text.length,
66
+ getChangeRange: () => undefined,
67
+ }]);
68
+ return modelSnapshot.get(model)?.[1];
23
69
  }
24
- else {
25
- files.deleteSourceFile(fileName);
26
- }
27
- });
28
- return { files };
29
- }, extraApis);
30
- }
31
- export function createTypeScriptWorkerService(ts, languages, services, getMirrorModels, compilerOptions, extraApis = {}) {
32
- return createWorkerService(services, env => {
33
- let projectVersion = 0;
34
- const modelSnapshot = new WeakMap();
35
- const modelVersions = new Map();
36
- const host = {
37
- getCurrentDirectory() {
38
- return env.uriToFileName(env.workspaceFolder.uri.toString(true));
39
- },
40
- getProjectVersion() {
41
- const models = getMirrorModels();
42
- if (modelVersions.size === getMirrorModels().length) {
43
- if (models.every(model => modelVersions.get(model) === model.version)) {
44
- return projectVersion.toString();
45
- }
46
- }
47
- modelVersions.clear();
48
- for (const model of getMirrorModels()) {
49
- modelVersions.set(model, model.version);
50
- }
51
- projectVersion++;
52
- return projectVersion.toString();
53
- },
54
- getScriptFileNames() {
55
- const models = getMirrorModels();
56
- return models.map(model => env.uriToFileName(model.uri.toString(true)));
57
- },
58
- getScriptSnapshot(fileName) {
59
- const uri = env.fileNameToUri(fileName);
60
- const model = getMirrorModels().find(model => model.uri.toString(true) === uri);
61
- if (model) {
62
- const cache = modelSnapshot.get(model);
63
- if (cache && cache[0] === model.version) {
64
- return cache[1];
65
- }
66
- const text = model.getValue();
67
- modelSnapshot.set(model, [model.version, {
68
- getText: (start, end) => text.substring(start, end),
69
- getLength: () => text.length,
70
- getChangeRange: () => undefined,
71
- }]);
72
- return modelSnapshot.get(model)?.[1];
73
- }
74
- },
75
- getCompilationSettings() {
76
- return compilerOptions;
77
- },
78
- getLanguageId: id => resolveCommonLanguageId(id),
79
- };
80
- const sys = createSys(ts, env, host.getCurrentDirectory());
81
- const language = createLanguage(ts, sys, languages, undefined, host);
82
- return language;
83
- }, extraApis);
84
- }
85
- function createWorkerService(services, getLanguage, extraApis = {}) {
86
- const env = {
87
- workspaceFolder: {
88
- uri: URI.file('/'),
89
- name: '',
90
70
  },
91
- uriToFileName: uri => URI.parse(uri).fsPath.replace(/\\/g, '/'),
92
- fileNameToUri: fileName => URI.file(fileName).toString(),
93
- console,
71
+ getCompilationSettings() {
72
+ return compilerOptions;
73
+ },
74
+ getLanguageId: id => resolveCommonLanguageId(id),
94
75
  };
95
- const language = getLanguage(env);
96
- const languageService = _createLanguageService(language, services, env);
76
+ const sys = createSys(ts, env, host);
77
+ const languageContext = createLanguage(ts, sys, languagePlugins, undefined, host, {
78
+ fileNameToFileId: env.typescript.fileNameToUri,
79
+ fileIdToFileName: env.typescript.uriToFileName,
80
+ });
81
+ return createWorkerService(languageContext, servicePlugins, env, extraApis);
82
+ }
83
+ function createWorkerService(languageContext, servicePlugins, env, extraApis = {}) {
84
+ const languageService = _createLanguageService(languageContext, servicePlugins, env);
97
85
  class WorkerService {
98
- constructor() {
99
- this.env = env;
100
- this.project = language;
101
- }
102
86
  }
103
87
  ;
104
88
  for (const api in languageService) {