@spyglassmc/core 0.4.0 → 0.4.2
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.d.ts +2 -2
- package/lib/common/ReadonlyProxy.js +3 -1
- package/lib/common/StateProxy.d.ts +2 -2
- package/lib/common/StateProxy.js +18 -7
- package/lib/common/externals/BrowserExternals.js +2 -9
- package/lib/common/externals/NodeJsExternals.js +11 -18
- package/lib/common/externals/downloader.d.ts +2 -2
- package/lib/common/externals/index.d.ts +2 -5
- package/lib/common/util.d.ts +8 -7
- package/lib/common/util.js +16 -12
- package/lib/node/AstNode.d.ts +1 -1
- package/lib/node/AstNode.js +9 -5
- package/lib/node/CommentNode.d.ts +2 -2
- package/lib/node/FileNode.js +6 -1
- package/lib/node/ResourceLocationNode.d.ts +3 -3
- package/lib/node/ResourceLocationNode.js +9 -5
- package/lib/node/StringNode.d.ts +3 -3
- package/lib/node/StringNode.js +4 -1
- package/lib/parser/Parser.d.ts +5 -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.d.ts +1 -1
- package/lib/parser/float.js +2 -1
- package/lib/parser/integer.d.ts +1 -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.d.ts +1 -1
- 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 +79 -8
- package/lib/parser/util.d.ts +7 -7
- package/lib/parser/util.js +14 -5
- package/lib/processor/ColorInfoProvider.d.ts +3 -3
- package/lib/processor/ColorInfoProvider.js +22 -7
- package/lib/processor/InlayHintProvider.d.ts +1 -1
- package/lib/processor/SignatureHelpProvider.d.ts +1 -1
- package/lib/processor/binder/Binder.d.ts +1 -1
- package/lib/processor/binder/builtin.d.ts +2 -2
- package/lib/processor/binder/builtin.js +30 -18
- package/lib/processor/binder/index.d.ts +1 -1
- package/lib/processor/binder/index.js +1 -1
- package/lib/processor/checker/Checker.d.ts +3 -3
- package/lib/processor/checker/builtin.d.ts +2 -3
- package/lib/processor/checker/builtin.js +12 -13
- package/lib/processor/colorizer/Colorizer.d.ts +3 -3
- package/lib/processor/colorizer/builtin.js +8 -7
- package/lib/processor/completer/Completer.d.ts +1 -1
- package/lib/processor/completer/Completer.js +4 -2
- package/lib/processor/completer/builtin.js +33 -26
- package/lib/processor/formatter/Formatter.d.ts +1 -1
- package/lib/processor/formatter/Formatter.js +3 -1
- package/lib/processor/formatter/builtin.js +14 -12
- package/lib/processor/linter/Linter.d.ts +1 -1
- package/lib/processor/linter/builtin/undeclaredSymbol.js +47 -24
- package/lib/processor/linter/builtin.js +7 -8
- package/lib/processor/util.d.ts +1 -1
- package/lib/service/CacheService.d.ts +1 -1
- package/lib/service/CacheService.js +9 -6
- package/lib/service/Config.d.ts +11 -11
- package/lib/service/Config.js +28 -21
- package/lib/service/Dependency.d.ts +3 -3
- package/lib/service/Downloader.js +12 -7
- package/lib/service/FileService.d.ts +1 -1
- package/lib/service/FileService.js +28 -10
- package/lib/service/MetaRegistry.js +7 -6
- package/lib/service/Profiler.js +10 -5
- package/lib/service/Project.d.ts +5 -5
- package/lib/service/Project.js +45 -34
- package/lib/service/Service.js +31 -12
- package/lib/service/SymbolRegistrar.d.ts +1 -1
- package/lib/service/UriProcessor.d.ts +3 -3
- package/lib/service/fileUtil.d.ts +2 -2
- package/lib/service/fileUtil.js +2 -1
- package/lib/source/IndexMap.d.ts +1 -1
- package/lib/source/IndexMap.js +1 -1
- package/lib/source/LanguageError.js +1 -1
- package/lib/source/Location.d.ts +1 -1
- package/lib/source/Location.js +4 -1
- package/lib/source/Offset.d.ts +1 -1
- package/lib/source/Range.d.ts +1 -1
- package/lib/source/Range.js +6 -3
- package/lib/source/Source.d.ts +4 -4
- package/lib/source/Source.js +3 -1
- package/lib/symbol/Symbol.d.ts +19 -19
- package/lib/symbol/Symbol.js +27 -12
- package/lib/symbol/SymbolUtil.d.ts +6 -6
- package/lib/symbol/SymbolUtil.js +76 -44
- package/package.json +2 -2
package/lib/processor/util.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DeepReadonly } from '../index.js';
|
|
2
2
|
import type { AstNode } from '../node/index.js';
|
|
3
|
-
|
|
3
|
+
type Callback<R> = (this: void, node: AstNode, parents: AstNode[]) => R;
|
|
4
4
|
export declare function traversePreOrder<CN extends AstNode>(node: DeepReadonly<AstNode>, shouldContinue: Callback<unknown>, shouldCallFn: (this: void, node: AstNode, parents: AstNode[]) => node is CN, fn: (this: void, node: CN, parents: AstNode[]) => void): void;
|
|
5
5
|
export declare function traversePreOrder(node: DeepReadonly<AstNode>, shouldContinue: Callback<unknown>, shouldCallFn: Callback<unknown>, fn: Callback<void>): void;
|
|
6
6
|
export {};
|
|
@@ -19,7 +19,7 @@ interface Checksums {
|
|
|
19
19
|
declare namespace Checksums {
|
|
20
20
|
function create(): Checksums;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
type ErrorCache = Record<string, readonly PosRangeLanguageError[]>;
|
|
23
23
|
interface LoadResult {
|
|
24
24
|
symbols: SymbolTable;
|
|
25
25
|
}
|
|
@@ -36,7 +36,8 @@ export class CacheService {
|
|
|
36
36
|
}
|
|
37
37
|
try {
|
|
38
38
|
// TODO: Don't update this for every single change.
|
|
39
|
-
this.checksums.files[doc.uri] = await this.project.externals.crypto
|
|
39
|
+
this.checksums.files[doc.uri] = await this.project.externals.crypto
|
|
40
|
+
.getSha1(doc.getText());
|
|
40
41
|
}
|
|
41
42
|
catch (e) {
|
|
42
43
|
if (!this.project.externals.error.isKind(e, 'EISDIR')) {
|
|
@@ -75,7 +76,7 @@ export class CacheService {
|
|
|
75
76
|
* @returns `${cacheRoot}symbols/${sha1(projectRoot)}.json`
|
|
76
77
|
*/
|
|
77
78
|
async getCacheFileUri() {
|
|
78
|
-
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());
|
|
79
80
|
}
|
|
80
81
|
async load() {
|
|
81
82
|
const __profiler = this.project.profilers.get('cache#load');
|
|
@@ -84,7 +85,7 @@ export class CacheService {
|
|
|
84
85
|
try {
|
|
85
86
|
filePath = await this.getCacheFileUri();
|
|
86
87
|
this.project.logger.info(`[CacheService#load] symbolCachePath = “${filePath}”`);
|
|
87
|
-
const cache = await fileUtil.readGzippedJson(this.project.externals, filePath);
|
|
88
|
+
const cache = (await fileUtil.readGzippedJson(this.project.externals, filePath));
|
|
88
89
|
__profiler.task('Read File');
|
|
89
90
|
if (cache.version === LatestCacheVersion) {
|
|
90
91
|
this.checksums = cache.checksums;
|
|
@@ -127,7 +128,7 @@ export class CacheService {
|
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
for (const [uri, checksum] of Object.entries(this.checksums.files)) {
|
|
130
|
-
if (unchangedRoots.some(root => uri.startsWith(root))) {
|
|
131
|
+
if (unchangedRoots.some((root) => uri.startsWith(root))) {
|
|
131
132
|
ans.unchangedFiles.push(uri);
|
|
132
133
|
continue;
|
|
133
134
|
}
|
|
@@ -141,7 +142,8 @@ export class CacheService {
|
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
catch (e) {
|
|
144
|
-
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')) {
|
|
145
147
|
ans.removedFiles.push(uri);
|
|
146
148
|
}
|
|
147
149
|
else {
|
|
@@ -185,7 +187,8 @@ export class CacheService {
|
|
|
185
187
|
return false;
|
|
186
188
|
}
|
|
187
189
|
async hasFileChangedSinceCache(doc) {
|
|
188
|
-
return this.checksums.files[doc.uri] !==
|
|
190
|
+
return (this.checksums.files[doc.uri] !==
|
|
191
|
+
(await this.project.externals.crypto.getSha1(doc.getText())));
|
|
189
192
|
}
|
|
190
193
|
reset() {
|
|
191
194
|
this.#hasValidatedFiles = false;
|
package/lib/service/Config.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface Config {
|
|
|
13
13
|
*/
|
|
14
14
|
format: FormatterConfig;
|
|
15
15
|
/**
|
|
16
|
-
*t Linter rules.
|
|
16
|
+
* t Linter rules.
|
|
17
17
|
*/
|
|
18
18
|
lint: LinterConfig;
|
|
19
19
|
/**
|
|
@@ -77,19 +77,19 @@ export interface EnvConfig {
|
|
|
77
77
|
permissionLevel: 1 | 2 | 3 | 4;
|
|
78
78
|
plugins: string[];
|
|
79
79
|
}
|
|
80
|
-
export
|
|
80
|
+
export type LinterSeverity = 'hint' | 'information' | 'warning' | 'error';
|
|
81
81
|
export declare namespace LinterSeverity {
|
|
82
82
|
function is(value: unknown): value is LinterSeverity;
|
|
83
83
|
function toErrorSeverity(value: LinterSeverity): ErrorSeverity;
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
export
|
|
85
|
+
type BracketSpacingConfig = any;
|
|
86
|
+
type SepSpacingConfig = any;
|
|
87
|
+
export type QuoteConfig = {
|
|
88
88
|
always?: boolean;
|
|
89
89
|
avoidEscape?: boolean | null;
|
|
90
90
|
type?: 'double' | 'single';
|
|
91
91
|
};
|
|
92
|
-
|
|
92
|
+
type LinterConfigValue<T> = T extends boolean ? null | T | [LinterSeverity, T] | LinterSeverity : null | T | [LinterSeverity, T];
|
|
93
93
|
export declare namespace LinterConfigValue {
|
|
94
94
|
function destruct(value: LinterConfigValue<boolean | string | number | object>): {
|
|
95
95
|
ruleSeverity: ErrorSeverity;
|
|
@@ -151,7 +151,7 @@ export interface LinterConfig {
|
|
|
151
151
|
export interface SnippetsConfig {
|
|
152
152
|
[label: string]: string;
|
|
153
153
|
}
|
|
154
|
-
export
|
|
154
|
+
export type SymbolLinterConfig = Arrayable<SymbolLinterConfig.Complex> | SymbolLinterConfig.Action;
|
|
155
155
|
export declare namespace SymbolLinterConfig {
|
|
156
156
|
function is(value: unknown): value is SymbolLinterConfig;
|
|
157
157
|
interface Complex {
|
|
@@ -189,13 +189,13 @@ 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
|
+
type ConfigEvent = {
|
|
196
196
|
config: Config;
|
|
197
197
|
};
|
|
198
|
-
|
|
198
|
+
type ErrorEvent = {
|
|
199
199
|
error: unknown;
|
|
200
200
|
uri: string;
|
|
201
201
|
};
|
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,
|
|
@@ -188,7 +192,9 @@ export const VanillaConfig = {
|
|
|
188
192
|
{
|
|
189
193
|
if: [
|
|
190
194
|
{ category: RegistryCategories, namespace: 'minecraft' },
|
|
191
|
-
{
|
|
195
|
+
{
|
|
196
|
+
category: [...FileCategories, 'bossbar', 'objective', 'team'],
|
|
197
|
+
},
|
|
192
198
|
],
|
|
193
199
|
then: { report: 'warning' },
|
|
194
200
|
},
|
|
@@ -202,7 +208,7 @@ export const VanillaConfig = {
|
|
|
202
208
|
summonAec: 'summon minecraft:area_effect_cloud ~ ~ ~ {Age: -2147483648, Duration: -1, WaitTime: -2147483648, Tags: ["${1:tag}"]}',
|
|
203
209
|
},
|
|
204
210
|
};
|
|
205
|
-
|
|
211
|
+
class ConfigService {
|
|
206
212
|
project;
|
|
207
213
|
defaultConfig;
|
|
208
214
|
static ConfigFileNames = Object.freeze([
|
|
@@ -253,7 +259,7 @@ export class ConfigService {
|
|
|
253
259
|
return ConfigService.merge(this.defaultConfig, ans);
|
|
254
260
|
}
|
|
255
261
|
static isConfigFile(uri) {
|
|
256
|
-
return ConfigService.ConfigFileNames.some(n => uri.endsWith(`/${n}`));
|
|
262
|
+
return ConfigService.ConfigFileNames.some((n) => uri.endsWith(`/${n}`));
|
|
257
263
|
}
|
|
258
264
|
static merge(base, ...overrides) {
|
|
259
265
|
// FIXME
|
|
@@ -266,4 +272,5 @@ export class ConfigService {
|
|
|
266
272
|
return ans;
|
|
267
273
|
}
|
|
268
274
|
}
|
|
275
|
+
export { ConfigService };
|
|
269
276
|
//# sourceMappingURL=Config.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type Dependency = {
|
|
2
2
|
uri: string;
|
|
3
3
|
info?: Record<string, any>;
|
|
4
4
|
};
|
|
5
|
-
export
|
|
5
|
+
export type DependencyKey = `@${string}`;
|
|
6
6
|
export declare namespace DependencyKey {
|
|
7
7
|
function is(value: string): value is DependencyKey;
|
|
8
8
|
}
|
|
9
|
-
export
|
|
9
|
+
export type DependencyProvider = () => PromiseLike<Dependency> | Dependency;
|
|
10
10
|
//# sourceMappingURL=Dependency.d.ts.map
|
|
@@ -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;
|
|
@@ -22,7 +22,7 @@ export interface UriProtocolSupporter {
|
|
|
22
22
|
*/
|
|
23
23
|
listRoots(): Iterable<RootUriString>;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
type Protocol = `${string}:`;
|
|
26
26
|
export interface FileService extends UriProtocolSupporter {
|
|
27
27
|
/**
|
|
28
28
|
* @param protocol A protocol of URI, including the colon. e.g. `file:`.
|
|
@@ -77,7 +77,8 @@ export class FileServiceImpl {
|
|
|
77
77
|
try {
|
|
78
78
|
let mappedUri = this.map.getKey(virtualUri);
|
|
79
79
|
if (mappedUri === undefined) {
|
|
80
|
-
mappedUri = `${this.virtualUrisRoot}${await this.externals.crypto
|
|
80
|
+
mappedUri = `${this.virtualUrisRoot}${await this.externals.crypto
|
|
81
|
+
.getSha1(virtualUri)}/${fileUtil.basename(virtualUri)}`;
|
|
81
82
|
const buffer = await this.readFile(virtualUri);
|
|
82
83
|
await fileUtil.writeFile(this.externals, mappedUri, buffer, 0o444);
|
|
83
84
|
this.map.set(mappedUri, virtualUri);
|
|
@@ -128,7 +129,8 @@ export class FileUriSupporter {
|
|
|
128
129
|
const files = new Map();
|
|
129
130
|
for (let { uri } of dependencies) {
|
|
130
131
|
try {
|
|
131
|
-
if (fileUtil.isFileUri(uri) &&
|
|
132
|
+
if (fileUtil.isFileUri(uri) &&
|
|
133
|
+
(await externals.fs.stat(uri)).isDirectory()) {
|
|
132
134
|
uri = fileUtil.ensureEndingSlash(uri);
|
|
133
135
|
roots.push(uri);
|
|
134
136
|
files.set(uri, await externals.fs.getAllFiles(uri));
|
|
@@ -146,11 +148,16 @@ export class FileUriSupporter {
|
|
|
146
148
|
// return uri.protocol === Protocol && uri.hostname === Hostname
|
|
147
149
|
// }
|
|
148
150
|
// }
|
|
149
|
-
|
|
151
|
+
class ArchiveUriSupporter {
|
|
150
152
|
externals;
|
|
151
153
|
entries;
|
|
152
154
|
static Protocol = 'archive:';
|
|
153
|
-
static SupportedArchiveExtnames = [
|
|
155
|
+
static SupportedArchiveExtnames = [
|
|
156
|
+
'.tar',
|
|
157
|
+
'.tar.bz2',
|
|
158
|
+
'.tar.gz',
|
|
159
|
+
'.zip',
|
|
160
|
+
];
|
|
154
161
|
protocol = ArchiveUriSupporter.Protocol;
|
|
155
162
|
/**
|
|
156
163
|
* @param entries A map from archive URIs to unzipped entries.
|
|
@@ -204,7 +211,7 @@ export class ArchiveUriSupporter {
|
|
|
204
211
|
}
|
|
205
212
|
}
|
|
206
213
|
static getUri(archiveUri, pathInArchive = '') {
|
|
207
|
-
return `${ArchiveUriSupporter.Protocol}
|
|
214
|
+
return `${ArchiveUriSupporter.Protocol}${encodeURIComponent(archiveUri)}?path=${encodeURIComponent(pathInArchive.replace(/\\/g, '/'))}`;
|
|
208
215
|
}
|
|
209
216
|
/**
|
|
210
217
|
* @throws When `uri` has the wrong protocol or hostname.
|
|
@@ -213,16 +220,22 @@ export class ArchiveUriSupporter {
|
|
|
213
220
|
if (uri.protocol !== ArchiveUriSupporter.Protocol) {
|
|
214
221
|
throw new Error(`Expected protocol “${ArchiveUriSupporter.Protocol}” in “${uri}”`);
|
|
215
222
|
}
|
|
223
|
+
const path = uri.searchParams.get('path');
|
|
224
|
+
if (!path) {
|
|
225
|
+
throw new Error(`Missing path in archive uri “${uri.toString()}”`);
|
|
226
|
+
}
|
|
216
227
|
return {
|
|
217
|
-
archiveUri: decodeURIComponent(uri.
|
|
218
|
-
pathInArchive:
|
|
228
|
+
archiveUri: decodeURIComponent(uri.pathname),
|
|
229
|
+
pathInArchive: path.charAt(0) === '/' ? path.slice(1) : path,
|
|
219
230
|
};
|
|
220
231
|
}
|
|
221
232
|
static async create(dependencies, externals, logger, checksums) {
|
|
222
233
|
const entries = new Map();
|
|
223
234
|
for (const { uri, info } of dependencies) {
|
|
224
235
|
try {
|
|
225
|
-
if (uri.startsWith('file:') &&
|
|
236
|
+
if (uri.startsWith('file:') &&
|
|
237
|
+
ArchiveUriSupporter.SupportedArchiveExtnames.some((ext) => uri.endsWith(ext)) &&
|
|
238
|
+
(await externals.fs.stat(uri)).isFile()) {
|
|
226
239
|
const rootUri = ArchiveUriSupporter.getUri(uri);
|
|
227
240
|
const cachedChecksum = checksums[rootUri];
|
|
228
241
|
if (cachedChecksum !== undefined) {
|
|
@@ -233,8 +246,12 @@ export class ArchiveUriSupporter {
|
|
|
233
246
|
continue;
|
|
234
247
|
}
|
|
235
248
|
}
|
|
236
|
-
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), {
|
|
237
|
-
|
|
249
|
+
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), {
|
|
250
|
+
stripLevel: typeof info?.startDepth === 'number'
|
|
251
|
+
? info.startDepth
|
|
252
|
+
: 0,
|
|
253
|
+
});
|
|
254
|
+
entries.set(uri, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
|
|
238
255
|
}
|
|
239
256
|
}
|
|
240
257
|
catch (e) {
|
|
@@ -244,6 +261,7 @@ export class ArchiveUriSupporter {
|
|
|
244
261
|
return new ArchiveUriSupporter(externals, entries);
|
|
245
262
|
}
|
|
246
263
|
}
|
|
264
|
+
export { ArchiveUriSupporter };
|
|
247
265
|
async function hashFile(externals, uri) {
|
|
248
266
|
return externals.crypto.getSha1(await externals.fs.readFile(uri));
|
|
249
267
|
}
|
|
@@ -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 {
|
package/lib/service/Project.d.ts
CHANGED
|
@@ -13,10 +13,10 @@ import { FileService } from './FileService.js';
|
|
|
13
13
|
import type { RootUriString } from './fileUtil.js';
|
|
14
14
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
15
15
|
import { ProfilerFactory } from './Profiler.js';
|
|
16
|
-
export
|
|
17
|
-
export
|
|
18
|
-
export
|
|
19
|
-
export
|
|
16
|
+
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'externals' | 'logger' | 'meta' | 'projectRoot'>;
|
|
17
|
+
export type SyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => Record<string, string> | void;
|
|
18
|
+
export type AsyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => PromiseLike<Record<string, string> | void>;
|
|
19
|
+
export type ProjectInitializer = SyncProjectInitializer | AsyncProjectInitializer;
|
|
20
20
|
export interface ProjectOptions {
|
|
21
21
|
cacheRoot: RootUriString;
|
|
22
22
|
defaultConfig?: Config;
|
|
@@ -55,7 +55,7 @@ interface SymbolRegistrarEvent {
|
|
|
55
55
|
id: string;
|
|
56
56
|
checksum: string | undefined;
|
|
57
57
|
}
|
|
58
|
-
export
|
|
58
|
+
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureBindingStarted' | 'externals' | 'fs' | 'logger' | 'meta' | 'profilers' | 'projectRoot' | 'roots' | 'symbols' | 'ctx'>;
|
|
59
59
|
/**
|
|
60
60
|
* Manage all tracked documents and errors.
|
|
61
61
|
*
|