@px-lsp/protocol 0.1.0 → 0.2.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/LICENSE +674 -674
- package/README.md +25 -25
- package/dist/calendar.d.ts +71 -0
- package/dist/calendar.js +182 -0
- package/dist/calendarFile.d.ts +26 -0
- package/dist/calendarFile.js +109 -0
- package/dist/calendarLoc.d.ts +60 -0
- package/dist/calendarLoc.js +101 -0
- package/dist/configDir.d.ts +17 -0
- package/dist/configDir.js +79 -0
- package/dist/descriptorMod.d.ts +21 -0
- package/dist/descriptorMod.js +61 -5
- package/dist/kinds.d.ts +72 -0
- package/dist/kinds.js +186 -0
- package/dist/protocol.d.ts +661 -4
- package/dist/protocol.js +159 -2
- package/dist/workshopMeta.d.ts +40 -0
- package/dist/workshopMeta.js +146 -0
- package/package.json +1 -1
- package/src/arrays.ts +16 -16
- package/src/calendar.ts +183 -0
- package/src/calendarFile.ts +81 -0
- package/src/calendarLoc.ts +159 -0
- package/src/configDir.ts +47 -0
- package/src/constants.ts +12 -12
- package/src/descriptorMetadata.ts +101 -101
- package/src/descriptorMod.ts +414 -354
- package/src/errorLogParser.ts +136 -136
- package/src/fsWalk.ts +126 -126
- package/src/kinds.ts +205 -0
- package/src/locProperties.ts +43 -43
- package/src/locRefs.ts +38 -38
- package/src/modName.ts +18 -18
- package/src/protocol.ts +2156 -1459
- package/src/regex.ts +19 -19
- package/src/suppression.ts +178 -178
- package/src/tigerParser.ts +79 -79
- package/src/translationCore.ts +140 -140
- package/src/types.ts +90 -90
- package/src/workshopMeta.ts +127 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PX_CONFIG_DIR = void 0;
|
|
37
|
+
exports.resolveConfigDir = resolveConfigDir;
|
|
38
|
+
exports.migrateConfigDir = migrateConfigDir;
|
|
39
|
+
/**
|
|
40
|
+
* The toolkit's per-mod config dir: `<mod>/.px-toolkit/`, holding
|
|
41
|
+
* `workshop.json`, `schema.json`, `playset.json`, the tiger baseline, the GUI
|
|
42
|
+
* preview values and the Workshop listing folder. Mods created before 0.4.0
|
|
43
|
+
* have a per-game name instead (each GameMeta's `legacyConfigDirName`);
|
|
44
|
+
* reads keep finding it, and the first write renames it.
|
|
45
|
+
*
|
|
46
|
+
* No `vscode` imports: unit-tested in plain Node.
|
|
47
|
+
*/
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
exports.PX_CONFIG_DIR = ".px-toolkit";
|
|
51
|
+
/**
|
|
52
|
+
* The config dir to READ from: the current name when it exists, else the
|
|
53
|
+
* legacy one when that exists, else the current name. Never touches disk.
|
|
54
|
+
*/
|
|
55
|
+
function resolveConfigDir(root, names) {
|
|
56
|
+
const current = path.join(root, names.configDirName);
|
|
57
|
+
if (!names.legacyConfigDirName || fs.existsSync(current))
|
|
58
|
+
return current;
|
|
59
|
+
const legacy = path.join(root, names.legacyConfigDirName);
|
|
60
|
+
return fs.existsSync(legacy) ? legacy : current;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The config dir to WRITE to. Renames a legacy dir to the current name first;
|
|
64
|
+
* if the rename fails (locked file, read-only parent) the legacy dir stays in
|
|
65
|
+
* use so the write still lands where reads look.
|
|
66
|
+
*/
|
|
67
|
+
function migrateConfigDir(root, names) {
|
|
68
|
+
const current = path.join(root, names.configDirName);
|
|
69
|
+
const resolved = resolveConfigDir(root, names);
|
|
70
|
+
if (resolved === current)
|
|
71
|
+
return current;
|
|
72
|
+
try {
|
|
73
|
+
fs.renameSync(resolved, current);
|
|
74
|
+
return current;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return resolved;
|
|
78
|
+
}
|
|
79
|
+
}
|
package/dist/descriptorMod.d.ts
CHANGED
|
@@ -53,6 +53,11 @@ export declare function validateDescriptor(text: string, opts: {
|
|
|
53
53
|
* something comes from ("Community Flavor Pack") instead of a generic "mod".
|
|
54
54
|
*/
|
|
55
55
|
export declare function readDescriptorName(dir: string): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* The quoted strings inside a top-level `<key>={ "A" "B" }` block of a .mod
|
|
58
|
+
* text, in file order; empty when the block is missing.
|
|
59
|
+
*/
|
|
60
|
+
export declare function readDescriptorBlock(text: string, key: string): string[];
|
|
56
61
|
/**
|
|
57
62
|
* The mod names inside `<dir>/descriptor.mod`'s `dependencies={ "A" "B" }`
|
|
58
63
|
* block, in file order; empty when the file or the block is missing. The
|
|
@@ -60,6 +65,22 @@ export declare function readDescriptorName(dir: string): string | null;
|
|
|
60
65
|
* Workshop id, so that is what the caller compares them with.
|
|
61
66
|
*/
|
|
62
67
|
export declare function readDescriptorDependencies(dir: string): string[];
|
|
68
|
+
/**
|
|
69
|
+
* `text` with the top-level `key="value"` entry replaced, or appended when the
|
|
70
|
+
* key is absent. Only scalar entries: a key whose value is a block is left
|
|
71
|
+
* alone and the entry is appended instead. Line endings and a leading BOM
|
|
72
|
+
* survive untouched; the appended line follows the file's dominant EOL.
|
|
73
|
+
* The value is made descriptor-safe like upsertDescriptorBlock's quoting:
|
|
74
|
+
* the format has no escape, so double quotes become apostrophes and line
|
|
75
|
+
* breaks collapse to one space.
|
|
76
|
+
*/
|
|
77
|
+
export declare function upsertDescriptorValue(text: string, key: string, value: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* `text` with the top-level `key={...}` block replaced by one holding exactly
|
|
80
|
+
* `values` (quoted, tab-indented, the file's EOL), or appended when absent.
|
|
81
|
+
* Descriptor blocks are flat, so the block ends at the first `}`-only line.
|
|
82
|
+
*/
|
|
83
|
+
export declare function upsertDescriptorBlock(text: string, key: string, values: string[]): string;
|
|
63
84
|
/** "1.19.0.6" -> "1.19.*" (the wildcard form that survives hotfixes). */
|
|
64
85
|
export declare function wildcardVersion(raw: string): string | null;
|
|
65
86
|
/** A launcher-correct starter descriptor.mod. */
|
package/dist/descriptorMod.js
CHANGED
|
@@ -37,7 +37,10 @@ exports.LAUNCHER_TAGS = exports.DESCRIPTOR_FIELD_MAP = exports.DESCRIPTOR_FIELDS
|
|
|
37
37
|
exports.parseDescriptor = parseDescriptor;
|
|
38
38
|
exports.validateDescriptor = validateDescriptor;
|
|
39
39
|
exports.readDescriptorName = readDescriptorName;
|
|
40
|
+
exports.readDescriptorBlock = readDescriptorBlock;
|
|
40
41
|
exports.readDescriptorDependencies = readDescriptorDependencies;
|
|
42
|
+
exports.upsertDescriptorValue = upsertDescriptorValue;
|
|
43
|
+
exports.upsertDescriptorBlock = upsertDescriptorBlock;
|
|
41
44
|
exports.wildcardVersion = wildcardVersion;
|
|
42
45
|
exports.scaffoldDescriptor = scaffoldDescriptor;
|
|
43
46
|
/**
|
|
@@ -296,6 +299,17 @@ function readDescriptorName(dir) {
|
|
|
296
299
|
const value = entry.value.replace(/^"([^]*)"$/, "$1").trim();
|
|
297
300
|
return value === "" ? null : value;
|
|
298
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* The quoted strings inside a top-level `<key>={ "A" "B" }` block of a .mod
|
|
304
|
+
* text, in file order; empty when the block is missing.
|
|
305
|
+
*/
|
|
306
|
+
function readDescriptorBlock(text, key) {
|
|
307
|
+
// Comments first: a commented-out entry is not an entry.
|
|
308
|
+
const block = new RegExp(`(?:^|\\n)[ \\t]*${key}[ \\t]*=[ \\t]*\\{([^}]*)\\}`).exec(text.replace(/#[^\n]*/g, ""));
|
|
309
|
+
if (!block)
|
|
310
|
+
return [];
|
|
311
|
+
return [...block[1].matchAll(/"([^"]*)"/g)].map((m) => m[1].trim()).filter((s) => s !== "");
|
|
312
|
+
}
|
|
299
313
|
/**
|
|
300
314
|
* The mod names inside `<dir>/descriptor.mod`'s `dependencies={ "A" "B" }`
|
|
301
315
|
* block, in file order; empty when the file or the block is missing. The
|
|
@@ -310,11 +324,53 @@ function readDescriptorDependencies(dir) {
|
|
|
310
324
|
catch {
|
|
311
325
|
return [];
|
|
312
326
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
327
|
+
return readDescriptorBlock(text, "dependencies");
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* `text` with the top-level `key="value"` entry replaced, or appended when the
|
|
331
|
+
* key is absent. Only scalar entries: a key whose value is a block is left
|
|
332
|
+
* alone and the entry is appended instead. Line endings and a leading BOM
|
|
333
|
+
* survive untouched; the appended line follows the file's dominant EOL.
|
|
334
|
+
* The value is made descriptor-safe like upsertDescriptorBlock's quoting:
|
|
335
|
+
* the format has no escape, so double quotes become apostrophes and line
|
|
336
|
+
* breaks collapse to one space.
|
|
337
|
+
*/
|
|
338
|
+
function upsertDescriptorValue(text, key, value) {
|
|
339
|
+
const v = value.replace(/"/g, "'").replace(/\s*\r?\n\s*/g, " ");
|
|
340
|
+
const entry = parseDescriptor(text).find((e) => e.key === key && e.value !== "");
|
|
341
|
+
if (entry) {
|
|
342
|
+
const lines = text.split(/(\r?\n)/); // keep separators at odd indices
|
|
343
|
+
const idx = entry.line * 2;
|
|
344
|
+
lines[idx] = lines[idx].replace(/=\s*("[^"]*"|\S+)([ \t]*(#.*)?)$/, (_m, _old, tail) => `="${v}"${tail}`);
|
|
345
|
+
return lines.join("");
|
|
346
|
+
}
|
|
347
|
+
const eol = text.includes("\r\n") ? "\r\n" : "\n";
|
|
348
|
+
const sep = text === "" || text.endsWith("\n") ? "" : eol;
|
|
349
|
+
return `${text}${sep}${key}="${v}"${eol}`;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* `text` with the top-level `key={...}` block replaced by one holding exactly
|
|
353
|
+
* `values` (quoted, tab-indented, the file's EOL), or appended when absent.
|
|
354
|
+
* Descriptor blocks are flat, so the block ends at the first `}`-only line.
|
|
355
|
+
*/
|
|
356
|
+
function upsertDescriptorBlock(text, key, values) {
|
|
357
|
+
const eol = text.includes("\r\n") ? "\r\n" : "\n";
|
|
358
|
+
const q = (v) => `"${v.replace(/"/g, "'")}"`;
|
|
359
|
+
const block = [`${key}={`, ...values.map((v) => `\t${q(v)}`), `}`].join(eol);
|
|
360
|
+
const lines = text.split(/\r?\n/);
|
|
361
|
+
const open = lines.findIndex((l) => new RegExp(`^\\s*${key}\\s*=\\s*\\{`).test(l));
|
|
362
|
+
if (open >= 0) {
|
|
363
|
+
let close = open;
|
|
364
|
+
// A one-line block (`tags={ "x" }`) closes on its own line.
|
|
365
|
+
if (!/\}\s*(#.*)?$/.test(lines[open])) {
|
|
366
|
+
while (close < lines.length - 1 && !/^\s*\}\s*(#.*)?$/.test(lines[close]))
|
|
367
|
+
close++;
|
|
368
|
+
}
|
|
369
|
+
lines.splice(open, close - open + 1, block);
|
|
370
|
+
return lines.join(eol);
|
|
371
|
+
}
|
|
372
|
+
const sep = text === "" || text.endsWith("\n") ? "" : eol;
|
|
373
|
+
return `${text}${sep}${block}${eol}`;
|
|
318
374
|
}
|
|
319
375
|
/** "1.19.0.6" -> "1.19.*" (the wildcard form that survives hotfixes). */
|
|
320
376
|
function wildcardVersion(raw) {
|
package/dist/kinds.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One kind map, four surfaces.
|
|
3
|
+
*
|
|
4
|
+
* Every place the product names a concept - the hover badge, the completion
|
|
5
|
+
* list icon, the tree leaf, the breadcrumb/outline entry - reads its glyph from
|
|
6
|
+
* here, so a trigger looks like a trigger everywhere.
|
|
7
|
+
*
|
|
8
|
+
* The colour is not a second decision. VS Code paints a completion row from the
|
|
9
|
+
* `symbolIcon.*Foreground` token of the `CompletionItemKind` we send, and we
|
|
10
|
+
* cannot override it, so the kind IS the colour. The hover badge reuses that
|
|
11
|
+
* same token, which is why there is no colour column to keep in sync. Four
|
|
12
|
+
* groups come out of that, and choosing the kind is choosing the group:
|
|
13
|
+
*
|
|
14
|
+
* purple asks a question Method
|
|
15
|
+
* orange makes it happen Class, Event, Enum, Value
|
|
16
|
+
* blue you stored it Variable, Field, Interface, EnumMember
|
|
17
|
+
* grey syntax, everything else all the rest
|
|
18
|
+
*
|
|
19
|
+
* Three facts shape the table and are easy to re-break:
|
|
20
|
+
*
|
|
21
|
+
* 1. **Codicon aliases collapse.** `symbol-method`, `symbol-function` and
|
|
22
|
+
* `symbol-constructor` are one codepoint, so they are one picture. Same for
|
|
23
|
+
* `symbol-enum`/`symbol-value`, `symbol-key`/`symbol-text`,
|
|
24
|
+
* `symbol-struct`/`symbol-structure`, `symbol-unit`/`symbol-ruler` and
|
|
25
|
+
* `symbol-type-parameter`/`symbol-parameter`. Check a proposed mapping
|
|
26
|
+
* against codepoints, not against the names. Prefer the canonical name of a
|
|
27
|
+
* pair: only it carries the `symbolIcon.*Foreground` rule, so a themed tree
|
|
28
|
+
* leaf tints and an alias does not.
|
|
29
|
+
* 2. **Only `CompletionItemKind` reaches the suggest widget.** 25 values,
|
|
30
|
+
* 22 distinct pictures after the collapse. A concept that appears in a
|
|
31
|
+
* completion list cannot use a glyph from outside that set in the list,
|
|
32
|
+
* even though the hover and the tree can draw all 461 codicons.
|
|
33
|
+
* 3. **Only `SymbolKind` reaches the outline.** Breadcrumbs, the outline,
|
|
34
|
+
* sticky scroll and Ctrl+T take an LSP `SymbolKind`, and VS Code draws
|
|
35
|
+
* member `X` with the codicon `symbol-<kebab X>`. `symbolKind` names the
|
|
36
|
+
* member drawing the same picture as `codicon`, so the breadcrumb bar and
|
|
37
|
+
* the hover badge cannot disagree; it is null for a picture no member
|
|
38
|
+
* draws. The server resolves the name to the numeric enum.
|
|
39
|
+
*
|
|
40
|
+
* `codicon`, `completionKind` and `symbolKind` are separate fields for exactly
|
|
41
|
+
* that reason. They name the same picture everywhere except two entries:
|
|
42
|
+
* `texture`, whose `file-media` glyph no completion kind can produce, and
|
|
43
|
+
* `list`, whose array glyph no *free* completion kind can produce (the colour
|
|
44
|
+
* has to stay blue, and all four blue kinds are taken), so the suggest widget
|
|
45
|
+
* alone still draws it as an enum member.
|
|
46
|
+
*
|
|
47
|
+
* Uniqueness is promised *within a completion list*, not globally: script, gui
|
|
48
|
+
* and datafunction completions never appear together, so they may share glyphs.
|
|
49
|
+
*
|
|
50
|
+
* No imports: this is shared by the server and the VS Code client.
|
|
51
|
+
*/
|
|
52
|
+
export interface KindStyle {
|
|
53
|
+
/** Codicon id, drawn in the hover badge and the tree. */
|
|
54
|
+
codicon: string;
|
|
55
|
+
/** `CompletionItemKind` member name; the server maps it to the enum. */
|
|
56
|
+
completionKind: string;
|
|
57
|
+
/**
|
|
58
|
+
* `SymbolKind` member name drawing the same picture as `codicon`, or null
|
|
59
|
+
* when no member draws it. The server maps it to the enum.
|
|
60
|
+
*/
|
|
61
|
+
symbolKind: string | null;
|
|
62
|
+
/** Hover badge colour as a `--vscode-symbolIcon-*` var, or null for none. */
|
|
63
|
+
color: string | null;
|
|
64
|
+
}
|
|
65
|
+
/** Anything the map does not name: a definition we have no opinion about. */
|
|
66
|
+
export declare const DEFAULT_KIND_STYLE: KindStyle;
|
|
67
|
+
/** Glyph, completion kind and badge colour for a kind name. Never throws. */
|
|
68
|
+
export declare function kindStyle(kind: string): KindStyle;
|
|
69
|
+
/** True when the map has an opinion, i.e. the kind is not falling through. */
|
|
70
|
+
export declare function hasKindStyle(kind: string): boolean;
|
|
71
|
+
/** Every mapped kind, for the coverage test that keeps this table honest. */
|
|
72
|
+
export declare function mappedKinds(): string[];
|
package/dist/kinds.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* One kind map, four surfaces.
|
|
4
|
+
*
|
|
5
|
+
* Every place the product names a concept - the hover badge, the completion
|
|
6
|
+
* list icon, the tree leaf, the breadcrumb/outline entry - reads its glyph from
|
|
7
|
+
* here, so a trigger looks like a trigger everywhere.
|
|
8
|
+
*
|
|
9
|
+
* The colour is not a second decision. VS Code paints a completion row from the
|
|
10
|
+
* `symbolIcon.*Foreground` token of the `CompletionItemKind` we send, and we
|
|
11
|
+
* cannot override it, so the kind IS the colour. The hover badge reuses that
|
|
12
|
+
* same token, which is why there is no colour column to keep in sync. Four
|
|
13
|
+
* groups come out of that, and choosing the kind is choosing the group:
|
|
14
|
+
*
|
|
15
|
+
* purple asks a question Method
|
|
16
|
+
* orange makes it happen Class, Event, Enum, Value
|
|
17
|
+
* blue you stored it Variable, Field, Interface, EnumMember
|
|
18
|
+
* grey syntax, everything else all the rest
|
|
19
|
+
*
|
|
20
|
+
* Three facts shape the table and are easy to re-break:
|
|
21
|
+
*
|
|
22
|
+
* 1. **Codicon aliases collapse.** `symbol-method`, `symbol-function` and
|
|
23
|
+
* `symbol-constructor` are one codepoint, so they are one picture. Same for
|
|
24
|
+
* `symbol-enum`/`symbol-value`, `symbol-key`/`symbol-text`,
|
|
25
|
+
* `symbol-struct`/`symbol-structure`, `symbol-unit`/`symbol-ruler` and
|
|
26
|
+
* `symbol-type-parameter`/`symbol-parameter`. Check a proposed mapping
|
|
27
|
+
* against codepoints, not against the names. Prefer the canonical name of a
|
|
28
|
+
* pair: only it carries the `symbolIcon.*Foreground` rule, so a themed tree
|
|
29
|
+
* leaf tints and an alias does not.
|
|
30
|
+
* 2. **Only `CompletionItemKind` reaches the suggest widget.** 25 values,
|
|
31
|
+
* 22 distinct pictures after the collapse. A concept that appears in a
|
|
32
|
+
* completion list cannot use a glyph from outside that set in the list,
|
|
33
|
+
* even though the hover and the tree can draw all 461 codicons.
|
|
34
|
+
* 3. **Only `SymbolKind` reaches the outline.** Breadcrumbs, the outline,
|
|
35
|
+
* sticky scroll and Ctrl+T take an LSP `SymbolKind`, and VS Code draws
|
|
36
|
+
* member `X` with the codicon `symbol-<kebab X>`. `symbolKind` names the
|
|
37
|
+
* member drawing the same picture as `codicon`, so the breadcrumb bar and
|
|
38
|
+
* the hover badge cannot disagree; it is null for a picture no member
|
|
39
|
+
* draws. The server resolves the name to the numeric enum.
|
|
40
|
+
*
|
|
41
|
+
* `codicon`, `completionKind` and `symbolKind` are separate fields for exactly
|
|
42
|
+
* that reason. They name the same picture everywhere except two entries:
|
|
43
|
+
* `texture`, whose `file-media` glyph no completion kind can produce, and
|
|
44
|
+
* `list`, whose array glyph no *free* completion kind can produce (the colour
|
|
45
|
+
* has to stay blue, and all four blue kinds are taken), so the suggest widget
|
|
46
|
+
* alone still draws it as an enum member.
|
|
47
|
+
*
|
|
48
|
+
* Uniqueness is promised *within a completion list*, not globally: script, gui
|
|
49
|
+
* and datafunction completions never appear together, so they may share glyphs.
|
|
50
|
+
*
|
|
51
|
+
* No imports: this is shared by the server and the VS Code client.
|
|
52
|
+
*/
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.DEFAULT_KIND_STYLE = void 0;
|
|
55
|
+
exports.kindStyle = kindStyle;
|
|
56
|
+
exports.hasKindStyle = hasKindStyle;
|
|
57
|
+
exports.mappedKinds = mappedKinds;
|
|
58
|
+
/**
|
|
59
|
+
* The `SymbolKind` member VS Code draws with each picture the table uses. VS
|
|
60
|
+
* Code renders member `X` as `symbol-<kebab X>`, so this is that rule read
|
|
61
|
+
* backwards, with the alias pairs resolved to the member owning the codepoint
|
|
62
|
+
* (`symbol-value` is `symbol-enum`, `symbol-text` is `symbol-key`). A codicon
|
|
63
|
+
* absent here has no `SymbolKind` at all: there are 26 members against 461
|
|
64
|
+
* codicons.
|
|
65
|
+
*/
|
|
66
|
+
const SYMBOL_KIND_BY_CODICON = {
|
|
67
|
+
"symbol-array": "Array",
|
|
68
|
+
"symbol-class": "Class",
|
|
69
|
+
"symbol-constant": "Constant",
|
|
70
|
+
"symbol-enum-member": "EnumMember",
|
|
71
|
+
"symbol-event": "Event",
|
|
72
|
+
"symbol-field": "Field",
|
|
73
|
+
"symbol-interface": "Interface",
|
|
74
|
+
"symbol-method": "Method",
|
|
75
|
+
"symbol-module": "Module",
|
|
76
|
+
"symbol-operator": "Operator",
|
|
77
|
+
"symbol-property": "Property",
|
|
78
|
+
"symbol-struct": "Struct",
|
|
79
|
+
"symbol-text": "Key",
|
|
80
|
+
"symbol-type-parameter": "TypeParameter",
|
|
81
|
+
"symbol-value": "Enum",
|
|
82
|
+
"symbol-variable": "Variable",
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The only completion kinds VS Code tints; the other 15 render in the plain
|
|
86
|
+
* editor foreground, so their badge emits no span at all.
|
|
87
|
+
*/
|
|
88
|
+
const TINT = {
|
|
89
|
+
Method: "method",
|
|
90
|
+
Function: "function",
|
|
91
|
+
Constructor: "constructor",
|
|
92
|
+
Class: "class",
|
|
93
|
+
Enum: "enumerator",
|
|
94
|
+
Value: "enumerator",
|
|
95
|
+
Event: "event",
|
|
96
|
+
Variable: "variable",
|
|
97
|
+
Field: "field",
|
|
98
|
+
Interface: "interface",
|
|
99
|
+
EnumMember: "enumeratorMember",
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* `colorFrom` defaults to the completion kind, which is what keeps the badge
|
|
103
|
+
* and the row the same colour. `on_action` is the one entry that overrides it:
|
|
104
|
+
* it wants the interface glyph with the orange of the group it belongs to, and
|
|
105
|
+
* a completion row cannot have both.
|
|
106
|
+
*/
|
|
107
|
+
const c = (codicon, completionKind, colorFrom = completionKind) => ({
|
|
108
|
+
codicon,
|
|
109
|
+
completionKind,
|
|
110
|
+
symbolKind: SYMBOL_KIND_BY_CODICON[codicon] ?? null,
|
|
111
|
+
color: TINT[colorFrom] ? `var(--vscode-symbolIcon-${TINT[colorFrom]}Foreground)` : null,
|
|
112
|
+
});
|
|
113
|
+
const SCRIPT = {
|
|
114
|
+
// purple: asks a question.
|
|
115
|
+
trigger: c("symbol-method", "Method"),
|
|
116
|
+
scripted_trigger: c("symbol-method", "Method"),
|
|
117
|
+
datafn: c("symbol-method", "Method"),
|
|
118
|
+
// orange: makes it happen.
|
|
119
|
+
effect: c("symbol-event", "Event"),
|
|
120
|
+
scripted_effect: c("symbol-event", "Event"),
|
|
121
|
+
event: c("symbol-class", "Class"),
|
|
122
|
+
decision: c("symbol-class", "Class"),
|
|
123
|
+
gui_type: c("symbol-class", "Class"),
|
|
124
|
+
data_type: c("symbol-class", "Class"),
|
|
125
|
+
on_action: c("symbol-interface", "Interface", "Class"),
|
|
126
|
+
trait: c("symbol-value", "Value"),
|
|
127
|
+
// blue: you stored it. A name that resolves to a scope or a stored value.
|
|
128
|
+
variable: c("symbol-variable", "Variable"),
|
|
129
|
+
local_variable: c("symbol-variable", "Variable"),
|
|
130
|
+
global_variable: c("symbol-variable", "Variable"),
|
|
131
|
+
promote: c("symbol-variable", "Variable"),
|
|
132
|
+
saved_scope: c("symbol-field", "Field"),
|
|
133
|
+
event_target: c("symbol-interface", "Interface"),
|
|
134
|
+
// The four list kinds each get their own picture. `add_to_list` builds a
|
|
135
|
+
// collection that lives for one effect block and is never saved, so it takes
|
|
136
|
+
// the array picture; the three `*_variable_list` kinds are entries in
|
|
137
|
+
// variable storage, split by storage class: the object-attached one keeps
|
|
138
|
+
// the enum-member picture, the event-chain-local one the plain list, the
|
|
139
|
+
// game-global one the globe.
|
|
140
|
+
// All four stay on `EnumMember`: the four blue completion kinds are already
|
|
141
|
+
// spoken for by variable, saved_scope and event_target, so the suggest widget
|
|
142
|
+
// draws every list as one blue enum-member row; the split shows in the hover
|
|
143
|
+
// badge and the tree. Of the four pictures only `symbol-enum-member` carries
|
|
144
|
+
// a `symbolIcon` colour rule, so the other three render tree leaves in the
|
|
145
|
+
// plain icon foreground while their badges stay blue (the map emits the
|
|
146
|
+
// colour); `list-unordered` and `globe` are pictures no SymbolKind draws, so
|
|
147
|
+
// those two fall back to Object in symbol lists.
|
|
148
|
+
list: c("symbol-array", "EnumMember"),
|
|
149
|
+
variable_list: c("symbol-enum-member", "EnumMember"),
|
|
150
|
+
local_variable_list: c("list-unordered", "EnumMember"),
|
|
151
|
+
global_variable_list: c("globe", "EnumMember"),
|
|
152
|
+
// grey: syntax and everything else.
|
|
153
|
+
scope_word: c("symbol-constant", "Constant"),
|
|
154
|
+
structure_key: c("symbol-struct", "Struct"),
|
|
155
|
+
descriptor_field: c("symbol-struct", "Struct"),
|
|
156
|
+
keyword: c("symbol-keyword", "Keyword"),
|
|
157
|
+
modifier: c("symbol-property", "Property"),
|
|
158
|
+
scripted_modifier: c("symbol-property", "Property"),
|
|
159
|
+
gui_property: c("symbol-property", "Property"),
|
|
160
|
+
script_value: c("symbol-operator", "Operator"),
|
|
161
|
+
define: c("symbol-unit", "Unit"),
|
|
162
|
+
namespace: c("symbol-module", "Module"),
|
|
163
|
+
loc_key: c("symbol-text", "Text"),
|
|
164
|
+
macro_param: c("symbol-type-parameter", "TypeParameter"),
|
|
165
|
+
text_format: c("symbol-color", "Color"),
|
|
166
|
+
gui_enum_value: c("symbol-constant", "Constant"),
|
|
167
|
+
format_suffix: c("symbol-constant", "Constant"),
|
|
168
|
+
gui_template: c("symbol-snippet", "Snippet"),
|
|
169
|
+
// The picture-frame glyph no completion kind can draw: the hover and the tree
|
|
170
|
+
// get `file-media`, the completion row falls back to the plain file glyph.
|
|
171
|
+
texture: c("file-media", "File"),
|
|
172
|
+
};
|
|
173
|
+
/** Anything the map does not name: a definition we have no opinion about. */
|
|
174
|
+
exports.DEFAULT_KIND_STYLE = c("go-to-file", "Reference");
|
|
175
|
+
/** Glyph, completion kind and badge colour for a kind name. Never throws. */
|
|
176
|
+
function kindStyle(kind) {
|
|
177
|
+
return SCRIPT[kind] ?? exports.DEFAULT_KIND_STYLE;
|
|
178
|
+
}
|
|
179
|
+
/** True when the map has an opinion, i.e. the kind is not falling through. */
|
|
180
|
+
function hasKindStyle(kind) {
|
|
181
|
+
return Object.prototype.hasOwnProperty.call(SCRIPT, kind);
|
|
182
|
+
}
|
|
183
|
+
/** Every mapped kind, for the coverage test that keeps this table honest. */
|
|
184
|
+
function mappedKinds() {
|
|
185
|
+
return Object.keys(SCRIPT);
|
|
186
|
+
}
|