@spyglassmc/core 0.4.2 → 0.4.4
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.d.ts +7 -7
- package/lib/common/Dev.js +18 -12
- package/lib/common/ReadonlyProxy.d.ts +8 -5
- package/lib/common/ReadonlyProxy.js +6 -4
- package/lib/common/StateProxy.d.ts +9 -9
- package/lib/common/StateProxy.js +21 -14
- package/lib/common/externals/NodeJsExternals.js +7 -2
- package/lib/common/externals/downloader.d.ts +6 -6
- package/lib/common/externals/downloader.js +12 -8
- package/lib/common/externals/index.d.ts +1 -1
- package/lib/common/util.d.ts +18 -16
- package/lib/common/util.js +11 -0
- package/lib/node/CommentNode.d.ts +4 -4
- package/lib/node/CommentNode.js +6 -4
- package/lib/parser/resourceLocation.js +1 -1
- package/lib/parser/util.d.ts +4 -0
- package/lib/parser/util.js +10 -0
- package/lib/processor/InlayHintProvider.d.ts +3 -1
- package/lib/processor/binder/Binder.d.ts +8 -8
- package/lib/processor/binder/Binder.js +18 -12
- package/lib/service/Config.js +15 -4
- package/lib/service/FileService.d.ts +2 -2
- package/lib/service/FileService.js +36 -32
- package/lib/service/Project.js +3 -4
- package/lib/service/fileUtil.d.ts +1 -0
- package/lib/service/fileUtil.js +4 -0
- package/lib/source/IndexMap.js +7 -7
- package/lib/source/LanguageError.d.ts +4 -4
- package/lib/source/LanguageError.js +9 -6
- package/lib/source/Source.d.ts +8 -6
- package/lib/source/Source.js +16 -9
- package/lib/symbol/Symbol.d.ts +4 -4
- package/lib/symbol/Symbol.js +6 -2
- package/package.json +5 -3
|
@@ -79,6 +79,17 @@ export class FileServiceImpl {
|
|
|
79
79
|
if (mappedUri === undefined) {
|
|
80
80
|
mappedUri = `${this.virtualUrisRoot}${await this.externals.crypto
|
|
81
81
|
.getSha1(virtualUri)}/${fileUtil.basename(virtualUri)}`;
|
|
82
|
+
// Delete old mapped file if it exists. This makes sure the
|
|
83
|
+
// readonly permission on the file is not removed by it being
|
|
84
|
+
// overwritten.
|
|
85
|
+
try {
|
|
86
|
+
await fileUtil.unlink(this.externals, mappedUri);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
if (!this.externals.error.isKind(e, 'ENOENT')) {
|
|
90
|
+
throw e;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
82
93
|
const buffer = await this.readFile(virtualUri);
|
|
83
94
|
await fileUtil.writeFile(this.externals, mappedUri, buffer, 0o444);
|
|
84
95
|
this.map.set(mappedUri, virtualUri);
|
|
@@ -148,7 +159,7 @@ export class FileUriSupporter {
|
|
|
148
159
|
// return uri.protocol === Protocol && uri.hostname === Hostname
|
|
149
160
|
// }
|
|
150
161
|
// }
|
|
151
|
-
class ArchiveUriSupporter {
|
|
162
|
+
export class ArchiveUriSupporter {
|
|
152
163
|
externals;
|
|
153
164
|
entries;
|
|
154
165
|
static Protocol = 'archive:';
|
|
@@ -160,58 +171,58 @@ class ArchiveUriSupporter {
|
|
|
160
171
|
];
|
|
161
172
|
protocol = ArchiveUriSupporter.Protocol;
|
|
162
173
|
/**
|
|
163
|
-
* @param entries A map from archive
|
|
174
|
+
* @param entries A map from archive names to unzipped entries.
|
|
164
175
|
*/
|
|
165
176
|
constructor(externals, entries) {
|
|
166
177
|
this.externals = externals;
|
|
167
178
|
this.entries = entries;
|
|
168
179
|
}
|
|
169
180
|
async hash(uri) {
|
|
170
|
-
const {
|
|
181
|
+
const { archiveName, pathInArchive } = ArchiveUriSupporter.decodeUri(new Uri(uri));
|
|
171
182
|
if (!pathInArchive) {
|
|
172
183
|
// Hash the archive itself.
|
|
173
|
-
return hashFile(this.externals,
|
|
184
|
+
return hashFile(this.externals, archiveName);
|
|
174
185
|
}
|
|
175
186
|
else {
|
|
176
187
|
// Hash the corresponding file.
|
|
177
|
-
return this.externals.crypto.getSha1(this.getDataInArchive(
|
|
188
|
+
return this.externals.crypto.getSha1(this.getDataInArchive(archiveName, pathInArchive));
|
|
178
189
|
}
|
|
179
190
|
}
|
|
180
191
|
async readFile(uri) {
|
|
181
|
-
const {
|
|
182
|
-
return this.getDataInArchive(
|
|
192
|
+
const { archiveName, pathInArchive } = ArchiveUriSupporter.decodeUri(new Uri(uri));
|
|
193
|
+
return this.getDataInArchive(archiveName, pathInArchive);
|
|
183
194
|
}
|
|
184
195
|
/**
|
|
185
196
|
* @throws
|
|
186
197
|
*/
|
|
187
|
-
getDataInArchive(
|
|
188
|
-
const entries = this.entries.get(
|
|
198
|
+
getDataInArchive(archiveName, pathInArchive) {
|
|
199
|
+
const entries = this.entries.get(archiveName);
|
|
189
200
|
if (!entries) {
|
|
190
|
-
throw new Error(`Archive “${
|
|
201
|
+
throw new Error(`Archive “${archiveName}” has not been loaded into the memory`);
|
|
191
202
|
}
|
|
192
203
|
const entry = entries.get(pathInArchive);
|
|
193
204
|
if (!entry) {
|
|
194
|
-
throw new Error(`Path “${pathInArchive}” does not exist in archive “${
|
|
205
|
+
throw new Error(`Path “${pathInArchive}” does not exist in archive “${archiveName}”`);
|
|
195
206
|
}
|
|
196
207
|
if (entry.type !== 'file') {
|
|
197
|
-
throw new Error(`Path “${pathInArchive}” in archive “${
|
|
208
|
+
throw new Error(`Path “${pathInArchive}” in archive “${archiveName}” is not a file`);
|
|
198
209
|
}
|
|
199
210
|
return entry.data;
|
|
200
211
|
}
|
|
201
212
|
*listFiles() {
|
|
202
|
-
for (const [
|
|
213
|
+
for (const [archiveName, files] of this.entries.entries()) {
|
|
203
214
|
for (const file of files.values()) {
|
|
204
|
-
yield ArchiveUriSupporter.getUri(
|
|
215
|
+
yield ArchiveUriSupporter.getUri(archiveName, file.path);
|
|
205
216
|
}
|
|
206
217
|
}
|
|
207
218
|
}
|
|
208
219
|
*listRoots() {
|
|
209
|
-
for (const
|
|
210
|
-
yield ArchiveUriSupporter.getUri(
|
|
220
|
+
for (const archiveName of this.entries.keys()) {
|
|
221
|
+
yield ArchiveUriSupporter.getUri(archiveName);
|
|
211
222
|
}
|
|
212
223
|
}
|
|
213
|
-
static getUri(
|
|
214
|
-
return `${ArchiveUriSupporter.Protocol}
|
|
224
|
+
static getUri(archiveName, pathInArchive = '') {
|
|
225
|
+
return `${ArchiveUriSupporter.Protocol}//${archiveName}/${pathInArchive.replace(/\\/g, '/')}`;
|
|
215
226
|
}
|
|
216
227
|
/**
|
|
217
228
|
* @throws When `uri` has the wrong protocol or hostname.
|
|
@@ -220,38 +231,32 @@ class ArchiveUriSupporter {
|
|
|
220
231
|
if (uri.protocol !== ArchiveUriSupporter.Protocol) {
|
|
221
232
|
throw new Error(`Expected protocol “${ArchiveUriSupporter.Protocol}” in “${uri}”`);
|
|
222
233
|
}
|
|
223
|
-
const path = uri.
|
|
234
|
+
const path = uri.pathname;
|
|
224
235
|
if (!path) {
|
|
225
236
|
throw new Error(`Missing path in archive uri “${uri.toString()}”`);
|
|
226
237
|
}
|
|
227
238
|
return {
|
|
228
|
-
|
|
239
|
+
archiveName: uri.host,
|
|
229
240
|
pathInArchive: path.charAt(0) === '/' ? path.slice(1) : path,
|
|
230
241
|
};
|
|
231
242
|
}
|
|
232
|
-
static async create(dependencies, externals, logger
|
|
243
|
+
static async create(dependencies, externals, logger) {
|
|
233
244
|
const entries = new Map();
|
|
234
245
|
for (const { uri, info } of dependencies) {
|
|
235
246
|
try {
|
|
236
247
|
if (uri.startsWith('file:') &&
|
|
237
248
|
ArchiveUriSupporter.SupportedArchiveExtnames.some((ext) => uri.endsWith(ext)) &&
|
|
238
249
|
(await externals.fs.stat(uri)).isFile()) {
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const checksum = await hashFile(externals, uri);
|
|
243
|
-
if (cachedChecksum === checksum) {
|
|
244
|
-
// The dependency has not changed since last cache.
|
|
245
|
-
logger.info(`[SpyglassUriSupporter#create] Skipped decompressing “${uri}” thanks to cache ${checksum}`);
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
250
|
+
const archiveName = fileUtil.basename(uri);
|
|
251
|
+
if (entries.has(archiveName)) {
|
|
252
|
+
throw new Error(`A different URI with ${archiveName} already exists`);
|
|
248
253
|
}
|
|
249
254
|
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), {
|
|
250
255
|
stripLevel: typeof info?.startDepth === 'number'
|
|
251
256
|
? info.startDepth
|
|
252
257
|
: 0,
|
|
253
258
|
});
|
|
254
|
-
entries.set(
|
|
259
|
+
entries.set(archiveName, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
|
|
255
260
|
}
|
|
256
261
|
}
|
|
257
262
|
catch (e) {
|
|
@@ -261,7 +266,6 @@ class ArchiveUriSupporter {
|
|
|
261
266
|
return new ArchiveUriSupporter(externals, entries);
|
|
262
267
|
}
|
|
263
268
|
}
|
|
264
|
-
export { ArchiveUriSupporter };
|
|
265
269
|
async function hashFile(externals, uri) {
|
|
266
270
|
return externals.crypto.getSha1(await externals.fs.readFile(uri));
|
|
267
271
|
}
|
package/lib/service/Project.js
CHANGED
|
@@ -21,7 +21,7 @@ import { ArchiveUriSupporter, FileService, FileUriSupporter, } from './FileServi
|
|
|
21
21
|
import { fileUtil } from './fileUtil.js';
|
|
22
22
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
23
23
|
import { ProfilerFactory } from './Profiler.js';
|
|
24
|
-
const CacheAutoSaveInterval =
|
|
24
|
+
const CacheAutoSaveInterval = 600_000; // 10 Minutes.
|
|
25
25
|
/* istanbul ignore next */
|
|
26
26
|
/**
|
|
27
27
|
* Manage all tracked documents and errors.
|
|
@@ -60,7 +60,7 @@ const CacheAutoSaveInterval = 600000; // 10 Minutes.
|
|
|
60
60
|
*
|
|
61
61
|
* After the READY process is complete, editing text documents as signaled by the client or the file watcher results in the file being re-processed.
|
|
62
62
|
*/
|
|
63
|
-
class Project {
|
|
63
|
+
export class Project {
|
|
64
64
|
static RootSuffix = '/pack.mcmeta';
|
|
65
65
|
/** Prevent circular binding. */
|
|
66
66
|
#bindingInProgressUris = new Set();
|
|
@@ -290,7 +290,7 @@ class Project {
|
|
|
290
290
|
const listDependencyFiles = async () => {
|
|
291
291
|
const dependencies = await getDependencies();
|
|
292
292
|
const fileUriSupporter = await FileUriSupporter.create(dependencies, this.externals, this.logger);
|
|
293
|
-
const archiveUriSupporter = await ArchiveUriSupporter.create(dependencies, this.externals, this.logger
|
|
293
|
+
const archiveUriSupporter = await ArchiveUriSupporter.create(dependencies, this.externals, this.logger);
|
|
294
294
|
this.fs.register('file:', fileUriSupporter, true);
|
|
295
295
|
this.fs.register(ArchiveUriSupporter.Protocol, archiveUriSupporter, true);
|
|
296
296
|
};
|
|
@@ -721,5 +721,4 @@ __decorate([
|
|
|
721
721
|
__decorate([
|
|
722
722
|
SingletonPromise()
|
|
723
723
|
], Project.prototype, "ensureClientManagedChecked", null);
|
|
724
|
-
export { Project };
|
|
725
724
|
//# sourceMappingURL=Project.js.map
|
|
@@ -57,6 +57,7 @@ export declare namespace fileUtil {
|
|
|
57
57
|
function chmod(externals: Externals, path: FsLocation, mode: number): Promise<void>;
|
|
58
58
|
function ensureWritable(externals: Externals, path: FsLocation): Promise<void>;
|
|
59
59
|
function markReadOnly(externals: Externals, path: FsLocation): Promise<void>;
|
|
60
|
+
function unlink(externals: Externals, path: FsLocation): Promise<void>;
|
|
60
61
|
function readFile(externals: Externals, path: FsLocation): Promise<Uint8Array>;
|
|
61
62
|
/**
|
|
62
63
|
* @throws
|
package/lib/service/fileUtil.js
CHANGED
|
@@ -123,6 +123,10 @@ export var fileUtil;
|
|
|
123
123
|
return chmod(externals, path, 0o444);
|
|
124
124
|
}
|
|
125
125
|
fileUtil.markReadOnly = markReadOnly;
|
|
126
|
+
async function unlink(externals, path) {
|
|
127
|
+
return externals.fs.unlink(path);
|
|
128
|
+
}
|
|
129
|
+
fileUtil.unlink = unlink;
|
|
126
130
|
async function readFile(externals, path) {
|
|
127
131
|
return externals.fs.readFile(path);
|
|
128
132
|
}
|
package/lib/source/IndexMap.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Range } from './Range.js';
|
|
2
2
|
export var IndexMap;
|
|
3
3
|
(function (IndexMap) {
|
|
4
|
-
function convertOffset(map, offset, from, to
|
|
4
|
+
function convertOffset(map, offset, from, to) {
|
|
5
5
|
let ans = offset;
|
|
6
6
|
for (const pair of map) {
|
|
7
|
-
if (Range.contains(pair[from], offset
|
|
8
|
-
return
|
|
7
|
+
if (Range.contains(pair[from], offset)) {
|
|
8
|
+
return pair[to].start;
|
|
9
9
|
}
|
|
10
10
|
else if (Range.endsBefore(pair[from], offset)) {
|
|
11
11
|
ans = offset - pair[from].end + pair[to].end;
|
|
@@ -17,19 +17,19 @@ export var IndexMap;
|
|
|
17
17
|
return ans;
|
|
18
18
|
}
|
|
19
19
|
function toInnerOffset(map, offset) {
|
|
20
|
-
return convertOffset(map, offset, 'outer', 'inner'
|
|
20
|
+
return convertOffset(map, offset, 'outer', 'inner');
|
|
21
21
|
}
|
|
22
22
|
IndexMap.toInnerOffset = toInnerOffset;
|
|
23
23
|
function toInnerRange(map, outer) {
|
|
24
|
-
return Range.create(toInnerOffset(map, outer.start),
|
|
24
|
+
return Range.create(toInnerOffset(map, outer.start), toInnerOffset(map, outer.end));
|
|
25
25
|
}
|
|
26
26
|
IndexMap.toInnerRange = toInnerRange;
|
|
27
27
|
function toOuterOffset(map, offset) {
|
|
28
|
-
return convertOffset(map, offset, 'inner', 'outer'
|
|
28
|
+
return convertOffset(map, offset, 'inner', 'outer');
|
|
29
29
|
}
|
|
30
30
|
IndexMap.toOuterOffset = toOuterOffset;
|
|
31
31
|
function toOuterRange(map, inner) {
|
|
32
|
-
return Range.create(toOuterOffset(map, inner.start),
|
|
32
|
+
return Range.create(toOuterOffset(map, inner.start), toOuterOffset(map, inner.end));
|
|
33
33
|
}
|
|
34
34
|
IndexMap.toOuterRange = toOuterRange;
|
|
35
35
|
function merge(outerMap, innerMap) {
|
|
@@ -16,13 +16,13 @@ export interface LanguageError extends LanguageErrorData {
|
|
|
16
16
|
export interface PosRangeLanguageError extends LanguageErrorData {
|
|
17
17
|
posRange: PositionRange;
|
|
18
18
|
}
|
|
19
|
-
export declare
|
|
20
|
-
create(message: string, range: Range, severity?: ErrorSeverity, info?: LanguageErrorInfo): LanguageError;
|
|
19
|
+
export declare namespace LanguageError {
|
|
20
|
+
function create(message: string, range: Range, severity?: ErrorSeverity, info?: LanguageErrorInfo): LanguageError;
|
|
21
21
|
/**
|
|
22
22
|
* @returns A {@link PosRangeLanguageError}.
|
|
23
23
|
*/
|
|
24
|
-
withPosRange(error: LanguageError, doc: TextDocument): PosRangeLanguageError;
|
|
25
|
-
}
|
|
24
|
+
function withPosRange(error: LanguageError, doc: TextDocument): PosRangeLanguageError;
|
|
25
|
+
}
|
|
26
26
|
export declare const enum ErrorSeverity {
|
|
27
27
|
Hint = 0,
|
|
28
28
|
Information = 1,
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { PositionRange } from './PositionRange.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
2
|
+
export var LanguageError;
|
|
3
|
+
(function (LanguageError) {
|
|
4
|
+
function create(message, range, severity = 3 /* ErrorSeverity.Error */, info) {
|
|
4
5
|
const ans = { range, message, severity };
|
|
5
6
|
if (info) {
|
|
6
7
|
ans.info = info;
|
|
7
8
|
}
|
|
8
9
|
return ans;
|
|
9
|
-
}
|
|
10
|
+
}
|
|
11
|
+
LanguageError.create = create;
|
|
10
12
|
/**
|
|
11
13
|
* @returns A {@link PosRangeLanguageError}.
|
|
12
14
|
*/
|
|
13
|
-
withPosRange(error, doc) {
|
|
15
|
+
function withPosRange(error, doc) {
|
|
14
16
|
return {
|
|
15
17
|
posRange: PositionRange.from(error.range, doc),
|
|
16
18
|
message: error.message,
|
|
17
19
|
severity: error.severity,
|
|
18
20
|
...(error.info && { info: error.info }),
|
|
19
21
|
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
+
}
|
|
23
|
+
LanguageError.withPosRange = withPosRange;
|
|
24
|
+
})(LanguageError || (LanguageError = {}));
|
|
22
25
|
//# sourceMappingURL=LanguageError.js.map
|
package/lib/source/Source.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export declare class Source extends ReadonlySource {
|
|
|
62
62
|
read(): string;
|
|
63
63
|
/**
|
|
64
64
|
* Skips the current character.
|
|
65
|
-
* @param step The step to skip.
|
|
65
|
+
* @param step The step to skip. Defaults to 1
|
|
66
66
|
*/
|
|
67
67
|
skip(step?: number): this;
|
|
68
68
|
/**
|
|
@@ -110,11 +110,13 @@ export declare class Source extends ReadonlySource {
|
|
|
110
110
|
skipUntilLineEnd(): this;
|
|
111
111
|
readRemaining(): string;
|
|
112
112
|
skipRemaining(): this;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
}
|
|
114
|
+
export declare namespace Source {
|
|
115
|
+
function isDigit(c: string): c is Digit;
|
|
116
|
+
function isBrigadierQuote(c: string): c is '"' | "'";
|
|
117
|
+
function isNewline(c: string): c is Newline;
|
|
118
|
+
function isSpace(c: string): c is Space;
|
|
119
|
+
function isWhitespace(c: string): c is Whitespace;
|
|
118
120
|
}
|
|
119
121
|
export {};
|
|
120
122
|
//# sourceMappingURL=Source.d.ts.map
|
package/lib/source/Source.js
CHANGED
|
@@ -79,10 +79,10 @@ export class ReadonlySource {
|
|
|
79
79
|
hasNonSpaceAheadInLine() {
|
|
80
80
|
for (let cursor = this.innerCursor; cursor < this.string.length; cursor++) {
|
|
81
81
|
const c = this.string.charAt(cursor);
|
|
82
|
-
if (c
|
|
82
|
+
if (Source.isNewline(c)) {
|
|
83
83
|
break;
|
|
84
84
|
}
|
|
85
|
-
if (!(c
|
|
85
|
+
if (!Source.isSpace(c)) {
|
|
86
86
|
return true;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -134,7 +134,7 @@ export class Source extends ReadonlySource {
|
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* Skips the current character.
|
|
137
|
-
* @param step The step to skip.
|
|
137
|
+
* @param step The step to skip. Defaults to 1
|
|
138
138
|
*/
|
|
139
139
|
skip(step = 1) {
|
|
140
140
|
this.innerCursor += step;
|
|
@@ -266,20 +266,27 @@ export class Source extends ReadonlySource {
|
|
|
266
266
|
this.readRemaining();
|
|
267
267
|
return this;
|
|
268
268
|
}
|
|
269
|
-
|
|
269
|
+
}
|
|
270
|
+
(function (Source) {
|
|
271
|
+
function isDigit(c) {
|
|
270
272
|
return c >= '0' && c <= '9';
|
|
271
273
|
}
|
|
272
|
-
|
|
274
|
+
Source.isDigit = isDigit;
|
|
275
|
+
function isBrigadierQuote(c) {
|
|
273
276
|
return c === '"' || c === "'";
|
|
274
277
|
}
|
|
275
|
-
|
|
278
|
+
Source.isBrigadierQuote = isBrigadierQuote;
|
|
279
|
+
function isNewline(c) {
|
|
276
280
|
return c === '\r\n' || c === '\r' || c === '\n';
|
|
277
281
|
}
|
|
278
|
-
|
|
282
|
+
Source.isNewline = isNewline;
|
|
283
|
+
function isSpace(c) {
|
|
279
284
|
return c === ' ' || c === '\t';
|
|
280
285
|
}
|
|
281
|
-
|
|
286
|
+
Source.isSpace = isSpace;
|
|
287
|
+
function isWhitespace(c) {
|
|
282
288
|
return Source.isSpace(c) || Source.isNewline(c);
|
|
283
289
|
}
|
|
284
|
-
|
|
290
|
+
Source.isWhitespace = isWhitespace;
|
|
291
|
+
})(Source || (Source = {}));
|
|
285
292
|
//# sourceMappingURL=Source.js.map
|