@spyglassmc/core 0.4.6 → 0.4.8
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/externals/BrowserExternals.js +1 -1
- package/lib/common/externals/NodeJsExternals.js +2 -2
- package/lib/common/externals/index.d.ts +1 -1
- package/lib/node/ResourceLocationNode.d.ts +3 -0
- package/lib/node/StringNode.d.ts +3 -0
- package/lib/node/StringNode.js +8 -0
- package/lib/node/SymbolNode.d.ts +1 -0
- package/lib/parser/resourceLocation.js +3 -0
- package/lib/parser/string.js +14 -4
- package/lib/parser/util.js +2 -2
- package/lib/processor/ColorInfoProvider.d.ts +15 -2
- package/lib/processor/ColorInfoProvider.js +48 -6
- package/lib/processor/binder/builtin.js +1 -0
- package/lib/processor/completer/Completer.d.ts +1 -0
- package/lib/processor/completer/builtin.js +4 -2
- package/lib/service/CacheService.d.ts +1 -6
- package/lib/service/CacheService.js +15 -9
- package/lib/service/Config.js +16 -13
- package/lib/service/Project.d.ts +6 -6
- package/lib/service/Project.js +18 -10
- package/lib/source/IndexMap.d.ts +0 -1
- package/lib/source/IndexMap.js +0 -4
- package/package.json +2 -2
|
@@ -105,8 +105,8 @@ export const NodeJsExternals = {
|
|
|
105
105
|
unlink(location) {
|
|
106
106
|
return fsp.unlink(toFsPathLike(location));
|
|
107
107
|
},
|
|
108
|
-
watch(
|
|
109
|
-
return new ChokidarWatcherWrapper(chokidar.watch(toPath
|
|
108
|
+
watch(locations) {
|
|
109
|
+
return new ChokidarWatcherWrapper(chokidar.watch(locations.map(toPath)));
|
|
110
110
|
},
|
|
111
111
|
writeFile(location, data, options) {
|
|
112
112
|
return fsp.writeFile(toFsPathLike(location), data, options);
|
|
@@ -72,7 +72,7 @@ export interface ExternalFileSystem {
|
|
|
72
72
|
isFile(): boolean;
|
|
73
73
|
}>;
|
|
74
74
|
unlink(location: FsLocation): Promise<void>;
|
|
75
|
-
watch(
|
|
75
|
+
watch(locations: FsLocation[]): FsWatcher;
|
|
76
76
|
/**
|
|
77
77
|
* @param options `mode` - File mode bit mask (e.g. `0o775`).
|
|
78
78
|
*/
|
|
@@ -12,16 +12,19 @@ export type ResourceLocationOptions = {
|
|
|
12
12
|
category: ResourceLocationCategory;
|
|
13
13
|
pool?: undefined;
|
|
14
14
|
allowTag?: false;
|
|
15
|
+
requireTag?: false;
|
|
15
16
|
allowUnknown?: false;
|
|
16
17
|
} | {
|
|
17
18
|
category: TaggableResourceLocationCategory;
|
|
18
19
|
pool?: undefined;
|
|
19
20
|
allowTag?: boolean;
|
|
21
|
+
requireTag?: boolean;
|
|
20
22
|
allowUnknown?: false;
|
|
21
23
|
} | {
|
|
22
24
|
category?: undefined;
|
|
23
25
|
pool: string[];
|
|
24
26
|
allowTag?: false;
|
|
27
|
+
requireTag?: false;
|
|
25
28
|
allowUnknown?: boolean;
|
|
26
29
|
});
|
|
27
30
|
export interface ResourceLocationBaseNode extends AstNode, Partial<ResourceLocation> {
|
package/lib/node/StringNode.d.ts
CHANGED
|
@@ -54,6 +54,9 @@ export interface StringBaseNode extends AstNode {
|
|
|
54
54
|
value: string;
|
|
55
55
|
readonly valueMap: IndexMap;
|
|
56
56
|
}
|
|
57
|
+
export declare namespace StringBaseNode {
|
|
58
|
+
function is(obj: object | undefined): obj is StringBaseNode;
|
|
59
|
+
}
|
|
57
60
|
export interface StringNode extends StringBaseNode {
|
|
58
61
|
readonly type: 'string';
|
|
59
62
|
}
|
package/lib/node/StringNode.js
CHANGED
|
@@ -18,6 +18,14 @@ export const EscapeTable = new Map([
|
|
|
18
18
|
['r', '\r'],
|
|
19
19
|
['t', '\t'],
|
|
20
20
|
]);
|
|
21
|
+
export var StringBaseNode;
|
|
22
|
+
(function (StringBaseNode) {
|
|
23
|
+
function is(obj) {
|
|
24
|
+
return Array.isArray(obj?.valueMap)
|
|
25
|
+
&& typeof obj?.options === 'object';
|
|
26
|
+
}
|
|
27
|
+
StringBaseNode.is = is;
|
|
28
|
+
})(StringBaseNode || (StringBaseNode = {}));
|
|
21
29
|
export var StringNode;
|
|
22
30
|
(function (StringNode) {
|
|
23
31
|
/* istanbul ignore next */
|
package/lib/node/SymbolNode.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { SymbolAccessType, SymbolUsageType } from '../symbol/index.js';
|
|
|
3
3
|
import type { AstNode } from './AstNode.js';
|
|
4
4
|
export interface SymbolOptions {
|
|
5
5
|
category: string;
|
|
6
|
+
subcategory?: string;
|
|
6
7
|
parentPath?: string[];
|
|
7
8
|
accessType?: SymbolAccessType;
|
|
8
9
|
usageType?: SymbolUsageType;
|
|
@@ -100,6 +100,9 @@ export function resourceLocation(options) {
|
|
|
100
100
|
if (ans.isTag && !options.allowTag) {
|
|
101
101
|
ctx.err.report(localize('parser.resource-location.tag-disallowed'), ans);
|
|
102
102
|
}
|
|
103
|
+
if (!ans.isTag && options.requireTag) {
|
|
104
|
+
ctx.err.report(localize('parser.resource-location.tag-required'), ans);
|
|
105
|
+
}
|
|
103
106
|
if (!ans.namespace && options.requireCanonical) {
|
|
104
107
|
ctx.err.report(localize('parser.resource-location.namespace-expected'), ans);
|
|
105
108
|
}
|
package/lib/parser/string.js
CHANGED
|
@@ -12,15 +12,15 @@ export function string(options) {
|
|
|
12
12
|
value: '',
|
|
13
13
|
valueMap: [],
|
|
14
14
|
};
|
|
15
|
-
let start
|
|
15
|
+
let start;
|
|
16
16
|
if (options.quotes?.length && (src.peek() === '"' || src.peek() === "'")) {
|
|
17
17
|
const currentQuote = src.read();
|
|
18
18
|
ans.quote = currentQuote;
|
|
19
|
-
|
|
19
|
+
let cStart = src.cursor;
|
|
20
|
+
start = cStart;
|
|
20
21
|
while (src.canRead() && src.peek() !== currentQuote) {
|
|
21
22
|
const c = src.peek();
|
|
22
23
|
if (options.escapable && c === '\\') {
|
|
23
|
-
const cStart = src.cursor;
|
|
24
24
|
src.skip();
|
|
25
25
|
const c2 = src.read();
|
|
26
26
|
if (c2 === '\\'
|
|
@@ -61,10 +61,19 @@ export function string(options) {
|
|
|
61
61
|
});
|
|
62
62
|
ans.value += c2;
|
|
63
63
|
}
|
|
64
|
+
cStart = src.cursor;
|
|
64
65
|
}
|
|
65
66
|
else {
|
|
66
67
|
src.skip();
|
|
68
|
+
const cEnd = src.cursor;
|
|
69
|
+
if (cEnd - cStart > 1) {
|
|
70
|
+
ans.valueMap.push({
|
|
71
|
+
inner: Range.create(ans.value.length, ans.value.length + 1),
|
|
72
|
+
outer: Range.create(cStart, cEnd),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
67
75
|
ans.value += c;
|
|
76
|
+
cStart = cEnd;
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
if (!src.trySkip(currentQuote)) {
|
|
@@ -73,9 +82,9 @@ export function string(options) {
|
|
|
73
82
|
if (!options.quotes.includes(currentQuote)) {
|
|
74
83
|
ctx.err.report(localize('parser.string.illegal-quote', options.quotes), ans);
|
|
75
84
|
}
|
|
76
|
-
start = contentStart;
|
|
77
85
|
}
|
|
78
86
|
else if (options.unquotable) {
|
|
87
|
+
start = src.cursor;
|
|
79
88
|
while (src.canRead() && isAllowedCharacter(src.peek(), options.unquotable)) {
|
|
80
89
|
ans.value += src.read();
|
|
81
90
|
}
|
|
@@ -84,6 +93,7 @@ export function string(options) {
|
|
|
84
93
|
}
|
|
85
94
|
}
|
|
86
95
|
else {
|
|
96
|
+
start = src.cursor;
|
|
87
97
|
ctx.err.report(localize('expected', options.quotes), src);
|
|
88
98
|
}
|
|
89
99
|
ans.valueMap.unshift({ inner: Range.create(0), outer: Range.create(start) });
|
package/lib/parser/util.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { localize } from '@spyglassmc/locales';
|
|
2
2
|
import { SequenceUtil, SequenceUtilDiscriminator } from '../node/index.js';
|
|
3
3
|
import { ErrorReporter } from '../service/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { Range, Source } from '../source/index.js';
|
|
5
5
|
import { Failure } from './Parser.js';
|
|
6
6
|
export function attempt(parser, src, ctx) {
|
|
7
7
|
const tmpSrc = src.clone();
|
|
@@ -227,7 +227,7 @@ export function concatOnTrailingBackslash(parser) {
|
|
|
227
227
|
const to = src.getCharRange(-1);
|
|
228
228
|
indexMap.push({ inner: Range.create(wrappedStr.length), outer: Range.span(from, to) });
|
|
229
229
|
}
|
|
230
|
-
const wrappedSrc = new Source(wrappedStr,
|
|
230
|
+
const wrappedSrc = new Source(wrappedStr, indexMap);
|
|
231
231
|
wrappedSrc.innerCursor = wrappedSrcCursor;
|
|
232
232
|
const ans = parser(wrappedSrc, ctx);
|
|
233
233
|
src.cursor = wrappedSrc.cursor;
|
|
@@ -10,6 +10,7 @@ export type Color = [number, number, number, number];
|
|
|
10
10
|
export declare namespace Color {
|
|
11
11
|
const NamedColors: Map<string, number>;
|
|
12
12
|
const ColorNames: string[];
|
|
13
|
+
function fromNamed(value: string): Color | undefined;
|
|
13
14
|
/**
|
|
14
15
|
* @param r A decimal within [0.0, 1.0].
|
|
15
16
|
* @param g A decimal within [0.0, 1.0].
|
|
@@ -36,10 +37,18 @@ export declare namespace Color {
|
|
|
36
37
|
* @param b An integer within [0, 255].
|
|
37
38
|
*/
|
|
38
39
|
function fromIntRGB(r: number, g: number, b: number): Color;
|
|
40
|
+
/**
|
|
41
|
+
* @param value A string in the format `#rrggbb`
|
|
42
|
+
*/
|
|
43
|
+
function fromHexRGB(value: string): Color;
|
|
39
44
|
/**
|
|
40
45
|
* @param value `R << 16 + G << 8 + B`. Negative values result in white.
|
|
41
46
|
*/
|
|
42
|
-
function
|
|
47
|
+
function fromCompositeRGB(value: number): Color;
|
|
48
|
+
/**
|
|
49
|
+
* @param value `A << 24 + R << 16 + G << 8 + B`.
|
|
50
|
+
*/
|
|
51
|
+
function fromCompositeARGB(value: number): Color;
|
|
43
52
|
}
|
|
44
53
|
export declare enum ColorFormat {
|
|
45
54
|
/**
|
|
@@ -69,7 +78,11 @@ export declare enum ColorFormat {
|
|
|
69
78
|
/**
|
|
70
79
|
* `16620441`
|
|
71
80
|
*/
|
|
72
|
-
|
|
81
|
+
CompositeRGB = 6,
|
|
82
|
+
/**
|
|
83
|
+
* `4294945365`
|
|
84
|
+
*/
|
|
85
|
+
CompositeARGB = 7
|
|
73
86
|
}
|
|
74
87
|
export type FormattableColor = {
|
|
75
88
|
value: Color;
|
|
@@ -19,6 +19,14 @@ export var Color;
|
|
|
19
19
|
['yellow', 0xffff55],
|
|
20
20
|
]);
|
|
21
21
|
Color.ColorNames = [...Color.NamedColors.keys()];
|
|
22
|
+
function fromNamed(value) {
|
|
23
|
+
const composite = Color.NamedColors.get(value);
|
|
24
|
+
if (composite === undefined) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
return fromCompositeRGB(composite);
|
|
28
|
+
}
|
|
29
|
+
Color.fromNamed = fromNamed;
|
|
22
30
|
/**
|
|
23
31
|
* @param r A decimal within [0.0, 1.0].
|
|
24
32
|
* @param g A decimal within [0.0, 1.0].
|
|
@@ -57,21 +65,46 @@ export var Color;
|
|
|
57
65
|
return fromIntRGBA(r, g, b, 255);
|
|
58
66
|
}
|
|
59
67
|
Color.fromIntRGB = fromIntRGB;
|
|
68
|
+
/**
|
|
69
|
+
* @param value A string in the format `#rrggbb`
|
|
70
|
+
*/
|
|
71
|
+
function fromHexRGB(value) {
|
|
72
|
+
var bigint = parseInt(value.slice(1), 16);
|
|
73
|
+
var r = (bigint >> 16) & 255;
|
|
74
|
+
var g = (bigint >> 8) & 255;
|
|
75
|
+
var b = bigint & 255;
|
|
76
|
+
return fromIntRGB(r, g, b);
|
|
77
|
+
}
|
|
78
|
+
Color.fromHexRGB = fromHexRGB;
|
|
60
79
|
/**
|
|
61
80
|
* @param value `R << 16 + G << 8 + B`. Negative values result in white.
|
|
62
81
|
*/
|
|
63
|
-
function
|
|
82
|
+
function fromCompositeRGB(value) {
|
|
64
83
|
if (value < 0) {
|
|
65
84
|
return fromDecRGB(1.0, 1.0, 1.0);
|
|
66
85
|
}
|
|
67
86
|
const b = value % 256;
|
|
68
|
-
value
|
|
87
|
+
value >>>= 8;
|
|
69
88
|
const g = value % 256;
|
|
70
|
-
value
|
|
89
|
+
value >>>= 8;
|
|
71
90
|
const r = value % 256;
|
|
72
91
|
return fromIntRGB(r, g, b);
|
|
73
92
|
}
|
|
74
|
-
Color.
|
|
93
|
+
Color.fromCompositeRGB = fromCompositeRGB;
|
|
94
|
+
/**
|
|
95
|
+
* @param value `A << 24 + R << 16 + G << 8 + B`.
|
|
96
|
+
*/
|
|
97
|
+
function fromCompositeARGB(value) {
|
|
98
|
+
const b = value % 256;
|
|
99
|
+
value >>>= 8;
|
|
100
|
+
const g = value % 256;
|
|
101
|
+
value >>>= 8;
|
|
102
|
+
const r = value % 256;
|
|
103
|
+
value >>>= 8;
|
|
104
|
+
const a = value % 256;
|
|
105
|
+
return fromIntRGBA(r, g, b, a);
|
|
106
|
+
}
|
|
107
|
+
Color.fromCompositeARGB = fromCompositeARGB;
|
|
75
108
|
})(Color || (Color = {}));
|
|
76
109
|
export var ColorFormat;
|
|
77
110
|
(function (ColorFormat) {
|
|
@@ -102,7 +135,11 @@ export var ColorFormat;
|
|
|
102
135
|
/**
|
|
103
136
|
* `16620441`
|
|
104
137
|
*/
|
|
105
|
-
ColorFormat[ColorFormat["
|
|
138
|
+
ColorFormat[ColorFormat["CompositeRGB"] = 6] = "CompositeRGB";
|
|
139
|
+
/**
|
|
140
|
+
* `4294945365`
|
|
141
|
+
*/
|
|
142
|
+
ColorFormat[ColorFormat["CompositeARGB"] = 7] = "CompositeARGB";
|
|
106
143
|
})(ColorFormat || (ColorFormat = {}));
|
|
107
144
|
export var ColorPresentation;
|
|
108
145
|
(function (ColorPresentation) {
|
|
@@ -128,8 +165,13 @@ export var ColorPresentation;
|
|
|
128
165
|
case ColorFormat.HexRGB:
|
|
129
166
|
return `#${Math.round(((color[0] * 255) << 16) + ((color[1] * 255) << 8) + color[2] * 255)
|
|
130
167
|
.toString(16).padStart(6, '0')}`;
|
|
131
|
-
case ColorFormat.
|
|
168
|
+
case ColorFormat.CompositeRGB:
|
|
132
169
|
return `${Math.round(((color[0] * 255) << 16) + ((color[1] * 255) << 8) + color[2] * 255)}`;
|
|
170
|
+
case ColorFormat.CompositeARGB:
|
|
171
|
+
return `${(BigInt(Math.round(color[3] * 255)) << 24n)
|
|
172
|
+
+ (BigInt(Math.round(color[0] * 255)) << 16n)
|
|
173
|
+
+ (BigInt(Math.round(color[1] * 255)) << 8n)
|
|
174
|
+
+ BigInt(Math.round(color[2] * 255))}`;
|
|
133
175
|
}
|
|
134
176
|
}
|
|
135
177
|
})(ColorPresentation || (ColorPresentation = {}));
|
|
@@ -107,6 +107,7 @@ export const symbol = SyncBinder.create((node, ctx) => {
|
|
|
107
107
|
if (node.value) {
|
|
108
108
|
const path = node.options.parentPath ? [...node.options.parentPath, node.value] : [node.value];
|
|
109
109
|
ctx.symbols.query(ctx.doc, node.options.category, ...path).enter({
|
|
110
|
+
data: { subcategory: node.options.subcategory },
|
|
110
111
|
usage: { type: node.options.usageType, node, accessType: node.options.accessType },
|
|
111
112
|
});
|
|
112
113
|
}
|
|
@@ -139,7 +139,9 @@ export const resourceLocation = (node, ctx) => {
|
|
|
139
139
|
const pool = node.options.pool
|
|
140
140
|
? optimizePool(node.options.pool)
|
|
141
141
|
: [
|
|
142
|
-
...
|
|
142
|
+
...(!node.options.requireTag
|
|
143
|
+
? getPool(node.options.category)
|
|
144
|
+
: []),
|
|
143
145
|
...(node.options.allowTag
|
|
144
146
|
? getPool(`tag/${node.options.category}`).map((v) => `${ResourceLocation.TagPrefix}${v}`)
|
|
145
147
|
: []),
|
|
@@ -148,7 +150,7 @@ export const resourceLocation = (node, ctx) => {
|
|
|
148
150
|
if (node.options.category) {
|
|
149
151
|
const symbols = ctx.symbols.getVisibleSymbols(node.options.category, ctx.doc.uri);
|
|
150
152
|
const thisKey = Object.entries(symbols).flatMap(([key, symbol]) => {
|
|
151
|
-
if ((symbol.declaration?.[0] ?? symbol.definition?.[0])?.uri
|
|
153
|
+
if ((symbol.declaration?.[0] ?? symbol.definition?.[0])?.uri === ctx.doc.uri) {
|
|
152
154
|
return [key];
|
|
153
155
|
}
|
|
154
156
|
return [];
|
|
@@ -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 = 4;
|
|
11
11
|
/**
|
|
12
12
|
* Checksums of cached files or roots.
|
|
13
13
|
*/
|
|
@@ -40,11 +40,6 @@ export declare class CacheService {
|
|
|
40
40
|
* @param project
|
|
41
41
|
*/
|
|
42
42
|
constructor(cacheRoot: RootUriString, project: Project);
|
|
43
|
-
/**
|
|
44
|
-
* @throws
|
|
45
|
-
*
|
|
46
|
-
* @returns `${cacheRoot}symbols/${sha1(projectRoot)}.json`
|
|
47
|
-
*/
|
|
48
43
|
private getCacheFileUri;
|
|
49
44
|
load(): Promise<LoadResult>;
|
|
50
45
|
validate(): Promise<ValidateResult>;
|
|
@@ -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 = 4;
|
|
9
9
|
var Checksums;
|
|
10
10
|
(function (Checksums) {
|
|
11
11
|
function create() {
|
|
@@ -65,17 +65,20 @@ export class CacheService {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
#cacheFilePath;
|
|
68
|
-
/**
|
|
69
|
-
* @throws
|
|
70
|
-
*
|
|
71
|
-
* @returns `${cacheRoot}symbols/${sha1(projectRoot)}.json`
|
|
72
|
-
*/
|
|
73
68
|
async getCacheFileUri() {
|
|
74
|
-
|
|
69
|
+
if (!this.#cacheFilePath) {
|
|
70
|
+
const sortedRoots = [...this.project.projectRoots].sort();
|
|
71
|
+
const hash = await this.project.externals.crypto.getSha1(sortedRoots.join(':'));
|
|
72
|
+
this.#cacheFilePath = new Uri(`symbols/${hash}.json.gz`, this.cacheRoot).toString();
|
|
73
|
+
}
|
|
74
|
+
return this.#cacheFilePath;
|
|
75
75
|
}
|
|
76
76
|
async load() {
|
|
77
|
-
const __profiler = this.project.profilers.get('cache#load');
|
|
78
77
|
const ans = { symbols: {} };
|
|
78
|
+
if (this.project.projectRoots.length === 0) {
|
|
79
|
+
return ans;
|
|
80
|
+
}
|
|
81
|
+
const __profiler = this.project.profilers.get('cache#load');
|
|
79
82
|
let filePath;
|
|
80
83
|
try {
|
|
81
84
|
filePath = await this.getCacheFileUri();
|
|
@@ -164,13 +167,16 @@ export class CacheService {
|
|
|
164
167
|
* @returns If the cache file was saved successfully.
|
|
165
168
|
*/
|
|
166
169
|
async save() {
|
|
170
|
+
if (this.project.projectRoots.length === 0) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
167
173
|
const __profiler = this.project.profilers.get('cache#save');
|
|
168
174
|
let filePath;
|
|
169
175
|
try {
|
|
170
176
|
filePath = await this.getCacheFileUri();
|
|
171
177
|
const cache = {
|
|
172
178
|
version: LatestCacheVersion,
|
|
173
|
-
|
|
179
|
+
projectRoots: this.project.projectRoots,
|
|
174
180
|
checksums: this.checksums,
|
|
175
181
|
symbols: SymbolTable.unlink(this.project.symbols.global),
|
|
176
182
|
errors: this.errors,
|
package/lib/service/Config.js
CHANGED
|
@@ -236,22 +236,25 @@ export class ConfigService {
|
|
|
236
236
|
return this.#eventEmitter.emit(event, ...args);
|
|
237
237
|
}
|
|
238
238
|
async load() {
|
|
239
|
-
|
|
240
|
-
for (const
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
239
|
+
const overrides = [];
|
|
240
|
+
for (const projectRoot of this.project.projectRoots) {
|
|
241
|
+
for (const name of ConfigService.ConfigFileNames) {
|
|
242
|
+
const uri = projectRoot + name;
|
|
243
|
+
try {
|
|
244
|
+
const contents = await this.project.externals.fs.readFile(uri);
|
|
245
|
+
overrides.push(JSON.parse(bufferToString(contents)));
|
|
246
|
+
}
|
|
247
|
+
catch (e) {
|
|
248
|
+
if (this.project.externals.error.isKind(e, 'ENOENT')) {
|
|
249
|
+
// File doesn't exist.
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
this.emit('error', { error: e, uri });
|
|
249
253
|
}
|
|
250
|
-
|
|
254
|
+
break;
|
|
251
255
|
}
|
|
252
|
-
break;
|
|
253
256
|
}
|
|
254
|
-
return ConfigService.merge(this.defaultConfig,
|
|
257
|
+
return ConfigService.merge(this.defaultConfig, ...overrides);
|
|
255
258
|
}
|
|
256
259
|
static isConfigFile(uri) {
|
|
257
260
|
return ConfigService.ConfigFileNames.some((n) => uri.endsWith(`/${n}`));
|
package/lib/service/Project.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { FileService } from './FileService.js';
|
|
|
14
14
|
import type { RootUriString } from './fileUtil.js';
|
|
15
15
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
16
16
|
import { ProfilerFactory } from './Profiler.js';
|
|
17
|
-
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'externals' | 'isDebugging' | 'logger' | 'meta' | '
|
|
17
|
+
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'externals' | 'isDebugging' | 'logger' | 'meta' | 'projectRoots'>;
|
|
18
18
|
export type SyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => Record<string, string> | void;
|
|
19
19
|
export type AsyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => PromiseLike<Record<string, string> | void>;
|
|
20
20
|
export type ProjectInitializer = SyncProjectInitializer | AsyncProjectInitializer;
|
|
@@ -29,9 +29,9 @@ export interface ProjectOptions {
|
|
|
29
29
|
logger?: Logger;
|
|
30
30
|
profilers?: ProfilerFactory;
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* File URIs to the roots of this project.
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
projectRoots: RootUriString[];
|
|
35
35
|
symbols?: SymbolUtil;
|
|
36
36
|
}
|
|
37
37
|
export interface DocAndNode {
|
|
@@ -57,7 +57,7 @@ interface SymbolRegistrarEvent {
|
|
|
57
57
|
id: string;
|
|
58
58
|
checksum: string | undefined;
|
|
59
59
|
}
|
|
60
|
-
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureBindingStarted' | 'externals' | 'fs' | 'isDebugging' | 'logger' | 'meta' | 'profilers' | '
|
|
60
|
+
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureBindingStarted' | 'externals' | 'fs' | 'isDebugging' | 'logger' | 'meta' | 'profilers' | 'projectRoots' | 'roots' | 'symbols' | 'ctx'>;
|
|
61
61
|
/**
|
|
62
62
|
* Manage all tracked documents and errors.
|
|
63
63
|
*
|
|
@@ -110,7 +110,7 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
110
110
|
readonly logger: Logger;
|
|
111
111
|
readonly meta: MetaRegistry;
|
|
112
112
|
readonly profilers: ProfilerFactory;
|
|
113
|
-
readonly
|
|
113
|
+
readonly projectRoots: RootUriString[];
|
|
114
114
|
symbols: SymbolUtil;
|
|
115
115
|
/**
|
|
116
116
|
* All tracked root URIs. Each URI in this array is guaranteed to end with a slash (`/`).
|
|
@@ -159,7 +159,7 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
159
159
|
* are not loaded into the memory.
|
|
160
160
|
*/
|
|
161
161
|
getTrackedFiles(): string[];
|
|
162
|
-
constructor({ cacheRoot, defaultConfig, downloader, externals, fs, initializers, isDebugging, logger, profilers,
|
|
162
|
+
constructor({ cacheRoot, defaultConfig, downloader, externals, fs, initializers, isDebugging, logger, profilers, projectRoots, }: ProjectOptions);
|
|
163
163
|
private setInitPromise;
|
|
164
164
|
private readGitignore;
|
|
165
165
|
private setReadyPromise;
|
package/lib/service/Project.js
CHANGED
|
@@ -93,7 +93,7 @@ export class Project {
|
|
|
93
93
|
logger;
|
|
94
94
|
meta = new MetaRegistry();
|
|
95
95
|
profilers;
|
|
96
|
-
|
|
96
|
+
projectRoots;
|
|
97
97
|
symbols;
|
|
98
98
|
#dependencyRoots;
|
|
99
99
|
#dependencyFiles;
|
|
@@ -125,7 +125,7 @@ export class Project {
|
|
|
125
125
|
return this.#cacheRoot;
|
|
126
126
|
}
|
|
127
127
|
updateRoots() {
|
|
128
|
-
const rawRoots = [...this.#dependencyRoots, this.
|
|
128
|
+
const rawRoots = [...this.#dependencyRoots ?? [], ...this.projectRoots];
|
|
129
129
|
const ans = new Set(rawRoots);
|
|
130
130
|
// Identify roots indicated by `pack.mcmeta`.
|
|
131
131
|
for (const file of this.getTrackedFiles()) {
|
|
@@ -155,11 +155,12 @@ export class Project {
|
|
|
155
155
|
*/
|
|
156
156
|
getTrackedFiles() {
|
|
157
157
|
const extensions = this.meta.getSupportedFileExtensions();
|
|
158
|
-
const supportedFiles = [...this.#dependencyFiles, ...this.#watchedFiles]
|
|
158
|
+
const supportedFiles = [...this.#dependencyFiles ?? [], ...this.#watchedFiles]
|
|
159
|
+
.filter((file) => extensions.includes(fileUtil.extname(file) ?? ''));
|
|
159
160
|
const filteredFiles = this.ignore.filter(supportedFiles);
|
|
160
161
|
return filteredFiles;
|
|
161
162
|
}
|
|
162
|
-
constructor({ cacheRoot, defaultConfig, downloader, externals, fs = FileService.create(externals, cacheRoot), initializers = [], isDebugging = false, logger = Logger.create(), profilers = ProfilerFactory.noop(),
|
|
163
|
+
constructor({ cacheRoot, defaultConfig, downloader, externals, fs = FileService.create(externals, cacheRoot), initializers = [], isDebugging = false, logger = Logger.create(), profilers = ProfilerFactory.noop(), projectRoots, }) {
|
|
163
164
|
this.#cacheRoot = cacheRoot;
|
|
164
165
|
this.#eventEmitter = new externals.event.EventEmitter();
|
|
165
166
|
this.externals = externals;
|
|
@@ -168,7 +169,7 @@ export class Project {
|
|
|
168
169
|
this.isDebugging = isDebugging;
|
|
169
170
|
this.logger = logger;
|
|
170
171
|
this.profilers = profilers;
|
|
171
|
-
this.
|
|
172
|
+
this.projectRoots = projectRoots;
|
|
172
173
|
this.cacheService = new CacheService(cacheRoot, this);
|
|
173
174
|
this.#configService = new ConfigService(this, defaultConfig);
|
|
174
175
|
this.downloader = downloader ?? new Downloader(cacheRoot, externals, logger);
|
|
@@ -246,7 +247,7 @@ export class Project {
|
|
|
246
247
|
isDebugging: this.isDebugging,
|
|
247
248
|
logger: this.logger,
|
|
248
249
|
meta: this.meta,
|
|
249
|
-
|
|
250
|
+
projectRoots: this.projectRoots,
|
|
250
251
|
};
|
|
251
252
|
const results = await Promise.allSettled(this.#initializers.map((init) => init(initCtx)));
|
|
252
253
|
let ctx = {};
|
|
@@ -274,8 +275,11 @@ export class Project {
|
|
|
274
275
|
this.#initPromise = init();
|
|
275
276
|
}
|
|
276
277
|
async readGitignore() {
|
|
278
|
+
if (this.projectRoots.length === 0) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
277
281
|
try {
|
|
278
|
-
const uri = this.
|
|
282
|
+
const uri = this.projectRoots[0] + Project.GitIgnore;
|
|
279
283
|
const contents = await this.externals.fs.readFile(uri);
|
|
280
284
|
return bufferToString(contents);
|
|
281
285
|
}
|
|
@@ -319,9 +323,13 @@ export class Project {
|
|
|
319
323
|
this.fs.register(ArchiveUriSupporter.Protocol, archiveUriSupporter, true);
|
|
320
324
|
};
|
|
321
325
|
const listProjectFiles = () => new Promise((resolve) => {
|
|
326
|
+
if (this.projectRoots.length === 0) {
|
|
327
|
+
resolve();
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
322
330
|
this.#watchedFiles.clear();
|
|
323
331
|
this.#watcherReady = false;
|
|
324
|
-
this.#watcher = this.externals.fs.watch(this.
|
|
332
|
+
this.#watcher = this.externals.fs.watch(this.projectRoots).once('ready', () => {
|
|
325
333
|
this.#watcherReady = true;
|
|
326
334
|
resolve();
|
|
327
335
|
}).on('add', (uri) => {
|
|
@@ -726,13 +734,13 @@ export class Project {
|
|
|
726
734
|
}
|
|
727
735
|
shouldRemove(uri) {
|
|
728
736
|
return (!this.#clientManagedUris.has(uri)
|
|
729
|
-
&& !this.#dependencyFiles
|
|
737
|
+
&& !this.#dependencyFiles?.has(uri)
|
|
730
738
|
&& !this.#watchedFiles.has(uri));
|
|
731
739
|
}
|
|
732
740
|
isOnlyWatched(uri) {
|
|
733
741
|
return (this.#watchedFiles.has(uri)
|
|
734
742
|
&& !this.#clientManagedUris.has(uri)
|
|
735
|
-
&& !this.#dependencyFiles
|
|
743
|
+
&& !this.#dependencyFiles?.has(uri));
|
|
736
744
|
}
|
|
737
745
|
}
|
|
738
746
|
__decorate([
|
package/lib/source/IndexMap.d.ts
CHANGED
|
@@ -11,6 +11,5 @@ export declare namespace IndexMap {
|
|
|
11
11
|
function toInnerRange(map: IndexMap, outer: Range): Range;
|
|
12
12
|
function toOuterOffset(map: IndexMap, offset: number): number;
|
|
13
13
|
function toOuterRange(map: IndexMap, inner: Range): Range;
|
|
14
|
-
function merge(outerMap: IndexMap, innerMap: IndexMap): IndexMap;
|
|
15
14
|
}
|
|
16
15
|
//# sourceMappingURL=IndexMap.d.ts.map
|
package/lib/source/IndexMap.js
CHANGED
|
@@ -32,9 +32,5 @@ export var IndexMap;
|
|
|
32
32
|
return Range.create(toOuterOffset(map, inner.start), toOuterOffset(map, inner.end));
|
|
33
33
|
}
|
|
34
34
|
IndexMap.toOuterRange = toOuterRange;
|
|
35
|
-
function merge(outerMap, innerMap) {
|
|
36
|
-
return innerMap.map((p) => ({ inner: p.inner, outer: toOuterRange(outerMap, p.outer) }));
|
|
37
|
-
}
|
|
38
|
-
IndexMap.merge = merge;
|
|
39
35
|
})(IndexMap || (IndexMap = {}));
|
|
40
36
|
//# sourceMappingURL=IndexMap.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spyglassmc/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"rfdc": "^1.3.0",
|
|
26
26
|
"vscode-languageserver-textdocument": "^1.0.4",
|
|
27
27
|
"whatwg-url": "^14.0.0",
|
|
28
|
-
"@spyglassmc/locales": "0.3.
|
|
28
|
+
"@spyglassmc/locales": "0.3.8"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/decompress": "^4.2.3",
|