@spyglassmc/core 0.4.5 → 0.4.7
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 +2 -5
- package/lib/common/ReadonlyProxy.js +1 -3
- package/lib/common/StateProxy.js +2 -8
- package/lib/common/externals/BrowserExternals.js +7 -12
- package/lib/common/externals/NodeJsExternals.js +12 -8
- package/lib/common/externals/index.d.ts +8 -1
- package/lib/common/util.js +3 -10
- package/lib/node/AstNode.js +7 -9
- package/lib/node/BooleanNode.js +1 -4
- package/lib/node/FloatNode.js +1 -5
- package/lib/node/IntegerNode.js +1 -5
- package/lib/node/ListNode.d.ts +1 -1
- package/lib/node/LiteralNode.js +1 -6
- package/lib/node/LongNode.js +1 -5
- package/lib/node/PrefixedNode.d.ts +13 -0
- package/lib/node/PrefixedNode.js +22 -0
- package/lib/node/ResourceLocationNode.d.ts +4 -1
- package/lib/node/ResourceLocationNode.js +2 -8
- package/lib/node/StringNode.d.ts +2 -1
- package/lib/node/StringNode.js +1 -4
- package/lib/node/SymbolNode.js +1 -6
- package/lib/node/index.d.ts +1 -0
- package/lib/node/index.js +1 -0
- package/lib/parser/comment.d.ts +1 -1
- package/lib/parser/comment.js +2 -6
- package/lib/parser/error.js +1 -4
- package/lib/parser/file.d.ts +2 -2
- package/lib/parser/file.js +1 -2
- package/lib/parser/float.js +2 -7
- package/lib/parser/index.d.ts +1 -0
- package/lib/parser/index.js +1 -0
- package/lib/parser/integer.js +3 -7
- package/lib/parser/list.d.ts +1 -1
- package/lib/parser/list.js +2 -6
- package/lib/parser/literal.js +2 -9
- package/lib/parser/long.js +2 -7
- package/lib/parser/prefixed.d.ts +8 -0
- package/lib/parser/prefixed.js +23 -0
- package/lib/parser/record.d.ts +1 -1
- package/lib/parser/record.js +11 -17
- package/lib/parser/resourceLocation.d.ts +1 -0
- package/lib/parser/resourceLocation.js +9 -4
- package/lib/parser/string.js +6 -9
- package/lib/parser/util.d.ts +14 -3
- package/lib/parser/util.js +48 -26
- package/lib/processor/ColorInfoProvider.js +8 -25
- package/lib/processor/binder/builtin.d.ts +1 -0
- package/lib/processor/binder/builtin.js +20 -30
- package/lib/processor/checker/builtin.d.ts +1 -0
- package/lib/processor/checker/builtin.js +13 -7
- package/lib/processor/colorizer/Colorizer.d.ts +1 -1
- package/lib/processor/colorizer/Colorizer.js +4 -7
- package/lib/processor/colorizer/builtin.js +2 -2
- package/lib/processor/completer/Completer.js +1 -3
- package/lib/processor/completer/builtin.d.ts +3 -2
- package/lib/processor/completer/builtin.js +70 -24
- package/lib/processor/formatter/Formatter.js +1 -3
- package/lib/processor/formatter/builtin.js +2 -4
- package/lib/processor/linter/builtin/undeclaredSymbol.js +27 -40
- package/lib/service/CacheService.d.ts +1 -1
- package/lib/service/CacheService.js +12 -13
- package/lib/service/Config.d.ts +36 -0
- package/lib/service/Config.js +28 -45
- package/lib/service/Context.d.ts +2 -0
- package/lib/service/Context.js +4 -12
- package/lib/service/Downloader.d.ts +3 -0
- package/lib/service/Downloader.js +9 -3
- package/lib/service/ErrorReporter.js +3 -0
- package/lib/service/FileService.js +10 -29
- package/lib/service/Hover.js +1 -4
- package/lib/service/MetaRegistry.d.ts +4 -2
- package/lib/service/MetaRegistry.js +16 -8
- package/lib/service/Project.d.ts +9 -3
- package/lib/service/Project.js +73 -49
- package/lib/service/Service.d.ts +1 -1
- package/lib/service/Service.js +11 -36
- package/lib/service/SymbolLocations.js +1 -4
- package/lib/service/fileUtil.d.ts +7 -0
- package/lib/service/fileUtil.js +29 -4
- package/lib/source/IndexMap.js +1 -4
- package/lib/source/Location.js +3 -9
- package/lib/source/Position.js +1 -2
- package/lib/source/PositionRange.js +2 -2
- package/lib/source/Range.js +9 -21
- package/lib/source/Source.d.ts +11 -1
- package/lib/source/Source.js +31 -5
- package/lib/symbol/Symbol.d.ts +14 -9
- package/lib/symbol/Symbol.js +80 -61
- package/lib/symbol/SymbolUtil.d.ts +3 -3
- package/lib/symbol/SymbolUtil.js +48 -72
- package/package.json +3 -2
|
@@ -51,9 +51,7 @@ export class InsertTextBuilder {
|
|
|
51
51
|
this.#ans += `$\{${this.#nextPlaceholder}:${CompletionItem.escape(defaultValues[0])}}`;
|
|
52
52
|
}
|
|
53
53
|
else {
|
|
54
|
-
this.#ans += `$\{${this.#nextPlaceholder}|${defaultValues
|
|
55
|
-
.map((v) => v.replace(/([\\$},|])/g, '\\$1'))
|
|
56
|
-
.join(',')}|}`;
|
|
54
|
+
this.#ans += `$\{${this.#nextPlaceholder}|${defaultValues.map((v) => v.replace(/([\\$},|])/g, '\\$1')).join(',')}|}`;
|
|
57
55
|
}
|
|
58
56
|
this.#nextPlaceholder += 1;
|
|
59
57
|
return this;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DeepReadonly } from '../../common/index.js';
|
|
2
2
|
import type { BooleanBaseNode } from '../../node/BooleanNode.js';
|
|
3
|
-
import type { FileNode, LiteralBaseNode, PairNode, RecordBaseNode, ResourceLocationNode, StringBaseNode, SymbolBaseNode } from '../../node/index.js';
|
|
3
|
+
import type { FileNode, LiteralBaseNode, PairNode, Quote, RecordBaseNode, ResourceLocationNode, StringBaseNode, SymbolBaseNode } from '../../node/index.js';
|
|
4
4
|
import { AstNode } from '../../node/index.js';
|
|
5
5
|
import type { CompleterContext, MetaRegistry } from '../../service/index.js';
|
|
6
6
|
import type { RangeLike } from '../../source/index.js';
|
|
@@ -20,11 +20,12 @@ export declare const literal: Completer<LiteralBaseNode>;
|
|
|
20
20
|
export declare const noop: Completer<any>;
|
|
21
21
|
interface RecordOptions<K extends AstNode, V extends AstNode, N extends RecordBaseNode<K, V>> {
|
|
22
22
|
key: (record: DeepReadonly<N>, pair: DeepReadonly<PairNode<K, V>> | undefined, ctx: CompleterContext, range: RangeLike, insertValue: boolean, insertPairEnd: boolean, existingKeys: DeepReadonly<K>[]) => CompletionItem[];
|
|
23
|
-
value: (record: DeepReadonly<N>, pair: DeepReadonly<PairNode<K, V>>, ctx: CompleterContext) => CompletionItem[];
|
|
23
|
+
value: (record: DeepReadonly<N>, pair: DeepReadonly<PairNode<K, V>>, ctx: CompleterContext, range: RangeLike) => CompletionItem[];
|
|
24
24
|
}
|
|
25
25
|
export declare function record<K extends AstNode, V extends AstNode, N extends RecordBaseNode<K, V>>(o: RecordOptions<K, V, N>): Completer<N>;
|
|
26
26
|
export declare const resourceLocation: Completer<ResourceLocationNode>;
|
|
27
27
|
export declare const string: Completer<StringBaseNode>;
|
|
28
|
+
export declare function escapeString(value: string, quote?: Quote): string;
|
|
28
29
|
export declare const symbol: Completer<SymbolBaseNode>;
|
|
29
30
|
export declare function registerCompleters(meta: MetaRegistry): void;
|
|
30
31
|
export {};
|
|
@@ -3,6 +3,7 @@ import { ResourceLocation } from '../../common/index.js';
|
|
|
3
3
|
import { AstNode } from '../../node/index.js';
|
|
4
4
|
import { LinterConfigValue } from '../../service/index.js';
|
|
5
5
|
import { Range } from '../../source/index.js';
|
|
6
|
+
import { SymbolUtil } from '../../symbol/index.js';
|
|
6
7
|
import { CompletionItem } from './Completer.js';
|
|
7
8
|
/**
|
|
8
9
|
* Uses the shallowest selected node that has its own completer to provide the completion items.
|
|
@@ -43,10 +44,22 @@ export const literal = (node) => {
|
|
|
43
44
|
['resourceLocation', 17 /* CompletionKind.File */],
|
|
44
45
|
['variable', 6 /* CompletionKind.Variable */],
|
|
45
46
|
]).get(node.options.colorTokenType ?? 'keyword') ?? 14 /* CompletionKind.Keyword */;
|
|
46
|
-
return (node.options.pool.map((v) => CompletionItem.create(v, node, { kind })) ??
|
|
47
|
-
[]);
|
|
47
|
+
return (node.options.pool.map((v) => CompletionItem.create(v, node, { kind })) ?? []);
|
|
48
48
|
};
|
|
49
49
|
export const noop = () => [];
|
|
50
|
+
const prefixed = (node, ctx) => {
|
|
51
|
+
const child = node.children.find(c => c.type !== 'literal');
|
|
52
|
+
if (!child) {
|
|
53
|
+
return [CompletionItem.create('!', node)];
|
|
54
|
+
}
|
|
55
|
+
const childItems = dispatch(child, ctx);
|
|
56
|
+
return childItems.map(item => ({
|
|
57
|
+
...item,
|
|
58
|
+
label: node.prefix + item.label,
|
|
59
|
+
filterText: node.prefix + (item.filterText ?? item.label),
|
|
60
|
+
insertText: node.prefix + (item.insertText ?? item.label),
|
|
61
|
+
}));
|
|
62
|
+
};
|
|
50
63
|
export function record(o) {
|
|
51
64
|
return (node, ctx) => {
|
|
52
65
|
if (!Range.contains(Range.translate(node, 1, -1), ctx.offset, true)) {
|
|
@@ -54,9 +67,7 @@ export function record(o) {
|
|
|
54
67
|
}
|
|
55
68
|
const completeKeys = (pair) => o.key(node, pair, ctx, pair?.key ?? ctx.offset, false, false, existingKeys);
|
|
56
69
|
const completePairs = (pair) => o.key(node, pair, ctx, pair ?? ctx.offset, true, hasNextPair || !!pair?.end, existingKeys);
|
|
57
|
-
const existingKeys = node.children
|
|
58
|
-
.filter((n) => !!n.key)
|
|
59
|
-
.map((n) => n.key);
|
|
70
|
+
const existingKeys = node.children.filter((n) => !!n.key).map((n) => n.key);
|
|
60
71
|
const index = binarySearch(node.children, ctx.offset, (n, o) => n.end
|
|
61
72
|
? Range.compareOffset(Range.translate(n, 0, -1), o, true)
|
|
62
73
|
: Range.compareOffset(n.range, o, true));
|
|
@@ -69,33 +80,35 @@ export function record(o) {
|
|
|
69
80
|
if (!key && !sep && !value) {
|
|
70
81
|
return completePairs(undefined);
|
|
71
82
|
}
|
|
72
|
-
if ((key && Range.contains(key, ctx.offset, true)) ||
|
|
73
|
-
(sep && ctx.offset <= sep.start) ||
|
|
74
|
-
(value && ctx.offset < value.range.start)) {
|
|
83
|
+
if ((key && Range.contains(key, ctx.offset, true)) || (sep && ctx.offset <= sep.start)) {
|
|
75
84
|
// Selected key.
|
|
76
85
|
if (!value || Range.isEmpty(value.range)) {
|
|
77
86
|
return completePairs(pair);
|
|
78
87
|
}
|
|
79
88
|
return completeKeys(pair);
|
|
80
89
|
}
|
|
81
|
-
if (
|
|
82
|
-
(
|
|
83
|
-
|
|
90
|
+
if (value && ctx.offset < value.range.start) {
|
|
91
|
+
return o.value(node, pair, ctx, ctx.offset);
|
|
92
|
+
}
|
|
93
|
+
if ((value && Range.contains(value, ctx.offset, true))
|
|
94
|
+
|| (sep && ctx.offset >= sep.end)
|
|
95
|
+
|| (key && ctx.offset > key.range.end)) {
|
|
84
96
|
// Selected value.
|
|
85
|
-
return o.value(node, pair, ctx);
|
|
97
|
+
return o.value(node, pair, ctx, value ?? ctx.offset);
|
|
86
98
|
}
|
|
87
99
|
return [];
|
|
88
100
|
};
|
|
89
101
|
}
|
|
90
102
|
export const resourceLocation = (node, ctx) => {
|
|
91
103
|
const config = LinterConfigValue.destruct(ctx.config.lint.idOmitDefaultNamespace);
|
|
92
|
-
const includeEmptyNamespace = !node.options.
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
const includeEmptyNamespace = !node.options.requireCanonical && node.namespace === '';
|
|
105
|
+
const includeDefaultNamespace = node.options.requireCanonical || config?.ruleValue !== true;
|
|
106
|
+
const excludeDefaultNamespace = !node.options.requireCanonical && config?.ruleValue !== false;
|
|
107
|
+
const getPool = (category) => {
|
|
108
|
+
const symbols = ctx.symbols.getVisibleSymbols(category, ctx.doc.uri);
|
|
109
|
+
const declarations = Object.entries(symbols).flatMap(([key, symbol]) => SymbolUtil.isDeclared(symbol) ? [key] : []);
|
|
110
|
+
return optimizePool(declarations);
|
|
111
|
+
};
|
|
99
112
|
const optimizePool = (pool) => {
|
|
100
113
|
const defaultNsPrefix = `${ResourceLocation.DefaultNamespace}${ResourceLocation.NamespacePathSep}`;
|
|
101
114
|
const defaultNsIds = [];
|
|
@@ -126,17 +139,39 @@ export const resourceLocation = (node, ctx) => {
|
|
|
126
139
|
const pool = node.options.pool
|
|
127
140
|
? optimizePool(node.options.pool)
|
|
128
141
|
: [
|
|
129
|
-
...
|
|
142
|
+
...(!node.options.requireTag
|
|
143
|
+
? getPool(node.options.category)
|
|
144
|
+
: []),
|
|
130
145
|
...(node.options.allowTag
|
|
131
146
|
? getPool(`tag/${node.options.category}`).map((v) => `${ResourceLocation.TagPrefix}${v}`)
|
|
132
147
|
: []),
|
|
133
148
|
];
|
|
134
|
-
|
|
149
|
+
const items = pool.map((v) => CompletionItem.create(v, node, { kind: 3 /* CompletionKind.Function */ }));
|
|
150
|
+
if (node.options.category) {
|
|
151
|
+
const symbols = ctx.symbols.getVisibleSymbols(node.options.category, ctx.doc.uri);
|
|
152
|
+
const thisKey = Object.entries(symbols).flatMap(([key, symbol]) => {
|
|
153
|
+
if ((symbol.declaration?.[0] ?? symbol.definition?.[0])?.uri == ctx.doc.uri) {
|
|
154
|
+
return [key];
|
|
155
|
+
}
|
|
156
|
+
return [];
|
|
157
|
+
});
|
|
158
|
+
if (thisKey.length > 0) {
|
|
159
|
+
items.push(CompletionItem.create('THIS', node, {
|
|
160
|
+
kind: 15 /* CompletionKind.Snippet */,
|
|
161
|
+
insertText: thisKey[0],
|
|
162
|
+
detail: thisKey[0],
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return items;
|
|
135
167
|
};
|
|
136
168
|
export const string = (node, ctx) => {
|
|
137
169
|
if (node.children?.length) {
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
return dispatch(node.children[0], ctx).map(item => ({
|
|
171
|
+
...item,
|
|
172
|
+
filterText: escapeString(item.filterText ?? item.label, node.quote),
|
|
173
|
+
insertText: escapeString(item.insertText ?? item.label, node.quote),
|
|
174
|
+
}));
|
|
140
175
|
}
|
|
141
176
|
if (node.options.quotes && node.value === '') {
|
|
142
177
|
return node.options.quotes.map((q) => CompletionItem.create(`${q}${q}`, node, {
|
|
@@ -146,8 +181,18 @@ export const string = (node, ctx) => {
|
|
|
146
181
|
}
|
|
147
182
|
return [];
|
|
148
183
|
};
|
|
184
|
+
export function escapeString(value, quote) {
|
|
185
|
+
if (!quote) {
|
|
186
|
+
return value;
|
|
187
|
+
}
|
|
188
|
+
return value.replaceAll('\\', '\\\\').replaceAll(quote, '\\"');
|
|
189
|
+
}
|
|
149
190
|
export const symbol = (node, ctx) => {
|
|
150
|
-
|
|
191
|
+
const path = node.options.parentPath ?? [];
|
|
192
|
+
const symbols = ctx.symbols.query(ctx.doc, node.options.category, ...path).visibleMembers;
|
|
193
|
+
return Object.entries(symbols)
|
|
194
|
+
.filter(([k, v]) => SymbolUtil.isDeclared(v))
|
|
195
|
+
.map(([k, v]) => CompletionItem.create(k, node, { kind: 6 /* CompletionKind.Variable */ }));
|
|
151
196
|
};
|
|
152
197
|
export function registerCompleters(meta) {
|
|
153
198
|
meta.registerCompleter('boolean', boolean);
|
|
@@ -156,6 +201,7 @@ export function registerCompleters(meta) {
|
|
|
156
201
|
meta.registerCompleter('integer', noop);
|
|
157
202
|
meta.registerCompleter('long', noop);
|
|
158
203
|
meta.registerCompleter('literal', literal);
|
|
204
|
+
meta.registerCompleter('prefixed', prefixed);
|
|
159
205
|
meta.registerCompleter('resource_location', resourceLocation);
|
|
160
206
|
meta.registerCompleter('string', string);
|
|
161
207
|
meta.registerCompleter('symbol', symbol);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export function formatterContextIndentation(ctx, additionalLevels = 0) {
|
|
2
2
|
const total = ctx.indentLevel + additionalLevels;
|
|
3
|
-
return ctx.insertSpaces
|
|
4
|
-
? ' '.repeat(total * ctx.tabSize)
|
|
5
|
-
: '\t'.repeat(total);
|
|
3
|
+
return ctx.insertSpaces ? ' '.repeat(total * ctx.tabSize) : '\t'.repeat(total);
|
|
6
4
|
}
|
|
7
5
|
export function indentFormatter(ctx, additionalLevels = 1) {
|
|
8
6
|
return {
|
|
@@ -3,11 +3,9 @@ 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
|
|
7
|
-
.map((child) => {
|
|
6
|
+
return node.children.map((child) => {
|
|
8
7
|
return ctx.meta.getFormatter(child.type)(child, ctx);
|
|
9
|
-
})
|
|
10
|
-
.join('');
|
|
8
|
+
}).join('');
|
|
11
9
|
};
|
|
12
10
|
export const boolean = (node) => {
|
|
13
11
|
return node.value ? 'true' : 'false';
|
|
@@ -1,37 +1,24 @@
|
|
|
1
|
+
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
1
2
|
import { Arrayable, ResourceLocation } from '../../../common/index.js';
|
|
2
|
-
import { SymbolLinterConfig as Config } from '../../../service/index.js';
|
|
3
|
-
|
|
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'
|
|
3
|
+
import { LinterSeverity, SymbolLinterConfig as Config } from '../../../service/index.js';
|
|
4
|
+
import { SymbolUtil } from '../../../symbol/index.js';
|
|
12
5
|
export const undeclaredSymbol = (node, ctx) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// node.symbol.category,
|
|
30
|
-
// localeQuote(node.symbol.identifier)
|
|
31
|
-
// ),
|
|
32
|
-
// node, undefined, severityOverride
|
|
33
|
-
// )
|
|
34
|
-
// }
|
|
6
|
+
if (!node.symbol || SymbolUtil.isDeclared(node.symbol)) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const action = getAction(ctx.ruleValue, node.symbol, ctx);
|
|
10
|
+
if (Config.Action.isDeclare(action)) {
|
|
11
|
+
ctx.symbols.query({ doc: ctx.doc, node }, node.symbol.category, ...node.symbol.path).amend({
|
|
12
|
+
data: { visibility: getVisibility(action.declare) },
|
|
13
|
+
usage: { type: 'declaration', node },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (Config.Action.isReport(action)) {
|
|
17
|
+
const severityOverride = action.report === 'inherit'
|
|
18
|
+
? undefined
|
|
19
|
+
: LinterSeverity.toErrorSeverity(action.report);
|
|
20
|
+
ctx.err.lint(localize('linter.undeclared-symbol.message', node.symbol.category, localeQuote(node.symbol.identifier)), node, undefined, severityOverride);
|
|
21
|
+
}
|
|
35
22
|
};
|
|
36
23
|
function getAction(config, symbol, ctx) {
|
|
37
24
|
if (Config.Action.is(config)) {
|
|
@@ -43,17 +30,17 @@ function getAction(config, symbol, ctx) {
|
|
|
43
30
|
const namespace = resourceLocation.slice(0, resourceLocation.indexOf(ResourceLocation.NamespacePathSep));
|
|
44
31
|
return ((condition.category
|
|
45
32
|
? Arrayable.toArray(condition.category).includes(symbol.category)
|
|
46
|
-
: true)
|
|
47
|
-
(condition.namespace
|
|
33
|
+
: true)
|
|
34
|
+
&& (condition.namespace
|
|
48
35
|
? Arrayable.toArray(condition.namespace).includes(namespace)
|
|
49
|
-
: true)
|
|
50
|
-
(condition.excludeNamespace
|
|
36
|
+
: true)
|
|
37
|
+
&& (condition.excludeNamespace
|
|
51
38
|
? !Arrayable.toArray(condition.excludeNamespace).includes(namespace)
|
|
52
|
-
: true)
|
|
53
|
-
(condition.pattern
|
|
39
|
+
: true)
|
|
40
|
+
&& (condition.pattern
|
|
54
41
|
? Arrayable.toArray(condition.pattern).some((p) => new RegExp(p).test(symbol.identifier))
|
|
55
|
-
: true)
|
|
56
|
-
(condition.excludePattern
|
|
42
|
+
: true)
|
|
43
|
+
&& (condition.excludePattern
|
|
57
44
|
? !Arrayable.toArray(condition.excludePattern).some((p) => new RegExp(p).test(symbol.identifier))
|
|
58
45
|
: true));
|
|
59
46
|
}
|
|
@@ -7,7 +7,7 @@ import type { Project } from './Project.js';
|
|
|
7
7
|
* The format version of the cache. Should be increased when any changes that
|
|
8
8
|
* could invalidate the cache are introduced to the Spyglass codebase.
|
|
9
9
|
*/
|
|
10
|
-
export declare const LatestCacheVersion =
|
|
10
|
+
export declare const LatestCacheVersion = 3;
|
|
11
11
|
/**
|
|
12
12
|
* Checksums of cached files or roots.
|
|
13
13
|
*/
|
|
@@ -5,15 +5,11 @@ import { fileUtil } from './fileUtil.js';
|
|
|
5
5
|
* The format version of the cache. Should be increased when any changes that
|
|
6
6
|
* could invalidate the cache are introduced to the Spyglass codebase.
|
|
7
7
|
*/
|
|
8
|
-
export const LatestCacheVersion =
|
|
8
|
+
export const LatestCacheVersion = 3;
|
|
9
9
|
var Checksums;
|
|
10
10
|
(function (Checksums) {
|
|
11
11
|
function create() {
|
|
12
|
-
return {
|
|
13
|
-
files: {},
|
|
14
|
-
roots: {},
|
|
15
|
-
symbolRegistrars: {},
|
|
16
|
-
};
|
|
12
|
+
return { files: {}, roots: {}, symbolRegistrars: {} };
|
|
17
13
|
}
|
|
18
14
|
Checksums.create = create;
|
|
19
15
|
})(Checksums || (Checksums = {}));
|
|
@@ -36,8 +32,7 @@ export class CacheService {
|
|
|
36
32
|
}
|
|
37
33
|
try {
|
|
38
34
|
// TODO: Don't update this for every single change.
|
|
39
|
-
this.checksums.files[doc.uri] = await this.project.externals.crypto
|
|
40
|
-
.getSha1(doc.getText());
|
|
35
|
+
this.checksums.files[doc.uri] = await this.project.externals.crypto.getSha1(doc.getText());
|
|
41
36
|
}
|
|
42
37
|
catch (e) {
|
|
43
38
|
if (!this.project.externals.error.isKind(e, 'EISDIR')) {
|
|
@@ -128,7 +123,11 @@ export class CacheService {
|
|
|
128
123
|
}
|
|
129
124
|
}
|
|
130
125
|
for (const [uri, checksum] of Object.entries(this.checksums.files)) {
|
|
131
|
-
if (unchangedRoots.some((root) =>
|
|
126
|
+
if (unchangedRoots.some((root) => fileUtil.isSubUriOf(uri, root))) {
|
|
127
|
+
ans.unchangedFiles.push(uri);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (this.project.ignore.ignores(uri)) {
|
|
132
131
|
ans.unchangedFiles.push(uri);
|
|
133
132
|
continue;
|
|
134
133
|
}
|
|
@@ -142,8 +141,8 @@ export class CacheService {
|
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
catch (e) {
|
|
145
|
-
if (this.project.externals.error.isKind(e, 'ENOENT')
|
|
146
|
-
this.project.externals.error.isKind(e, 'EISDIR')) {
|
|
144
|
+
if (this.project.externals.error.isKind(e, 'ENOENT')
|
|
145
|
+
|| this.project.externals.error.isKind(e, 'EISDIR')) {
|
|
147
146
|
ans.removedFiles.push(uri);
|
|
148
147
|
}
|
|
149
148
|
else {
|
|
@@ -187,8 +186,8 @@ export class CacheService {
|
|
|
187
186
|
return false;
|
|
188
187
|
}
|
|
189
188
|
async hasFileChangedSinceCache(doc) {
|
|
190
|
-
return (this.checksums.files[doc.uri]
|
|
191
|
-
(await this.project.externals.crypto.getSha1(doc.getText())));
|
|
189
|
+
return (this.checksums.files[doc.uri]
|
|
190
|
+
!== (await this.project.externals.crypto.getSha1(doc.getText())));
|
|
192
191
|
}
|
|
193
192
|
reset() {
|
|
194
193
|
this.#hasValidatedFiles = false;
|
package/lib/service/Config.d.ts
CHANGED
|
@@ -21,6 +21,28 @@ export interface Config {
|
|
|
21
21
|
*/
|
|
22
22
|
snippet: SnippetsConfig;
|
|
23
23
|
}
|
|
24
|
+
export interface CustomResourceConfig {
|
|
25
|
+
/**
|
|
26
|
+
* The entry you have dispatched from mcdoc. (eg. `picoblaze:game_event`)
|
|
27
|
+
*/
|
|
28
|
+
category: string;
|
|
29
|
+
/**
|
|
30
|
+
* The file extension name of the dispatched resource. Only `.json` is supported for now.
|
|
31
|
+
*/
|
|
32
|
+
ext?: '.json';
|
|
33
|
+
/**
|
|
34
|
+
* The pack type of the dispatched resource. Only `data` is supported for now.
|
|
35
|
+
*/
|
|
36
|
+
pack?: 'data';
|
|
37
|
+
/**
|
|
38
|
+
* The first minecraft version the dispatched resource is available in.
|
|
39
|
+
*/
|
|
40
|
+
since?: `1.${number}`;
|
|
41
|
+
/**
|
|
42
|
+
* The first minecraft version the dispatched resource is no longer available in.
|
|
43
|
+
*/
|
|
44
|
+
until?: `1.${number}`;
|
|
45
|
+
}
|
|
24
46
|
export interface EnvConfig {
|
|
25
47
|
/**
|
|
26
48
|
* Where to download data like `mcmeta` or `vanilla-mcdoc` from (case-insensitive).
|
|
@@ -36,6 +58,20 @@ export interface EnvConfig {
|
|
|
36
58
|
* to a data pack folder or data pack archive (e.g. `.zip` or `.tar.gz`), or a special string like `@vanilla-mcdoc`.
|
|
37
59
|
*/
|
|
38
60
|
dependencies: string[];
|
|
61
|
+
/**
|
|
62
|
+
* A list of file patterns to exclude. Each value in this array can either be a glob pattern or the special string `@gitignore`.
|
|
63
|
+
*/
|
|
64
|
+
exclude: string[];
|
|
65
|
+
/**
|
|
66
|
+
* **Experimental feature, breaking changes could occur.**
|
|
67
|
+
*
|
|
68
|
+
* Track changes at [issue #1254](https://github.com/SpyglassMC/Spyglass/issues/1254).
|
|
69
|
+
*
|
|
70
|
+
* Custom resources, currently only works for `minecraft:resource` JSON definitions dispatched from mcdoc.
|
|
71
|
+
*/
|
|
72
|
+
customResources: {
|
|
73
|
+
[path: string]: CustomResourceConfig;
|
|
74
|
+
};
|
|
39
75
|
feature: {
|
|
40
76
|
codeActions: boolean;
|
|
41
77
|
colors: boolean;
|
package/lib/service/Config.js
CHANGED
|
@@ -4,10 +4,10 @@ import { FileCategories, RegistryCategories } from '../symbol/index.js';
|
|
|
4
4
|
export var LinterSeverity;
|
|
5
5
|
(function (LinterSeverity) {
|
|
6
6
|
function is(value) {
|
|
7
|
-
return (value === 'hint'
|
|
8
|
-
value === 'information'
|
|
9
|
-
value === 'warning'
|
|
10
|
-
value === 'error');
|
|
7
|
+
return (value === 'hint'
|
|
8
|
+
|| value === 'information'
|
|
9
|
+
|| value === 'warning'
|
|
10
|
+
|| value === 'error');
|
|
11
11
|
}
|
|
12
12
|
LinterSeverity.is = is;
|
|
13
13
|
function toErrorSeverity(value) {
|
|
@@ -31,21 +31,12 @@ export var LinterConfigValue;
|
|
|
31
31
|
return undefined;
|
|
32
32
|
}
|
|
33
33
|
if (LinterSeverity.is(value)) {
|
|
34
|
-
return {
|
|
35
|
-
ruleSeverity: LinterSeverity.toErrorSeverity(value),
|
|
36
|
-
ruleValue: true,
|
|
37
|
-
};
|
|
34
|
+
return { ruleSeverity: LinterSeverity.toErrorSeverity(value), ruleValue: true };
|
|
38
35
|
}
|
|
39
36
|
if (Array.isArray(value) && LinterSeverity.is(value[0])) {
|
|
40
|
-
return {
|
|
41
|
-
ruleSeverity: LinterSeverity.toErrorSeverity(value[0]),
|
|
42
|
-
ruleValue: value[1],
|
|
43
|
-
};
|
|
37
|
+
return { ruleSeverity: LinterSeverity.toErrorSeverity(value[0]), ruleValue: value[1] };
|
|
44
38
|
}
|
|
45
|
-
return {
|
|
46
|
-
ruleSeverity: 2 /* ErrorSeverity.Warning */,
|
|
47
|
-
ruleValue: value,
|
|
48
|
-
};
|
|
39
|
+
return { ruleSeverity: 2 /* ErrorSeverity.Warning */, ruleValue: value };
|
|
49
40
|
}
|
|
50
41
|
LinterConfigValue.destruct = destruct;
|
|
51
42
|
})(LinterConfigValue || (LinterConfigValue = {}));
|
|
@@ -62,10 +53,9 @@ export var SymbolLinterConfig;
|
|
|
62
53
|
return false;
|
|
63
54
|
}
|
|
64
55
|
const value = v;
|
|
65
|
-
return ((value.if === undefined || Arrayable.is(value.if, Condition.is))
|
|
66
|
-
(value.then === undefined || Action.is(value.then))
|
|
67
|
-
(value.override === undefined ||
|
|
68
|
-
Arrayable.is(value.override, Complex.is)));
|
|
56
|
+
return ((value.if === undefined || Arrayable.is(value.if, Condition.is))
|
|
57
|
+
&& (value.then === undefined || Action.is(value.then))
|
|
58
|
+
&& (value.override === undefined || Arrayable.is(value.override, Complex.is)));
|
|
69
59
|
}
|
|
70
60
|
Complex.is = is;
|
|
71
61
|
})(Complex = SymbolLinterConfig.Complex || (SymbolLinterConfig.Complex = {}));
|
|
@@ -76,29 +66,28 @@ export var SymbolLinterConfig;
|
|
|
76
66
|
return false;
|
|
77
67
|
}
|
|
78
68
|
const value = v;
|
|
79
|
-
return ((value.category === undefined
|
|
80
|
-
Arrayable.is(value.category, TypePredicates.isString))
|
|
81
|
-
(value.pattern === undefined ||
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Arrayable.is(value.excludeNamespace, TypePredicates.isString)));
|
|
69
|
+
return ((value.category === undefined
|
|
70
|
+
|| Arrayable.is(value.category, TypePredicates.isString))
|
|
71
|
+
&& (value.pattern === undefined || Arrayable.is(value.pattern, TypePredicates.isString))
|
|
72
|
+
&& (value.excludePattern === undefined
|
|
73
|
+
|| Arrayable.is(value.excludePattern, TypePredicates.isString))
|
|
74
|
+
&& (value.namespace === undefined
|
|
75
|
+
|| Arrayable.is(value.namespace, TypePredicates.isString))
|
|
76
|
+
&& (value.excludeNamespace === undefined
|
|
77
|
+
|| Arrayable.is(value.excludeNamespace, TypePredicates.isString)));
|
|
89
78
|
}
|
|
90
79
|
Condition.is = is;
|
|
91
80
|
})(Condition = SymbolLinterConfig.Condition || (SymbolLinterConfig.Condition = {}));
|
|
92
81
|
let Action;
|
|
93
82
|
(function (Action) {
|
|
94
83
|
function isDeclare(value) {
|
|
95
|
-
return (value !== undefined
|
|
96
|
-
['block', 'file', 'public'].includes(value.declare));
|
|
84
|
+
return (value !== undefined
|
|
85
|
+
&& ['block', 'file', 'public'].includes(value.declare));
|
|
97
86
|
}
|
|
98
87
|
Action.isDeclare = isDeclare;
|
|
99
88
|
function isReport(value) {
|
|
100
|
-
return (value !== undefined
|
|
101
|
-
['inherit', 'hint', 'information', 'warning', 'error'].includes(value.report));
|
|
89
|
+
return (value !== undefined
|
|
90
|
+
&& ['inherit', 'hint', 'information', 'warning', 'error'].includes(value.report));
|
|
102
91
|
}
|
|
103
92
|
Action.isReport = isReport;
|
|
104
93
|
function is(v) {
|
|
@@ -117,10 +106,9 @@ export var SymbolLinterConfig;
|
|
|
117
106
|
export const VanillaConfig = {
|
|
118
107
|
env: {
|
|
119
108
|
dataSource: 'GitHub',
|
|
120
|
-
dependencies: [
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
],
|
|
109
|
+
dependencies: ['@vanilla-datapack', '@vanilla-mcdoc'],
|
|
110
|
+
exclude: ['@gitignore', '.vscode/', '.github/'],
|
|
111
|
+
customResources: {},
|
|
124
112
|
feature: {
|
|
125
113
|
codeActions: true,
|
|
126
114
|
colors: true,
|
|
@@ -204,9 +192,7 @@ export const VanillaConfig = {
|
|
|
204
192
|
{
|
|
205
193
|
if: [
|
|
206
194
|
{ category: RegistryCategories, namespace: 'minecraft' },
|
|
207
|
-
{
|
|
208
|
-
category: [...FileCategories, 'bossbar', 'objective', 'team'],
|
|
209
|
-
},
|
|
195
|
+
{ category: [...FileCategories, 'bossbar', 'objective', 'team'] },
|
|
210
196
|
],
|
|
211
197
|
then: { report: 'warning' },
|
|
212
198
|
},
|
|
@@ -223,10 +209,7 @@ export const VanillaConfig = {
|
|
|
223
209
|
export class ConfigService {
|
|
224
210
|
project;
|
|
225
211
|
defaultConfig;
|
|
226
|
-
static ConfigFileNames = Object.freeze([
|
|
227
|
-
'spyglass.json',
|
|
228
|
-
'.spyglassrc.json',
|
|
229
|
-
]);
|
|
212
|
+
static ConfigFileNames = Object.freeze(['spyglass.json', '.spyglassrc.json']);
|
|
230
213
|
#eventEmitter;
|
|
231
214
|
constructor(project, defaultConfig = VanillaConfig) {
|
|
232
215
|
this.project = project;
|
package/lib/service/Context.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { ProfilerFactory } from './Profiler.js';
|
|
|
13
13
|
import type { ProjectData } from './Project.js';
|
|
14
14
|
export interface ContextBase {
|
|
15
15
|
fs: FileService;
|
|
16
|
+
isDebugging: boolean;
|
|
16
17
|
logger: Logger;
|
|
17
18
|
meta: MetaRegistry;
|
|
18
19
|
profilers: ProfilerFactory;
|
|
@@ -137,6 +138,7 @@ export declare namespace SignatureHelpProviderContext {
|
|
|
137
138
|
function create(project: ProjectData, opts: SignatureHelpProviderContextOptions): SignatureHelpProviderContext;
|
|
138
139
|
}
|
|
139
140
|
export interface UriBinderContext extends ContextBase {
|
|
141
|
+
config: Config;
|
|
140
142
|
symbols: SymbolUtil;
|
|
141
143
|
}
|
|
142
144
|
export declare namespace UriBinderContext {
|
package/lib/service/Context.js
CHANGED
|
@@ -7,6 +7,7 @@ export var ContextBase;
|
|
|
7
7
|
function create(project) {
|
|
8
8
|
return {
|
|
9
9
|
fs: project.fs,
|
|
10
|
+
isDebugging: project.isDebugging,
|
|
10
11
|
logger: project.logger,
|
|
11
12
|
meta: project.meta,
|
|
12
13
|
profilers: project.profilers,
|
|
@@ -44,20 +45,14 @@ export var ProcessorContext;
|
|
|
44
45
|
var ProcessorWithRangeContext;
|
|
45
46
|
(function (ProcessorWithRangeContext) {
|
|
46
47
|
function create(project, opts) {
|
|
47
|
-
return {
|
|
48
|
-
...ProcessorContext.create(project, opts),
|
|
49
|
-
range: opts.range,
|
|
50
|
-
};
|
|
48
|
+
return { ...ProcessorContext.create(project, opts), range: opts.range };
|
|
51
49
|
}
|
|
52
50
|
ProcessorWithRangeContext.create = create;
|
|
53
51
|
})(ProcessorWithRangeContext || (ProcessorWithRangeContext = {}));
|
|
54
52
|
var ProcessorWithOffsetContext;
|
|
55
53
|
(function (ProcessorWithOffsetContext) {
|
|
56
54
|
function create(project, opts) {
|
|
57
|
-
return {
|
|
58
|
-
...ProcessorContext.create(project, opts),
|
|
59
|
-
offset: opts.offset,
|
|
60
|
-
};
|
|
55
|
+
return { ...ProcessorContext.create(project, opts), offset: opts.offset };
|
|
61
56
|
}
|
|
62
57
|
ProcessorWithOffsetContext.create = create;
|
|
63
58
|
})(ProcessorWithOffsetContext || (ProcessorWithOffsetContext = {}));
|
|
@@ -137,10 +132,7 @@ export var SignatureHelpProviderContext;
|
|
|
137
132
|
export var UriBinderContext;
|
|
138
133
|
(function (UriBinderContext) {
|
|
139
134
|
function create(project) {
|
|
140
|
-
return {
|
|
141
|
-
...ContextBase.create(project),
|
|
142
|
-
symbols: project.symbols,
|
|
143
|
-
};
|
|
135
|
+
return { ...ContextBase.create(project), config: project.config, symbols: project.symbols };
|
|
144
136
|
}
|
|
145
137
|
UriBinderContext.create = create;
|
|
146
138
|
})(UriBinderContext || (UriBinderContext = {}));
|