@spyglassmc/core 0.4.4 → 0.4.6
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 +1 -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 +6 -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 +67 -23
- 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 +71 -48
- 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
|
@@ -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 = [];
|
|
@@ -131,12 +144,32 @@ export const resourceLocation = (node, ctx) => {
|
|
|
131
144
|
? getPool(`tag/${node.options.category}`).map((v) => `${ResourceLocation.TagPrefix}${v}`)
|
|
132
145
|
: []),
|
|
133
146
|
];
|
|
134
|
-
|
|
147
|
+
const items = pool.map((v) => CompletionItem.create(v, node, { kind: 3 /* CompletionKind.Function */ }));
|
|
148
|
+
if (node.options.category) {
|
|
149
|
+
const symbols = ctx.symbols.getVisibleSymbols(node.options.category, ctx.doc.uri);
|
|
150
|
+
const thisKey = Object.entries(symbols).flatMap(([key, symbol]) => {
|
|
151
|
+
if ((symbol.declaration?.[0] ?? symbol.definition?.[0])?.uri == ctx.doc.uri) {
|
|
152
|
+
return [key];
|
|
153
|
+
}
|
|
154
|
+
return [];
|
|
155
|
+
});
|
|
156
|
+
if (thisKey.length > 0) {
|
|
157
|
+
items.push(CompletionItem.create('THIS', node, {
|
|
158
|
+
kind: 15 /* CompletionKind.Snippet */,
|
|
159
|
+
insertText: thisKey[0],
|
|
160
|
+
detail: thisKey[0],
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return items;
|
|
135
165
|
};
|
|
136
166
|
export const string = (node, ctx) => {
|
|
137
167
|
if (node.children?.length) {
|
|
138
|
-
|
|
139
|
-
|
|
168
|
+
return dispatch(node.children[0], ctx).map(item => ({
|
|
169
|
+
...item,
|
|
170
|
+
filterText: escapeString(item.filterText ?? item.label, node.quote),
|
|
171
|
+
insertText: escapeString(item.insertText ?? item.label, node.quote),
|
|
172
|
+
}));
|
|
140
173
|
}
|
|
141
174
|
if (node.options.quotes && node.value === '') {
|
|
142
175
|
return node.options.quotes.map((q) => CompletionItem.create(`${q}${q}`, node, {
|
|
@@ -146,8 +179,18 @@ export const string = (node, ctx) => {
|
|
|
146
179
|
}
|
|
147
180
|
return [];
|
|
148
181
|
};
|
|
182
|
+
export function escapeString(value, quote) {
|
|
183
|
+
if (!quote) {
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
return value.replaceAll('\\', '\\\\').replaceAll(quote, '\\"');
|
|
187
|
+
}
|
|
149
188
|
export const symbol = (node, ctx) => {
|
|
150
|
-
|
|
189
|
+
const path = node.options.parentPath ?? [];
|
|
190
|
+
const symbols = ctx.symbols.query(ctx.doc, node.options.category, ...path).visibleMembers;
|
|
191
|
+
return Object.entries(symbols)
|
|
192
|
+
.filter(([k, v]) => SymbolUtil.isDeclared(v))
|
|
193
|
+
.map(([k, v]) => CompletionItem.create(k, node, { kind: 6 /* CompletionKind.Variable */ }));
|
|
151
194
|
};
|
|
152
195
|
export function registerCompleters(meta) {
|
|
153
196
|
meta.registerCompleter('boolean', boolean);
|
|
@@ -156,6 +199,7 @@ export function registerCompleters(meta) {
|
|
|
156
199
|
meta.registerCompleter('integer', noop);
|
|
157
200
|
meta.registerCompleter('long', noop);
|
|
158
201
|
meta.registerCompleter('literal', literal);
|
|
202
|
+
meta.registerCompleter('prefixed', prefixed);
|
|
159
203
|
meta.registerCompleter('resource_location', resourceLocation);
|
|
160
204
|
meta.registerCompleter('string', string);
|
|
161
205
|
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 = {}));
|
|
@@ -13,9 +13,12 @@ export class Downloader {
|
|
|
13
13
|
async download(job, out = {}) {
|
|
14
14
|
const { id, cache, uri, options, transformer, ttl } = job;
|
|
15
15
|
if (ttl && this.#memoryCache.has(uri)) {
|
|
16
|
-
const
|
|
17
|
-
|
|
16
|
+
const memoryCacheEntry = this.#memoryCache.get(uri);
|
|
17
|
+
const { buffer, time, cacheUri, checksum } = memoryCacheEntry;
|
|
18
|
+
if (performance.now() <= time + ttl) {
|
|
18
19
|
this.logger.info(`[Downloader] [${id}] Skipped thanks to valid cache in memory`);
|
|
20
|
+
out.cacheUri = cacheUri;
|
|
21
|
+
out.checksum = checksum;
|
|
19
22
|
return await transformer(buffer);
|
|
20
23
|
}
|
|
21
24
|
else {
|
|
@@ -28,7 +31,8 @@ export class Downloader {
|
|
|
28
31
|
if (cache) {
|
|
29
32
|
const { checksumJob, checksumExtension } = cache;
|
|
30
33
|
out.cacheUri = cacheUri = new Uri(`downloader/${id}`, this.cacheRoot).toString();
|
|
31
|
-
cacheChecksumUri = new Uri(`downloader/${id}${checksumExtension}`, this.cacheRoot)
|
|
34
|
+
cacheChecksumUri = new Uri(`downloader/${id}${checksumExtension}`, this.cacheRoot)
|
|
35
|
+
.toString();
|
|
32
36
|
try {
|
|
33
37
|
out.checksum = checksum = await this.download({
|
|
34
38
|
...checksumJob,
|
|
@@ -42,6 +46,8 @@ export class Downloader {
|
|
|
42
46
|
if (ttl) {
|
|
43
47
|
this.#memoryCache.set(uri, {
|
|
44
48
|
buffer: cachedBuffer,
|
|
49
|
+
cacheUri,
|
|
50
|
+
checksum,
|
|
45
51
|
time: performance.now(),
|
|
46
52
|
});
|
|
47
53
|
}
|