@spyglassmc/core 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/Dev.js +5 -2
- package/lib/common/Operations.js +7 -3
- package/lib/common/ReadonlyProxy.js +3 -1
- package/lib/common/StateProxy.js +18 -7
- package/lib/common/externals/BrowserExternals.js +2 -9
- package/lib/common/externals/NodeJsExternals.js +7 -17
- package/lib/common/externals/index.d.ts +0 -3
- package/lib/common/util.d.ts +1 -0
- package/lib/common/util.js +14 -10
- package/lib/node/AstNode.js +6 -4
- package/lib/node/FileNode.js +6 -1
- package/lib/node/ResourceLocationNode.d.ts +2 -2
- package/lib/node/ResourceLocationNode.js +11 -5
- package/lib/parser/boolean.js +1 -1
- package/lib/parser/comment.d.ts +1 -1
- package/lib/parser/comment.js +1 -1
- package/lib/parser/float.js +2 -1
- package/lib/parser/integer.js +2 -1
- package/lib/parser/list.d.ts +1 -1
- package/lib/parser/list.js +3 -3
- package/lib/parser/long.js +2 -1
- package/lib/parser/record.d.ts +1 -1
- package/lib/parser/record.js +18 -8
- package/lib/parser/resourceLocation.js +61 -8
- package/lib/parser/string.js +75 -7
- package/lib/parser/util.d.ts +1 -0
- package/lib/parser/util.js +8 -4
- package/lib/processor/ColorInfoProvider.js +20 -7
- package/lib/processor/binder/builtin.js +27 -17
- package/lib/processor/checker/builtin.d.ts +1 -2
- package/lib/processor/checker/builtin.js +10 -12
- package/lib/processor/colorizer/builtin.js +10 -8
- package/lib/processor/completer/Completer.js +4 -2
- package/lib/processor/completer/builtin.js +26 -23
- package/lib/processor/formatter/builtin.js +14 -12
- package/lib/processor/linter/builtin/undeclaredSymbol.js +47 -24
- package/lib/processor/linter/builtin.js +7 -8
- package/lib/service/CacheService.d.ts +5 -2
- package/lib/service/CacheService.js +21 -9
- package/lib/service/Config.d.ts +2 -2
- package/lib/service/Config.js +23 -19
- package/lib/service/Downloader.js +12 -7
- package/lib/service/FileService.js +22 -8
- package/lib/service/MetaRegistry.d.ts +5 -0
- package/lib/service/MetaRegistry.js +7 -6
- package/lib/service/Profiler.js +10 -5
- package/lib/service/Project.d.ts +9 -7
- package/lib/service/Project.js +62 -36
- package/lib/service/Service.js +19 -9
- package/lib/service/fileUtil.js +2 -1
- package/lib/source/IndexMap.js +1 -1
- package/lib/source/LanguageError.d.ts +18 -4
- package/lib/source/LanguageError.js +16 -6
- package/lib/source/Location.js +4 -1
- package/lib/source/PositionRange.d.ts +1 -1
- package/lib/source/PositionRange.js +4 -4
- package/lib/source/Range.js +6 -3
- package/lib/source/Source.d.ts +2 -0
- package/lib/source/Source.js +9 -1
- package/lib/symbol/Symbol.d.ts +7 -7
- package/lib/symbol/Symbol.js +22 -9
- package/lib/symbol/SymbolUtil.d.ts +2 -2
- package/lib/symbol/SymbolUtil.js +74 -43
- package/package.json +2 -2
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
2
1
|
import { Arrayable, ResourceLocation } from '../../../common/index.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { SymbolLinterConfig as Config } from '../../../service/index.js';
|
|
3
|
+
// import { localeQuote, localize } from '@spyglassmc/locales'
|
|
4
|
+
// import type { DeepReadonly } from '../../../common/index.js'
|
|
5
|
+
// import { Arrayable, ResourceLocation } from '../../../common/index.js'
|
|
6
|
+
// import type { AstNode } from '../../../node/index.js'
|
|
7
|
+
// import type { LinterContext } from '../../../service/index.js'
|
|
8
|
+
// import { LinterSeverity, SymbolLinterConfig as Config } from '../../../service/index.js'
|
|
9
|
+
// import type { Symbol } from '../../../symbol/index.js'
|
|
10
|
+
// import { SymbolUtil, SymbolVisibility } from '../../../symbol/index.js'
|
|
11
|
+
// import type { Linter } from '../Linter.js'
|
|
5
12
|
export const undeclaredSymbol = (node, ctx) => {
|
|
6
|
-
if (!node.symbol || SymbolUtil.isDeclared(node.symbol)) {
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
const action = getAction(ctx.ruleValue, node.symbol, ctx)
|
|
10
|
-
if (Config.Action.isDeclare(action)) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
if (Config.Action.isReport(action)) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
// if (!node.symbol || SymbolUtil.isDeclared(node.symbol)) {
|
|
14
|
+
// return
|
|
15
|
+
// }
|
|
16
|
+
// const action = getAction(ctx.ruleValue as Config, node.symbol, ctx)
|
|
17
|
+
// if (Config.Action.isDeclare(action)) {
|
|
18
|
+
// ctx.symbols
|
|
19
|
+
// .query({ doc: ctx.doc, node }, node.symbol.category, ...node.symbol.path)
|
|
20
|
+
// .amend({
|
|
21
|
+
// data: { visibility: getVisibility(action.declare) },
|
|
22
|
+
// usage: { type: 'declaration', node },
|
|
23
|
+
// })
|
|
24
|
+
// }
|
|
25
|
+
// if (Config.Action.isReport(action)) {
|
|
26
|
+
// const severityOverride = action.report === 'inherit' ? undefined : LinterSeverity.toErrorSeverity(action.report)
|
|
27
|
+
// ctx.err.lint(
|
|
28
|
+
// localize('linter.undeclared-symbol.message',
|
|
29
|
+
// node.symbol.category,
|
|
30
|
+
// localeQuote(node.symbol.identifier)
|
|
31
|
+
// ),
|
|
32
|
+
// node, undefined, severityOverride
|
|
33
|
+
// )
|
|
34
|
+
// }
|
|
22
35
|
};
|
|
23
36
|
function getAction(config, symbol, ctx) {
|
|
24
37
|
if (Config.Action.is(config)) {
|
|
@@ -28,11 +41,21 @@ function getAction(config, symbol, ctx) {
|
|
|
28
41
|
function testSingleCondition(condition) {
|
|
29
42
|
const resourceLocation = ResourceLocation.lengthen(symbol.identifier);
|
|
30
43
|
const namespace = resourceLocation.slice(0, resourceLocation.indexOf(ResourceLocation.NamespacePathSep));
|
|
31
|
-
return ((condition.category
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
(condition.
|
|
35
|
-
|
|
44
|
+
return ((condition.category
|
|
45
|
+
? Arrayable.toArray(condition.category).includes(symbol.category)
|
|
46
|
+
: true) &&
|
|
47
|
+
(condition.namespace
|
|
48
|
+
? Arrayable.toArray(condition.namespace).includes(namespace)
|
|
49
|
+
: true) &&
|
|
50
|
+
(condition.excludeNamespace
|
|
51
|
+
? !Arrayable.toArray(condition.excludeNamespace).includes(namespace)
|
|
52
|
+
: true) &&
|
|
53
|
+
(condition.pattern
|
|
54
|
+
? Arrayable.toArray(condition.pattern).some((p) => new RegExp(p).test(symbol.identifier))
|
|
55
|
+
: true) &&
|
|
56
|
+
(condition.excludePattern
|
|
57
|
+
? !Arrayable.toArray(condition.excludePattern).some((p) => new RegExp(p).test(symbol.identifier))
|
|
58
|
+
: true));
|
|
36
59
|
}
|
|
37
60
|
try {
|
|
38
61
|
return Arrayable.toArray(conditions).some(testSingleCondition);
|
|
@@ -28,7 +28,7 @@ export function nameConvention(key) {
|
|
|
28
28
|
export const quote = (node, ctx) => {
|
|
29
29
|
const config = ctx.ruleValue;
|
|
30
30
|
const mustValueBeQuoted = node.options.unquotable
|
|
31
|
-
? [...node.value].some(c => !isAllowedCharacter(c, node.options.unquotable))
|
|
31
|
+
? [...node.value].some((c) => !isAllowedCharacter(c, node.options.unquotable))
|
|
32
32
|
: true;
|
|
33
33
|
const isQuoteRequired = config.always || mustValueBeQuoted;
|
|
34
34
|
const isQuoteProhibited = config.always === false && !mustValueBeQuoted;
|
|
@@ -66,8 +66,7 @@ export var configValidator;
|
|
|
66
66
|
new RegExp(val);
|
|
67
67
|
}
|
|
68
68
|
catch (e) {
|
|
69
|
-
logger.error(wrapError(name, localize('')
|
|
70
|
-
), e);
|
|
69
|
+
logger.error(wrapError(name, localize('')), e);
|
|
71
70
|
return false;
|
|
72
71
|
}
|
|
73
72
|
return true;
|
|
@@ -82,27 +81,27 @@ export function registerLinters(meta) {
|
|
|
82
81
|
meta.registerLinter('nameOfObjective', {
|
|
83
82
|
configValidator: configValidator.nameConvention,
|
|
84
83
|
linter: nameConvention('value'),
|
|
85
|
-
nodePredicate: n => n.symbol && n.symbol.category === 'objective',
|
|
84
|
+
nodePredicate: (n) => n.symbol && n.symbol.category === 'objective',
|
|
86
85
|
});
|
|
87
86
|
meta.registerLinter('nameOfScoreHolder', {
|
|
88
87
|
configValidator: configValidator.nameConvention,
|
|
89
88
|
linter: nameConvention('value'),
|
|
90
|
-
nodePredicate: n => n.symbol && n.symbol.category === 'score_holder',
|
|
89
|
+
nodePredicate: (n) => n.symbol && n.symbol.category === 'score_holder',
|
|
91
90
|
});
|
|
92
91
|
meta.registerLinter('nameOfTag', {
|
|
93
92
|
configValidator: configValidator.nameConvention,
|
|
94
93
|
linter: nameConvention('value'),
|
|
95
|
-
nodePredicate: n => n.symbol && n.symbol.category === 'tag',
|
|
94
|
+
nodePredicate: (n) => n.symbol && n.symbol.category === 'tag',
|
|
96
95
|
});
|
|
97
96
|
meta.registerLinter('nameOfTeam', {
|
|
98
97
|
configValidator: configValidator.nameConvention,
|
|
99
98
|
linter: nameConvention('value'),
|
|
100
|
-
nodePredicate: n => n.symbol && n.symbol.category === 'team',
|
|
99
|
+
nodePredicate: (n) => n.symbol && n.symbol.category === 'team',
|
|
101
100
|
});
|
|
102
101
|
meta.registerLinter('undeclaredSymbol', {
|
|
103
102
|
configValidator: configValidator.symbolLinterConfig,
|
|
104
103
|
linter: undeclaredSymbol,
|
|
105
|
-
nodePredicate: n => n.symbol && !McdocCategories.includes(n.symbol.category),
|
|
104
|
+
nodePredicate: (n) => n.symbol && !McdocCategories.includes(n.symbol.category),
|
|
106
105
|
});
|
|
107
106
|
}
|
|
108
107
|
//# sourceMappingURL=builtin.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
2
|
+
import type { PosRangeLanguageError } from '../source/index.js';
|
|
2
3
|
import { SymbolTable } from '../symbol/index.js';
|
|
3
4
|
import type { RootUriString } from './fileUtil.js';
|
|
4
5
|
import type { Project } from './Project.js';
|
|
@@ -6,7 +7,7 @@ import type { Project } from './Project.js';
|
|
|
6
7
|
* The format version of the cache. Should be increased when any changes that
|
|
7
8
|
* could invalidate the cache are introduced to the Spyglass codebase.
|
|
8
9
|
*/
|
|
9
|
-
export declare const LatestCacheVersion =
|
|
10
|
+
export declare const LatestCacheVersion = 2;
|
|
10
11
|
/**
|
|
11
12
|
* Checksums of cached files or roots.
|
|
12
13
|
*/
|
|
@@ -18,6 +19,7 @@ interface Checksums {
|
|
|
18
19
|
declare namespace Checksums {
|
|
19
20
|
function create(): Checksums;
|
|
20
21
|
}
|
|
22
|
+
declare type ErrorCache = Record<string, readonly PosRangeLanguageError[]>;
|
|
21
23
|
interface LoadResult {
|
|
22
24
|
symbols: SymbolTable;
|
|
23
25
|
}
|
|
@@ -32,6 +34,7 @@ export declare class CacheService {
|
|
|
32
34
|
private readonly cacheRoot;
|
|
33
35
|
private readonly project;
|
|
34
36
|
checksums: Checksums;
|
|
37
|
+
errors: ErrorCache;
|
|
35
38
|
/**
|
|
36
39
|
* @param cacheRoot File path to the directory where cache files by Spyglass should be stored.
|
|
37
40
|
* @param project
|
|
@@ -50,7 +53,7 @@ export declare class CacheService {
|
|
|
50
53
|
*/
|
|
51
54
|
save(): Promise<boolean>;
|
|
52
55
|
hasFileChangedSinceCache(doc: TextDocument): Promise<boolean>;
|
|
53
|
-
reset():
|
|
56
|
+
reset(): LoadResult;
|
|
54
57
|
}
|
|
55
58
|
export {};
|
|
56
59
|
//# sourceMappingURL=CacheService.d.ts.map
|
|
@@ -5,7 +5,7 @@ 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 = 2;
|
|
9
9
|
var Checksums;
|
|
10
10
|
(function (Checksums) {
|
|
11
11
|
function create() {
|
|
@@ -21,6 +21,7 @@ export class CacheService {
|
|
|
21
21
|
cacheRoot;
|
|
22
22
|
project;
|
|
23
23
|
checksums = Checksums.create();
|
|
24
|
+
errors = {};
|
|
24
25
|
#hasValidatedFiles = false;
|
|
25
26
|
/**
|
|
26
27
|
* @param cacheRoot File path to the directory where cache files by Spyglass should be stored.
|
|
@@ -35,7 +36,8 @@ export class CacheService {
|
|
|
35
36
|
}
|
|
36
37
|
try {
|
|
37
38
|
// TODO: Don't update this for every single change.
|
|
38
|
-
this.checksums.files[doc.uri] =
|
|
39
|
+
this.checksums.files[doc.uri] =
|
|
40
|
+
await this.project.externals.crypto.getSha1(doc.getText());
|
|
39
41
|
}
|
|
40
42
|
catch (e) {
|
|
41
43
|
if (!this.project.externals.error.isKind(e, 'EISDIR')) {
|
|
@@ -63,6 +65,9 @@ export class CacheService {
|
|
|
63
65
|
this.checksums.symbolRegistrars[id] = checksum;
|
|
64
66
|
}
|
|
65
67
|
});
|
|
68
|
+
this.project.on('documentErrored', ({ uri, errors }) => {
|
|
69
|
+
this.errors[uri] = errors;
|
|
70
|
+
});
|
|
66
71
|
}
|
|
67
72
|
#cacheFilePath;
|
|
68
73
|
/**
|
|
@@ -71,7 +76,7 @@ export class CacheService {
|
|
|
71
76
|
* @returns `${cacheRoot}symbols/${sha1(projectRoot)}.json`
|
|
72
77
|
*/
|
|
73
78
|
async getCacheFileUri() {
|
|
74
|
-
return this.#cacheFilePath ??= new Uri(`symbols/${await this.project.externals.crypto.getSha1(this.project.projectRoot)}.json.gz`, this.cacheRoot).toString();
|
|
79
|
+
return (this.#cacheFilePath ??= new Uri(`symbols/${await this.project.externals.crypto.getSha1(this.project.projectRoot)}.json.gz`, this.cacheRoot).toString());
|
|
75
80
|
}
|
|
76
81
|
async load() {
|
|
77
82
|
const __profiler = this.project.profilers.get('cache#load');
|
|
@@ -80,10 +85,11 @@ export class CacheService {
|
|
|
80
85
|
try {
|
|
81
86
|
filePath = await this.getCacheFileUri();
|
|
82
87
|
this.project.logger.info(`[CacheService#load] symbolCachePath = “${filePath}”`);
|
|
83
|
-
const cache = await fileUtil.readGzippedJson(this.project.externals, filePath);
|
|
88
|
+
const cache = (await fileUtil.readGzippedJson(this.project.externals, filePath));
|
|
84
89
|
__profiler.task('Read File');
|
|
85
90
|
if (cache.version === LatestCacheVersion) {
|
|
86
91
|
this.checksums = cache.checksums;
|
|
92
|
+
this.errors = cache.errors;
|
|
87
93
|
ans.symbols = SymbolTable.link(cache.symbols);
|
|
88
94
|
__profiler.task('Link Symbols');
|
|
89
95
|
}
|
|
@@ -122,7 +128,7 @@ export class CacheService {
|
|
|
122
128
|
}
|
|
123
129
|
}
|
|
124
130
|
for (const [uri, checksum] of Object.entries(this.checksums.files)) {
|
|
125
|
-
if (unchangedRoots.some(root => uri.startsWith(root))) {
|
|
131
|
+
if (unchangedRoots.some((root) => uri.startsWith(root))) {
|
|
126
132
|
ans.unchangedFiles.push(uri);
|
|
127
133
|
continue;
|
|
128
134
|
}
|
|
@@ -136,7 +142,8 @@ export class CacheService {
|
|
|
136
142
|
}
|
|
137
143
|
}
|
|
138
144
|
catch (e) {
|
|
139
|
-
if (this.project.externals.error.isKind(e, 'ENOENT') ||
|
|
145
|
+
if (this.project.externals.error.isKind(e, 'ENOENT') ||
|
|
146
|
+
this.project.externals.error.isKind(e, 'EISDIR')) {
|
|
140
147
|
ans.removedFiles.push(uri);
|
|
141
148
|
}
|
|
142
149
|
else {
|
|
@@ -163,10 +170,11 @@ export class CacheService {
|
|
|
163
170
|
try {
|
|
164
171
|
filePath = await this.getCacheFileUri();
|
|
165
172
|
const cache = {
|
|
166
|
-
|
|
173
|
+
version: LatestCacheVersion,
|
|
167
174
|
projectRoot: this.project.projectRoot,
|
|
175
|
+
checksums: this.checksums,
|
|
168
176
|
symbols: SymbolTable.unlink(this.project.symbols.global),
|
|
169
|
-
|
|
177
|
+
errors: this.errors,
|
|
170
178
|
};
|
|
171
179
|
__profiler.task('Unlink Symbols');
|
|
172
180
|
await fileUtil.writeGzippedJson(this.project.externals, filePath, cache);
|
|
@@ -179,10 +187,14 @@ export class CacheService {
|
|
|
179
187
|
return false;
|
|
180
188
|
}
|
|
181
189
|
async hasFileChangedSinceCache(doc) {
|
|
182
|
-
return this.checksums.files[doc.uri] !==
|
|
190
|
+
return (this.checksums.files[doc.uri] !==
|
|
191
|
+
(await this.project.externals.crypto.getSha1(doc.getText())));
|
|
183
192
|
}
|
|
184
193
|
reset() {
|
|
194
|
+
this.#hasValidatedFiles = false;
|
|
185
195
|
this.checksums = Checksums.create();
|
|
196
|
+
this.errors = {};
|
|
197
|
+
return { symbols: {} };
|
|
186
198
|
}
|
|
187
199
|
}
|
|
188
200
|
//# sourceMappingURL=CacheService.js.map
|
package/lib/service/Config.d.ts
CHANGED
|
@@ -189,8 +189,8 @@ export declare namespace SymbolLinterConfig {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
/**
|
|
192
|
-
* Config which simulates the default vanilla command system.
|
|
193
|
-
*/
|
|
192
|
+
* Config which simulates the default vanilla command system.
|
|
193
|
+
*/
|
|
194
194
|
export declare const VanillaConfig: Config;
|
|
195
195
|
declare type ConfigEvent = {
|
|
196
196
|
config: Config;
|
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' ||
|
|
7
|
+
return (value === 'hint' ||
|
|
8
8
|
value === 'information' ||
|
|
9
9
|
value === 'warning' ||
|
|
10
|
-
value === 'error';
|
|
10
|
+
value === 'error');
|
|
11
11
|
}
|
|
12
12
|
LinterSeverity.is = is;
|
|
13
13
|
function toErrorSeverity(value) {
|
|
@@ -64,7 +64,8 @@ export var SymbolLinterConfig;
|
|
|
64
64
|
const value = v;
|
|
65
65
|
return ((value.if === undefined || Arrayable.is(value.if, Condition.is)) &&
|
|
66
66
|
(value.then === undefined || Action.is(value.then)) &&
|
|
67
|
-
(value.override === undefined ||
|
|
67
|
+
(value.override === undefined ||
|
|
68
|
+
Arrayable.is(value.override, Complex.is)));
|
|
68
69
|
}
|
|
69
70
|
Complex.is = is;
|
|
70
71
|
})(Complex = SymbolLinterConfig.Complex || (SymbolLinterConfig.Complex = {}));
|
|
@@ -75,22 +76,29 @@ export var SymbolLinterConfig;
|
|
|
75
76
|
return false;
|
|
76
77
|
}
|
|
77
78
|
const value = v;
|
|
78
|
-
return ((value.category === undefined ||
|
|
79
|
-
|
|
80
|
-
(value.
|
|
81
|
-
|
|
82
|
-
(value.
|
|
79
|
+
return ((value.category === undefined ||
|
|
80
|
+
Arrayable.is(value.category, TypePredicates.isString)) &&
|
|
81
|
+
(value.pattern === undefined ||
|
|
82
|
+
Arrayable.is(value.pattern, TypePredicates.isString)) &&
|
|
83
|
+
(value.excludePattern === undefined ||
|
|
84
|
+
Arrayable.is(value.excludePattern, TypePredicates.isString)) &&
|
|
85
|
+
(value.namespace === undefined ||
|
|
86
|
+
Arrayable.is(value.namespace, TypePredicates.isString)) &&
|
|
87
|
+
(value.excludeNamespace === undefined ||
|
|
88
|
+
Arrayable.is(value.excludeNamespace, TypePredicates.isString)));
|
|
83
89
|
}
|
|
84
90
|
Condition.is = is;
|
|
85
91
|
})(Condition = SymbolLinterConfig.Condition || (SymbolLinterConfig.Condition = {}));
|
|
86
92
|
let Action;
|
|
87
93
|
(function (Action) {
|
|
88
94
|
function isDeclare(value) {
|
|
89
|
-
return value !== undefined &&
|
|
95
|
+
return (value !== undefined &&
|
|
96
|
+
['block', 'file', 'public'].includes(value.declare));
|
|
90
97
|
}
|
|
91
98
|
Action.isDeclare = isDeclare;
|
|
92
99
|
function isReport(value) {
|
|
93
|
-
return value !== undefined &&
|
|
100
|
+
return (value !== undefined &&
|
|
101
|
+
['inherit', 'hint', 'information', 'warning', 'error'].includes(value.report));
|
|
94
102
|
}
|
|
95
103
|
Action.isReport = isReport;
|
|
96
104
|
function is(v) {
|
|
@@ -104,14 +112,12 @@ export var SymbolLinterConfig;
|
|
|
104
112
|
})(Action = SymbolLinterConfig.Action || (SymbolLinterConfig.Action = {}));
|
|
105
113
|
})(SymbolLinterConfig || (SymbolLinterConfig = {}));
|
|
106
114
|
/**
|
|
107
|
-
* Config which simulates the default vanilla command system.
|
|
108
|
-
*/
|
|
115
|
+
* Config which simulates the default vanilla command system.
|
|
116
|
+
*/
|
|
109
117
|
export const VanillaConfig = {
|
|
110
118
|
env: {
|
|
111
119
|
dataSource: 'GitHub',
|
|
112
|
-
dependencies: [
|
|
113
|
-
'@vanilla-mcdoc',
|
|
114
|
-
],
|
|
120
|
+
dependencies: ['@vanilla-mcdoc'],
|
|
115
121
|
feature: {
|
|
116
122
|
codeActions: true,
|
|
117
123
|
colors: true,
|
|
@@ -122,9 +128,7 @@ export const VanillaConfig = {
|
|
|
122
128
|
formatting: true,
|
|
123
129
|
hover: true,
|
|
124
130
|
inlayHint: {
|
|
125
|
-
enabledNodes: [
|
|
126
|
-
'mcfunction:command_child/unknown',
|
|
127
|
-
],
|
|
131
|
+
enabledNodes: ['mcfunction:command_child/unknown'],
|
|
128
132
|
},
|
|
129
133
|
semanticColoring: true,
|
|
130
134
|
selectionRanges: true,
|
|
@@ -253,7 +257,7 @@ export class ConfigService {
|
|
|
253
257
|
return ConfigService.merge(this.defaultConfig, ans);
|
|
254
258
|
}
|
|
255
259
|
static isConfigFile(uri) {
|
|
256
|
-
return ConfigService.ConfigFileNames.some(n => uri.endsWith(`/${n}`));
|
|
260
|
+
return ConfigService.ConfigFileNames.some((n) => uri.endsWith(`/${n}`));
|
|
257
261
|
}
|
|
258
262
|
static merge(base, ...overrides) {
|
|
259
263
|
// FIXME
|
|
@@ -30,17 +30,22 @@ export class Downloader {
|
|
|
30
30
|
out.cacheUri = cacheUri = new Uri(`downloader/${id}`, this.cacheRoot).toString();
|
|
31
31
|
cacheChecksumUri = new Uri(`downloader/${id}${checksumExtension}`, this.cacheRoot).toString();
|
|
32
32
|
try {
|
|
33
|
-
out.checksum = checksum = await this.download({
|
|
33
|
+
out.checksum = checksum = await this.download({
|
|
34
|
+
...checksumJob,
|
|
35
|
+
id: id + checksumExtension,
|
|
36
|
+
});
|
|
34
37
|
try {
|
|
35
|
-
const cacheChecksum = bufferToString(await fileUtil.readFile(this.externals, cacheChecksumUri))
|
|
36
|
-
.slice(0, -1); // Remove ending newline
|
|
38
|
+
const cacheChecksum = bufferToString(await fileUtil.readFile(this.externals, cacheChecksumUri)).slice(0, -1); // Remove ending newline
|
|
37
39
|
if (checksum === cacheChecksum) {
|
|
38
40
|
try {
|
|
39
41
|
const cachedBuffer = await fileUtil.readFile(this.externals, cacheUri);
|
|
40
42
|
if (ttl) {
|
|
41
|
-
this.#memoryCache.set(uri, {
|
|
43
|
+
this.#memoryCache.set(uri, {
|
|
44
|
+
buffer: cachedBuffer,
|
|
45
|
+
time: performance.now(),
|
|
46
|
+
});
|
|
42
47
|
}
|
|
43
|
-
const deserializer = cache.deserializer ?? (b => b);
|
|
48
|
+
const deserializer = cache.deserializer ?? ((b) => b);
|
|
44
49
|
const ans = await transformer(deserializer(cachedBuffer));
|
|
45
50
|
this.logger.info(`[Downloader] [${id}] Skipped downloading thanks to cache ${cacheChecksum}`);
|
|
46
51
|
return ans;
|
|
@@ -85,7 +90,7 @@ export class Downloader {
|
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
92
|
try {
|
|
88
|
-
const serializer = cache.serializer ?? (b => b);
|
|
93
|
+
const serializer = cache.serializer ?? ((b) => b);
|
|
89
94
|
await fileUtil.writeFile(this.externals, cacheUri, serializer(buffer));
|
|
90
95
|
}
|
|
91
96
|
catch (e) {
|
|
@@ -100,7 +105,7 @@ export class Downloader {
|
|
|
100
105
|
if (cache && cacheUri) {
|
|
101
106
|
try {
|
|
102
107
|
const cachedBuffer = await fileUtil.readFile(this.externals, cacheUri);
|
|
103
|
-
const deserializer = cache.deserializer ?? (b => b);
|
|
108
|
+
const deserializer = cache.deserializer ?? ((b) => b);
|
|
104
109
|
const ans = await transformer(deserializer(cachedBuffer));
|
|
105
110
|
this.logger.warn(`[Downloader] [${id}] Fell back to cached file “${cacheUri}”`);
|
|
106
111
|
return ans;
|
|
@@ -128,7 +128,8 @@ export class FileUriSupporter {
|
|
|
128
128
|
const files = new Map();
|
|
129
129
|
for (let { uri } of dependencies) {
|
|
130
130
|
try {
|
|
131
|
-
if (fileUtil.isFileUri(uri) &&
|
|
131
|
+
if (fileUtil.isFileUri(uri) &&
|
|
132
|
+
(await externals.fs.stat(uri)).isDirectory()) {
|
|
132
133
|
uri = fileUtil.ensureEndingSlash(uri);
|
|
133
134
|
roots.push(uri);
|
|
134
135
|
files.set(uri, await externals.fs.getAllFiles(uri));
|
|
@@ -150,7 +151,12 @@ export class ArchiveUriSupporter {
|
|
|
150
151
|
externals;
|
|
151
152
|
entries;
|
|
152
153
|
static Protocol = 'archive:';
|
|
153
|
-
static SupportedArchiveExtnames = [
|
|
154
|
+
static SupportedArchiveExtnames = [
|
|
155
|
+
'.tar',
|
|
156
|
+
'.tar.bz2',
|
|
157
|
+
'.tar.gz',
|
|
158
|
+
'.zip',
|
|
159
|
+
];
|
|
154
160
|
protocol = ArchiveUriSupporter.Protocol;
|
|
155
161
|
/**
|
|
156
162
|
* @param entries A map from archive URIs to unzipped entries.
|
|
@@ -204,7 +210,7 @@ export class ArchiveUriSupporter {
|
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
static getUri(archiveUri, pathInArchive = '') {
|
|
207
|
-
return `${ArchiveUriSupporter.Protocol}
|
|
213
|
+
return `${ArchiveUriSupporter.Protocol}${encodeURIComponent(archiveUri)}?path=${encodeURIComponent(pathInArchive.replace(/\\/g, '/'))}`;
|
|
208
214
|
}
|
|
209
215
|
/**
|
|
210
216
|
* @throws When `uri` has the wrong protocol or hostname.
|
|
@@ -213,16 +219,22 @@ export class ArchiveUriSupporter {
|
|
|
213
219
|
if (uri.protocol !== ArchiveUriSupporter.Protocol) {
|
|
214
220
|
throw new Error(`Expected protocol “${ArchiveUriSupporter.Protocol}” in “${uri}”`);
|
|
215
221
|
}
|
|
222
|
+
const path = uri.searchParams.get('path');
|
|
223
|
+
if (!path) {
|
|
224
|
+
throw new Error(`Missing path in archive uri “${uri.toString()}”`);
|
|
225
|
+
}
|
|
216
226
|
return {
|
|
217
|
-
archiveUri: decodeURIComponent(uri.
|
|
218
|
-
pathInArchive:
|
|
227
|
+
archiveUri: decodeURIComponent(uri.pathname),
|
|
228
|
+
pathInArchive: path.charAt(0) === '/' ? path.slice(1) : path,
|
|
219
229
|
};
|
|
220
230
|
}
|
|
221
231
|
static async create(dependencies, externals, logger, checksums) {
|
|
222
232
|
const entries = new Map();
|
|
223
233
|
for (const { uri, info } of dependencies) {
|
|
224
234
|
try {
|
|
225
|
-
if (uri.startsWith('file:') &&
|
|
235
|
+
if (uri.startsWith('file:') &&
|
|
236
|
+
ArchiveUriSupporter.SupportedArchiveExtnames.some((ext) => uri.endsWith(ext)) &&
|
|
237
|
+
(await externals.fs.stat(uri)).isFile()) {
|
|
226
238
|
const rootUri = ArchiveUriSupporter.getUri(uri);
|
|
227
239
|
const cachedChecksum = checksums[rootUri];
|
|
228
240
|
if (cachedChecksum !== undefined) {
|
|
@@ -233,8 +245,10 @@ export class ArchiveUriSupporter {
|
|
|
233
245
|
continue;
|
|
234
246
|
}
|
|
235
247
|
}
|
|
236
|
-
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), {
|
|
237
|
-
|
|
248
|
+
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), {
|
|
249
|
+
stripLevel: typeof info?.startDepth === 'number' ? info.startDepth : 0,
|
|
250
|
+
});
|
|
251
|
+
entries.set(uri, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
|
|
238
252
|
}
|
|
239
253
|
}
|
|
240
254
|
catch (e) {
|
|
@@ -26,6 +26,11 @@ interface LinterRegistration {
|
|
|
26
26
|
}
|
|
27
27
|
interface SymbolRegistrarRegistration {
|
|
28
28
|
registrar: SymbolRegistrar;
|
|
29
|
+
/**
|
|
30
|
+
* A checksum associated with this symbol registrar.
|
|
31
|
+
* If the cached checksum is equal to this provided checksum,
|
|
32
|
+
* the symbol registrar is not executed.
|
|
33
|
+
*/
|
|
29
34
|
checksum: string | undefined;
|
|
30
35
|
}
|
|
31
36
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Lazy } from '../common/index.js';
|
|
2
|
-
import { binder, checker, colorizer, completer, formatter, linter } from '../processor/index.js';
|
|
2
|
+
import { binder, checker, colorizer, completer, formatter, linter, } from '../processor/index.js';
|
|
3
3
|
/* istanbul ignore next */
|
|
4
4
|
/**
|
|
5
5
|
* The meta registry of Spyglass. You can register new parsers, processors, and languages here.
|
|
@@ -51,13 +51,13 @@ export class MetaRegistry {
|
|
|
51
51
|
* An array of file extensions (including the leading dot (`.`)) that are supported.
|
|
52
52
|
*/
|
|
53
53
|
getSupportedFileExtensions() {
|
|
54
|
-
return [...this.#languages.values()].flatMap(v => v.extensions);
|
|
54
|
+
return [...this.#languages.values()].flatMap((v) => v.extensions);
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* An array of characters that trigger a completion request.
|
|
58
58
|
*/
|
|
59
59
|
getTriggerCharacters() {
|
|
60
|
-
return Array.from(this.#languages.values()).flatMap(v => v.triggerCharacters ?? []);
|
|
60
|
+
return Array.from(this.#languages.values()).flatMap((v) => v.triggerCharacters ?? []);
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* @param fileExtension The file extension including the leading dot. e.g. `".mcfunction"`.
|
|
@@ -109,7 +109,8 @@ export class MetaRegistry {
|
|
|
109
109
|
}
|
|
110
110
|
shouldComplete(languageID, triggerCharacter) {
|
|
111
111
|
const language = this.#languages.get(languageID);
|
|
112
|
-
return !triggerCharacter ||
|
|
112
|
+
return (!triggerCharacter ||
|
|
113
|
+
!!language?.triggerCharacters?.includes(triggerCharacter));
|
|
113
114
|
}
|
|
114
115
|
getCompleterForLanguageID(languageID) {
|
|
115
116
|
return this.#languages.get(languageID)?.completer ?? completer.fallback;
|
|
@@ -136,11 +137,11 @@ export class MetaRegistry {
|
|
|
136
137
|
return this.#inlayHintProviders;
|
|
137
138
|
}
|
|
138
139
|
getLinter(ruleName) {
|
|
139
|
-
return this.#linters.get(ruleName) ?? {
|
|
140
|
+
return (this.#linters.get(ruleName) ?? {
|
|
140
141
|
configValidator: () => false,
|
|
141
142
|
linter: linter.noop,
|
|
142
143
|
nodePredicate: () => false,
|
|
143
|
-
};
|
|
144
|
+
});
|
|
144
145
|
}
|
|
145
146
|
registerLinter(ruleName, options) {
|
|
146
147
|
this.#linters.set(ruleName, options);
|
package/lib/service/Profiler.js
CHANGED
|
@@ -42,7 +42,7 @@ class TopNImpl {
|
|
|
42
42
|
this.logger.info(`[Profiler: ${this.id}] Min/Avg/Max: ${this.#minTime} / ${totalDuration / this.#taskCount} / ${this.#maxTime} ms`);
|
|
43
43
|
this.logger.info(`[Profiler: ${this.id}] Top ${Math.min(this.n, this.#topTasks.length)} task(s):`);
|
|
44
44
|
for (const [name, time] of this.#topTasks) {
|
|
45
|
-
this.logger.info(`[Profiler: ${this.id}] ${name}${' '.repeat(longestTaskNameLength - name.length)} - ${time} ms (${time / totalDuration * 100}%)`);
|
|
45
|
+
this.logger.info(`[Profiler: ${this.id}] ${name}${' '.repeat(longestTaskNameLength - name.length)} - ${time} ms (${(time / totalDuration) * 100}%)`);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -83,7 +83,9 @@ class TotalImpl {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
class NoopImpl {
|
|
86
|
-
task() {
|
|
86
|
+
task() {
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
87
89
|
finalize() { }
|
|
88
90
|
}
|
|
89
91
|
export class ProfilerFactory {
|
|
@@ -96,9 +98,12 @@ export class ProfilerFactory {
|
|
|
96
98
|
get(id, style = 'total', n) {
|
|
97
99
|
if (this.#enabledProfilers.has(id)) {
|
|
98
100
|
switch (style) {
|
|
99
|
-
case 'top-n':
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
case 'top-n':
|
|
102
|
+
return new TopNImpl(id, this.logger, n);
|
|
103
|
+
case 'total':
|
|
104
|
+
return new TotalImpl(id, this.logger);
|
|
105
|
+
default:
|
|
106
|
+
return Dev.assertNever(style);
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
else {
|