@topce/native-preview 7.0.0-dev.20260531.1 → 7.0.0-dev.20260711.3

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 (198) hide show
  1. package/NOTICE.txt +436 -0
  2. package/README.md +3 -1
  3. package/bin/tsgo +2 -0
  4. package/dist/api/async/api.d.ts +405 -78
  5. package/dist/api/async/api.d.ts.map +1 -1
  6. package/dist/api/async/api.js +992 -169
  7. package/dist/api/async/api.js.map +1 -1
  8. package/dist/api/async/client.d.ts +17 -0
  9. package/dist/api/async/client.d.ts.map +1 -1
  10. package/dist/api/async/client.js +72 -1
  11. package/dist/api/async/client.js.map +1 -1
  12. package/dist/api/async/types.d.ts +148 -17
  13. package/dist/api/async/types.d.ts.map +1 -1
  14. package/dist/api/compilerOptions.d.ts +109 -0
  15. package/dist/api/compilerOptions.d.ts.map +1 -0
  16. package/dist/api/compilerOptions.js +2 -0
  17. package/dist/api/compilerOptions.js.map +1 -0
  18. package/dist/api/node/encoder.d.ts.map +1 -1
  19. package/dist/api/node/encoder.js +1 -18
  20. package/dist/api/node/encoder.js.map +1 -1
  21. package/dist/api/node/msgpack.d.ts.map +1 -1
  22. package/dist/api/node/msgpack.js +2 -1
  23. package/dist/api/node/msgpack.js.map +1 -1
  24. package/dist/api/node/node.d.ts +19 -6
  25. package/dist/api/node/node.d.ts.map +1 -1
  26. package/dist/api/node/node.generated.d.ts +11 -0
  27. package/dist/api/node/node.generated.d.ts.map +1 -1
  28. package/dist/api/node/node.generated.js +70 -49
  29. package/dist/api/node/node.generated.js.map +1 -1
  30. package/dist/api/node/node.infrastructure.d.ts +11 -0
  31. package/dist/api/node/node.infrastructure.d.ts.map +1 -1
  32. package/dist/api/node/node.infrastructure.js.map +1 -1
  33. package/dist/api/node/node.js +117 -20
  34. package/dist/api/node/node.js.map +1 -1
  35. package/dist/api/node/wtf8.d.ts +6 -0
  36. package/dist/api/node/wtf8.d.ts.map +1 -0
  37. package/dist/api/node/wtf8.js +61 -0
  38. package/dist/api/node/wtf8.js.map +1 -0
  39. package/dist/api/options.d.ts +8 -0
  40. package/dist/api/options.d.ts.map +1 -1
  41. package/dist/api/options.js.map +1 -1
  42. package/dist/api/proto.d.ts +111 -24
  43. package/dist/api/proto.d.ts.map +1 -1
  44. package/dist/api/proto.js +15 -0
  45. package/dist/api/proto.js.map +1 -1
  46. package/dist/api/sourceFileCache.d.ts +4 -4
  47. package/dist/api/sync/api.d.ts +405 -78
  48. package/dist/api/sync/api.d.ts.map +1 -1
  49. package/dist/api/sync/api.js +990 -167
  50. package/dist/api/sync/api.js.map +1 -1
  51. package/dist/api/sync/client.d.ts +17 -0
  52. package/dist/api/sync/client.d.ts.map +1 -1
  53. package/dist/api/sync/client.js +53 -1
  54. package/dist/api/sync/client.js.map +1 -1
  55. package/dist/api/sync/types.d.ts +148 -17
  56. package/dist/api/sync/types.d.ts.map +1 -1
  57. package/dist/api/syncChannel.d.ts +4 -1
  58. package/dist/api/syncChannel.d.ts.map +1 -1
  59. package/dist/api/syncChannel.js +21 -1
  60. package/dist/api/syncChannel.js.map +1 -1
  61. package/dist/api/timing.d.ts +175 -0
  62. package/dist/api/timing.d.ts.map +1 -0
  63. package/dist/api/timing.js +149 -0
  64. package/dist/api/timing.js.map +1 -0
  65. package/dist/ast/ast.d.ts +36 -2
  66. package/dist/ast/ast.d.ts.map +1 -1
  67. package/dist/ast/ast.generated.d.ts +3 -3
  68. package/dist/ast/ast.generated.d.ts.map +1 -1
  69. package/dist/ast/ast.js.map +1 -1
  70. package/dist/ast/factory.generated.d.ts +12 -4
  71. package/dist/ast/factory.generated.d.ts.map +1 -1
  72. package/dist/ast/factory.generated.js +36 -2
  73. package/dist/ast/factory.generated.js.map +1 -1
  74. package/dist/ast/index.d.ts +2 -0
  75. package/dist/ast/index.d.ts.map +1 -1
  76. package/dist/ast/index.js +2 -0
  77. package/dist/ast/index.js.map +1 -1
  78. package/dist/ast/is.d.ts +2 -1
  79. package/dist/ast/is.d.ts.map +1 -1
  80. package/dist/ast/is.generated.d.ts +2 -2
  81. package/dist/ast/is.generated.d.ts.map +1 -1
  82. package/dist/ast/is.generated.js +3 -4
  83. package/dist/ast/is.generated.js.map +1 -1
  84. package/dist/ast/is.js +8 -1
  85. package/dist/ast/is.js.map +1 -1
  86. package/dist/ast/jsdoc.d.ts +11 -0
  87. package/dist/ast/jsdoc.d.ts.map +1 -0
  88. package/dist/ast/jsdoc.js +202 -0
  89. package/dist/ast/jsdoc.js.map +1 -0
  90. package/dist/ast/utils.d.ts +12 -0
  91. package/dist/ast/utils.d.ts.map +1 -1
  92. package/dist/ast/utils.js +40 -0
  93. package/dist/ast/utils.js.map +1 -1
  94. package/dist/enums/characterCodes.enum.d.ts +1 -1
  95. package/dist/enums/characterCodes.enum.d.ts.map +1 -1
  96. package/dist/enums/characterCodes.enum.js.map +1 -1
  97. package/dist/enums/commentDirectiveType.enum.d.ts +1 -1
  98. package/dist/enums/commentDirectiveType.enum.d.ts.map +1 -1
  99. package/dist/enums/commentDirectiveType.enum.js.map +1 -1
  100. package/dist/enums/completionItemKind.d.ts +2 -0
  101. package/dist/enums/completionItemKind.d.ts.map +1 -0
  102. package/dist/enums/completionItemKind.enum.d.ts +28 -0
  103. package/dist/enums/completionItemKind.enum.d.ts.map +1 -0
  104. package/dist/enums/completionItemKind.enum.js +30 -0
  105. package/dist/enums/completionItemKind.enum.js.map +1 -0
  106. package/dist/enums/completionItemKind.js +30 -0
  107. package/dist/enums/completionItemKind.js.map +1 -0
  108. package/dist/enums/internalSymbolName.d.ts +2 -0
  109. package/dist/enums/internalSymbolName.d.ts.map +1 -0
  110. package/dist/enums/internalSymbolName.enum.d.ts +23 -0
  111. package/dist/enums/internalSymbolName.enum.d.ts.map +1 -0
  112. package/dist/enums/internalSymbolName.enum.js +25 -0
  113. package/dist/enums/internalSymbolName.enum.js.map +1 -0
  114. package/dist/enums/internalSymbolName.js +25 -0
  115. package/dist/enums/internalSymbolName.js.map +1 -0
  116. package/dist/enums/jsxEmit.d.ts +2 -0
  117. package/dist/enums/jsxEmit.d.ts.map +1 -0
  118. package/dist/enums/jsxEmit.enum.d.ts +9 -0
  119. package/dist/enums/jsxEmit.enum.d.ts.map +1 -0
  120. package/dist/enums/jsxEmit.enum.js +11 -0
  121. package/dist/enums/jsxEmit.enum.js.map +1 -0
  122. package/dist/enums/jsxEmit.js +11 -0
  123. package/dist/enums/jsxEmit.js.map +1 -0
  124. package/dist/enums/languageVariant.enum.d.ts +1 -1
  125. package/dist/enums/languageVariant.enum.d.ts.map +1 -1
  126. package/dist/enums/languageVariant.enum.js.map +1 -1
  127. package/dist/enums/moduleDetectionKind.d.ts +2 -0
  128. package/dist/enums/moduleDetectionKind.d.ts.map +1 -0
  129. package/dist/enums/moduleDetectionKind.enum.d.ts +7 -0
  130. package/dist/enums/moduleDetectionKind.enum.d.ts.map +1 -0
  131. package/dist/enums/moduleDetectionKind.enum.js +9 -0
  132. package/dist/enums/moduleDetectionKind.enum.js.map +1 -0
  133. package/dist/enums/moduleDetectionKind.js +9 -0
  134. package/dist/enums/moduleDetectionKind.js.map +1 -0
  135. package/dist/enums/moduleKind.d.ts +2 -0
  136. package/dist/enums/moduleKind.d.ts.map +1 -0
  137. package/dist/enums/moduleKind.enum.d.ts +17 -0
  138. package/dist/enums/moduleKind.enum.d.ts.map +1 -0
  139. package/dist/enums/moduleKind.enum.js +19 -0
  140. package/dist/enums/moduleKind.enum.js.map +1 -0
  141. package/dist/enums/moduleKind.js +19 -0
  142. package/dist/enums/moduleKind.js.map +1 -0
  143. package/dist/enums/moduleResolutionKind.d.ts +2 -0
  144. package/dist/enums/moduleResolutionKind.d.ts.map +1 -0
  145. package/dist/enums/moduleResolutionKind.enum.d.ts +9 -0
  146. package/dist/enums/moduleResolutionKind.enum.d.ts.map +1 -0
  147. package/dist/enums/moduleResolutionKind.enum.js +11 -0
  148. package/dist/enums/moduleResolutionKind.enum.js.map +1 -0
  149. package/dist/enums/moduleResolutionKind.js +11 -0
  150. package/dist/enums/moduleResolutionKind.js.map +1 -0
  151. package/dist/enums/newLineKind.d.ts +2 -0
  152. package/dist/enums/newLineKind.d.ts.map +1 -0
  153. package/dist/enums/newLineKind.enum.d.ts +6 -0
  154. package/dist/enums/newLineKind.enum.d.ts.map +1 -0
  155. package/dist/enums/newLineKind.enum.js +8 -0
  156. package/dist/enums/newLineKind.enum.js.map +1 -0
  157. package/dist/enums/newLineKind.js +8 -0
  158. package/dist/enums/newLineKind.js.map +1 -0
  159. package/dist/enums/nodeFlags.enum.d.ts +1 -0
  160. package/dist/enums/nodeFlags.enum.d.ts.map +1 -1
  161. package/dist/enums/nodeFlags.enum.js +1 -0
  162. package/dist/enums/nodeFlags.enum.js.map +1 -1
  163. package/dist/enums/nodeFlags.js +1 -0
  164. package/dist/enums/nodeFlags.js.map +1 -1
  165. package/dist/enums/outerExpressionKinds.enum.d.ts +5 -1
  166. package/dist/enums/outerExpressionKinds.enum.d.ts.map +1 -1
  167. package/dist/enums/outerExpressionKinds.enum.js +4 -0
  168. package/dist/enums/outerExpressionKinds.enum.js.map +1 -1
  169. package/dist/enums/outerExpressionKinds.js +4 -0
  170. package/dist/enums/outerExpressionKinds.js.map +1 -1
  171. package/dist/enums/regularExpressionFlags.enum.d.ts +1 -1
  172. package/dist/enums/regularExpressionFlags.enum.d.ts.map +1 -1
  173. package/dist/enums/regularExpressionFlags.enum.js.map +1 -1
  174. package/dist/enums/scriptKind.enum.d.ts +1 -1
  175. package/dist/enums/scriptKind.enum.d.ts.map +1 -1
  176. package/dist/enums/scriptKind.enum.js.map +1 -1
  177. package/dist/enums/scriptTarget.enum.d.ts +1 -1
  178. package/dist/enums/scriptTarget.enum.d.ts.map +1 -1
  179. package/dist/enums/scriptTarget.enum.js.map +1 -1
  180. package/dist/enums/tokenFlags.enum.d.ts +1 -1
  181. package/dist/enums/tokenFlags.enum.d.ts.map +1 -1
  182. package/dist/enums/tokenFlags.enum.js.map +1 -1
  183. package/dist/internal/utils.d.ts +23 -0
  184. package/dist/internal/utils.d.ts.map +1 -0
  185. package/dist/internal/utils.js +25 -0
  186. package/dist/internal/utils.js.map +1 -0
  187. package/lib/getExePath.js +17 -4
  188. package/{bin → lib}/tsgo.js +28 -28
  189. package/lib/version.cjs +3 -0
  190. package/lib/version.d.cts +2 -0
  191. package/package.json +20 -17
  192. package/vendor/vscode-jsonrpc/License.txt +11 -0
  193. package/vendor/vscode-jsonrpc/README.md +1 -16
  194. package/vendor/vscode-jsonrpc/lib/browser/ril.js +8 -1
  195. package/vendor/vscode-jsonrpc/lib/common/connection.js +0 -1
  196. package/vendor/vscode-jsonrpc/lib/common/events.js +0 -1
  197. package/vendor/vscode-jsonrpc/lib/node/main.js +1 -1
  198. package/vendor/vscode-jsonrpc/package.json +3 -3
@@ -1,6 +1,8 @@
1
1
  /// <reference path="../node/node.ts" preserve="true" />
2
+ import { CompletionItemKind } from "#enums/completionItemKind";
2
3
  import { DiagnosticCategory } from "#enums/diagnosticCategory";
3
4
  import { ElementFlags } from "#enums/elementFlags";
5
+ import { ModuleKind } from "#enums/moduleKind";
4
6
  import { NodeBuilderFlags } from "#enums/nodeBuilderFlags";
5
7
  import { ObjectFlags } from "#enums/objectFlags";
6
8
  import { SignatureFlags } from "#enums/signatureFlags";
@@ -8,16 +10,16 @@ import { SignatureKind } from "#enums/signatureKind";
8
10
  import { SymbolFlags } from "#enums/symbolFlags";
9
11
  import { TypeFlags } from "#enums/typeFlags";
10
12
  import { TypePredicateKind } from "#enums/typePredicateKind";
11
- import { ModifierFlags, } from "../../ast/index.js";
13
+ import { ModifierFlags, unescapeLeadingUnderscores, } from "../../ast/index.js";
12
14
  import { encodeNode, uint8ArrayToBase64, } from "../node/encoder.js";
13
- import { decodeNode, findDescendant, getNodeId, parseNodeHandle, readParseOptionsKey, readSourceFileHash, RemoteSourceFile, } from "../node/node.js";
14
- import { ObjectRegistry } from "../objectRegistry.js";
15
+ import { decodeNode, getNodeId, parseNodeHandle, readParseOptionsKey, readSourceFileHash, RemoteSourceFile, } from "../node/node.js";
16
+ import { Wtf8Decoder } from "../node/wtf8.js";
15
17
  import { createGetCanonicalFileName, toPath, } from "../path.js";
16
- import { resolveFileName } from "../proto.js";
18
+ import { resolveFileName, toUpdateSnapshotRequest, } from "../proto.js";
17
19
  import { SourceFileCache } from "../sourceFileCache.js";
18
20
  import { Client, } from "./client.js";
19
- export { DiagnosticCategory, ElementFlags, ModifierFlags, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
20
21
  export { documentURIToFileName, fileNameToDocumentURI } from "../path.js";
22
+ export { CompletionItemKind, DiagnosticCategory, ElementFlags, ModifierFlags, ModuleKind, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
21
23
  export class API {
22
24
  client;
23
25
  sourceFileCache;
@@ -25,9 +27,11 @@ export class API {
25
27
  initialized = false;
26
28
  activeSnapshots = new Set();
27
29
  latestSnapshot;
28
- constructor(options) {
30
+ internal;
31
+ constructor(options = {}) {
29
32
  this.client = new Client(options);
30
33
  this.sourceFileCache = new SourceFileCache();
34
+ this.internal = new InternalAPI(this.client, () => this.ensureInitialized());
31
35
  }
32
36
  /**
33
37
  * Create an API instance from an existing LSP connection's API session.
@@ -53,10 +57,7 @@ export class API {
53
57
  }
54
58
  async updateSnapshot(params) {
55
59
  await this.ensureInitialized();
56
- const requestParams = params ?? {};
57
- if (requestParams.openProject) {
58
- requestParams.openProject = resolveFileName(requestParams.openProject);
59
- }
60
+ const requestParams = toUpdateSnapshotRequest(params);
60
61
  const data = await this.client.apiRequest("updateSnapshot", requestParams);
61
62
  // Retain cached source files from previous snapshot for unchanged files
62
63
  if (this.latestSnapshot) {
@@ -91,29 +92,65 @@ export class API {
91
92
  clearSourceFileCache() {
92
93
  this.sourceFileCache.clear();
93
94
  }
95
+ /**
96
+ * Returns a snapshot of collected timing information for requests made
97
+ * through this API instance: client-measured round-trip latency and bytes
98
+ * transferred, folded together with the server's own per-request processing
99
+ * time and an estimated transport overhead (round-trip minus server time).
100
+ *
101
+ * Fetching the snapshot issues a lightweight request to the server to
102
+ * retrieve its timing collection. Collection must be enabled via the
103
+ * `collectTiming` option; when it is not, the returned snapshot has
104
+ * `enabled: false` and zeroed totals.
105
+ */
106
+ getTimingInfo() {
107
+ return this.client.getTimingInfo();
108
+ }
109
+ /** Clears all accumulated timing totals and recent-request history, on both the client and the server. */
110
+ resetTimingInfo() {
111
+ return this.client.resetTimingInfo();
112
+ }
113
+ }
114
+ export class InternalAPI {
115
+ client;
116
+ ensureInitialized;
117
+ /** @internal */
118
+ constructor(client, ensureInitialized) {
119
+ this.client = client;
120
+ this.ensureInitialized = ensureInitialized;
121
+ }
122
+ async startCPUProfile(dir) {
123
+ await this.ensureInitialized();
124
+ await this.client.apiRequest("startCPUProfile", { dir });
125
+ }
126
+ async stopCPUProfile() {
127
+ await this.ensureInitialized();
128
+ const result = await this.client.apiRequest("stopCPUProfile", null);
129
+ return result.file;
130
+ }
131
+ async saveHeapProfile(dir) {
132
+ await this.ensureInitialized();
133
+ const result = await this.client.apiRequest("saveHeapProfile", { dir });
134
+ return result.file;
135
+ }
94
136
  }
95
137
  export class Snapshot {
96
138
  id;
97
139
  projectMap;
98
140
  toPath;
99
141
  client;
100
- objectRegistry;
101
142
  disposed = false;
102
143
  onDispose;
144
+ snapshotRegistry;
103
145
  constructor(data, client, sourceFileCache, toPath, onDispose) {
104
146
  this.id = data.snapshot;
105
147
  this.client = client;
106
148
  this.toPath = toPath;
107
149
  this.onDispose = onDispose;
108
- this.objectRegistry = new ObjectRegistry({
109
- createSymbol: symbolData => new Symbol(symbolData, this.client, this.id, this.objectRegistry),
110
- createType: typeData => new TypeObject(typeData, this.client, this.id, this.objectRegistry),
111
- createSignature: sigData => new Signature(sigData, this.objectRegistry),
112
- });
113
- // Create projects
114
150
  this.projectMap = new Map();
151
+ this.snapshotRegistry = new SnapshotObjectRegistry(client, this.id, projectId => this.projectMap.get(projectId));
115
152
  for (const projData of data.projects) {
116
- const project = new Project(projData, this.id, client, this.objectRegistry, sourceFileCache, toPath);
153
+ const project = new Project(projData, this.id, client, sourceFileCache, toPath, this.snapshotRegistry);
117
154
  this.projectMap.set(toPath(projData.configFileName), project);
118
155
  }
119
156
  }
@@ -142,9 +179,13 @@ export class Snapshot {
142
179
  if (this.disposed)
143
180
  return;
144
181
  this.disposed = true;
145
- this.objectRegistry.clear();
182
+ for (const project of this.projectMap.values()) {
183
+ project.dispose();
184
+ }
185
+ this.projectMap.clear();
186
+ this.snapshotRegistry.clear();
146
187
  this.onDispose();
147
- await this.client.apiRequest("release", { handle: this.id });
188
+ await this.client.apiRequest("release", { snapshot: this.id });
148
189
  }
149
190
  isDisposed() {
150
191
  return this.disposed;
@@ -155,6 +196,196 @@ export class Snapshot {
155
196
  }
156
197
  }
157
198
  }
199
+ class SnapshotObjectRegistry {
200
+ symbols = new Map();
201
+ client;
202
+ snapshotId;
203
+ resolveProject;
204
+ constructor(client, snapshotId, resolveProject) {
205
+ this.client = client;
206
+ this.snapshotId = snapshotId;
207
+ this.resolveProject = resolveProject;
208
+ }
209
+ /** Resolve a project id (a config file path) to its Project within this snapshot. */
210
+ getProject(projectId) {
211
+ return this.resolveProject(projectId);
212
+ }
213
+ getOrCreateSymbol(data) {
214
+ let symbol = this.symbols.get(data.id);
215
+ if (!symbol) {
216
+ symbol = new Symbol(data, this);
217
+ this.symbols.set(data.id, symbol);
218
+ }
219
+ return symbol;
220
+ }
221
+ getSymbol(id) {
222
+ return this.symbols.get(id);
223
+ }
224
+ clear() {
225
+ this.symbols.clear();
226
+ }
227
+ async fetchSymbol(source, method, handle, projectId) {
228
+ if (!handle)
229
+ return undefined;
230
+ const cached = this.getSymbol(handle);
231
+ if (cached)
232
+ return cached;
233
+ const data = await this.client.apiRequest(method, {
234
+ snapshot: this.snapshotId,
235
+ project: projectId,
236
+ objectId: source.id,
237
+ });
238
+ if (!data)
239
+ throw new Error(`${method} returned null symbol for ${source.constructor.name} ${source.id}`);
240
+ return this.getOrCreateSymbol(data);
241
+ }
242
+ async fetchSymbols(source, method, handles, projectId) {
243
+ if (handles) {
244
+ const result = new Array(handles.length);
245
+ let allCached = true;
246
+ for (let i = 0; i < handles.length; i++) {
247
+ const cached = this.getSymbol(handles[i]);
248
+ if (!cached) {
249
+ allCached = false;
250
+ break;
251
+ }
252
+ result[i] = cached;
253
+ }
254
+ if (allCached)
255
+ return result;
256
+ }
257
+ const symbolData = await this.client.apiRequest(method, {
258
+ snapshot: this.snapshotId,
259
+ project: projectId,
260
+ objectId: source.id,
261
+ });
262
+ if (symbolData == null)
263
+ return [];
264
+ else
265
+ return symbolData.map(data => this.getOrCreateSymbol(data));
266
+ }
267
+ }
268
+ class ProjectObjectRegistry {
269
+ client;
270
+ snapshotId;
271
+ project;
272
+ snapshotRegistry;
273
+ types = new Map();
274
+ signatures = new Map();
275
+ constructor(client, snapshotId, project, snapshotRegistry) {
276
+ this.client = client;
277
+ this.snapshotId = snapshotId;
278
+ this.project = project;
279
+ this.snapshotRegistry = snapshotRegistry;
280
+ }
281
+ getOrCreateSymbol(data) {
282
+ return this.snapshotRegistry.getOrCreateSymbol(data);
283
+ }
284
+ getSymbol(id) {
285
+ return this.snapshotRegistry.getSymbol(id);
286
+ }
287
+ getOrCreateType(data) {
288
+ let type = this.types.get(data.id);
289
+ if (!type) {
290
+ type = new TypeObject(data, this);
291
+ this.types.set(data.id, type);
292
+ }
293
+ return type;
294
+ }
295
+ getType(id) {
296
+ return this.types.get(id);
297
+ }
298
+ getOrCreateSignature(data) {
299
+ let sig = this.signatures.get(data.id);
300
+ if (!sig) {
301
+ sig = new Signature(data, this.project, this);
302
+ this.signatures.set(data.id, sig);
303
+ }
304
+ return sig;
305
+ }
306
+ getSignature(id) {
307
+ return this.signatures.get(id);
308
+ }
309
+ clear() {
310
+ this.types.clear();
311
+ this.signatures.clear();
312
+ }
313
+ async fetchType(source, method, handle) {
314
+ if (handle !== false) {
315
+ if (!handle)
316
+ return undefined;
317
+ const cached = this.getType(handle);
318
+ if (cached)
319
+ return cached;
320
+ }
321
+ const data = await this.client.apiRequest(method, {
322
+ snapshot: this.snapshotId,
323
+ project: this.project.id,
324
+ objectId: source.id,
325
+ });
326
+ if (!data)
327
+ throw new Error(`${method} returned null type for ${source.constructor.name} ${source.id}`);
328
+ return this.getOrCreateType(data);
329
+ }
330
+ async fetchSymbol(source, method, handle) {
331
+ return this.snapshotRegistry.fetchSymbol(source, method, handle, this.project.id);
332
+ }
333
+ async fetchSignature(source, method, handle) {
334
+ if (!handle)
335
+ return undefined;
336
+ const cached = this.getSignature(handle);
337
+ if (cached)
338
+ return cached;
339
+ const data = await this.client.apiRequest(method, {
340
+ snapshot: this.snapshotId,
341
+ project: this.project.id,
342
+ objectId: source.id,
343
+ });
344
+ if (!data)
345
+ throw new Error(`${method} returned null signature for ${source.constructor.name} ${source.id}`);
346
+ return this.getOrCreateSignature(data);
347
+ }
348
+ async fetchTypes(source, method, handles) {
349
+ if (handles) {
350
+ const result = new Array(handles.length);
351
+ let allCached = true;
352
+ for (let i = 0; i < handles.length; i++) {
353
+ const cached = this.getType(handles[i]);
354
+ if (!cached) {
355
+ allCached = false;
356
+ break;
357
+ }
358
+ result[i] = cached;
359
+ }
360
+ if (allCached)
361
+ return result;
362
+ }
363
+ const typesData = await this.client.apiRequest(method, {
364
+ snapshot: this.snapshotId,
365
+ project: this.project.id,
366
+ objectId: source.id,
367
+ });
368
+ if (typesData == null)
369
+ return [];
370
+ else
371
+ return typesData.map(data => this.getOrCreateType(data));
372
+ }
373
+ async fetchSymbols(source, method, handles) {
374
+ return this.snapshotRegistry.fetchSymbols(source, method, handles, this.project.id);
375
+ }
376
+ // getBaseTypes is a checker-level endpoint keyed by `type` (not `objectId`),
377
+ // so it cannot go through fetchTypes. This helper reuses that server method.
378
+ async fetchBaseTypes(source) {
379
+ const typesData = await this.client.apiRequest("getBaseTypes", {
380
+ snapshot: this.snapshotId,
381
+ project: this.project.id,
382
+ type: source.id,
383
+ });
384
+ if (typesData == null)
385
+ return [];
386
+ return typesData.map(data => this.getOrCreateType(data));
387
+ }
388
+ }
158
389
  export class Project {
159
390
  id;
160
391
  configFileName;
@@ -164,43 +395,51 @@ export class Project {
164
395
  checker;
165
396
  emitter;
166
397
  client;
167
- constructor(data, snapshotId, client, objectRegistry, sourceFileCache, toPath) {
398
+ constructor(data, snapshotId, client, sourceFileCache, toPath, snapshotRegistry) {
168
399
  this.id = data.id;
169
400
  this.configFileName = data.configFileName;
170
401
  this.compilerOptions = data.compilerOptions;
171
402
  this.rootFiles = data.rootFiles;
172
403
  this.client = client;
173
- this.program = new Program(snapshotId, this.id, client, sourceFileCache, toPath);
174
- this.checker = new Checker(snapshotId, this.id, client, objectRegistry);
404
+ this.program = new Program(snapshotId, this, client, sourceFileCache, toPath);
405
+ const objectRegistry = new ProjectObjectRegistry(client, snapshotId, this, snapshotRegistry);
406
+ this.checker = new Checker(snapshotId, this, client, objectRegistry);
175
407
  this.emitter = new Emitter(client);
176
408
  }
409
+ dispose() {
410
+ this.checker.dispose();
411
+ }
177
412
  }
178
413
  export class Program {
179
414
  snapshotId;
180
- projectId;
415
+ project;
181
416
  client;
182
417
  sourceFileCache;
183
418
  toPath;
184
- decoder = new TextDecoder();
185
- constructor(snapshotId, projectId, client, sourceFileCache, toPath) {
419
+ decoder = new Wtf8Decoder();
420
+ sourceFileMetadataCache = new Map();
421
+ constructor(snapshotId, project, client, sourceFileCache, toPath) {
186
422
  this.snapshotId = snapshotId;
187
- this.projectId = projectId;
423
+ this.project = project;
188
424
  this.client = client;
189
425
  this.sourceFileCache = sourceFileCache;
190
426
  this.toPath = toPath;
191
427
  }
428
+ getCompilerOptions() {
429
+ return this.project.compilerOptions;
430
+ }
192
431
  async getSourceFile(file) {
193
432
  const fileName = resolveFileName(file);
194
433
  const path = this.toPath(fileName);
195
434
  // Check if we already have a retained cache entry for this (snapshot, project) pair
196
- const retained = this.sourceFileCache.getRetained(path, this.snapshotId, this.projectId);
435
+ const retained = this.sourceFileCache.getRetained(path, this.snapshotId, this.project.id);
197
436
  if (retained) {
198
437
  return retained;
199
438
  }
200
439
  // Fetch from server
201
440
  const binaryData = await this.client.apiRequestBinary("getSourceFile", {
202
441
  snapshot: this.snapshotId,
203
- project: this.projectId,
442
+ project: this.project.id,
204
443
  file,
205
444
  });
206
445
  if (!binaryData) {
@@ -210,8 +449,63 @@ export class Program {
210
449
  const contentHash = readSourceFileHash(view);
211
450
  const parseOptionsKey = readParseOptionsKey(view);
212
451
  // Create a new RemoteSourceFile and cache it (set returns existing if hash matches)
213
- const sourceFile = new RemoteSourceFile(binaryData, this.decoder);
214
- return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.projectId);
452
+ const sourceFile = new RemoteSourceFile(binaryData, this.decoder, this.client.getTimingCollector());
453
+ return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.project.id);
454
+ }
455
+ async getSourceFileNames() {
456
+ const data = await this.client.apiRequest("getSourceFileNames", {
457
+ snapshot: this.snapshotId,
458
+ project: this.project.id,
459
+ });
460
+ return data ?? [];
461
+ }
462
+ /**
463
+ * Returns program-stored metadata for the given source file, or `undefined` if the file
464
+ * is not part of the program. Metadata is fetched lazily per file and cached on this
465
+ * `Program` instance.
466
+ */
467
+ getSourceFileMetadata(fileName) {
468
+ return this.getSourceFileMetadataByPath(this.toPath(fileName));
469
+ }
470
+ /**
471
+ * Returns program-stored metadata for the source file at the given path, or `undefined`
472
+ * if the file is not part of the program. Like {@link getSourceFileMetadata}, but skips
473
+ * the file name to path conversion. Metadata is fetched lazily per file and cached on
474
+ * this `Program` instance.
475
+ */
476
+ getSourceFileMetadataByPath(path) {
477
+ let metadata = this.sourceFileMetadataCache.get(path);
478
+ if (metadata === undefined) {
479
+ metadata = this.fetchSourceFileMetadata(path);
480
+ this.sourceFileMetadataCache.set(path, metadata);
481
+ }
482
+ return metadata;
483
+ }
484
+ async fetchSourceFileMetadata(path) {
485
+ const data = await this.client.apiRequest("getSourceFileMetadata", {
486
+ snapshot: this.snapshotId,
487
+ project: this.project.id,
488
+ file: path,
489
+ });
490
+ return data ?? undefined;
491
+ }
492
+ /**
493
+ * Returns whether the given source file was loaded as part of an external library
494
+ * (e.g. a dependency resolved from `node_modules`). The underlying program metadata is
495
+ * fetched lazily per file and cached on this `Program` instance.
496
+ */
497
+ async isSourceFileFromExternalLibrary(file) {
498
+ const metadata = await this.getSourceFileMetadataByPath(file.path);
499
+ return metadata?.isFromExternalLibrary ?? false;
500
+ }
501
+ /**
502
+ * Returns whether the given source file is a default library file (e.g. `lib.d.ts`).
503
+ * The underlying program metadata is fetched lazily per file and cached on this
504
+ * `Program` instance.
505
+ */
506
+ async isSourceFileDefaultLibrary(file) {
507
+ const metadata = await this.getSourceFileMetadataByPath(file.path);
508
+ return metadata?.isDefaultLibrary ?? false;
215
509
  }
216
510
  /**
217
511
  * Get syntactic (parse) diagnostics for a specific file or all files.
@@ -220,7 +514,19 @@ export class Program {
220
514
  async getSyntacticDiagnostics(file) {
221
515
  const data = await this.client.apiRequest("getSyntacticDiagnostics", {
222
516
  snapshot: this.snapshotId,
223
- project: this.projectId,
517
+ project: this.project.id,
518
+ ...(file !== undefined ? { file } : {}),
519
+ });
520
+ return data ?? [];
521
+ }
522
+ /**
523
+ * Get binder diagnostics for a specific file or all files.
524
+ * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
525
+ */
526
+ async getBindDiagnostics(file) {
527
+ const data = await this.client.apiRequest("getBindDiagnostics", {
528
+ snapshot: this.snapshotId,
529
+ project: this.project.id,
224
530
  ...(file !== undefined ? { file } : {}),
225
531
  });
226
532
  return data ?? [];
@@ -232,7 +538,7 @@ export class Program {
232
538
  async getSemanticDiagnostics(file) {
233
539
  const data = await this.client.apiRequest("getSemanticDiagnostics", {
234
540
  snapshot: this.snapshotId,
235
- project: this.projectId,
541
+ project: this.project.id,
236
542
  ...(file !== undefined ? { file } : {}),
237
543
  });
238
544
  return data ?? [];
@@ -244,7 +550,7 @@ export class Program {
244
550
  async getSuggestionDiagnostics(file) {
245
551
  const data = await this.client.apiRequest("getSuggestionDiagnostics", {
246
552
  snapshot: this.snapshotId,
247
- project: this.projectId,
553
+ project: this.project.id,
248
554
  ...(file !== undefined ? { file } : {}),
249
555
  });
250
556
  return data ?? [];
@@ -256,45 +562,70 @@ export class Program {
256
562
  async getDeclarationDiagnostics(file) {
257
563
  const data = await this.client.apiRequest("getDeclarationDiagnostics", {
258
564
  snapshot: this.snapshotId,
259
- project: this.projectId,
565
+ project: this.project.id,
260
566
  ...(file !== undefined ? { file } : {}),
261
567
  });
262
568
  return data ?? [];
263
569
  }
570
+ /**
571
+ * Get program-wide diagnostics for the project, including compiler options diagnostics.
572
+ */
573
+ async getProgramDiagnostics() {
574
+ const data = await this.client.apiRequest("getProgramDiagnostics", {
575
+ snapshot: this.snapshotId,
576
+ project: this.project.id,
577
+ });
578
+ return data ?? [];
579
+ }
580
+ /**
581
+ * Get global (non-file-specific) semantic diagnostics for the project.
582
+ */
583
+ async getGlobalDiagnostics() {
584
+ const data = await this.client.apiRequest("getGlobalDiagnostics", {
585
+ snapshot: this.snapshotId,
586
+ project: this.project.id,
587
+ });
588
+ return data ?? [];
589
+ }
264
590
  /**
265
591
  * Get config file parsing diagnostics for the project.
266
592
  */
267
593
  async getConfigFileParsingDiagnostics() {
268
594
  const data = await this.client.apiRequest("getConfigFileParsingDiagnostics", {
269
595
  snapshot: this.snapshotId,
270
- project: this.projectId,
596
+ project: this.project.id,
271
597
  });
272
598
  return data ?? [];
273
599
  }
274
600
  }
275
601
  export class Checker {
276
602
  snapshotId;
277
- projectId;
603
+ project;
278
604
  client;
279
605
  objectRegistry;
280
- constructor(snapshotId, projectId, client, objectRegistry) {
606
+ wellKnownSymbols;
607
+ wellKnownSignatures;
608
+ constructor(snapshotId, project, client, objectRegistry) {
281
609
  this.snapshotId = snapshotId;
282
- this.projectId = projectId;
610
+ this.project = project;
283
611
  this.client = client;
284
612
  this.objectRegistry = objectRegistry;
285
613
  }
614
+ dispose() {
615
+ this.objectRegistry.clear();
616
+ }
286
617
  async getSymbolAtLocation(nodeOrNodes) {
287
618
  if (Array.isArray(nodeOrNodes)) {
288
619
  const data = await this.client.apiRequest("getSymbolsAtLocations", {
289
620
  snapshot: this.snapshotId,
290
- project: this.projectId,
621
+ project: this.project.id,
291
622
  locations: nodeOrNodes.map(node => getNodeId(node)),
292
623
  });
293
624
  return data.map(d => d ? this.objectRegistry.getOrCreateSymbol(d) : undefined);
294
625
  }
295
626
  const data = await this.client.apiRequest("getSymbolAtLocation", {
296
627
  snapshot: this.snapshotId,
297
- project: this.projectId,
628
+ project: this.project.id,
298
629
  location: getNodeId(nodeOrNodes),
299
630
  });
300
631
  return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
@@ -303,7 +634,7 @@ export class Checker {
303
634
  if (typeof positionOrPositions === "number") {
304
635
  const data = await this.client.apiRequest("getSymbolAtPosition", {
305
636
  snapshot: this.snapshotId,
306
- project: this.projectId,
637
+ project: this.project.id,
307
638
  file,
308
639
  position: positionOrPositions,
309
640
  });
@@ -311,7 +642,7 @@ export class Checker {
311
642
  }
312
643
  const data = await this.client.apiRequest("getSymbolsAtPositions", {
313
644
  snapshot: this.snapshotId,
314
- project: this.projectId,
645
+ project: this.project.id,
315
646
  file,
316
647
  positions: positionOrPositions,
317
648
  });
@@ -321,64 +652,126 @@ export class Checker {
321
652
  if (Array.isArray(symbolOrSymbols)) {
322
653
  const data = await this.client.apiRequest("getTypesOfSymbols", {
323
654
  snapshot: this.snapshotId,
324
- project: this.projectId,
655
+ project: this.project.id,
325
656
  symbols: symbolOrSymbols.map(s => s.id),
326
657
  });
327
- return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
658
+ return data.map(d => this.objectRegistry.getOrCreateType(d));
328
659
  }
329
660
  const data = await this.client.apiRequest("getTypeOfSymbol", {
330
661
  snapshot: this.snapshotId,
331
- project: this.projectId,
662
+ project: this.project.id,
332
663
  symbol: symbolOrSymbols.id,
333
664
  });
334
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
665
+ return this.objectRegistry.getOrCreateType(data);
335
666
  }
667
+ /**
668
+ * Get the declared type of a symbol. Always returns a type; for symbols whose
669
+ * declared type cannot be determined the checker yields the error type (use
670
+ * {@link Type.isErrorType} to detect it).
671
+ */
336
672
  async getDeclaredTypeOfSymbol(symbol) {
337
673
  const data = await this.client.apiRequest("getDeclaredTypeOfSymbol", {
338
674
  snapshot: this.snapshotId,
339
- project: this.projectId,
675
+ project: this.project.id,
340
676
  symbol: symbol.id,
341
677
  });
342
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
678
+ return this.objectRegistry.getOrCreateType(data);
679
+ }
680
+ async getReferencesToSymbolInFile(file, symbol) {
681
+ const data = await this.client.apiRequest("getReferencesToSymbolInFile", {
682
+ snapshot: this.snapshotId,
683
+ project: this.project.id,
684
+ file,
685
+ symbol: symbol.id,
686
+ });
687
+ return (data ?? []).map(h => new NodeHandle(h, this.project));
688
+ }
689
+ async getReferencedSymbolsForNode(node, position) {
690
+ const data = await this.client.apiRequest("getReferencedSymbolsForNode", {
691
+ snapshot: this.snapshotId,
692
+ project: this.project.id,
693
+ node: getNodeId(node),
694
+ position,
695
+ });
696
+ return (data ?? []).map(entry => ({
697
+ definition: new NodeHandle(entry.definition, this.project),
698
+ symbol: entry.symbol ? this.objectRegistry.getOrCreateSymbol(entry.symbol) : undefined,
699
+ references: (entry.references ?? []).map(h => new NodeHandle(h, this.project)),
700
+ }));
701
+ }
702
+ async getSignatureUsage(signatureDecl) {
703
+ const data = await this.client.apiRequest("getSignatureUsages", {
704
+ snapshot: this.snapshotId,
705
+ project: this.project.id,
706
+ signatureDecl: getNodeId(signatureDecl),
707
+ });
708
+ return (data ?? []).map(entry => ({
709
+ name: new NodeHandle(entry.name, this.project),
710
+ call: entry.call ? new NodeHandle(entry.call, this.project) : undefined,
711
+ }));
712
+ }
713
+ async getCompletionsAtPosition(document, position, options) {
714
+ const data = await this.client.apiRequest("getCompletionsAtPosition", {
715
+ snapshot: this.snapshotId,
716
+ project: this.project.id,
717
+ file: document,
718
+ position,
719
+ triggerCharacter: options?.triggerCharacter,
720
+ includeSymbol: options?.includeSymbol,
721
+ });
722
+ if (!data)
723
+ return undefined;
724
+ return {
725
+ isIncomplete: data.isIncomplete,
726
+ entries: data.entries.map(e => ({
727
+ ...e,
728
+ symbol: e.symbol ? this.objectRegistry.getOrCreateSymbol(e.symbol) : undefined,
729
+ })),
730
+ };
343
731
  }
344
732
  async getTypeAtLocation(nodeOrNodes) {
345
733
  if (Array.isArray(nodeOrNodes)) {
346
734
  const data = await this.client.apiRequest("getTypeAtLocations", {
347
735
  snapshot: this.snapshotId,
348
- project: this.projectId,
736
+ project: this.project.id,
349
737
  locations: nodeOrNodes.map(node => getNodeId(node)),
350
738
  });
351
- return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
739
+ return data.map(d => this.objectRegistry.getOrCreateType(d));
352
740
  }
353
741
  const data = await this.client.apiRequest("getTypeAtLocation", {
354
742
  snapshot: this.snapshotId,
355
- project: this.projectId,
743
+ project: this.project.id,
356
744
  location: getNodeId(nodeOrNodes),
357
745
  });
358
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
746
+ return this.objectRegistry.getOrCreateType(data);
359
747
  }
360
748
  async getSignaturesOfType(type, kind) {
361
749
  const data = await this.client.apiRequest("getSignaturesOfType", {
362
750
  snapshot: this.snapshotId,
363
- project: this.projectId,
751
+ project: this.project.id,
364
752
  type: type.id,
365
753
  kind,
366
754
  });
367
755
  return data.map(d => this.objectRegistry.getOrCreateSignature(d));
368
756
  }
757
+ /**
758
+ * Get the resolved signature of a call-like expression. Always returns a
759
+ * signature; when a call cannot be resolved the checker yields the unknown
760
+ * signature (use {@link Checker.isUnknownSignature} to detect it).
761
+ */
369
762
  async getResolvedSignature(node) {
370
763
  const data = await this.client.apiRequest("getResolvedSignature", {
371
764
  snapshot: this.snapshotId,
372
- project: this.projectId,
765
+ project: this.project.id,
373
766
  location: getNodeId(node),
374
767
  });
375
- return data ? this.objectRegistry.getOrCreateSignature(data) : undefined;
768
+ return this.objectRegistry.getOrCreateSignature(data);
376
769
  }
377
770
  async getTypeAtPosition(file, positionOrPositions) {
378
771
  if (typeof positionOrPositions === "number") {
379
772
  const data = await this.client.apiRequest("getTypeAtPosition", {
380
773
  snapshot: this.snapshotId,
381
- project: this.projectId,
774
+ project: this.project.id,
382
775
  file,
383
776
  position: positionOrPositions,
384
777
  });
@@ -386,7 +779,7 @@ export class Checker {
386
779
  }
387
780
  const data = await this.client.apiRequest("getTypesAtPositions", {
388
781
  snapshot: this.snapshotId,
389
- project: this.projectId,
782
+ project: this.project.id,
390
783
  file,
391
784
  positions: positionOrPositions,
392
785
  });
@@ -397,7 +790,7 @@ export class Checker {
397
790
  const isNode = location && "kind" in location;
398
791
  const data = await this.client.apiRequest("resolveName", {
399
792
  snapshot: this.snapshotId,
400
- project: this.projectId,
793
+ project: this.project.id,
401
794
  name,
402
795
  meaning,
403
796
  location: isNode ? getNodeId(location) : undefined,
@@ -416,80 +809,105 @@ export class Checker {
416
809
  async getContextualType(node) {
417
810
  const data = await this.client.apiRequest("getContextualType", {
418
811
  snapshot: this.snapshotId,
419
- project: this.projectId,
812
+ project: this.project.id,
420
813
  location: getNodeId(node),
421
814
  });
422
815
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
423
816
  }
817
+ /** Get the base type of a literal type (e.g. `number` for `42`). Always returns a type. */
424
818
  async getBaseTypeOfLiteralType(type) {
425
819
  const data = await this.client.apiRequest("getBaseTypeOfLiteralType", {
426
820
  snapshot: this.snapshotId,
427
- project: this.projectId,
821
+ project: this.project.id,
428
822
  type: type.id,
429
823
  });
430
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
824
+ return this.objectRegistry.getOrCreateType(data);
431
825
  }
826
+ /** Get the type with `null` and `undefined` removed. Always returns a type. */
432
827
  async getNonNullableType(type) {
433
828
  const data = await this.client.apiRequest("getNonNullableType", {
434
829
  snapshot: this.snapshotId,
435
- project: this.projectId,
830
+ project: this.project.id,
436
831
  type: type.id,
437
832
  });
438
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
833
+ return this.objectRegistry.getOrCreateType(data);
439
834
  }
835
+ /**
836
+ * Get the type for a type node. Always returns a type; for type nodes whose
837
+ * type cannot be determined the checker yields the error type (use
838
+ * {@link Type.isErrorType} to detect it).
839
+ */
440
840
  async getTypeFromTypeNode(node) {
441
841
  const data = await this.client.apiRequest("getTypeFromTypeNode", {
442
842
  snapshot: this.snapshotId,
443
- project: this.projectId,
843
+ project: this.project.id,
444
844
  location: getNodeId(node),
445
845
  });
446
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
846
+ return this.objectRegistry.getOrCreateType(data);
447
847
  }
848
+ /** Get the widened type. Always returns a type. */
448
849
  async getWidenedType(type) {
449
850
  const data = await this.client.apiRequest("getWidenedType", {
450
851
  snapshot: this.snapshotId,
451
- project: this.projectId,
852
+ project: this.project.id,
452
853
  type: type.id,
453
854
  });
454
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
855
+ return this.objectRegistry.getOrCreateType(data);
455
856
  }
857
+ /**
858
+ * Get the type of the parameter at the given index in a signature. Always
859
+ * returns a type; an out-of-range index yields the `any` type.
860
+ */
456
861
  async getParameterType(signature, index) {
457
862
  const data = await this.client.apiRequest("getParameterType", {
458
863
  snapshot: this.snapshotId,
459
- project: this.projectId,
864
+ project: this.project.id,
460
865
  signature: signature.id,
461
866
  index,
462
867
  });
463
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
868
+ return this.objectRegistry.getOrCreateType(data);
464
869
  }
465
870
  async isArrayLikeType(type) {
466
871
  return this.client.apiRequest("isArrayLikeType", {
467
872
  snapshot: this.snapshotId,
468
- project: this.projectId,
873
+ project: this.project.id,
469
874
  type: type.id,
470
875
  });
471
876
  }
877
+ async isTypeAssignableTo(source, target) {
878
+ return this.client.apiRequest("isTypeAssignableTo", {
879
+ snapshot: this.snapshotId,
880
+ project: this.project.id,
881
+ source: source.id,
882
+ target: target.id,
883
+ });
884
+ }
472
885
  async getShorthandAssignmentValueSymbol(node) {
473
886
  const data = await this.client.apiRequest("getShorthandAssignmentValueSymbol", {
474
887
  snapshot: this.snapshotId,
475
- project: this.projectId,
888
+ project: this.project.id,
476
889
  location: getNodeId(node),
477
890
  });
478
891
  return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
479
892
  }
893
+ /**
894
+ * Get the type of a symbol as narrowed at a specific location. Always returns
895
+ * a type; for symbols whose type cannot be determined the checker yields the
896
+ * error type (use {@link Type.isErrorType} to detect it).
897
+ */
480
898
  async getTypeOfSymbolAtLocation(symbol, location) {
481
899
  const data = await this.client.apiRequest("getTypeOfSymbolAtLocation", {
482
900
  snapshot: this.snapshotId,
483
- project: this.projectId,
901
+ project: this.project.id,
484
902
  symbol: symbol.id,
485
903
  location: getNodeId(location),
486
904
  });
487
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
905
+ return this.objectRegistry.getOrCreateType(data);
488
906
  }
489
907
  async getIntrinsicType(method) {
490
908
  const data = await this.client.apiRequest(method, {
491
909
  snapshot: this.snapshotId,
492
- project: this.projectId,
910
+ project: this.project.id,
493
911
  });
494
912
  return this.objectRegistry.getOrCreateType(data);
495
913
  }
@@ -529,7 +947,7 @@ export class Checker {
529
947
  async typeToTypeNode(type, enclosingDeclaration, flags) {
530
948
  const binaryData = await this.client.apiRequestBinary("typeToTypeNode", {
531
949
  snapshot: this.snapshotId,
532
- project: this.projectId,
950
+ project: this.project.id,
533
951
  type: type.id,
534
952
  location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
535
953
  flags,
@@ -541,7 +959,7 @@ export class Checker {
541
959
  async signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags) {
542
960
  const binaryData = await this.client.apiRequestBinary("signatureToSignatureDeclaration", {
543
961
  snapshot: this.snapshotId,
544
- project: this.projectId,
962
+ project: this.project.id,
545
963
  signature: signature.id,
546
964
  kind,
547
965
  location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
@@ -554,7 +972,7 @@ export class Checker {
554
972
  async typeToString(type, enclosingDeclaration, flags) {
555
973
  return this.client.apiRequest("typeToString", {
556
974
  snapshot: this.snapshotId,
557
- project: this.projectId,
975
+ project: this.project.id,
558
976
  type: type.id,
559
977
  location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
560
978
  flags,
@@ -563,30 +981,49 @@ export class Checker {
563
981
  async isContextSensitive(node) {
564
982
  return this.client.apiRequest("isContextSensitive", {
565
983
  snapshot: this.snapshotId,
566
- project: this.projectId,
984
+ project: this.project.id,
567
985
  location: getNodeId(node),
568
986
  });
569
987
  }
988
+ async isArrayType(type) {
989
+ return this.client.apiRequest("isArrayType", {
990
+ snapshot: this.snapshotId,
991
+ project: this.project.id,
992
+ type: type.id,
993
+ });
994
+ }
995
+ async isTupleType(type) {
996
+ return this.client.apiRequest("isTupleType", {
997
+ snapshot: this.snapshotId,
998
+ project: this.project.id,
999
+ type: type.id,
1000
+ });
1001
+ }
1002
+ /** Get the return type of a signature. Always returns a type. */
570
1003
  async getReturnTypeOfSignature(signature) {
571
1004
  const data = await this.client.apiRequest("getReturnTypeOfSignature", {
572
1005
  snapshot: this.snapshotId,
573
- project: this.projectId,
1006
+ project: this.project.id,
574
1007
  signature: signature.id,
575
1008
  });
576
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
1009
+ return this.objectRegistry.getOrCreateType(data);
577
1010
  }
1011
+ /**
1012
+ * Get the rest type of a signature. Always returns a type; a signature with
1013
+ * no rest parameter yields the `any` type.
1014
+ */
578
1015
  async getRestTypeOfSignature(signature) {
579
1016
  const data = await this.client.apiRequest("getRestTypeOfSignature", {
580
1017
  snapshot: this.snapshotId,
581
- project: this.projectId,
1018
+ project: this.project.id,
582
1019
  signature: signature.id,
583
1020
  });
584
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
1021
+ return this.objectRegistry.getOrCreateType(data);
585
1022
  }
586
1023
  async getTypePredicateOfSignature(signature) {
587
1024
  const data = await this.client.apiRequest("getTypePredicateOfSignature", {
588
1025
  snapshot: this.snapshotId,
589
- project: this.projectId,
1026
+ project: this.project.id,
590
1027
  signature: signature.id,
591
1028
  });
592
1029
  if (!data)
@@ -598,18 +1035,31 @@ export class Checker {
598
1035
  type: data.type ? this.objectRegistry.getOrCreateType(data.type) : undefined,
599
1036
  };
600
1037
  }
1038
+ /**
1039
+ * Get the base types of a class or interface type. A type with no base types
1040
+ * yields an empty array.
1041
+ */
601
1042
  async getBaseTypes(type) {
602
1043
  const data = await this.client.apiRequest("getBaseTypes", {
603
1044
  snapshot: this.snapshotId,
604
- project: this.projectId,
1045
+ project: this.project.id,
605
1046
  type: type.id,
606
1047
  });
607
1048
  return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
608
1049
  }
1050
+ /** Get the apparent type of a type. Always returns a type. */
1051
+ async getApparentType(type) {
1052
+ const data = await this.client.apiRequest("getApparentType", {
1053
+ snapshot: this.snapshotId,
1054
+ project: this.project.id,
1055
+ type: type.id,
1056
+ });
1057
+ return this.objectRegistry.getOrCreateType(data);
1058
+ }
609
1059
  async getPropertiesOfType(type) {
610
1060
  const data = await this.client.apiRequest("getPropertiesOfType", {
611
1061
  snapshot: this.snapshotId,
612
- project: this.projectId,
1062
+ project: this.project.id,
613
1063
  type: type.id,
614
1064
  });
615
1065
  return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
@@ -617,7 +1067,7 @@ export class Checker {
617
1067
  async getIndexInfosOfType(type) {
618
1068
  const data = await this.client.apiRequest("getIndexInfosOfType", {
619
1069
  snapshot: this.snapshotId,
620
- project: this.projectId,
1070
+ project: this.project.id,
621
1071
  type: type.id,
622
1072
  });
623
1073
  if (!data)
@@ -626,20 +1076,173 @@ export class Checker {
626
1076
  keyType: this.objectRegistry.getOrCreateType(d.keyType),
627
1077
  valueType: this.objectRegistry.getOrCreateType(d.valueType),
628
1078
  isReadonly: d.isReadonly ?? false,
1079
+ declaration: d.declaration ? new NodeHandle(d.declaration, this.project) : undefined,
629
1080
  }));
630
1081
  }
1082
+ /**
1083
+ * Get the constraint of a type parameter (the `T` in `<U extends T>`), or
1084
+ * undefined if it has none.
1085
+ */
631
1086
  async getConstraintOfTypeParameter(type) {
632
1087
  const data = await this.client.apiRequest("getConstraintOfTypeParameter", {
633
1088
  snapshot: this.snapshotId,
634
- project: this.projectId,
1089
+ project: this.project.id,
1090
+ type: type.id,
1091
+ });
1092
+ return data ? this.objectRegistry.getOrCreateType(data) : undefined;
1093
+ }
1094
+ async getBaseConstraintOfType(type) {
1095
+ const data = await this.client.apiRequest("getBaseConstraintOfType", {
1096
+ snapshot: this.snapshotId,
1097
+ project: this.project.id,
635
1098
  type: type.id,
636
1099
  });
637
1100
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
638
1101
  }
1102
+ async getPropertyOfType(type, name) {
1103
+ const data = await this.client.apiRequest("getPropertyOfType", {
1104
+ snapshot: this.snapshotId,
1105
+ project: this.project.id,
1106
+ type: type.id,
1107
+ name,
1108
+ });
1109
+ return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1110
+ }
1111
+ async getConstantValue(node) {
1112
+ const data = await this.client.apiRequest("getConstantValue", {
1113
+ snapshot: this.snapshotId,
1114
+ project: this.project.id,
1115
+ location: getNodeId(node),
1116
+ });
1117
+ return data ?? undefined;
1118
+ }
1119
+ /** Get the signature of a function-like declaration. Always returns a signature. */
1120
+ async getSignatureFromDeclaration(node) {
1121
+ const data = await this.client.apiRequest("getSignatureFromDeclaration", {
1122
+ snapshot: this.snapshotId,
1123
+ project: this.project.id,
1124
+ location: getNodeId(node),
1125
+ });
1126
+ return this.objectRegistry.getOrCreateSignature(data);
1127
+ }
1128
+ async getExportSpecifierLocalTargetSymbol(node) {
1129
+ const data = await this.client.apiRequest("getExportSpecifierLocalTargetSymbol", {
1130
+ snapshot: this.snapshotId,
1131
+ project: this.project.id,
1132
+ location: getNodeId(node),
1133
+ });
1134
+ return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1135
+ }
1136
+ /**
1137
+ * Follow all aliases to get the original symbol. Always returns a symbol; for
1138
+ * an unresolved alias the checker yields the unknown symbol (use
1139
+ * {@link Checker.isUnknownSymbol} to detect it).
1140
+ */
1141
+ async getAliasedSymbol(symbol) {
1142
+ const data = await this.client.apiRequest("getAliasedSymbol", {
1143
+ snapshot: this.snapshotId,
1144
+ project: this.project.id,
1145
+ symbol: symbol.id,
1146
+ });
1147
+ return this.objectRegistry.getOrCreateSymbol(data);
1148
+ }
1149
+ async getImmediateAliasedSymbol(symbol) {
1150
+ const data = await this.client.apiRequest("getImmediateAliasedSymbol", {
1151
+ snapshot: this.snapshotId,
1152
+ project: this.project.id,
1153
+ symbol: symbol.id,
1154
+ });
1155
+ return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1156
+ }
1157
+ /**
1158
+ * Fetch (once, then cache) the handle ids of the per-checker singleton
1159
+ * symbols (unknown, undefined, arguments). These ids are stable for the life
1160
+ * of the project's checker, so identity checks against them are local after
1161
+ * the first call.
1162
+ */
1163
+ getWellKnownSymbols() {
1164
+ return this.wellKnownSymbols ??= this.client.apiRequest("getWellKnownSymbols", {
1165
+ snapshot: this.snapshotId,
1166
+ project: this.project.id,
1167
+ });
1168
+ }
1169
+ /**
1170
+ * Returns `true` if the symbol is the checker's "unknown" symbol (e.g. the
1171
+ * result of {@link Checker.getAliasedSymbol} on an unresolved alias).
1172
+ */
1173
+ async isUnknownSymbol(symbol) {
1174
+ return symbol.id === (await this.getWellKnownSymbols()).unknown;
1175
+ }
1176
+ /**
1177
+ * Returns `true` if the symbol is the checker's "undefined" symbol.
1178
+ */
1179
+ async isUndefinedSymbol(symbol) {
1180
+ return symbol.id === (await this.getWellKnownSymbols()).undefined;
1181
+ }
1182
+ /**
1183
+ * Returns `true` if the symbol is the checker's "arguments" symbol.
1184
+ */
1185
+ async isArgumentsSymbol(symbol) {
1186
+ return symbol.id === (await this.getWellKnownSymbols()).arguments;
1187
+ }
1188
+ /**
1189
+ * Fetch (once, then cache) the handle id of the per-checker unknown
1190
+ * signature. This id is stable for the life of the project's checker, so
1191
+ * identity checks against it are local after the first call.
1192
+ */
1193
+ getWellKnownSignatures() {
1194
+ return this.wellKnownSignatures ??= this.client.apiRequest("getWellKnownSignatures", {
1195
+ snapshot: this.snapshotId,
1196
+ project: this.project.id,
1197
+ });
1198
+ }
1199
+ /**
1200
+ * Returns `true` if the signature is the checker's "unknown" signature (e.g.
1201
+ * the result of {@link Checker.getResolvedSignature} on a call that cannot be
1202
+ * resolved).
1203
+ */
1204
+ async isUnknownSignature(signature) {
1205
+ return signature.id === (await this.getWellKnownSignatures()).unknown;
1206
+ }
1207
+ async getExportsOfModule(symbol) {
1208
+ const data = await this.client.apiRequest("getExportsOfModule", {
1209
+ snapshot: this.snapshotId,
1210
+ project: this.project.id,
1211
+ symbol: symbol.id,
1212
+ });
1213
+ return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
1214
+ }
1215
+ async getMemberInModuleExports(symbol, name) {
1216
+ const data = await this.client.apiRequest("getMemberInModuleExports", {
1217
+ snapshot: this.snapshotId,
1218
+ project: this.project.id,
1219
+ symbol: symbol.id,
1220
+ name,
1221
+ });
1222
+ return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1223
+ }
1224
+ async getJsDocTagsOfSymbol(symbol) {
1225
+ const data = await this.client.apiRequest("getJsDocTags", {
1226
+ snapshot: this.snapshotId,
1227
+ project: this.project.id,
1228
+ symbol: symbol.id,
1229
+ });
1230
+ return data ?? [];
1231
+ }
1232
+ async getDocumentationCommentOfSymbol(symbol) {
1233
+ return this.client.apiRequest("getDocumentationComment", {
1234
+ snapshot: this.snapshotId,
1235
+ project: this.project.id,
1236
+ symbol: symbol.id,
1237
+ });
1238
+ }
1239
+ /**
1240
+ * Get the type arguments of a type reference (e.g. the `string` in `Array<string>`).
1241
+ */
639
1242
  async getTypeArguments(type) {
640
1243
  const data = await this.client.apiRequest("getTypeArguments", {
641
1244
  snapshot: this.snapshotId,
642
- project: this.projectId,
1245
+ project: this.project.id,
643
1246
  type: type.id,
644
1247
  });
645
1248
  return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
@@ -660,80 +1263,129 @@ export class Emitter {
660
1263
  }
661
1264
  }
662
1265
  export class NodeHandle {
1266
+ /**
1267
+ * The project this handle was produced in, used as the default for {@link resolve}.
1268
+ * Node handles are only meaningful within a project's program, so the producing project
1269
+ * is remembered so callers don't have to pass it explicitly.
1270
+ */
1271
+ canonicalProject;
1272
+ index;
663
1273
  kind;
664
- pos;
665
- end;
666
1274
  path;
667
- constructor(handle) {
1275
+ constructor(handle, canonicalProject) {
668
1276
  const parsed = parseNodeHandle(handle);
669
- this.pos = parsed.pos;
670
- this.end = parsed.end;
1277
+ this.index = parsed.index;
671
1278
  this.kind = parsed.kind;
672
1279
  this.path = parsed.path;
1280
+ this.canonicalProject = canonicalProject;
673
1281
  }
674
1282
  /**
675
- * Resolve this handle to the actual AST node by fetching the source file
676
- * from the given project and finding the node at the stored position.
1283
+ * Resolve this handle to the actual AST node by fetching the source file from a project
1284
+ * and looking up the node by index. If no project is passed, the project that produced
1285
+ * the handle is used.
677
1286
  */
678
- async resolve(project) {
1287
+ async resolve(project = this.canonicalProject) {
679
1288
  const sourceFile = await project.program.getSourceFile(this.path);
680
1289
  if (!sourceFile) {
681
1290
  return undefined;
682
1291
  }
683
- // Find the node at the stored position with matching kind and end
684
- return findDescendant(sourceFile, this.pos, this.end, this.kind);
1292
+ return sourceFile.getOrCreateNodeAtIndex(this.index);
685
1293
  }
686
1294
  }
687
1295
  export class Symbol {
688
- client;
689
- snapshotId;
690
1296
  objectRegistry;
1297
+ /**
1298
+ * The project this symbol was first observed in, used as the default project for
1299
+ * lookups that need a project context (members/exports/parent). Symbols are shared
1300
+ * snapshot-wide, so these lookups can otherwise be ambiguous about which project to use.
1301
+ */
1302
+ canonicalProject;
691
1303
  id;
1304
+ /** The escaped (`__String`) name, used as the key in member/export tables. */
1305
+ escapedName;
1306
+ /** The display name (escaped underscores removed). */
692
1307
  name;
693
1308
  flags;
694
1309
  checkFlags;
695
1310
  declarations;
696
1311
  valueDeclaration;
697
- constructor(data, client, snapshotId, objectRegistry) {
698
- this.client = client;
699
- this.snapshotId = snapshotId;
1312
+ parent;
1313
+ exportSymbol;
1314
+ membersCache;
1315
+ exportsCache;
1316
+ constructor(data, objectRegistry) {
700
1317
  this.objectRegistry = objectRegistry;
701
1318
  this.id = data.id;
702
- this.name = data.name;
1319
+ this.escapedName = data.name;
1320
+ this.name = unescapeLeadingUnderscores(data.name);
703
1321
  this.flags = data.flags;
704
1322
  this.checkFlags = data.checkFlags;
705
- this.declarations = (data.declarations ?? []).map(d => new NodeHandle(d));
706
- this.valueDeclaration = data.valueDeclaration ? new NodeHandle(data.valueDeclaration) : undefined;
1323
+ const canonicalProject = objectRegistry.getProject(data.project);
1324
+ if (!canonicalProject) {
1325
+ throw new Error(`Symbol ${data.id} references unknown canonical project '${data.project}'`);
1326
+ }
1327
+ this.canonicalProject = canonicalProject;
1328
+ this.declarations = (data.declarations ?? []).map(d => new NodeHandle(d, canonicalProject));
1329
+ this.valueDeclaration = data.valueDeclaration ? new NodeHandle(data.valueDeclaration, canonicalProject) : undefined;
1330
+ if (data.parent !== undefined)
1331
+ this.parent = data.parent;
1332
+ if (data.exportSymbol !== undefined)
1333
+ this.exportSymbol = data.exportSymbol;
707
1334
  }
708
1335
  async getParent() {
709
- const data = await this.client.apiRequest("getParentOfSymbol", { snapshot: this.snapshotId, symbol: this.id });
710
- return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1336
+ return this.objectRegistry.fetchSymbol(this, "getParentOfSymbol", this.parent, this.canonicalProject.id);
711
1337
  }
712
- async getMembers() {
713
- const data = await this.client.apiRequest("getMembersOfSymbol", { snapshot: this.snapshotId, symbol: this.id });
714
- return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
1338
+ /**
1339
+ * Get this symbol's members keyed by escaped name. The result is cached on
1340
+ * the symbol, so repeated calls do not round-trip to the server.
1341
+ */
1342
+ getMembers() {
1343
+ return this.membersCache ??= this.fetchSymbolTable("getMembersOfSymbol");
715
1344
  }
716
- async getExports() {
717
- const data = await this.client.apiRequest("getExportsOfSymbol", { snapshot: this.snapshotId, symbol: this.id });
718
- return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
1345
+ /**
1346
+ * Get this symbol's exports keyed by escaped name. The result is cached on
1347
+ * the symbol, so repeated calls do not round-trip to the server.
1348
+ */
1349
+ getExports() {
1350
+ return this.exportsCache ??= this.fetchSymbolTable("getExportsOfSymbol");
1351
+ }
1352
+ async fetchSymbolTable(method) {
1353
+ const symbols = await this.objectRegistry.fetchSymbols(this, method, undefined, this.canonicalProject.id);
1354
+ const table = new Map();
1355
+ for (const symbol of symbols) {
1356
+ table.set(symbol.escapedName, symbol);
1357
+ }
1358
+ return table;
719
1359
  }
720
1360
  async getExportSymbol() {
721
- const data = await this.client.apiRequest("getExportSymbolOfSymbol", { snapshot: this.snapshotId, symbol: this.id });
722
- return this.objectRegistry.getOrCreateSymbol(data);
1361
+ if (!this.exportSymbol)
1362
+ return this;
1363
+ return this.objectRegistry.fetchSymbol(this, "getExportSymbolOfSymbol", this.exportSymbol, this.canonicalProject.id);
1364
+ }
1365
+ async getJsDocTags(checker) {
1366
+ return checker.getJsDocTagsOfSymbol(this);
1367
+ }
1368
+ async getDocumentationComment(checker) {
1369
+ return checker.getDocumentationCommentOfSymbol(this);
723
1370
  }
724
1371
  }
725
1372
  class TypeObject {
726
- client;
727
- snapshotId;
728
1373
  objectRegistry;
729
1374
  id;
730
1375
  flags;
731
1376
  objectFlags;
1377
+ symbol;
732
1378
  value;
1379
+ intrinsicName;
1380
+ isThisType;
1381
+ freshType;
1382
+ regularType;
733
1383
  target;
734
1384
  typeParameters;
735
1385
  outerTypeParameters;
736
1386
  localTypeParameters;
1387
+ aliasTypeArguments;
1388
+ aliasSymbol;
737
1389
  elementFlags;
738
1390
  fixedLength;
739
1391
  readonly;
@@ -744,24 +1396,37 @@ class TypeObject {
744
1396
  extendsType;
745
1397
  baseType;
746
1398
  substConstraint;
747
- constructor(data, client, snapshotId, objectRegistry) {
748
- this.client = client;
749
- this.snapshotId = snapshotId;
1399
+ trueType; // false if not yet loaded
1400
+ falseType; // false if not yet loaded
1401
+ constructor(data, objectRegistry) {
750
1402
  this.objectRegistry = objectRegistry;
751
1403
  this.id = data.id;
752
1404
  this.flags = data.flags;
753
1405
  if (data.objectFlags !== undefined)
754
1406
  this.objectFlags = data.objectFlags;
755
- if (data.value !== undefined)
756
- this.value = data.value;
1407
+ if (data.symbol !== undefined)
1408
+ this.symbol = data.symbol;
1409
+ if (data.value != null) {
1410
+ // BigInt literal values are serialized as decimal strings (e.g. "-123") because
1411
+ // JSON cannot represent bigint. Decode them back into a real bigint here.
1412
+ this.value = (data.flags & TypeFlags.BigIntLiteral) ? BigInt(data.value) : data.value;
1413
+ }
1414
+ if (data.intrinsicName !== undefined)
1415
+ this.intrinsicName = data.intrinsicName;
1416
+ if (data.isThisType !== undefined)
1417
+ this.isThisType = data.isThisType;
1418
+ if (data.freshType !== undefined)
1419
+ this.freshType = data.freshType;
1420
+ if (data.regularType !== undefined)
1421
+ this.regularType = data.regularType;
757
1422
  if (data.target !== undefined)
758
1423
  this.target = data.target;
759
- if (data.typeParameters !== undefined)
760
- this.typeParameters = data.typeParameters;
761
- if (data.outerTypeParameters !== undefined)
762
- this.outerTypeParameters = data.outerTypeParameters;
763
- if (data.localTypeParameters !== undefined)
764
- this.localTypeParameters = data.localTypeParameters;
1424
+ this.typeParameters = data.typeParameters ?? [];
1425
+ this.outerTypeParameters = data.outerTypeParameters ?? [];
1426
+ this.localTypeParameters = data.localTypeParameters ?? [];
1427
+ this.aliasTypeArguments = data.aliasTypeArguments ?? [];
1428
+ if (data.aliasSymbol !== undefined)
1429
+ this.aliasSymbol = data.aliasSymbol;
765
1430
  if (data.elementFlags !== undefined)
766
1431
  this.elementFlags = data.elementFlags;
767
1432
  if (data.fixedLength !== undefined)
@@ -782,82 +1447,240 @@ class TypeObject {
782
1447
  this.baseType = data.baseType;
783
1448
  if (data.substConstraint !== undefined)
784
1449
  this.substConstraint = data.substConstraint;
1450
+ this.trueType = false;
1451
+ this.falseType = false;
785
1452
  }
786
1453
  async getSymbol() {
787
- const data = await this.client.apiRequest("getSymbolOfType", { snapshot: this.snapshotId, type: this.id });
788
- return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
789
- }
790
- async fetchType(handle, method) {
791
- const cached = handle ? this.objectRegistry.getType(handle) : undefined;
792
- if (cached)
793
- return cached;
794
- const data = await this.client.apiRequest(method, { snapshot: this.snapshotId, type: this.id });
795
- if (!data)
796
- throw new Error(`${method} returned null for type ${this.id}`);
797
- return this.objectRegistry.getOrCreateType(data);
1454
+ return this.objectRegistry.fetchSymbol(this, "getSymbolOfType", this.symbol);
798
1455
  }
799
- async fetchTypes(method) {
800
- const data = await this.client.apiRequest(method, { snapshot: this.snapshotId, type: this.id });
801
- return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
1456
+ async getAliasSymbol() {
1457
+ return this.objectRegistry.fetchSymbol(this, "getAliasSymbolOfType", this.aliasSymbol);
802
1458
  }
803
1459
  async getTarget() {
804
- return this.fetchType(this.target, "getTargetOfType");
1460
+ return this.objectRegistry.fetchType(this, "getTargetOfType", this.target);
1461
+ }
1462
+ async getFreshType() {
1463
+ return this.objectRegistry.fetchType(this, "getFreshTypeOfType", this.freshType);
1464
+ }
1465
+ async getRegularType() {
1466
+ return this.objectRegistry.fetchType(this, "getRegularTypeOfType", this.regularType);
805
1467
  }
806
1468
  async getTypes() {
807
- return this.fetchTypes("getTypesOfType");
1469
+ // Only union, intersection, and template literal types have constituent
1470
+ // types; any other kind has none, so return undefined rather than sending
1471
+ // a request the server cannot satisfy.
1472
+ if (!(this.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral))) {
1473
+ return undefined;
1474
+ }
1475
+ return this.objectRegistry.fetchTypes(this, "getTypesOfType");
808
1476
  }
809
1477
  async getTypeParameters() {
810
- return this.fetchTypes("getTypeParametersOfType");
1478
+ return this.objectRegistry.fetchTypes(this, "getTypeParametersOfType", this.typeParameters);
811
1479
  }
812
1480
  async getOuterTypeParameters() {
813
- return this.fetchTypes("getOuterTypeParametersOfType");
1481
+ return this.objectRegistry.fetchTypes(this, "getOuterTypeParametersOfType", this.outerTypeParameters);
814
1482
  }
815
1483
  async getLocalTypeParameters() {
816
- return this.fetchTypes("getLocalTypeParametersOfType");
1484
+ return this.objectRegistry.fetchTypes(this, "getLocalTypeParametersOfType", this.localTypeParameters);
1485
+ }
1486
+ async getAliasTypeArguments() {
1487
+ return this.objectRegistry.fetchTypes(this, "getAliasTypeArgumentsOfType", this.aliasTypeArguments);
817
1488
  }
818
1489
  async getObjectType() {
819
- return this.fetchType(this.objectType, "getObjectTypeOfType");
1490
+ return this.objectRegistry.fetchType(this, "getObjectTypeOfType", this.objectType);
820
1491
  }
821
1492
  async getIndexType() {
822
- return this.fetchType(this.indexType, "getIndexTypeOfType");
1493
+ return this.objectRegistry.fetchType(this, "getIndexTypeOfType", this.indexType);
823
1494
  }
824
1495
  async getCheckType() {
825
- return this.fetchType(this.checkType, "getCheckTypeOfType");
1496
+ return this.objectRegistry.fetchType(this, "getCheckTypeOfType", this.checkType);
826
1497
  }
827
1498
  async getExtendsType() {
828
- return this.fetchType(this.extendsType, "getExtendsTypeOfType");
1499
+ return this.objectRegistry.fetchType(this, "getExtendsTypeOfType", this.extendsType);
829
1500
  }
830
1501
  async getBaseType() {
831
- return this.fetchType(this.baseType, "getBaseTypeOfType");
1502
+ return this.objectRegistry.fetchType(this, "getBaseTypeOfType", this.baseType);
832
1503
  }
833
1504
  async getConstraint() {
834
- return this.fetchType(this.substConstraint, "getConstraintOfType");
1505
+ return this.objectRegistry.fetchType(this, "getConstraintOfType", this.substConstraint);
1506
+ }
1507
+ async getTrueType() {
1508
+ const result = await this.objectRegistry.fetchType(this, "getTrueTypeOfConditionalType", this.trueType);
1509
+ this.trueType = result.id;
1510
+ return result;
1511
+ }
1512
+ async getFalseType() {
1513
+ const result = await this.objectRegistry.fetchType(this, "getFalseTypeOfConditionalType", this.falseType);
1514
+ this.falseType = result.id;
1515
+ return result;
1516
+ }
1517
+ /**
1518
+ * Get the base types of this type. Returns `undefined` for any type that is
1519
+ * not a class or interface.
1520
+ */
1521
+ async getBaseTypes() {
1522
+ if (!this.isClassOrInterface()) {
1523
+ return undefined;
1524
+ }
1525
+ return this.objectRegistry.fetchBaseTypes(this);
1526
+ }
1527
+ isClassOrInterface() {
1528
+ return isClassOrInterfaceType(this);
1529
+ }
1530
+ isUnionType() {
1531
+ return isUnionType(this);
1532
+ }
1533
+ isIntersectionType() {
1534
+ return isIntersectionType(this);
835
1535
  }
1536
+ isObjectType() {
1537
+ return isObjectType(this);
1538
+ }
1539
+ isIntrinsicType() {
1540
+ return isIntrinsicType(this);
1541
+ }
1542
+ isErrorType() {
1543
+ return isErrorType(this);
1544
+ }
1545
+ isLiteralType() {
1546
+ return isLiteralType(this);
1547
+ }
1548
+ isStringLiteralType() {
1549
+ return isStringLiteralType(this);
1550
+ }
1551
+ isNumberLiteralType() {
1552
+ return isNumberLiteralType(this);
1553
+ }
1554
+ isBigIntLiteralType() {
1555
+ return isBigIntLiteralType(this);
1556
+ }
1557
+ isBooleanLiteralType() {
1558
+ return isBooleanLiteralType(this);
1559
+ }
1560
+ isTypeReference() {
1561
+ return isTypeReference(this);
1562
+ }
1563
+ isTupleType() {
1564
+ return isTupleType(this);
1565
+ }
1566
+ isIndexType() {
1567
+ return isIndexType(this);
1568
+ }
1569
+ isIndexedAccessType() {
1570
+ return isIndexedAccessType(this);
1571
+ }
1572
+ isConditionalType() {
1573
+ return isConditionalType(this);
1574
+ }
1575
+ isSubstitutionType() {
1576
+ return isSubstitutionType(this);
1577
+ }
1578
+ isTemplateLiteralType() {
1579
+ return isTemplateLiteralType(this);
1580
+ }
1581
+ isStringMappingType() {
1582
+ return isStringMappingType(this);
1583
+ }
1584
+ isTypeParameter() {
1585
+ return isTypeParameter(this);
1586
+ }
1587
+ }
1588
+ export function isUnionType(type) {
1589
+ return (type.flags & TypeFlags.Union) !== 0;
1590
+ }
1591
+ export function isIntersectionType(type) {
1592
+ return (type.flags & TypeFlags.Intersection) !== 0;
1593
+ }
1594
+ export function isObjectType(type) {
1595
+ return (type.flags & TypeFlags.Object) !== 0;
1596
+ }
1597
+ export function isClassOrInterfaceType(type) {
1598
+ return isObjectType(type) && (type.objectFlags & ObjectFlags.ClassOrInterface) !== 0;
1599
+ }
1600
+ export function isIntrinsicType(type) {
1601
+ return (type.flags & TypeFlags.Intrinsic) !== 0;
1602
+ }
1603
+ /**
1604
+ * Whether this is the error type — the placeholder the checker produces when a
1605
+ * type cannot be determined (e.g. an unresolved reference). It is an intrinsic
1606
+ * type named `"error"` (this covers both the singleton error type and the
1607
+ * per-alias error types manufactured for unresolved type alias references).
1608
+ */
1609
+ export function isErrorType(type) {
1610
+ return isIntrinsicType(type) && type.intrinsicName === "error";
1611
+ }
1612
+ export function isLiteralType(type) {
1613
+ return (type.flags & TypeFlags.Literal) !== 0;
1614
+ }
1615
+ export function isStringLiteralType(type) {
1616
+ return (type.flags & TypeFlags.StringLiteral) !== 0;
1617
+ }
1618
+ export function isNumberLiteralType(type) {
1619
+ return (type.flags & TypeFlags.NumberLiteral) !== 0;
1620
+ }
1621
+ export function isBigIntLiteralType(type) {
1622
+ return (type.flags & TypeFlags.BigIntLiteral) !== 0;
1623
+ }
1624
+ export function isBooleanLiteralType(type) {
1625
+ return (type.flags & TypeFlags.BooleanLiteral) !== 0;
1626
+ }
1627
+ export function isTypeReference(type) {
1628
+ return isObjectType(type) && (type.objectFlags & ObjectFlags.Reference) !== 0;
1629
+ }
1630
+ export function isTupleType(type) {
1631
+ return isObjectType(type) && (type.objectFlags & ObjectFlags.Tuple) !== 0;
1632
+ }
1633
+ export function isIndexType(type) {
1634
+ return (type.flags & TypeFlags.Index) !== 0;
1635
+ }
1636
+ export function isIndexedAccessType(type) {
1637
+ return (type.flags & TypeFlags.IndexedAccess) !== 0;
1638
+ }
1639
+ export function isConditionalType(type) {
1640
+ return (type.flags & TypeFlags.Conditional) !== 0;
1641
+ }
1642
+ export function isSubstitutionType(type) {
1643
+ return (type.flags & TypeFlags.Substitution) !== 0;
1644
+ }
1645
+ export function isTemplateLiteralType(type) {
1646
+ return (type.flags & TypeFlags.TemplateLiteral) !== 0;
1647
+ }
1648
+ export function isStringMappingType(type) {
1649
+ return (type.flags & TypeFlags.StringMapping) !== 0;
1650
+ }
1651
+ export function isTypeParameter(type) {
1652
+ return (type.flags & TypeFlags.TypeParameter) !== 0;
836
1653
  }
837
1654
  export class Signature {
838
1655
  flags;
1656
+ objectRegistry;
839
1657
  id;
840
1658
  declaration;
841
1659
  typeParameters;
842
1660
  parameters;
843
1661
  thisParameter;
844
1662
  target;
845
- constructor(data, objectRegistry) {
1663
+ constructor(data, project, objectRegistry) {
846
1664
  this.id = data.id;
847
1665
  this.flags = data.flags;
848
- this.declaration = data.declaration ? new NodeHandle(data.declaration) : undefined;
849
- this.typeParameters = (data.typeParameters ?? []).map(id => {
850
- return objectRegistry.getOrCreateType({ id, flags: 0 });
851
- });
852
- this.parameters = (data.parameters ?? []).map(id => {
853
- return objectRegistry.getOrCreateSymbol({ id, name: "", flags: 0, checkFlags: 0 });
854
- });
855
- this.thisParameter = data.thisParameter
856
- ? objectRegistry.getOrCreateSymbol({ id: data.thisParameter, name: "", flags: 0, checkFlags: 0 })
857
- : undefined;
858
- this.target = data.target
859
- ? objectRegistry.getOrCreateSignature({ id: data.target, flags: 0 })
860
- : undefined;
1666
+ this.objectRegistry = objectRegistry;
1667
+ this.declaration = data.declaration ? new NodeHandle(data.declaration, project) : undefined;
1668
+ this.typeParameters = data.typeParameters ?? [];
1669
+ this.parameters = data.parameters ?? [];
1670
+ this.thisParameter = data.thisParameter;
1671
+ this.target = data.target;
1672
+ }
1673
+ async getTypeParameters() {
1674
+ return this.objectRegistry.fetchTypes(this, "getTypeParametersOfSignature", this.typeParameters);
1675
+ }
1676
+ async getParameters() {
1677
+ return this.objectRegistry.fetchSymbols(this, "getParametersOfSignature", this.parameters);
1678
+ }
1679
+ async getThisParameter() {
1680
+ return this.objectRegistry.fetchSymbol(this, "getThisParameterOfSignature", this.thisParameter);
1681
+ }
1682
+ async getTarget() {
1683
+ return this.objectRegistry.fetchSignature(this, "getTargetOfSignature", this.target);
861
1684
  }
862
1685
  get hasRestParameter() {
863
1686
  return (this.flags & SignatureFlags.HasRestParameter) !== 0;