@spyglassmc/core 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/Dev.js +5 -2
- package/lib/common/Operations.js +7 -3
- package/lib/common/ReadonlyProxy.js +3 -1
- package/lib/common/StateProxy.js +18 -7
- package/lib/common/externals/BrowserExternals.js +2 -9
- package/lib/common/externals/NodeJsExternals.js +7 -17
- package/lib/common/externals/index.d.ts +0 -3
- package/lib/common/util.d.ts +1 -0
- package/lib/common/util.js +14 -10
- package/lib/node/AstNode.js +6 -4
- package/lib/node/FileNode.js +6 -1
- package/lib/node/ResourceLocationNode.d.ts +2 -2
- package/lib/node/ResourceLocationNode.js +11 -5
- package/lib/parser/boolean.js +1 -1
- package/lib/parser/comment.d.ts +1 -1
- package/lib/parser/comment.js +1 -1
- package/lib/parser/float.js +2 -1
- package/lib/parser/integer.js +2 -1
- package/lib/parser/list.d.ts +1 -1
- package/lib/parser/list.js +3 -3
- package/lib/parser/long.js +2 -1
- package/lib/parser/record.d.ts +1 -1
- package/lib/parser/record.js +18 -8
- package/lib/parser/resourceLocation.js +61 -8
- package/lib/parser/string.js +75 -7
- package/lib/parser/util.d.ts +1 -0
- package/lib/parser/util.js +8 -4
- package/lib/processor/ColorInfoProvider.js +20 -7
- package/lib/processor/binder/builtin.js +27 -17
- package/lib/processor/checker/builtin.d.ts +1 -2
- package/lib/processor/checker/builtin.js +10 -12
- package/lib/processor/colorizer/builtin.js +10 -8
- package/lib/processor/completer/Completer.js +4 -2
- package/lib/processor/completer/builtin.js +26 -23
- package/lib/processor/formatter/builtin.js +14 -12
- package/lib/processor/linter/builtin/undeclaredSymbol.js +47 -24
- package/lib/processor/linter/builtin.js +7 -8
- package/lib/service/CacheService.d.ts +5 -2
- package/lib/service/CacheService.js +21 -9
- package/lib/service/Config.d.ts +2 -2
- package/lib/service/Config.js +23 -19
- package/lib/service/Downloader.js +12 -7
- package/lib/service/FileService.js +22 -8
- package/lib/service/MetaRegistry.d.ts +5 -0
- package/lib/service/MetaRegistry.js +7 -6
- package/lib/service/Profiler.js +10 -5
- package/lib/service/Project.d.ts +9 -7
- package/lib/service/Project.js +62 -36
- package/lib/service/Service.js +19 -9
- package/lib/service/fileUtil.js +2 -1
- package/lib/source/IndexMap.js +1 -1
- package/lib/source/LanguageError.d.ts +18 -4
- package/lib/source/LanguageError.js +16 -6
- package/lib/source/Location.js +4 -1
- package/lib/source/PositionRange.d.ts +1 -1
- package/lib/source/PositionRange.js +4 -4
- package/lib/source/Range.js +6 -3
- package/lib/source/Source.d.ts +2 -0
- package/lib/source/Source.js +9 -1
- package/lib/symbol/Symbol.d.ts +7 -7
- package/lib/symbol/Symbol.js +22 -9
- package/lib/symbol/SymbolUtil.d.ts +2 -2
- package/lib/symbol/SymbolUtil.js +74 -43
- package/package.json +2 -2
package/lib/service/Project.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { ExternalEventEmitter, Externals } from '../common/index.js';
|
|
|
4
4
|
import { Logger } from '../common/index.js';
|
|
5
5
|
import type { AstNode } from '../node/index.js';
|
|
6
6
|
import { FileNode } from '../node/index.js';
|
|
7
|
-
import type {
|
|
7
|
+
import type { PosRangeLanguageError } from '../source/index.js';
|
|
8
8
|
import { SymbolUtil } from '../symbol/index.js';
|
|
9
9
|
import { CacheService } from './CacheService.js';
|
|
10
10
|
import type { Config } from './Config.js';
|
|
@@ -38,8 +38,10 @@ export interface DocAndNode {
|
|
|
38
38
|
}
|
|
39
39
|
interface DocumentEvent extends DocAndNode {
|
|
40
40
|
}
|
|
41
|
-
interface DocumentErrorEvent
|
|
42
|
-
errors:
|
|
41
|
+
interface DocumentErrorEvent {
|
|
42
|
+
errors: readonly PosRangeLanguageError[];
|
|
43
|
+
uri: string;
|
|
44
|
+
version?: number;
|
|
43
45
|
}
|
|
44
46
|
interface FileEvent {
|
|
45
47
|
uri: string;
|
|
@@ -124,21 +126,21 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
124
126
|
*/
|
|
125
127
|
get cacheRoot(): RootUriString;
|
|
126
128
|
private updateRoots;
|
|
127
|
-
on(event: '
|
|
129
|
+
on(event: 'documentErrored', callbackFn: (data: DocumentErrorEvent) => void): this;
|
|
128
130
|
on(event: 'documentUpdated', callbackFn: (data: DocumentEvent) => void): this;
|
|
129
131
|
on(event: 'documentRemoved', callbackFn: (data: FileEvent) => void): this;
|
|
130
132
|
on(event: `file${'Created' | 'Modified' | 'Deleted'}`, callbackFn: (data: FileEvent) => void): this;
|
|
131
133
|
on(event: 'ready', callbackFn: (data: EmptyEvent) => void): this;
|
|
132
134
|
on(event: 'rootsUpdated', callbackFn: (data: RootsEvent) => void): this;
|
|
133
135
|
on(event: 'symbolRegistrarExecuted', callbackFn: (data: SymbolRegistrarEvent) => void): this;
|
|
134
|
-
once(event: '
|
|
136
|
+
once(event: 'documentErrored', callbackFn: (data: DocumentErrorEvent) => void): this;
|
|
135
137
|
once(event: 'documentUpdated', callbackFn: (data: DocumentEvent) => void): this;
|
|
136
138
|
once(event: 'documentRemoved', callbackFn: (data: FileEvent) => void): this;
|
|
137
139
|
once(event: `file${'Created' | 'Modified' | 'Deleted'}`, callbackFn: (data: FileEvent) => void): this;
|
|
138
140
|
once(event: 'ready', callbackFn: (data: EmptyEvent) => void): this;
|
|
139
141
|
once(event: 'rootsUpdated', callbackFn: (data: RootsEvent) => void): this;
|
|
140
142
|
once(event: 'symbolRegistrarExecuted', callbackFn: (data: SymbolRegistrarEvent) => void): this;
|
|
141
|
-
emit(event: '
|
|
143
|
+
emit(event: 'documentErrored', data: DocumentErrorEvent): boolean;
|
|
142
144
|
emit(event: 'documentUpdated', data: DocumentEvent): boolean;
|
|
143
145
|
emit(event: 'documentRemoved', data: FileEvent): boolean;
|
|
144
146
|
emit(event: `file${'Created' | 'Modified' | 'Deleted'}`, data: FileEvent): boolean;
|
|
@@ -168,7 +170,7 @@ export declare class Project implements ExternalEventEmitter {
|
|
|
168
170
|
*/
|
|
169
171
|
close(): Promise<void>;
|
|
170
172
|
restart(): Promise<void>;
|
|
171
|
-
resetCache(): void
|
|
173
|
+
resetCache(): Promise<void>;
|
|
172
174
|
normalizeUri(uri: string): string;
|
|
173
175
|
private static readonly TextDocumentCacheMaxLength;
|
|
174
176
|
private removeCachedTextDocument;
|
package/lib/service/Project.js
CHANGED
|
@@ -5,19 +5,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
8
|
-
import { bufferToString, Logger, SingletonPromise, StateProxy } from '../common/index.js';
|
|
8
|
+
import { bufferToString, Logger, normalizeUri, SingletonPromise, StateProxy, } from '../common/index.js';
|
|
9
9
|
import { FileNode } from '../node/index.js';
|
|
10
10
|
import { file } from '../parser/index.js';
|
|
11
11
|
import { traversePreOrder } from '../processor/index.js';
|
|
12
|
-
import { Source } from '../source/index.js';
|
|
12
|
+
import { LanguageError, Source } from '../source/index.js';
|
|
13
13
|
import { SymbolUtil } from '../symbol/index.js';
|
|
14
14
|
import { CacheService } from './CacheService.js';
|
|
15
15
|
import { ConfigService, LinterConfigValue } from './Config.js';
|
|
16
|
-
import { BinderContext, CheckerContext, LinterContext, ParserContext, UriBinderContext } from './Context.js';
|
|
16
|
+
import { BinderContext, CheckerContext, LinterContext, ParserContext, UriBinderContext, } from './Context.js';
|
|
17
17
|
import { DependencyKey } from './Dependency.js';
|
|
18
18
|
import { Downloader } from './Downloader.js';
|
|
19
19
|
import { LinterErrorReporter } from './ErrorReporter.js';
|
|
20
|
-
import { ArchiveUriSupporter, FileService, FileUriSupporter } from './FileService.js';
|
|
20
|
+
import { ArchiveUriSupporter, FileService, FileUriSupporter, } from './FileService.js';
|
|
21
21
|
import { fileUtil } from './fileUtil.js';
|
|
22
22
|
import { MetaRegistry } from './MetaRegistry.js';
|
|
23
23
|
import { ProfilerFactory } from './Profiler.js';
|
|
@@ -125,7 +125,8 @@ export class Project {
|
|
|
125
125
|
const ans = new Set(rawRoots);
|
|
126
126
|
// Identify roots indicated by `pack.mcmeta`.
|
|
127
127
|
for (const file of this.getTrackedFiles()) {
|
|
128
|
-
if (file.endsWith(Project.RootSuffix) &&
|
|
128
|
+
if (file.endsWith(Project.RootSuffix) &&
|
|
129
|
+
rawRoots.some((r) => file.startsWith(r))) {
|
|
129
130
|
ans.add(file.slice(0, 1 - Project.RootSuffix.length));
|
|
130
131
|
}
|
|
131
132
|
}
|
|
@@ -151,8 +152,7 @@ export class Project {
|
|
|
151
152
|
*/
|
|
152
153
|
getTrackedFiles() {
|
|
153
154
|
const extensions = this.meta.getSupportedFileExtensions();
|
|
154
|
-
return [...this.#dependencyFiles, ...this.#watchedFiles]
|
|
155
|
-
.filter(file => extensions.includes(fileUtil.extname(file) ?? ''));
|
|
155
|
+
return [...this.#dependencyFiles, ...this.#watchedFiles].filter((file) => extensions.includes(fileUtil.extname(file) ?? ''));
|
|
156
156
|
}
|
|
157
157
|
constructor({ cacheRoot, defaultConfig, downloader, externals, fs = FileService.create(externals, cacheRoot), initializers = [], logger = Logger.create(), profilers = ProfilerFactory.noop(), projectRoot, }) {
|
|
158
158
|
this.#cacheRoot = cacheRoot;
|
|
@@ -178,16 +178,18 @@ export class Project {
|
|
|
178
178
|
this.setInitPromise();
|
|
179
179
|
this.setReadyPromise();
|
|
180
180
|
this.#cacheSaverIntervalId = setInterval(() => this.cacheService.save(), CacheAutoSaveInterval);
|
|
181
|
-
this
|
|
182
|
-
.on('documentUpdated', ({ doc, node }) => {
|
|
181
|
+
this.on('documentUpdated', ({ doc, node }) => {
|
|
183
182
|
// if (!this.#isReady) {
|
|
184
183
|
// return
|
|
185
184
|
// }
|
|
186
|
-
this.emit('
|
|
187
|
-
doc,
|
|
188
|
-
|
|
189
|
-
|
|
185
|
+
this.emit('documentErrored', {
|
|
186
|
+
errors: FileNode.getErrors(node).map((e) => LanguageError.withPosRange(e, doc)),
|
|
187
|
+
uri: doc.uri,
|
|
188
|
+
version: doc.version,
|
|
190
189
|
});
|
|
190
|
+
})
|
|
191
|
+
.on('documentRemoved', ({ uri }) => {
|
|
192
|
+
this.emit('documentErrored', { errors: [], uri });
|
|
191
193
|
})
|
|
192
194
|
.on('fileCreated', async ({ uri }) => {
|
|
193
195
|
if (uri.endsWith(Project.RootSuffix)) {
|
|
@@ -234,7 +236,7 @@ export class Project {
|
|
|
234
236
|
meta: this.meta,
|
|
235
237
|
projectRoot: this.projectRoot,
|
|
236
238
|
};
|
|
237
|
-
const results = await Promise.allSettled(this.#initializers.map(init => init(initCtx)));
|
|
239
|
+
const results = await Promise.allSettled(this.#initializers.map((init) => init(initCtx)));
|
|
238
240
|
let ctx = {};
|
|
239
241
|
results.forEach(async (r, i) => {
|
|
240
242
|
if (r.status === 'rejected') {
|
|
@@ -291,7 +293,8 @@ export class Project {
|
|
|
291
293
|
this.fs.register('file:', fileUriSupporter, true);
|
|
292
294
|
this.fs.register(ArchiveUriSupporter.Protocol, archiveUriSupporter, true);
|
|
293
295
|
};
|
|
294
|
-
const listProjectFiles = () => new Promise(resolve => {
|
|
296
|
+
const listProjectFiles = () => new Promise((resolve) => {
|
|
297
|
+
this.#watchedFiles.clear();
|
|
295
298
|
this.#watcherReady = false;
|
|
296
299
|
this.#watcher = this.externals.fs
|
|
297
300
|
.watch(this.projectRoot)
|
|
@@ -299,34 +302,31 @@ export class Project {
|
|
|
299
302
|
this.#watcherReady = true;
|
|
300
303
|
resolve();
|
|
301
304
|
})
|
|
302
|
-
.on('add', uri => {
|
|
305
|
+
.on('add', (uri) => {
|
|
303
306
|
this.#watchedFiles.add(uri);
|
|
304
307
|
if (this.#watcherReady) {
|
|
305
308
|
this.emit('fileCreated', { uri });
|
|
306
309
|
}
|
|
307
310
|
})
|
|
308
|
-
.on('change', uri => {
|
|
311
|
+
.on('change', (uri) => {
|
|
309
312
|
if (this.#watcherReady) {
|
|
310
313
|
this.emit('fileModified', { uri });
|
|
311
314
|
}
|
|
312
315
|
})
|
|
313
|
-
.on('unlink', uri => {
|
|
316
|
+
.on('unlink', (uri) => {
|
|
314
317
|
this.#watchedFiles.delete(uri);
|
|
315
318
|
if (this.#watcherReady) {
|
|
316
319
|
this.emit('fileDeleted', { uri });
|
|
317
320
|
}
|
|
318
321
|
})
|
|
319
|
-
.on('error', e => {
|
|
322
|
+
.on('error', (e) => {
|
|
320
323
|
this.logger.error('[Project] [chokidar]', e);
|
|
321
324
|
});
|
|
322
325
|
});
|
|
323
326
|
const ready = async () => {
|
|
324
327
|
await this.init();
|
|
325
328
|
const __profiler = this.profilers.get('project#ready');
|
|
326
|
-
await Promise.all([
|
|
327
|
-
listDependencyFiles(),
|
|
328
|
-
listProjectFiles(),
|
|
329
|
-
]);
|
|
329
|
+
await Promise.all([listDependencyFiles(), listProjectFiles()]);
|
|
330
330
|
this.#dependencyFiles = new Set(this.fs.listFiles());
|
|
331
331
|
this.#dependencyRoots = new Set(this.fs.listRoots());
|
|
332
332
|
this.updateRoots();
|
|
@@ -345,9 +345,13 @@ export class Project {
|
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
__profiler.task('Register Symbols');
|
|
348
|
+
for (const [uri, values] of Object.entries(this.cacheService.errors)) {
|
|
349
|
+
this.emit('documentErrored', { errors: values, uri });
|
|
350
|
+
}
|
|
351
|
+
__profiler.task('Pop Errors');
|
|
348
352
|
const { addedFiles, changedFiles, removedFiles } = await this.cacheService.validate();
|
|
349
353
|
for (const uri of removedFiles) {
|
|
350
|
-
this.
|
|
354
|
+
this.emit('fileDeleted', { uri });
|
|
351
355
|
}
|
|
352
356
|
__profiler.task('Validate Cache');
|
|
353
357
|
if (addedFiles.length > 0) {
|
|
@@ -366,6 +370,7 @@ export class Project {
|
|
|
366
370
|
__profiler.finalize();
|
|
367
371
|
this.emit('ready', {});
|
|
368
372
|
};
|
|
373
|
+
this.#isReady = false;
|
|
369
374
|
this.#readyPromise = ready();
|
|
370
375
|
}
|
|
371
376
|
/**
|
|
@@ -393,6 +398,8 @@ export class Project {
|
|
|
393
398
|
async restart() {
|
|
394
399
|
try {
|
|
395
400
|
await this.#watcher.close();
|
|
401
|
+
this.#bindingInProgressUris.clear();
|
|
402
|
+
this.#symbolUpToDateUris.clear();
|
|
396
403
|
this.setReadyPromise();
|
|
397
404
|
await this.ready();
|
|
398
405
|
}
|
|
@@ -401,10 +408,19 @@ export class Project {
|
|
|
401
408
|
}
|
|
402
409
|
}
|
|
403
410
|
resetCache() {
|
|
404
|
-
|
|
411
|
+
this.logger.info('[Project#resetCache] Initiated...');
|
|
412
|
+
// Clear existing errors.
|
|
413
|
+
for (const uri of Object.keys(this.cacheService.errors)) {
|
|
414
|
+
this.emit('documentErrored', { errors: [], uri });
|
|
415
|
+
}
|
|
416
|
+
// Reset cache.
|
|
417
|
+
const { symbols } = this.cacheService.reset();
|
|
418
|
+
this.symbols = new SymbolUtil(symbols, this.externals.event.EventEmitter);
|
|
419
|
+
this.symbols.buildCache();
|
|
420
|
+
return this.restart();
|
|
405
421
|
}
|
|
406
422
|
normalizeUri(uri) {
|
|
407
|
-
return this.fs.mapFromDisk(
|
|
423
|
+
return this.fs.mapFromDisk(normalizeUri(uri));
|
|
408
424
|
}
|
|
409
425
|
static TextDocumentCacheMaxLength = 268435456;
|
|
410
426
|
#textDocumentCache = new Map();
|
|
@@ -554,7 +570,7 @@ export class Project {
|
|
|
554
570
|
ruleName,
|
|
555
571
|
ruleValue,
|
|
556
572
|
});
|
|
557
|
-
traversePreOrder(node, () => true, () => true, node => {
|
|
573
|
+
traversePreOrder(node, () => true, () => true, (node) => {
|
|
558
574
|
if (nodePredicate(node)) {
|
|
559
575
|
const proxy = StateProxy.create(node);
|
|
560
576
|
linter(proxy, ctx);
|
|
@@ -569,7 +585,9 @@ export class Project {
|
|
|
569
585
|
}
|
|
570
586
|
// @SingletonPromise()
|
|
571
587
|
async ensureBindingStarted(uri) {
|
|
572
|
-
|
|
588
|
+
uri = this.normalizeUri(uri);
|
|
589
|
+
if (this.#symbolUpToDateUris.has(uri) ||
|
|
590
|
+
this.#bindingInProgressUris.has(uri)) {
|
|
573
591
|
return;
|
|
574
592
|
}
|
|
575
593
|
this.#bindingInProgressUris.add(uri);
|
|
@@ -615,8 +633,8 @@ export class Project {
|
|
|
615
633
|
* @throws If there is no `TextDocument` corresponding to the URI.
|
|
616
634
|
*/
|
|
617
635
|
async onDidChange(uri, changes, version) {
|
|
618
|
-
this.#symbolUpToDateUris.delete(uri);
|
|
619
636
|
uri = this.normalizeUri(uri);
|
|
637
|
+
this.#symbolUpToDateUris.delete(uri);
|
|
620
638
|
if (!fileUtil.isFileUri(uri)) {
|
|
621
639
|
return; // We only accept `file:` scheme for client-managed URIs.
|
|
622
640
|
}
|
|
@@ -645,17 +663,21 @@ export class Project {
|
|
|
645
663
|
this.tryClearingCache(uri);
|
|
646
664
|
}
|
|
647
665
|
async ensureClientManagedChecked(uri) {
|
|
666
|
+
uri = this.normalizeUri(uri);
|
|
648
667
|
const result = this.#clientManagedDocAndNodes.get(uri);
|
|
649
|
-
if (result
|
|
668
|
+
if (result) {
|
|
650
669
|
const { doc, node } = result;
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
670
|
+
if (this.#isReady) {
|
|
671
|
+
await this.bind(doc, node);
|
|
672
|
+
await this.check(doc, node);
|
|
673
|
+
this.emit('documentUpdated', result);
|
|
674
|
+
}
|
|
675
|
+
return result;
|
|
655
676
|
}
|
|
656
677
|
return undefined;
|
|
657
678
|
}
|
|
658
679
|
getClientManaged(uri) {
|
|
680
|
+
uri = this.normalizeUri(uri);
|
|
659
681
|
return this.#clientManagedDocAndNodes.get(uri);
|
|
660
682
|
}
|
|
661
683
|
async showCacheRoot() {
|
|
@@ -676,10 +698,14 @@ export class Project {
|
|
|
676
698
|
}
|
|
677
699
|
}
|
|
678
700
|
shouldRemove(uri) {
|
|
679
|
-
return !this.#clientManagedUris.has(uri) &&
|
|
701
|
+
return (!this.#clientManagedUris.has(uri) &&
|
|
702
|
+
!this.#dependencyFiles.has(uri) &&
|
|
703
|
+
!this.#watchedFiles.has(uri));
|
|
680
704
|
}
|
|
681
705
|
isOnlyWatched(uri) {
|
|
682
|
-
return this.#watchedFiles.has(uri) &&
|
|
706
|
+
return (this.#watchedFiles.has(uri) &&
|
|
707
|
+
!this.#clientManagedUris.has(uri) &&
|
|
708
|
+
!this.#dependencyFiles.has(uri));
|
|
683
709
|
}
|
|
684
710
|
}
|
|
685
711
|
__decorate([
|
package/lib/service/Service.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AstNode } from '../node/index.js';
|
|
2
|
-
import { ColorPresentation, completer, traversePreOrder } from '../processor/index.js';
|
|
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
|
-
import { ColorizerContext, CompleterContext, FormatterContext, ProcessorContext, SignatureHelpProviderContext } from './Context.js';
|
|
5
|
+
import { ColorizerContext, CompleterContext, FormatterContext, ProcessorContext, SignatureHelpProviderContext, } from './Context.js';
|
|
6
6
|
import { fileUtil } from './fileUtil.js';
|
|
7
7
|
import { Hover } from './Hover.js';
|
|
8
8
|
import { ProfilerFactory } from './Profiler.js';
|
|
@@ -44,9 +44,11 @@ export class Service {
|
|
|
44
44
|
try {
|
|
45
45
|
this.debug(`Getting color info for '${doc.uri}' # ${doc.version}`);
|
|
46
46
|
const ans = [];
|
|
47
|
-
traversePreOrder(node, _ => true, node => node.color, node => ans.push({
|
|
47
|
+
traversePreOrder(node, (_) => true, (node) => node.color, (node) => ans.push({
|
|
48
48
|
color: Array.isArray(node.color) ? node.color : node.color.value,
|
|
49
|
-
range: Array.isArray(node.color)
|
|
49
|
+
range: Array.isArray(node.color)
|
|
50
|
+
? node.range
|
|
51
|
+
: node.color.range ?? node.range,
|
|
50
52
|
}));
|
|
51
53
|
return ans;
|
|
52
54
|
}
|
|
@@ -63,7 +65,7 @@ export class Service {
|
|
|
63
65
|
const nodeColor = node.color;
|
|
64
66
|
if (nodeColor && !Array.isArray(nodeColor)) {
|
|
65
67
|
const colorRange = nodeColor.range ?? node.range;
|
|
66
|
-
return nodeColor.format.map(format => ColorPresentation.fromColorFormat(format, color, colorRange));
|
|
68
|
+
return nodeColor.format.map((format) => ColorPresentation.fromColorFormat(format, color, colorRange));
|
|
67
69
|
}
|
|
68
70
|
node = node.parent;
|
|
69
71
|
}
|
|
@@ -78,7 +80,11 @@ export class Service {
|
|
|
78
80
|
this.debug(`Getting completion for '${doc.uri}' # ${doc.version} @ ${offset}`);
|
|
79
81
|
const shouldComplete = this.project.meta.shouldComplete(doc.languageId, triggerCharacter);
|
|
80
82
|
if (shouldComplete) {
|
|
81
|
-
return completer.file(node, CompleterContext.create(this.project, {
|
|
83
|
+
return completer.file(node, CompleterContext.create(this.project, {
|
|
84
|
+
doc,
|
|
85
|
+
offset,
|
|
86
|
+
triggerCharacter,
|
|
87
|
+
}));
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
90
|
catch (e) {
|
|
@@ -121,7 +127,8 @@ export class Service {
|
|
|
121
127
|
while (node) {
|
|
122
128
|
const symbol = this.project.symbols.resolveAlias(node.symbol);
|
|
123
129
|
if (symbol) {
|
|
124
|
-
const hover = `\`\`\`typescript\n(${symbol.category}${symbol.subcategory ? `/${symbol.subcategory}` : ''}) ${symbol.identifier}\n\`\`\`` +
|
|
130
|
+
const hover = `\`\`\`typescript\n(${symbol.category}${symbol.subcategory ? `/${symbol.subcategory}` : ''}) ${symbol.identifier}\n\`\`\`` +
|
|
131
|
+
(symbol.desc ? `\n******\n${symbol.desc}` : '');
|
|
125
132
|
return Hover.create(node.range, hover);
|
|
126
133
|
}
|
|
127
134
|
if (node.hover) {
|
|
@@ -154,7 +161,10 @@ export class Service {
|
|
|
154
161
|
getSignatureHelp(node, doc, offset) {
|
|
155
162
|
try {
|
|
156
163
|
this.debug(`Getting signature help for '${doc.uri}' # ${doc.version} @ ${offset}`);
|
|
157
|
-
const ctx = SignatureHelpProviderContext.create(this.project, {
|
|
164
|
+
const ctx = SignatureHelpProviderContext.create(this.project, {
|
|
165
|
+
doc,
|
|
166
|
+
offset,
|
|
167
|
+
});
|
|
158
168
|
for (const provider of this.project.meta.signatureHelpProviders) {
|
|
159
169
|
const result = provider(node, ctx);
|
|
160
170
|
if (result) {
|
|
@@ -184,7 +194,7 @@ export class Service {
|
|
|
184
194
|
for (const usage of searchedUsages) {
|
|
185
195
|
let locs = symbol[usage] ?? [];
|
|
186
196
|
if (currentFileOnly) {
|
|
187
|
-
locs = locs.filter(l => l.uri === doc.uri);
|
|
197
|
+
locs = locs.filter((l) => l.uri === doc.uri);
|
|
188
198
|
}
|
|
189
199
|
rawLocations.push(...locs);
|
|
190
200
|
}
|
package/lib/service/fileUtil.js
CHANGED
|
@@ -43,7 +43,8 @@ export var fileUtil;
|
|
|
43
43
|
}
|
|
44
44
|
fileUtil.ensureEndingSlash = ensureEndingSlash;
|
|
45
45
|
function join(fromUri, toUri) {
|
|
46
|
-
return ensureEndingSlash(fromUri) +
|
|
46
|
+
return (ensureEndingSlash(fromUri) +
|
|
47
|
+
(toUri.startsWith('/') ? toUri.slice(1) : toUri));
|
|
47
48
|
}
|
|
48
49
|
fileUtil.join = join;
|
|
49
50
|
/**
|
package/lib/source/IndexMap.js
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
1
2
|
import type { Location } from './Location.js';
|
|
3
|
+
import { PositionRange } from './PositionRange.js';
|
|
2
4
|
import type { Range } from './Range.js';
|
|
3
|
-
export interface
|
|
5
|
+
export interface LanguageErrorData {
|
|
4
6
|
message: string;
|
|
5
|
-
range: Range;
|
|
6
7
|
severity: ErrorSeverity;
|
|
7
8
|
info?: LanguageErrorInfo;
|
|
8
9
|
}
|
|
9
|
-
export
|
|
10
|
-
|
|
10
|
+
export interface LanguageError extends LanguageErrorData {
|
|
11
|
+
range: Range;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A language error that uses {@link PositionRange} instead of {@link Range} to represent the span of the error.
|
|
15
|
+
*/
|
|
16
|
+
export interface PosRangeLanguageError extends LanguageErrorData {
|
|
17
|
+
posRange: PositionRange;
|
|
11
18
|
}
|
|
19
|
+
export declare const LanguageError: Readonly<{
|
|
20
|
+
create(message: string, range: Range, severity?: ErrorSeverity, info?: LanguageErrorInfo): LanguageError;
|
|
21
|
+
/**
|
|
22
|
+
* @returns A {@link PosRangeLanguageError}.
|
|
23
|
+
*/
|
|
24
|
+
withPosRange(error: LanguageError, doc: TextDocument): PosRangeLanguageError;
|
|
25
|
+
}>;
|
|
12
26
|
export declare const enum ErrorSeverity {
|
|
13
27
|
Hint = 0,
|
|
14
28
|
Information = 1,
|
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { PositionRange } from './PositionRange.js';
|
|
2
|
+
export const LanguageError = Object.freeze({
|
|
3
|
+
create(message, range, severity = 3 /* ErrorSeverity.Error */, info) {
|
|
4
4
|
const ans = { range, message, severity };
|
|
5
5
|
if (info) {
|
|
6
6
|
ans.info = info;
|
|
7
7
|
}
|
|
8
8
|
return ans;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
},
|
|
10
|
+
/**
|
|
11
|
+
* @returns A {@link PosRangeLanguageError}.
|
|
12
|
+
*/
|
|
13
|
+
withPosRange(error, doc) {
|
|
14
|
+
return {
|
|
15
|
+
posRange: PositionRange.from(error.range, doc),
|
|
16
|
+
message: error.message,
|
|
17
|
+
severity: error.severity,
|
|
18
|
+
...(error.info && { info: error.info }),
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
});
|
|
12
22
|
//# sourceMappingURL=LanguageError.js.map
|
package/lib/source/Location.js
CHANGED
|
@@ -6,7 +6,10 @@ export var Location;
|
|
|
6
6
|
return {
|
|
7
7
|
uri: partial.uri ?? '',
|
|
8
8
|
range: Range.get(partial.range ?? { start: 0, end: 0 }),
|
|
9
|
-
posRange: partial.posRange ?? {
|
|
9
|
+
posRange: partial.posRange ?? {
|
|
10
|
+
start: { line: 0, character: 0 },
|
|
11
|
+
end: { line: 0, character: 0 },
|
|
12
|
+
},
|
|
10
13
|
};
|
|
11
14
|
}
|
|
12
15
|
Location.get = get;
|
|
@@ -12,7 +12,7 @@ export declare namespace PositionRange {
|
|
|
12
12
|
/**
|
|
13
13
|
* @returns A `PositionRange` converted from a `RangeLike`.
|
|
14
14
|
*/
|
|
15
|
-
function from(
|
|
15
|
+
function from(rangeLike: RangeLike, doc: TextDocument): PositionRange;
|
|
16
16
|
/**
|
|
17
17
|
* ```typescript
|
|
18
18
|
* {
|
|
@@ -27,11 +27,11 @@ export var PositionRange;
|
|
|
27
27
|
/**
|
|
28
28
|
* @returns A `PositionRange` converted from a `RangeLike`.
|
|
29
29
|
*/
|
|
30
|
-
function from(
|
|
31
|
-
const
|
|
30
|
+
function from(rangeLike, doc) {
|
|
31
|
+
const range = Range.get(rangeLike);
|
|
32
32
|
const ans = {
|
|
33
|
-
start: doc.positionAt(
|
|
34
|
-
end: doc.positionAt(
|
|
33
|
+
start: doc.positionAt(range.start),
|
|
34
|
+
end: doc.positionAt(range.end),
|
|
35
35
|
};
|
|
36
36
|
return ans;
|
|
37
37
|
}
|
package/lib/source/Range.js
CHANGED
|
@@ -42,7 +42,8 @@ export var Range;
|
|
|
42
42
|
}
|
|
43
43
|
Range.span = span;
|
|
44
44
|
function is(obj) {
|
|
45
|
-
return (!!obj &&
|
|
45
|
+
return (!!obj &&
|
|
46
|
+
typeof obj === 'object' &&
|
|
46
47
|
typeof obj.start === 'number' &&
|
|
47
48
|
typeof obj.end === 'number');
|
|
48
49
|
}
|
|
@@ -65,7 +66,8 @@ export var Range;
|
|
|
65
66
|
Range.toString = toString;
|
|
66
67
|
function contains(range, offset, endInclusive = false) {
|
|
67
68
|
range = get(range);
|
|
68
|
-
return range.start <= offset &&
|
|
69
|
+
return (range.start <= offset &&
|
|
70
|
+
(endInclusive ? offset <= range.end : offset < range.end));
|
|
69
71
|
}
|
|
70
72
|
Range.contains = contains;
|
|
71
73
|
function containsRange(a, b, endInclusive = false) {
|
|
@@ -144,7 +146,8 @@ export var Range;
|
|
|
144
146
|
export var RangeContainer;
|
|
145
147
|
(function (RangeContainer) {
|
|
146
148
|
function is(obj) {
|
|
147
|
-
return (!!obj &&
|
|
149
|
+
return (!!obj &&
|
|
150
|
+
typeof obj === 'object' &&
|
|
148
151
|
Range.is(obj.range));
|
|
149
152
|
}
|
|
150
153
|
RangeContainer.is = is;
|
package/lib/source/Source.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export declare class ReadonlySource {
|
|
|
43
43
|
tryPeekAfterWhitespace(expectedValue: string): boolean;
|
|
44
44
|
peekUntil(...terminators: string[]): string;
|
|
45
45
|
peekLine(): string;
|
|
46
|
+
peekRemaining(): string;
|
|
47
|
+
matchPattern(regex: RegExp): boolean;
|
|
46
48
|
hasNonSpaceAheadInLine(): boolean;
|
|
47
49
|
slice(start: number, end?: number): string;
|
|
48
50
|
slice(rangeLike: Range | RangeContainer): string;
|
package/lib/source/Source.js
CHANGED
|
@@ -70,6 +70,12 @@ export class ReadonlySource {
|
|
|
70
70
|
peekLine() {
|
|
71
71
|
return this.peekUntil(CR, LF);
|
|
72
72
|
}
|
|
73
|
+
peekRemaining() {
|
|
74
|
+
return this.string.slice(this.innerCursor);
|
|
75
|
+
}
|
|
76
|
+
matchPattern(regex) {
|
|
77
|
+
return regex.test(this.peekRemaining());
|
|
78
|
+
}
|
|
73
79
|
hasNonSpaceAheadInLine() {
|
|
74
80
|
for (let cursor = this.innerCursor; cursor < this.string.length; cursor++) {
|
|
75
81
|
const c = this.string.charAt(cursor);
|
|
@@ -85,7 +91,9 @@ export class ReadonlySource {
|
|
|
85
91
|
slice(param0, end) {
|
|
86
92
|
if (typeof param0 === 'number') {
|
|
87
93
|
const innerStart = IndexMap.toInnerOffset(this.indexMap, param0);
|
|
88
|
-
const innerEnd = end !== undefined
|
|
94
|
+
const innerEnd = end !== undefined
|
|
95
|
+
? IndexMap.toInnerOffset(this.indexMap, end)
|
|
96
|
+
: undefined;
|
|
89
97
|
return this.string.slice(innerStart, innerEnd);
|
|
90
98
|
}
|
|
91
99
|
const range = IndexMap.toInnerRange(this.indexMap, Range.get(param0));
|