@spyglassmc/core 0.4.5 → 0.4.6
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 +2 -5
- package/lib/common/ReadonlyProxy.js +1 -3
- package/lib/common/StateProxy.js +2 -8
- package/lib/common/externals/BrowserExternals.js +7 -12
- package/lib/common/externals/NodeJsExternals.js +12 -8
- package/lib/common/externals/index.d.ts +8 -1
- package/lib/common/util.js +3 -10
- package/lib/node/AstNode.js +7 -9
- package/lib/node/BooleanNode.js +1 -4
- package/lib/node/FloatNode.js +1 -5
- package/lib/node/IntegerNode.js +1 -5
- package/lib/node/ListNode.d.ts +1 -1
- package/lib/node/LiteralNode.js +1 -6
- package/lib/node/LongNode.js +1 -5
- package/lib/node/PrefixedNode.d.ts +13 -0
- package/lib/node/PrefixedNode.js +22 -0
- package/lib/node/ResourceLocationNode.d.ts +1 -1
- package/lib/node/ResourceLocationNode.js +2 -8
- package/lib/node/StringNode.d.ts +2 -1
- package/lib/node/StringNode.js +1 -4
- package/lib/node/SymbolNode.js +1 -6
- package/lib/node/index.d.ts +1 -0
- package/lib/node/index.js +1 -0
- package/lib/parser/comment.d.ts +1 -1
- package/lib/parser/comment.js +2 -6
- package/lib/parser/error.js +1 -4
- package/lib/parser/file.d.ts +2 -2
- package/lib/parser/file.js +1 -2
- package/lib/parser/float.js +2 -7
- package/lib/parser/index.d.ts +1 -0
- package/lib/parser/index.js +1 -0
- package/lib/parser/integer.js +3 -7
- package/lib/parser/list.d.ts +1 -1
- package/lib/parser/list.js +2 -6
- package/lib/parser/literal.js +2 -9
- package/lib/parser/long.js +2 -7
- package/lib/parser/prefixed.d.ts +8 -0
- package/lib/parser/prefixed.js +23 -0
- package/lib/parser/record.d.ts +1 -1
- package/lib/parser/record.js +11 -17
- package/lib/parser/resourceLocation.d.ts +1 -0
- package/lib/parser/resourceLocation.js +6 -4
- package/lib/parser/string.js +6 -9
- package/lib/parser/util.d.ts +14 -3
- package/lib/parser/util.js +48 -26
- package/lib/processor/ColorInfoProvider.js +8 -25
- package/lib/processor/binder/builtin.d.ts +1 -0
- package/lib/processor/binder/builtin.js +20 -30
- package/lib/processor/checker/builtin.d.ts +1 -0
- package/lib/processor/checker/builtin.js +13 -7
- package/lib/processor/colorizer/Colorizer.d.ts +1 -1
- package/lib/processor/colorizer/Colorizer.js +4 -7
- package/lib/processor/colorizer/builtin.js +2 -2
- package/lib/processor/completer/Completer.js +1 -3
- package/lib/processor/completer/builtin.d.ts +3 -2
- package/lib/processor/completer/builtin.js +67 -23
- package/lib/processor/formatter/Formatter.js +1 -3
- package/lib/processor/formatter/builtin.js +2 -4
- package/lib/processor/linter/builtin/undeclaredSymbol.js +27 -40
- package/lib/service/CacheService.d.ts +1 -1
- package/lib/service/CacheService.js +12 -13
- package/lib/service/Config.d.ts +36 -0
- package/lib/service/Config.js +28 -45
- package/lib/service/Context.d.ts +2 -0
- package/lib/service/Context.js +4 -12
- package/lib/service/Downloader.d.ts +3 -0
- package/lib/service/Downloader.js +9 -3
- package/lib/service/ErrorReporter.js +3 -0
- package/lib/service/FileService.js +10 -29
- package/lib/service/Hover.js +1 -4
- package/lib/service/MetaRegistry.d.ts +4 -2
- package/lib/service/MetaRegistry.js +16 -8
- package/lib/service/Project.d.ts +9 -3
- package/lib/service/Project.js +71 -48
- package/lib/service/Service.d.ts +1 -1
- package/lib/service/Service.js +11 -36
- package/lib/service/SymbolLocations.js +1 -4
- package/lib/service/fileUtil.d.ts +7 -0
- package/lib/service/fileUtil.js +29 -4
- package/lib/source/IndexMap.js +1 -4
- package/lib/source/Location.js +3 -9
- package/lib/source/Position.js +1 -2
- package/lib/source/PositionRange.js +2 -2
- package/lib/source/Range.js +9 -21
- package/lib/source/Source.d.ts +11 -1
- package/lib/source/Source.js +31 -5
- package/lib/symbol/Symbol.d.ts +14 -9
- package/lib/symbol/Symbol.js +80 -61
- package/lib/symbol/SymbolUtil.d.ts +3 -3
- package/lib/symbol/SymbolUtil.js +48 -72
- package/package.json +3 -2
|
@@ -7,6 +7,9 @@ export class ErrorReporter {
|
|
|
7
7
|
* Reports a new error.
|
|
8
8
|
*/
|
|
9
9
|
report(message, range, severity = 3 /* ErrorSeverity.Error */, info) {
|
|
10
|
+
if (message.trim() === '') {
|
|
11
|
+
throw new Error('Tried to report an error with no message');
|
|
12
|
+
}
|
|
10
13
|
this.errors.push(LanguageError.create(message, Range.get(range), severity, info));
|
|
11
14
|
}
|
|
12
15
|
/**
|
|
@@ -77,8 +77,7 @@ 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
|
|
81
|
-
.getSha1(virtualUri)}/${fileUtil.basename(virtualUri)}`;
|
|
80
|
+
mappedUri = `${this.virtualUrisRoot}${await this.externals.crypto.getSha1(virtualUri)}/${fileUtil.basename(virtualUri)}`;
|
|
82
81
|
// Delete old mapped file if it exists. This makes sure the
|
|
83
82
|
// readonly permission on the file is not removed by it being
|
|
84
83
|
// overwritten.
|
|
@@ -140,8 +139,7 @@ export class FileUriSupporter {
|
|
|
140
139
|
const files = new Map();
|
|
141
140
|
for (let { uri } of dependencies) {
|
|
142
141
|
try {
|
|
143
|
-
if (fileUtil.isFileUri(uri) &&
|
|
144
|
-
(await externals.fs.stat(uri)).isDirectory()) {
|
|
142
|
+
if (fileUtil.isFileUri(uri) && (await externals.fs.stat(uri)).isDirectory()) {
|
|
145
143
|
uri = fileUtil.ensureEndingSlash(uri);
|
|
146
144
|
roots.push(uri);
|
|
147
145
|
files.set(uri, await externals.fs.getAllFiles(uri));
|
|
@@ -154,21 +152,11 @@ export class FileUriSupporter {
|
|
|
154
152
|
return new FileUriSupporter(externals, roots, files);
|
|
155
153
|
}
|
|
156
154
|
}
|
|
157
|
-
// namespace ArchiveUri {
|
|
158
|
-
// export function is(uri: Uri): boolean {
|
|
159
|
-
// return uri.protocol === Protocol && uri.hostname === Hostname
|
|
160
|
-
// }
|
|
161
|
-
// }
|
|
162
155
|
export class ArchiveUriSupporter {
|
|
163
156
|
externals;
|
|
164
157
|
entries;
|
|
165
158
|
static Protocol = 'archive:';
|
|
166
|
-
static SupportedArchiveExtnames = [
|
|
167
|
-
'.tar',
|
|
168
|
-
'.tar.bz2',
|
|
169
|
-
'.tar.gz',
|
|
170
|
-
'.zip',
|
|
171
|
-
];
|
|
159
|
+
static SupportedArchiveExtnames = ['.tar', '.tar.bz2', '.tar.gz', '.zip'];
|
|
172
160
|
protocol = ArchiveUriSupporter.Protocol;
|
|
173
161
|
/**
|
|
174
162
|
* @param entries A map from archive names to unzipped entries.
|
|
@@ -202,10 +190,10 @@ export class ArchiveUriSupporter {
|
|
|
202
190
|
}
|
|
203
191
|
const entry = entries.get(pathInArchive);
|
|
204
192
|
if (!entry) {
|
|
205
|
-
throw
|
|
193
|
+
throw this.externals.error.createKind('ENOENT', `Path “${pathInArchive}” does not exist in archive “${archiveName}”`);
|
|
206
194
|
}
|
|
207
195
|
if (entry.type !== 'file') {
|
|
208
|
-
throw
|
|
196
|
+
throw this.externals.error.createKind('EISDIR', `Path “${pathInArchive}” in archive “${archiveName}” is not a file`);
|
|
209
197
|
}
|
|
210
198
|
return entry.data;
|
|
211
199
|
}
|
|
@@ -235,27 +223,20 @@ export class ArchiveUriSupporter {
|
|
|
235
223
|
if (!path) {
|
|
236
224
|
throw new Error(`Missing path in archive uri “${uri.toString()}”`);
|
|
237
225
|
}
|
|
238
|
-
return {
|
|
239
|
-
archiveName: uri.host,
|
|
240
|
-
pathInArchive: path.charAt(0) === '/' ? path.slice(1) : path,
|
|
241
|
-
};
|
|
226
|
+
return { archiveName: uri.host, pathInArchive: path.charAt(0) === '/' ? path.slice(1) : path };
|
|
242
227
|
}
|
|
243
228
|
static async create(dependencies, externals, logger) {
|
|
244
229
|
const entries = new Map();
|
|
245
230
|
for (const { uri, info } of dependencies) {
|
|
246
231
|
try {
|
|
247
|
-
if (uri.startsWith('file:')
|
|
248
|
-
ArchiveUriSupporter.SupportedArchiveExtnames.some((ext) => uri.endsWith(ext))
|
|
249
|
-
(await externals.fs.stat(uri)).isFile()) {
|
|
232
|
+
if (uri.startsWith('file:')
|
|
233
|
+
&& ArchiveUriSupporter.SupportedArchiveExtnames.some((ext) => uri.endsWith(ext))
|
|
234
|
+
&& (await externals.fs.stat(uri)).isFile()) {
|
|
250
235
|
const archiveName = fileUtil.basename(uri);
|
|
251
236
|
if (entries.has(archiveName)) {
|
|
252
237
|
throw new Error(`A different URI with ${archiveName} already exists`);
|
|
253
238
|
}
|
|
254
|
-
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), {
|
|
255
|
-
stripLevel: typeof info?.startDepth === 'number'
|
|
256
|
-
? info.startDepth
|
|
257
|
-
: 0,
|
|
258
|
-
});
|
|
239
|
+
const files = await externals.archive.decompressBall(await externals.fs.readFile(uri), { stripLevel: typeof info?.startDepth === 'number' ? info.startDepth : 0 });
|
|
259
240
|
entries.set(archiveName, new Map(files.map((f) => [f.path.replace(/\\/g, '/'), f])));
|
|
260
241
|
}
|
|
261
242
|
}
|
package/lib/service/Hover.js
CHANGED
|
@@ -3,10 +3,7 @@ export var Hover;
|
|
|
3
3
|
(function (Hover) {
|
|
4
4
|
/* istanbul ignore next */
|
|
5
5
|
function create(range, markdown) {
|
|
6
|
-
return {
|
|
7
|
-
range: Range.get(range),
|
|
8
|
-
markdown,
|
|
9
|
-
};
|
|
6
|
+
return { range: Range.get(range), markdown };
|
|
10
7
|
}
|
|
11
8
|
Hover.create = create;
|
|
12
9
|
})(Hover || (Hover = {}));
|
|
@@ -16,7 +16,7 @@ export interface LanguageOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
extensions: FileExtension[];
|
|
18
18
|
triggerCharacters?: string[];
|
|
19
|
-
parser
|
|
19
|
+
parser?: Parser<AstNode>;
|
|
20
20
|
completer?: Completer<any>;
|
|
21
21
|
}
|
|
22
22
|
interface LinterRegistration {
|
|
@@ -102,11 +102,13 @@ export declare class MetaRegistry {
|
|
|
102
102
|
* @returns The corresponding `Parser` for the language ID.
|
|
103
103
|
* @throws If there's no such language in the registry.
|
|
104
104
|
*/
|
|
105
|
-
getParserForLanguageId<N extends AstNode>(languageID: string): Parser<N
|
|
105
|
+
getParserForLanguageId<N extends AstNode>(languageID: string): Parser<N> | undefined;
|
|
106
106
|
registerSignatureHelpProvider(provider: SignatureHelpProvider<any>): void;
|
|
107
107
|
get signatureHelpProviders(): Set<SignatureHelpProvider<any>>;
|
|
108
108
|
registerSymbolRegistrar(id: string, registrar: SymbolRegistrarRegistration): void;
|
|
109
109
|
get symbolRegistrars(): Map<string, SymbolRegistrarRegistration>;
|
|
110
|
+
registerCustom<T>(group: string, id: string, object: T): void;
|
|
111
|
+
getCustom<T>(group: string): Map<string, T> | undefined;
|
|
110
112
|
registerUriBinder(uriBinder: UriBinder): void;
|
|
111
113
|
get uriBinders(): Set<UriBinder>;
|
|
112
114
|
setUriSorter(uriSorter: UriSorterRegistration): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Lazy } from '../common/index.js';
|
|
2
|
-
import { binder, checker, colorizer, completer, formatter, linter
|
|
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.
|
|
@@ -20,6 +20,7 @@ export class MetaRegistry {
|
|
|
20
20
|
#parsers = new Map();
|
|
21
21
|
#signatureHelpProviders = new Set();
|
|
22
22
|
#symbolRegistrars = new Map();
|
|
23
|
+
#custom = new Map();
|
|
23
24
|
#uriBinders = new Set();
|
|
24
25
|
#uriSorter = () => 0;
|
|
25
26
|
constructor() {
|
|
@@ -109,8 +110,7 @@ export class MetaRegistry {
|
|
|
109
110
|
}
|
|
110
111
|
shouldComplete(languageID, triggerCharacter) {
|
|
111
112
|
const language = this.#languages.get(languageID);
|
|
112
|
-
return (!triggerCharacter ||
|
|
113
|
-
!!language?.triggerCharacters?.includes(triggerCharacter));
|
|
113
|
+
return (!triggerCharacter || !!language?.triggerCharacters?.includes(triggerCharacter));
|
|
114
114
|
}
|
|
115
115
|
getCompleterForLanguageID(languageID) {
|
|
116
116
|
return this.#languages.get(languageID)?.completer ?? completer.fallback;
|
|
@@ -137,11 +137,8 @@ export class MetaRegistry {
|
|
|
137
137
|
return this.#inlayHintProviders;
|
|
138
138
|
}
|
|
139
139
|
getLinter(ruleName) {
|
|
140
|
-
return (this.#linters.get(ruleName)
|
|
141
|
-
configValidator: () => false,
|
|
142
|
-
linter: linter.noop,
|
|
143
|
-
nodePredicate: () => false,
|
|
144
|
-
});
|
|
140
|
+
return (this.#linters.get(ruleName)
|
|
141
|
+
?? { configValidator: () => false, linter: linter.noop, nodePredicate: () => false });
|
|
145
142
|
}
|
|
146
143
|
registerLinter(ruleName, options) {
|
|
147
144
|
this.#linters.set(ruleName, options);
|
|
@@ -184,6 +181,17 @@ export class MetaRegistry {
|
|
|
184
181
|
get symbolRegistrars() {
|
|
185
182
|
return this.#symbolRegistrars;
|
|
186
183
|
}
|
|
184
|
+
registerCustom(group, id, object) {
|
|
185
|
+
let groupRegistry = this.#custom.get(group);
|
|
186
|
+
if (!groupRegistry) {
|
|
187
|
+
groupRegistry = new Map();
|
|
188
|
+
this.#custom.set(group, groupRegistry);
|
|
189
|
+
}
|
|
190
|
+
groupRegistry.set(id, object);
|
|
191
|
+
}
|
|
192
|
+
getCustom(group) {
|
|
193
|
+
return this.#custom.get(group);
|
|
194
|
+
}
|
|
187
195
|
registerUriBinder(uriBinder) {
|
|
188
196
|
this.#uriBinders.add(uriBinder);
|
|
189
197
|
}
|
package/lib/service/Project.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Ignore } from 'ignore';
|
|
1
2
|
import type { TextDocumentContentChangeEvent } from 'vscode-languageserver-textdocument';
|
|
2
3
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
4
|
import type { ExternalEventEmitter, Externals } from '../common/index.js';
|
|
@@ -13,7 +14,7 @@ import { FileService } from './FileService.js';
|
|
|
13
14
|
import type { RootUriString } from './fileUtil.js';
|
|
14
15
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
15
16
|
import { ProfilerFactory } from './Profiler.js';
|
|
16
|
-
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'externals' | 'logger' | 'meta' | 'projectRoot'>;
|
|
17
|
+
export type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'externals' | 'isDebugging' | 'logger' | 'meta' | 'projectRoot'>;
|
|
17
18
|
export type SyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => Record<string, string> | void;
|
|
18
19
|
export type AsyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => PromiseLike<Record<string, string> | void>;
|
|
19
20
|
export type ProjectInitializer = SyncProjectInitializer | AsyncProjectInitializer;
|
|
@@ -24,6 +25,7 @@ export interface ProjectOptions {
|
|
|
24
25
|
externals: Externals;
|
|
25
26
|
fs?: FileService;
|
|
26
27
|
initializers?: readonly ProjectInitializer[];
|
|
28
|
+
isDebugging?: boolean;
|
|
27
29
|
logger?: Logger;
|
|
28
30
|
profilers?: ProfilerFactory;
|
|
29
31
|
/**
|
|
@@ -55,7 +57,7 @@ interface SymbolRegistrarEvent {
|
|
|
55
57
|
id: string;
|
|
56
58
|
checksum: string | undefined;
|
|
57
59
|
}
|
|
58
|
-
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureBindingStarted' | 'externals' | 'fs' | 'logger' | 'meta' | 'profilers' | 'projectRoot' | 'roots' | 'symbols' | 'ctx'>;
|
|
60
|
+
export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureBindingStarted' | 'externals' | 'fs' | 'isDebugging' | 'logger' | 'meta' | 'profilers' | 'projectRoot' | 'roots' | 'symbols' | 'ctx'>;
|
|
59
61
|
/**
|
|
60
62
|
* Manage all tracked documents and errors.
|
|
61
63
|
*
|
|
@@ -96,12 +98,15 @@ export type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' |
|
|
|
96
98
|
export declare class Project implements ExternalEventEmitter {
|
|
97
99
|
#private;
|
|
98
100
|
private static readonly RootSuffix;
|
|
101
|
+
private static readonly GitIgnore;
|
|
99
102
|
readonly cacheService: CacheService;
|
|
100
103
|
get isReady(): boolean;
|
|
101
104
|
config: Config;
|
|
105
|
+
ignore: Ignore;
|
|
102
106
|
readonly downloader: Downloader;
|
|
103
107
|
readonly externals: Externals;
|
|
104
108
|
readonly fs: FileService;
|
|
109
|
+
readonly isDebugging: boolean;
|
|
105
110
|
readonly logger: Logger;
|
|
106
111
|
readonly meta: MetaRegistry;
|
|
107
112
|
readonly profilers: ProfilerFactory;
|
|
@@ -154,8 +159,9 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
154
159
|
* are not loaded into the memory.
|
|
155
160
|
*/
|
|
156
161
|
getTrackedFiles(): string[];
|
|
157
|
-
constructor({ cacheRoot, defaultConfig, downloader, externals, fs, initializers, logger, profilers, projectRoot, }: ProjectOptions);
|
|
162
|
+
constructor({ cacheRoot, defaultConfig, downloader, externals, fs, initializers, isDebugging, logger, profilers, projectRoot, }: ProjectOptions);
|
|
158
163
|
private setInitPromise;
|
|
164
|
+
private readGitignore;
|
|
159
165
|
private setReadyPromise;
|
|
160
166
|
/**
|
|
161
167
|
* Load the config file and initialize parsers and processors.
|
package/lib/service/Project.js
CHANGED
|
@@ -4,12 +4,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
+
import ignore from 'ignore';
|
|
7
8
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
8
9
|
import { bufferToString, Logger, normalizeUri, SingletonPromise, StateProxy, } from '../common/index.js';
|
|
9
10
|
import { FileNode } from '../node/index.js';
|
|
10
11
|
import { file } from '../parser/index.js';
|
|
11
12
|
import { traversePreOrder } from '../processor/index.js';
|
|
12
|
-
import { LanguageError, Source } from '../source/index.js';
|
|
13
|
+
import { LanguageError, Range, Source } from '../source/index.js';
|
|
13
14
|
import { SymbolUtil } from '../symbol/index.js';
|
|
14
15
|
import { CacheService } from './CacheService.js';
|
|
15
16
|
import { ConfigService, LinterConfigValue } from './Config.js';
|
|
@@ -17,7 +18,7 @@ import { BinderContext, CheckerContext, LinterContext, ParserContext, UriBinderC
|
|
|
17
18
|
import { DependencyKey } from './Dependency.js';
|
|
18
19
|
import { Downloader } from './Downloader.js';
|
|
19
20
|
import { LinterErrorReporter } from './ErrorReporter.js';
|
|
20
|
-
import { ArchiveUriSupporter, FileService, FileUriSupporter
|
|
21
|
+
import { ArchiveUriSupporter, FileService, FileUriSupporter } from './FileService.js';
|
|
21
22
|
import { fileUtil } from './fileUtil.js';
|
|
22
23
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
23
24
|
import { ProfilerFactory } from './Profiler.js';
|
|
@@ -62,6 +63,7 @@ const CacheAutoSaveInterval = 600_000; // 10 Minutes.
|
|
|
62
63
|
*/
|
|
63
64
|
export class Project {
|
|
64
65
|
static RootSuffix = '/pack.mcmeta';
|
|
66
|
+
static GitIgnore = '.gitignore';
|
|
65
67
|
/** Prevent circular binding. */
|
|
66
68
|
#bindingInProgressUris = new Set();
|
|
67
69
|
#cacheSaverIntervalId;
|
|
@@ -83,9 +85,11 @@ export class Project {
|
|
|
83
85
|
return this.#isReady;
|
|
84
86
|
}
|
|
85
87
|
config;
|
|
88
|
+
ignore = ignore();
|
|
86
89
|
downloader;
|
|
87
90
|
externals;
|
|
88
91
|
fs;
|
|
92
|
+
isDebugging;
|
|
89
93
|
logger;
|
|
90
94
|
meta = new MetaRegistry();
|
|
91
95
|
profilers;
|
|
@@ -125,8 +129,7 @@ export class Project {
|
|
|
125
129
|
const ans = new Set(rawRoots);
|
|
126
130
|
// Identify roots indicated by `pack.mcmeta`.
|
|
127
131
|
for (const file of this.getTrackedFiles()) {
|
|
128
|
-
if (file.endsWith(Project.RootSuffix) &&
|
|
129
|
-
rawRoots.some((r) => file.startsWith(r))) {
|
|
132
|
+
if (file.endsWith(Project.RootSuffix) && rawRoots.some((r) => file.startsWith(r))) {
|
|
130
133
|
ans.add(file.slice(0, 1 - Project.RootSuffix.length));
|
|
131
134
|
}
|
|
132
135
|
}
|
|
@@ -152,30 +155,30 @@ export class Project {
|
|
|
152
155
|
*/
|
|
153
156
|
getTrackedFiles() {
|
|
154
157
|
const extensions = this.meta.getSupportedFileExtensions();
|
|
155
|
-
|
|
158
|
+
const supportedFiles = [...this.#dependencyFiles, ...this.#watchedFiles].filter((file) => extensions.includes(fileUtil.extname(file) ?? ''));
|
|
159
|
+
const filteredFiles = this.ignore.filter(supportedFiles);
|
|
160
|
+
return filteredFiles;
|
|
156
161
|
}
|
|
157
|
-
constructor({ cacheRoot, defaultConfig, downloader, externals, fs = FileService.create(externals, cacheRoot), initializers = [], logger = Logger.create(), profilers = ProfilerFactory.noop(), projectRoot, }) {
|
|
162
|
+
constructor({ cacheRoot, defaultConfig, downloader, externals, fs = FileService.create(externals, cacheRoot), initializers = [], isDebugging = false, logger = Logger.create(), profilers = ProfilerFactory.noop(), projectRoot, }) {
|
|
158
163
|
this.#cacheRoot = cacheRoot;
|
|
159
164
|
this.#eventEmitter = new externals.event.EventEmitter();
|
|
160
165
|
this.externals = externals;
|
|
161
166
|
this.fs = fs;
|
|
162
167
|
this.#initializers = initializers;
|
|
168
|
+
this.isDebugging = isDebugging;
|
|
163
169
|
this.logger = logger;
|
|
164
170
|
this.profilers = profilers;
|
|
165
171
|
this.projectRoot = projectRoot;
|
|
166
172
|
this.cacheService = new CacheService(cacheRoot, this);
|
|
167
173
|
this.#configService = new ConfigService(this, defaultConfig);
|
|
168
|
-
this.downloader = downloader ??
|
|
169
|
-
new Downloader(cacheRoot, externals, logger);
|
|
174
|
+
this.downloader = downloader ?? new Downloader(cacheRoot, externals, logger);
|
|
170
175
|
this.symbols = new SymbolUtil({}, externals.event.EventEmitter);
|
|
171
176
|
this.#ctx = {};
|
|
172
177
|
this.logger.info(`[Project] [init] cacheRoot = “${cacheRoot}”`);
|
|
173
|
-
this.#configService
|
|
174
|
-
.on('changed', ({ config }) => {
|
|
178
|
+
this.#configService.on('changed', ({ config }) => {
|
|
175
179
|
this.config = config;
|
|
176
180
|
this.logger.info('[Project] [Config] Changed');
|
|
177
|
-
})
|
|
178
|
-
.on('error', ({ error, uri }) => this.logger.error(`[Project] [Config] Failed loading “${uri}”`, error));
|
|
181
|
+
}).on('error', ({ error, uri }) => this.logger.error(`[Project] [Config] Failed loading “${uri}”`, error));
|
|
179
182
|
this.setInitPromise();
|
|
180
183
|
this.setReadyPromise();
|
|
181
184
|
this.#cacheSaverIntervalId = setInterval(() => this.cacheService.save(), CacheAutoSaveInterval);
|
|
@@ -188,32 +191,27 @@ export class Project {
|
|
|
188
191
|
uri: doc.uri,
|
|
189
192
|
version: doc.version,
|
|
190
193
|
});
|
|
191
|
-
})
|
|
192
|
-
.on('documentRemoved', ({ uri }) => {
|
|
194
|
+
}).on('documentRemoved', ({ uri }) => {
|
|
193
195
|
this.emit('documentErrored', { errors: [], uri });
|
|
194
|
-
})
|
|
195
|
-
.on('fileCreated', async ({ uri }) => {
|
|
196
|
+
}).on('fileCreated', async ({ uri }) => {
|
|
196
197
|
if (uri.endsWith(Project.RootSuffix)) {
|
|
197
198
|
this.updateRoots();
|
|
198
199
|
}
|
|
199
200
|
this.bindUri(uri);
|
|
200
201
|
return this.ensureBindingStarted(uri);
|
|
201
|
-
})
|
|
202
|
-
.on('fileModified', async ({ uri }) => {
|
|
202
|
+
}).on('fileModified', async ({ uri }) => {
|
|
203
203
|
this.#symbolUpToDateUris.delete(uri);
|
|
204
204
|
if (this.isOnlyWatched(uri)) {
|
|
205
205
|
await this.ensureBindingStarted(uri);
|
|
206
206
|
}
|
|
207
|
-
})
|
|
208
|
-
.on('fileDeleted', ({ uri }) => {
|
|
207
|
+
}).on('fileDeleted', ({ uri }) => {
|
|
209
208
|
if (uri.endsWith(Project.RootSuffix)) {
|
|
210
209
|
this.updateRoots();
|
|
211
210
|
}
|
|
212
211
|
this.#symbolUpToDateUris.delete(uri);
|
|
213
212
|
this.symbols.clear({ uri });
|
|
214
213
|
this.tryClearingCache(uri);
|
|
215
|
-
})
|
|
216
|
-
.on('ready', () => {
|
|
214
|
+
}).on('ready', () => {
|
|
217
215
|
this.#isReady = true;
|
|
218
216
|
// // Recheck client managed files after the READY process, as they may have incomplete results and are user-facing.
|
|
219
217
|
// const promises: Promise<unknown>[] = []
|
|
@@ -226,6 +224,18 @@ export class Project {
|
|
|
226
224
|
setInitPromise() {
|
|
227
225
|
const loadConfig = async () => {
|
|
228
226
|
this.config = await this.#configService.load();
|
|
227
|
+
this.ignore = ignore();
|
|
228
|
+
for (const pattern of this.config.env.exclude) {
|
|
229
|
+
if (pattern === '@gitignore') {
|
|
230
|
+
const gitignore = await this.readGitignore();
|
|
231
|
+
if (gitignore) {
|
|
232
|
+
this.ignore.add(gitignore);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
this.ignore.add(pattern);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
229
239
|
};
|
|
230
240
|
const callIntializers = async () => {
|
|
231
241
|
const initCtx = {
|
|
@@ -233,6 +243,7 @@ export class Project {
|
|
|
233
243
|
config: this.config,
|
|
234
244
|
downloader: this.downloader,
|
|
235
245
|
externals: this.externals,
|
|
246
|
+
isDebugging: this.isDebugging,
|
|
236
247
|
logger: this.logger,
|
|
237
248
|
meta: this.meta,
|
|
238
249
|
projectRoot: this.projectRoot,
|
|
@@ -262,6 +273,19 @@ export class Project {
|
|
|
262
273
|
};
|
|
263
274
|
this.#initPromise = init();
|
|
264
275
|
}
|
|
276
|
+
async readGitignore() {
|
|
277
|
+
try {
|
|
278
|
+
const uri = this.projectRoot + Project.GitIgnore;
|
|
279
|
+
const contents = await this.externals.fs.readFile(uri);
|
|
280
|
+
return bufferToString(contents);
|
|
281
|
+
}
|
|
282
|
+
catch (e) {
|
|
283
|
+
if (!this.externals.error.isKind(e, 'ENOENT')) {
|
|
284
|
+
this.logger.error(`[Project] [readGitignore]`, e);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
265
289
|
setReadyPromise() {
|
|
266
290
|
const getDependencies = async () => {
|
|
267
291
|
const ans = [];
|
|
@@ -297,30 +321,24 @@ export class Project {
|
|
|
297
321
|
const listProjectFiles = () => new Promise((resolve) => {
|
|
298
322
|
this.#watchedFiles.clear();
|
|
299
323
|
this.#watcherReady = false;
|
|
300
|
-
this.#watcher = this.externals.fs
|
|
301
|
-
.watch(this.projectRoot)
|
|
302
|
-
.once('ready', () => {
|
|
324
|
+
this.#watcher = this.externals.fs.watch(this.projectRoot).once('ready', () => {
|
|
303
325
|
this.#watcherReady = true;
|
|
304
326
|
resolve();
|
|
305
|
-
})
|
|
306
|
-
.on('add', (uri) => {
|
|
327
|
+
}).on('add', (uri) => {
|
|
307
328
|
this.#watchedFiles.add(uri);
|
|
308
329
|
if (this.#watcherReady) {
|
|
309
330
|
this.emit('fileCreated', { uri });
|
|
310
331
|
}
|
|
311
|
-
})
|
|
312
|
-
.on('change', (uri) => {
|
|
332
|
+
}).on('change', (uri) => {
|
|
313
333
|
if (this.#watcherReady) {
|
|
314
334
|
this.emit('fileModified', { uri });
|
|
315
335
|
}
|
|
316
|
-
})
|
|
317
|
-
.on('unlink', (uri) => {
|
|
336
|
+
}).on('unlink', (uri) => {
|
|
318
337
|
this.#watchedFiles.delete(uri);
|
|
319
338
|
if (this.#watcherReady) {
|
|
320
339
|
this.emit('fileDeleted', { uri });
|
|
321
340
|
}
|
|
322
|
-
})
|
|
323
|
-
.on('error', (e) => {
|
|
341
|
+
}).on('error', (e) => {
|
|
324
342
|
this.logger.error('[Project] [chokidar]', e);
|
|
325
343
|
});
|
|
326
344
|
});
|
|
@@ -350,9 +368,7 @@ export class Project {
|
|
|
350
368
|
this.emit('documentErrored', { errors: values, uri });
|
|
351
369
|
}
|
|
352
370
|
__profiler.task('Pop Errors');
|
|
353
|
-
const { addedFiles, changedFiles, removedFiles } = await this
|
|
354
|
-
.cacheService
|
|
355
|
-
.validate();
|
|
371
|
+
const { addedFiles, changedFiles, removedFiles } = await this.cacheService.validate();
|
|
356
372
|
for (const uri of removedFiles) {
|
|
357
373
|
this.emit('fileDeleted', { uri });
|
|
358
374
|
}
|
|
@@ -506,9 +522,18 @@ export class Project {
|
|
|
506
522
|
}
|
|
507
523
|
parse(doc) {
|
|
508
524
|
const ctx = ParserContext.create(this, { doc });
|
|
525
|
+
const parser = ctx.meta.getParserForLanguageId(ctx.doc.languageId);
|
|
526
|
+
if (!parser) {
|
|
527
|
+
return {
|
|
528
|
+
type: 'file',
|
|
529
|
+
range: Range.create(0),
|
|
530
|
+
children: [],
|
|
531
|
+
locals: Object.create(null),
|
|
532
|
+
parserErrors: [],
|
|
533
|
+
};
|
|
534
|
+
}
|
|
509
535
|
const src = new Source(doc.getText());
|
|
510
|
-
|
|
511
|
-
return node;
|
|
536
|
+
return file(parser)(src, ctx);
|
|
512
537
|
}
|
|
513
538
|
async bind(doc, node) {
|
|
514
539
|
if (node.binderErrors) {
|
|
@@ -562,8 +587,7 @@ export class Project {
|
|
|
562
587
|
continue;
|
|
563
588
|
}
|
|
564
589
|
const { ruleSeverity, ruleValue } = result;
|
|
565
|
-
const { configValidator, linter, nodePredicate } = this.meta
|
|
566
|
-
.getLinter(ruleName);
|
|
590
|
+
const { configValidator, linter, nodePredicate } = this.meta.getLinter(ruleName);
|
|
567
591
|
if (!configValidator(ruleName, ruleValue, this.logger)) {
|
|
568
592
|
// Config value is invalid.
|
|
569
593
|
continue;
|
|
@@ -590,8 +614,7 @@ export class Project {
|
|
|
590
614
|
// @SingletonPromise()
|
|
591
615
|
async ensureBindingStarted(uri) {
|
|
592
616
|
uri = this.normalizeUri(uri);
|
|
593
|
-
if (this.#symbolUpToDateUris.has(uri) ||
|
|
594
|
-
this.#bindingInProgressUris.has(uri)) {
|
|
617
|
+
if (this.#symbolUpToDateUris.has(uri) || this.#bindingInProgressUris.has(uri)) {
|
|
595
618
|
return;
|
|
596
619
|
}
|
|
597
620
|
this.#bindingInProgressUris.add(uri);
|
|
@@ -702,14 +725,14 @@ export class Project {
|
|
|
702
725
|
}
|
|
703
726
|
}
|
|
704
727
|
shouldRemove(uri) {
|
|
705
|
-
return (!this.#clientManagedUris.has(uri)
|
|
706
|
-
!this.#dependencyFiles.has(uri)
|
|
707
|
-
!this.#watchedFiles.has(uri));
|
|
728
|
+
return (!this.#clientManagedUris.has(uri)
|
|
729
|
+
&& !this.#dependencyFiles.has(uri)
|
|
730
|
+
&& !this.#watchedFiles.has(uri));
|
|
708
731
|
}
|
|
709
732
|
isOnlyWatched(uri) {
|
|
710
|
-
return (this.#watchedFiles.has(uri)
|
|
711
|
-
!this.#clientManagedUris.has(uri)
|
|
712
|
-
!this.#dependencyFiles.has(uri));
|
|
733
|
+
return (this.#watchedFiles.has(uri)
|
|
734
|
+
&& !this.#clientManagedUris.has(uri)
|
|
735
|
+
&& !this.#dependencyFiles.has(uri));
|
|
713
736
|
}
|
|
714
737
|
}
|
|
715
738
|
__decorate([
|
package/lib/service/Service.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare class Service {
|
|
|
22
22
|
readonly logger: Logger;
|
|
23
23
|
readonly profilers: ProfilerFactory;
|
|
24
24
|
readonly project: Project;
|
|
25
|
-
constructor({ isDebugging, logger, profilers, project
|
|
25
|
+
constructor({ isDebugging, logger, profilers, project }: Options);
|
|
26
26
|
private debug;
|
|
27
27
|
colorize(node: FileNode<AstNode>, doc: TextDocument, range?: Range): readonly ColorToken[];
|
|
28
28
|
getColorInfo(node: FileNode<AstNode>, doc: TextDocument): ColorInfo[];
|
package/lib/service/Service.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstNode } from '../node/index.js';
|
|
2
|
-
import { ColorPresentation, completer, traversePreOrder
|
|
2
|
+
import { ColorPresentation, completer, traversePreOrder } from '../processor/index.js';
|
|
3
3
|
import { Range } from '../source/index.js';
|
|
4
4
|
import { SymbolUsageTypes } from '../symbol/index.js';
|
|
5
5
|
import { ColorizerContext, CompleterContext, FormatterContext, ProcessorContext, SignatureHelpProviderContext, } from './Context.js';
|
|
@@ -14,15 +14,11 @@ export class Service {
|
|
|
14
14
|
logger;
|
|
15
15
|
profilers;
|
|
16
16
|
project;
|
|
17
|
-
constructor({ isDebugging = false, logger, profilers = ProfilerFactory.noop(), project
|
|
17
|
+
constructor({ isDebugging = false, logger, profilers = ProfilerFactory.noop(), project }) {
|
|
18
18
|
this.isDebugging = isDebugging;
|
|
19
19
|
this.logger = logger;
|
|
20
20
|
this.profilers = profilers;
|
|
21
|
-
this.project = new Project({
|
|
22
|
-
logger,
|
|
23
|
-
profilers,
|
|
24
|
-
...project,
|
|
25
|
-
});
|
|
21
|
+
this.project = new Project({ isDebugging, logger, profilers, ...project });
|
|
26
22
|
}
|
|
27
23
|
debug(message) {
|
|
28
24
|
if (this.isDebugging) {
|
|
@@ -45,12 +41,8 @@ export class Service {
|
|
|
45
41
|
this.debug(`Getting color info for '${doc.uri}' # ${doc.version}`);
|
|
46
42
|
const ans = [];
|
|
47
43
|
traversePreOrder(node, (_) => true, (node) => node.color, (node) => ans.push({
|
|
48
|
-
color: Array.isArray(node.color)
|
|
49
|
-
|
|
50
|
-
: node.color.value,
|
|
51
|
-
range: Array.isArray(node.color)
|
|
52
|
-
? node.range
|
|
53
|
-
: node.color.range ?? node.range,
|
|
44
|
+
color: Array.isArray(node.color) ? node.color : node.color.value,
|
|
45
|
+
range: Array.isArray(node.color) ? node.range : node.color.range ?? node.range,
|
|
54
46
|
}));
|
|
55
47
|
return ans;
|
|
56
48
|
}
|
|
@@ -62,10 +54,7 @@ export class Service {
|
|
|
62
54
|
getColorPresentation(file, doc, range, color) {
|
|
63
55
|
try {
|
|
64
56
|
this.debug(`Getting color presentation for '${doc.uri}' # ${doc.version} @ ${Range.toString(range)}`);
|
|
65
|
-
let node = AstNode.findDeepestChild({
|
|
66
|
-
node: file,
|
|
67
|
-
needle: range.start,
|
|
68
|
-
});
|
|
57
|
+
let node = AstNode.findDeepestChild({ node: file, needle: range.start });
|
|
69
58
|
while (node) {
|
|
70
59
|
const nodeColor = node.color;
|
|
71
60
|
if (nodeColor && !Array.isArray(nodeColor)) {
|
|
@@ -85,11 +74,7 @@ export class Service {
|
|
|
85
74
|
this.debug(`Getting completion for '${doc.uri}' # ${doc.version} @ ${offset}`);
|
|
86
75
|
const shouldComplete = this.project.meta.shouldComplete(doc.languageId, triggerCharacter);
|
|
87
76
|
if (shouldComplete) {
|
|
88
|
-
return completer.file(node, CompleterContext.create(this.project, {
|
|
89
|
-
doc,
|
|
90
|
-
offset,
|
|
91
|
-
triggerCharacter,
|
|
92
|
-
}));
|
|
77
|
+
return completer.file(node, CompleterContext.create(this.project, { doc, offset, triggerCharacter }));
|
|
93
78
|
}
|
|
94
79
|
}
|
|
95
80
|
catch (e) {
|
|
@@ -110,19 +95,13 @@ export class Service {
|
|
|
110
95
|
// Punctuation should not be treated differently from any other characters, per example:
|
|
111
96
|
// Hata &ack Sub
|
|
112
97
|
// —— Skylinerw, 2022 https://discord.com/channels/154777837382008833/734106483104415856/955521761351454741
|
|
113
|
-
return [...initialism]
|
|
114
|
-
.map((c, i) => `${c.toUpperCase()}${secrets[i % secrets.length]}`)
|
|
115
|
-
.join(' ');
|
|
98
|
+
return [...initialism].map((c, i) => `${c.toUpperCase()}${secrets[i % secrets.length]}`).join(' ');
|
|
116
99
|
}
|
|
117
100
|
format(node, doc, tabSize, insertSpaces) {
|
|
118
101
|
try {
|
|
119
102
|
this.debug(`Formatting '${doc.uri}' # ${doc.version}`);
|
|
120
103
|
const formatter = this.project.meta.getFormatter(node.type);
|
|
121
|
-
return formatter(node, FormatterContext.create(this.project, {
|
|
122
|
-
doc,
|
|
123
|
-
tabSize,
|
|
124
|
-
insertSpaces,
|
|
125
|
-
}));
|
|
104
|
+
return formatter(node, FormatterContext.create(this.project, { doc, tabSize, insertSpaces }));
|
|
126
105
|
}
|
|
127
106
|
catch (e) {
|
|
128
107
|
this.logger.error(`[Service] [format] Failed for “${doc.uri}” #${doc.version}`, e);
|
|
@@ -136,8 +115,7 @@ export class Service {
|
|
|
136
115
|
while (node) {
|
|
137
116
|
const symbol = this.project.symbols.resolveAlias(node.symbol);
|
|
138
117
|
if (symbol) {
|
|
139
|
-
const hover = `\`\`\`typescript\n(${symbol.category}${symbol.subcategory ? `/${symbol.subcategory}` : ''}) ${symbol.identifier}\n\`\`\`` +
|
|
140
|
-
(symbol.desc ? `\n******\n${symbol.desc}` : '');
|
|
118
|
+
const hover = `\`\`\`typescript\n(${symbol.category}${symbol.subcategory ? `/${symbol.subcategory}` : ''}) ${symbol.identifier}\n\`\`\`` + (symbol.desc ? `\n******\n${symbol.desc}` : '');
|
|
141
119
|
return Hover.create(node.range, hover);
|
|
142
120
|
}
|
|
143
121
|
if (node.hover) {
|
|
@@ -170,10 +148,7 @@ export class Service {
|
|
|
170
148
|
getSignatureHelp(node, doc, offset) {
|
|
171
149
|
try {
|
|
172
150
|
this.debug(`Getting signature help for '${doc.uri}' # ${doc.version} @ ${offset}`);
|
|
173
|
-
const ctx = SignatureHelpProviderContext.create(this.project, {
|
|
174
|
-
doc,
|
|
175
|
-
offset,
|
|
176
|
-
});
|
|
151
|
+
const ctx = SignatureHelpProviderContext.create(this.project, { doc, offset });
|
|
177
152
|
for (const provider of this.project.meta.signatureHelpProviders) {
|
|
178
153
|
const result = provider(node, ctx);
|
|
179
154
|
if (result) {
|
|
@@ -3,10 +3,7 @@ export var SymbolLocations;
|
|
|
3
3
|
(function (SymbolLocations) {
|
|
4
4
|
/* istanbul ignore next */
|
|
5
5
|
function create(range, locations) {
|
|
6
|
-
return {
|
|
7
|
-
range: Range.get(range),
|
|
8
|
-
locations,
|
|
9
|
-
};
|
|
6
|
+
return { range: Range.get(range), locations };
|
|
10
7
|
}
|
|
11
8
|
SymbolLocations.create = create;
|
|
12
9
|
})(SymbolLocations || (SymbolLocations = {}));
|