@spyglassmc/java-edition 0.3.8 → 0.3.10
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/binder/index.d.ts +11 -9
- package/lib/binder/index.js +149 -150
- package/lib/common/index.js +6 -9
- package/lib/dependency/common.d.ts +5 -0
- package/lib/dependency/common.js +8 -0
- package/lib/dependency/index.js +7 -17
- package/lib/dependency/mcmeta.d.ts +6 -12
- package/lib/dependency/mcmeta.js +21 -38
- package/lib/index.d.ts +1 -0
- package/lib/index.js +74 -32
- package/lib/json/checker/index.d.ts +3 -10
- package/lib/json/checker/index.js +36 -244
- package/lib/json/index.d.ts +0 -1
- package/lib/json/index.js +0 -3
- package/lib/mcfunction/checker/index.d.ts +0 -2
- package/lib/mcfunction/checker/index.js +254 -183
- package/lib/mcfunction/common/index.d.ts +4 -2
- package/lib/mcfunction/common/index.js +56 -52
- package/lib/mcfunction/completer/argument.js +112 -57
- package/lib/mcfunction/index.d.ts +3 -2
- package/lib/mcfunction/index.js +18 -19
- package/lib/mcfunction/inlayHintProvider.js +2 -3
- package/lib/mcfunction/mcdocAttributes.d.ts +4 -0
- package/lib/mcfunction/mcdocAttributes.js +74 -0
- package/lib/mcfunction/node/argument.d.ts +115 -12
- package/lib/mcfunction/node/argument.js +131 -63
- package/lib/mcfunction/parser/argument.d.ts +14 -4
- package/lib/mcfunction/parser/argument.js +380 -212
- package/lib/mcfunction/signatureHelpProvider.d.ts +2 -1
- package/lib/mcfunction/signatureHelpProvider.js +10 -18
- package/lib/mcfunction/tree/argument.d.ts +68 -1
- package/lib/mcfunction/tree/patch.js +279 -77
- package/lib/mcfunction/tree/patchValidator.d.ts +7 -0
- package/lib/mcfunction/tree/patchValidator.js +25 -0
- package/package.json +8 -9
|
@@ -2,9 +2,11 @@ import { AstNode, BooleanNode, BrigadierStringOptions, completer, CompletionItem
|
|
|
2
2
|
import * as json from '@spyglassmc/json';
|
|
3
3
|
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
4
4
|
import { getTagValues } from '../../common/index.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
5
|
+
import { ReleaseVersion } from '../../dependency/common.js';
|
|
6
|
+
import { ColorArgumentValues, EntityAnchorArgumentValues, GamemodeArgumentValues, getItemSlotArgumentValues, getItemSlotsArgumentValues, getScoreboardSlotArgumentValues, HeightmapValues, MirrorValues, OperationArgumentValues, RotationValues, SwizzleArgumentValues, } from '../common/index.js';
|
|
7
|
+
import { BlockNode, ComponentTestExactNode, ComponentTestSubpredicateNode, CoordinateNode, EntitySelectorAtVariable, EntitySelectorNode, IntRangeNode, ItemPredicateNode, ItemStackNode, ObjectiveCriteriaNode, ParticleNode, ScoreHolderNode, VectorNode, } from '../node/index.js';
|
|
8
|
+
export const getMockNodes = (rawTreeNode, ctx) => {
|
|
9
|
+
const range = ctx.offset;
|
|
8
10
|
const treeNode = rawTreeNode;
|
|
9
11
|
switch (treeNode.parser) {
|
|
10
12
|
case 'brigadier:bool':
|
|
@@ -44,7 +46,9 @@ export const getMockNodes = (rawTreeNode, range) => {
|
|
|
44
46
|
return ResourceLocationNode.mock(range, { category: 'dimension' });
|
|
45
47
|
case 'minecraft:entity':
|
|
46
48
|
case 'minecraft:game_profile':
|
|
47
|
-
return EntitySelectorNode.mock(range
|
|
49
|
+
return EntitySelectorNode.mock(range, {
|
|
50
|
+
pool: EntitySelectorAtVariable.filterAvailable(ctx),
|
|
51
|
+
});
|
|
48
52
|
case 'minecraft:heightmap':
|
|
49
53
|
return LiteralNode.mock(range, { pool: HeightmapValues });
|
|
50
54
|
case 'minecraft:entity_anchor':
|
|
@@ -60,11 +64,19 @@ export const getMockNodes = (rawTreeNode, range) => {
|
|
|
60
64
|
case 'minecraft:item_enchantment':
|
|
61
65
|
return ResourceLocationNode.mock(range, { category: 'enchantment' });
|
|
62
66
|
case 'minecraft:item_predicate':
|
|
63
|
-
return
|
|
67
|
+
return ItemPredicateNode.mock(range);
|
|
64
68
|
case 'minecraft:item_slot':
|
|
65
|
-
return LiteralNode.mock(range, { pool:
|
|
69
|
+
return LiteralNode.mock(range, { pool: getItemSlotArgumentValues(ctx) });
|
|
70
|
+
case 'minecraft:item_slots':
|
|
71
|
+
return LiteralNode.mock(range, { pool: getItemSlotsArgumentValues(ctx) });
|
|
66
72
|
case 'minecraft:item_stack':
|
|
67
|
-
return
|
|
73
|
+
return ItemStackNode.mock(range);
|
|
74
|
+
case 'minecraft:loot_modifier':
|
|
75
|
+
return ResourceLocationNode.mock(range, { category: 'item_modifier' });
|
|
76
|
+
case 'minecraft:loot_predicate':
|
|
77
|
+
return ResourceLocationNode.mock(range, { category: 'predicate' });
|
|
78
|
+
case 'minecraft:loot_table':
|
|
79
|
+
return ResourceLocationNode.mock(range, { category: 'loot_table' });
|
|
68
80
|
case 'minecraft:mob_effect':
|
|
69
81
|
return ResourceLocationNode.mock(range, { category: 'mob_effect' });
|
|
70
82
|
case 'minecraft:objective':
|
|
@@ -81,18 +93,23 @@ export const getMockNodes = (rawTreeNode, range) => {
|
|
|
81
93
|
case 'minecraft:resource':
|
|
82
94
|
case 'minecraft:resource_key':
|
|
83
95
|
case 'minecraft:resource_or_tag':
|
|
96
|
+
case 'minecraft:resource_or_tag_key':
|
|
97
|
+
const allowTag = treeNode.parser === 'minecraft:resource_or_tag'
|
|
98
|
+
|| treeNode.parser === 'minecraft:resource_or_tag_key';
|
|
84
99
|
return ResourceLocationNode.mock(range, {
|
|
85
100
|
category: ResourceLocation.shorten(treeNode.properties.registry),
|
|
86
|
-
allowTag
|
|
101
|
+
allowTag,
|
|
87
102
|
});
|
|
88
103
|
case 'minecraft:resource_location':
|
|
89
104
|
return ResourceLocationNode.mock(range, treeNode.properties ?? { pool: [], allowUnknown: true });
|
|
90
105
|
case 'minecraft:rotation':
|
|
91
106
|
return VectorNode.mock(range, { dimension: 2, noLocal: true });
|
|
92
107
|
case 'minecraft:scoreboard_slot':
|
|
93
|
-
return LiteralNode.mock(range, { pool:
|
|
108
|
+
return LiteralNode.mock(range, { pool: getScoreboardSlotArgumentValues(ctx) });
|
|
94
109
|
case 'minecraft:score_holder':
|
|
95
110
|
return ScoreHolderNode.mock(range);
|
|
111
|
+
case 'minecraft:style':
|
|
112
|
+
return json.JsonObjectNode.mock(range);
|
|
96
113
|
case 'minecraft:swizzle':
|
|
97
114
|
return LiteralNode.mock(range, { pool: SwizzleArgumentValues });
|
|
98
115
|
case 'minecraft:team':
|
|
@@ -121,10 +138,12 @@ const block = (node, ctx) => {
|
|
|
121
138
|
if (Range.contains(node.id, ctx.offset, true)) {
|
|
122
139
|
ans.push(...completer.resourceLocation(node.id, ctx));
|
|
123
140
|
}
|
|
124
|
-
if (node.states &&
|
|
125
|
-
Range.contains(Range.translate(node.states, 1, -1), ctx.offset, true)) {
|
|
141
|
+
if (node.states && Range.contains(Range.translate(node.states, 1, -1), ctx.offset, true)) {
|
|
126
142
|
ans.push(...blockStates(node.states, ctx));
|
|
127
143
|
}
|
|
144
|
+
if (node.nbt && Range.contains(Range.translate(node.nbt, 1, -1), ctx.offset, true)) {
|
|
145
|
+
ans.push(...completer.dispatch(node.nbt, ctx));
|
|
146
|
+
}
|
|
128
147
|
return ans;
|
|
129
148
|
};
|
|
130
149
|
const blockStates = (node, ctx) => {
|
|
@@ -137,51 +156,90 @@ const blockStates = (node, ctx) => {
|
|
|
137
156
|
const states = getStates('block', blocks, ctx);
|
|
138
157
|
return completer.record({
|
|
139
158
|
key: (_record, pair, _ctx, range, insertValue, insertComma, existingKeys) => {
|
|
140
|
-
return Object.keys(states)
|
|
141
|
-
.filter((k) => pair?.key?.value === k ||
|
|
142
|
-
!existingKeys.some((ek) => ek.value === k))
|
|
143
|
-
.map((k) => CompletionItem.create(k, range, {
|
|
159
|
+
return Object.keys(states).filter((k) => pair?.key?.value === k || !existingKeys.some((ek) => ek.value === k)).map((k) => CompletionItem.create(k, range, {
|
|
144
160
|
kind: 10 /* CompletionKind.Property */,
|
|
145
161
|
detail: localize('mcfunction.completer.block.states.default-value', localeQuote(states[k][0])),
|
|
146
|
-
insertText: new InsertTextBuilder()
|
|
147
|
-
.literal(k)
|
|
148
|
-
.if(insertValue, (b) => b.literal('=').placeholder(...states[k]))
|
|
149
|
-
.if(insertComma, (b) => b.literal(','))
|
|
150
|
-
.build(),
|
|
162
|
+
insertText: new InsertTextBuilder().literal(k).if(insertValue, (b) => b.literal('=').placeholder(...states[k])).if(insertComma, (b) => b.literal(',')).build(),
|
|
151
163
|
}));
|
|
152
164
|
},
|
|
153
165
|
value: (_record, pair, ctx) => {
|
|
154
166
|
if (pair.key && states[pair.key.value]) {
|
|
155
|
-
return states[pair.key.value].map((v) => CompletionItem.create(v, pair.value ?? ctx.offset, {
|
|
156
|
-
kind: 12 /* CompletionKind.Value */,
|
|
157
|
-
}));
|
|
167
|
+
return states[pair.key.value].map((v) => CompletionItem.create(v, pair.value ?? ctx.offset, { kind: 12 /* CompletionKind.Value */ }));
|
|
158
168
|
}
|
|
159
169
|
return [];
|
|
160
170
|
},
|
|
161
171
|
})(node, ctx);
|
|
162
172
|
};
|
|
173
|
+
const componentList = (node, ctx) => {
|
|
174
|
+
return completer.record({
|
|
175
|
+
key: (_record, pair, ctx, range) => {
|
|
176
|
+
const id = pair?.key
|
|
177
|
+
?? ResourceLocationNode.mock(pair?.key ?? range, { category: 'data_component_type' });
|
|
178
|
+
return completer.resourceLocation(id, ctx);
|
|
179
|
+
},
|
|
180
|
+
value: (_record, pair, ctx) => {
|
|
181
|
+
if (!pair.value) {
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
return completer.dispatch(pair.value, ctx);
|
|
185
|
+
},
|
|
186
|
+
})(node, ctx);
|
|
187
|
+
};
|
|
188
|
+
const componentTests = (node, ctx) => {
|
|
189
|
+
// TODO: improve this completer
|
|
190
|
+
const test = AstNode.findShallowestChild({
|
|
191
|
+
node: node,
|
|
192
|
+
needle: ctx.offset,
|
|
193
|
+
endInclusive: true,
|
|
194
|
+
predicate: (n) => ComponentTestExactNode.is(n) || ComponentTestSubpredicateNode.is(n),
|
|
195
|
+
});
|
|
196
|
+
if (test && ComponentTestExactNode.is(test) && test.value) {
|
|
197
|
+
return completer.dispatch(test.value, ctx);
|
|
198
|
+
}
|
|
199
|
+
else if (test && ComponentTestSubpredicateNode.is(test) && test.value) {
|
|
200
|
+
return completer.dispatch(test.value, ctx);
|
|
201
|
+
}
|
|
202
|
+
return [];
|
|
203
|
+
};
|
|
163
204
|
const coordinate = (node, _ctx) => {
|
|
164
205
|
return [CompletionItem.create('~', node)];
|
|
165
206
|
};
|
|
166
|
-
const
|
|
207
|
+
const itemStack = (node, ctx) => {
|
|
167
208
|
const ans = [];
|
|
168
209
|
if (Range.contains(node.id, ctx.offset, true)) {
|
|
169
210
|
ans.push(...completer.resourceLocation(node.id, ctx));
|
|
170
211
|
}
|
|
212
|
+
if (node.components && Range.contains(node.components, ctx.offset, true)) {
|
|
213
|
+
ans.push(...componentList(node.components, ctx));
|
|
214
|
+
}
|
|
215
|
+
if (node.nbt && Range.contains(node.nbt, ctx.offset, true)) {
|
|
216
|
+
ans.push(...completer.dispatch(node.nbt, ctx));
|
|
217
|
+
}
|
|
218
|
+
return ans;
|
|
219
|
+
};
|
|
220
|
+
const itemPredicate = (node, ctx) => {
|
|
221
|
+
const ans = [];
|
|
222
|
+
if (Range.contains(node.id, ctx.offset, true)) {
|
|
223
|
+
ans.push(CompletionItem.create('*', node, { sortText: '##' }));
|
|
224
|
+
if (node.id.type === 'resource_location') {
|
|
225
|
+
ans.push(...completer.resourceLocation(node.id, ctx));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (node.tests && Range.contains(node.tests, ctx.offset, true)) {
|
|
229
|
+
ans.push(...componentTests(node.tests, ctx));
|
|
230
|
+
}
|
|
231
|
+
if (node.nbt && Range.contains(node.nbt, ctx.offset, true)) {
|
|
232
|
+
ans.push(...completer.dispatch(node.nbt, ctx));
|
|
233
|
+
}
|
|
171
234
|
return ans;
|
|
172
235
|
};
|
|
173
236
|
const objectiveCriteria = (node, ctx) => {
|
|
174
237
|
const ans = ObjectiveCriteriaNode.SimpleValues.map((v) => CompletionItem.create(v, node));
|
|
175
|
-
if (!node.children?.[0] ||
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
ResourceLocationNode.mock(node, {
|
|
179
|
-
category: 'stat_type',
|
|
180
|
-
namespacePathSep: '.',
|
|
181
|
-
}), ctx));
|
|
238
|
+
if (!node.children?.[0] || Range.contains(node.children[0], ctx.offset, true)) {
|
|
239
|
+
ans.push(...completer.resourceLocation(node.children?.[0]
|
|
240
|
+
?? ResourceLocationNode.mock(node, { category: 'stat_type', namespacePathSep: '.' }), ctx));
|
|
182
241
|
}
|
|
183
|
-
if (node.children?.[1] &&
|
|
184
|
-
Range.contains(node.children[1], ctx.offset, true)) {
|
|
242
|
+
if (node.children?.[1] && Range.contains(node.children[1], ctx.offset, true)) {
|
|
185
243
|
ans.push(...completer.resourceLocation(node.children[1], ctx));
|
|
186
244
|
}
|
|
187
245
|
return ans;
|
|
@@ -191,21 +249,22 @@ const particle = (node, ctx) => {
|
|
|
191
249
|
if (child) {
|
|
192
250
|
return completer.dispatch(child, ctx);
|
|
193
251
|
}
|
|
252
|
+
const release = ctx.project['loadedVersion'];
|
|
253
|
+
if (!release || ReleaseVersion.cmp(release, '1.20.5') >= 0) {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
194
256
|
const id = ResourceLocationNode.toString(node.id, 'short');
|
|
195
257
|
const map = {
|
|
196
258
|
block: [BlockNode.mock(ctx.offset, false)],
|
|
197
259
|
block_marker: [BlockNode.mock(ctx.offset, false)],
|
|
198
|
-
dust: [
|
|
199
|
-
VectorNode.mock(ctx.offset, { dimension: 3 }),
|
|
200
|
-
FloatNode.mock(ctx.offset),
|
|
201
|
-
],
|
|
260
|
+
dust: [VectorNode.mock(ctx.offset, { dimension: 3 }), FloatNode.mock(ctx.offset)],
|
|
202
261
|
dust_color_transition: [
|
|
203
262
|
VectorNode.mock(ctx.offset, { dimension: 3 }),
|
|
204
263
|
FloatNode.mock(ctx.offset),
|
|
205
264
|
VectorNode.mock(ctx.offset, { dimension: 3 }),
|
|
206
265
|
],
|
|
207
266
|
falling_dust: [BlockNode.mock(ctx.offset, false)],
|
|
208
|
-
item: [
|
|
267
|
+
item: [ItemStackNode.mock(ctx.offset)],
|
|
209
268
|
sculk_charge: [FloatNode.mock(ctx.offset)],
|
|
210
269
|
shriek: [IntegerNode.mock(ctx.offset)],
|
|
211
270
|
vibration: [
|
|
@@ -215,8 +274,8 @@ const particle = (node, ctx) => {
|
|
|
215
274
|
],
|
|
216
275
|
};
|
|
217
276
|
if (ParticleNode.isSpecialType(id)) {
|
|
218
|
-
const numParamsBefore = node.children?.slice(1).filter((n) => n.range.end < ctx.offset).length
|
|
219
|
-
0;
|
|
277
|
+
const numParamsBefore = node.children?.slice(1).filter((n) => n.range.end < ctx.offset).length
|
|
278
|
+
?? 0;
|
|
220
279
|
const mock = map[id][numParamsBefore];
|
|
221
280
|
if (mock) {
|
|
222
281
|
return completer.dispatch(mock, ctx);
|
|
@@ -234,7 +293,7 @@ const scoreHolder = (node, ctx) => {
|
|
|
234
293
|
}
|
|
235
294
|
else {
|
|
236
295
|
ans = completer.symbol(node.fakeName ?? SymbolNode.mock(node, { category: 'score_holder' }), ctx);
|
|
237
|
-
ans.push(...selector(EntitySelectorNode.mock(node), ctx));
|
|
296
|
+
ans.push(...selector(EntitySelectorNode.mock(node, { pool: EntitySelectorAtVariable.filterAvailable(ctx) }), ctx));
|
|
238
297
|
}
|
|
239
298
|
return ans;
|
|
240
299
|
};
|
|
@@ -242,8 +301,7 @@ const selector = (node, ctx) => {
|
|
|
242
301
|
if (Range.contains(node.children[0], ctx.offset, true)) {
|
|
243
302
|
return completer.literal(node.children[0], ctx);
|
|
244
303
|
}
|
|
245
|
-
if (node.arguments &&
|
|
246
|
-
Range.contains(Range.translate(node.arguments, 1, -1), ctx.offset, true)) {
|
|
304
|
+
if (node.arguments && Range.contains(Range.translate(node.arguments, 1, -1), ctx.offset, true)) {
|
|
247
305
|
return selectorArguments(node.arguments, ctx);
|
|
248
306
|
}
|
|
249
307
|
return [];
|
|
@@ -255,16 +313,10 @@ const selectorArguments = (node, ctx) => {
|
|
|
255
313
|
}
|
|
256
314
|
return completer.record({
|
|
257
315
|
key: (record, pair, _ctx, range, insertValue, insertComma) => {
|
|
258
|
-
return [...EntitySelectorNode.ArgumentKeys]
|
|
259
|
-
.filter((k) => EntitySelectorNode.canKeyExist(selector, record, k) ===
|
|
260
|
-
0 /* EntitySelectorNode.Result.Ok */)
|
|
261
|
-
.map((k) => CompletionItem.create(k, range, {
|
|
316
|
+
return [...EntitySelectorNode.ArgumentKeys].filter((k) => EntitySelectorNode.canKeyExist(selector, record, k) === 0 /* EntitySelectorNode.Result.Ok */).map((k) => CompletionItem.create(k, range, {
|
|
262
317
|
kind: 10 /* CompletionKind.Property */,
|
|
263
|
-
insertText: new InsertTextBuilder()
|
|
264
|
-
.literal(
|
|
265
|
-
.if(insertValue, (b) => b.literal('=').placeholder()) // TODO
|
|
266
|
-
.if(insertComma, (b) => b.literal(','))
|
|
267
|
-
.build(),
|
|
318
|
+
insertText: new InsertTextBuilder().literal(k).if(insertValue, (b) => b.literal('=').placeholder()) // TODO
|
|
319
|
+
.if(insertComma, (b) => b.literal(',')).build(),
|
|
268
320
|
}));
|
|
269
321
|
},
|
|
270
322
|
value: (_record, pair, ctx) => {
|
|
@@ -277,13 +329,13 @@ const selectorArguments = (node, ctx) => {
|
|
|
277
329
|
};
|
|
278
330
|
const intRange = (node, _ctx) => {
|
|
279
331
|
return [
|
|
280
|
-
CompletionItem.create('-2147483648..2147483647', node, {
|
|
281
|
-
kind: 21 /* CompletionKind.Constant */,
|
|
282
|
-
}),
|
|
332
|
+
CompletionItem.create('-2147483648..2147483647', node, { kind: 21 /* CompletionKind.Constant */ }),
|
|
283
333
|
];
|
|
284
334
|
};
|
|
285
335
|
const vector = (node, _ctx) => {
|
|
286
|
-
const createCompletion = (coordinate, sortText) => CompletionItem.create(new Array(node.options.dimension).fill(coordinate).join(' '), node, {
|
|
336
|
+
const createCompletion = (coordinate, sortText) => CompletionItem.create(new Array(node.options.dimension).fill(coordinate).join(' '), node, {
|
|
337
|
+
sortText,
|
|
338
|
+
});
|
|
287
339
|
const ans = [];
|
|
288
340
|
ans.push(createCompletion('~', 'a'));
|
|
289
341
|
if (!node.options.noLocal) {
|
|
@@ -294,11 +346,14 @@ const vector = (node, _ctx) => {
|
|
|
294
346
|
};
|
|
295
347
|
export function register(meta) {
|
|
296
348
|
meta.registerCompleter('mcfunction:block', block);
|
|
349
|
+
meta.registerCompleter('mcfunction:component_list', componentList);
|
|
350
|
+
meta.registerCompleter('mcfunction:component_tests', componentTests);
|
|
297
351
|
meta.registerCompleter('mcfunction:coordinate', coordinate);
|
|
298
352
|
meta.registerCompleter('mcfunction:entity_selector', selector);
|
|
299
353
|
meta.registerCompleter('mcfunction:entity_selector/arguments', selectorArguments);
|
|
300
354
|
meta.registerCompleter('mcfunction:int_range', intRange);
|
|
301
|
-
meta.registerCompleter('mcfunction:
|
|
355
|
+
meta.registerCompleter('mcfunction:item_stack', itemStack);
|
|
356
|
+
meta.registerCompleter('mcfunction:item_predicate', itemPredicate);
|
|
302
357
|
meta.registerCompleter('mcfunction:objective_criteria', objectiveCriteria);
|
|
303
358
|
meta.registerCompleter('mcfunction:particle', particle);
|
|
304
359
|
meta.registerCompleter('mcfunction:score_holder', scoreHolder);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { McmetaCommands
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
2
|
+
import type { McmetaCommands } from '../dependency/index.js';
|
|
3
|
+
import { ReleaseVersion } from '../dependency/index.js';
|
|
3
4
|
export * as checker from './checker/index.js';
|
|
4
5
|
export * as colorizer from './colorizer/index.js';
|
|
5
6
|
export * as completer from './completer/index.js';
|
package/lib/mcfunction/index.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
1
2
|
import * as mcf from '@spyglassmc/mcfunction';
|
|
3
|
+
import { registerCustomResources } from '../binder/index.js';
|
|
4
|
+
import { ReleaseVersion } from '../dependency/index.js';
|
|
2
5
|
import * as checker from './checker/index.js';
|
|
3
6
|
import * as colorizer from './colorizer/index.js';
|
|
4
7
|
import * as completer from './completer/index.js';
|
|
5
8
|
import { inlayHintProvider } from './inlayHintProvider.js';
|
|
9
|
+
import { registerMcdocAttributes } from './mcdocAttributes.js';
|
|
6
10
|
import * as parser from './parser/index.js';
|
|
7
11
|
import { signatureHelpProvider } from './signatureHelpProvider.js';
|
|
8
12
|
import { getPatch } from './tree/patch.js';
|
|
13
|
+
import { validatePatchedTree } from './tree/patchValidator.js';
|
|
9
14
|
export * as checker from './checker/index.js';
|
|
10
15
|
export * as colorizer from './colorizer/index.js';
|
|
11
16
|
export * as completer from './completer/index.js';
|
|
@@ -13,36 +18,30 @@ export * as parser from './parser/index.js';
|
|
|
13
18
|
/* istanbul ignore next */
|
|
14
19
|
export const initialize = (ctx, commands, releaseVersion) => {
|
|
15
20
|
const { meta } = ctx;
|
|
21
|
+
registerCustomResources(ctx.config);
|
|
22
|
+
const tree = core.merge(commands, getPatch(releaseVersion));
|
|
23
|
+
if (ctx.isDebugging) {
|
|
24
|
+
validatePatchedTree(tree, ctx.logger);
|
|
25
|
+
}
|
|
16
26
|
mcf.initialize(ctx);
|
|
17
|
-
|
|
27
|
+
const supportsBackslashContinuation = ReleaseVersion.cmp(releaseVersion, '1.20.2') >= 0;
|
|
28
|
+
const supportsMacros = ReleaseVersion.cmp(releaseVersion, '1.20.2') >= 0;
|
|
18
29
|
meta.registerLanguage('mcfunction', {
|
|
19
30
|
extensions: ['.mcfunction'],
|
|
20
|
-
parser: mcf.entry(
|
|
21
|
-
completer: mcf.completer.entry(
|
|
22
|
-
triggerCharacters: [
|
|
23
|
-
' ',
|
|
24
|
-
'[',
|
|
25
|
-
'=',
|
|
26
|
-
'!',
|
|
27
|
-
',',
|
|
28
|
-
'{',
|
|
29
|
-
':',
|
|
30
|
-
'/',
|
|
31
|
-
'.',
|
|
32
|
-
'"',
|
|
33
|
-
"'",
|
|
34
|
-
],
|
|
31
|
+
parser: mcf.entry(tree, parser.argument, { supportsBackslashContinuation, supportsMacros }),
|
|
32
|
+
completer: mcf.completer.entry(tree, completer.getMockNodes),
|
|
33
|
+
triggerCharacters: [' ', '[', '=', '!', ',', '{', ':', '/', '.', '"', "'"],
|
|
35
34
|
});
|
|
36
35
|
meta.registerParser('mcfunction:block_predicate', parser.blockPredicate);
|
|
37
|
-
meta.registerParser('mcfunction:component', parser.component);
|
|
38
36
|
meta.registerParser('mcfunction:particle', parser.particle);
|
|
39
37
|
meta.registerParser('mcfunction:tag', parser.tag());
|
|
40
38
|
meta.registerParser('mcfunction:team', parser.team());
|
|
41
|
-
meta.registerParser('mcfunction:command', mcf.command(
|
|
39
|
+
meta.registerParser('mcfunction:command', mcf.command(tree, parser.argument));
|
|
40
|
+
registerMcdocAttributes(meta, tree);
|
|
42
41
|
checker.register(meta);
|
|
43
42
|
colorizer.register(meta);
|
|
44
43
|
completer.register(meta);
|
|
45
44
|
meta.registerInlayHintProvider(inlayHintProvider);
|
|
46
|
-
meta.registerSignatureHelpProvider(signatureHelpProvider(
|
|
45
|
+
meta.registerSignatureHelpProvider(signatureHelpProvider(tree));
|
|
47
46
|
};
|
|
48
47
|
//# sourceMappingURL=index.js.map
|
|
@@ -8,9 +8,8 @@ export const inlayHintProvider = (node, ctx) => {
|
|
|
8
8
|
core.traversePreOrder(node, (_) => true, mcf.CommandChildNode.is, (n) => {
|
|
9
9
|
const node = n;
|
|
10
10
|
const config = ctx.config.env.feature.inlayHint;
|
|
11
|
-
if (config === true
|
|
12
|
-
(typeof config === 'object' &&
|
|
13
|
-
config.enabledNodes.includes(node.children[0].type))) {
|
|
11
|
+
if (config === true
|
|
12
|
+
|| (typeof config === 'object' && config.enabledNodes.includes(node.children[0].type))) {
|
|
14
13
|
ans.push({
|
|
15
14
|
offset: node.range.start,
|
|
16
15
|
label: `${node.path[node.path.length - 1]}:`,
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
2
|
+
import * as json from '@spyglassmc/json';
|
|
3
|
+
import { localize } from '@spyglassmc/locales';
|
|
4
|
+
import * as mcdoc from '@spyglassmc/mcdoc';
|
|
5
|
+
import * as mcf from '@spyglassmc/mcfunction';
|
|
6
|
+
import { getItemSlotsArgumentValues } from './common/index.js';
|
|
7
|
+
import { EntitySelectorAtVariable, EntitySelectorNode, ScoreHolderNode } from './node/argument.js';
|
|
8
|
+
import * as parser from './parser/index.js';
|
|
9
|
+
const validator = mcdoc.runtime.attribute.validator;
|
|
10
|
+
const entityValidator = validator.alternatives(validator.tree({
|
|
11
|
+
amount: validator.options('multiple', 'single'),
|
|
12
|
+
type: validator.options('entities', 'players'),
|
|
13
|
+
}), () => ({ amount: 'multiple', type: 'entities' }));
|
|
14
|
+
const scoreHolderValidator = validator.alternatives(validator.tree({
|
|
15
|
+
amount: validator.options('multiple', 'single'),
|
|
16
|
+
}), () => ({ amount: 'multiple' }));
|
|
17
|
+
export function registerMcdocAttributes(meta, rootTreeNode) {
|
|
18
|
+
mcdoc.runtime.registerAttribute(meta, 'command', () => undefined, {
|
|
19
|
+
// TODO: validate slash
|
|
20
|
+
// TODO: fix completer inside commands
|
|
21
|
+
stringParser: () => {
|
|
22
|
+
return mcf.command(rootTreeNode, parser.argument);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
mcdoc.runtime.registerAttribute(meta, 'text_component', () => undefined, {
|
|
26
|
+
stringParser: () => makeInfallible(core.map(json.parser.entry, (res) => ({
|
|
27
|
+
type: 'json:typed',
|
|
28
|
+
range: res.range,
|
|
29
|
+
children: [res],
|
|
30
|
+
targetType: { kind: 'reference', path: '::java::server::util::text::Text' },
|
|
31
|
+
})), localize('text-component')),
|
|
32
|
+
});
|
|
33
|
+
mcdoc.runtime.registerAttribute(meta, 'objective', () => undefined, {
|
|
34
|
+
stringParser: () => parser.objective('reference'),
|
|
35
|
+
stringMocker: (_, __, ctx) => core.SymbolNode.mock(ctx.offset, { category: 'objective' }),
|
|
36
|
+
});
|
|
37
|
+
mcdoc.runtime.registerAttribute(meta, 'team', () => undefined, {
|
|
38
|
+
stringParser: () => parser.team('reference'),
|
|
39
|
+
stringMocker: (_, __, ctx) => core.SymbolNode.mock(ctx.offset, { category: 'team' }),
|
|
40
|
+
});
|
|
41
|
+
mcdoc.runtime.registerAttribute(meta, 'score_holder', scoreHolderValidator, {
|
|
42
|
+
stringParser: (config) => makeInfallible(parser.scoreHolder('reference', config.amount), localize('score-holder')),
|
|
43
|
+
stringMocker: (_, __, ctx) => ScoreHolderNode.mock(ctx.offset),
|
|
44
|
+
});
|
|
45
|
+
mcdoc.runtime.registerAttribute(meta, 'tag', () => undefined, {
|
|
46
|
+
stringParser: () => parser.tag('definition'), // TODO: make this a config
|
|
47
|
+
stringMocker: (_, __, ctx) => core.SymbolNode.mock(ctx.offset, { category: 'tag' }),
|
|
48
|
+
});
|
|
49
|
+
mcdoc.runtime.registerAttribute(meta, 'entity', entityValidator, {
|
|
50
|
+
stringParser: (config) => makeInfallible(parser.entity(config.amount, config.type), localize('selector')),
|
|
51
|
+
stringMocker: (_, __, ctx) => EntitySelectorNode.mock(ctx.offset, {
|
|
52
|
+
pool: EntitySelectorAtVariable.filterAvailable(ctx),
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
mcdoc.runtime.registerAttribute(meta, 'item_slots', () => undefined, {
|
|
56
|
+
stringParser: () => parser.itemSlots,
|
|
57
|
+
stringMocker: (_, __, ctx) => core.LiteralNode.mock(ctx.offset, { pool: getItemSlotsArgumentValues(ctx) }),
|
|
58
|
+
});
|
|
59
|
+
mcdoc.runtime.registerAttribute(meta, 'uuid', () => undefined, {
|
|
60
|
+
stringParser: () => parser.uuid,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function makeInfallible(parser, message) {
|
|
64
|
+
return (src, ctx) => {
|
|
65
|
+
const start = src.cursor;
|
|
66
|
+
const res = parser(src, ctx);
|
|
67
|
+
if (res === core.Failure) {
|
|
68
|
+
ctx.err.report(localize('expected', message), core.Range.create(start, src.skipRemaining()));
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return res;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=mcdocAttributes.js.map
|