@gi-tcg/gts-language-server 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,5 +3,5 @@ if (process.argv.includes("--version")) {
3
3
  const pkgJSON = await import("../package.json");
4
4
  console.log(`${pkgJSON["version"]}`);
5
5
  } else {
6
- await import("../dist/index.js");
6
+ await import("../dist/node/node.js");
7
7
  }
@@ -0,0 +1,9 @@
1
+ import { GtsConfig } from "@gi-tcg/gts-transpiler";
2
+ import ts from "typescript";
3
+ interface GtsLanguageServerBrowserInitializationOptions {
4
+ tsdkUrl?: string;
5
+ inlineGtsConfig?: GtsConfig;
6
+ inlineCompilerOptions?: ts.CompilerOptions;
7
+ fs?: Record<string, string>;
8
+ }
9
+ export { GtsLanguageServerBrowserInitializationOptions };
@@ -0,0 +1,320 @@
1
+ // packages/language-server/src/browser.ts
2
+ import {
3
+ createConnection,
4
+ createServer,
5
+ createTypeScriptProject,
6
+ loadTsdkByUrl
7
+ } from "@volar/language-server/browser.js";
8
+ import { createGtsLanguagePlugin } from "@gi-tcg/gts-language-plugin";
9
+ import { path } from "@gi-tcg/gts-transpiler";
10
+
11
+ // packages/language-server/src/diagnostics.ts
12
+ import {
13
+ DiagnosticSeverity
14
+ } from "@volar/language-server";
15
+
16
+ // packages/language-server/src/utils.ts
17
+ import { URI } from "vscode-uri";
18
+ import { GtsVirtualCode } from "@gi-tcg/gts-language-plugin";
19
+ function getVirtualCode(document, context) {
20
+ const uri = URI.parse(document.uri);
21
+ const decoded = context.decodeEmbeddedDocumentUri(uri);
22
+ const [sourceUri, virtualCodeId] = decoded;
23
+ const sourceScript = context.language.scripts.get(sourceUri);
24
+ const virtualCode = sourceScript?.generated?.embeddedCodes.get(virtualCodeId);
25
+ if (!virtualCode) {
26
+ return [null, sourceUri];
27
+ }
28
+ if (!(virtualCode instanceof GtsVirtualCode)) {
29
+ return [null, sourceUri];
30
+ }
31
+ return [virtualCode, sourceUri];
32
+ }
33
+
34
+ // packages/language-server/src/diagnostics.ts
35
+ var createDiagnosticsPlugin = () => {
36
+ return {
37
+ name: "gts-diagnostics",
38
+ capabilities: {
39
+ diagnosticProvider: {
40
+ interFileDependencies: false,
41
+ workspaceDiagnostics: false
42
+ }
43
+ },
44
+ create: (context) => {
45
+ return {
46
+ provideDiagnostics: (document) => {
47
+ try {
48
+ const [virtualCode] = getVirtualCode(document, context);
49
+ if (!virtualCode) {
50
+ return;
51
+ }
52
+ return virtualCode.errors.map((err) => {
53
+ const loc = err.position ?? {
54
+ start: { line: 1, column: 0 },
55
+ end: { line: 1, column: 1 }
56
+ };
57
+ const range = {
58
+ start: {
59
+ line: loc.start.line - 1,
60
+ character: loc.start.column
61
+ },
62
+ end: { line: loc.end.line - 1, character: loc.end.column }
63
+ };
64
+ return {
65
+ severity: DiagnosticSeverity.Error,
66
+ range,
67
+ message: err.message,
68
+ source: "gts-transpiler",
69
+ code: "gts-transpiler-error"
70
+ };
71
+ });
72
+ } catch (e) {
73
+ console.error(e);
74
+ return;
75
+ }
76
+ }
77
+ };
78
+ }
79
+ };
80
+ };
81
+
82
+ // packages/language-server/src/typescript.ts
83
+ import { create } from "volar-service-typescript";
84
+ function createTypeScriptServices(ts) {
85
+ const services = create(ts);
86
+ const semanticService = services.find((service) => service.name === "typescript-semantic");
87
+ if (semanticService?.capabilities.signatureHelpProvider?.triggerCharacters) {
88
+ semanticService.capabilities.signatureHelpProvider.triggerCharacters.push(" ");
89
+ }
90
+ return services;
91
+ }
92
+
93
+ // packages/language-server/src/completion.ts
94
+ var createCompletionPlugin = () => {
95
+ return {
96
+ name: "gts-completion",
97
+ capabilities: {
98
+ completionProvider: {
99
+ triggerCharacters: [":"]
100
+ }
101
+ },
102
+ create: (context) => {
103
+ let originalProvideCompletionItems;
104
+ for (const [plugin, instance] of context.plugins) {
105
+ if (plugin.name === "typescript-semantic") {
106
+ originalProvideCompletionItems = instance.provideCompletionItems;
107
+ }
108
+ }
109
+ if (!originalProvideCompletionItems) {
110
+ console.warn(`TS's original provideCompletionItems not found`);
111
+ return {};
112
+ }
113
+ return {
114
+ provideCompletionItems: async (document, position, context2, token) => {
115
+ if (context2.triggerCharacter === ":") {
116
+ context2.triggerCharacter = ".";
117
+ const response = await originalProvideCompletionItems(document, position, context2, token);
118
+ return response;
119
+ }
120
+ return null;
121
+ }
122
+ };
123
+ }
124
+ };
125
+ };
126
+
127
+ // packages/language-server/src/browser.ts
128
+ import { fs as memfs } from "@zenfs/core";
129
+
130
+ // packages/language-server/src/zen_fs_provider.ts
131
+ function zenFsProvider(fs) {
132
+ return {
133
+ stat(uri) {
134
+ try {
135
+ const stats = fs.statSync(uri.path);
136
+ console.log("stat", uri.path, stats);
137
+ return {
138
+ type: stats.isFile() ? 1 : stats.isDirectory() ? 2 : stats.isSymbolicLink() ? 64 : 0,
139
+ ctime: stats.ctimeMs,
140
+ mtime: stats.mtimeMs,
141
+ size: stats.size
142
+ };
143
+ } catch {
144
+ return;
145
+ }
146
+ },
147
+ readFile(uri, encoding) {
148
+ try {
149
+ console.log("readFile", uri.path);
150
+ return fs.readFileSync(uri.path, {
151
+ encoding: encoding ?? "utf-8"
152
+ });
153
+ } catch {
154
+ return;
155
+ }
156
+ },
157
+ readDirectory(uri) {
158
+ try {
159
+ const files = fs.readdirSync(uri.path, { withFileTypes: true });
160
+ console.log("readDirectory", uri.path, files.map((f) => f.name));
161
+ return files.map((file) => {
162
+ return [
163
+ file.name,
164
+ file.isFile() ? 1 : file.isDirectory() ? 2 : file.isSymbolicLink() ? 64 : 0
165
+ ];
166
+ });
167
+ } catch {
168
+ return [];
169
+ }
170
+ }
171
+ };
172
+ }
173
+
174
+ // packages/language-server/src/browser.ts
175
+ var connection = createConnection();
176
+ var server = createServer(connection);
177
+ server.fileSystem.install("file", zenFsProvider(memfs));
178
+ connection.listen();
179
+ connection.onInitialize(async (params) => {
180
+ const {
181
+ tsdkUrl = "https://cdn.jsdelivr.net/npm/typescript@latest/lib",
182
+ fs = {},
183
+ inlineGtsConfig = {},
184
+ inlineCompilerOptions = {}
185
+ } = params.initializationOptions ?? {};
186
+ const tsdk = await loadTsdkByUrl(tsdkUrl, params.locale);
187
+ await loadLibs(tsdkUrl);
188
+ for (const [filepath, content] of Object.entries(fs)) {
189
+ memfs.mkdirSync(path.dirname(filepath), { recursive: true });
190
+ memfs.writeFileSync(filepath, content);
191
+ }
192
+ return server.initialize(params, createTypeScriptProject(tsdk.typescript, tsdk.diagnosticMessages, ({ env }) => {
193
+ return {
194
+ languagePlugins: [
195
+ createGtsLanguagePlugin(tsdk.typescript, inlineGtsConfig)
196
+ ]
197
+ };
198
+ }), [
199
+ ...createTypeScriptServices(tsdk.typescript),
200
+ createDiagnosticsPlugin(),
201
+ createCompletionPlugin()
202
+ ]);
203
+ });
204
+ connection.onInitialized(server.initialized);
205
+ connection.onShutdown(server.shutdown);
206
+ self.addEventListener("error", (event) => {
207
+ console.error("Uncaught exception:", event.error);
208
+ });
209
+ self.addEventListener("unhandledrejection", (event) => {
210
+ console.error("Unhandled rejection at:", event.promise, "reason:", event.reason);
211
+ });
212
+ async function loadLibs(tsdkUrl) {
213
+ memfs.mkdirSync("/node_modules/typescript/lib", { recursive: true });
214
+ const libs = await Promise.all(ALL_LIBS.map((lib) => fetch(`${tsdkUrl}/${lib}`).then((res) => res.text()).then((content) => [lib, content])));
215
+ for (const [lib, content] of libs) {
216
+ memfs.writeFileSync(`/node_modules/typescript/lib/${lib}`, content);
217
+ }
218
+ }
219
+ var ALL_LIBS = [
220
+ "lib.d.ts",
221
+ "lib.decorators.d.ts",
222
+ "lib.decorators.legacy.d.ts",
223
+ "lib.dom.asynciterable.d.ts",
224
+ "lib.dom.d.ts",
225
+ "lib.dom.iterable.d.ts",
226
+ "lib.es2015.collection.d.ts",
227
+ "lib.es2015.core.d.ts",
228
+ "lib.es2015.d.ts",
229
+ "lib.es2015.generator.d.ts",
230
+ "lib.es2015.iterable.d.ts",
231
+ "lib.es2015.promise.d.ts",
232
+ "lib.es2015.proxy.d.ts",
233
+ "lib.es2015.reflect.d.ts",
234
+ "lib.es2015.symbol.d.ts",
235
+ "lib.es2015.symbol.wellknown.d.ts",
236
+ "lib.es2016.array.include.d.ts",
237
+ "lib.es2016.d.ts",
238
+ "lib.es2016.full.d.ts",
239
+ "lib.es2016.intl.d.ts",
240
+ "lib.es2017.arraybuffer.d.ts",
241
+ "lib.es2017.d.ts",
242
+ "lib.es2017.date.d.ts",
243
+ "lib.es2017.full.d.ts",
244
+ "lib.es2017.intl.d.ts",
245
+ "lib.es2017.object.d.ts",
246
+ "lib.es2017.sharedmemory.d.ts",
247
+ "lib.es2017.string.d.ts",
248
+ "lib.es2017.typedarrays.d.ts",
249
+ "lib.es2018.asyncgenerator.d.ts",
250
+ "lib.es2018.asynciterable.d.ts",
251
+ "lib.es2018.d.ts",
252
+ "lib.es2018.full.d.ts",
253
+ "lib.es2018.intl.d.ts",
254
+ "lib.es2018.promise.d.ts",
255
+ "lib.es2018.regexp.d.ts",
256
+ "lib.es2019.array.d.ts",
257
+ "lib.es2019.d.ts",
258
+ "lib.es2019.full.d.ts",
259
+ "lib.es2019.intl.d.ts",
260
+ "lib.es2019.object.d.ts",
261
+ "lib.es2019.string.d.ts",
262
+ "lib.es2019.symbol.d.ts",
263
+ "lib.es2020.bigint.d.ts",
264
+ "lib.es2020.d.ts",
265
+ "lib.es2020.date.d.ts",
266
+ "lib.es2020.full.d.ts",
267
+ "lib.es2020.intl.d.ts",
268
+ "lib.es2020.number.d.ts",
269
+ "lib.es2020.promise.d.ts",
270
+ "lib.es2020.sharedmemory.d.ts",
271
+ "lib.es2020.string.d.ts",
272
+ "lib.es2020.symbol.wellknown.d.ts",
273
+ "lib.es2021.d.ts",
274
+ "lib.es2021.full.d.ts",
275
+ "lib.es2021.intl.d.ts",
276
+ "lib.es2021.promise.d.ts",
277
+ "lib.es2021.string.d.ts",
278
+ "lib.es2021.weakref.d.ts",
279
+ "lib.es2022.array.d.ts",
280
+ "lib.es2022.d.ts",
281
+ "lib.es2022.error.d.ts",
282
+ "lib.es2022.full.d.ts",
283
+ "lib.es2022.intl.d.ts",
284
+ "lib.es2022.object.d.ts",
285
+ "lib.es2022.regexp.d.ts",
286
+ "lib.es2022.string.d.ts",
287
+ "lib.es2023.array.d.ts",
288
+ "lib.es2023.collection.d.ts",
289
+ "lib.es2023.d.ts",
290
+ "lib.es2023.full.d.ts",
291
+ "lib.es2023.intl.d.ts",
292
+ "lib.es2024.arraybuffer.d.ts",
293
+ "lib.es2024.collection.d.ts",
294
+ "lib.es2024.d.ts",
295
+ "lib.es2024.full.d.ts",
296
+ "lib.es2024.object.d.ts",
297
+ "lib.es2024.promise.d.ts",
298
+ "lib.es2024.regexp.d.ts",
299
+ "lib.es2024.sharedmemory.d.ts",
300
+ "lib.es2024.string.d.ts",
301
+ "lib.es5.d.ts",
302
+ "lib.es6.d.ts",
303
+ "lib.esnext.array.d.ts",
304
+ "lib.esnext.collection.d.ts",
305
+ "lib.esnext.d.ts",
306
+ "lib.esnext.decorators.d.ts",
307
+ "lib.esnext.disposable.d.ts",
308
+ "lib.esnext.error.d.ts",
309
+ "lib.esnext.float16.d.ts",
310
+ "lib.esnext.full.d.ts",
311
+ "lib.esnext.intl.d.ts",
312
+ "lib.esnext.iterator.d.ts",
313
+ "lib.esnext.promise.d.ts",
314
+ "lib.esnext.sharedmemory.d.ts",
315
+ "lib.scripthost.d.ts",
316
+ "lib.webworker.asynciterable.d.ts",
317
+ "lib.webworker.d.ts",
318
+ "lib.webworker.importscripts.d.ts",
319
+ "lib.webworker.iterable.d.ts"
320
+ ];
@@ -1,11 +1,10 @@
1
- // packages/language-server/src/index.ts
1
+ // packages/language-server/src/node.ts
2
2
  import {
3
3
  createConnection,
4
4
  createServer,
5
5
  createTypeScriptProject,
6
6
  loadTsdkByPath
7
7
  } from "@volar/language-server/node.js";
8
- import { create as createTypeScriptServices } from "volar-service-typescript";
9
8
  import { createGtsLanguagePlugin } from "@gi-tcg/gts-language-plugin";
10
9
 
11
10
  // packages/language-server/src/diagnostics.ts
@@ -45,9 +44,7 @@ var createDiagnosticsPlugin = () => {
45
44
  return {
46
45
  provideDiagnostics: (document) => {
47
46
  try {
48
- console.log(document.uri);
49
47
  const [virtualCode] = getVirtualCode(document, context);
50
- console.log(document.uri, virtualCode);
51
48
  if (!virtualCode) {
52
49
  return;
53
50
  }
@@ -63,7 +60,6 @@ var createDiagnosticsPlugin = () => {
63
60
  },
64
61
  end: { line: loc.end.line - 1, character: loc.end.column }
65
62
  };
66
- console.log(range);
67
63
  return {
68
64
  severity: DiagnosticSeverity.Error,
69
65
  range,
@@ -82,7 +78,52 @@ var createDiagnosticsPlugin = () => {
82
78
  };
83
79
  };
84
80
 
85
- // packages/language-server/src/index.ts
81
+ // packages/language-server/src/typescript.ts
82
+ import { create } from "volar-service-typescript";
83
+ function createTypeScriptServices(ts) {
84
+ const services = create(ts);
85
+ const semanticService = services.find((service) => service.name === "typescript-semantic");
86
+ if (semanticService?.capabilities.signatureHelpProvider?.triggerCharacters) {
87
+ semanticService.capabilities.signatureHelpProvider.triggerCharacters.push(" ");
88
+ }
89
+ return services;
90
+ }
91
+
92
+ // packages/language-server/src/completion.ts
93
+ var createCompletionPlugin = () => {
94
+ return {
95
+ name: "gts-completion",
96
+ capabilities: {
97
+ completionProvider: {
98
+ triggerCharacters: [":"]
99
+ }
100
+ },
101
+ create: (context) => {
102
+ let originalProvideCompletionItems;
103
+ for (const [plugin, instance] of context.plugins) {
104
+ if (plugin.name === "typescript-semantic") {
105
+ originalProvideCompletionItems = instance.provideCompletionItems;
106
+ }
107
+ }
108
+ if (!originalProvideCompletionItems) {
109
+ console.warn(`TS's original provideCompletionItems not found`);
110
+ return {};
111
+ }
112
+ return {
113
+ provideCompletionItems: async (document, position, context2, token) => {
114
+ if (context2.triggerCharacter === ":") {
115
+ context2.triggerCharacter = ".";
116
+ const response = await originalProvideCompletionItems(document, position, context2, token);
117
+ return response;
118
+ }
119
+ return null;
120
+ }
121
+ };
122
+ }
123
+ };
124
+ };
125
+
126
+ // packages/language-server/src/node.ts
86
127
  var connection = createConnection();
87
128
  var server = createServer(connection);
88
129
  connection.listen();
@@ -92,7 +133,11 @@ connection.onInitialize((params) => {
92
133
  return {
93
134
  languagePlugins: [createGtsLanguagePlugin(tsdk.typescript)]
94
135
  };
95
- }), [...createTypeScriptServices(tsdk.typescript), createDiagnosticsPlugin()]);
136
+ }), [
137
+ ...createTypeScriptServices(tsdk.typescript),
138
+ createDiagnosticsPlugin(),
139
+ createCompletionPlugin()
140
+ ]);
96
141
  });
97
142
  connection.onInitialized(server.initialized);
98
143
  connection.onShutdown(server.shutdown);
package/package.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "name": "@gi-tcg/gts-language-server",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "repository": "https://github.com/piovium/gts.git",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
- "main": "dist/index.js",
8
7
  "exports": {
9
- ".": {
10
- "bun": "./src/index.ts",
11
- "default": "./dist/index.js"
8
+ "./node": {
9
+ "bun": "./src/node.ts",
10
+ "default": "./dist/node/node.js"
11
+ },
12
+ "./browser": {
13
+ "bun": "./src/browser.ts",
14
+ "default": "./dist/browser/browser.js"
12
15
  }
13
16
  },
14
17
  "bin": {
@@ -21,9 +24,10 @@
21
24
  ],
22
25
  "scripts": {},
23
26
  "dependencies": {
24
- "@gi-tcg/gts-transpiler": "0.2.0",
25
- "@gi-tcg/gts-language-plugin": "0.2.0",
27
+ "@gi-tcg/gts-language-plugin": "0.3.0",
28
+ "@gi-tcg/gts-transpiler": "0.3.0",
26
29
  "@volar/language-server": "~2.4.0",
30
+ "@zenfs/core": "^2.5.0",
27
31
  "volar-service-typescript": "volar-2.4",
28
32
  "vscode-uri": "^3.0.8"
29
33
  },
package/src/browser.ts ADDED
@@ -0,0 +1,206 @@
1
+ /// <reference lib="webworker" />
2
+ import {
3
+ createConnection,
4
+ createServer,
5
+ createTypeScriptProject,
6
+ Diagnostic,
7
+ FileType,
8
+ loadTsdkByUrl,
9
+ type InitializeParams,
10
+ } from "@volar/language-server/browser.js";
11
+ import { createGtsLanguagePlugin } from "@gi-tcg/gts-language-plugin";
12
+ import { path, type GtsConfig } from "@gi-tcg/gts-transpiler";
13
+ import { createDiagnosticsPlugin } from "./diagnostics";
14
+ import { createTypeScriptServices } from "./typescript";
15
+ import { createCompletionPlugin } from "./completion";
16
+ import { Dirent, fs as memfs } from "@zenfs/core";
17
+ import ts from "typescript";
18
+ import zenFsProvider from "./zen_fs_provider";
19
+
20
+ export interface GtsLanguageServerBrowserInitializationOptions {
21
+ tsdkUrl?: string;
22
+ inlineGtsConfig?: GtsConfig;
23
+ inlineCompilerOptions?: ts.CompilerOptions;
24
+ fs?: Record<string, string>;
25
+ }
26
+
27
+ const connection = createConnection();
28
+ const server = createServer(connection);
29
+
30
+ server.fileSystem.install("file", zenFsProvider(memfs));
31
+
32
+ connection.listen();
33
+
34
+ type AnyTuple = [unknown, ...unknown[]];
35
+
36
+ connection.onInitialize(
37
+ async (
38
+ params: Omit<InitializeParams, "initializationOptions"> & {
39
+ initializationOptions?: GtsLanguageServerBrowserInitializationOptions;
40
+ },
41
+ ) => {
42
+ const {
43
+ tsdkUrl = "https://cdn.jsdelivr.net/npm/typescript@latest/lib",
44
+ fs = {},
45
+ inlineGtsConfig = {},
46
+ inlineCompilerOptions = {},
47
+ } = params.initializationOptions ?? {};
48
+ const tsdk = await loadTsdkByUrl(tsdkUrl, params.locale);
49
+ await loadLibs(tsdkUrl);
50
+ for (const [filepath, content] of Object.entries(fs)) {
51
+ memfs.mkdirSync(path.dirname(filepath), { recursive: true });
52
+ memfs.writeFileSync(filepath, content);
53
+ }
54
+ return server.initialize(
55
+ params,
56
+ createTypeScriptProject(
57
+ tsdk.typescript,
58
+ tsdk.diagnosticMessages,
59
+ ({ env }) => {
60
+ return {
61
+ languagePlugins: [
62
+ createGtsLanguagePlugin(tsdk.typescript, inlineGtsConfig),
63
+ ],
64
+ };
65
+ },
66
+ ),
67
+ [
68
+ ...createTypeScriptServices(tsdk.typescript),
69
+ createDiagnosticsPlugin(),
70
+ createCompletionPlugin(),
71
+ ],
72
+ );
73
+ },
74
+ );
75
+
76
+ connection.onInitialized(server.initialized);
77
+
78
+ connection.onShutdown(server.shutdown);
79
+
80
+ self.addEventListener("error", (event) => {
81
+ console.error("Uncaught exception:", event.error);
82
+ });
83
+
84
+ self.addEventListener("unhandledrejection", (event) => {
85
+ console.error(
86
+ "Unhandled rejection at:",
87
+ event.promise,
88
+ "reason:",
89
+ event.reason,
90
+ );
91
+ });
92
+
93
+ async function loadLibs(tsdkUrl: string) {
94
+ memfs.mkdirSync("/node_modules/typescript/lib", { recursive: true });
95
+ const libs = await Promise.all(
96
+ ALL_LIBS.map((lib) =>
97
+ fetch(`${tsdkUrl}/${lib}`).then((res) => res.text()).then((content) => [lib, content] as const),
98
+ ),
99
+ );
100
+ for (const [lib, content] of libs) {
101
+ memfs.writeFileSync(`/node_modules/typescript/lib/${lib}`, content);
102
+ }
103
+ }
104
+
105
+ const ALL_LIBS = [
106
+ "lib.d.ts",
107
+ "lib.decorators.d.ts",
108
+ "lib.decorators.legacy.d.ts",
109
+ "lib.dom.asynciterable.d.ts",
110
+ "lib.dom.d.ts",
111
+ "lib.dom.iterable.d.ts",
112
+ "lib.es2015.collection.d.ts",
113
+ "lib.es2015.core.d.ts",
114
+ "lib.es2015.d.ts",
115
+ "lib.es2015.generator.d.ts",
116
+ "lib.es2015.iterable.d.ts",
117
+ "lib.es2015.promise.d.ts",
118
+ "lib.es2015.proxy.d.ts",
119
+ "lib.es2015.reflect.d.ts",
120
+ "lib.es2015.symbol.d.ts",
121
+ "lib.es2015.symbol.wellknown.d.ts",
122
+ "lib.es2016.array.include.d.ts",
123
+ "lib.es2016.d.ts",
124
+ "lib.es2016.full.d.ts",
125
+ "lib.es2016.intl.d.ts",
126
+ "lib.es2017.arraybuffer.d.ts",
127
+ "lib.es2017.d.ts",
128
+ "lib.es2017.date.d.ts",
129
+ "lib.es2017.full.d.ts",
130
+ "lib.es2017.intl.d.ts",
131
+ "lib.es2017.object.d.ts",
132
+ "lib.es2017.sharedmemory.d.ts",
133
+ "lib.es2017.string.d.ts",
134
+ "lib.es2017.typedarrays.d.ts",
135
+ "lib.es2018.asyncgenerator.d.ts",
136
+ "lib.es2018.asynciterable.d.ts",
137
+ "lib.es2018.d.ts",
138
+ "lib.es2018.full.d.ts",
139
+ "lib.es2018.intl.d.ts",
140
+ "lib.es2018.promise.d.ts",
141
+ "lib.es2018.regexp.d.ts",
142
+ "lib.es2019.array.d.ts",
143
+ "lib.es2019.d.ts",
144
+ "lib.es2019.full.d.ts",
145
+ "lib.es2019.intl.d.ts",
146
+ "lib.es2019.object.d.ts",
147
+ "lib.es2019.string.d.ts",
148
+ "lib.es2019.symbol.d.ts",
149
+ "lib.es2020.bigint.d.ts",
150
+ "lib.es2020.d.ts",
151
+ "lib.es2020.date.d.ts",
152
+ "lib.es2020.full.d.ts",
153
+ "lib.es2020.intl.d.ts",
154
+ "lib.es2020.number.d.ts",
155
+ "lib.es2020.promise.d.ts",
156
+ "lib.es2020.sharedmemory.d.ts",
157
+ "lib.es2020.string.d.ts",
158
+ "lib.es2020.symbol.wellknown.d.ts",
159
+ "lib.es2021.d.ts",
160
+ "lib.es2021.full.d.ts",
161
+ "lib.es2021.intl.d.ts",
162
+ "lib.es2021.promise.d.ts",
163
+ "lib.es2021.string.d.ts",
164
+ "lib.es2021.weakref.d.ts",
165
+ "lib.es2022.array.d.ts",
166
+ "lib.es2022.d.ts",
167
+ "lib.es2022.error.d.ts",
168
+ "lib.es2022.full.d.ts",
169
+ "lib.es2022.intl.d.ts",
170
+ "lib.es2022.object.d.ts",
171
+ "lib.es2022.regexp.d.ts",
172
+ "lib.es2022.string.d.ts",
173
+ "lib.es2023.array.d.ts",
174
+ "lib.es2023.collection.d.ts",
175
+ "lib.es2023.d.ts",
176
+ "lib.es2023.full.d.ts",
177
+ "lib.es2023.intl.d.ts",
178
+ "lib.es2024.arraybuffer.d.ts",
179
+ "lib.es2024.collection.d.ts",
180
+ "lib.es2024.d.ts",
181
+ "lib.es2024.full.d.ts",
182
+ "lib.es2024.object.d.ts",
183
+ "lib.es2024.promise.d.ts",
184
+ "lib.es2024.regexp.d.ts",
185
+ "lib.es2024.sharedmemory.d.ts",
186
+ "lib.es2024.string.d.ts",
187
+ "lib.es5.d.ts",
188
+ "lib.es6.d.ts",
189
+ "lib.esnext.array.d.ts",
190
+ "lib.esnext.collection.d.ts",
191
+ "lib.esnext.d.ts",
192
+ "lib.esnext.decorators.d.ts",
193
+ "lib.esnext.disposable.d.ts",
194
+ "lib.esnext.error.d.ts",
195
+ "lib.esnext.float16.d.ts",
196
+ "lib.esnext.full.d.ts",
197
+ "lib.esnext.intl.d.ts",
198
+ "lib.esnext.iterator.d.ts",
199
+ "lib.esnext.promise.d.ts",
200
+ "lib.esnext.sharedmemory.d.ts",
201
+ "lib.scripthost.d.ts",
202
+ "lib.webworker.asynciterable.d.ts",
203
+ "lib.webworker.d.ts",
204
+ "lib.webworker.importscripts.d.ts",
205
+ "lib.webworker.iterable.d.ts",
206
+ ];
@@ -0,0 +1,46 @@
1
+ import {
2
+ type LanguageServicePlugin,
3
+ type LanguageServicePluginInstance,
4
+ } from "@volar/language-server";
5
+
6
+ // Lets extend TS's completion provider to support `:`-auto-completion
7
+
8
+ export const createCompletionPlugin = (): LanguageServicePlugin => {
9
+ return {
10
+ name: "gts-completion",
11
+ capabilities: {
12
+ completionProvider: {
13
+ triggerCharacters: [":"],
14
+ },
15
+ },
16
+ create: (context) => {
17
+ let originalProvideCompletionItems: LanguageServicePluginInstance["provideCompletionItems"];
18
+
19
+ for (const [plugin, instance] of context.plugins) {
20
+ if (plugin.name === "typescript-semantic") {
21
+ originalProvideCompletionItems = instance.provideCompletionItems;
22
+ }
23
+ }
24
+
25
+ if (!originalProvideCompletionItems) {
26
+ console.warn(`TS's original provideCompletionItems not found`);
27
+ return {};
28
+ }
29
+ return {
30
+ provideCompletionItems: async (document, position, context, token) => {
31
+ if (context.triggerCharacter === ":") {
32
+ context.triggerCharacter = ".";
33
+ const response = await originalProvideCompletionItems(
34
+ document,
35
+ position,
36
+ context,
37
+ token,
38
+ );
39
+ return response;
40
+ }
41
+ return null;
42
+ },
43
+ };
44
+ },
45
+ };
46
+ };
@@ -17,9 +17,7 @@ export const createDiagnosticsPlugin = (): LanguageServicePlugin => {
17
17
  return {
18
18
  provideDiagnostics: (document) => {
19
19
  try {
20
- console.log(document.uri);
21
20
  const [virtualCode] = getVirtualCode(document, context);
22
- console.log(document.uri, virtualCode);
23
21
  if (!virtualCode) {
24
22
  return;
25
23
  }
@@ -35,7 +33,6 @@ export const createDiagnosticsPlugin = (): LanguageServicePlugin => {
35
33
  },
36
34
  end: { line: loc.end.line - 1, character: loc.end.column },
37
35
  };
38
- console.log(range);
39
36
  return {
40
37
  severity: DiagnosticSeverity.Error,
41
38
  range,
@@ -4,7 +4,7 @@ import type {
4
4
  } from "@volar/language-server";
5
5
  import { getVirtualCode, getWordFromPosition } from "./utils";
6
6
 
7
- export function createDocumentHighlightPlugin(): LanguageServicePlugin {
7
+ export function createDocumentHighlightService(): LanguageServicePlugin {
8
8
  return {
9
9
  name: "gts-document-highlight",
10
10
  capabilities: {
@@ -5,9 +5,10 @@ import {
5
5
  Diagnostic,
6
6
  loadTsdkByPath,
7
7
  } from "@volar/language-server/node.js";
8
- import { create as createTypeScriptServices } from "volar-service-typescript";
9
8
  import { createGtsLanguagePlugin } from "@gi-tcg/gts-language-plugin";
10
9
  import { createDiagnosticsPlugin } from "./diagnostics";
10
+ import { createTypeScriptServices } from "./typescript";
11
+ import { createCompletionPlugin } from "./completion";
11
12
 
12
13
  const connection = createConnection();
13
14
  const server = createServer(connection);
@@ -21,16 +22,16 @@ connection.onInitialize((params) => {
21
22
  );
22
23
  return server.initialize(
23
24
  params,
24
- createTypeScriptProject(
25
- tsdk.typescript,
26
- tsdk.diagnosticMessages,
27
- () => {
28
- return {
29
- languagePlugins: [createGtsLanguagePlugin(tsdk.typescript)],
30
- };
31
- },
32
- ),
33
- [...createTypeScriptServices(tsdk.typescript), createDiagnosticsPlugin()],
25
+ createTypeScriptProject(tsdk.typescript, tsdk.diagnosticMessages, () => {
26
+ return {
27
+ languagePlugins: [createGtsLanguagePlugin(tsdk.typescript)],
28
+ };
29
+ }),
30
+ [
31
+ ...createTypeScriptServices(tsdk.typescript),
32
+ createDiagnosticsPlugin(),
33
+ createCompletionPlugin(),
34
+ ],
34
35
  );
35
36
  });
36
37
 
@@ -0,0 +1,20 @@
1
+ import { create } from "volar-service-typescript";
2
+ import type { LanguageServicePlugin } from "@volar/language-server";
3
+
4
+ export function createTypeScriptServices(
5
+ ts: typeof import("typescript"),
6
+ ): LanguageServicePlugin[] {
7
+ const services = create(ts);
8
+ const semanticService = services.find(
9
+ (service) => service.name === "typescript-semantic",
10
+ );
11
+ // make space triggers signature help too.
12
+ // GTS have syntax `name arg1, arg2` transpiled to `name(arg1, arg2)`
13
+ // the space after `name` will trigger a request for signature help
14
+ if (semanticService?.capabilities.signatureHelpProvider?.triggerCharacters) {
15
+ semanticService.capabilities.signatureHelpProvider.triggerCharacters.push(
16
+ " ",
17
+ );
18
+ }
19
+ return services;
20
+ }
@@ -0,0 +1,58 @@
1
+ import type { FileSystem, FileType } from "@volar/language-service";
2
+
3
+ export default function zenFsProvider(
4
+ fs: typeof import("@zenfs/core").fs,
5
+ ): FileSystem {
6
+ return {
7
+ stat(uri) {
8
+ try {
9
+ const stats = fs.statSync(uri.path);
10
+ console.log("stat", uri.path, stats);
11
+ return {
12
+ type: stats.isFile()
13
+ ? (1 satisfies FileType.File)
14
+ : stats.isDirectory()
15
+ ? (2 satisfies FileType.Directory)
16
+ : stats.isSymbolicLink()
17
+ ? (64 satisfies FileType.SymbolicLink)
18
+ : (0 satisfies FileType.Unknown),
19
+ ctime: stats.ctimeMs,
20
+ mtime: stats.mtimeMs,
21
+ size: stats.size,
22
+ };
23
+ } catch {
24
+ return;
25
+ }
26
+ },
27
+ readFile(uri, encoding) {
28
+ try {
29
+ console.log("readFile", uri.path);
30
+ return fs.readFileSync(uri.path, {
31
+ encoding: (encoding as "utf-8") ?? "utf-8",
32
+ });
33
+ } catch {
34
+ return;
35
+ }
36
+ },
37
+ readDirectory(uri) {
38
+ try {
39
+ const files = fs.readdirSync(uri.path, { withFileTypes: true });
40
+ console.log("readDirectory", uri.path, files.map((f) => f.name));
41
+ return files.map<[string, FileType]>((file) => {
42
+ return [
43
+ file.name,
44
+ file.isFile()
45
+ ? (1 satisfies FileType.File)
46
+ : file.isDirectory()
47
+ ? (2 satisfies FileType.Directory)
48
+ : file.isSymbolicLink()
49
+ ? (64 satisfies FileType.SymbolicLink)
50
+ : (0 satisfies FileType.Unknown),
51
+ ];
52
+ });
53
+ } catch {
54
+ return [];
55
+ }
56
+ },
57
+ };
58
+ }