@spyglassmc/core 0.1.1 → 0.3.0

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.
Files changed (206) hide show
  1. package/README.md +7 -0
  2. package/lib/browser.d.ts +2 -0
  3. package/lib/browser.js +2 -0
  4. package/lib/common/Dev.d.ts +11 -0
  5. package/lib/common/Dev.js +90 -0
  6. package/lib/{service → common}/Logger.d.ts +0 -0
  7. package/lib/{service → common}/Logger.js +2 -5
  8. package/lib/common/Operations.d.ts +12 -0
  9. package/lib/common/Operations.js +33 -0
  10. package/lib/common/ReadonlyProxy.d.ts +9 -0
  11. package/lib/common/ReadonlyProxy.js +23 -0
  12. package/lib/common/StateProxy.d.ts +35 -0
  13. package/lib/common/StateProxy.js +69 -0
  14. package/lib/common/TwoWayMap.d.ts +21 -0
  15. package/lib/common/TwoWayMap.js +69 -0
  16. package/lib/common/externals/BrowserExternals.d.ts +3 -0
  17. package/lib/common/externals/BrowserExternals.js +191 -0
  18. package/lib/common/externals/NodeJsExternals.d.ts +3 -0
  19. package/lib/common/externals/NodeJsExternals.js +152 -0
  20. package/lib/common/externals/downloader.d.ts +31 -0
  21. package/lib/common/externals/downloader.js +32 -0
  22. package/lib/common/externals/index.d.ts +96 -0
  23. package/lib/common/externals/index.js +2 -0
  24. package/lib/common/index.d.ts +8 -1
  25. package/lib/common/index.js +8 -13
  26. package/lib/common/util.d.ts +50 -39
  27. package/lib/common/util.js +73 -122
  28. package/lib/index.d.ts +7 -7
  29. package/lib/index.js +7 -19
  30. package/lib/node/AstNode.d.ts +12 -11
  31. package/lib/node/AstNode.js +10 -16
  32. package/lib/node/BooleanNode.d.ts +2 -2
  33. package/lib/node/BooleanNode.js +4 -7
  34. package/lib/node/CommentNode.d.ts +6 -5
  35. package/lib/node/CommentNode.js +4 -9
  36. package/lib/node/ErrorNode.d.ts +1 -1
  37. package/lib/node/ErrorNode.js +2 -5
  38. package/lib/node/FileNode.d.ts +8 -4
  39. package/lib/node/FileNode.js +3 -6
  40. package/lib/node/FloatNode.d.ts +3 -3
  41. package/lib/node/FloatNode.js +4 -7
  42. package/lib/node/IntegerNode.d.ts +3 -3
  43. package/lib/node/IntegerNode.js +4 -7
  44. package/lib/node/ListNode.d.ts +2 -2
  45. package/lib/node/ListNode.js +2 -5
  46. package/lib/node/LiteralNode.d.ts +5 -5
  47. package/lib/node/LiteralNode.js +5 -8
  48. package/lib/node/LongNode.d.ts +3 -3
  49. package/lib/node/LongNode.js +4 -7
  50. package/lib/node/RecordNode.d.ts +2 -2
  51. package/lib/node/RecordNode.js +2 -5
  52. package/lib/node/ResourceLocationNode.d.ts +8 -10
  53. package/lib/node/ResourceLocationNode.js +9 -12
  54. package/lib/node/Sequence.d.ts +4 -3
  55. package/lib/node/Sequence.js +4 -6
  56. package/lib/node/StringNode.d.ts +5 -5
  57. package/lib/node/StringNode.js +9 -12
  58. package/lib/node/SymbolNode.d.ts +5 -5
  59. package/lib/node/SymbolNode.js +5 -8
  60. package/lib/node/index.d.ts +15 -15
  61. package/lib/node/index.js +15 -27
  62. package/lib/nodejs.d.ts +2 -0
  63. package/lib/nodejs.js +2 -0
  64. package/lib/parser/Parser.d.ts +3 -3
  65. package/lib/parser/Parser.js +1 -4
  66. package/lib/parser/boolean.d.ts +2 -2
  67. package/lib/parser/boolean.js +3 -6
  68. package/lib/parser/comment.d.ts +2 -2
  69. package/lib/parser/comment.js +5 -9
  70. package/lib/parser/empty.d.ts +1 -1
  71. package/lib/parser/empty.js +1 -5
  72. package/lib/parser/error.d.ts +2 -2
  73. package/lib/parser/error.js +5 -9
  74. package/lib/parser/file.d.ts +3 -3
  75. package/lib/parser/file.js +9 -13
  76. package/lib/parser/float.d.ts +4 -4
  77. package/lib/parser/float.js +12 -16
  78. package/lib/parser/index.d.ts +16 -16
  79. package/lib/parser/index.js +16 -34
  80. package/lib/parser/integer.d.ts +4 -4
  81. package/lib/parser/integer.js +10 -14
  82. package/lib/parser/list.d.ts +2 -2
  83. package/lib/parser/list.js +15 -19
  84. package/lib/parser/literal.d.ts +2 -2
  85. package/lib/parser/literal.js +5 -9
  86. package/lib/parser/long.d.ts +4 -4
  87. package/lib/parser/long.js +10 -14
  88. package/lib/parser/record.d.ts +3 -3
  89. package/lib/parser/record.js +20 -24
  90. package/lib/parser/resourceLocation.d.ts +2 -2
  91. package/lib/parser/resourceLocation.js +12 -24
  92. package/lib/parser/string.d.ts +7 -7
  93. package/lib/parser/string.js +40 -44
  94. package/lib/parser/symbol.d.ts +3 -3
  95. package/lib/parser/symbol.js +4 -14
  96. package/lib/parser/util.d.ts +30 -12
  97. package/lib/parser/util.js +78 -65
  98. package/lib/processor/ColorInfoProvider.d.ts +1 -1
  99. package/lib/processor/ColorInfoProvider.js +6 -9
  100. package/lib/processor/InlayHintProvider.d.ts +4 -3
  101. package/lib/processor/InlayHintProvider.js +1 -2
  102. package/lib/processor/SignatureHelpProvider.d.ts +4 -3
  103. package/lib/processor/SignatureHelpProvider.js +1 -2
  104. package/lib/processor/binder/Binder.d.ts +26 -0
  105. package/lib/processor/binder/Binder.js +18 -0
  106. package/lib/processor/binder/builtin.d.ts +27 -0
  107. package/lib/processor/binder/builtin.js +116 -0
  108. package/lib/processor/binder/index.d.ts +3 -0
  109. package/lib/processor/binder/index.js +3 -0
  110. package/lib/processor/checker/Checker.d.ts +2 -2
  111. package/lib/processor/checker/Checker.js +1 -5
  112. package/lib/processor/checker/builtin.d.ts +4 -4
  113. package/lib/processor/checker/builtin.js +22 -33
  114. package/lib/processor/checker/index.d.ts +2 -2
  115. package/lib/processor/checker/index.js +2 -27
  116. package/lib/processor/colorizer/Colorizer.d.ts +6 -5
  117. package/lib/processor/colorizer/Colorizer.js +8 -11
  118. package/lib/processor/colorizer/builtin.d.ts +3 -3
  119. package/lib/processor/colorizer/builtin.js +33 -46
  120. package/lib/processor/colorizer/index.d.ts +2 -2
  121. package/lib/processor/colorizer/index.js +2 -27
  122. package/lib/processor/completer/Completer.d.ts +6 -5
  123. package/lib/processor/completer/Completer.js +14 -33
  124. package/lib/processor/completer/builtin.d.ts +10 -9
  125. package/lib/processor/completer/builtin.js +59 -75
  126. package/lib/processor/completer/index.d.ts +2 -2
  127. package/lib/processor/completer/index.js +2 -27
  128. package/lib/processor/formatter/Formatter.d.ts +4 -3
  129. package/lib/processor/formatter/Formatter.js +2 -7
  130. package/lib/processor/formatter/builtin.d.ts +3 -3
  131. package/lib/processor/formatter/builtin.js +22 -36
  132. package/lib/processor/formatter/index.d.ts +2 -2
  133. package/lib/processor/formatter/index.js +2 -27
  134. package/lib/processor/index.d.ts +10 -9
  135. package/lib/processor/index.js +10 -21
  136. package/lib/processor/linter/Linter.d.ts +4 -3
  137. package/lib/processor/linter/Linter.js +1 -2
  138. package/lib/processor/linter/builtin/undeclaredSymbol.d.ts +2 -2
  139. package/lib/processor/linter/builtin/undeclaredSymbol.js +23 -27
  140. package/lib/processor/linter/builtin.d.ts +4 -3
  141. package/lib/processor/linter/builtin.js +19 -26
  142. package/lib/processor/linter/index.d.ts +2 -2
  143. package/lib/processor/linter/index.js +2 -27
  144. package/lib/processor/util.d.ts +4 -14
  145. package/lib/processor/util.js +1 -16
  146. package/lib/service/CacheService.d.ts +8 -6
  147. package/lib/service/CacheService.js +35 -56
  148. package/lib/service/Config.d.ts +17 -16
  149. package/lib/service/Config.js +56 -51
  150. package/lib/service/Context.d.ts +24 -21
  151. package/lib/service/Context.js +40 -36
  152. package/lib/service/Dependency.js +2 -5
  153. package/lib/service/Downloader.d.ts +9 -39
  154. package/lib/service/Downloader.js +37 -106
  155. package/lib/service/ErrorReporter.d.ts +2 -2
  156. package/lib/service/ErrorReporter.js +11 -15
  157. package/lib/service/FileService.d.ts +40 -14
  158. package/lib/service/FileService.js +107 -81
  159. package/lib/service/Hover.d.ts +2 -2
  160. package/lib/service/Hover.js +4 -7
  161. package/lib/service/MetaRegistry.d.ts +17 -12
  162. package/lib/service/MetaRegistry.js +81 -73
  163. package/lib/service/Profiler.d.ts +3 -2
  164. package/lib/service/Profiler.js +81 -45
  165. package/lib/service/Project.d.ts +101 -73
  166. package/lib/service/Project.js +438 -367
  167. package/lib/service/Service.d.ts +19 -29
  168. package/lib/service/Service.js +57 -53
  169. package/lib/service/SymbolLocations.d.ts +3 -3
  170. package/lib/service/SymbolLocations.js +4 -7
  171. package/lib/service/SymbolRegistrar.d.ts +1 -1
  172. package/lib/service/SymbolRegistrar.js +1 -2
  173. package/lib/service/UriProcessor.d.ts +5 -0
  174. package/lib/service/UriProcessor.js +2 -0
  175. package/lib/service/fileUtil.d.ts +21 -41
  176. package/lib/service/fileUtil.js +59 -129
  177. package/lib/service/index.d.ts +16 -17
  178. package/lib/service/index.js +16 -31
  179. package/lib/source/IndexMap.d.ts +1 -1
  180. package/lib/source/IndexMap.js +7 -10
  181. package/lib/source/LanguageError.d.ts +2 -2
  182. package/lib/source/LanguageError.js +3 -6
  183. package/lib/source/Location.d.ts +3 -3
  184. package/lib/source/Location.js +6 -9
  185. package/lib/source/Offset.d.ts +1 -1
  186. package/lib/source/Offset.js +4 -7
  187. package/lib/source/Position.js +2 -5
  188. package/lib/source/PositionRange.d.ts +2 -2
  189. package/lib/source/PositionRange.js +14 -17
  190. package/lib/source/Range.d.ts +1 -1
  191. package/lib/source/Range.js +7 -10
  192. package/lib/source/Source.d.ts +9 -4
  193. package/lib/source/Source.js +58 -31
  194. package/lib/source/index.d.ts +8 -8
  195. package/lib/source/index.js +8 -20
  196. package/lib/symbol/Symbol.d.ts +15 -14
  197. package/lib/symbol/Symbol.js +53 -68
  198. package/lib/symbol/SymbolUtil.d.ts +30 -39
  199. package/lib/symbol/SymbolUtil.js +189 -168
  200. package/lib/symbol/index.d.ts +2 -3
  201. package/lib/symbol/index.js +2 -15
  202. package/package.json +7 -4
  203. package/lib/service/Operations.d.ts +0 -8
  204. package/lib/service/Operations.js +0 -26
  205. package/lib/symbol/UriBinder.d.ts +0 -3
  206. package/lib/symbol/UriBinder.js +0 -3
@@ -1,76 +1,112 @@
1
- "use strict";
2
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
- if (kind === "m") throw new TypeError("Private method is not writable");
4
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
- };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _ProfilerImpl_finalized, _ProfilerImpl_startTime, _ProfilerImpl_lastTime, _ProfilerImpl_tasks, _ProfilerImpl_longestTaskNameLength, _ProfilerFactory_enabledProfilers;
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.ProfilerFactory = void 0;
16
- const perf_hooks_1 = require("perf_hooks");
17
- const Logger_1 = require("./Logger");
1
+ import { Dev, Logger } from '../common/index.js';
2
+ class TopNImpl {
3
+ id;
4
+ logger;
5
+ n;
6
+ #finalized = false;
7
+ #startTime;
8
+ #lastTime;
9
+ #taskCount = 0;
10
+ #topTasks = [];
11
+ #minTime = Infinity;
12
+ #maxTime = 0;
13
+ constructor(id, logger, n) {
14
+ this.id = id;
15
+ this.logger = logger;
16
+ this.n = n;
17
+ this.#startTime = this.#lastTime = performance.now();
18
+ }
19
+ task(name) {
20
+ if (this.#finalized) {
21
+ throw new Error('The profiler has already been finalized');
22
+ }
23
+ this.#taskCount++;
24
+ const time = performance.now();
25
+ const duration = time - this.#lastTime;
26
+ this.#lastTime = time;
27
+ this.#minTime = Math.min(this.#minTime, duration);
28
+ this.#maxTime = Math.max(this.#maxTime, duration);
29
+ this.#topTasks.push([name, duration]);
30
+ this.#topTasks.sort((a, b) => b[1] - a[1]);
31
+ if (this.#topTasks.length > this.n) {
32
+ this.#topTasks = this.#topTasks.slice(0, -1);
33
+ }
34
+ return this;
35
+ }
36
+ finalize() {
37
+ this.#finalized = true;
38
+ const longestTaskNameLength = this.#topTasks.reduce((length, [name]) => Math.max(length, name.length), 0);
39
+ const totalDuration = this.#lastTime - this.#startTime;
40
+ this.logger.info(`[Profiler: ${this.id}] == Summary ==`);
41
+ this.logger.info(`[Profiler: ${this.id}] Total tasks: ${this.#taskCount} done in ${totalDuration} ms`);
42
+ this.logger.info(`[Profiler: ${this.id}] Min/Avg/Max: ${this.#minTime} / ${totalDuration / this.#taskCount} / ${this.#maxTime} ms`);
43
+ this.logger.info(`[Profiler: ${this.id}] Top ${Math.min(this.n, this.#topTasks.length)} task(s):`);
44
+ for (const [name, time] of this.#topTasks) {
45
+ this.logger.info(`[Profiler: ${this.id}] ${name}${' '.repeat(longestTaskNameLength - name.length)} - ${time} ms (${time / totalDuration * 100}%)`);
46
+ }
47
+ }
48
+ }
18
49
  const TotalTaskName = 'Total';
19
- class ProfilerImpl {
50
+ class TotalImpl {
51
+ id;
52
+ logger;
53
+ #finalized = false;
54
+ #startTime;
55
+ #lastTime;
56
+ #tasks = [];
57
+ #longestTaskNameLength = 0;
20
58
  constructor(id, logger) {
21
59
  this.id = id;
22
60
  this.logger = logger;
23
- _ProfilerImpl_finalized.set(this, false);
24
- _ProfilerImpl_startTime.set(this, void 0);
25
- _ProfilerImpl_lastTime.set(this, void 0);
26
- _ProfilerImpl_tasks.set(this, []);
27
- _ProfilerImpl_longestTaskNameLength.set(this, 0);
28
- __classPrivateFieldSet(this, _ProfilerImpl_startTime, __classPrivateFieldSet(this, _ProfilerImpl_lastTime, perf_hooks_1.performance.now(), "f"), "f");
61
+ this.#startTime = this.#lastTime = performance.now();
29
62
  }
30
63
  task(name) {
31
- if (__classPrivateFieldGet(this, _ProfilerImpl_finalized, "f")) {
64
+ if (this.#finalized) {
32
65
  throw new Error('The profiler is finalized.');
33
66
  }
34
- const time = perf_hooks_1.performance.now();
35
- __classPrivateFieldGet(this, _ProfilerImpl_tasks, "f").push([name, time - __classPrivateFieldGet(this, _ProfilerImpl_lastTime, "f")]);
36
- __classPrivateFieldSet(this, _ProfilerImpl_lastTime, time, "f");
37
- __classPrivateFieldSet(this, _ProfilerImpl_longestTaskNameLength, Math.max(__classPrivateFieldGet(this, _ProfilerImpl_longestTaskNameLength, "f"), name.length), "f");
38
- this.logger.info(`[Profiler: ${this.id}] Done: ${name}`);
67
+ const time = performance.now();
68
+ const duration = time - this.#lastTime;
69
+ this.#lastTime = time;
70
+ this.#tasks.push([name, duration]);
71
+ this.#longestTaskNameLength = Math.max(this.#longestTaskNameLength, name.length);
72
+ this.logger.info(`[Profiler: ${this.id}] Done: ${name} in ${duration} ms`);
39
73
  return this;
40
74
  }
41
75
  finalize() {
42
- __classPrivateFieldSet(this, _ProfilerImpl_finalized, true, "f");
43
- __classPrivateFieldGet(this, _ProfilerImpl_tasks, "f").push([TotalTaskName, __classPrivateFieldGet(this, _ProfilerImpl_lastTime, "f") - __classPrivateFieldGet(this, _ProfilerImpl_startTime, "f")]);
44
- __classPrivateFieldSet(this, _ProfilerImpl_longestTaskNameLength, Math.max(__classPrivateFieldGet(this, _ProfilerImpl_longestTaskNameLength, "f"), TotalTaskName.length), "f");
76
+ this.#finalized = true;
77
+ this.#tasks.push([TotalTaskName, this.#lastTime - this.#startTime]);
78
+ this.#longestTaskNameLength = Math.max(this.#longestTaskNameLength, TotalTaskName.length);
45
79
  this.logger.info(`[Profiler: ${this.id}] == Summary ==`);
46
- for (const [name, time] of __classPrivateFieldGet(this, _ProfilerImpl_tasks, "f")) {
47
- this.logger.info(`[Profiler: ${this.id}] ${name}${' '.repeat(__classPrivateFieldGet(this, _ProfilerImpl_longestTaskNameLength, "f") - name.length)} - ${time} ms`);
80
+ for (const [name, time] of this.#tasks) {
81
+ this.logger.info(`[Profiler: ${this.id}] ${name}${' '.repeat(this.#longestTaskNameLength - name.length)} - ${time} ms`);
48
82
  }
49
83
  }
50
84
  }
51
- _ProfilerImpl_finalized = new WeakMap(), _ProfilerImpl_startTime = new WeakMap(), _ProfilerImpl_lastTime = new WeakMap(), _ProfilerImpl_tasks = new WeakMap(), _ProfilerImpl_longestTaskNameLength = new WeakMap();
52
85
  class NoopImpl {
53
86
  task() { return this; }
54
87
  finalize() { }
55
88
  }
56
- class ProfilerFactory {
89
+ export class ProfilerFactory {
90
+ logger;
91
+ #enabledProfilers;
57
92
  constructor(logger, enabledProfilers) {
58
93
  this.logger = logger;
59
- _ProfilerFactory_enabledProfilers.set(this, void 0);
60
- __classPrivateFieldSet(this, _ProfilerFactory_enabledProfilers, new Set(enabledProfilers), "f");
94
+ this.#enabledProfilers = new Set(enabledProfilers);
61
95
  }
62
- get(id) {
63
- if (__classPrivateFieldGet(this, _ProfilerFactory_enabledProfilers, "f").has(id)) {
64
- return new ProfilerImpl(id, this.logger);
96
+ get(id, style = 'total', n) {
97
+ if (this.#enabledProfilers.has(id)) {
98
+ switch (style) {
99
+ case 'top-n': return new TopNImpl(id, this.logger, n);
100
+ case 'total': return new TotalImpl(id, this.logger);
101
+ default: return Dev.assertNever(style);
102
+ }
65
103
  }
66
104
  else {
67
105
  return new NoopImpl();
68
106
  }
69
107
  }
70
108
  static noop() {
71
- return new ProfilerFactory(Logger_1.Logger.noop(), []);
109
+ return new ProfilerFactory(Logger.noop(), []);
72
110
  }
73
111
  }
74
- exports.ProfilerFactory = ProfilerFactory;
75
- _ProfilerFactory_enabledProfilers = new WeakMap();
76
112
  //# sourceMappingURL=Profiler.js.map
@@ -1,32 +1,35 @@
1
- /// <reference types="node" />
2
- import EventEmitter from 'events';
3
1
  import type { TextDocumentContentChangeEvent } from 'vscode-languageserver-textdocument';
4
2
  import { TextDocument } from 'vscode-languageserver-textdocument';
5
- import type { AstNode } from '../node';
6
- import { FileNode } from '../node';
7
- import type { LanguageError } from '../source';
8
- import { SymbolUtil } from '../symbol';
9
- import { CacheService } from './CacheService';
10
- import type { Config } from './Config';
11
- import { Downloader } from './Downloader';
12
- import { FileService } from './FileService';
13
- import type { RootUriString } from './fileUtil';
14
- import { Logger } from './Logger';
15
- import { MetaRegistry } from './MetaRegistry';
16
- import { ProfilerFactory } from './Profiler';
17
- export declare type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'logger' | 'meta' | 'projectRoot'>;
18
- export declare type ProjectInitializer = (this: void, ctx: ProjectInitializerContext) => PromiseLike<Record<string, string> | void> | Record<string, string> | void;
19
- interface Options {
20
- cacheRoot: string;
3
+ import type { ExternalEventEmitter, Externals } from '../common/index.js';
4
+ import { Logger } from '../common/index.js';
5
+ import type { AstNode } from '../node/index.js';
6
+ import { FileNode } from '../node/index.js';
7
+ import type { LanguageError } from '../source/index.js';
8
+ import { SymbolUtil } from '../symbol/index.js';
9
+ import { CacheService } from './CacheService.js';
10
+ import type { Config } from './Config.js';
11
+ import { Downloader } from './Downloader.js';
12
+ import { FileService } from './FileService.js';
13
+ import type { RootUriString } from './fileUtil.js';
14
+ import { MetaRegistry } from './MetaRegistry.js';
15
+ import { ProfilerFactory } from './Profiler.js';
16
+ export declare type ProjectInitializerContext = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'externals' | 'logger' | 'meta' | 'projectRoot'>;
17
+ export declare type SyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => Record<string, string> | void;
18
+ export declare type AsyncProjectInitializer = (this: void, ctx: ProjectInitializerContext) => PromiseLike<Record<string, string> | void>;
19
+ export declare type ProjectInitializer = SyncProjectInitializer | AsyncProjectInitializer;
20
+ export interface ProjectOptions {
21
+ cacheRoot: RootUriString;
22
+ defaultConfig?: Config;
21
23
  downloader?: Downloader;
24
+ externals: Externals;
22
25
  fs?: FileService;
23
26
  initializers?: readonly ProjectInitializer[];
24
27
  logger?: Logger;
25
28
  profilers?: ProfilerFactory;
26
29
  /**
27
- * A file path to the root of this project.
30
+ * A file URI to the root of this project.
28
31
  */
29
- projectPath: string;
32
+ projectRoot: RootUriString;
30
33
  symbols?: SymbolUtil;
31
34
  }
32
35
  export interface DocAndNode {
@@ -50,48 +53,56 @@ interface SymbolRegistrarEvent {
50
53
  id: string;
51
54
  checksum: string | undefined;
52
55
  }
53
- export declare type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureParsedAndChecked' | 'fs' | 'get' | 'logger' | 'meta' | 'profilers' | 'projectRoot' | 'roots' | 'symbols' | 'ctx'>;
54
- export declare namespace ProjectData {
55
- function mock(data?: Partial<ProjectData>): ProjectData;
56
- }
57
- export interface Project extends EventEmitter {
58
- on(event: 'documentErrorred', callbackFn: (data: DocumentErrorEvent) => void): this;
59
- on(event: 'documentUpdated', callbackFn: (data: DocumentEvent) => void): this;
60
- on(event: 'documentRemoved', callbackFn: (data: FileEvent) => void): this;
61
- on(event: `file${'Created' | 'Modified' | 'Deleted'}`, callbackFn: (data: FileEvent) => void): this;
62
- on(event: 'ready', callbackFn: (data: EmptyEvent) => void): this;
63
- on(event: 'rootsUpdated', callbackFn: (data: RootsEvent) => void): this;
64
- on(event: 'symbolRegistrarExecuted', callbackFn: (data: SymbolRegistrarEvent) => void): this;
65
- once(event: 'documentErrorred', callbackFn: (data: DocumentErrorEvent) => void): this;
66
- once(event: 'documentUpdated', callbackFn: (data: DocumentEvent) => void): this;
67
- once(event: 'documentRemoved', callbackFn: (data: FileEvent) => void): this;
68
- once(event: `file${'Created' | 'Modified' | 'Deleted'}`, callbackFn: (data: FileEvent) => void): this;
69
- once(event: 'ready', callbackFn: (data: EmptyEvent) => void): this;
70
- once(event: 'rootsUpdated', callbackFn: (data: RootsEvent) => void): this;
71
- once(event: 'symbolRegistrarExecuted', callbackFn: (data: SymbolRegistrarEvent) => void): this;
72
- emit(event: 'documentErrorred', data: DocumentErrorEvent): boolean;
73
- emit(event: 'documentUpdated', data: DocumentEvent): boolean;
74
- emit(event: 'documentRemoved', data: FileEvent): boolean;
75
- emit(event: `file${'Created' | 'Modified' | 'Deleted'}`, data: FileEvent): boolean;
76
- emit(event: 'ready', data: EmptyEvent): boolean;
77
- emit(event: 'rootsUpdated', data: RootsEvent): boolean;
78
- emit(event: 'symbolRegistrarExecuted', data: SymbolRegistrarEvent): boolean;
79
- }
56
+ export declare type ProjectData = Pick<Project, 'cacheRoot' | 'config' | 'downloader' | 'ensureBindingStarted' | 'externals' | 'fs' | 'logger' | 'meta' | 'profilers' | 'projectRoot' | 'roots' | 'symbols' | 'ctx'>;
80
57
  /**
81
58
  * Manage all tracked documents and errors.
59
+ *
60
+ * The four stages of processing a document:
61
+ * 1. `read` - read the file from the external file system as a `TextDocument`.
62
+ * 2. `parse` - Parse the `TextDocument` into an `AstNode`.
63
+ * 3. `bind` - Bind the `AstNode` and populate both the global symbol table and the local symbol tables on the nodes.
64
+ * 4. `check` (includes `lint`) - Check the `AstNode` with information from the symbol tables.
65
+ *
66
+ * **Caching**
67
+ *
68
+ * The global symbol table along with a list of file URIs and checksums is cached in memory and is periodically saved to disk.
69
+ *
70
+ * The `TextDocument`s and file `AstNode`s (including their local symbol tables) managed by the client are stored in memory until the client sends a `didClose` notification.
71
+ *
72
+ * Some `TextDocument`s may be cached to avoid excessive reading from the file system.
73
+ *
74
+ * **INIT and READY**
75
+ *
76
+ * When a new instance of the {@link Project} class is constructed, its INIT and READY processes are immediately started in serial.
77
+ *
78
+ * During the INIT process of the project, the config and language feature initialization are processed.
79
+ * The Promise returned by the {@link init} function resolves when the INIT process is complete.
80
+ *
81
+ * During the READY process of the project, the whole project is analyzed mainly to populate the global symbol table.
82
+ * The Promise returned by the {@link ready} function resolves when the READY process is complete.
83
+ *
84
+ * The following generally happens during the READY process:
85
+ * 1. A list of file URIs under the project is obtained.
86
+ * 2. The global symbol cache, if available, is loaded and validated against the know list of files.
87
+ * A list of files that need to be (re)processed is returned in this step.
88
+ * 3. For each files in the new list, the file is read, parsed, bound, and checked.
89
+ *
90
+ * **EDITING**
91
+ *
92
+ * 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.
82
93
  */
83
- export declare class Project extends EventEmitter {
94
+ export declare class Project implements ExternalEventEmitter {
84
95
  #private;
85
96
  private static readonly RootSuffix;
86
97
  readonly cacheService: CacheService;
87
98
  get isReady(): boolean;
88
99
  config: Config;
89
100
  readonly downloader: Downloader;
101
+ readonly externals: Externals;
90
102
  readonly fs: FileService;
91
103
  readonly logger: Logger;
92
104
  readonly meta: MetaRegistry;
93
105
  readonly profilers: ProfilerFactory;
94
- readonly projectPath: string;
95
106
  readonly projectRoot: RootUriString;
96
107
  symbols: SymbolUtil;
97
108
  /**
@@ -109,10 +120,31 @@ export declare class Project extends EventEmitter {
109
120
  */
110
121
  get ctx(): Record<string, string>;
111
122
  /**
112
- * File path to a directory where all cache files of Spyglass should be stored.
123
+ * File URI to a directory where all cache files of Spyglass should be stored.
113
124
  */
114
- get cacheRoot(): string;
125
+ get cacheRoot(): RootUriString;
115
126
  private updateRoots;
127
+ on(event: 'documentErrorred', callbackFn: (data: DocumentErrorEvent) => void): this;
128
+ on(event: 'documentUpdated', callbackFn: (data: DocumentEvent) => void): this;
129
+ on(event: 'documentRemoved', callbackFn: (data: FileEvent) => void): this;
130
+ on(event: `file${'Created' | 'Modified' | 'Deleted'}`, callbackFn: (data: FileEvent) => void): this;
131
+ on(event: 'ready', callbackFn: (data: EmptyEvent) => void): this;
132
+ on(event: 'rootsUpdated', callbackFn: (data: RootsEvent) => void): this;
133
+ on(event: 'symbolRegistrarExecuted', callbackFn: (data: SymbolRegistrarEvent) => void): this;
134
+ once(event: 'documentErrorred', callbackFn: (data: DocumentErrorEvent) => void): this;
135
+ once(event: 'documentUpdated', callbackFn: (data: DocumentEvent) => void): this;
136
+ once(event: 'documentRemoved', callbackFn: (data: FileEvent) => void): this;
137
+ once(event: `file${'Created' | 'Modified' | 'Deleted'}`, callbackFn: (data: FileEvent) => void): this;
138
+ once(event: 'ready', callbackFn: (data: EmptyEvent) => void): this;
139
+ once(event: 'rootsUpdated', callbackFn: (data: RootsEvent) => void): this;
140
+ once(event: 'symbolRegistrarExecuted', callbackFn: (data: SymbolRegistrarEvent) => void): this;
141
+ emit(event: 'documentErrorred', data: DocumentErrorEvent): boolean;
142
+ emit(event: 'documentUpdated', data: DocumentEvent): boolean;
143
+ emit(event: 'documentRemoved', data: FileEvent): boolean;
144
+ emit(event: `file${'Created' | 'Modified' | 'Deleted'}`, data: FileEvent): boolean;
145
+ emit(event: 'ready', data: EmptyEvent): boolean;
146
+ emit(event: 'rootsUpdated', data: RootsEvent): boolean;
147
+ emit(event: 'symbolRegistrarExecuted', data: SymbolRegistrarEvent): boolean;
116
148
  /**
117
149
  * Get all files that are tracked and supported.
118
150
  *
@@ -120,10 +152,16 @@ export declare class Project extends EventEmitter {
120
152
  * are not loaded into the memory.
121
153
  */
122
154
  getTrackedFiles(): string[];
123
- constructor({ cacheRoot, downloader, fs, initializers, logger, profilers, projectPath, }: Options);
155
+ constructor({ cacheRoot, defaultConfig, downloader, externals, fs, initializers, logger, profilers, projectRoot, }: ProjectOptions);
124
156
  private setInitPromise;
125
157
  private setReadyPromise;
158
+ /**
159
+ * Load the config file and initialize parsers and processors.
160
+ */
126
161
  init(): Promise<this>;
162
+ /**
163
+ * Finish the initial run of parsing, binding, and checking the entire project.
164
+ */
127
165
  ready(): Promise<this>;
128
166
  /**
129
167
  * Behavior of the `Project` instance is undefined after this function has settled.
@@ -131,41 +169,31 @@ export declare class Project extends EventEmitter {
131
169
  close(): Promise<void>;
132
170
  restart(): Promise<void>;
133
171
  resetCache(): void;
134
- /**
135
- * @returns The language ID of the file, or the file extension without the leading dot.
136
- */
137
- private getLanguageID;
138
- /**
139
- * @returns The cached `TextDocument` and `AstNode` for the URI, or `undefined` when such data isn't available in cache.
140
- */
141
- get(uri: string): DocAndNode | undefined;
142
- /**
143
- * @throws FS-related errors
144
- */
145
- ensureParsed(uri: string): Promise<DocAndNode | undefined>;
146
- private parseAndCache;
172
+ normalizeUri(uri: string): string;
173
+ private static readonly TextDocumentCacheMaxLength;
174
+ private removeCachedTextDocument;
175
+ private read;
147
176
  private parse;
148
- private cache;
177
+ private bind;
149
178
  private check;
150
- ensureChecked(doc: TextDocument, node: FileNode<AstNode>): Promise<void>;
151
179
  private lint;
152
- ensureLinted(doc: TextDocument, node: FileNode<AstNode>): void;
153
- ensureParsedAndChecked(uri: string): Promise<DocAndNode | undefined>;
154
- ensureParsedAndCheckedOnlyWhenReady(uri: string): Promise<DocAndNode | undefined>;
155
- private bind;
180
+ ensureBindingStarted(uri: string): Promise<void>;
181
+ private bindUri;
156
182
  /**
157
183
  * Notify that a new document was opened in the editor.
158
184
  */
159
- onDidOpen(uri: string, languageID: string, version: number, content: string): void;
185
+ onDidOpen(uri: string, languageID: string, version: number, content: string): Promise<void>;
160
186
  /**
161
187
  * Notify that an existing document was changed in the editor.
162
188
  * @throws If there is no `TextDocument` corresponding to the URI.
163
189
  */
164
- onDidChange(uri: string, changes: TextDocumentContentChangeEvent[], version: number): void;
190
+ onDidChange(uri: string, changes: TextDocumentContentChangeEvent[], version: number): Promise<void>;
165
191
  /**
166
192
  * Notify that an existing document was closed in the editor.
167
193
  */
168
194
  onDidClose(uri: string): void;
195
+ ensureClientManagedChecked(uri: string): Promise<DocAndNode | undefined>;
196
+ getClientManaged(uri: string): DocAndNode | undefined;
169
197
  showCacheRoot(): Promise<void>;
170
198
  private tryClearingCache;
171
199
  private shouldRemove;