@spyglassmc/core 0.4.0 → 0.4.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/lib/common/Dev.js +5 -2
- package/lib/common/Operations.js +7 -3
- package/lib/common/ReadonlyProxy.js +3 -1
- package/lib/common/StateProxy.js +18 -7
- package/lib/common/externals/BrowserExternals.js +2 -9
- package/lib/common/externals/NodeJsExternals.js +7 -17
- package/lib/common/externals/index.d.ts +0 -3
- package/lib/common/util.d.ts +1 -0
- package/lib/common/util.js +14 -10
- package/lib/node/AstNode.js +6 -4
- package/lib/node/FileNode.js +6 -1
- package/lib/node/ResourceLocationNode.d.ts +2 -2
- package/lib/node/ResourceLocationNode.js +11 -5
- package/lib/parser/boolean.js +1 -1
- package/lib/parser/comment.d.ts +1 -1
- package/lib/parser/comment.js +1 -1
- package/lib/parser/float.js +2 -1
- package/lib/parser/integer.js +2 -1
- package/lib/parser/list.d.ts +1 -1
- package/lib/parser/list.js +3 -3
- package/lib/parser/long.js +2 -1
- package/lib/parser/record.d.ts +1 -1
- package/lib/parser/record.js +18 -8
- package/lib/parser/resourceLocation.js +61 -8
- package/lib/parser/string.js +75 -7
- package/lib/parser/util.js +7 -3
- package/lib/processor/ColorInfoProvider.js +20 -7
- package/lib/processor/binder/builtin.js +27 -17
- package/lib/processor/checker/builtin.d.ts +1 -2
- package/lib/processor/checker/builtin.js +10 -12
- package/lib/processor/colorizer/builtin.js +8 -7
- package/lib/processor/completer/Completer.js +4 -2
- package/lib/processor/completer/builtin.js +26 -23
- package/lib/processor/formatter/builtin.js +14 -12
- package/lib/processor/linter/builtin/undeclaredSymbol.js +47 -24
- package/lib/processor/linter/builtin.js +7 -8
- package/lib/service/CacheService.js +9 -6
- package/lib/service/Config.d.ts +2 -2
- package/lib/service/Config.js +23 -19
- package/lib/service/Downloader.js +12 -7
- package/lib/service/FileService.js +22 -8
- package/lib/service/MetaRegistry.js +7 -6
- package/lib/service/Profiler.js +10 -5
- package/lib/service/Project.js +36 -30
- package/lib/service/Service.js +19 -9
- package/lib/service/fileUtil.js +2 -1
- package/lib/source/IndexMap.js +1 -1
- package/lib/source/LanguageError.js +1 -1
- package/lib/source/Location.js +4 -1
- package/lib/source/Range.js +6 -3
- package/lib/source/Source.js +3 -1
- package/lib/symbol/Symbol.d.ts +7 -7
- package/lib/symbol/Symbol.js +22 -9
- package/lib/symbol/SymbolUtil.d.ts +2 -2
- package/lib/symbol/SymbolUtil.js +74 -43
- package/package.json +2 -2
package/lib/parser/string.js
CHANGED
|
@@ -22,7 +22,9 @@ export function string(options) {
|
|
|
22
22
|
const cStart = src.cursor;
|
|
23
23
|
src.skip();
|
|
24
24
|
const c2 = src.read();
|
|
25
|
-
if (c2 === '\\' ||
|
|
25
|
+
if (c2 === '\\' ||
|
|
26
|
+
c2 === currentQuote ||
|
|
27
|
+
EscapeChar.is(options.escapable.characters, c2)) {
|
|
26
28
|
ans.valueMap.push({
|
|
27
29
|
inner: Range.create(ans.value.length, ans.value.length + 1),
|
|
28
30
|
outer: Range.create(cStart, src),
|
|
@@ -73,7 +75,8 @@ export function string(options) {
|
|
|
73
75
|
start = contentStart;
|
|
74
76
|
}
|
|
75
77
|
else if (options.unquotable) {
|
|
76
|
-
while (src.canRead() &&
|
|
78
|
+
while (src.canRead() &&
|
|
79
|
+
isAllowedCharacter(src.peek(), options.unquotable)) {
|
|
77
80
|
ans.value += src.read();
|
|
78
81
|
}
|
|
79
82
|
if (!ans.value && !options.unquotable.allowEmpty) {
|
|
@@ -105,14 +108,79 @@ export function parseStringValue(parser, value, map, ctx) {
|
|
|
105
108
|
return parser(valueSrc, valueCtx);
|
|
106
109
|
}
|
|
107
110
|
export const BrigadierUnquotableCharacters = Object.freeze([
|
|
108
|
-
'0',
|
|
109
|
-
'
|
|
110
|
-
'
|
|
111
|
-
'
|
|
111
|
+
'0',
|
|
112
|
+
'1',
|
|
113
|
+
'2',
|
|
114
|
+
'3',
|
|
115
|
+
'4',
|
|
116
|
+
'5',
|
|
117
|
+
'6',
|
|
118
|
+
'7',
|
|
119
|
+
'8',
|
|
120
|
+
'9',
|
|
121
|
+
'A',
|
|
122
|
+
'B',
|
|
123
|
+
'C',
|
|
124
|
+
'D',
|
|
125
|
+
'E',
|
|
126
|
+
'F',
|
|
127
|
+
'G',
|
|
128
|
+
'H',
|
|
129
|
+
'I',
|
|
130
|
+
'J',
|
|
131
|
+
'K',
|
|
132
|
+
'L',
|
|
133
|
+
'M',
|
|
134
|
+
'N',
|
|
135
|
+
'O',
|
|
136
|
+
'P',
|
|
137
|
+
'Q',
|
|
138
|
+
'R',
|
|
139
|
+
'S',
|
|
140
|
+
'T',
|
|
141
|
+
'U',
|
|
142
|
+
'V',
|
|
143
|
+
'W',
|
|
144
|
+
'X',
|
|
145
|
+
'Y',
|
|
146
|
+
'Z',
|
|
147
|
+
'a',
|
|
148
|
+
'b',
|
|
149
|
+
'c',
|
|
150
|
+
'd',
|
|
151
|
+
'e',
|
|
152
|
+
'f',
|
|
153
|
+
'g',
|
|
154
|
+
'h',
|
|
155
|
+
'i',
|
|
156
|
+
'j',
|
|
157
|
+
'k',
|
|
158
|
+
'l',
|
|
159
|
+
'm',
|
|
160
|
+
'n',
|
|
161
|
+
'o',
|
|
162
|
+
'p',
|
|
163
|
+
'q',
|
|
164
|
+
'r',
|
|
165
|
+
's',
|
|
166
|
+
't',
|
|
167
|
+
'u',
|
|
168
|
+
'v',
|
|
169
|
+
'w',
|
|
170
|
+
'x',
|
|
171
|
+
'y',
|
|
172
|
+
'z',
|
|
173
|
+
'_',
|
|
174
|
+
'.',
|
|
175
|
+
'+',
|
|
176
|
+
'-',
|
|
112
177
|
]);
|
|
113
178
|
export const BrigadierUnquotableCharacterSet = new Set(BrigadierUnquotableCharacters);
|
|
114
179
|
export const BrigadierUnquotablePattern = /^[0-9A-Za-z_\.\+\-]*$/;
|
|
115
|
-
export const BrigadierUnquotableOption = {
|
|
180
|
+
export const BrigadierUnquotableOption = {
|
|
181
|
+
allowEmpty: true,
|
|
182
|
+
allowList: BrigadierUnquotableCharacterSet,
|
|
183
|
+
};
|
|
116
184
|
export const BrigadierStringOptions = {
|
|
117
185
|
escapable: {},
|
|
118
186
|
quotes: ['"', "'"],
|
package/lib/parser/util.js
CHANGED
|
@@ -84,7 +84,8 @@ export function any(parsers, out) {
|
|
|
84
84
|
const results = parsers
|
|
85
85
|
.map((parser, i) => ({ attempt: attempt(parser, src, ctx), index: i }))
|
|
86
86
|
.filter(({ attempt }) => attempt.result !== Failure)
|
|
87
|
-
.sort((a, b) =>
|
|
87
|
+
.sort((a, b) => b.attempt.endCursor - a.attempt.endCursor ||
|
|
88
|
+
a.attempt.errorAmount - b.attempt.errorAmount);
|
|
88
89
|
if (results.length === 0) {
|
|
89
90
|
if (out) {
|
|
90
91
|
out.index = -1;
|
|
@@ -151,7 +152,10 @@ export function recover(parser, defaultValue) {
|
|
|
151
152
|
export function select(cases) {
|
|
152
153
|
return (src, ctx) => {
|
|
153
154
|
for (const { predicate, prefix, parser, regex } of cases) {
|
|
154
|
-
if (predicate?.(src) ??
|
|
155
|
+
if (predicate?.(src) ??
|
|
156
|
+
(prefix !== undefined ? src.tryPeek(prefix) : undefined) ??
|
|
157
|
+
(regex && src.matchPattern(regex)) ??
|
|
158
|
+
true) {
|
|
155
159
|
const callableParser = typeof parser === 'object' ? parser.get() : parser;
|
|
156
160
|
return callableParser(src, ctx);
|
|
157
161
|
}
|
|
@@ -170,7 +174,7 @@ export function map(parser, fn) {
|
|
|
170
174
|
};
|
|
171
175
|
}
|
|
172
176
|
export function setType(type, parser) {
|
|
173
|
-
return map(parser, res => {
|
|
177
|
+
return map(parser, (res) => {
|
|
174
178
|
const { type: _type, ...restResult } = res;
|
|
175
179
|
const ans = {
|
|
176
180
|
type,
|
|
@@ -119,19 +119,32 @@ export var ColorPresentation;
|
|
|
119
119
|
const round = (num) => parseFloat(num.toFixed(3));
|
|
120
120
|
switch (format) {
|
|
121
121
|
case ColorFormat.DecRGBA:
|
|
122
|
-
return color.map(c => round(c)).join(' ');
|
|
122
|
+
return color.map((c) => round(c)).join(' ');
|
|
123
123
|
case ColorFormat.DecRGB:
|
|
124
|
-
return color
|
|
124
|
+
return color
|
|
125
|
+
.slice(0, 3)
|
|
126
|
+
.map((c) => round(c))
|
|
127
|
+
.join(' ');
|
|
125
128
|
case ColorFormat.IntRGBA:
|
|
126
|
-
return color.map(c => Math.round(c * 255)).join(' ');
|
|
129
|
+
return color.map((c) => Math.round(c * 255)).join(' ');
|
|
127
130
|
case ColorFormat.IntRGB:
|
|
128
|
-
return color
|
|
131
|
+
return color
|
|
132
|
+
.slice(0, 3)
|
|
133
|
+
.map((c) => Math.round(c * 255))
|
|
134
|
+
.join(' ');
|
|
129
135
|
case ColorFormat.HexRGBA:
|
|
130
|
-
return `#${Math.round((color[0] * 255 << 24) +
|
|
136
|
+
return `#${Math.round((((color[0] * 255) << 24) +
|
|
137
|
+
((color[1] * 255) << 16) +
|
|
138
|
+
color[2] * 255) <<
|
|
139
|
+
(8 + color[3] * 255))
|
|
140
|
+
.toString(16)
|
|
141
|
+
.padStart(8, '0')}`;
|
|
131
142
|
case ColorFormat.HexRGB:
|
|
132
|
-
return `#${Math.round((color[0] * 255 << 16) + (color[1] * 255 << 8) + color[2] * 255)
|
|
143
|
+
return `#${Math.round(((color[0] * 255) << 16) + ((color[1] * 255) << 8) + color[2] * 255)
|
|
144
|
+
.toString(16)
|
|
145
|
+
.padStart(6, '0')}`;
|
|
133
146
|
case ColorFormat.CompositeInt:
|
|
134
|
-
return `${Math.round((color[0] * 255 << 16) + (color[1] * 255 << 8) + color[2] * 255)}`;
|
|
147
|
+
return `${Math.round(((color[0] * 255) << 16) + ((color[1] * 255) << 8) + color[2] * 255)}`;
|
|
135
148
|
}
|
|
136
149
|
}
|
|
137
150
|
})(ColorPresentation || (ColorPresentation = {}));
|
|
@@ -13,7 +13,7 @@ export function attempt(binder, node, ctx) {
|
|
|
13
13
|
const processAfterBinder = () => {
|
|
14
14
|
StateProxy.undoChanges(node);
|
|
15
15
|
const totalErrorSpan = tempCtx.err.errors
|
|
16
|
-
.map(e => e.range.end - e.range.start)
|
|
16
|
+
.map((e) => e.range.end - e.range.start)
|
|
17
17
|
.reduce((a, b) => a + b, 0);
|
|
18
18
|
return {
|
|
19
19
|
errorAmount: tempCtx.err.errors.length,
|
|
@@ -44,15 +44,14 @@ export function any(binders) {
|
|
|
44
44
|
if (binders.every(SyncBinder.is)) {
|
|
45
45
|
return SyncBinder.create((node, ctx) => {
|
|
46
46
|
const attempts = binders
|
|
47
|
-
.map(binder => attempt(binder, node, ctx))
|
|
47
|
+
.map((binder) => attempt(binder, node, ctx))
|
|
48
48
|
.sort(attemptSorter);
|
|
49
49
|
attempts[0].updateNodeAndCtx();
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
else {
|
|
53
53
|
return AsyncBinder.create(async (node, ctx) => {
|
|
54
|
-
const attempts = (await Promise.all(binders.map(binder => attempt(binder, node, ctx))))
|
|
55
|
-
.sort(attemptSorter);
|
|
54
|
+
const attempts = (await Promise.all(binders.map((binder) => attempt(binder, node, ctx)))).sort(attemptSorter);
|
|
56
55
|
attempts[0].updateNodeAndCtx();
|
|
57
56
|
});
|
|
58
57
|
}
|
|
@@ -66,7 +65,7 @@ export const noop = SyncBinder.create(() => { });
|
|
|
66
65
|
*/
|
|
67
66
|
export const fallback = AsyncBinder.create(async (node, ctx) => {
|
|
68
67
|
const promises = [];
|
|
69
|
-
traversePreOrder(node, node => !ctx.meta.hasBinder(node.type), node => ctx.meta.hasBinder(node.type), node => {
|
|
68
|
+
traversePreOrder(node, (node) => !ctx.meta.hasBinder(node.type), (node) => ctx.meta.hasBinder(node.type), (node) => {
|
|
70
69
|
const binder = ctx.meta.getBinder(node.type);
|
|
71
70
|
const result = binder(node, ctx);
|
|
72
71
|
if (result instanceof Promise) {
|
|
@@ -84,18 +83,23 @@ export const dispatchSync = SyncBinder.create((node, ctx) => {
|
|
|
84
83
|
}
|
|
85
84
|
});
|
|
86
85
|
export const resourceLocation = SyncBinder.create((node, ctx) => {
|
|
86
|
+
const raw = ResourceLocationNode.toString(node, 'full');
|
|
87
|
+
const sanitizedRaw = ResourceLocation.lengthen(node.options.namespacePathSep === '.'
|
|
88
|
+
? raw.replace(/\./g, ResourceLocation.NamespacePathSep)
|
|
89
|
+
: raw);
|
|
87
90
|
if (node.options.category) {
|
|
88
|
-
const raw = ResourceLocationNode.toString(node, 'full');
|
|
89
|
-
const sanitizedRaw = ResourceLocation.lengthen(node.options.namespacePathSep === '.'
|
|
90
|
-
? raw.replace('.', ResourceLocation.NamespacePathSep)
|
|
91
|
-
: raw);
|
|
92
91
|
ctx.symbols
|
|
93
92
|
.query(ctx.doc, node.isTag ? `tag/${node.options.category}` : node.options.category, sanitizedRaw)
|
|
94
|
-
.enter({
|
|
93
|
+
.enter({
|
|
94
|
+
usage: {
|
|
95
|
+
type: node.options.usageType,
|
|
96
|
+
node,
|
|
97
|
+
accessType: node.options.accessType,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
95
100
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (!node.options.pool.includes(full)) {
|
|
101
|
+
if (node.options.pool && !node.options.allowUnknown) {
|
|
102
|
+
if (!node.options.pool.includes(sanitizedRaw)) {
|
|
99
103
|
ctx.err.report(localize('expected', node.options.pool), node, 3 /* ErrorSeverity.Error */);
|
|
100
104
|
}
|
|
101
105
|
return;
|
|
@@ -103,10 +107,16 @@ export const resourceLocation = SyncBinder.create((node, ctx) => {
|
|
|
103
107
|
});
|
|
104
108
|
export const symbol = SyncBinder.create((node, ctx) => {
|
|
105
109
|
if (node.value) {
|
|
106
|
-
const path = node.options.parentPath
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
const path = node.options.parentPath
|
|
111
|
+
? [...node.options.parentPath, node.value]
|
|
112
|
+
: [node.value];
|
|
113
|
+
ctx.symbols.query(ctx.doc, node.options.category, ...path).enter({
|
|
114
|
+
usage: {
|
|
115
|
+
type: node.options.usageType,
|
|
116
|
+
node: node,
|
|
117
|
+
accessType: node.options.accessType,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
110
120
|
}
|
|
111
121
|
});
|
|
112
122
|
export function registerBinders(meta) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { AstNode, SymbolBaseNode } from '../../node/index.js';
|
|
2
|
-
import { ResourceLocationNode } from '../../node/index.js';
|
|
1
|
+
import type { AstNode, ResourceLocationNode, SymbolBaseNode } from '../../node/index.js';
|
|
3
2
|
import type { CheckerContext, MetaRegistry } from '../../service/index.js';
|
|
4
3
|
import type { Checker, SyncChecker } from './Checker.js';
|
|
5
4
|
export declare type AttemptResult = {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { localize } from '@spyglassmc/locales';
|
|
2
1
|
import { StateProxy } from '../../common/index.js';
|
|
3
|
-
import { ResourceLocationNode } from '../../node/index.js';
|
|
4
2
|
import { ErrorReporter } from '../../service/index.js';
|
|
5
3
|
import { traversePreOrder } from '../util.js';
|
|
6
4
|
export function attempt(checker, node, ctx) {
|
|
@@ -13,7 +11,7 @@ export function attempt(checker, node, ctx) {
|
|
|
13
11
|
checker(node, tempCtx);
|
|
14
12
|
StateProxy.undoChanges(node);
|
|
15
13
|
const totalErrorSpan = tempCtx.err.errors
|
|
16
|
-
.map(e => e.range.end - e.range.start)
|
|
14
|
+
.map((e) => e.range.end - e.range.start)
|
|
17
15
|
.reduce((a, b) => a + b, 0);
|
|
18
16
|
return {
|
|
19
17
|
errorAmount: tempCtx.err.errors.length,
|
|
@@ -31,7 +29,7 @@ export function any(checkers) {
|
|
|
31
29
|
}
|
|
32
30
|
return (node, ctx) => {
|
|
33
31
|
const attempts = checkers
|
|
34
|
-
.map(checker => attempt(checker, node, ctx))
|
|
32
|
+
.map((checker) => attempt(checker, node, ctx))
|
|
35
33
|
.sort((a, b) => a.errorAmount - b.errorAmount || a.totalErrorSpan - b.totalErrorSpan);
|
|
36
34
|
attempts[0].updateNodeAndCtx();
|
|
37
35
|
};
|
|
@@ -45,7 +43,7 @@ export const noop = () => { };
|
|
|
45
43
|
*/
|
|
46
44
|
export const fallback = async (node, ctx) => {
|
|
47
45
|
const promises = [];
|
|
48
|
-
traversePreOrder(node, node => !ctx.meta.hasChecker(node.type), node => ctx.meta.hasChecker(node.type), node => {
|
|
46
|
+
traversePreOrder(node, (node) => !ctx.meta.hasChecker(node.type), (node) => ctx.meta.hasChecker(node.type), (node) => {
|
|
49
47
|
const checker = ctx.meta.getChecker(node.type);
|
|
50
48
|
const result = checker(node, ctx);
|
|
51
49
|
if (result instanceof Promise) {
|
|
@@ -63,13 +61,13 @@ export const dispatchSync = (node, ctx) => {
|
|
|
63
61
|
}
|
|
64
62
|
};
|
|
65
63
|
export const resourceLocation = (node, ctx) => {
|
|
66
|
-
const full = ResourceLocationNode.toString(node, 'full')
|
|
67
|
-
if (node.options.pool) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
64
|
+
// const full = ResourceLocationNode.toString(node, 'full')
|
|
65
|
+
// if (node.options.pool) {
|
|
66
|
+
// if (!node.options.pool.includes(full)) {
|
|
67
|
+
// ctx.err.report(localize('expected', node.options.pool), node, ErrorSeverity.Error)
|
|
68
|
+
// }
|
|
69
|
+
// return
|
|
70
|
+
// }
|
|
73
71
|
};
|
|
74
72
|
export const symbol = (_node, _ctx) => {
|
|
75
73
|
// TODO
|
|
@@ -6,27 +6,28 @@ import { ColorToken } from './Colorizer.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export const fallback = (node, ctx) => {
|
|
8
8
|
const ans = [];
|
|
9
|
-
traversePreOrder(node, node => !ctx.meta.hasColorizer(node.type) &&
|
|
9
|
+
traversePreOrder(node, (node) => !ctx.meta.hasColorizer(node.type) &&
|
|
10
|
+
(!ctx.range || Range.intersects(node.range, ctx.range)), (node) => ctx.meta.hasColorizer(node.type), (node) => {
|
|
10
11
|
const colorizer = ctx.meta.getColorizer(node.type);
|
|
11
12
|
const result = colorizer(node, ctx);
|
|
12
13
|
ans.push(...result);
|
|
13
14
|
});
|
|
14
15
|
return Object.freeze(ans);
|
|
15
16
|
};
|
|
16
|
-
export const boolean = node => {
|
|
17
|
+
export const boolean = (node) => {
|
|
17
18
|
return [ColorToken.create(node, 'literal')];
|
|
18
19
|
};
|
|
19
|
-
export const comment = node => {
|
|
20
|
+
export const comment = (node) => {
|
|
20
21
|
return [ColorToken.create(node, 'comment')];
|
|
21
22
|
};
|
|
22
|
-
export const error = node => {
|
|
23
|
+
export const error = (node) => {
|
|
23
24
|
// return [ColorToken.create(node, 'error')]
|
|
24
25
|
return [];
|
|
25
26
|
};
|
|
26
|
-
export const literal = node => {
|
|
27
|
+
export const literal = (node) => {
|
|
27
28
|
return [ColorToken.create(node, node.options.colorTokenType ?? 'literal')];
|
|
28
29
|
};
|
|
29
|
-
export const number = node => {
|
|
30
|
+
export const number = (node) => {
|
|
30
31
|
return [ColorToken.create(node, 'number')];
|
|
31
32
|
};
|
|
32
33
|
export const resourceLocation = (node, _ctx) => {
|
|
@@ -53,7 +54,7 @@ export const string = (node, ctx) => {
|
|
|
53
54
|
return [ColorToken.create(node, node.options.colorTokenType ?? 'string')];
|
|
54
55
|
}
|
|
55
56
|
};
|
|
56
|
-
export const symbol = node => {
|
|
57
|
+
export const symbol = (node) => {
|
|
57
58
|
// TODO: Set the modifiers according to `node.symbol`.
|
|
58
59
|
return [ColorToken.create(node, 'variable')];
|
|
59
60
|
};
|
|
@@ -17,7 +17,7 @@ export var CompletionItem;
|
|
|
17
17
|
...other,
|
|
18
18
|
label,
|
|
19
19
|
range: Range.get(range),
|
|
20
|
-
...shouldEscape ? { insertText: escape(label) } : {},
|
|
20
|
+
...(shouldEscape ? { insertText: escape(label) } : {}),
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
CompletionItem.create = create;
|
|
@@ -51,7 +51,9 @@ export class InsertTextBuilder {
|
|
|
51
51
|
this.#ans += `$\{${this.#nextPlaceholder}:${CompletionItem.escape(defaultValues[0])}}`;
|
|
52
52
|
}
|
|
53
53
|
else {
|
|
54
|
-
this.#ans += `$\{${this.#nextPlaceholder}|${defaultValues
|
|
54
|
+
this.#ans += `$\{${this.#nextPlaceholder}|${defaultValues
|
|
55
|
+
.map((v) => v.replace(/([\\$},|])/g, '\\$1'))
|
|
56
|
+
.join(',')}|}`;
|
|
55
57
|
}
|
|
56
58
|
this.#nextPlaceholder += 1;
|
|
57
59
|
return this;
|
|
@@ -12,11 +12,9 @@ export const dispatch = (node, ctx) => {
|
|
|
12
12
|
node: node,
|
|
13
13
|
needle: ctx.offset,
|
|
14
14
|
endInclusive: true,
|
|
15
|
-
predicate: n => ctx.meta.hasCompleter(n.type),
|
|
15
|
+
predicate: (n) => ctx.meta.hasCompleter(n.type),
|
|
16
16
|
});
|
|
17
|
-
return child
|
|
18
|
-
? ctx.meta.getCompleter(child.type)(child, ctx)
|
|
19
|
-
: [];
|
|
17
|
+
return child ? ctx.meta.getCompleter(child.type)(child, ctx) : [];
|
|
20
18
|
};
|
|
21
19
|
export const fallback = dispatch;
|
|
22
20
|
export const boolean = (node, ctx) => {
|
|
@@ -32,7 +30,7 @@ export const file = (node, ctx) => {
|
|
|
32
30
|
const completer = ctx.meta.getCompleterForLanguageID(ctx.doc.languageId);
|
|
33
31
|
return completer(node.children[0], ctx);
|
|
34
32
|
};
|
|
35
|
-
export const literal = node => {
|
|
33
|
+
export const literal = (node) => {
|
|
36
34
|
const kind = new Map([
|
|
37
35
|
['enum', 13 /* CompletionKind.Enum */],
|
|
38
36
|
['enumMember', 20 /* CompletionKind.EnumMember */],
|
|
@@ -45,7 +43,7 @@ export const literal = node => {
|
|
|
45
43
|
['resourceLocation', 17 /* CompletionKind.File */],
|
|
46
44
|
['variable', 6 /* CompletionKind.Variable */],
|
|
47
45
|
]).get(node.options.colorTokenType ?? 'keyword') ?? 14 /* CompletionKind.Keyword */;
|
|
48
|
-
return node.options.pool.map(v => CompletionItem.create(v, node, { kind })) ?? [];
|
|
46
|
+
return (node.options.pool.map((v) => CompletionItem.create(v, node, { kind })) ?? []);
|
|
49
47
|
};
|
|
50
48
|
export const noop = () => [];
|
|
51
49
|
export function record(o) {
|
|
@@ -57,12 +55,12 @@ export function record(o) {
|
|
|
57
55
|
const completePairs = (pair) => o.key(node, pair, ctx, pair ?? ctx.offset, true, hasNextPair || !!pair?.end, existingKeys);
|
|
58
56
|
const existingKeys = node.children
|
|
59
57
|
.filter((n) => !!n.key)
|
|
60
|
-
.map(n => n.key);
|
|
58
|
+
.map((n) => n.key);
|
|
61
59
|
const index = binarySearch(node.children, ctx.offset, (n, o) => n.end
|
|
62
60
|
? Range.compareOffset(Range.translate(n, 0, -1), o, true)
|
|
63
61
|
: Range.compareOffset(n.range, o, true));
|
|
64
62
|
const pair = index >= 0 ? node.children[index] : undefined;
|
|
65
|
-
const hasNextPair = !!node.children.find(n => n.range.start > ctx.offset);
|
|
63
|
+
const hasNextPair = !!node.children.find((n) => n.range.start > ctx.offset);
|
|
66
64
|
if (!pair) {
|
|
67
65
|
return completePairs(undefined);
|
|
68
66
|
}
|
|
@@ -70,14 +68,18 @@ export function record(o) {
|
|
|
70
68
|
if (!key && !sep && !value) {
|
|
71
69
|
return completePairs(undefined);
|
|
72
70
|
}
|
|
73
|
-
if ((key && Range.contains(key, ctx.offset, true)) ||
|
|
71
|
+
if ((key && Range.contains(key, ctx.offset, true)) ||
|
|
72
|
+
(sep && ctx.offset <= sep.start) ||
|
|
73
|
+
(value && ctx.offset < value.range.start)) {
|
|
74
74
|
// Selected key.
|
|
75
75
|
if (!value || Range.isEmpty(value.range)) {
|
|
76
76
|
return completePairs(pair);
|
|
77
77
|
}
|
|
78
78
|
return completeKeys(pair);
|
|
79
79
|
}
|
|
80
|
-
if ((value && Range.contains(value, ctx.offset, true)) ||
|
|
80
|
+
if ((value && Range.contains(value, ctx.offset, true)) ||
|
|
81
|
+
(sep && ctx.offset >= sep.end) ||
|
|
82
|
+
(key && ctx.offset > key.range.end)) {
|
|
81
83
|
// Selected value.
|
|
82
84
|
return o.value(node, pair, ctx);
|
|
83
85
|
}
|
|
@@ -104,12 +106,16 @@ export const resourceLocation = (node, ctx) => {
|
|
|
104
106
|
}
|
|
105
107
|
const ans = [
|
|
106
108
|
...otherIds,
|
|
107
|
-
...includeDefaultNamespace ? defaultNsIds : [],
|
|
108
|
-
...excludeDefaultNamespace
|
|
109
|
-
|
|
109
|
+
...(includeDefaultNamespace ? defaultNsIds : []),
|
|
110
|
+
...(excludeDefaultNamespace
|
|
111
|
+
? defaultNsIds.map((id) => id.slice(defaultNsPrefix.length))
|
|
112
|
+
: []),
|
|
113
|
+
...(includeEmptyNamespace
|
|
114
|
+
? defaultNsIds.map((id) => id.slice(ResourceLocation.DefaultNamespace.length))
|
|
115
|
+
: []),
|
|
110
116
|
];
|
|
111
117
|
if (node.options.namespacePathSep === '.') {
|
|
112
|
-
return ans.map(v => v.replace(ResourceLocation.NamespacePathSep, '.'));
|
|
118
|
+
return ans.map((v) => v.replace(ResourceLocation.NamespacePathSep, '.'));
|
|
113
119
|
}
|
|
114
120
|
return ans;
|
|
115
121
|
};
|
|
@@ -117,12 +123,11 @@ export const resourceLocation = (node, ctx) => {
|
|
|
117
123
|
? optimizePool(node.options.pool)
|
|
118
124
|
: [
|
|
119
125
|
...getPool(node.options.category),
|
|
120
|
-
...node.options.allowTag
|
|
121
|
-
? getPool(`tag/${node.options.category}`)
|
|
122
|
-
|
|
123
|
-
: [],
|
|
126
|
+
...(node.options.allowTag
|
|
127
|
+
? getPool(`tag/${node.options.category}`).map((v) => `${ResourceLocation.TagPrefix}${v}`)
|
|
128
|
+
: []),
|
|
124
129
|
];
|
|
125
|
-
return pool.map(v => CompletionItem.create(v, node, { kind: 3 /* CompletionKind.Function */ }));
|
|
130
|
+
return pool.map((v) => CompletionItem.create(v, node, { kind: 3 /* CompletionKind.Function */ }));
|
|
126
131
|
};
|
|
127
132
|
export const string = (node, ctx) => {
|
|
128
133
|
if (node.children?.length) {
|
|
@@ -130,7 +135,7 @@ export const string = (node, ctx) => {
|
|
|
130
135
|
return dispatch(node.children[0], ctx);
|
|
131
136
|
}
|
|
132
137
|
if (node.options.quotes && node.value === '') {
|
|
133
|
-
return node.options.quotes.map(q => CompletionItem.create(`${q}${q}`, node, {
|
|
138
|
+
return node.options.quotes.map((q) => CompletionItem.create(`${q}${q}`, node, {
|
|
134
139
|
insertText: `${q}$1${q}`,
|
|
135
140
|
kind: 12 /* CompletionKind.Value */,
|
|
136
141
|
}));
|
|
@@ -138,9 +143,7 @@ export const string = (node, ctx) => {
|
|
|
138
143
|
return [];
|
|
139
144
|
};
|
|
140
145
|
export const symbol = (node, ctx) => {
|
|
141
|
-
return Object
|
|
142
|
-
.keys(ctx.symbols.query(ctx.doc, node.options.category, ...node.options.parentPath ?? []).visibleMembers)
|
|
143
|
-
.map(v => CompletionItem.create(v, node, { kind: 6 /* CompletionKind.Variable */ }));
|
|
146
|
+
return Object.keys(ctx.symbols.query(ctx.doc, node.options.category, ...(node.options.parentPath ?? [])).visibleMembers).map((v) => CompletionItem.create(v, node, { kind: 6 /* CompletionKind.Variable */ }));
|
|
144
147
|
};
|
|
145
148
|
export function registerCompleters(meta) {
|
|
146
149
|
meta.registerCompleter('boolean', boolean);
|
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
import { ResourceLocationNode } from '../../node/index.js';
|
|
2
|
-
export const fallback = node => {
|
|
2
|
+
export const fallback = (node) => {
|
|
3
3
|
throw new Error(`No formatter registered for type ${node.type}`);
|
|
4
4
|
};
|
|
5
5
|
export const file = (node, ctx) => {
|
|
6
|
-
return node.children
|
|
6
|
+
return node.children
|
|
7
|
+
.map((child) => {
|
|
7
8
|
return ctx.meta.getFormatter(child.type)(child, ctx);
|
|
8
|
-
})
|
|
9
|
+
})
|
|
10
|
+
.join('');
|
|
9
11
|
};
|
|
10
|
-
export const boolean = node => {
|
|
12
|
+
export const boolean = (node) => {
|
|
11
13
|
return node.value ? 'true' : 'false';
|
|
12
14
|
};
|
|
13
|
-
export const comment = node => {
|
|
15
|
+
export const comment = (node) => {
|
|
14
16
|
return '#' + node.comment;
|
|
15
17
|
};
|
|
16
|
-
export const float = node => {
|
|
18
|
+
export const float = (node) => {
|
|
17
19
|
return node.value.toString();
|
|
18
20
|
};
|
|
19
|
-
export const integer = node => {
|
|
21
|
+
export const integer = (node) => {
|
|
20
22
|
return node.value.toFixed();
|
|
21
23
|
};
|
|
22
|
-
export const literal = node => {
|
|
24
|
+
export const literal = (node) => {
|
|
23
25
|
return node.value;
|
|
24
26
|
};
|
|
25
|
-
export const long = node => {
|
|
27
|
+
export const long = (node) => {
|
|
26
28
|
return node.value.toString();
|
|
27
29
|
};
|
|
28
|
-
export const resourceLocation = node => {
|
|
29
|
-
return ResourceLocationNode.toString(node, 'origin');
|
|
30
|
+
export const resourceLocation = (node) => {
|
|
31
|
+
return ResourceLocationNode.toString(node, 'origin', true);
|
|
30
32
|
};
|
|
31
|
-
export const string = node => {
|
|
33
|
+
export const string = (node) => {
|
|
32
34
|
// FIXME: escape this value according to the node's IndexMap and context
|
|
33
35
|
return `"${node.value}"`;
|
|
34
36
|
};
|
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
2
1
|
import { Arrayable, ResourceLocation } from '../../../common/index.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { SymbolLinterConfig as Config } from '../../../service/index.js';
|
|
3
|
+
// import { localeQuote, localize } from '@spyglassmc/locales'
|
|
4
|
+
// import type { DeepReadonly } from '../../../common/index.js'
|
|
5
|
+
// import { Arrayable, ResourceLocation } from '../../../common/index.js'
|
|
6
|
+
// import type { AstNode } from '../../../node/index.js'
|
|
7
|
+
// import type { LinterContext } from '../../../service/index.js'
|
|
8
|
+
// import { LinterSeverity, SymbolLinterConfig as Config } from '../../../service/index.js'
|
|
9
|
+
// import type { Symbol } from '../../../symbol/index.js'
|
|
10
|
+
// import { SymbolUtil, SymbolVisibility } from '../../../symbol/index.js'
|
|
11
|
+
// import type { Linter } from '../Linter.js'
|
|
5
12
|
export const undeclaredSymbol = (node, ctx) => {
|
|
6
|
-
if (!node.symbol || SymbolUtil.isDeclared(node.symbol)) {
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
const action = getAction(ctx.ruleValue, node.symbol, ctx)
|
|
10
|
-
if (Config.Action.isDeclare(action)) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
if (Config.Action.isReport(action)) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
// if (!node.symbol || SymbolUtil.isDeclared(node.symbol)) {
|
|
14
|
+
// return
|
|
15
|
+
// }
|
|
16
|
+
// const action = getAction(ctx.ruleValue as Config, node.symbol, ctx)
|
|
17
|
+
// if (Config.Action.isDeclare(action)) {
|
|
18
|
+
// ctx.symbols
|
|
19
|
+
// .query({ doc: ctx.doc, node }, node.symbol.category, ...node.symbol.path)
|
|
20
|
+
// .amend({
|
|
21
|
+
// data: { visibility: getVisibility(action.declare) },
|
|
22
|
+
// usage: { type: 'declaration', node },
|
|
23
|
+
// })
|
|
24
|
+
// }
|
|
25
|
+
// if (Config.Action.isReport(action)) {
|
|
26
|
+
// const severityOverride = action.report === 'inherit' ? undefined : LinterSeverity.toErrorSeverity(action.report)
|
|
27
|
+
// ctx.err.lint(
|
|
28
|
+
// localize('linter.undeclared-symbol.message',
|
|
29
|
+
// node.symbol.category,
|
|
30
|
+
// localeQuote(node.symbol.identifier)
|
|
31
|
+
// ),
|
|
32
|
+
// node, undefined, severityOverride
|
|
33
|
+
// )
|
|
34
|
+
// }
|
|
22
35
|
};
|
|
23
36
|
function getAction(config, symbol, ctx) {
|
|
24
37
|
if (Config.Action.is(config)) {
|
|
@@ -28,11 +41,21 @@ function getAction(config, symbol, ctx) {
|
|
|
28
41
|
function testSingleCondition(condition) {
|
|
29
42
|
const resourceLocation = ResourceLocation.lengthen(symbol.identifier);
|
|
30
43
|
const namespace = resourceLocation.slice(0, resourceLocation.indexOf(ResourceLocation.NamespacePathSep));
|
|
31
|
-
return ((condition.category
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
(condition.
|
|
35
|
-
|
|
44
|
+
return ((condition.category
|
|
45
|
+
? Arrayable.toArray(condition.category).includes(symbol.category)
|
|
46
|
+
: true) &&
|
|
47
|
+
(condition.namespace
|
|
48
|
+
? Arrayable.toArray(condition.namespace).includes(namespace)
|
|
49
|
+
: true) &&
|
|
50
|
+
(condition.excludeNamespace
|
|
51
|
+
? !Arrayable.toArray(condition.excludeNamespace).includes(namespace)
|
|
52
|
+
: true) &&
|
|
53
|
+
(condition.pattern
|
|
54
|
+
? Arrayable.toArray(condition.pattern).some((p) => new RegExp(p).test(symbol.identifier))
|
|
55
|
+
: true) &&
|
|
56
|
+
(condition.excludePattern
|
|
57
|
+
? !Arrayable.toArray(condition.excludePattern).some((p) => new RegExp(p).test(symbol.identifier))
|
|
58
|
+
: true));
|
|
36
59
|
}
|
|
37
60
|
try {
|
|
38
61
|
return Arrayable.toArray(conditions).some(testSingleCondition);
|