typescript 7.1.0-dev.20260929.1 → 7.1.0-dev.20260930.4

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 (59) hide show
  1. package/dist/api/async/api.d.ts +58 -35
  2. package/dist/api/async/api.d.ts.map +1 -1
  3. package/dist/api/async/api.js +219 -117
  4. package/dist/api/async/api.js.map +1 -1
  5. package/dist/api/async/client.d.ts.map +1 -1
  6. package/dist/api/async/client.js +21 -35
  7. package/dist/api/async/client.js.map +1 -1
  8. package/dist/api/fs.d.ts +39 -13
  9. package/dist/api/fs.d.ts.map +1 -1
  10. package/dist/api/fs.js +13 -108
  11. package/dist/api/fs.js.map +1 -1
  12. package/dist/api/fsCallbacks.d.ts +27 -0
  13. package/dist/api/fsCallbacks.d.ts.map +1 -0
  14. package/dist/api/fsCallbacks.js +111 -0
  15. package/dist/api/fsCallbacks.js.map +1 -0
  16. package/dist/api/node/node.d.ts +8 -2
  17. package/dist/api/node/node.d.ts.map +1 -1
  18. package/dist/api/node/node.infrastructure.d.ts +1 -0
  19. package/dist/api/node/node.infrastructure.d.ts.map +1 -1
  20. package/dist/api/node/node.infrastructure.js +8 -1
  21. package/dist/api/node/node.infrastructure.js.map +1 -1
  22. package/dist/api/node/node.js +14 -2
  23. package/dist/api/node/node.js.map +1 -1
  24. package/dist/api/options.d.ts +5 -3
  25. package/dist/api/options.d.ts.map +1 -1
  26. package/dist/api/options.js +10 -0
  27. package/dist/api/options.js.map +1 -1
  28. package/dist/api/path.d.ts +1 -0
  29. package/dist/api/path.d.ts.map +1 -1
  30. package/dist/api/path.js +3 -0
  31. package/dist/api/path.js.map +1 -1
  32. package/dist/api/proto.d.ts +26 -3
  33. package/dist/api/proto.d.ts.map +1 -1
  34. package/dist/api/proto.generated.d.ts +72 -34
  35. package/dist/api/proto.generated.d.ts.map +1 -1
  36. package/dist/api/proto.generated.js +2 -0
  37. package/dist/api/proto.generated.js.map +1 -1
  38. package/dist/api/proto.js +20 -0
  39. package/dist/api/proto.js.map +1 -1
  40. package/dist/api/sourceFileCache.d.ts +29 -13
  41. package/dist/api/sourceFileCache.d.ts.map +1 -1
  42. package/dist/api/sourceFileCache.js +97 -16
  43. package/dist/api/sourceFileCache.js.map +1 -1
  44. package/dist/api/sync/api.d.ts +64 -44
  45. package/dist/api/sync/api.d.ts.map +1 -1
  46. package/dist/api/sync/api.js +339 -191
  47. package/dist/api/sync/api.js.map +1 -1
  48. package/dist/api/sync/client.d.ts.map +1 -1
  49. package/dist/api/sync/client.js +11 -26
  50. package/dist/api/sync/client.js.map +1 -1
  51. package/dist/enums/symbolOwnerKind.d.ts +2 -0
  52. package/dist/enums/symbolOwnerKind.d.ts.map +1 -0
  53. package/dist/enums/symbolOwnerKind.enum.d.ts +5 -0
  54. package/dist/enums/symbolOwnerKind.enum.d.ts.map +1 -0
  55. package/dist/enums/symbolOwnerKind.enum.js +7 -0
  56. package/dist/enums/symbolOwnerKind.enum.js.map +1 -0
  57. package/dist/enums/symbolOwnerKind.js +7 -0
  58. package/dist/enums/symbolOwnerKind.js.map +1 -0
  59. package/package.json +9 -9
@@ -15,21 +15,22 @@ import { ScriptKind } from "#enums/scriptKind";
15
15
  import { SignatureFlags } from "#enums/signatureFlags";
16
16
  import { SignatureKind } from "#enums/signatureKind";
17
17
  import { SymbolFlags } from "#enums/symbolFlags";
18
+ import { SymbolOwnerKind } from "#enums/symbolOwnerKind";
18
19
  import { TypeFlags } from "#enums/typeFlags";
19
20
  import { TypeFormatFlags } from "#enums/typeFormatFlags";
20
21
  import { TypePredicateKind } from "#enums/typePredicateKind";
21
22
  import { ModifierFlags, unescapeLeadingUnderscores, } from "../../ast/index.js";
22
23
  import { assertNever } from "../../internal/utils.js";
23
24
  import { encodeNode, uint8ArrayToBase64, } from "../node/encoder.js";
24
- import { decodeNode, getNodeId, parseNodeHandle, readParseOptionsKey, readSourceFileHash, readSourceFileLease, RemoteSourceFile, } from "../node/node.js";
25
+ import { decodeNode, getNodeId, parseNodeHandle, readSourceFileLease, RemoteSourceFile, } from "../node/node.js";
25
26
  import { Wtf8Decoder } from "../node/wtf8.js";
26
27
  import { createGetCanonicalFileName, toPath, } from "../path.js";
27
- import { resolveFileName, toCreateSnapshotRequest, } from "../proto.js";
28
- import { SourceFileCache } from "../sourceFileCache.js";
28
+ import { resolveFileName, toCreateSnapshotRequest, validateSymbolResponse, } from "../proto.js";
29
+ import { SourceFileCache, } from "../sourceFileCache.js";
29
30
  import { Client, } from "./client.js";
30
31
  export { formatDiagnostics, formatDiagnosticsWithColorAndContext } from "../diagnosticFormatter.js";
31
32
  export { documentURIToFileName, fileNameToDocumentURI } from "../path.js";
32
- export { CheckFlags, CompletionItemKind, DiagnosticCategory, ElementFlags, EmitOnly, IndexKind, JsxEmit, ModifierFlags, ModuleKind, ModuleResolutionKind, NodeBuilderFlags, ObjectFlags, ScriptKind, SignatureFlags, SignatureKind, SymbolFlags, TypeFlags, TypeFormatFlags, TypePredicateKind };
33
+ export { CheckFlags, CompletionItemKind, DiagnosticCategory, ElementFlags, EmitOnly, IndexKind, JsxEmit, ModifierFlags, ModuleKind, ModuleResolutionKind, NodeBuilderFlags, ObjectFlags, ScriptKind, SignatureFlags, SignatureKind, SymbolFlags, SymbolOwnerKind, TypeFlags, TypeFormatFlags, TypePredicateKind };
33
34
  let nextModuleResolutionCallbackId = 0;
34
35
  function registerModuleResolutionCallback(client, callback, getSnapshot) {
35
36
  const name = `resolveModuleName/${++nextModuleResolutionCallbackId}`;
@@ -259,18 +260,41 @@ export class API {
259
260
  return owner.retainSourceFileResponse(data);
260
261
  });
261
262
  }
263
+ /**
264
+ * Retain an ordinary remote source file independently of the snapshot or lease that produced it.
265
+ */
266
+ get retainSourceFile() {
267
+ const owner = this;
268
+ return cacheGeneratorMethod(owner, "retainSourceFile", function (sourceFile) {
269
+ owner.ensureInitialized();
270
+ if (!(sourceFile instanceof RemoteSourceFile)) {
271
+ throw new TypeError("Only remote source files can be retained");
272
+ }
273
+ const cached = owner.sourceFileCache.get(sourceFile);
274
+ if (cached && cached !== sourceFile) {
275
+ throw new Error("Source file is no longer the canonical cached instance");
276
+ }
277
+ const result = owner.client.apiRequest("retainSourceFile", { file: sourceFileDescriptor(sourceFile) });
278
+ return owner.addSourceFileLease(sourceFile, result.lease);
279
+ }, function* (sourceFile) {
280
+ yield* owner.ensureInitialized.gen();
281
+ if (!(sourceFile instanceof RemoteSourceFile)) {
282
+ throw new TypeError("Only remote source files can be retained");
283
+ }
284
+ const cached = owner.sourceFileCache.get(sourceFile);
285
+ if (cached && cached !== sourceFile) {
286
+ throw new Error("Source file is no longer the canonical cached instance");
287
+ }
288
+ const result = yield* apiRequest("retainSourceFile", { file: sourceFileDescriptor(sourceFile) });
289
+ return owner.addSourceFileLease(sourceFile, result.lease);
290
+ });
291
+ }
262
292
  retainSourceFileResponse(data) {
263
293
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
264
294
  const lease = readSourceFileLease(view);
265
295
  try {
266
296
  const decoded = new RemoteSourceFile(data, this.decoder, this.client.getTimingCollector());
267
- const sourceFile = this.sourceFileCache.setForLease(decoded.path, decoded, readParseOptionsKey(view), readSourceFileHash(view), lease);
268
- const retained = new RetainedSourceFile(sourceFile, lease, this.client, () => {
269
- this.activeSourceFileLeases.delete(lease);
270
- this.sourceFileCache.releaseLease(lease);
271
- });
272
- this.activeSourceFileLeases.set(lease, retained);
273
- return retained;
297
+ return this.addSourceFileLease(decoded, lease);
274
298
  }
275
299
  catch (error) {
276
300
  try {
@@ -280,6 +304,15 @@ export class API {
280
304
  throw error;
281
305
  }
282
306
  }
307
+ addSourceFileLease(sourceFile, lease) {
308
+ const cached = this.sourceFileCache.setForLease(sourceFile, lease);
309
+ const retained = new RetainedSourceFile(cached, lease, this.client, () => {
310
+ this.activeSourceFileLeases.delete(lease);
311
+ this.sourceFileCache.releaseLease(lease);
312
+ });
313
+ this.activeSourceFileLeases.set(lease, retained);
314
+ return retained;
315
+ }
283
316
  get transpileModule() {
284
317
  const owner = this;
285
318
  return cacheGeneratorMethod(owner, "transpileModule", function (input, options = {}) {
@@ -659,6 +692,16 @@ export class API {
659
692
  });
660
693
  }
661
694
  }
695
+ function sourceFileDescriptor(sourceFile) {
696
+ return {
697
+ fileName: sourceFile.fileName,
698
+ path: sourceFile.path,
699
+ contentHash: sourceFile.contentHash,
700
+ parseOptionsKey: sourceFile.parseOptionsKey,
701
+ scriptKind: sourceFile.scriptKind,
702
+ nodeId: sourceFile.nodeId,
703
+ };
704
+ }
662
705
  /** An independently retained source file and its disposable remote-lifetime lease. */
663
706
  export class RetainedSourceFile {
664
707
  sourceFile;
@@ -780,7 +823,7 @@ export class Snapshot {
780
823
  projectDataMap.set(projectData.id, projectData);
781
824
  }
782
825
  this.projectDataMap = new Map([...projectDataMap].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
783
- this.snapshotRegistry = new SnapshotObjectRegistry(client, this.id, projectId => this.projectMap.get(projectId));
826
+ this.snapshotRegistry = new SnapshotObjectRegistry(this.id);
784
827
  for (const projData of this.projectDataMap.values()) {
785
828
  const project = new Project(projData, this.id, client, sourceFileCache, toPath, formatDiagnosticsHost, this.snapshotRegistry);
786
829
  this.projectMap.set(projData.id, project);
@@ -974,23 +1017,28 @@ export class ModuleResolver {
974
1017
  }
975
1018
  class SnapshotObjectRegistry {
976
1019
  symbols = new Map();
977
- client;
1020
+ projectRegistries = new Map();
978
1021
  snapshotId;
979
- resolveProject;
980
- constructor(client, snapshotId, resolveProject) {
981
- this.client = client;
1022
+ constructor(snapshotId) {
982
1023
  this.snapshotId = snapshotId;
983
- this.resolveProject = resolveProject;
984
1024
  }
985
- /** Resolve a project ID to its Project within this snapshot. */
986
- getProject(projectId) {
987
- return this.resolveProject(projectId);
1025
+ addProjectRegistry(registry) {
1026
+ this.projectRegistries.set(registry.project.id, registry);
988
1027
  }
989
1028
  getOrCreateSymbol(data) {
990
- let symbol = this.symbols.get(data.id);
1029
+ const reference = data.reference;
1030
+ if (reference.kind !== SymbolOwnerKind.Snapshot)
1031
+ throw new Error(`Symbol ${reference.id} is not snapshot-owned`);
1032
+ let symbol = this.symbols.get(reference.id);
991
1033
  if (!symbol) {
992
- symbol = new Symbol(data, this);
993
- this.symbols.set(data.id, symbol);
1034
+ if (reference.snapshot !== this.snapshotId) {
1035
+ throw new Error(`Symbol ${reference.id} belongs to snapshot ${reference.snapshot}, not ${this.snapshotId}`);
1036
+ }
1037
+ const registry = this.projectRegistries.get(reference.project);
1038
+ if (!registry)
1039
+ throw new Error(`Symbol ${reference.id} references unknown project '${reference.project}'`);
1040
+ symbol = new Symbol(data, { kind: SymbolOwnerKind.Snapshot, registry });
1041
+ this.symbols.set(reference.id, symbol);
994
1042
  }
995
1043
  return symbol;
996
1044
  }
@@ -1000,109 +1048,49 @@ class SnapshotObjectRegistry {
1000
1048
  clear() {
1001
1049
  this.symbols.clear();
1002
1050
  }
1003
- get fetchSymbol() {
1004
- const owner = this;
1005
- return cacheGeneratorMethod(owner, "fetchSymbol", function (source, method, handle, projectId) {
1006
- if (!handle)
1007
- return undefined;
1008
- const cached = owner.getSymbol(handle);
1009
- if (cached)
1010
- return cached;
1011
- const data = owner.client.apiRequest(method, {
1012
- snapshot: owner.snapshotId,
1013
- project: projectId,
1014
- objectId: source.id,
1015
- });
1016
- if (!data)
1017
- throw new Error(`${method} returned null symbol for ${source.constructor.name} ${source.id}`);
1018
- return owner.getOrCreateSymbol(data);
1019
- }, function* (source, method, handle, projectId) {
1020
- if (!handle)
1021
- return undefined;
1022
- const cached = owner.getSymbol(handle);
1023
- if (cached)
1024
- return cached;
1025
- const data = yield* apiRequest(method, {
1026
- snapshot: owner.snapshotId,
1027
- project: projectId,
1028
- objectId: source.id,
1029
- });
1030
- if (!data)
1031
- throw new Error(`${method} returned null symbol for ${source.constructor.name} ${source.id}`);
1032
- return owner.getOrCreateSymbol(data);
1033
- });
1034
- }
1035
- get fetchSymbols() {
1036
- const owner = this;
1037
- return cacheGeneratorMethod(owner, "fetchSymbols", function (source, method, handles, projectId) {
1038
- if (handles) {
1039
- const result = new Array(handles.length);
1040
- let allCached = true;
1041
- for (let i = 0; i < handles.length; i++) {
1042
- const cached = owner.getSymbol(handles[i]);
1043
- if (!cached) {
1044
- allCached = false;
1045
- break;
1046
- }
1047
- result[i] = cached;
1048
- }
1049
- if (allCached)
1050
- return result;
1051
- }
1052
- const symbolData = owner.client.apiRequest(method, {
1053
- snapshot: owner.snapshotId,
1054
- project: projectId,
1055
- objectId: source.id,
1056
- });
1057
- if (symbolData == null)
1058
- return [];
1059
- else
1060
- return symbolData.map(data => owner.getOrCreateSymbol(data));
1061
- }, function* (source, method, handles, projectId) {
1062
- if (handles) {
1063
- const result = new Array(handles.length);
1064
- let allCached = true;
1065
- for (let i = 0; i < handles.length; i++) {
1066
- const cached = owner.getSymbol(handles[i]);
1067
- if (!cached) {
1068
- allCached = false;
1069
- break;
1070
- }
1071
- result[i] = cached;
1072
- }
1073
- if (allCached)
1074
- return result;
1075
- }
1076
- const symbolData = yield* apiRequest(method, {
1077
- snapshot: owner.snapshotId,
1078
- project: projectId,
1079
- objectId: source.id,
1080
- });
1081
- if (symbolData == null)
1082
- return [];
1083
- else
1084
- return symbolData.map(data => owner.getOrCreateSymbol(data));
1085
- });
1086
- }
1087
1051
  }
1088
1052
  class ProjectObjectRegistry {
1089
1053
  client;
1090
1054
  snapshotId;
1091
1055
  project;
1092
1056
  snapshotRegistry;
1057
+ sourceFileCache;
1093
1058
  types = new Map();
1094
1059
  signatures = new Map();
1095
- constructor(client, snapshotId, project, snapshotRegistry) {
1060
+ disposed = false;
1061
+ constructor(client, snapshotId, project, snapshotRegistry, sourceFileCache) {
1096
1062
  this.client = client;
1097
1063
  this.snapshotId = snapshotId;
1098
1064
  this.project = project;
1099
1065
  this.snapshotRegistry = snapshotRegistry;
1066
+ this.sourceFileCache = sourceFileCache;
1067
+ snapshotRegistry.addProjectRegistry(this);
1100
1068
  }
1101
1069
  getOrCreateSymbol(data) {
1102
- return this.snapshotRegistry.getOrCreateSymbol(data);
1103
- }
1104
- getSymbol(id) {
1105
- return this.snapshotRegistry.getSymbol(id);
1070
+ this.ensureNotDisposed();
1071
+ validateSymbolResponse(data);
1072
+ const reference = data.reference;
1073
+ if (reference.kind === SymbolOwnerKind.Snapshot) {
1074
+ return this.snapshotRegistry.getOrCreateSymbol(data);
1075
+ }
1076
+ const record = this.sourceFileCache.getOrCreateRecord(reference.file, this.snapshotId, this.project.id);
1077
+ return this.sourceFileCache.getOrCreateSymbol(record, reference.file, reference.id, () => new Symbol(data, {
1078
+ kind: SymbolOwnerKind.File,
1079
+ owner: { record, cache: this.sourceFileCache, client: this.client },
1080
+ }));
1081
+ }
1082
+ /** Find an already-interned symbol and retain its file record for this registry. */
1083
+ getCachedSymbol(reference) {
1084
+ this.ensureNotDisposed();
1085
+ if (reference.file === undefined) {
1086
+ return this.snapshotRegistry.getSymbol(reference.id);
1087
+ }
1088
+ const record = this.sourceFileCache.findRecord(reference.file);
1089
+ const symbol = record?.symbols.get(reference.id);
1090
+ if (record && symbol) {
1091
+ this.sourceFileCache.retainRecord(record, this.snapshotId, this.project.id);
1092
+ }
1093
+ return symbol;
1106
1094
  }
1107
1095
  getOrCreateType(data) {
1108
1096
  let type = this.types.get(data.id);
@@ -1130,9 +1118,14 @@ class ProjectObjectRegistry {
1130
1118
  return this.signatures.get(id);
1131
1119
  }
1132
1120
  clear() {
1121
+ this.disposed = true;
1133
1122
  this.types.clear();
1134
1123
  this.signatures.clear();
1135
1124
  }
1125
+ ensureNotDisposed() {
1126
+ if (this.disposed)
1127
+ throw new Error("Project object registry is disposed");
1128
+ }
1136
1129
  get fetchOptionalType() {
1137
1130
  const owner = this;
1138
1131
  return cacheGeneratorMethod(owner, "fetchOptionalType", function (source, method, handle) {
@@ -1185,10 +1178,38 @@ class ProjectObjectRegistry {
1185
1178
  }
1186
1179
  get fetchSymbol() {
1187
1180
  const owner = this;
1188
- return cacheGeneratorMethod(owner, "fetchSymbol", function (source, method, handle) {
1189
- return owner.snapshotRegistry.fetchSymbol(source, method, handle, owner.project.id);
1190
- }, function* (source, method, handle) {
1191
- return yield* owner.snapshotRegistry.fetchSymbol.gen(source, method, handle, owner.project.id);
1181
+ return cacheGeneratorMethod(owner, "fetchSymbol", function (source, method, reference) {
1182
+ if (!reference)
1183
+ return undefined;
1184
+ const cached = owner.getCachedSymbol(reference);
1185
+ if (cached)
1186
+ return cached;
1187
+ const data = source instanceof Symbol
1188
+ ? owner.client.apiRequest(method, { symbol: source.reference })
1189
+ : owner.client.apiRequest(method, {
1190
+ snapshot: owner.snapshotId,
1191
+ project: owner.project.id,
1192
+ objectId: source.id,
1193
+ });
1194
+ if (!data)
1195
+ throw new Error(`${method} returned null symbol for ${source.constructor.name} ${source.id}`);
1196
+ return owner.getOrCreateSymbol(data);
1197
+ }, function* (source, method, reference) {
1198
+ if (!reference)
1199
+ return undefined;
1200
+ const cached = owner.getCachedSymbol(reference);
1201
+ if (cached)
1202
+ return cached;
1203
+ const data = source instanceof Symbol
1204
+ ? yield* apiRequest(method, { symbol: source.reference })
1205
+ : yield* apiRequest(method, {
1206
+ snapshot: owner.snapshotId,
1207
+ project: owner.project.id,
1208
+ objectId: source.id,
1209
+ });
1210
+ if (!data)
1211
+ throw new Error(`${method} returned null symbol for ${source.constructor.name} ${source.id}`);
1212
+ return owner.getOrCreateSymbol(data);
1192
1213
  });
1193
1214
  }
1194
1215
  get fetchSignature() {
@@ -1277,10 +1298,54 @@ class ProjectObjectRegistry {
1277
1298
  }
1278
1299
  get fetchSymbols() {
1279
1300
  const owner = this;
1280
- return cacheGeneratorMethod(owner, "fetchSymbols", function (source, method, handles) {
1281
- return owner.snapshotRegistry.fetchSymbols(source, method, handles, owner.project.id);
1282
- }, function* (source, method, handles) {
1283
- return yield* owner.snapshotRegistry.fetchSymbols.gen(source, method, handles, owner.project.id);
1301
+ return cacheGeneratorMethod(owner, "fetchSymbols", function (source, method, references) {
1302
+ if (references) {
1303
+ const result = new Array(references.length);
1304
+ for (let i = 0; i < references.length; i++) {
1305
+ const cached = owner.getCachedSymbol(references[i]);
1306
+ if (!cached) {
1307
+ return owner.fetchSymbolsFromServer(source, method);
1308
+ }
1309
+ result[i] = cached;
1310
+ }
1311
+ return result;
1312
+ }
1313
+ return owner.fetchSymbolsFromServer(source, method);
1314
+ }, function* (source, method, references) {
1315
+ if (references) {
1316
+ const result = new Array(references.length);
1317
+ for (let i = 0; i < references.length; i++) {
1318
+ const cached = owner.getCachedSymbol(references[i]);
1319
+ if (!cached) {
1320
+ return yield* owner.fetchSymbolsFromServer.gen(source, method);
1321
+ }
1322
+ result[i] = cached;
1323
+ }
1324
+ return result;
1325
+ }
1326
+ return yield* owner.fetchSymbolsFromServer.gen(source, method);
1327
+ });
1328
+ }
1329
+ get fetchSymbolsFromServer() {
1330
+ const owner = this;
1331
+ return cacheGeneratorMethod(owner, "fetchSymbolsFromServer", function (source, method) {
1332
+ const data = source instanceof Symbol
1333
+ ? owner.client.apiRequest(method, { symbol: source.reference })
1334
+ : owner.client.apiRequest(method, {
1335
+ snapshot: owner.snapshotId,
1336
+ project: owner.project.id,
1337
+ objectId: source.id,
1338
+ });
1339
+ return data?.map(symbol => owner.getOrCreateSymbol(symbol)) ?? [];
1340
+ }, function* (source, method) {
1341
+ const data = source instanceof Symbol
1342
+ ? yield* apiRequest(method, { symbol: source.reference })
1343
+ : yield* apiRequest(method, {
1344
+ snapshot: owner.snapshotId,
1345
+ project: owner.project.id,
1346
+ objectId: source.id,
1347
+ });
1348
+ return data?.map(symbol => owner.getOrCreateSymbol(symbol)) ?? [];
1284
1349
  });
1285
1350
  }
1286
1351
  // getBaseTypes is a checker-level endpoint keyed by `type` (not `objectId`),
@@ -1465,7 +1530,7 @@ export class Project {
1465
1530
  this.client = client;
1466
1531
  this.snapshotId = snapshotId;
1467
1532
  this.program = new Program(snapshotId, this, client, sourceFileCache, toPath, formatDiagnosticsHost);
1468
- const objectRegistry = new ProjectObjectRegistry(client, snapshotId, this, snapshotRegistry);
1533
+ const objectRegistry = new ProjectObjectRegistry(client, snapshotId, this, snapshotRegistry, sourceFileCache);
1469
1534
  this.checker = new Checker(snapshotId, this, client, objectRegistry);
1470
1535
  this.languageService = new LanguageService(snapshotId, this, client, objectRegistry);
1471
1536
  }
@@ -1510,7 +1575,7 @@ export class LanguageService {
1510
1575
  case "importSymbol":
1511
1576
  const importSymbolAction = {
1512
1577
  kind: "importSymbol",
1513
- symbol: action.symbol.id,
1578
+ symbol: action.symbol.reference,
1514
1579
  };
1515
1580
  if (action.isValidTypeOnlyUseSite !== undefined) {
1516
1581
  importSymbolAction.isValidTypeOnlyUseSite = action.isValidTypeOnlyUseSite;
@@ -1533,7 +1598,7 @@ export class LanguageService {
1533
1598
  case "importSymbol":
1534
1599
  const importSymbolAction = {
1535
1600
  kind: "importSymbol",
1536
- symbol: action.symbol.id,
1601
+ symbol: action.symbol.reference,
1537
1602
  };
1538
1603
  if (action.isValidTypeOnlyUseSite !== undefined) {
1539
1604
  importSymbolAction.isValidTypeOnlyUseSite = action.isValidTypeOnlyUseSite;
@@ -1759,12 +1824,9 @@ export class Program {
1759
1824
  if (!binaryData) {
1760
1825
  return undefined;
1761
1826
  }
1762
- const view = new DataView(binaryData.buffer, binaryData.byteOffset, binaryData.byteLength);
1763
- const contentHash = readSourceFileHash(view);
1764
- const parseOptionsKey = readParseOptionsKey(view);
1765
1827
  // Create a new RemoteSourceFile and cache it (set returns existing if hash matches)
1766
- const sourceFile = new RemoteSourceFile(binaryData, owner.decoder, owner.client.getTimingCollector());
1767
- return owner.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, owner.snapshotId, owner.project.id);
1828
+ const decoded = new RemoteSourceFile(binaryData, owner.decoder, owner.client.getTimingCollector());
1829
+ return owner.sourceFileCache.set(decoded, owner.snapshotId, owner.project.id);
1768
1830
  }, function* (file) {
1769
1831
  const fileName = resolveFileName(file);
1770
1832
  const path = owner.toPath(fileName);
@@ -1782,12 +1844,9 @@ export class Program {
1782
1844
  if (!binaryData) {
1783
1845
  return undefined;
1784
1846
  }
1785
- const view = new DataView(binaryData.buffer, binaryData.byteOffset, binaryData.byteLength);
1786
- const contentHash = readSourceFileHash(view);
1787
- const parseOptionsKey = readParseOptionsKey(view);
1788
1847
  // Create a new RemoteSourceFile and cache it (set returns existing if hash matches)
1789
- const sourceFile = new RemoteSourceFile(binaryData, owner.decoder, owner.client.getTimingCollector());
1790
- return owner.sourceFileCache.set(path, sourceFile, parseOptionsKey, contentHash, owner.snapshotId, owner.project.id);
1848
+ const decoded = new RemoteSourceFile(binaryData, owner.decoder, owner.client.getTimingCollector());
1849
+ return owner.sourceFileCache.set(decoded, owner.snapshotId, owner.project.id);
1791
1850
  });
1792
1851
  }
1793
1852
  get getResolvedModule() {
@@ -2652,14 +2711,14 @@ export class Checker {
2652
2711
  const data = owner.client.apiRequest("getTypesOfSymbols", {
2653
2712
  snapshot: owner.snapshotId,
2654
2713
  project: owner.project.id,
2655
- symbols: symbolOrSymbols.map(s => s.id),
2714
+ symbols: symbolOrSymbols.map(symbol => symbol.reference),
2656
2715
  });
2657
2716
  return data.map(d => owner.objectRegistry.getOrCreateType(d));
2658
2717
  }
2659
2718
  const data = owner.client.apiRequest("getTypeOfSymbol", {
2660
2719
  snapshot: owner.snapshotId,
2661
2720
  project: owner.project.id,
2662
- symbol: symbolOrSymbols.id,
2721
+ symbol: symbolOrSymbols.reference,
2663
2722
  });
2664
2723
  return owner.objectRegistry.getOrCreateType(data);
2665
2724
  }
@@ -2668,14 +2727,14 @@ export class Checker {
2668
2727
  const data = yield* apiRequest("getTypesOfSymbols", {
2669
2728
  snapshot: owner.snapshotId,
2670
2729
  project: owner.project.id,
2671
- symbols: symbolOrSymbols.map(s => s.id),
2730
+ symbols: symbolOrSymbols.map(symbol => symbol.reference),
2672
2731
  });
2673
2732
  return data.map(d => owner.objectRegistry.getOrCreateType(d));
2674
2733
  }
2675
2734
  const data = yield* apiRequest("getTypeOfSymbol", {
2676
2735
  snapshot: owner.snapshotId,
2677
2736
  project: owner.project.id,
2678
- symbol: symbolOrSymbols.id,
2737
+ symbol: symbolOrSymbols.reference,
2679
2738
  });
2680
2739
  return owner.objectRegistry.getOrCreateType(data);
2681
2740
  }
@@ -2692,14 +2751,14 @@ export class Checker {
2692
2751
  const data = owner.client.apiRequest("getDeclaredTypeOfSymbol", {
2693
2752
  snapshot: owner.snapshotId,
2694
2753
  project: owner.project.id,
2695
- symbol: symbol.id,
2754
+ symbol: symbol.reference,
2696
2755
  });
2697
2756
  return owner.objectRegistry.getOrCreateType(data);
2698
2757
  }, function* (symbol) {
2699
2758
  const data = yield* apiRequest("getDeclaredTypeOfSymbol", {
2700
2759
  snapshot: owner.snapshotId,
2701
2760
  project: owner.project.id,
2702
- symbol: symbol.id,
2761
+ symbol: symbol.reference,
2703
2762
  });
2704
2763
  return owner.objectRegistry.getOrCreateType(data);
2705
2764
  });
@@ -2716,14 +2775,14 @@ export class Checker {
2716
2775
  const data = owner.client.apiRequest("getNonMissingTypeOfSymbol", {
2717
2776
  snapshot: owner.snapshotId,
2718
2777
  project: owner.project.id,
2719
- symbol: symbol.id,
2778
+ symbol: symbol.reference,
2720
2779
  });
2721
2780
  return owner.objectRegistry.getOrCreateType(data);
2722
2781
  }, function* (symbol) {
2723
2782
  const data = yield* apiRequest("getNonMissingTypeOfSymbol", {
2724
2783
  snapshot: owner.snapshotId,
2725
2784
  project: owner.project.id,
2726
- symbol: symbol.id,
2785
+ symbol: symbol.reference,
2727
2786
  });
2728
2787
  return owner.objectRegistry.getOrCreateType(data);
2729
2788
  });
@@ -2735,7 +2794,7 @@ export class Checker {
2735
2794
  snapshot: owner.snapshotId,
2736
2795
  project: owner.project.id,
2737
2796
  file,
2738
- symbol: symbol.id,
2797
+ symbol: symbol.reference,
2739
2798
  });
2740
2799
  return (data ?? []).map(h => new NodeHandle(h, owner.project));
2741
2800
  }, function* (file, symbol) {
@@ -2743,7 +2802,7 @@ export class Checker {
2743
2802
  snapshot: owner.snapshotId,
2744
2803
  project: owner.project.id,
2745
2804
  file,
2746
- symbol: symbol.id,
2805
+ symbol: symbol.reference,
2747
2806
  });
2748
2807
  return (data ?? []).map(h => new NodeHandle(h, owner.project));
2749
2808
  });
@@ -3177,7 +3236,7 @@ export class Checker {
3177
3236
  const data = owner.client.apiRequest("getTypeOfSymbolAtLocation", {
3178
3237
  snapshot: owner.snapshotId,
3179
3238
  project: owner.project.id,
3180
- symbol: symbol.id,
3239
+ symbol: symbol.reference,
3181
3240
  location: getNodeId(location),
3182
3241
  });
3183
3242
  return owner.objectRegistry.getOrCreateType(data);
@@ -3185,7 +3244,7 @@ export class Checker {
3185
3244
  const data = yield* apiRequest("getTypeOfSymbolAtLocation", {
3186
3245
  snapshot: owner.snapshotId,
3187
3246
  project: owner.project.id,
3188
- symbol: symbol.id,
3247
+ symbol: symbol.reference,
3189
3248
  location: getNodeId(location),
3190
3249
  });
3191
3250
  return owner.objectRegistry.getOrCreateType(data);
@@ -3446,13 +3505,13 @@ export class Checker {
3446
3505
  return owner.client.apiRequest("isReadonlySymbol", {
3447
3506
  snapshot: owner.snapshotId,
3448
3507
  project: owner.project.id,
3449
- symbol: symbol.id,
3508
+ symbol: symbol.reference,
3450
3509
  });
3451
3510
  }, function* (symbol) {
3452
3511
  return yield* apiRequest("isReadonlySymbol", {
3453
3512
  snapshot: owner.snapshotId,
3454
3513
  project: owner.project.id,
3455
- symbol: symbol.id,
3514
+ symbol: symbol.reference,
3456
3515
  });
3457
3516
  });
3458
3517
  }
@@ -3771,14 +3830,14 @@ export class Checker {
3771
3830
  const data = owner.client.apiRequest("getAliasedSymbol", {
3772
3831
  snapshot: owner.snapshotId,
3773
3832
  project: owner.project.id,
3774
- symbol: symbol.id,
3833
+ symbol: symbol.reference,
3775
3834
  });
3776
3835
  return owner.objectRegistry.getOrCreateSymbol(data);
3777
3836
  }, function* (symbol) {
3778
3837
  const data = yield* apiRequest("getAliasedSymbol", {
3779
3838
  snapshot: owner.snapshotId,
3780
3839
  project: owner.project.id,
3781
- symbol: symbol.id,
3840
+ symbol: symbol.reference,
3782
3841
  });
3783
3842
  return owner.objectRegistry.getOrCreateSymbol(data);
3784
3843
  });
@@ -3793,13 +3852,13 @@ export class Checker {
3793
3852
  return owner.client.apiRequest("getFullyQualifiedName", {
3794
3853
  snapshot: owner.snapshotId,
3795
3854
  project: owner.project.id,
3796
- symbol: symbol.id,
3855
+ symbol: symbol.reference,
3797
3856
  });
3798
3857
  }, function* (symbol) {
3799
3858
  return yield* apiRequest("getFullyQualifiedName", {
3800
3859
  snapshot: owner.snapshotId,
3801
3860
  project: owner.project.id,
3802
- symbol: symbol.id,
3861
+ symbol: symbol.reference,
3803
3862
  });
3804
3863
  });
3805
3864
  }
@@ -3809,14 +3868,14 @@ export class Checker {
3809
3868
  const data = owner.client.apiRequest("getImmediateAliasedSymbol", {
3810
3869
  snapshot: owner.snapshotId,
3811
3870
  project: owner.project.id,
3812
- symbol: symbol.id,
3871
+ symbol: symbol.reference,
3813
3872
  });
3814
3873
  return data ? owner.objectRegistry.getOrCreateSymbol(data) : undefined;
3815
3874
  }, function* (symbol) {
3816
3875
  const data = yield* apiRequest("getImmediateAliasedSymbol", {
3817
3876
  snapshot: owner.snapshotId,
3818
3877
  project: owner.project.id,
3819
- symbol: symbol.id,
3878
+ symbol: symbol.reference,
3820
3879
  });
3821
3880
  return data ? owner.objectRegistry.getOrCreateSymbol(data) : undefined;
3822
3881
  });
@@ -3831,7 +3890,7 @@ export class Checker {
3831
3890
  const data = owner.client.apiRequest("getTargetSymbol", {
3832
3891
  snapshot: owner.snapshotId,
3833
3892
  project: owner.project.id,
3834
- symbol: symbol.id,
3893
+ symbol: symbol.reference,
3835
3894
  });
3836
3895
  return owner.objectRegistry.getOrCreateSymbol(data);
3837
3896
  }
@@ -3841,7 +3900,7 @@ export class Checker {
3841
3900
  const data = yield* apiRequest("getTargetSymbol", {
3842
3901
  snapshot: owner.snapshotId,
3843
3902
  project: owner.project.id,
3844
- symbol: symbol.id,
3903
+ symbol: symbol.reference,
3845
3904
  });
3846
3905
  return owner.objectRegistry.getOrCreateSymbol(data);
3847
3906
  }
@@ -3854,14 +3913,14 @@ export class Checker {
3854
3913
  const data = owner.client.apiRequest("getExportSymbolOfSymbolForChecker", {
3855
3914
  snapshot: owner.snapshotId,
3856
3915
  project: owner.project.id,
3857
- symbol: symbol.id,
3916
+ symbol: symbol.reference,
3858
3917
  });
3859
3918
  return owner.objectRegistry.getOrCreateSymbol(data);
3860
3919
  }, function* (symbol) {
3861
3920
  const data = yield* apiRequest("getExportSymbolOfSymbolForChecker", {
3862
3921
  snapshot: owner.snapshotId,
3863
3922
  project: owner.project.id,
3864
- symbol: symbol.id,
3923
+ symbol: symbol.reference,
3865
3924
  });
3866
3925
  return owner.objectRegistry.getOrCreateSymbol(data);
3867
3926
  });
@@ -3958,14 +4017,14 @@ export class Checker {
3958
4017
  const data = owner.client.apiRequest("getExportsOfModule", {
3959
4018
  snapshot: owner.snapshotId,
3960
4019
  project: owner.project.id,
3961
- symbol: symbol.id,
4020
+ symbol: symbol.reference,
3962
4021
  });
3963
4022
  return data ? data.map(d => owner.objectRegistry.getOrCreateSymbol(d)) : [];
3964
4023
  }, function* (symbol) {
3965
4024
  const data = yield* apiRequest("getExportsOfModule", {
3966
4025
  snapshot: owner.snapshotId,
3967
4026
  project: owner.project.id,
3968
- symbol: symbol.id,
4027
+ symbol: symbol.reference,
3969
4028
  });
3970
4029
  return data ? data.map(d => owner.objectRegistry.getOrCreateSymbol(d)) : [];
3971
4030
  });
@@ -3976,7 +4035,7 @@ export class Checker {
3976
4035
  const data = owner.client.apiRequest("getMemberInModuleExports", {
3977
4036
  snapshot: owner.snapshotId,
3978
4037
  project: owner.project.id,
3979
- symbol: symbol.id,
4038
+ symbol: symbol.reference,
3980
4039
  name,
3981
4040
  });
3982
4041
  return data ? owner.objectRegistry.getOrCreateSymbol(data) : undefined;
@@ -3984,7 +4043,7 @@ export class Checker {
3984
4043
  const data = yield* apiRequest("getMemberInModuleExports", {
3985
4044
  snapshot: owner.snapshotId,
3986
4045
  project: owner.project.id,
3987
- symbol: symbol.id,
4046
+ symbol: symbol.reference,
3988
4047
  name,
3989
4048
  });
3990
4049
  return data ? owner.objectRegistry.getOrCreateSymbol(data) : undefined;
@@ -3996,14 +4055,14 @@ export class Checker {
3996
4055
  const data = owner.client.apiRequest("getJsDocTags", {
3997
4056
  snapshot: owner.snapshotId,
3998
4057
  project: owner.project.id,
3999
- symbol: symbol.id,
4058
+ symbol: symbol.reference,
4000
4059
  });
4001
4060
  return data ?? [];
4002
4061
  }, function* (symbol) {
4003
4062
  const data = yield* apiRequest("getJsDocTags", {
4004
4063
  snapshot: owner.snapshotId,
4005
4064
  project: owner.project.id,
4006
- symbol: symbol.id,
4065
+ symbol: symbol.reference,
4007
4066
  });
4008
4067
  return data ?? [];
4009
4068
  });
@@ -4014,13 +4073,13 @@ export class Checker {
4014
4073
  return owner.client.apiRequest("getDocumentationComment", {
4015
4074
  snapshot: owner.snapshotId,
4016
4075
  project: owner.project.id,
4017
- symbol: symbol.id,
4076
+ symbol: symbol.reference,
4018
4077
  });
4019
4078
  }, function* (symbol) {
4020
4079
  return yield* apiRequest("getDocumentationComment", {
4021
4080
  snapshot: owner.snapshotId,
4022
4081
  project: owner.project.id,
4023
- symbol: symbol.id,
4082
+ symbol: symbol.reference,
4024
4083
  });
4025
4084
  });
4026
4085
  }
@@ -4158,30 +4217,46 @@ export class NodeHandle {
4158
4217
  * is remembered so callers don't have to pass it explicitly.
4159
4218
  */
4160
4219
  canonicalProject;
4220
+ /** The owning source file of a file-owned symbol's declaration. */
4221
+ fileOwner;
4161
4222
  index;
4162
4223
  kind;
4163
4224
  path;
4164
- constructor(handle, canonicalProject) {
4225
+ constructor(handle, canonicalProject, fileOwner) {
4165
4226
  const parsed = parseNodeHandle(handle);
4166
4227
  this.index = parsed.index;
4167
4228
  this.kind = parsed.kind;
4168
4229
  this.path = parsed.path;
4169
4230
  this.canonicalProject = canonicalProject;
4231
+ this.fileOwner = fileOwner;
4170
4232
  }
4171
4233
  /**
4172
4234
  * Resolve this handle to the actual AST node by fetching the source file from a project
4173
4235
  * and looking up the node by index. If no project is passed, the project that produced
4174
- * the handle is used.
4236
+ * the handle is used. Declarations of file-owned symbols identify an exact source file and
4237
+ * resolve through it, independently of any project.
4175
4238
  */
4176
4239
  get resolve() {
4177
4240
  const owner = this;
4178
4241
  return cacheGeneratorMethod(owner, "resolve", function (project = owner.canonicalProject) {
4242
+ if (owner.fileOwner) {
4243
+ const sourceFile = owner.fileOwner.record.file ?? owner.fetchOwnerFile(owner.fileOwner);
4244
+ return sourceFile.getOrCreateNodeAtIndex(owner.index);
4245
+ }
4246
+ if (!project)
4247
+ throw new Error(`Node handle for '${owner.path}' has no project context`);
4179
4248
  const sourceFile = project.program.getSourceFile(owner.path);
4180
4249
  if (!sourceFile) {
4181
4250
  return undefined;
4182
4251
  }
4183
4252
  return sourceFile.getOrCreateNodeAtIndex(owner.index);
4184
4253
  }, function* (project = owner.canonicalProject) {
4254
+ if (owner.fileOwner) {
4255
+ const sourceFile = owner.fileOwner.record.file ?? (yield* owner.fetchOwnerFile.gen(owner.fileOwner));
4256
+ return sourceFile.getOrCreateNodeAtIndex(owner.index);
4257
+ }
4258
+ if (!project)
4259
+ throw new Error(`Node handle for '${owner.path}' has no project context`);
4185
4260
  const sourceFile = yield* project.program.getSourceFile.gen(owner.path);
4186
4261
  if (!sourceFile) {
4187
4262
  return undefined;
@@ -4189,42 +4264,56 @@ export class NodeHandle {
4189
4264
  return sourceFile.getOrCreateNodeAtIndex(owner.index);
4190
4265
  });
4191
4266
  }
4267
+ get fetchOwnerFile() {
4268
+ const owner = this;
4269
+ return cacheGeneratorMethod(owner, "fetchOwnerFile", function (fileOwner) {
4270
+ const data = fileOwner.client.apiRequestBinary("getCachedSourceFile", { file: fileOwner.record.descriptor });
4271
+ if (!data)
4272
+ throw new Error(`Source file '${fileOwner.record.descriptor.fileName}' is not available`);
4273
+ return fileOwner.cache.attachFile(fileOwner.record, new RemoteSourceFile(data, new Wtf8Decoder(), fileOwner.client.getTimingCollector()));
4274
+ }, function* (fileOwner) {
4275
+ const data = sourceFileResponseToUint8Array(yield* apiRequest("getCachedSourceFile", { file: fileOwner.record.descriptor }));
4276
+ if (!data)
4277
+ throw new Error(`Source file '${fileOwner.record.descriptor.fileName}' is not available`);
4278
+ return fileOwner.cache.attachFile(fileOwner.record, new RemoteSourceFile(data, new Wtf8Decoder(), fileOwner.client.getTimingCollector()));
4279
+ });
4280
+ }
4192
4281
  }
4193
4282
  export class Symbol {
4194
- objectRegistry;
4195
- /**
4196
- * The project this symbol was first observed in, used as the default project for
4197
- * lookups that need a project context (members/exports/parent). Symbols are shared
4198
- * snapshot-wide, so these lookups can otherwise be ambiguous about which project to use.
4199
- */
4200
- canonicalProject;
4201
- id;
4283
+ storage;
4284
+ get id() {
4285
+ return this.reference.id;
4286
+ }
4202
4287
  /** The escaped (`__String`) name, used as the key in member/export tables. */
4203
4288
  escapedName;
4204
4289
  /** The display name (escaped underscores removed). */
4205
4290
  name;
4206
4291
  flags;
4207
4292
  checkFlags;
4293
+ /** @internal */
4294
+ reference;
4208
4295
  declarations;
4209
4296
  valueDeclaration;
4210
4297
  parent;
4211
4298
  exportSymbol;
4212
4299
  membersCache;
4213
4300
  exportsCache;
4214
- constructor(data, objectRegistry) {
4215
- this.objectRegistry = objectRegistry;
4216
- this.id = data.id;
4301
+ constructor(data, storage) {
4302
+ if (data.reference.kind !== storage.kind)
4303
+ throw new Error(`Symbol ${data.reference.id} has mismatched ownership and storage`);
4304
+ this.storage = storage;
4305
+ this.reference = data.reference;
4217
4306
  this.escapedName = data.name;
4218
4307
  this.name = unescapeLeadingUnderscores(data.name);
4219
4308
  this.flags = data.flags;
4220
4309
  this.checkFlags = data.checkFlags;
4221
- const canonicalProject = objectRegistry.getProject(data.project);
4222
- if (!canonicalProject) {
4223
- throw new Error(`Symbol ${data.id} references unknown canonical project '${data.project}'`);
4224
- }
4225
- this.canonicalProject = canonicalProject;
4226
- this.declarations = (data.declarations ?? []).map(d => new NodeHandle(d, canonicalProject));
4227
- this.valueDeclaration = data.valueDeclaration ? new NodeHandle(data.valueDeclaration, canonicalProject) : undefined;
4310
+ // A file-owned symbol has no canonical project; its declarations resolve through its file.
4311
+ const project = storage.kind === SymbolOwnerKind.Snapshot ? storage.registry.project : undefined;
4312
+ const fileOwner = storage.kind === SymbolOwnerKind.File ? storage.owner : undefined;
4313
+ this.declarations = (data.declarations ?? []).map(handle => new NodeHandle(handle, project, fileOwner));
4314
+ this.valueDeclaration = data.valueDeclaration
4315
+ ? new NodeHandle(data.valueDeclaration, project, fileOwner)
4316
+ : undefined;
4228
4317
  if (data.parent !== undefined)
4229
4318
  this.parent = data.parent;
4230
4319
  if (data.exportSymbol !== undefined)
@@ -4233,9 +4322,13 @@ export class Symbol {
4233
4322
  get getParent() {
4234
4323
  const owner = this;
4235
4324
  return cacheGeneratorMethod(owner, "getParent", function () {
4236
- return owner.objectRegistry.fetchSymbol(owner, "getParentOfSymbol", owner.parent, owner.canonicalProject.id);
4325
+ if (!owner.parent)
4326
+ return undefined;
4327
+ return owner.fetchSymbol("getParentOfSymbol", owner.parent);
4237
4328
  }, function* () {
4238
- return yield* owner.objectRegistry.fetchSymbol.gen(owner, "getParentOfSymbol", owner.parent, owner.canonicalProject.id);
4329
+ if (!owner.parent)
4330
+ return undefined;
4331
+ return yield* owner.fetchSymbol.gen("getParentOfSymbol", owner.parent);
4239
4332
  });
4240
4333
  }
4241
4334
  /**
@@ -4265,14 +4358,14 @@ export class Symbol {
4265
4358
  get fetchSymbolTable() {
4266
4359
  const owner = this;
4267
4360
  return cacheGeneratorMethod(owner, "fetchSymbolTable", function (method) {
4268
- const symbols = owner.objectRegistry.fetchSymbols(owner, method, undefined, owner.canonicalProject.id);
4361
+ const symbols = owner.fetchSymbols(method);
4269
4362
  const table = new Map();
4270
4363
  for (const symbol of symbols) {
4271
4364
  table.set(symbol.escapedName, symbol);
4272
4365
  }
4273
4366
  return table;
4274
4367
  }, function* (method) {
4275
- const symbols = yield* owner.objectRegistry.fetchSymbols.gen(owner, method, undefined, owner.canonicalProject.id);
4368
+ const symbols = yield* owner.fetchSymbols.gen(method);
4276
4369
  const table = new Map();
4277
4370
  for (const symbol of symbols) {
4278
4371
  table.set(symbol.escapedName, symbol);
@@ -4285,11 +4378,11 @@ export class Symbol {
4285
4378
  return cacheGeneratorMethod(owner, "getExportSymbol", function () {
4286
4379
  if (!owner.exportSymbol)
4287
4380
  return owner;
4288
- return owner.objectRegistry.fetchSymbol(owner, "getExportSymbolOfSymbol", owner.exportSymbol, owner.canonicalProject.id);
4381
+ return owner.fetchSymbol("getExportSymbolOfSymbol", owner.exportSymbol);
4289
4382
  }, function* () {
4290
4383
  if (!owner.exportSymbol)
4291
4384
  return owner;
4292
- return yield* owner.objectRegistry.fetchSymbol.gen(owner, "getExportSymbolOfSymbol", owner.exportSymbol, owner.canonicalProject.id);
4385
+ return yield* owner.fetchSymbol.gen("getExportSymbolOfSymbol", owner.exportSymbol);
4293
4386
  });
4294
4387
  }
4295
4388
  get getJsDocTags() {
@@ -4308,6 +4401,61 @@ export class Symbol {
4308
4401
  return yield* checker.getDocumentationCommentOfSymbol.gen(owner);
4309
4402
  });
4310
4403
  }
4404
+ get fetchSymbol() {
4405
+ const owner = this;
4406
+ return cacheGeneratorMethod(owner, "fetchSymbol", function (method, reference) {
4407
+ if (owner.storage.kind === SymbolOwnerKind.Snapshot) {
4408
+ return owner.storage.registry.fetchSymbol(owner, method, reference);
4409
+ }
4410
+ const fileOwner = owner.storage.owner;
4411
+ // A file-owned symbol's relationships are always owned by the same file.
4412
+ const cached = reference.file === fileOwner.record.descriptor.nodeId ? fileOwner.record.symbols.get(reference.id) : undefined;
4413
+ if (cached)
4414
+ return cached;
4415
+ const data = fileOwner.client.apiRequest(method, { symbol: owner.reference });
4416
+ if (!data)
4417
+ throw new Error(`${method} returned null symbol for Symbol ${owner.id}`);
4418
+ return owner.internFileSymbol(fileOwner, data);
4419
+ }, function* (method, reference) {
4420
+ if (owner.storage.kind === SymbolOwnerKind.Snapshot) {
4421
+ return yield* owner.storage.registry.fetchSymbol.gen(owner, method, reference);
4422
+ }
4423
+ const fileOwner = owner.storage.owner;
4424
+ // A file-owned symbol's relationships are always owned by the same file.
4425
+ const cached = reference.file === fileOwner.record.descriptor.nodeId ? fileOwner.record.symbols.get(reference.id) : undefined;
4426
+ if (cached)
4427
+ return cached;
4428
+ const data = yield* apiRequest(method, { symbol: owner.reference });
4429
+ if (!data)
4430
+ throw new Error(`${method} returned null symbol for Symbol ${owner.id}`);
4431
+ return owner.internFileSymbol(fileOwner, data);
4432
+ });
4433
+ }
4434
+ get fetchSymbols() {
4435
+ const owner = this;
4436
+ return cacheGeneratorMethod(owner, "fetchSymbols", function (method) {
4437
+ if (owner.storage.kind === SymbolOwnerKind.Snapshot) {
4438
+ return owner.storage.registry.fetchSymbols(owner, method);
4439
+ }
4440
+ const fileOwner = owner.storage.owner;
4441
+ const data = fileOwner.client.apiRequest(method, { symbol: owner.reference });
4442
+ return data?.map(symbol => owner.internFileSymbol(fileOwner, symbol)) ?? [];
4443
+ }, function* (method) {
4444
+ if (owner.storage.kind === SymbolOwnerKind.Snapshot) {
4445
+ return yield* owner.storage.registry.fetchSymbols.gen(owner, method);
4446
+ }
4447
+ const fileOwner = owner.storage.owner;
4448
+ const data = yield* apiRequest(method, { symbol: owner.reference });
4449
+ return data?.map(symbol => owner.internFileSymbol(fileOwner, symbol)) ?? [];
4450
+ });
4451
+ }
4452
+ internFileSymbol(fileOwner, data) {
4453
+ validateSymbolResponse(data);
4454
+ const reference = data.reference;
4455
+ if (reference.kind !== SymbolOwnerKind.File)
4456
+ throw new Error(`Symbol ${reference.id} is not file-owned`);
4457
+ return fileOwner.cache.getOrCreateSymbol(fileOwner.record, reference.file, reference.id, () => new Symbol(data, { kind: SymbolOwnerKind.File, owner: fileOwner }));
4458
+ }
4311
4459
  }
4312
4460
  class TypeObject {
4313
4461
  objectRegistry;