@spyglassmc/core 0.1.1 → 0.1.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/TwoWayMap.d.ts +21 -0
- package/lib/common/TwoWayMap.js +75 -0
- package/lib/common/index.js +5 -1
- package/lib/common/util.d.ts +3 -20
- package/lib/common/util.js +6 -40
- package/lib/index.js +5 -1
- package/lib/node/LiteralNode.d.ts +1 -1
- package/lib/node/LiteralNode.js +1 -1
- package/lib/node/ResourceLocationNode.d.ts +2 -4
- package/lib/node/Sequence.d.ts +2 -1
- package/lib/node/Sequence.js +3 -2
- package/lib/node/SymbolNode.d.ts +1 -1
- package/lib/node/SymbolNode.js +1 -1
- package/lib/node/index.js +5 -1
- package/lib/parser/float.js +1 -1
- package/lib/parser/index.js +5 -1
- package/lib/parser/integer.js +1 -1
- package/lib/parser/long.js +1 -1
- package/lib/parser/string.js +4 -2
- package/lib/parser/util.d.ts +25 -7
- package/lib/parser/util.js +50 -17
- package/lib/processor/checker/builtin.js +1 -1
- package/lib/processor/checker/index.js +5 -1
- package/lib/processor/colorizer/index.js +5 -1
- package/lib/processor/completer/builtin.js +16 -16
- package/lib/processor/completer/index.js +5 -1
- package/lib/processor/formatter/index.js +5 -1
- package/lib/processor/index.js +5 -1
- package/lib/processor/linter/builtin/undeclaredSymbol.js +3 -3
- package/lib/processor/linter/builtin.js +1 -1
- package/lib/processor/linter/index.js +5 -1
- package/lib/service/Config.d.ts +6 -4
- package/lib/service/Config.js +6 -6
- package/lib/service/Context.d.ts +2 -2
- package/lib/service/Context.js +1 -0
- package/lib/service/Downloader.d.ts +1 -0
- package/lib/service/Downloader.js +4 -0
- package/lib/service/ErrorReporter.js +1 -1
- package/lib/service/FileService.d.ts +29 -4
- package/lib/service/FileService.js +82 -19
- package/lib/service/Project.d.ts +1 -0
- package/lib/service/Project.js +23 -11
- package/lib/service/Service.d.ts +2 -2
- package/lib/service/Service.js +25 -15
- package/lib/service/fileUtil.d.ts +15 -5
- package/lib/service/fileUtil.js +39 -4
- package/lib/service/index.js +5 -1
- package/lib/source/LanguageError.js +1 -1
- package/lib/source/Source.d.ts +6 -1
- package/lib/source/Source.js +30 -2
- package/lib/source/index.js +5 -1
- package/lib/symbol/Symbol.d.ts +10 -10
- package/lib/symbol/Symbol.js +7 -6
- package/lib/symbol/SymbolUtil.d.ts +1 -8
- package/lib/symbol/SymbolUtil.js +12 -12
- package/lib/symbol/index.js +5 -1
- package/package.json +2 -2
package/lib/service/Project.js
CHANGED
|
@@ -57,7 +57,7 @@ var ProjectData;
|
|
|
57
57
|
ctx: data.ctx ?? {},
|
|
58
58
|
downloader,
|
|
59
59
|
ensureParsedAndChecked: data.ensureParsedAndChecked,
|
|
60
|
-
fs: data.fs ?? FileService_1.FileService.create(),
|
|
60
|
+
fs: data.fs ?? FileService_1.FileService.create('file:///cache/'),
|
|
61
61
|
get: data.get ?? (() => undefined),
|
|
62
62
|
logger,
|
|
63
63
|
meta: data.meta ?? new MetaRegistry_1.MetaRegistry(),
|
|
@@ -74,7 +74,7 @@ var ProjectData;
|
|
|
74
74
|
* Manage all tracked documents and errors.
|
|
75
75
|
*/
|
|
76
76
|
class Project extends events_1.default {
|
|
77
|
-
constructor({ cacheRoot, downloader, fs = FileService_1.FileService.create(), initializers = [], logger = Logger_1.Logger.create(), profilers = Profiler_1.ProfilerFactory.noop(), projectPath, }) {
|
|
77
|
+
constructor({ cacheRoot, downloader, fs = FileService_1.FileService.create(cacheRoot), initializers = [], logger = Logger_1.Logger.create(), profilers = Profiler_1.ProfilerFactory.noop(), projectPath, }) {
|
|
78
78
|
super();
|
|
79
79
|
_Project_cacheSaverIntervalId.set(this, void 0);
|
|
80
80
|
/**
|
|
@@ -288,9 +288,9 @@ class Project extends events_1.default {
|
|
|
288
288
|
const listDependencyFiles = async () => {
|
|
289
289
|
const dependencies = await getDependencies();
|
|
290
290
|
const fileUriSupporter = await FileService_1.FileUriSupporter.create(dependencies, this.logger);
|
|
291
|
-
const
|
|
291
|
+
const archiveUriSupporter = await FileService_1.ArchiveUriSupporter.create(dependencies, this.logger, this.cacheService.checksums.roots);
|
|
292
292
|
this.fs.register('file:', fileUriSupporter, true);
|
|
293
|
-
this.fs.register(
|
|
293
|
+
this.fs.register(FileService_1.ArchiveUriSupporter.Protocol, archiveUriSupporter, true);
|
|
294
294
|
};
|
|
295
295
|
const listProjectFiles = () => new Promise(resolve => {
|
|
296
296
|
__classPrivateFieldSet(this, _Project_watcherReady, false, "f");
|
|
@@ -361,7 +361,7 @@ class Project extends events_1.default {
|
|
|
361
361
|
this.bind(addedFiles);
|
|
362
362
|
}
|
|
363
363
|
__profiler.task('Bind URIs');
|
|
364
|
-
const files = [...addedFiles, ...changedFiles]; // FIXME:
|
|
364
|
+
const files = [...addedFiles, ...changedFiles]; // FIXME: mcdoc files might need to be parsed and checked before others.
|
|
365
365
|
// const docAndNodes = (await Promise.all(files.map(uri => limit(ensureParsed, uri)))).filter((r): r is DocAndNode => !!r)
|
|
366
366
|
const docAndNodes = (await Promise.all(files.map(uri => ensureParsed(uri)))).filter((r) => !!r);
|
|
367
367
|
__profiler.task('Parse Files');
|
|
@@ -401,11 +401,14 @@ class Project extends events_1.default {
|
|
|
401
401
|
resetCache() {
|
|
402
402
|
return this.cacheService.reset();
|
|
403
403
|
}
|
|
404
|
+
normalizeUri(uri) {
|
|
405
|
+
return this.fs.mapFromDisk(fileUtil_1.fileUtil.normalize(uri));
|
|
406
|
+
}
|
|
404
407
|
/**
|
|
405
408
|
* @returns The language ID of the file, or the file extension without the leading dot.
|
|
406
409
|
*/
|
|
407
410
|
getLanguageID(uri) {
|
|
408
|
-
uri =
|
|
411
|
+
uri = this.normalizeUri(uri);
|
|
409
412
|
const ext = fileUtil_1.fileUtil.extname(uri) ?? '.plaintext';
|
|
410
413
|
return this.meta.getLanguageID(ext) ?? ext.slice(1);
|
|
411
414
|
}
|
|
@@ -413,14 +416,14 @@ class Project extends events_1.default {
|
|
|
413
416
|
* @returns The cached `TextDocument` and `AstNode` for the URI, or `undefined` when such data isn't available in cache.
|
|
414
417
|
*/
|
|
415
418
|
get(uri) {
|
|
416
|
-
uri =
|
|
419
|
+
uri = this.normalizeUri(uri);
|
|
417
420
|
return __classPrivateFieldGet(this, _Project_docAndNodes, "f").get(uri);
|
|
418
421
|
}
|
|
419
422
|
/**
|
|
420
423
|
* @throws FS-related errors
|
|
421
424
|
*/
|
|
422
425
|
async ensureParsed(uri) {
|
|
423
|
-
uri =
|
|
426
|
+
uri = this.normalizeUri(uri);
|
|
424
427
|
if (__classPrivateFieldGet(this, _Project_docAndNodes, "f").has(uri)) {
|
|
425
428
|
return __classPrivateFieldGet(this, _Project_docAndNodes, "f").get(uri);
|
|
426
429
|
}
|
|
@@ -546,7 +549,10 @@ class Project extends events_1.default {
|
|
|
546
549
|
* Notify that a new document was opened in the editor.
|
|
547
550
|
*/
|
|
548
551
|
onDidOpen(uri, languageID, version, content) {
|
|
549
|
-
uri =
|
|
552
|
+
uri = this.normalizeUri(uri);
|
|
553
|
+
if (!fileUtil_1.fileUtil.isFileUri(uri)) {
|
|
554
|
+
return; // We only accept `file:` scheme for client-managed URIs.
|
|
555
|
+
}
|
|
550
556
|
__classPrivateFieldGet(this, _Project_clientManagedUris, "f").add(uri);
|
|
551
557
|
const doc = vscode_languageserver_textdocument_1.TextDocument.create(uri, languageID, version, content);
|
|
552
558
|
const { node } = this.parseAndCache(doc);
|
|
@@ -559,7 +565,10 @@ class Project extends events_1.default {
|
|
|
559
565
|
* @throws If there is no `TextDocument` corresponding to the URI.
|
|
560
566
|
*/
|
|
561
567
|
onDidChange(uri, changes, version) {
|
|
562
|
-
uri =
|
|
568
|
+
uri = this.normalizeUri(uri);
|
|
569
|
+
if (!fileUtil_1.fileUtil.isFileUri(uri)) {
|
|
570
|
+
return; // We only accept `file:` scheme for client-managed URIs.
|
|
571
|
+
}
|
|
563
572
|
const result = this.get(uri);
|
|
564
573
|
if (!result) {
|
|
565
574
|
throw new Error(`Document for “${uri}” is not cached. This should not happen. Did the language client send a didChange notification without sending a didOpen one?`);
|
|
@@ -574,7 +583,10 @@ class Project extends events_1.default {
|
|
|
574
583
|
* Notify that an existing document was closed in the editor.
|
|
575
584
|
*/
|
|
576
585
|
onDidClose(uri) {
|
|
577
|
-
uri =
|
|
586
|
+
uri = this.normalizeUri(uri);
|
|
587
|
+
if (!fileUtil_1.fileUtil.isFileUri(uri)) {
|
|
588
|
+
return; // We only accept `file:` scheme for client-managed URIs.
|
|
589
|
+
}
|
|
578
590
|
__classPrivateFieldGet(this, _Project_clientManagedUris, "f").delete(uri);
|
|
579
591
|
this.tryClearingCache(uri);
|
|
580
592
|
}
|
package/lib/service/Service.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ export declare class Service extends EventEmitter {
|
|
|
39
39
|
getColorPresentation(file: FileNode<AstNode>, doc: TextDocument, range: Range, color: Color): ColorPresentation[];
|
|
40
40
|
complete(node: FileNode<AstNode>, doc: TextDocument, offset: number, triggerCharacter?: string): import("../processor").CompletionItem[];
|
|
41
41
|
dataHackPubify(initialism: string): string;
|
|
42
|
+
format(node: FileNode<AstNode>, doc: TextDocument, tabSize: number, insertSpaces: boolean): string;
|
|
42
43
|
getHover(file: FileNode<AstNode>, doc: TextDocument, offset: number): Hover | undefined;
|
|
43
44
|
getInlayHints(node: FileNode<AstNode>, doc: TextDocument, range?: Range): InlayHint[];
|
|
44
45
|
getSignatureHelp(node: FileNode<AstNode>, doc: TextDocument, offset: number): SignatureHelp | undefined;
|
|
@@ -48,8 +49,7 @@ export declare class Service extends EventEmitter {
|
|
|
48
49
|
*
|
|
49
50
|
* @returns Symbol locations of the selected symbol at `offset`, or `undefined` if there's no symbol at `offset`.
|
|
50
51
|
*/
|
|
51
|
-
getSymbolLocations(file: FileNode<AstNode>, doc: TextDocument, offset: number, searchedUsages?: readonly SymbolUsageType[], currentFileOnly?: boolean): SymbolLocations | undefined
|
|
52
|
-
format(node: FileNode<AstNode>, doc: TextDocument, tabSize: number, insertSpaces: boolean): string;
|
|
52
|
+
getSymbolLocations(file: FileNode<AstNode>, doc: TextDocument, offset: number, searchedUsages?: readonly SymbolUsageType[], currentFileOnly?: boolean): Promise<SymbolLocations | undefined>;
|
|
53
53
|
}
|
|
54
54
|
export {};
|
|
55
55
|
//# sourceMappingURL=Service.d.ts.map
|
package/lib/service/Service.js
CHANGED
|
@@ -12,6 +12,7 @@ const symbol_1 = require("../symbol");
|
|
|
12
12
|
const Context_1 = require("./Context");
|
|
13
13
|
const Downloader_1 = require("./Downloader");
|
|
14
14
|
const FileService_1 = require("./FileService");
|
|
15
|
+
const fileUtil_1 = require("./fileUtil");
|
|
15
16
|
const Hover_1 = require("./Hover");
|
|
16
17
|
const Logger_1 = require("./Logger");
|
|
17
18
|
const Profiler_1 = require("./Profiler");
|
|
@@ -19,7 +20,7 @@ const Project_1 = require("./Project");
|
|
|
19
20
|
const SymbolLocations_1 = require("./SymbolLocations");
|
|
20
21
|
/* istanbul ignore next */
|
|
21
22
|
class Service extends events_1.default {
|
|
22
|
-
constructor({ cacheRoot, downloader, fs = FileService_1.FileService.create(), initializers = [], isDebugging = false, logger = Logger_1.Logger.create(), profilers = Profiler_1.ProfilerFactory.noop(), projectPath, }) {
|
|
23
|
+
constructor({ cacheRoot, downloader, fs = FileService_1.FileService.create(cacheRoot), initializers = [], isDebugging = false, logger = Logger_1.Logger.create(), profilers = Profiler_1.ProfilerFactory.noop(), projectPath, }) {
|
|
23
24
|
super();
|
|
24
25
|
this.downloader = (downloader ?? (downloader = new Downloader_1.Downloader(cacheRoot, logger)));
|
|
25
26
|
this.fs = fs;
|
|
@@ -107,6 +108,17 @@ class Service extends events_1.default {
|
|
|
107
108
|
.map((c, i) => `${c.toUpperCase()}${secrets[i % secrets.length]}`)
|
|
108
109
|
.join(' ');
|
|
109
110
|
}
|
|
111
|
+
format(node, doc, tabSize, insertSpaces) {
|
|
112
|
+
try {
|
|
113
|
+
this.debug(`Formatting '${doc.uri}' # ${doc.version}`);
|
|
114
|
+
const formatter = this.project.meta.getFormatter(node.type);
|
|
115
|
+
return formatter(node, Context_1.FormatterContext.create(this.project, { doc, tabSize, insertSpaces }));
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
this.logger.error(`[Service] [format] Failed for “${doc.uri}” #${doc.version}`, e);
|
|
119
|
+
throw e;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
110
122
|
getHover(file, doc, offset) {
|
|
111
123
|
try {
|
|
112
124
|
this.debug(`Getting hover for '${doc.uri}' # ${doc.version} @ ${offset}`);
|
|
@@ -166,20 +178,29 @@ class Service extends events_1.default {
|
|
|
166
178
|
*
|
|
167
179
|
* @returns Symbol locations of the selected symbol at `offset`, or `undefined` if there's no symbol at `offset`.
|
|
168
180
|
*/
|
|
169
|
-
getSymbolLocations(file, doc, offset, searchedUsages = symbol_1.SymbolUsageTypes, currentFileOnly = false) {
|
|
181
|
+
async getSymbolLocations(file, doc, offset, searchedUsages = symbol_1.SymbolUsageTypes, currentFileOnly = false) {
|
|
170
182
|
try {
|
|
171
183
|
this.debug(`Getting symbol locations of usage '${searchedUsages.join(',')}' for '${doc.uri}' # ${doc.version} @ ${offset} with currentFileOnly=${currentFileOnly}`);
|
|
172
184
|
let node = node_1.AstNode.findDeepestChild({ node: file, needle: offset });
|
|
173
185
|
while (node) {
|
|
174
186
|
const symbol = this.project.symbols.resolveAlias(node.symbol);
|
|
175
187
|
if (symbol) {
|
|
176
|
-
const
|
|
188
|
+
const rawLocations = [];
|
|
177
189
|
for (const usage of searchedUsages) {
|
|
178
190
|
let locs = symbol[usage] ?? [];
|
|
179
191
|
if (currentFileOnly) {
|
|
180
192
|
locs = locs.filter(l => l.uri === doc.uri);
|
|
181
193
|
}
|
|
182
|
-
|
|
194
|
+
rawLocations.push(...locs);
|
|
195
|
+
}
|
|
196
|
+
const locations = [];
|
|
197
|
+
for (const loc of rawLocations) {
|
|
198
|
+
const mappedUri = fileUtil_1.fileUtil.isFileUri(loc.uri)
|
|
199
|
+
? loc.uri
|
|
200
|
+
: await this.project.fs.mapToDisk(loc.uri);
|
|
201
|
+
if (mappedUri) {
|
|
202
|
+
locations.push({ ...loc, uri: mappedUri });
|
|
203
|
+
}
|
|
183
204
|
}
|
|
184
205
|
return SymbolLocations_1.SymbolLocations.create(node.range, locations.length ? locations : undefined);
|
|
185
206
|
}
|
|
@@ -191,17 +212,6 @@ class Service extends events_1.default {
|
|
|
191
212
|
}
|
|
192
213
|
return undefined;
|
|
193
214
|
}
|
|
194
|
-
format(node, doc, tabSize, insertSpaces) {
|
|
195
|
-
try {
|
|
196
|
-
this.debug(`Formatting '${doc.uri}' # ${doc.version}`);
|
|
197
|
-
const formatter = this.project.meta.getFormatter(node.type);
|
|
198
|
-
return formatter(node, Context_1.FormatterContext.create(this.project, { doc, tabSize, insertSpaces }));
|
|
199
|
-
}
|
|
200
|
-
catch (e) {
|
|
201
|
-
this.logger.error(`[Service] [format] Failed for “${doc.uri}” #${doc.version}`, e);
|
|
202
|
-
throw e;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
215
|
}
|
|
206
216
|
exports.Service = Service;
|
|
207
217
|
//# sourceMappingURL=Service.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
|
|
2
|
+
/// <reference types="node" />
|
|
3
3
|
import { URL as Uri } from 'url';
|
|
4
4
|
export declare type RootUriString = `${string}/`;
|
|
5
5
|
export declare type FileExtension = `.${string}`;
|
|
@@ -41,6 +41,10 @@ export declare namespace fileUtil {
|
|
|
41
41
|
* @returns The part from the last `.` to the end of the URI, or `undefined` if no dots exist. No special treatment for leading dots.
|
|
42
42
|
*/
|
|
43
43
|
function extname(value: string): FileExtension | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* @returns The part from the last `/` to the end of the URI.
|
|
46
|
+
*/
|
|
47
|
+
function basename(uri: string): string;
|
|
44
48
|
/**
|
|
45
49
|
* @param fileUri A file URI.
|
|
46
50
|
* @returns The corresponding file path of the `fileUri` in platform-specific format.
|
|
@@ -59,7 +63,7 @@ export declare namespace fileUtil {
|
|
|
59
63
|
*
|
|
60
64
|
* @param mode Default to `0o777` (`rwxrwxrwx`)
|
|
61
65
|
*/
|
|
62
|
-
function ensureDir(path: PathLike, mode?:
|
|
66
|
+
function ensureDir(path: PathLike, mode?: number): Promise<void>;
|
|
63
67
|
/**
|
|
64
68
|
* @throws
|
|
65
69
|
*
|
|
@@ -67,18 +71,24 @@ export declare namespace fileUtil {
|
|
|
67
71
|
*
|
|
68
72
|
* @param mode Default to `0o777` (`rwxrwxrwx`)
|
|
69
73
|
*/
|
|
70
|
-
function ensureParentOfFile(path: PathLike, mode?:
|
|
74
|
+
function ensureParentOfFile(path: PathLike, mode?: number): Promise<void>;
|
|
75
|
+
function chmod(path: PathLike, mode: number): Promise<void>;
|
|
76
|
+
function ensureWritable(path: PathLike): Promise<void>;
|
|
77
|
+
function markReadOnly(path: PathLike): Promise<void>;
|
|
71
78
|
function readFile(path: PathLike): Promise<Buffer>;
|
|
72
79
|
/**
|
|
73
80
|
* @throws
|
|
74
81
|
*
|
|
75
|
-
* The directory of the file will be created recursively if it doesn'
|
|
82
|
+
* The directory of the file will be created recursively if it doesn't exist.
|
|
83
|
+
*
|
|
84
|
+
* The target file will be given permission `0o666` (`rw-rw-rw-`) before being written into, and changed back to the
|
|
85
|
+
* specified `mode`.
|
|
76
86
|
*
|
|
77
87
|
* * Encoding: `utf-8`
|
|
78
88
|
* * Mode: `0o666` (`rw-rw-rw-`)
|
|
79
89
|
* * Flag: `w`
|
|
80
90
|
*/
|
|
81
|
-
function writeFile(path: PathLike, data: Buffer | string): Promise<void>;
|
|
91
|
+
function writeFile(path: PathLike, data: Buffer | string, mode?: number): Promise<void>;
|
|
82
92
|
/**
|
|
83
93
|
* @throws
|
|
84
94
|
*/
|
package/lib/service/fileUtil.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -93,6 +97,14 @@ var fileUtil;
|
|
|
93
97
|
return i >= 0 ? value.slice(i) : undefined;
|
|
94
98
|
}
|
|
95
99
|
fileUtil.extname = extname;
|
|
100
|
+
/**
|
|
101
|
+
* @returns The part from the last `/` to the end of the URI.
|
|
102
|
+
*/
|
|
103
|
+
function basename(uri) {
|
|
104
|
+
const i = uri.lastIndexOf('/');
|
|
105
|
+
return i >= 0 ? uri.slice(i + 1) : uri;
|
|
106
|
+
}
|
|
107
|
+
fileUtil.basename = basename;
|
|
96
108
|
/* istanbul ignore next */
|
|
97
109
|
/**
|
|
98
110
|
* @param fileUri A file URI.
|
|
@@ -172,6 +184,25 @@ var fileUtil;
|
|
|
172
184
|
return ensureDir(getParentOfFile(path), mode);
|
|
173
185
|
}
|
|
174
186
|
fileUtil.ensureParentOfFile = ensureParentOfFile;
|
|
187
|
+
async function chmod(path, mode) {
|
|
188
|
+
return fs_1.promises.chmod(toFsPathLike(path), mode);
|
|
189
|
+
}
|
|
190
|
+
fileUtil.chmod = chmod;
|
|
191
|
+
async function ensureWritable(path) {
|
|
192
|
+
try {
|
|
193
|
+
await chmod(path, 0o666);
|
|
194
|
+
}
|
|
195
|
+
catch (e) {
|
|
196
|
+
if (!(0, common_1.isEnoent)(e)) {
|
|
197
|
+
throw e;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
fileUtil.ensureWritable = ensureWritable;
|
|
202
|
+
async function markReadOnly(path) {
|
|
203
|
+
return chmod(path, 0o444);
|
|
204
|
+
}
|
|
205
|
+
fileUtil.markReadOnly = markReadOnly;
|
|
175
206
|
async function readFile(path) {
|
|
176
207
|
return fs_1.promises.readFile(toFsPathLike(path));
|
|
177
208
|
}
|
|
@@ -180,15 +211,19 @@ var fileUtil;
|
|
|
180
211
|
/**
|
|
181
212
|
* @throws
|
|
182
213
|
*
|
|
183
|
-
* The directory of the file will be created recursively if it doesn'
|
|
214
|
+
* The directory of the file will be created recursively if it doesn't exist.
|
|
215
|
+
*
|
|
216
|
+
* The target file will be given permission `0o666` (`rw-rw-rw-`) before being written into, and changed back to the
|
|
217
|
+
* specified `mode`.
|
|
184
218
|
*
|
|
185
219
|
* * Encoding: `utf-8`
|
|
186
220
|
* * Mode: `0o666` (`rw-rw-rw-`)
|
|
187
221
|
* * Flag: `w`
|
|
188
222
|
*/
|
|
189
|
-
async function writeFile(path, data) {
|
|
223
|
+
async function writeFile(path, data, mode = 0o666) {
|
|
190
224
|
await ensureParentOfFile(path);
|
|
191
|
-
|
|
225
|
+
await ensureWritable(path);
|
|
226
|
+
return fs_1.promises.writeFile(toFsPathLike(path), data, { mode });
|
|
192
227
|
}
|
|
193
228
|
fileUtil.writeFile = writeFile;
|
|
194
229
|
/* istanbul ignore next */
|
package/lib/service/index.js
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
/* istanbul ignore file */
|
|
3
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
4
|
if (k2 === undefined) k2 = k;
|
|
5
|
-
Object.
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
6
10
|
}) : (function(o, m, k, k2) {
|
|
7
11
|
if (k2 === undefined) k2 = k;
|
|
8
12
|
o[k2] = m[k];
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LanguageError = void 0;
|
|
4
4
|
var LanguageError;
|
|
5
5
|
(function (LanguageError) {
|
|
6
|
-
function create(message, range, severity = 3 /* Error */, info) {
|
|
6
|
+
function create(message, range, severity = 3 /* ErrorSeverity.Error */, info) {
|
|
7
7
|
const ans = { range, message, severity };
|
|
8
8
|
if (info) {
|
|
9
9
|
ans.info = info;
|
package/lib/source/Source.d.ts
CHANGED
|
@@ -35,9 +35,12 @@ export declare class ReadonlySource {
|
|
|
35
35
|
/**
|
|
36
36
|
* If the `expectedValue` is right after the cursor, returns `true`. Otherwise returns `false`.
|
|
37
37
|
*
|
|
38
|
+
* @param offset Defaults to 0.
|
|
39
|
+
*
|
|
38
40
|
* @see {@link Source.trySkip}
|
|
39
41
|
*/
|
|
40
|
-
tryPeek(expectedValue: string): boolean;
|
|
42
|
+
tryPeek(expectedValue: string, offset?: number): boolean;
|
|
43
|
+
tryPeekAfterWhitespace(expectedValue: string): boolean;
|
|
41
44
|
peekUntil(...terminators: string[]): string;
|
|
42
45
|
peekLine(): string;
|
|
43
46
|
hasNonSpaceAheadInLine(): boolean;
|
|
@@ -91,6 +94,8 @@ export declare class Source extends ReadonlySource {
|
|
|
91
94
|
skipSpace(): this;
|
|
92
95
|
readWhitespace(): string;
|
|
93
96
|
skipWhitespace(): this;
|
|
97
|
+
readIf(predicate: (this: void, char: string) => boolean): string;
|
|
98
|
+
skipIf(predicate: (this: void, char: string) => boolean): this;
|
|
94
99
|
/**
|
|
95
100
|
* @param terminators Ending character. Will not be skipped or included in the result.
|
|
96
101
|
*/
|
package/lib/source/Source.js
CHANGED
|
@@ -40,10 +40,20 @@ class ReadonlySource {
|
|
|
40
40
|
/**
|
|
41
41
|
* If the `expectedValue` is right after the cursor, returns `true`. Otherwise returns `false`.
|
|
42
42
|
*
|
|
43
|
+
* @param offset Defaults to 0.
|
|
44
|
+
*
|
|
43
45
|
* @see {@link Source.trySkip}
|
|
44
46
|
*/
|
|
45
|
-
tryPeek(expectedValue) {
|
|
46
|
-
return this.peek(expectedValue.length) === expectedValue;
|
|
47
|
+
tryPeek(expectedValue, offset = 0) {
|
|
48
|
+
return this.peek(expectedValue.length, offset) === expectedValue;
|
|
49
|
+
}
|
|
50
|
+
tryPeekAfterWhitespace(expectedValue) {
|
|
51
|
+
const maxOffset = this.string.length - this.innerCursor;
|
|
52
|
+
let offset = 0;
|
|
53
|
+
while (offset < maxOffset && Source.isWhitespace(this.peek(1, offset))) {
|
|
54
|
+
offset++;
|
|
55
|
+
}
|
|
56
|
+
return this.tryPeek(expectedValue, offset);
|
|
47
57
|
}
|
|
48
58
|
peekUntil(...terminators) {
|
|
49
59
|
let ans = '';
|
|
@@ -191,6 +201,24 @@ class Source extends ReadonlySource {
|
|
|
191
201
|
}
|
|
192
202
|
return this;
|
|
193
203
|
}
|
|
204
|
+
readIf(predicate) {
|
|
205
|
+
let ans = '';
|
|
206
|
+
while (this.canRead()) {
|
|
207
|
+
const c = this.peek();
|
|
208
|
+
if (predicate(c)) {
|
|
209
|
+
this.skip();
|
|
210
|
+
ans += c;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return ans;
|
|
217
|
+
}
|
|
218
|
+
skipIf(predicate) {
|
|
219
|
+
this.readIf(predicate);
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
194
222
|
/**
|
|
195
223
|
* @param terminators Ending character. Will not be skipped or included in the result.
|
|
196
224
|
*/
|
package/lib/source/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|