@typescript/native-preview 7.0.0-dev.20260630.1 → 7.0.0-dev.20260702.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 (121) hide show
  1. package/dist/api/async/api.d.ts +144 -33
  2. package/dist/api/async/api.d.ts.map +1 -1
  3. package/dist/api/async/api.js +309 -115
  4. package/dist/api/async/api.js.map +1 -1
  5. package/dist/api/async/types.d.ts +31 -19
  6. package/dist/api/async/types.d.ts.map +1 -1
  7. package/dist/api/compilerOptions.d.ts +109 -0
  8. package/dist/api/compilerOptions.d.ts.map +1 -0
  9. package/dist/api/compilerOptions.js +2 -0
  10. package/dist/api/compilerOptions.js.map +1 -0
  11. package/dist/api/node/encoder.d.ts.map +1 -1
  12. package/dist/api/node/encoder.js +1 -18
  13. package/dist/api/node/encoder.js.map +1 -1
  14. package/dist/api/node/msgpack.d.ts.map +1 -1
  15. package/dist/api/node/msgpack.js +2 -1
  16. package/dist/api/node/msgpack.js.map +1 -1
  17. package/dist/api/node/node.d.ts +1 -1
  18. package/dist/api/node/node.d.ts.map +1 -1
  19. package/dist/api/node/node.generated.d.ts +1 -0
  20. package/dist/api/node/node.generated.d.ts.map +1 -1
  21. package/dist/api/node/node.generated.js +5 -36
  22. package/dist/api/node/node.generated.js.map +1 -1
  23. package/dist/api/node/node.infrastructure.d.ts +3 -0
  24. package/dist/api/node/node.infrastructure.d.ts.map +1 -1
  25. package/dist/api/node/node.infrastructure.js.map +1 -1
  26. package/dist/api/node/node.js +2 -1
  27. package/dist/api/node/node.js.map +1 -1
  28. package/dist/api/node/wtf8.d.ts +6 -0
  29. package/dist/api/node/wtf8.d.ts.map +1 -0
  30. package/dist/api/node/wtf8.js +61 -0
  31. package/dist/api/node/wtf8.js.map +1 -0
  32. package/dist/api/proto.d.ts +20 -3
  33. package/dist/api/proto.d.ts.map +1 -1
  34. package/dist/api/proto.js.map +1 -1
  35. package/dist/api/sync/api.d.ts +144 -33
  36. package/dist/api/sync/api.d.ts.map +1 -1
  37. package/dist/api/sync/api.js +307 -113
  38. package/dist/api/sync/api.js.map +1 -1
  39. package/dist/api/sync/types.d.ts +31 -19
  40. package/dist/api/sync/types.d.ts.map +1 -1
  41. package/dist/ast/ast.d.ts +16 -2
  42. package/dist/ast/ast.d.ts.map +1 -1
  43. package/dist/ast/ast.generated.d.ts +3 -3
  44. package/dist/ast/ast.generated.d.ts.map +1 -1
  45. package/dist/ast/ast.js.map +1 -1
  46. package/dist/ast/factory.generated.d.ts +4 -4
  47. package/dist/ast/factory.generated.d.ts.map +1 -1
  48. package/dist/ast/factory.generated.js.map +1 -1
  49. package/dist/ast/index.d.ts +2 -0
  50. package/dist/ast/index.d.ts.map +1 -1
  51. package/dist/ast/index.js +2 -0
  52. package/dist/ast/index.js.map +1 -1
  53. package/dist/ast/is.d.ts +2 -1
  54. package/dist/ast/is.d.ts.map +1 -1
  55. package/dist/ast/is.generated.d.ts +1 -2
  56. package/dist/ast/is.generated.d.ts.map +1 -1
  57. package/dist/ast/is.generated.js +0 -4
  58. package/dist/ast/is.generated.js.map +1 -1
  59. package/dist/ast/is.js +8 -1
  60. package/dist/ast/is.js.map +1 -1
  61. package/dist/ast/jsdoc.d.ts +11 -0
  62. package/dist/ast/jsdoc.d.ts.map +1 -0
  63. package/dist/ast/jsdoc.js +202 -0
  64. package/dist/ast/jsdoc.js.map +1 -0
  65. package/dist/ast/utils.d.ts +11 -1
  66. package/dist/ast/utils.d.ts.map +1 -1
  67. package/dist/ast/utils.js +20 -0
  68. package/dist/ast/utils.js.map +1 -1
  69. package/dist/enums/internalSymbolName.d.ts +2 -0
  70. package/dist/enums/internalSymbolName.d.ts.map +1 -0
  71. package/dist/enums/internalSymbolName.enum.d.ts +23 -0
  72. package/dist/enums/internalSymbolName.enum.d.ts.map +1 -0
  73. package/dist/enums/internalSymbolName.enum.js +25 -0
  74. package/dist/enums/internalSymbolName.enum.js.map +1 -0
  75. package/dist/enums/internalSymbolName.js +25 -0
  76. package/dist/enums/internalSymbolName.js.map +1 -0
  77. package/dist/enums/jsxEmit.d.ts +2 -0
  78. package/dist/enums/jsxEmit.d.ts.map +1 -0
  79. package/dist/enums/jsxEmit.enum.d.ts +9 -0
  80. package/dist/enums/jsxEmit.enum.d.ts.map +1 -0
  81. package/dist/enums/jsxEmit.enum.js +11 -0
  82. package/dist/enums/jsxEmit.enum.js.map +1 -0
  83. package/dist/enums/jsxEmit.js +11 -0
  84. package/dist/enums/jsxEmit.js.map +1 -0
  85. package/dist/enums/moduleDetectionKind.d.ts +2 -0
  86. package/dist/enums/moduleDetectionKind.d.ts.map +1 -0
  87. package/dist/enums/moduleDetectionKind.enum.d.ts +7 -0
  88. package/dist/enums/moduleDetectionKind.enum.d.ts.map +1 -0
  89. package/dist/enums/moduleDetectionKind.enum.js +9 -0
  90. package/dist/enums/moduleDetectionKind.enum.js.map +1 -0
  91. package/dist/enums/moduleDetectionKind.js +9 -0
  92. package/dist/enums/moduleDetectionKind.js.map +1 -0
  93. package/dist/enums/moduleKind.d.ts +2 -0
  94. package/dist/enums/moduleKind.d.ts.map +1 -0
  95. package/dist/enums/moduleKind.enum.d.ts +17 -0
  96. package/dist/enums/moduleKind.enum.d.ts.map +1 -0
  97. package/dist/enums/moduleKind.enum.js +19 -0
  98. package/dist/enums/moduleKind.enum.js.map +1 -0
  99. package/dist/enums/moduleKind.js +19 -0
  100. package/dist/enums/moduleKind.js.map +1 -0
  101. package/dist/enums/moduleResolutionKind.d.ts +2 -0
  102. package/dist/enums/moduleResolutionKind.d.ts.map +1 -0
  103. package/dist/enums/moduleResolutionKind.enum.d.ts +9 -0
  104. package/dist/enums/moduleResolutionKind.enum.d.ts.map +1 -0
  105. package/dist/enums/moduleResolutionKind.enum.js +11 -0
  106. package/dist/enums/moduleResolutionKind.enum.js.map +1 -0
  107. package/dist/enums/moduleResolutionKind.js +11 -0
  108. package/dist/enums/moduleResolutionKind.js.map +1 -0
  109. package/dist/enums/newLineKind.d.ts +2 -0
  110. package/dist/enums/newLineKind.d.ts.map +1 -0
  111. package/dist/enums/newLineKind.enum.d.ts +6 -0
  112. package/dist/enums/newLineKind.enum.d.ts.map +1 -0
  113. package/dist/enums/newLineKind.enum.js +8 -0
  114. package/dist/enums/newLineKind.enum.js.map +1 -0
  115. package/dist/enums/newLineKind.js +8 -0
  116. package/dist/enums/newLineKind.js.map +1 -0
  117. package/dist/internal/utils.d.ts +23 -0
  118. package/dist/internal/utils.d.ts.map +1 -0
  119. package/dist/internal/utils.js +25 -0
  120. package/dist/internal/utils.js.map +1 -0
  121. package/package.json +9 -9
@@ -2,6 +2,7 @@
2
2
  import { CompletionItemKind } from "#enums/completionItemKind";
3
3
  import { DiagnosticCategory } from "#enums/diagnosticCategory";
4
4
  import { ElementFlags } from "#enums/elementFlags";
5
+ import { ModuleKind } from "#enums/moduleKind";
5
6
  import { NodeBuilderFlags } from "#enums/nodeBuilderFlags";
6
7
  import { ObjectFlags } from "#enums/objectFlags";
7
8
  import { SignatureFlags } from "#enums/signatureFlags";
@@ -9,14 +10,15 @@ import { SignatureKind } from "#enums/signatureKind";
9
10
  import { SymbolFlags } from "#enums/symbolFlags";
10
11
  import { TypeFlags } from "#enums/typeFlags";
11
12
  import { TypePredicateKind } from "#enums/typePredicateKind";
12
- import { ModifierFlags, } from "../../ast/index.js";
13
+ import { ModifierFlags, unescapeLeadingUnderscores, } from "../../ast/index.js";
13
14
  import { encodeNode, uint8ArrayToBase64, } from "../node/encoder.js";
14
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
18
  import { resolveFileName, toUpdateSnapshotRequest, } from "../proto.js";
17
19
  import { SourceFileCache } from "../sourceFileCache.js";
18
20
  import { Client, } from "./client.js";
19
- export { CompletionItemKind, DiagnosticCategory, ElementFlags, ModifierFlags, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
21
+ export { CompletionItemKind, DiagnosticCategory, ElementFlags, ModifierFlags, ModuleKind, NodeBuilderFlags, ObjectFlags, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypePredicateKind };
20
22
  export { documentURIToFileName, fileNameToDocumentURI } from "../path.js";
21
23
  export class API {
22
24
  client;
@@ -26,7 +28,7 @@ export class API {
26
28
  activeSnapshots = new Set();
27
29
  latestSnapshot;
28
30
  internal;
29
- constructor(options) {
31
+ constructor(options = {}) {
30
32
  this.client = new Client(options);
31
33
  this.sourceFileCache = new SourceFileCache();
32
34
  this.internal = new InternalAPI(this.client, () => this.ensureInitialized());
@@ -127,8 +129,8 @@ export class Snapshot {
127
129
  this.client = client;
128
130
  this.toPath = toPath;
129
131
  this.onDispose = onDispose;
130
- this.snapshotRegistry = new SnapshotObjectRegistry(client, this.id);
131
132
  this.projectMap = new Map();
133
+ this.snapshotRegistry = new SnapshotObjectRegistry(client, this.id, projectId => this.projectMap.get(projectId));
132
134
  for (const projData of data.projects) {
133
135
  const project = new Project(projData, this.id, client, sourceFileCache, toPath, this.snapshotRegistry);
134
136
  this.projectMap.set(toPath(projData.configFileName), project);
@@ -180,9 +182,15 @@ class SnapshotObjectRegistry {
180
182
  symbols = new Map();
181
183
  client;
182
184
  snapshotId;
183
- constructor(client, snapshotId) {
185
+ resolveProject;
186
+ constructor(client, snapshotId, resolveProject) {
184
187
  this.client = client;
185
188
  this.snapshotId = snapshotId;
189
+ this.resolveProject = resolveProject;
190
+ }
191
+ /** Resolve a project id (a config file path) to its Project within this snapshot. */
192
+ getProject(projectId) {
193
+ return this.resolveProject(projectId);
186
194
  }
187
195
  getOrCreateSymbol(data) {
188
196
  let symbol = this.symbols.get(data.id);
@@ -242,14 +250,14 @@ class SnapshotObjectRegistry {
242
250
  class ProjectObjectRegistry {
243
251
  client;
244
252
  snapshotId;
245
- projectId;
253
+ project;
246
254
  snapshotRegistry;
247
255
  types = new Map();
248
256
  signatures = new Map();
249
- constructor(client, snapshotId, projectId, snapshotRegistry) {
257
+ constructor(client, snapshotId, project, snapshotRegistry) {
250
258
  this.client = client;
251
259
  this.snapshotId = snapshotId;
252
- this.projectId = projectId;
260
+ this.project = project;
253
261
  this.snapshotRegistry = snapshotRegistry;
254
262
  }
255
263
  getOrCreateSymbol(data) {
@@ -272,7 +280,7 @@ class ProjectObjectRegistry {
272
280
  getOrCreateSignature(data) {
273
281
  let sig = this.signatures.get(data.id);
274
282
  if (!sig) {
275
- sig = new Signature(data, this);
283
+ sig = new Signature(data, this.project, this);
276
284
  this.signatures.set(data.id, sig);
277
285
  }
278
286
  return sig;
@@ -294,7 +302,7 @@ class ProjectObjectRegistry {
294
302
  }
295
303
  const data = await this.client.apiRequest(method, {
296
304
  snapshot: this.snapshotId,
297
- project: this.projectId,
305
+ project: this.project.id,
298
306
  objectId: source.id,
299
307
  });
300
308
  if (!data)
@@ -302,7 +310,7 @@ class ProjectObjectRegistry {
302
310
  return this.getOrCreateType(data);
303
311
  }
304
312
  async fetchSymbol(source, method, handle) {
305
- return this.snapshotRegistry.fetchSymbol(source, method, handle, this.projectId);
313
+ return this.snapshotRegistry.fetchSymbol(source, method, handle, this.project.id);
306
314
  }
307
315
  async fetchSignature(source, method, handle) {
308
316
  if (!handle)
@@ -312,7 +320,7 @@ class ProjectObjectRegistry {
312
320
  return cached;
313
321
  const data = await this.client.apiRequest(method, {
314
322
  snapshot: this.snapshotId,
315
- project: this.projectId,
323
+ project: this.project.id,
316
324
  objectId: source.id,
317
325
  });
318
326
  if (!data)
@@ -336,7 +344,7 @@ class ProjectObjectRegistry {
336
344
  }
337
345
  const typesData = await this.client.apiRequest(method, {
338
346
  snapshot: this.snapshotId,
339
- project: this.projectId,
347
+ project: this.project.id,
340
348
  objectId: source.id,
341
349
  });
342
350
  if (typesData == null)
@@ -345,7 +353,19 @@ class ProjectObjectRegistry {
345
353
  return typesData.map(data => this.getOrCreateType(data));
346
354
  }
347
355
  async fetchSymbols(source, method, handles) {
348
- return this.snapshotRegistry.fetchSymbols(source, method, handles, this.projectId);
356
+ return this.snapshotRegistry.fetchSymbols(source, method, handles, this.project.id);
357
+ }
358
+ // getBaseTypes is a checker-level endpoint keyed by `type` (not `objectId`),
359
+ // so it cannot go through fetchTypes. This helper reuses that server method.
360
+ async fetchBaseTypes(source) {
361
+ const typesData = await this.client.apiRequest("getBaseTypes", {
362
+ snapshot: this.snapshotId,
363
+ project: this.project.id,
364
+ type: source.id,
365
+ });
366
+ if (typesData == null)
367
+ return [];
368
+ return typesData.map(data => this.getOrCreateType(data));
349
369
  }
350
370
  }
351
371
  export class Project {
@@ -363,9 +383,9 @@ export class Project {
363
383
  this.compilerOptions = data.compilerOptions;
364
384
  this.rootFiles = data.rootFiles;
365
385
  this.client = client;
366
- this.program = new Program(snapshotId, this.id, client, sourceFileCache, toPath);
367
- const objectRegistry = new ProjectObjectRegistry(client, snapshotId, this.id, snapshotRegistry);
368
- this.checker = new Checker(snapshotId, this.id, client, objectRegistry);
386
+ this.program = new Program(snapshotId, this, client, sourceFileCache, toPath);
387
+ const objectRegistry = new ProjectObjectRegistry(client, snapshotId, this, snapshotRegistry);
388
+ this.checker = new Checker(snapshotId, this, client, objectRegistry);
369
389
  this.emitter = new Emitter(client);
370
390
  }
371
391
  dispose() {
@@ -374,30 +394,34 @@ export class Project {
374
394
  }
375
395
  export class Program {
376
396
  snapshotId;
377
- projectId;
397
+ project;
378
398
  client;
379
399
  sourceFileCache;
380
400
  toPath;
381
- decoder = new TextDecoder();
382
- constructor(snapshotId, projectId, client, sourceFileCache, toPath) {
401
+ decoder = new Wtf8Decoder();
402
+ sourceFileMetadataCache = new Map();
403
+ constructor(snapshotId, project, client, sourceFileCache, toPath) {
383
404
  this.snapshotId = snapshotId;
384
- this.projectId = projectId;
405
+ this.project = project;
385
406
  this.client = client;
386
407
  this.sourceFileCache = sourceFileCache;
387
408
  this.toPath = toPath;
388
409
  }
410
+ getCompilerOptions() {
411
+ return this.project.compilerOptions;
412
+ }
389
413
  async getSourceFile(file) {
390
414
  const fileName = resolveFileName(file);
391
415
  const path = this.toPath(fileName);
392
416
  // Check if we already have a retained cache entry for this (snapshot, project) pair
393
- const retained = this.sourceFileCache.getRetained(path, this.snapshotId, this.projectId);
417
+ const retained = this.sourceFileCache.getRetained(path, this.snapshotId, this.project.id);
394
418
  if (retained) {
395
419
  return retained;
396
420
  }
397
421
  // Fetch from server
398
422
  const binaryData = await this.client.apiRequestBinary("getSourceFile", {
399
423
  snapshot: this.snapshotId,
400
- project: this.projectId,
424
+ project: this.project.id,
401
425
  file,
402
426
  });
403
427
  if (!binaryData) {
@@ -408,15 +432,63 @@ export class Program {
408
432
  const parseOptionsKey = readParseOptionsKey(view);
409
433
  // Create a new RemoteSourceFile and cache it (set returns existing if hash matches)
410
434
  const sourceFile = new RemoteSourceFile(binaryData, this.decoder);
411
- return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.projectId);
435
+ return this.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, this.snapshotId, this.project.id);
412
436
  }
413
437
  async getSourceFileNames() {
414
438
  const data = await this.client.apiRequest("getSourceFileNames", {
415
439
  snapshot: this.snapshotId,
416
- project: this.projectId,
440
+ project: this.project.id,
417
441
  });
418
442
  return data ?? [];
419
443
  }
444
+ /**
445
+ * Returns program-stored metadata for the given source file, or `undefined` if the file
446
+ * is not part of the program. Metadata is fetched lazily per file and cached on this
447
+ * `Program` instance.
448
+ */
449
+ getSourceFileMetadata(fileName) {
450
+ return this.getSourceFileMetadataByPath(this.toPath(fileName));
451
+ }
452
+ /**
453
+ * Returns program-stored metadata for the source file at the given path, or `undefined`
454
+ * if the file is not part of the program. Like {@link getSourceFileMetadata}, but skips
455
+ * the file name to path conversion. Metadata is fetched lazily per file and cached on
456
+ * this `Program` instance.
457
+ */
458
+ getSourceFileMetadataByPath(path) {
459
+ let metadata = this.sourceFileMetadataCache.get(path);
460
+ if (metadata === undefined) {
461
+ metadata = this.fetchSourceFileMetadata(path);
462
+ this.sourceFileMetadataCache.set(path, metadata);
463
+ }
464
+ return metadata;
465
+ }
466
+ async fetchSourceFileMetadata(path) {
467
+ const data = await this.client.apiRequest("getSourceFileMetadata", {
468
+ snapshot: this.snapshotId,
469
+ project: this.project.id,
470
+ file: path,
471
+ });
472
+ return data ?? undefined;
473
+ }
474
+ /**
475
+ * Returns whether the given source file was loaded as part of an external library
476
+ * (e.g. a dependency resolved from `node_modules`). The underlying program metadata is
477
+ * fetched lazily per file and cached on this `Program` instance.
478
+ */
479
+ async isSourceFileFromExternalLibrary(file) {
480
+ const metadata = await this.getSourceFileMetadataByPath(file.path);
481
+ return metadata?.isFromExternalLibrary ?? false;
482
+ }
483
+ /**
484
+ * Returns whether the given source file is a default library file (e.g. `lib.d.ts`).
485
+ * The underlying program metadata is fetched lazily per file and cached on this
486
+ * `Program` instance.
487
+ */
488
+ async isSourceFileDefaultLibrary(file) {
489
+ const metadata = await this.getSourceFileMetadataByPath(file.path);
490
+ return metadata?.isDefaultLibrary ?? false;
491
+ }
420
492
  /**
421
493
  * Get syntactic (parse) diagnostics for a specific file or all files.
422
494
  * @param file - Optional file to get diagnostics for. If omitted, returns diagnostics for all files.
@@ -424,7 +496,7 @@ export class Program {
424
496
  async getSyntacticDiagnostics(file) {
425
497
  const data = await this.client.apiRequest("getSyntacticDiagnostics", {
426
498
  snapshot: this.snapshotId,
427
- project: this.projectId,
499
+ project: this.project.id,
428
500
  ...(file !== undefined ? { file } : {}),
429
501
  });
430
502
  return data ?? [];
@@ -436,7 +508,7 @@ export class Program {
436
508
  async getBindDiagnostics(file) {
437
509
  const data = await this.client.apiRequest("getBindDiagnostics", {
438
510
  snapshot: this.snapshotId,
439
- project: this.projectId,
511
+ project: this.project.id,
440
512
  ...(file !== undefined ? { file } : {}),
441
513
  });
442
514
  return data ?? [];
@@ -448,7 +520,7 @@ export class Program {
448
520
  async getSemanticDiagnostics(file) {
449
521
  const data = await this.client.apiRequest("getSemanticDiagnostics", {
450
522
  snapshot: this.snapshotId,
451
- project: this.projectId,
523
+ project: this.project.id,
452
524
  ...(file !== undefined ? { file } : {}),
453
525
  });
454
526
  return data ?? [];
@@ -460,7 +532,7 @@ export class Program {
460
532
  async getSuggestionDiagnostics(file) {
461
533
  const data = await this.client.apiRequest("getSuggestionDiagnostics", {
462
534
  snapshot: this.snapshotId,
463
- project: this.projectId,
535
+ project: this.project.id,
464
536
  ...(file !== undefined ? { file } : {}),
465
537
  });
466
538
  return data ?? [];
@@ -472,7 +544,7 @@ export class Program {
472
544
  async getDeclarationDiagnostics(file) {
473
545
  const data = await this.client.apiRequest("getDeclarationDiagnostics", {
474
546
  snapshot: this.snapshotId,
475
- project: this.projectId,
547
+ project: this.project.id,
476
548
  ...(file !== undefined ? { file } : {}),
477
549
  });
478
550
  return data ?? [];
@@ -483,7 +555,7 @@ export class Program {
483
555
  async getProgramDiagnostics() {
484
556
  const data = await this.client.apiRequest("getProgramDiagnostics", {
485
557
  snapshot: this.snapshotId,
486
- project: this.projectId,
558
+ project: this.project.id,
487
559
  });
488
560
  return data ?? [];
489
561
  }
@@ -493,7 +565,7 @@ export class Program {
493
565
  async getGlobalDiagnostics() {
494
566
  const data = await this.client.apiRequest("getGlobalDiagnostics", {
495
567
  snapshot: this.snapshotId,
496
- project: this.projectId,
568
+ project: this.project.id,
497
569
  });
498
570
  return data ?? [];
499
571
  }
@@ -503,19 +575,20 @@ export class Program {
503
575
  async getConfigFileParsingDiagnostics() {
504
576
  const data = await this.client.apiRequest("getConfigFileParsingDiagnostics", {
505
577
  snapshot: this.snapshotId,
506
- project: this.projectId,
578
+ project: this.project.id,
507
579
  });
508
580
  return data ?? [];
509
581
  }
510
582
  }
511
583
  export class Checker {
512
584
  snapshotId;
513
- projectId;
585
+ project;
514
586
  client;
515
587
  objectRegistry;
516
- constructor(snapshotId, projectId, client, objectRegistry) {
588
+ wellKnownSymbols;
589
+ constructor(snapshotId, project, client, objectRegistry) {
517
590
  this.snapshotId = snapshotId;
518
- this.projectId = projectId;
591
+ this.project = project;
519
592
  this.client = client;
520
593
  this.objectRegistry = objectRegistry;
521
594
  }
@@ -526,14 +599,14 @@ export class Checker {
526
599
  if (Array.isArray(nodeOrNodes)) {
527
600
  const data = await this.client.apiRequest("getSymbolsAtLocations", {
528
601
  snapshot: this.snapshotId,
529
- project: this.projectId,
602
+ project: this.project.id,
530
603
  locations: nodeOrNodes.map(node => getNodeId(node)),
531
604
  });
532
605
  return data.map(d => d ? this.objectRegistry.getOrCreateSymbol(d) : undefined);
533
606
  }
534
607
  const data = await this.client.apiRequest("getSymbolAtLocation", {
535
608
  snapshot: this.snapshotId,
536
- project: this.projectId,
609
+ project: this.project.id,
537
610
  location: getNodeId(nodeOrNodes),
538
611
  });
539
612
  return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
@@ -542,7 +615,7 @@ export class Checker {
542
615
  if (typeof positionOrPositions === "number") {
543
616
  const data = await this.client.apiRequest("getSymbolAtPosition", {
544
617
  snapshot: this.snapshotId,
545
- project: this.projectId,
618
+ project: this.project.id,
546
619
  file,
547
620
  position: positionOrPositions,
548
621
  });
@@ -550,7 +623,7 @@ export class Checker {
550
623
  }
551
624
  const data = await this.client.apiRequest("getSymbolsAtPositions", {
552
625
  snapshot: this.snapshotId,
553
- project: this.projectId,
626
+ project: this.project.id,
554
627
  file,
555
628
  positions: positionOrPositions,
556
629
  });
@@ -560,63 +633,70 @@ export class Checker {
560
633
  if (Array.isArray(symbolOrSymbols)) {
561
634
  const data = await this.client.apiRequest("getTypesOfSymbols", {
562
635
  snapshot: this.snapshotId,
563
- project: this.projectId,
636
+ project: this.project.id,
564
637
  symbols: symbolOrSymbols.map(s => s.id),
565
638
  });
566
639
  return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
567
640
  }
568
641
  const data = await this.client.apiRequest("getTypeOfSymbol", {
569
642
  snapshot: this.snapshotId,
570
- project: this.projectId,
643
+ project: this.project.id,
571
644
  symbol: symbolOrSymbols.id,
572
645
  });
573
646
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
574
647
  }
648
+ /**
649
+ * Get the declared type of a symbol. Always returns a type; for symbols whose
650
+ * declared type cannot be determined the checker yields the error type (use
651
+ * {@link Type.isErrorType} to detect it).
652
+ */
575
653
  async getDeclaredTypeOfSymbol(symbol) {
576
654
  const data = await this.client.apiRequest("getDeclaredTypeOfSymbol", {
577
655
  snapshot: this.snapshotId,
578
- project: this.projectId,
656
+ project: this.project.id,
579
657
  symbol: symbol.id,
580
658
  });
581
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
659
+ if (!data)
660
+ throw new Error(`getDeclaredTypeOfSymbol returned no type for symbol ${symbol.id}`);
661
+ return this.objectRegistry.getOrCreateType(data);
582
662
  }
583
663
  async getReferencesToSymbolInFile(file, symbol) {
584
664
  const data = await this.client.apiRequest("getReferencesToSymbolInFile", {
585
665
  snapshot: this.snapshotId,
586
- project: this.projectId,
666
+ project: this.project.id,
587
667
  file,
588
668
  symbol: symbol.id,
589
669
  });
590
- return (data ?? []).map(h => new NodeHandle(h));
670
+ return (data ?? []).map(h => new NodeHandle(h, this.project));
591
671
  }
592
672
  async getReferencedSymbolsForNode(node, position) {
593
673
  const data = await this.client.apiRequest("getReferencedSymbolsForNode", {
594
674
  snapshot: this.snapshotId,
595
- project: this.projectId,
675
+ project: this.project.id,
596
676
  node: getNodeId(node),
597
677
  position,
598
678
  });
599
679
  return (data ?? []).map(entry => ({
600
- definition: new NodeHandle(entry.definition),
680
+ definition: new NodeHandle(entry.definition, this.project),
601
681
  symbol: entry.symbol ? this.objectRegistry.getOrCreateSymbol(entry.symbol) : undefined,
602
- references: (entry.references ?? []).map(h => new NodeHandle(h)),
682
+ references: (entry.references ?? []).map(h => new NodeHandle(h, this.project)),
603
683
  }));
604
684
  }
605
685
  async getSignatureUsage(signatureDecl) {
606
686
  const data = await this.client.apiRequest("getSignatureUsages", {
607
687
  snapshot: this.snapshotId,
608
- project: this.projectId,
688
+ project: this.project.id,
609
689
  signatureDecl: getNodeId(signatureDecl),
610
690
  });
611
691
  return (data ?? []).map(entry => ({
612
- name: new NodeHandle(entry.name),
613
- call: entry.call ? new NodeHandle(entry.call) : undefined,
692
+ name: new NodeHandle(entry.name, this.project),
693
+ call: entry.call ? new NodeHandle(entry.call, this.project) : undefined,
614
694
  }));
615
695
  }
616
696
  async getCompletionsAtPosition(document, position, options) {
617
697
  const data = await this.client.apiRequest("getCompletionsAtPosition", {
618
698
  snapshot: this.snapshotId,
619
- project: this.projectId,
699
+ project: this.project.id,
620
700
  file: document,
621
701
  position,
622
702
  triggerCharacter: options?.triggerCharacter,
@@ -636,14 +716,14 @@ export class Checker {
636
716
  if (Array.isArray(nodeOrNodes)) {
637
717
  const data = await this.client.apiRequest("getTypeAtLocations", {
638
718
  snapshot: this.snapshotId,
639
- project: this.projectId,
719
+ project: this.project.id,
640
720
  locations: nodeOrNodes.map(node => getNodeId(node)),
641
721
  });
642
722
  return data.map(d => d ? this.objectRegistry.getOrCreateType(d) : undefined);
643
723
  }
644
724
  const data = await this.client.apiRequest("getTypeAtLocation", {
645
725
  snapshot: this.snapshotId,
646
- project: this.projectId,
726
+ project: this.project.id,
647
727
  location: getNodeId(nodeOrNodes),
648
728
  });
649
729
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -651,7 +731,7 @@ export class Checker {
651
731
  async getSignaturesOfType(type, kind) {
652
732
  const data = await this.client.apiRequest("getSignaturesOfType", {
653
733
  snapshot: this.snapshotId,
654
- project: this.projectId,
734
+ project: this.project.id,
655
735
  type: type.id,
656
736
  kind,
657
737
  });
@@ -660,7 +740,7 @@ export class Checker {
660
740
  async getResolvedSignature(node) {
661
741
  const data = await this.client.apiRequest("getResolvedSignature", {
662
742
  snapshot: this.snapshotId,
663
- project: this.projectId,
743
+ project: this.project.id,
664
744
  location: getNodeId(node),
665
745
  });
666
746
  return data ? this.objectRegistry.getOrCreateSignature(data) : undefined;
@@ -669,7 +749,7 @@ export class Checker {
669
749
  if (typeof positionOrPositions === "number") {
670
750
  const data = await this.client.apiRequest("getTypeAtPosition", {
671
751
  snapshot: this.snapshotId,
672
- project: this.projectId,
752
+ project: this.project.id,
673
753
  file,
674
754
  position: positionOrPositions,
675
755
  });
@@ -677,7 +757,7 @@ export class Checker {
677
757
  }
678
758
  const data = await this.client.apiRequest("getTypesAtPositions", {
679
759
  snapshot: this.snapshotId,
680
- project: this.projectId,
760
+ project: this.project.id,
681
761
  file,
682
762
  positions: positionOrPositions,
683
763
  });
@@ -688,7 +768,7 @@ export class Checker {
688
768
  const isNode = location && "kind" in location;
689
769
  const data = await this.client.apiRequest("resolveName", {
690
770
  snapshot: this.snapshotId,
691
- project: this.projectId,
771
+ project: this.project.id,
692
772
  name,
693
773
  meaning,
694
774
  location: isNode ? getNodeId(location) : undefined,
@@ -707,7 +787,7 @@ export class Checker {
707
787
  async getContextualType(node) {
708
788
  const data = await this.client.apiRequest("getContextualType", {
709
789
  snapshot: this.snapshotId,
710
- project: this.projectId,
790
+ project: this.project.id,
711
791
  location: getNodeId(node),
712
792
  });
713
793
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -715,7 +795,7 @@ export class Checker {
715
795
  async getBaseTypeOfLiteralType(type) {
716
796
  const data = await this.client.apiRequest("getBaseTypeOfLiteralType", {
717
797
  snapshot: this.snapshotId,
718
- project: this.projectId,
798
+ project: this.project.id,
719
799
  type: type.id,
720
800
  });
721
801
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -723,7 +803,7 @@ export class Checker {
723
803
  async getNonNullableType(type) {
724
804
  const data = await this.client.apiRequest("getNonNullableType", {
725
805
  snapshot: this.snapshotId,
726
- project: this.projectId,
806
+ project: this.project.id,
727
807
  type: type.id,
728
808
  });
729
809
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -731,7 +811,7 @@ export class Checker {
731
811
  async getTypeFromTypeNode(node) {
732
812
  const data = await this.client.apiRequest("getTypeFromTypeNode", {
733
813
  snapshot: this.snapshotId,
734
- project: this.projectId,
814
+ project: this.project.id,
735
815
  location: getNodeId(node),
736
816
  });
737
817
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -739,7 +819,7 @@ export class Checker {
739
819
  async getWidenedType(type) {
740
820
  const data = await this.client.apiRequest("getWidenedType", {
741
821
  snapshot: this.snapshotId,
742
- project: this.projectId,
822
+ project: this.project.id,
743
823
  type: type.id,
744
824
  });
745
825
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -747,7 +827,7 @@ export class Checker {
747
827
  async getParameterType(signature, index) {
748
828
  const data = await this.client.apiRequest("getParameterType", {
749
829
  snapshot: this.snapshotId,
750
- project: this.projectId,
830
+ project: this.project.id,
751
831
  signature: signature.id,
752
832
  index,
753
833
  });
@@ -756,14 +836,14 @@ export class Checker {
756
836
  async isArrayLikeType(type) {
757
837
  return this.client.apiRequest("isArrayLikeType", {
758
838
  snapshot: this.snapshotId,
759
- project: this.projectId,
839
+ project: this.project.id,
760
840
  type: type.id,
761
841
  });
762
842
  }
763
843
  async isTypeAssignableTo(source, target) {
764
844
  return this.client.apiRequest("isTypeAssignableTo", {
765
845
  snapshot: this.snapshotId,
766
- project: this.projectId,
846
+ project: this.project.id,
767
847
  source: source.id,
768
848
  target: target.id,
769
849
  });
@@ -771,24 +851,31 @@ export class Checker {
771
851
  async getShorthandAssignmentValueSymbol(node) {
772
852
  const data = await this.client.apiRequest("getShorthandAssignmentValueSymbol", {
773
853
  snapshot: this.snapshotId,
774
- project: this.projectId,
854
+ project: this.project.id,
775
855
  location: getNodeId(node),
776
856
  });
777
857
  return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
778
858
  }
859
+ /**
860
+ * Get the type of a symbol as narrowed at a specific location. Always returns
861
+ * a type; for symbols whose type cannot be determined the checker yields the
862
+ * error type (use {@link Type.isErrorType} to detect it).
863
+ */
779
864
  async getTypeOfSymbolAtLocation(symbol, location) {
780
865
  const data = await this.client.apiRequest("getTypeOfSymbolAtLocation", {
781
866
  snapshot: this.snapshotId,
782
- project: this.projectId,
867
+ project: this.project.id,
783
868
  symbol: symbol.id,
784
869
  location: getNodeId(location),
785
870
  });
786
- return data ? this.objectRegistry.getOrCreateType(data) : undefined;
871
+ if (!data)
872
+ throw new Error(`getTypeOfSymbolAtLocation returned no type for symbol ${symbol.id}`);
873
+ return this.objectRegistry.getOrCreateType(data);
787
874
  }
788
875
  async getIntrinsicType(method) {
789
876
  const data = await this.client.apiRequest(method, {
790
877
  snapshot: this.snapshotId,
791
- project: this.projectId,
878
+ project: this.project.id,
792
879
  });
793
880
  return this.objectRegistry.getOrCreateType(data);
794
881
  }
@@ -828,7 +915,7 @@ export class Checker {
828
915
  async typeToTypeNode(type, enclosingDeclaration, flags) {
829
916
  const binaryData = await this.client.apiRequestBinary("typeToTypeNode", {
830
917
  snapshot: this.snapshotId,
831
- project: this.projectId,
918
+ project: this.project.id,
832
919
  type: type.id,
833
920
  location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
834
921
  flags,
@@ -840,7 +927,7 @@ export class Checker {
840
927
  async signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags) {
841
928
  const binaryData = await this.client.apiRequestBinary("signatureToSignatureDeclaration", {
842
929
  snapshot: this.snapshotId,
843
- project: this.projectId,
930
+ project: this.project.id,
844
931
  signature: signature.id,
845
932
  kind,
846
933
  location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
@@ -853,7 +940,7 @@ export class Checker {
853
940
  async typeToString(type, enclosingDeclaration, flags) {
854
941
  return this.client.apiRequest("typeToString", {
855
942
  snapshot: this.snapshotId,
856
- project: this.projectId,
943
+ project: this.project.id,
857
944
  type: type.id,
858
945
  location: enclosingDeclaration ? getNodeId(enclosingDeclaration) : undefined,
859
946
  flags,
@@ -862,28 +949,28 @@ export class Checker {
862
949
  async isContextSensitive(node) {
863
950
  return this.client.apiRequest("isContextSensitive", {
864
951
  snapshot: this.snapshotId,
865
- project: this.projectId,
952
+ project: this.project.id,
866
953
  location: getNodeId(node),
867
954
  });
868
955
  }
869
956
  async isArrayType(type) {
870
957
  return this.client.apiRequest("isArrayType", {
871
958
  snapshot: this.snapshotId,
872
- project: this.projectId,
959
+ project: this.project.id,
873
960
  type: type.id,
874
961
  });
875
962
  }
876
963
  async isTupleType(type) {
877
964
  return this.client.apiRequest("isTupleType", {
878
965
  snapshot: this.snapshotId,
879
- project: this.projectId,
966
+ project: this.project.id,
880
967
  type: type.id,
881
968
  });
882
969
  }
883
970
  async getReturnTypeOfSignature(signature) {
884
971
  const data = await this.client.apiRequest("getReturnTypeOfSignature", {
885
972
  snapshot: this.snapshotId,
886
- project: this.projectId,
973
+ project: this.project.id,
887
974
  signature: signature.id,
888
975
  });
889
976
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -891,7 +978,7 @@ export class Checker {
891
978
  async getRestTypeOfSignature(signature) {
892
979
  const data = await this.client.apiRequest("getRestTypeOfSignature", {
893
980
  snapshot: this.snapshotId,
894
- project: this.projectId,
981
+ project: this.project.id,
895
982
  signature: signature.id,
896
983
  });
897
984
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -899,7 +986,7 @@ export class Checker {
899
986
  async getTypePredicateOfSignature(signature) {
900
987
  const data = await this.client.apiRequest("getTypePredicateOfSignature", {
901
988
  snapshot: this.snapshotId,
902
- project: this.projectId,
989
+ project: this.project.id,
903
990
  signature: signature.id,
904
991
  });
905
992
  if (!data)
@@ -918,7 +1005,7 @@ export class Checker {
918
1005
  async getBaseTypes(type) {
919
1006
  const data = await this.client.apiRequest("getBaseTypes", {
920
1007
  snapshot: this.snapshotId,
921
- project: this.projectId,
1008
+ project: this.project.id,
922
1009
  type: type.id,
923
1010
  });
924
1011
  return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
@@ -926,7 +1013,7 @@ export class Checker {
926
1013
  async getApparentType(type) {
927
1014
  const data = await this.client.apiRequest("getApparentType", {
928
1015
  snapshot: this.snapshotId,
929
- project: this.projectId,
1016
+ project: this.project.id,
930
1017
  type: type.id,
931
1018
  });
932
1019
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -934,7 +1021,7 @@ export class Checker {
934
1021
  async getPropertiesOfType(type) {
935
1022
  const data = await this.client.apiRequest("getPropertiesOfType", {
936
1023
  snapshot: this.snapshotId,
937
- project: this.projectId,
1024
+ project: this.project.id,
938
1025
  type: type.id,
939
1026
  });
940
1027
  return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
@@ -942,7 +1029,7 @@ export class Checker {
942
1029
  async getIndexInfosOfType(type) {
943
1030
  const data = await this.client.apiRequest("getIndexInfosOfType", {
944
1031
  snapshot: this.snapshotId,
945
- project: this.projectId,
1032
+ project: this.project.id,
946
1033
  type: type.id,
947
1034
  });
948
1035
  if (!data)
@@ -951,7 +1038,7 @@ export class Checker {
951
1038
  keyType: this.objectRegistry.getOrCreateType(d.keyType),
952
1039
  valueType: this.objectRegistry.getOrCreateType(d.valueType),
953
1040
  isReadonly: d.isReadonly ?? false,
954
- declaration: d.declaration ? new NodeHandle(d.declaration) : undefined,
1041
+ declaration: d.declaration ? new NodeHandle(d.declaration, this.project) : undefined,
955
1042
  }));
956
1043
  }
957
1044
  /**
@@ -961,7 +1048,7 @@ export class Checker {
961
1048
  async getConstraintOfTypeParameter(type) {
962
1049
  const data = await this.client.apiRequest("getConstraintOfTypeParameter", {
963
1050
  snapshot: this.snapshotId,
964
- project: this.projectId,
1051
+ project: this.project.id,
965
1052
  type: type.id,
966
1053
  });
967
1054
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -969,7 +1056,7 @@ export class Checker {
969
1056
  async getBaseConstraintOfType(type) {
970
1057
  const data = await this.client.apiRequest("getBaseConstraintOfType", {
971
1058
  snapshot: this.snapshotId,
972
- project: this.projectId,
1059
+ project: this.project.id,
973
1060
  type: type.id,
974
1061
  });
975
1062
  return data ? this.objectRegistry.getOrCreateType(data) : undefined;
@@ -977,7 +1064,7 @@ export class Checker {
977
1064
  async getPropertyOfType(type, name) {
978
1065
  const data = await this.client.apiRequest("getPropertyOfType", {
979
1066
  snapshot: this.snapshotId,
980
- project: this.projectId,
1067
+ project: this.project.id,
981
1068
  type: type.id,
982
1069
  name,
983
1070
  });
@@ -986,7 +1073,7 @@ export class Checker {
986
1073
  async getConstantValue(node) {
987
1074
  const data = await this.client.apiRequest("getConstantValue", {
988
1075
  snapshot: this.snapshotId,
989
- project: this.projectId,
1076
+ project: this.project.id,
990
1077
  location: getNodeId(node),
991
1078
  });
992
1079
  return data ?? undefined;
@@ -994,7 +1081,7 @@ export class Checker {
994
1081
  async getSignatureFromDeclaration(node) {
995
1082
  const data = await this.client.apiRequest("getSignatureFromDeclaration", {
996
1083
  snapshot: this.snapshotId,
997
- project: this.projectId,
1084
+ project: this.project.id,
998
1085
  location: getNodeId(node),
999
1086
  });
1000
1087
  return data ? this.objectRegistry.getOrCreateSignature(data) : undefined;
@@ -1002,31 +1089,69 @@ export class Checker {
1002
1089
  async getExportSpecifierLocalTargetSymbol(node) {
1003
1090
  const data = await this.client.apiRequest("getExportSpecifierLocalTargetSymbol", {
1004
1091
  snapshot: this.snapshotId,
1005
- project: this.projectId,
1092
+ project: this.project.id,
1006
1093
  location: getNodeId(node),
1007
1094
  });
1008
1095
  return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1009
1096
  }
1097
+ /**
1098
+ * Follow all aliases to get the original symbol. Always returns a symbol; for
1099
+ * an unresolved alias the checker yields the unknown symbol (use
1100
+ * {@link Checker.isUnknownSymbol} to detect it).
1101
+ */
1010
1102
  async getAliasedSymbol(symbol) {
1011
1103
  const data = await this.client.apiRequest("getAliasedSymbol", {
1012
1104
  snapshot: this.snapshotId,
1013
- project: this.projectId,
1105
+ project: this.project.id,
1014
1106
  symbol: symbol.id,
1015
1107
  });
1016
- return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1108
+ if (!data)
1109
+ throw new Error(`getAliasedSymbol returned no symbol for symbol ${symbol.id}`);
1110
+ return this.objectRegistry.getOrCreateSymbol(data);
1017
1111
  }
1018
1112
  async getImmediateAliasedSymbol(symbol) {
1019
1113
  const data = await this.client.apiRequest("getImmediateAliasedSymbol", {
1020
1114
  snapshot: this.snapshotId,
1021
- project: this.projectId,
1115
+ project: this.project.id,
1022
1116
  symbol: symbol.id,
1023
1117
  });
1024
1118
  return data ? this.objectRegistry.getOrCreateSymbol(data) : undefined;
1025
1119
  }
1120
+ /**
1121
+ * Fetch (once, then cache) the handle ids of the per-checker singleton
1122
+ * symbols (unknown, undefined, arguments). These ids are stable for the life
1123
+ * of the project's checker, so identity checks against them are local after
1124
+ * the first call.
1125
+ */
1126
+ getWellKnownSymbols() {
1127
+ return this.wellKnownSymbols ??= this.client.apiRequest("getWellKnownSymbols", {
1128
+ snapshot: this.snapshotId,
1129
+ project: this.project.id,
1130
+ });
1131
+ }
1132
+ /**
1133
+ * Returns `true` if the symbol is the checker's "unknown" symbol (e.g. the
1134
+ * result of {@link Checker.getAliasedSymbol} on an unresolved alias).
1135
+ */
1136
+ async isUnknownSymbol(symbol) {
1137
+ return symbol.id === (await this.getWellKnownSymbols()).unknown;
1138
+ }
1139
+ /**
1140
+ * Returns `true` if the symbol is the checker's "undefined" symbol.
1141
+ */
1142
+ async isUndefinedSymbol(symbol) {
1143
+ return symbol.id === (await this.getWellKnownSymbols()).undefined;
1144
+ }
1145
+ /**
1146
+ * Returns `true` if the symbol is the checker's "arguments" symbol.
1147
+ */
1148
+ async isArgumentsSymbol(symbol) {
1149
+ return symbol.id === (await this.getWellKnownSymbols()).arguments;
1150
+ }
1026
1151
  async getExportsOfModule(symbol) {
1027
1152
  const data = await this.client.apiRequest("getExportsOfModule", {
1028
1153
  snapshot: this.snapshotId,
1029
- project: this.projectId,
1154
+ project: this.project.id,
1030
1155
  symbol: symbol.id,
1031
1156
  });
1032
1157
  return data ? data.map(d => this.objectRegistry.getOrCreateSymbol(d)) : [];
@@ -1034,7 +1159,7 @@ export class Checker {
1034
1159
  async getMemberInModuleExports(symbol, name) {
1035
1160
  const data = await this.client.apiRequest("getMemberInModuleExports", {
1036
1161
  snapshot: this.snapshotId,
1037
- project: this.projectId,
1162
+ project: this.project.id,
1038
1163
  symbol: symbol.id,
1039
1164
  name,
1040
1165
  });
@@ -1043,7 +1168,7 @@ export class Checker {
1043
1168
  async getJsDocTagsOfSymbol(symbol) {
1044
1169
  const data = await this.client.apiRequest("getJsDocTags", {
1045
1170
  snapshot: this.snapshotId,
1046
- project: this.projectId,
1171
+ project: this.project.id,
1047
1172
  symbol: symbol.id,
1048
1173
  });
1049
1174
  return data ?? [];
@@ -1051,7 +1176,7 @@ export class Checker {
1051
1176
  async getDocumentationCommentOfSymbol(symbol) {
1052
1177
  return this.client.apiRequest("getDocumentationComment", {
1053
1178
  snapshot: this.snapshotId,
1054
- project: this.projectId,
1179
+ project: this.project.id,
1055
1180
  symbol: symbol.id,
1056
1181
  });
1057
1182
  }
@@ -1061,7 +1186,7 @@ export class Checker {
1061
1186
  async getTypeArguments(type) {
1062
1187
  const data = await this.client.apiRequest("getTypeArguments", {
1063
1188
  snapshot: this.snapshotId,
1064
- project: this.projectId,
1189
+ project: this.project.id,
1065
1190
  type: type.id,
1066
1191
  });
1067
1192
  return data ? data.map(d => this.objectRegistry.getOrCreateType(d)) : [];
@@ -1082,20 +1207,28 @@ export class Emitter {
1082
1207
  }
1083
1208
  }
1084
1209
  export class NodeHandle {
1210
+ /**
1211
+ * The project this handle was produced in, used as the default for {@link resolve}.
1212
+ * Node handles are only meaningful within a project's program, so the producing project
1213
+ * is remembered so callers don't have to pass it explicitly.
1214
+ */
1215
+ canonicalProject;
1085
1216
  index;
1086
1217
  kind;
1087
1218
  path;
1088
- constructor(handle) {
1219
+ constructor(handle, canonicalProject) {
1089
1220
  const parsed = parseNodeHandle(handle);
1090
1221
  this.index = parsed.index;
1091
1222
  this.kind = parsed.kind;
1092
1223
  this.path = parsed.path;
1224
+ this.canonicalProject = canonicalProject;
1093
1225
  }
1094
1226
  /**
1095
- * Resolve this handle to the actual AST node by fetching the source file
1096
- * from the given project and looking up the node by index.
1227
+ * Resolve this handle to the actual AST node by fetching the source file from a project
1228
+ * and looking up the node by index. If no project is passed, the project that produced
1229
+ * the handle is used.
1097
1230
  */
1098
- async resolve(project) {
1231
+ async resolve(project = this.canonicalProject) {
1099
1232
  const sourceFile = await project.program.getSourceFile(this.path);
1100
1233
  if (!sourceFile) {
1101
1234
  return undefined;
@@ -1105,7 +1238,16 @@ export class NodeHandle {
1105
1238
  }
1106
1239
  export class Symbol {
1107
1240
  objectRegistry;
1241
+ /**
1242
+ * The project this symbol was first observed in, used as the default project for
1243
+ * lookups that need a project context (members/exports/parent). Symbols are shared
1244
+ * snapshot-wide, so these lookups can otherwise be ambiguous about which project to use.
1245
+ */
1246
+ canonicalProject;
1108
1247
  id;
1248
+ /** The escaped (`__String`) name, used as the key in member/export tables. */
1249
+ escapedName;
1250
+ /** The display name (escaped underscores removed). */
1109
1251
  name;
1110
1252
  flags;
1111
1253
  checkFlags;
@@ -1113,32 +1255,56 @@ export class Symbol {
1113
1255
  valueDeclaration;
1114
1256
  parent;
1115
1257
  exportSymbol;
1258
+ membersCache;
1259
+ exportsCache;
1116
1260
  constructor(data, objectRegistry) {
1117
1261
  this.objectRegistry = objectRegistry;
1118
1262
  this.id = data.id;
1119
- this.name = data.name;
1263
+ this.escapedName = data.name;
1264
+ this.name = unescapeLeadingUnderscores(data.name);
1120
1265
  this.flags = data.flags;
1121
1266
  this.checkFlags = data.checkFlags;
1122
- this.declarations = (data.declarations ?? []).map(d => new NodeHandle(d));
1123
- this.valueDeclaration = data.valueDeclaration ? new NodeHandle(data.valueDeclaration) : undefined;
1267
+ const canonicalProject = objectRegistry.getProject(data.project);
1268
+ if (!canonicalProject) {
1269
+ throw new Error(`Symbol ${data.id} references unknown canonical project '${data.project}'`);
1270
+ }
1271
+ this.canonicalProject = canonicalProject;
1272
+ this.declarations = (data.declarations ?? []).map(d => new NodeHandle(d, canonicalProject));
1273
+ this.valueDeclaration = data.valueDeclaration ? new NodeHandle(data.valueDeclaration, canonicalProject) : undefined;
1124
1274
  if (data.parent !== undefined)
1125
1275
  this.parent = data.parent;
1126
1276
  if (data.exportSymbol !== undefined)
1127
1277
  this.exportSymbol = data.exportSymbol;
1128
1278
  }
1129
1279
  async getParent() {
1130
- return this.objectRegistry.fetchSymbol(this, "getParentOfSymbol", this.parent);
1280
+ return this.objectRegistry.fetchSymbol(this, "getParentOfSymbol", this.parent, this.canonicalProject.id);
1131
1281
  }
1132
- async getMembers() {
1133
- return this.objectRegistry.fetchSymbols(this, "getMembersOfSymbol");
1282
+ /**
1283
+ * Get this symbol's members keyed by escaped name. The result is cached on
1284
+ * the symbol, so repeated calls do not round-trip to the server.
1285
+ */
1286
+ getMembers() {
1287
+ return this.membersCache ??= this.fetchSymbolTable("getMembersOfSymbol");
1134
1288
  }
1135
- async getExports() {
1136
- return this.objectRegistry.fetchSymbols(this, "getExportsOfSymbol");
1289
+ /**
1290
+ * Get this symbol's exports keyed by escaped name. The result is cached on
1291
+ * the symbol, so repeated calls do not round-trip to the server.
1292
+ */
1293
+ getExports() {
1294
+ return this.exportsCache ??= this.fetchSymbolTable("getExportsOfSymbol");
1295
+ }
1296
+ async fetchSymbolTable(method) {
1297
+ const symbols = await this.objectRegistry.fetchSymbols(this, method, undefined, this.canonicalProject.id);
1298
+ const table = new Map();
1299
+ for (const symbol of symbols) {
1300
+ table.set(symbol.escapedName, symbol);
1301
+ }
1302
+ return table;
1137
1303
  }
1138
1304
  async getExportSymbol() {
1139
1305
  if (!this.exportSymbol)
1140
1306
  return this;
1141
- return this.objectRegistry.fetchSymbol(this, "getExportSymbolOfSymbol", this.exportSymbol);
1307
+ return this.objectRegistry.fetchSymbol(this, "getExportSymbolOfSymbol", this.exportSymbol, this.canonicalProject.id);
1142
1308
  }
1143
1309
  async getJsDocTags(checker) {
1144
1310
  return checker.getJsDocTagsOfSymbol(this);
@@ -1292,6 +1458,19 @@ class TypeObject {
1292
1458
  this.falseType = result.id;
1293
1459
  return result;
1294
1460
  }
1461
+ /**
1462
+ * Get the base types of this type. Returns `undefined` for any type that is
1463
+ * not a class or interface.
1464
+ */
1465
+ async getBaseTypes() {
1466
+ if (!this.isClassOrInterface()) {
1467
+ return undefined;
1468
+ }
1469
+ return this.objectRegistry.fetchBaseTypes(this);
1470
+ }
1471
+ isClassOrInterface() {
1472
+ return isClassOrInterfaceType(this);
1473
+ }
1295
1474
  isUnionType() {
1296
1475
  return isUnionType(this);
1297
1476
  }
@@ -1304,6 +1483,9 @@ class TypeObject {
1304
1483
  isIntrinsicType() {
1305
1484
  return isIntrinsicType(this);
1306
1485
  }
1486
+ isErrorType() {
1487
+ return isErrorType(this);
1488
+ }
1307
1489
  isLiteralType() {
1308
1490
  return isLiteralType(this);
1309
1491
  }
@@ -1356,9 +1538,21 @@ export function isIntersectionType(type) {
1356
1538
  export function isObjectType(type) {
1357
1539
  return (type.flags & TypeFlags.Object) !== 0;
1358
1540
  }
1541
+ export function isClassOrInterfaceType(type) {
1542
+ return isObjectType(type) && (type.objectFlags & ObjectFlags.ClassOrInterface) !== 0;
1543
+ }
1359
1544
  export function isIntrinsicType(type) {
1360
1545
  return (type.flags & TypeFlags.Intrinsic) !== 0;
1361
1546
  }
1547
+ /**
1548
+ * Whether this is the error type — the placeholder the checker produces when a
1549
+ * type cannot be determined (e.g. an unresolved reference). It is an intrinsic
1550
+ * type named `"error"` (this covers both the singleton error type and the
1551
+ * per-alias error types manufactured for unresolved type alias references).
1552
+ */
1553
+ export function isErrorType(type) {
1554
+ return isIntrinsicType(type) && type.intrinsicName === "error";
1555
+ }
1362
1556
  export function isLiteralType(type) {
1363
1557
  return (type.flags & TypeFlags.Literal) !== 0;
1364
1558
  }
@@ -1410,11 +1604,11 @@ export class Signature {
1410
1604
  parameters;
1411
1605
  thisParameter;
1412
1606
  target;
1413
- constructor(data, objectRegistry) {
1607
+ constructor(data, project, objectRegistry) {
1414
1608
  this.id = data.id;
1415
1609
  this.flags = data.flags;
1416
1610
  this.objectRegistry = objectRegistry;
1417
- this.declaration = data.declaration ? new NodeHandle(data.declaration) : undefined;
1611
+ this.declaration = data.declaration ? new NodeHandle(data.declaration, project) : undefined;
1418
1612
  this.typeParameters = data.typeParameters ?? [];
1419
1613
  this.parameters = data.parameters ?? [];
1420
1614
  this.thisParameter = data.thisParameter;