@spyglassmc/language-server 0.1.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.
- package/README.md +75 -0
- package/bin/server +2 -0
- package/lib/server.d.ts +2 -0
- package/lib/server.js +357 -0
- package/lib/util/index.d.ts +4 -0
- package/lib/util/index.js +16 -0
- package/lib/util/toCore.d.ts +14 -0
- package/lib/util/toCore.js +44 -0
- package/lib/util/toLS.d.ts +52 -0
- package/lib/util/toLS.js +327 -0
- package/lib/util/types.d.ts +21 -0
- package/lib/util/types.js +3 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# `@spyglassmc/language-server`
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
[](https://npmjs.com/package/datapack-language-server)
|
|
6
|
+
|
|
7
|
+
This is a [language server][lsp] wrapped around some other Spyglass packages.
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [For Use](#for-use)
|
|
11
|
+
- [Sublime Text 3](#sublime-text-3)
|
|
12
|
+
- [Visual Studio Code](#visual-studio-code)
|
|
13
|
+
- [For Developers](#for-developers)
|
|
14
|
+
|
|
15
|
+
# Installation
|
|
16
|
+
|
|
17
|
+
## For Use
|
|
18
|
+
|
|
19
|
+
### Sublime Text 3
|
|
20
|
+
|
|
21
|
+
1. Install [Node.js](https://nodejs.org/) if you haven't.
|
|
22
|
+
2. Execute `npm i -g @spyglassmc/language-server` in your command line to install the language server.
|
|
23
|
+
3. Install [Package Control](https://packagecontrol.io/installation) if you haven't.
|
|
24
|
+
4. Install [Arcensoth](https://github.com/Arcensoth)'s language-mcfunction package by following the [instructions](https://github.com/Arcensoth/language-mcfunction#installing-the-sublimetext-package) if you haven't.
|
|
25
|
+
5. Install [LSP](https://packagecontrol.io/packages/LSP) package.
|
|
26
|
+
6. Open the Command Palette and select `Preferences: LSP Settings`.
|
|
27
|
+
7. Configure LSP to add the Data-pack Language Server. Here's one example:
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"clients": {
|
|
31
|
+
"datapack-language-server": {
|
|
32
|
+
"command": [
|
|
33
|
+
"datapack-language-server",
|
|
34
|
+
"--stdio"
|
|
35
|
+
],
|
|
36
|
+
"enabled": true,
|
|
37
|
+
"languages": [
|
|
38
|
+
{
|
|
39
|
+
"languageId": "mcfunction",
|
|
40
|
+
"scopes": [
|
|
41
|
+
"source.mcfunction"
|
|
42
|
+
],
|
|
43
|
+
"syntaxes": [
|
|
44
|
+
"Packages/language-mcfunction/mcfunction.tmLanguage"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"languageId": "json",
|
|
49
|
+
"scopes": [
|
|
50
|
+
"source.json"
|
|
51
|
+
],
|
|
52
|
+
"syntaxes": [
|
|
53
|
+
"Packages/JavaScript/JSON.sublime-syntax"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"only_show_lsp_completions": true
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
8. Open the Command Palette, select `LSP: Enable Language Server Globally`, and choose `datapack-language-server`.
|
|
63
|
+
9. Enjoy. Do note that you need to execute the command in step 2 manually if you want to update the language server.
|
|
64
|
+
|
|
65
|
+
- TODO (for SPGoding): make a fine-tuned Sublime package, so that the language server can be updated automatically and the user doesn't need to set all these crazy stuff.
|
|
66
|
+
|
|
67
|
+
### Visual Studio Code
|
|
68
|
+
|
|
69
|
+
We have a ready-for-use [VS Code](https://code.visualstudio.com/) extension: [](https://marketplace.visualstudio.com/items?itemName=SPGoding.datapack-language-server)
|
|
70
|
+
|
|
71
|
+
## For Developers
|
|
72
|
+
|
|
73
|
+
See our [wiki](https://spyglassmc.com/wiki/Language-Server-Details) for more information.
|
|
74
|
+
|
|
75
|
+
[lsp]: https://microsoft.github.io/language-server-protocol/
|
package/bin/server
ADDED
package/lib/server.d.ts
ADDED
package/lib/server.js
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
25
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
const core = __importStar(require("@spyglassmc/core"));
|
|
29
|
+
const je = __importStar(require("@spyglassmc/java-edition"));
|
|
30
|
+
const locales = __importStar(require("@spyglassmc/locales"));
|
|
31
|
+
const nbtdoc = __importStar(require("@spyglassmc/nbtdoc"));
|
|
32
|
+
const env_paths_1 = __importDefault(require("env-paths"));
|
|
33
|
+
const util = __importStar(require("util"));
|
|
34
|
+
const ls = __importStar(require("vscode-languageserver/node"));
|
|
35
|
+
const util_1 = require("./util");
|
|
36
|
+
__exportStar(require("./util/types"), exports);
|
|
37
|
+
if (process.argv.length === 2) {
|
|
38
|
+
// When the server is launched from the cmd script, the process arguments
|
|
39
|
+
// are wiped. I don't know why it happens, but this is what it is.
|
|
40
|
+
// Therefore, we push a '--stdio' if the argument list is too short.
|
|
41
|
+
process.argv.push('--stdio');
|
|
42
|
+
}
|
|
43
|
+
const { cache: cacheRoot } = (0, env_paths_1.default)('spyglassmc');
|
|
44
|
+
const connection = ls.createConnection();
|
|
45
|
+
let capabilities;
|
|
46
|
+
let workspaceFolders;
|
|
47
|
+
let hasShutdown = false;
|
|
48
|
+
let progressReporter;
|
|
49
|
+
const logger = {
|
|
50
|
+
error: (msg, ...args) => connection.console.error(util.format(msg, ...args)),
|
|
51
|
+
info: (msg, ...args) => connection.console.info(util.format(msg, ...args)),
|
|
52
|
+
log: (msg, ...args) => connection.console.log(util.format(msg, ...args)),
|
|
53
|
+
warn: (msg, ...args) => connection.console.warn(util.format(msg, ...args)),
|
|
54
|
+
};
|
|
55
|
+
let service;
|
|
56
|
+
connection.onInitialize(async (params) => {
|
|
57
|
+
logger.info(`[onInitialize] processId = ${JSON.stringify(params.processId)}`);
|
|
58
|
+
logger.info(`[onInitialize] clientInfo = ${JSON.stringify(params.clientInfo)}`);
|
|
59
|
+
logger.info(`[onInitialize] initializationOptions = ${JSON.stringify(params.initializationOptions)}`);
|
|
60
|
+
capabilities = params.capabilities;
|
|
61
|
+
workspaceFolders = params.workspaceFolders ?? [];
|
|
62
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
63
|
+
logger.warn('Delayed 3 seconds manually. If you see this in production, it means SPGoding messed up.');
|
|
64
|
+
if (params.workDoneToken) {
|
|
65
|
+
progressReporter = connection.window.attachWorkDoneProgress(params.workDoneToken);
|
|
66
|
+
progressReporter.begin(locales.localize('server.progress.preparing.title'));
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
await locales.loadLocale(params.locale);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
logger.error('[loadLocale]', e);
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
service = new core.Service({
|
|
76
|
+
cacheRoot,
|
|
77
|
+
initializers: [
|
|
78
|
+
nbtdoc.initialize,
|
|
79
|
+
je.initialize,
|
|
80
|
+
],
|
|
81
|
+
isDebugging: false,
|
|
82
|
+
logger,
|
|
83
|
+
profilers: new core.ProfilerFactory(logger, [
|
|
84
|
+
'cache#load',
|
|
85
|
+
'cache#save',
|
|
86
|
+
'project#init',
|
|
87
|
+
'project#ready',
|
|
88
|
+
]),
|
|
89
|
+
projectPath: core.fileUtil.fileUriToPath(workspaceFolders[0].uri),
|
|
90
|
+
});
|
|
91
|
+
service.project
|
|
92
|
+
.on('documentErrorred', ({ doc, errors }) => {
|
|
93
|
+
connection.sendDiagnostics({
|
|
94
|
+
diagnostics: util_1.toLS.diagnostics(errors, doc),
|
|
95
|
+
uri: doc.uri,
|
|
96
|
+
version: doc.version,
|
|
97
|
+
});
|
|
98
|
+
})
|
|
99
|
+
.on('documentRemoved', ({ uri }) => {
|
|
100
|
+
connection.sendDiagnostics({ uri, diagnostics: [] });
|
|
101
|
+
})
|
|
102
|
+
.on('ready', () => {
|
|
103
|
+
progressReporter?.done();
|
|
104
|
+
});
|
|
105
|
+
await service.project.init();
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
logger.error('[new Service]', e);
|
|
109
|
+
}
|
|
110
|
+
const customCapabilities = {
|
|
111
|
+
dataHackPubify: true,
|
|
112
|
+
inlayHints: true,
|
|
113
|
+
resetProjectCache: true,
|
|
114
|
+
showCacheRoot: true,
|
|
115
|
+
};
|
|
116
|
+
const ans = {
|
|
117
|
+
serverInfo: {
|
|
118
|
+
name: 'Spyglass Language Server',
|
|
119
|
+
},
|
|
120
|
+
capabilities: {
|
|
121
|
+
colorProvider: {},
|
|
122
|
+
completionProvider: {
|
|
123
|
+
triggerCharacters: service.project.meta.getTriggerCharacters(),
|
|
124
|
+
},
|
|
125
|
+
declarationProvider: {},
|
|
126
|
+
definitionProvider: {},
|
|
127
|
+
implementationProvider: {},
|
|
128
|
+
documentFormattingProvider: {},
|
|
129
|
+
referencesProvider: {},
|
|
130
|
+
typeDefinitionProvider: {},
|
|
131
|
+
documentHighlightProvider: {},
|
|
132
|
+
documentSymbolProvider: {
|
|
133
|
+
label: 'Spyglass',
|
|
134
|
+
},
|
|
135
|
+
hoverProvider: {},
|
|
136
|
+
semanticTokensProvider: {
|
|
137
|
+
documentSelector: util_1.toLS.documentSelector(service.project.meta),
|
|
138
|
+
legend: util_1.toLS.semanticTokensLegend(),
|
|
139
|
+
full: { delta: false },
|
|
140
|
+
range: true,
|
|
141
|
+
},
|
|
142
|
+
signatureHelpProvider: {
|
|
143
|
+
triggerCharacters: [' '],
|
|
144
|
+
},
|
|
145
|
+
textDocumentSync: {
|
|
146
|
+
change: ls.TextDocumentSyncKind.Incremental,
|
|
147
|
+
openClose: true,
|
|
148
|
+
},
|
|
149
|
+
workspaceSymbolProvider: {},
|
|
150
|
+
experimental: {
|
|
151
|
+
spyglassmc: customCapabilities,
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
if (capabilities.workspace?.workspaceFolders) {
|
|
156
|
+
ans.capabilities.workspace = {
|
|
157
|
+
workspaceFolders: {
|
|
158
|
+
supported: true,
|
|
159
|
+
changeNotifications: true,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return ans;
|
|
164
|
+
});
|
|
165
|
+
connection.onInitialized(async () => {
|
|
166
|
+
await service.project.ready();
|
|
167
|
+
if (capabilities.workspace?.workspaceFolders) {
|
|
168
|
+
connection.workspace.onDidChangeWorkspaceFolders(async () => {
|
|
169
|
+
// FIXME
|
|
170
|
+
// service.rawRoots = (await connection.workspace.getWorkspaceFolders() ?? []).map(r => r.uri)
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
connection.onDidOpenTextDocument(async ({ textDocument: { text, uri, version, languageId: languageID } }) => {
|
|
175
|
+
service.project.onDidOpen(uri, languageID, version, text);
|
|
176
|
+
});
|
|
177
|
+
connection.onDidChangeTextDocument(async ({ contentChanges, textDocument: { uri, version } }) => {
|
|
178
|
+
service.project.onDidChange(uri, contentChanges, version);
|
|
179
|
+
});
|
|
180
|
+
connection.onDidCloseTextDocument(({ textDocument: { uri } }) => {
|
|
181
|
+
service.project.onDidClose(uri);
|
|
182
|
+
});
|
|
183
|
+
connection.workspace.onDidRenameFiles(({}) => {
|
|
184
|
+
});
|
|
185
|
+
connection.onColorPresentation(async ({ textDocument: { uri }, color, range }) => {
|
|
186
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
187
|
+
if (!docAndNode) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
const { doc, node } = docAndNode;
|
|
191
|
+
const presentation = service.getColorPresentation(node, doc, util_1.toCore.range(range, doc), util_1.toCore.color(color));
|
|
192
|
+
return util_1.toLS.colorPresentationArray(presentation, doc);
|
|
193
|
+
});
|
|
194
|
+
connection.onDocumentColor(async ({ textDocument: { uri } }) => {
|
|
195
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
196
|
+
if (!docAndNode) {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
const { doc, node } = docAndNode;
|
|
200
|
+
const info = service.getColorInfo(node, doc);
|
|
201
|
+
return util_1.toLS.colorInformationArray(info, doc);
|
|
202
|
+
});
|
|
203
|
+
connection.onCompletion(async ({ textDocument: { uri }, position, context }) => {
|
|
204
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
205
|
+
if (!docAndNode) {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
const { doc, node } = docAndNode;
|
|
209
|
+
const offset = util_1.toCore.offset(position, doc);
|
|
210
|
+
const items = service.complete(node, doc, offset, context?.triggerCharacter);
|
|
211
|
+
return items.map(item => util_1.toLS.completionItem(item, doc, offset, capabilities.textDocument?.completion?.completionItem?.insertReplaceSupport));
|
|
212
|
+
});
|
|
213
|
+
connection.onRequest('spyglassmc/dataHackPubify', ({ initialism }) => {
|
|
214
|
+
return service.dataHackPubify(initialism);
|
|
215
|
+
});
|
|
216
|
+
connection.onDeclaration(async ({ textDocument: { uri }, position }) => {
|
|
217
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
218
|
+
if (!docAndNode) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
const { doc, node } = docAndNode;
|
|
222
|
+
const ans = service.getSymbolLocations(node, doc, util_1.toCore.offset(position, doc), ['declaration', 'definition']);
|
|
223
|
+
return util_1.toLS.locationLink(ans, doc, capabilities.textDocument?.declaration?.linkSupport);
|
|
224
|
+
});
|
|
225
|
+
connection.onDefinition(async ({ textDocument: { uri }, position }) => {
|
|
226
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
227
|
+
if (!docAndNode) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
const { doc, node } = docAndNode;
|
|
231
|
+
const ans = service.getSymbolLocations(node, doc, util_1.toCore.offset(position, doc), ['definition', 'declaration', 'implementation', 'typeDefinition']);
|
|
232
|
+
return util_1.toLS.locationLink(ans, doc, capabilities.textDocument?.definition?.linkSupport);
|
|
233
|
+
});
|
|
234
|
+
connection.onImplementation(async ({ textDocument: { uri }, position }) => {
|
|
235
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
236
|
+
if (!docAndNode) {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
const { doc, node } = docAndNode;
|
|
240
|
+
const ans = service.getSymbolLocations(node, doc, util_1.toCore.offset(position, doc), ['implementation', 'definition']);
|
|
241
|
+
return util_1.toLS.locationLink(ans, doc, capabilities.textDocument?.implementation?.linkSupport);
|
|
242
|
+
});
|
|
243
|
+
connection.onReferences(async ({ textDocument: { uri }, position, context: { includeDeclaration } }) => {
|
|
244
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
245
|
+
if (!docAndNode) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
const { doc, node } = docAndNode;
|
|
249
|
+
const ans = service.getSymbolLocations(node, doc, util_1.toCore.offset(position, doc), includeDeclaration ? undefined : ['reference']);
|
|
250
|
+
return util_1.toLS.locationLink(ans, doc, false);
|
|
251
|
+
});
|
|
252
|
+
connection.onTypeDefinition(async ({ textDocument: { uri }, position }) => {
|
|
253
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
254
|
+
if (!docAndNode) {
|
|
255
|
+
return undefined;
|
|
256
|
+
}
|
|
257
|
+
const { doc, node } = docAndNode;
|
|
258
|
+
const ans = service.getSymbolLocations(node, doc, util_1.toCore.offset(position, doc), ['typeDefinition']);
|
|
259
|
+
return util_1.toLS.locationLink(ans, doc, capabilities.textDocument?.typeDefinition?.linkSupport);
|
|
260
|
+
});
|
|
261
|
+
connection.onDocumentHighlight(async ({ textDocument: { uri }, position }) => {
|
|
262
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
263
|
+
if (!docAndNode) {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
const { doc, node } = docAndNode;
|
|
267
|
+
const ans = service.getSymbolLocations(node, doc, util_1.toCore.offset(position, doc), undefined, true);
|
|
268
|
+
return util_1.toLS.documentHighlight(ans);
|
|
269
|
+
});
|
|
270
|
+
connection.onDocumentSymbol(async ({ textDocument: { uri } }) => {
|
|
271
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
272
|
+
if (!docAndNode) {
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
const { doc, node } = docAndNode;
|
|
276
|
+
return util_1.toLS.documentSymbolsFromTables([service.project.symbols.global, ...core.AstNode.getLocalsToLeaves(node)], doc, capabilities.textDocument?.documentSymbol?.hierarchicalDocumentSymbolSupport, capabilities.textDocument?.documentSymbol?.symbolKind?.valueSet);
|
|
277
|
+
});
|
|
278
|
+
connection.onHover(async ({ textDocument: { uri }, position }) => {
|
|
279
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
280
|
+
if (!docAndNode) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
const { doc, node } = docAndNode;
|
|
284
|
+
const ans = service.getHover(node, doc, util_1.toCore.offset(position, doc));
|
|
285
|
+
return ans ? util_1.toLS.hover(ans, doc) : undefined;
|
|
286
|
+
});
|
|
287
|
+
connection.onRequest('spyglassmc/inlayHints', async ({ textDocument: { uri }, range }) => {
|
|
288
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
289
|
+
if (!docAndNode) {
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
const { doc, node } = docAndNode;
|
|
293
|
+
const hints = service.getInlayHints(node, doc, util_1.toCore.range(range, doc));
|
|
294
|
+
return util_1.toLS.inlayHints(hints, doc);
|
|
295
|
+
});
|
|
296
|
+
connection.onRequest('spyglassmc/resetProjectCache', async () => {
|
|
297
|
+
service.project.resetCache();
|
|
298
|
+
return service.project.restart();
|
|
299
|
+
});
|
|
300
|
+
connection.onRequest('spyglassmc/showCacheRoot', async () => {
|
|
301
|
+
return service.project.showCacheRoot();
|
|
302
|
+
});
|
|
303
|
+
connection.languages.semanticTokens.on(async ({ textDocument: { uri } }) => {
|
|
304
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
305
|
+
if (!docAndNode) {
|
|
306
|
+
return { data: [] };
|
|
307
|
+
}
|
|
308
|
+
const { doc, node } = docAndNode;
|
|
309
|
+
const tokens = service.colorize(node, doc);
|
|
310
|
+
return util_1.toLS.semanticTokens(tokens, doc);
|
|
311
|
+
});
|
|
312
|
+
connection.languages.semanticTokens.onRange(async ({ textDocument: { uri }, range }) => {
|
|
313
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
314
|
+
if (!docAndNode) {
|
|
315
|
+
return { data: [] };
|
|
316
|
+
}
|
|
317
|
+
const { doc, node } = docAndNode;
|
|
318
|
+
const tokens = service.colorize(node, doc, util_1.toCore.range(range, doc));
|
|
319
|
+
return util_1.toLS.semanticTokens(tokens, doc);
|
|
320
|
+
});
|
|
321
|
+
connection.onSignatureHelp(async ({ textDocument: { uri }, position }) => {
|
|
322
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
323
|
+
if (!docAndNode) {
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
const { doc, node } = docAndNode;
|
|
327
|
+
const help = service.getSignatureHelp(node, doc, util_1.toCore.offset(position, doc));
|
|
328
|
+
return util_1.toLS.signatureHelp(help);
|
|
329
|
+
});
|
|
330
|
+
connection.onWorkspaceSymbol(({ query }) => {
|
|
331
|
+
return util_1.toLS.symbolInformationArrayFromTable(service.project.symbols.global, query, capabilities.textDocument?.documentSymbol?.symbolKind?.valueSet);
|
|
332
|
+
});
|
|
333
|
+
connection.onDocumentFormatting(async ({ textDocument: { uri }, options }) => {
|
|
334
|
+
const docAndNode = await service.project.ensureParsedAndChecked(uri);
|
|
335
|
+
if (!docAndNode) {
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
const { doc, node } = docAndNode;
|
|
339
|
+
let text = service.format(node, doc, options.tabSize, options.insertSpaces);
|
|
340
|
+
if (options.insertFinalNewline && text.charAt(text.length - 1) !== '\n') {
|
|
341
|
+
text += '\n';
|
|
342
|
+
}
|
|
343
|
+
return [util_1.toLS.textEdit(node.range, text, doc)];
|
|
344
|
+
});
|
|
345
|
+
connection.onShutdown(async () => {
|
|
346
|
+
await service.project.close();
|
|
347
|
+
hasShutdown = true;
|
|
348
|
+
});
|
|
349
|
+
connection.onExit(() => {
|
|
350
|
+
connection.dispose();
|
|
351
|
+
if (!hasShutdown) {
|
|
352
|
+
console.error('The server has not finished the shutdown request before receiving the exit request.');
|
|
353
|
+
process.exitCode = 1;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
connection.listen();
|
|
357
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
__exportStar(require("./toCore"), exports);
|
|
14
|
+
__exportStar(require("./toLS"), exports);
|
|
15
|
+
__exportStar(require("./types"), exports);
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
2
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
|
+
import type * as ls from 'vscode-languageserver/node';
|
|
4
|
+
/**
|
|
5
|
+
* A series of functions that can transform `vscode-languageserver` types to `@spyglassmc/core` types.
|
|
6
|
+
*
|
|
7
|
+
* Functions are named after types in `@spyglassmc/core`.
|
|
8
|
+
*/
|
|
9
|
+
export declare namespace toCore {
|
|
10
|
+
function offset(position: ls.Position, doc: TextDocument): number;
|
|
11
|
+
function range(range: ls.Range, doc: TextDocument): core.Range;
|
|
12
|
+
function color(color: ls.Color): core.Color;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=toCore.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.toCore = void 0;
|
|
23
|
+
const core = __importStar(require("@spyglassmc/core"));
|
|
24
|
+
/**
|
|
25
|
+
* A series of functions that can transform `vscode-languageserver` types to `@spyglassmc/core` types.
|
|
26
|
+
*
|
|
27
|
+
* Functions are named after types in `@spyglassmc/core`.
|
|
28
|
+
*/
|
|
29
|
+
var toCore;
|
|
30
|
+
(function (toCore) {
|
|
31
|
+
function offset(position, doc) {
|
|
32
|
+
return doc.offsetAt(position);
|
|
33
|
+
}
|
|
34
|
+
toCore.offset = offset;
|
|
35
|
+
function range(range, doc) {
|
|
36
|
+
return core.Range.create(offset(range.start, doc), offset(range.end, doc));
|
|
37
|
+
}
|
|
38
|
+
toCore.range = range;
|
|
39
|
+
function color(color) {
|
|
40
|
+
return [color.red, color.green, color.blue, color.alpha];
|
|
41
|
+
}
|
|
42
|
+
toCore.color = color;
|
|
43
|
+
})(toCore = exports.toCore || (exports.toCore = {}));
|
|
44
|
+
//# sourceMappingURL=toCore.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
2
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
|
+
import * as ls from 'vscode-languageserver/node';
|
|
4
|
+
import type { MyLspInlayHint } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* A series of functions that can transform `@spyglassmc/core` types to `vscode-languageserver` types.
|
|
7
|
+
*
|
|
8
|
+
* Functions are named after types in `vscode-languageserver`.
|
|
9
|
+
*/
|
|
10
|
+
export declare namespace toLS {
|
|
11
|
+
function color(color: core.Color): ls.Color;
|
|
12
|
+
function colorInformation(info: core.ColorInfo, doc: TextDocument): ls.ColorInformation;
|
|
13
|
+
function colorInformationArray(info: core.ColorInfo[], doc: TextDocument): ls.ColorInformation[];
|
|
14
|
+
function colorPresentation(presentation: core.ColorPresentation, doc: TextDocument): ls.ColorPresentation;
|
|
15
|
+
function colorPresentationArray(presentation: core.ColorPresentation[], doc: TextDocument): ls.ColorPresentation[];
|
|
16
|
+
function diagnostic(error: core.LanguageError, doc: TextDocument): ls.Diagnostic;
|
|
17
|
+
function diagnostics(errors: readonly core.LanguageError[], doc: TextDocument): ls.Diagnostic[];
|
|
18
|
+
function diagnosticSeverity(severity: core.ErrorSeverity): ls.DiagnosticSeverity;
|
|
19
|
+
function documentHighlight(locations: core.SymbolLocations | undefined): ls.DocumentHighlight[] | undefined;
|
|
20
|
+
function documentSelector(meta: core.MetaRegistry): ls.DocumentSelector;
|
|
21
|
+
function documentSymbol(symbol: core.Symbol, symLoc: core.SymbolLocation, doc: TextDocument, hierarchicalSupport: boolean | undefined, supportedKinds?: ls.SymbolKind[]): ls.DocumentSymbol;
|
|
22
|
+
function documentSymbols(map: core.SymbolMap | undefined, doc: TextDocument, hierarchicalSupport: boolean | undefined, supportedKinds?: ls.SymbolKind[]): ls.DocumentSymbol[];
|
|
23
|
+
function documentSymbolsFromTable(table: core.SymbolTable, doc: TextDocument, hierarchicalSupport: boolean | undefined, supportedKinds?: ls.SymbolKind[]): ls.DocumentSymbol[];
|
|
24
|
+
function documentSymbolsFromTables(tables: core.SymbolTable[], doc: TextDocument, hierarchicalSupport: boolean | undefined, supportedKinds?: ls.SymbolKind[]): ls.DocumentSymbol[];
|
|
25
|
+
function hover(hover: core.Hover, doc: TextDocument): ls.Hover;
|
|
26
|
+
function inlayHint(hint: core.InlayHint, doc: TextDocument): MyLspInlayHint;
|
|
27
|
+
function inlayHints(hints: core.InlayHint[], doc: TextDocument): MyLspInlayHint[];
|
|
28
|
+
function completionItem(completion: core.CompletionItem, doc: TextDocument, requestedOffset: number, insertReplaceSupport: boolean | undefined): ls.CompletionItem;
|
|
29
|
+
function location(location: {
|
|
30
|
+
uri: string;
|
|
31
|
+
posRange: core.PositionRange;
|
|
32
|
+
}): ls.Location;
|
|
33
|
+
function locationLink(locations: core.SymbolLocations | undefined, doc: TextDocument, linkSupport: false): ls.Location[] | undefined;
|
|
34
|
+
function locationLink(locations: core.SymbolLocations | undefined, doc: TextDocument, linkSupport: boolean | undefined): ls.LocationLink[] | ls.Location[] | undefined;
|
|
35
|
+
function markupContent(value: string): ls.MarkupContent;
|
|
36
|
+
function position(offset: number, doc: TextDocument): ls.Position;
|
|
37
|
+
function range(range: core.Range, doc: TextDocument): ls.Range;
|
|
38
|
+
function semanticTokenModifier(modifier: core.ColorTokenModifier): number;
|
|
39
|
+
function semanticTokenModifiers(modifiers?: readonly core.ColorTokenModifier[]): number;
|
|
40
|
+
function semanticTokens(tokens: readonly core.ColorToken[], doc: TextDocument): ls.SemanticTokens;
|
|
41
|
+
function semanticTokensLegend(): ls.SemanticTokensLegend;
|
|
42
|
+
function semanticTokenType(type: core.ColorTokenType): number;
|
|
43
|
+
function signatureHelp(help: core.SignatureHelp | undefined): ls.SignatureHelp | undefined;
|
|
44
|
+
function signatureInformation(info: core.SignatureInfo): ls.SignatureInformation;
|
|
45
|
+
function parameterInformation(info: core.ParameterInfo): ls.ParameterInformation;
|
|
46
|
+
function symbolInformation(symbol: core.Symbol, symLoc: core.SymbolLocation, supportedKinds?: ls.SymbolKind[]): ls.SymbolInformation;
|
|
47
|
+
function symbolInformationArray(map: core.SymbolMap | undefined, query: string, supportedKinds?: ls.SymbolKind[]): ls.SymbolInformation[];
|
|
48
|
+
function symbolInformationArrayFromTable(table: core.SymbolTable, query: string, supportedKinds?: ls.SymbolKind[]): ls.SymbolInformation[];
|
|
49
|
+
function symbolKind(category: string, subcategory?: string, supportedKinds?: ls.SymbolKind[]): ls.SymbolKind;
|
|
50
|
+
function textEdit(range: core.Range, text: string, doc: TextDocument): ls.TextEdit;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=toLS.d.ts.map
|
package/lib/util/toLS.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.toLS = void 0;
|
|
23
|
+
const core = __importStar(require("@spyglassmc/core"));
|
|
24
|
+
const ls = __importStar(require("vscode-languageserver/node"));
|
|
25
|
+
const node_1 = require("vscode-languageserver/node");
|
|
26
|
+
/**
|
|
27
|
+
* A series of functions that can transform `@spyglassmc/core` types to `vscode-languageserver` types.
|
|
28
|
+
*
|
|
29
|
+
* Functions are named after types in `vscode-languageserver`.
|
|
30
|
+
*/
|
|
31
|
+
var toLS;
|
|
32
|
+
(function (toLS) {
|
|
33
|
+
const ZeroPosition = { line: 0, character: 0 };
|
|
34
|
+
const ZeroRange = { start: ZeroPosition, end: ZeroPosition };
|
|
35
|
+
function color(color) {
|
|
36
|
+
return ls.Color.create(...color);
|
|
37
|
+
}
|
|
38
|
+
toLS.color = color;
|
|
39
|
+
function colorInformation(info, doc) {
|
|
40
|
+
return ls.ColorInformation.create(range(info.range, doc), color(info.color));
|
|
41
|
+
}
|
|
42
|
+
toLS.colorInformation = colorInformation;
|
|
43
|
+
function colorInformationArray(info, doc) {
|
|
44
|
+
return info.map(i => colorInformation(i, doc));
|
|
45
|
+
}
|
|
46
|
+
toLS.colorInformationArray = colorInformationArray;
|
|
47
|
+
function colorPresentation(presentation, doc) {
|
|
48
|
+
const edit = ls.TextEdit.replace(range(presentation.range, doc), presentation.text);
|
|
49
|
+
return ls.ColorPresentation.create(presentation.label, edit);
|
|
50
|
+
}
|
|
51
|
+
toLS.colorPresentation = colorPresentation;
|
|
52
|
+
function colorPresentationArray(presentation, doc) {
|
|
53
|
+
return presentation.map(p => colorPresentation(p, doc));
|
|
54
|
+
}
|
|
55
|
+
toLS.colorPresentationArray = colorPresentationArray;
|
|
56
|
+
function diagnostic(error, doc) {
|
|
57
|
+
const ans = ls.Diagnostic.create(range(error.range, doc), error.message, diagnosticSeverity(error.severity), undefined, 'spyglassmc');
|
|
58
|
+
if (error.info?.deprecated) {
|
|
59
|
+
(ans.tags ?? (ans.tags = []))?.push(ls.DiagnosticTag.Deprecated);
|
|
60
|
+
}
|
|
61
|
+
if (error.info?.unnecessary) {
|
|
62
|
+
(ans.tags ?? (ans.tags = []))?.push(ls.DiagnosticTag.Unnecessary);
|
|
63
|
+
}
|
|
64
|
+
if (error.info?.codeAction) {
|
|
65
|
+
ans.data = {
|
|
66
|
+
codeAction: error.info?.codeAction,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (error.info?.related) {
|
|
70
|
+
ans.relatedInformation = error.info?.related.map(v => ({
|
|
71
|
+
location: location(v.location),
|
|
72
|
+
message: v.message,
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
return ans;
|
|
76
|
+
}
|
|
77
|
+
toLS.diagnostic = diagnostic;
|
|
78
|
+
function diagnostics(errors, doc) {
|
|
79
|
+
return errors.map(e => diagnostic(e, doc));
|
|
80
|
+
}
|
|
81
|
+
toLS.diagnostics = diagnostics;
|
|
82
|
+
function diagnosticSeverity(severity) {
|
|
83
|
+
switch (severity) {
|
|
84
|
+
case 0 /* Hint */:
|
|
85
|
+
return ls.DiagnosticSeverity.Hint;
|
|
86
|
+
case 1 /* Information */:
|
|
87
|
+
return ls.DiagnosticSeverity.Information;
|
|
88
|
+
case 2 /* Warning */:
|
|
89
|
+
return ls.DiagnosticSeverity.Warning;
|
|
90
|
+
case 3 /* Error */:
|
|
91
|
+
return ls.DiagnosticSeverity.Error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
toLS.diagnosticSeverity = diagnosticSeverity;
|
|
95
|
+
function documentHighlight(locations) {
|
|
96
|
+
return locations?.locations
|
|
97
|
+
?.filter(loc => loc.posRange)
|
|
98
|
+
?.map(loc => ({ range: loc.posRange }));
|
|
99
|
+
}
|
|
100
|
+
toLS.documentHighlight = documentHighlight;
|
|
101
|
+
function documentSelector(meta) {
|
|
102
|
+
const ans = meta.getLanguages().map(id => ({ language: id }));
|
|
103
|
+
return ans;
|
|
104
|
+
}
|
|
105
|
+
toLS.documentSelector = documentSelector;
|
|
106
|
+
function documentSymbol(symbol, symLoc, doc, hierarchicalSupport, supportedKinds = []) {
|
|
107
|
+
return {
|
|
108
|
+
name: symbol.identifier,
|
|
109
|
+
kind: symbolKind(symbol.category, symbol.subcategory, supportedKinds),
|
|
110
|
+
range: symLoc.fullPosRange ?? symLoc.posRange ?? ZeroRange,
|
|
111
|
+
selectionRange: symLoc.posRange ?? ZeroRange,
|
|
112
|
+
children: hierarchicalSupport ? documentSymbols(symbol.members, doc, hierarchicalSupport, supportedKinds) : undefined,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
toLS.documentSymbol = documentSymbol;
|
|
116
|
+
function documentSymbols(map = {}, doc, hierarchicalSupport, supportedKinds = []) {
|
|
117
|
+
return Object.values(map)
|
|
118
|
+
.map(s => [s, [...s.declaration ?? [], ...s.definition ?? [], ...s.implementation ?? [], ...s.typeDefinition ?? []].find(l => l.uri === doc.uri)])
|
|
119
|
+
.filter(([_s, l]) => !!l)
|
|
120
|
+
.map(([s, l]) => documentSymbol(s, l, doc, hierarchicalSupport, supportedKinds));
|
|
121
|
+
}
|
|
122
|
+
toLS.documentSymbols = documentSymbols;
|
|
123
|
+
function documentSymbolsFromTable(table, doc, hierarchicalSupport, supportedKinds = []) {
|
|
124
|
+
return Object.values(table)
|
|
125
|
+
.map(m => documentSymbols(m, doc, hierarchicalSupport, supportedKinds))
|
|
126
|
+
.flat();
|
|
127
|
+
}
|
|
128
|
+
toLS.documentSymbolsFromTable = documentSymbolsFromTable;
|
|
129
|
+
function documentSymbolsFromTables(tables, doc, hierarchicalSupport, supportedKinds = []) {
|
|
130
|
+
return tables
|
|
131
|
+
.map(t => documentSymbolsFromTable(t, doc, hierarchicalSupport, supportedKinds))
|
|
132
|
+
.flat();
|
|
133
|
+
}
|
|
134
|
+
toLS.documentSymbolsFromTables = documentSymbolsFromTables;
|
|
135
|
+
function hover(hover, doc) {
|
|
136
|
+
const ans = {
|
|
137
|
+
contents: markupContent(hover.markdown),
|
|
138
|
+
range: range(hover.range, doc),
|
|
139
|
+
};
|
|
140
|
+
return ans;
|
|
141
|
+
}
|
|
142
|
+
toLS.hover = hover;
|
|
143
|
+
function inlayHint(hint, doc) {
|
|
144
|
+
return {
|
|
145
|
+
position: doc.positionAt(hint.offset),
|
|
146
|
+
text: hint.text,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
toLS.inlayHint = inlayHint;
|
|
150
|
+
function inlayHints(hints, doc) {
|
|
151
|
+
return hints.map(h => inlayHint(h, doc));
|
|
152
|
+
}
|
|
153
|
+
toLS.inlayHints = inlayHints;
|
|
154
|
+
function completionItem(completion, doc, requestedOffset, insertReplaceSupport) {
|
|
155
|
+
const insertText = completion.insertText ?? completion.label;
|
|
156
|
+
const canInsertReplace = insertReplaceSupport && ![core.CR, core.LF, core.CRLF].includes(insertText);
|
|
157
|
+
const textEdit = canInsertReplace
|
|
158
|
+
? ls.InsertReplaceEdit.create(insertText,
|
|
159
|
+
/* insert */ range(core.Range.create(completion.range.start, requestedOffset), doc),
|
|
160
|
+
/* replace */ range(completion.range, doc))
|
|
161
|
+
: ls.TextEdit.replace(range(completion.range, doc), insertText);
|
|
162
|
+
const ans = {
|
|
163
|
+
label: completion.label,
|
|
164
|
+
kind: completion.kind,
|
|
165
|
+
detail: completion.detail,
|
|
166
|
+
documentation: completion.documentation,
|
|
167
|
+
filterText: completion.filterText,
|
|
168
|
+
sortText: completion.sortText,
|
|
169
|
+
textEdit,
|
|
170
|
+
insertTextFormat: node_1.InsertTextFormat.Snippet,
|
|
171
|
+
insertTextMode: ls.InsertTextMode.adjustIndentation,
|
|
172
|
+
...completion.deprecated ? { tags: [ls.CompletionItemTag.Deprecated] } : {},
|
|
173
|
+
};
|
|
174
|
+
return ans;
|
|
175
|
+
}
|
|
176
|
+
toLS.completionItem = completionItem;
|
|
177
|
+
function location(location) {
|
|
178
|
+
return {
|
|
179
|
+
uri: location.uri,
|
|
180
|
+
range: location.posRange,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
toLS.location = location;
|
|
184
|
+
function locationLink(locations, doc, linkSupport) {
|
|
185
|
+
return locations?.locations
|
|
186
|
+
? linkSupport
|
|
187
|
+
? locations.locations.map(loc => ({
|
|
188
|
+
originSelectionRange: range(locations.range, doc),
|
|
189
|
+
targetUri: loc.uri,
|
|
190
|
+
targetRange: loc.fullPosRange ?? loc.posRange ?? ZeroRange,
|
|
191
|
+
targetSelectionRange: loc.posRange ?? ZeroRange,
|
|
192
|
+
}))
|
|
193
|
+
: (locations.locations).map(loc => location({ uri: loc.uri, posRange: loc.posRange ?? ZeroRange }))
|
|
194
|
+
: undefined;
|
|
195
|
+
}
|
|
196
|
+
toLS.locationLink = locationLink;
|
|
197
|
+
function markupContent(value) {
|
|
198
|
+
return {
|
|
199
|
+
kind: ls.MarkupKind.Markdown,
|
|
200
|
+
value: value,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
toLS.markupContent = markupContent;
|
|
204
|
+
function position(offset, doc) {
|
|
205
|
+
return doc.positionAt(offset);
|
|
206
|
+
}
|
|
207
|
+
toLS.position = position;
|
|
208
|
+
function range(range, doc) {
|
|
209
|
+
return ls.Range.create(position(range.start, doc), position(range.end, doc));
|
|
210
|
+
}
|
|
211
|
+
toLS.range = range;
|
|
212
|
+
function semanticTokenModifier(modifier) {
|
|
213
|
+
return core.ColorTokenModifiers.indexOf(modifier);
|
|
214
|
+
}
|
|
215
|
+
toLS.semanticTokenModifier = semanticTokenModifier;
|
|
216
|
+
function semanticTokenModifiers(modifiers = []) {
|
|
217
|
+
let ans = 0;
|
|
218
|
+
for (const modifier of modifiers) {
|
|
219
|
+
ans += 1 << semanticTokenModifier(modifier);
|
|
220
|
+
}
|
|
221
|
+
return ans;
|
|
222
|
+
}
|
|
223
|
+
toLS.semanticTokenModifiers = semanticTokenModifiers;
|
|
224
|
+
function semanticTokens(tokens, doc) {
|
|
225
|
+
const builder = new ls.SemanticTokensBuilder();
|
|
226
|
+
for (const token of tokens) {
|
|
227
|
+
const pos = position(token.range.start, doc);
|
|
228
|
+
const length = token.range.end - token.range.start;
|
|
229
|
+
builder.push(pos.line, pos.character, length, semanticTokenType(token.type), semanticTokenModifiers(token.modifiers));
|
|
230
|
+
}
|
|
231
|
+
return builder.build();
|
|
232
|
+
}
|
|
233
|
+
toLS.semanticTokens = semanticTokens;
|
|
234
|
+
function semanticTokensLegend() {
|
|
235
|
+
const ans = {
|
|
236
|
+
tokenTypes: core.ColorTokenTypes,
|
|
237
|
+
tokenModifiers: core.ColorTokenModifiers,
|
|
238
|
+
};
|
|
239
|
+
return ans;
|
|
240
|
+
}
|
|
241
|
+
toLS.semanticTokensLegend = semanticTokensLegend;
|
|
242
|
+
function semanticTokenType(type) {
|
|
243
|
+
return core.ColorTokenTypes.indexOf(type);
|
|
244
|
+
}
|
|
245
|
+
toLS.semanticTokenType = semanticTokenType;
|
|
246
|
+
function signatureHelp(help) {
|
|
247
|
+
if (!help || help.signatures.length === 0) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
signatures: help.signatures.map(signatureInformation),
|
|
252
|
+
activeParameter: help.signatures[help.activeSignature].activeParameter,
|
|
253
|
+
activeSignature: help.activeSignature,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
toLS.signatureHelp = signatureHelp;
|
|
257
|
+
function signatureInformation(info) {
|
|
258
|
+
return {
|
|
259
|
+
label: info.label,
|
|
260
|
+
activeParameter: info.activeParameter,
|
|
261
|
+
documentation: info.documentation ? markupContent(info.documentation) : undefined,
|
|
262
|
+
parameters: info.parameters.map(parameterInformation),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
toLS.signatureInformation = signatureInformation;
|
|
266
|
+
function parameterInformation(info) {
|
|
267
|
+
return {
|
|
268
|
+
label: info.label,
|
|
269
|
+
documentation: info.documentation ? markupContent(info.documentation) : undefined,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
toLS.parameterInformation = parameterInformation;
|
|
273
|
+
function symbolInformation(symbol, symLoc, supportedKinds = []) {
|
|
274
|
+
return {
|
|
275
|
+
name: symbol.identifier,
|
|
276
|
+
kind: symbolKind(symbol.category, symbol.subcategory, supportedKinds),
|
|
277
|
+
location: location({ uri: symLoc.uri, posRange: symLoc.fullPosRange ?? symLoc.posRange ?? ZeroRange }),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
toLS.symbolInformation = symbolInformation;
|
|
281
|
+
function symbolInformationArray(map = {}, query, supportedKinds = []) {
|
|
282
|
+
return Object.values(map)
|
|
283
|
+
.filter(s => s.identifier.includes(query))
|
|
284
|
+
.map(s => [s, [...s.declaration ?? [], ...s.definition ?? [], ...s.implementation ?? [], ...s.typeDefinition ?? []][0]])
|
|
285
|
+
.filter(([_s, l]) => !!l)
|
|
286
|
+
.map(([s, l]) => symbolInformation(s, l, supportedKinds));
|
|
287
|
+
}
|
|
288
|
+
toLS.symbolInformationArray = symbolInformationArray;
|
|
289
|
+
function symbolInformationArrayFromTable(table, query, supportedKinds = []) {
|
|
290
|
+
return Object.values(table)
|
|
291
|
+
.map(m => symbolInformationArray(m, query, supportedKinds))
|
|
292
|
+
.flat();
|
|
293
|
+
}
|
|
294
|
+
toLS.symbolInformationArrayFromTable = symbolInformationArrayFromTable;
|
|
295
|
+
function symbolKind(category, subcategory = '', supportedKinds = []) {
|
|
296
|
+
const UltimateFallback = ls.SymbolKind.Variable;
|
|
297
|
+
const getKind = (kind, fallback) => supportedKinds?.includes(kind) ? kind : fallback;
|
|
298
|
+
if (core.ResourceLocationCategory.is(category)) {
|
|
299
|
+
return ls.SymbolKind.Function;
|
|
300
|
+
}
|
|
301
|
+
if (category === 'nbtdoc') {
|
|
302
|
+
const map = new Map([
|
|
303
|
+
['enum', ls.SymbolKind.Enum],
|
|
304
|
+
['enum_key', getKind(ls.SymbolKind.EnumMember, ls.SymbolKind.Field)],
|
|
305
|
+
['compound', getKind(ls.SymbolKind.Struct, ls.SymbolKind.Interface)],
|
|
306
|
+
['compound_key', ls.SymbolKind.Field],
|
|
307
|
+
['module', ls.SymbolKind.Module],
|
|
308
|
+
]);
|
|
309
|
+
return map.get(subcategory) ?? UltimateFallback;
|
|
310
|
+
}
|
|
311
|
+
const map = new Map([
|
|
312
|
+
['attribute_modifier_uuid', ls.SymbolKind.Number],
|
|
313
|
+
['nbtdoc/description', ls.SymbolKind.Constructor],
|
|
314
|
+
['objective', ls.SymbolKind.Variable],
|
|
315
|
+
['score_holder', ls.SymbolKind.Class],
|
|
316
|
+
['tag', ls.SymbolKind.String],
|
|
317
|
+
['team', ls.SymbolKind.Array],
|
|
318
|
+
]);
|
|
319
|
+
return map.get(category) ?? UltimateFallback;
|
|
320
|
+
}
|
|
321
|
+
toLS.symbolKind = symbolKind;
|
|
322
|
+
function textEdit(range, text, doc) {
|
|
323
|
+
return ls.TextEdit.replace(toLS.range(range, doc), text);
|
|
324
|
+
}
|
|
325
|
+
toLS.textEdit = textEdit;
|
|
326
|
+
})(toLS = exports.toLS || (exports.toLS = {}));
|
|
327
|
+
//# sourceMappingURL=toLS.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as ls from 'vscode-languageserver/node';
|
|
2
|
+
export interface CustomServerCapabilities {
|
|
3
|
+
dataHackPubify?: boolean;
|
|
4
|
+
inlayHints?: boolean;
|
|
5
|
+
resetProjectCache?: boolean;
|
|
6
|
+
showCacheRoot?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface MyLspDataHackPubifyRequestParams {
|
|
9
|
+
initialism: string;
|
|
10
|
+
}
|
|
11
|
+
export interface MyLspInlayHint {
|
|
12
|
+
position: ls.Position;
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
export interface MyLspInlayHintRequestParams {
|
|
16
|
+
textDocument: {
|
|
17
|
+
uri: string;
|
|
18
|
+
};
|
|
19
|
+
range: ls.Range;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spyglassmc/language-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "lib/server.js",
|
|
5
|
+
"types": "lib/server.d.ts",
|
|
6
|
+
"author": "SPGoding",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"directories": {
|
|
9
|
+
"man": "man",
|
|
10
|
+
"test": "test"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"spyglassmc-language-server": "./bin/server"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"release": "npm publish",
|
|
17
|
+
"release:dry": "npm publish --dry-run"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"env-paths": "^2.2.1",
|
|
21
|
+
"vscode-languageserver": "^7.0.0",
|
|
22
|
+
"vscode-languageserver-textdocument": "^1.0.1",
|
|
23
|
+
"@spyglassmc/core": "0.1.0",
|
|
24
|
+
"@spyglassmc/java-edition": "0.1.0",
|
|
25
|
+
"@spyglassmc/locales": "0.1.0",
|
|
26
|
+
"@spyglassmc/nbtdoc": "0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/SpyglassMC/Spyglass.git"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://spyglassmc.com",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/SpyglassMC/Spyglass/issues"
|
|
38
|
+
}
|
|
39
|
+
}
|