@esportsplus/typescript 0.32.0 → 0.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +34 -49
  2. package/build/cli/tsc.d.ts +3 -2
  3. package/build/cli/tsc.js +15 -97
  4. package/build/{probe → guard}/adapter.d.ts +1 -2
  5. package/build/{probe → guard}/adapter.js +1 -4
  6. package/build/{probe → guard}/async/channel.d.ts +1 -1
  7. package/build/{probe → guard}/async/channel.js +11 -191
  8. package/build/{probe → guard}/async/value.d.ts +1 -2
  9. package/build/{probe → guard}/async/value.js +1 -4
  10. package/build/guard/channels.d.ts +4 -0
  11. package/build/guard/channels.js +13 -0
  12. package/build/{probe → guard}/exceptions/channel.d.ts +3 -2
  13. package/build/{probe → guard}/exceptions/channel.js +167 -107
  14. package/build/guard/exceptions/derive.d.ts +49 -0
  15. package/build/guard/exceptions/derive.js +478 -0
  16. package/build/guard/exceptions/resolve-js.d.ts +2 -0
  17. package/build/guard/exceptions/resolve-js.js +26 -0
  18. package/build/{probe → guard}/exceptions/value.d.ts +3 -2
  19. package/build/{probe → guard}/exceptions/value.js +12 -4
  20. package/build/{probe → guard}/kernel/analyze.d.ts +2 -1
  21. package/build/guard/kernel/analyze.js +84 -0
  22. package/build/guard/kernel/ast.d.ts +13 -0
  23. package/build/{probe → guard}/kernel/ast.js +22 -15
  24. package/build/guard/kernel/config.js +93 -0
  25. package/build/guard/kernel/fixpoint.d.ts +6 -0
  26. package/build/{probe → guard}/kernel/fixpoint.js +8 -48
  27. package/build/guard/kernel/graph.d.ts +4 -0
  28. package/build/guard/kernel/graph.js +268 -0
  29. package/build/{probe → guard}/kernel/ids.d.ts +2 -3
  30. package/build/{probe → guard}/kernel/ids.js +1 -6
  31. package/build/{probe → guard}/kernel/types.d.ts +3 -32
  32. package/build/{probe → guard}/overlay/base/async.jsonc +1 -1
  33. package/build/{probe → guard}/overlay/base/exceptions.jsonc +16 -3
  34. package/build/{probe → guard}/overlay/base/resources.jsonc +7 -8
  35. package/build/{probe → guard}/overlay/load.d.ts +3 -7
  36. package/build/{probe → guard}/overlay/load.js +37 -120
  37. package/build/{probe → guard}/resources/channel.d.ts +1 -1
  38. package/build/{probe → guard}/resources/channel.js +81 -159
  39. package/build/{probe → guard}/resources/value.d.ts +1 -2
  40. package/build/{probe → guard}/resources/value.js +1 -14
  41. package/build/lsp/diagnostics.d.ts +2 -2
  42. package/build/lsp/diagnostics.js +2 -2
  43. package/build/lsp/server.js +41 -3
  44. package/build/lsp/workspace.d.ts +6 -3
  45. package/build/lsp/workspace.js +19 -5
  46. package/build/tsconfig.d.ts +2 -1
  47. package/build/tsconfig.js +44 -102
  48. package/package.json +2 -2
  49. package/tsconfig.base.json +12 -19
  50. package/tsconfig.package.json +6 -1
  51. package/build/probe/channels.d.ts +0 -4
  52. package/build/probe/channels.js +0 -16
  53. package/build/probe/kernel/analyze.js +0 -68
  54. package/build/probe/kernel/ast.d.ts +0 -11
  55. package/build/probe/kernel/config.js +0 -209
  56. package/build/probe/kernel/fixpoint.d.ts +0 -6
  57. package/build/probe/kernel/graph.d.ts +0 -4
  58. package/build/probe/kernel/graph.js +0 -507
  59. package/build/probe/overlay/presets/express.jsonc +0 -25
  60. package/build/probe/overlay/presets/node.jsonc +0 -17
  61. /package/build/{probe → guard}/exceptions/jsdoc.d.ts +0 -0
  62. /package/build/{probe → guard}/exceptions/jsdoc.js +0 -0
  63. /package/build/{probe → guard}/kernel/config.d.ts +0 -0
  64. /package/build/{probe → guard}/kernel/format.d.ts +0 -0
  65. /package/build/{probe → guard}/kernel/format.js +0 -0
  66. /package/build/{probe → guard}/kernel/program.d.ts +0 -0
  67. /package/build/{probe → guard}/kernel/program.js +0 -0
  68. /package/build/{probe → guard}/kernel/types.js +0 -0
@@ -1,5 +1,6 @@
1
- import type { Channel } from '../kernel/types.js';
1
+ import { type ThrowIndex } from './derive.js';
2
2
  import { type ExceptionsValue } from './value.js';
3
+ import type { Channel } from '../kernel/types.js';
3
4
  declare function overlayThrows(entry: unknown): boolean;
4
- declare function createExceptionsChannel(): Channel<ExceptionsValue>;
5
+ declare function createExceptionsChannel(throwIndex: ThrowIndex): Channel<ExceptionsValue>;
5
6
  export { createExceptionsChannel, overlayThrows };
@@ -1,18 +1,21 @@
1
1
  import * as NodeFS from 'node:fs';
2
2
  import * as ts from '../adapter.js';
3
- import { bodyOf, calleeSelectors, paramSymbols } from '../kernel/ast.js';
3
+ import { bodyOf, constituents, isAwaited, paramSymbols } from '../kernel/ast.js';
4
4
  import { isFunctionLike, locationOf } from '../kernel/ids.js';
5
5
  import { declaredExceptions } from './jsdoc.js';
6
- import { bottom, constituentsOf, equals, isEmpty, join, originsOf, refOfType, render, single, subtract, top, TOP_KEY, widen, withOrigin, } from './value.js';
6
+ import { deriveThrows } from './derive.js';
7
+ import { bottom, equals, isEmpty, join, originOf, originsOf, refOfType, render, single, subtract, top, TOP_KEY, widen, withOrigin, } from './value.js';
7
8
  function overlayThrows(entry) {
8
9
  const e = (entry ?? {});
9
10
  return ((Array.isArray(e.exceptions) && e.exceptions.length > 0) ||
10
11
  (Array.isArray(e.exceptionsFromCallbacks) &&
11
12
  e.exceptionsFromCallbacks.length > 0));
12
13
  }
13
- function createExceptionsChannel() {
14
+ function createExceptionsChannel(throwIndex) {
14
15
  let unhandledCache;
15
16
  const typeCache = new Map();
17
+ const importIndex = new Map();
18
+ const namedTypeCache = new Map();
16
19
  const typeAt = (checker, node) => {
17
20
  if (typeCache.has(node)) {
18
21
  return typeCache.get(node);
@@ -21,6 +24,69 @@ function createExceptionsChannel() {
21
24
  typeCache.set(node, type);
22
25
  return type;
23
26
  };
27
+ const importsFor = (sf) => {
28
+ let imports = importIndex.get(sf);
29
+ if (imports) {
30
+ return imports;
31
+ }
32
+ imports = new Map();
33
+ importIndex.set(sf, imports);
34
+ for (const statement of sf.statements) {
35
+ if (!ts.isImportDeclaration(statement) ||
36
+ !ts.isStringLiteral(statement.moduleSpecifier) ||
37
+ !statement.importClause) {
38
+ continue;
39
+ }
40
+ const specifier = statement.moduleSpecifier.text;
41
+ if (specifier.startsWith('.') || specifier.startsWith('/')) {
42
+ continue;
43
+ }
44
+ const clause = statement.importClause;
45
+ if (clause.name) {
46
+ imports.set(clause.name.text, {
47
+ exportName: 'default',
48
+ isNamespace: false,
49
+ memberName: undefined,
50
+ specifier,
51
+ });
52
+ }
53
+ if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
54
+ for (const element of clause.namedBindings.elements) {
55
+ imports.set(element.name.text, {
56
+ exportName: (element.propertyName ?? element.name).text,
57
+ isNamespace: false,
58
+ memberName: undefined,
59
+ specifier,
60
+ });
61
+ }
62
+ }
63
+ else if (clause.namedBindings &&
64
+ ts.isNamespaceImport(clause.namedBindings)) {
65
+ imports.set(clause.namedBindings.name.text, {
66
+ exportName: '',
67
+ isNamespace: true,
68
+ memberName: undefined,
69
+ specifier,
70
+ });
71
+ }
72
+ }
73
+ return imports;
74
+ };
75
+ const namedTypeAt = (checker, name, location) => {
76
+ const sf = location.getSourceFile();
77
+ let names = namedTypeCache.get(sf);
78
+ if (!names) {
79
+ names = new Map();
80
+ namedTypeCache.set(sf, names);
81
+ }
82
+ if (names.has(name)) {
83
+ return names.get(name);
84
+ }
85
+ const sym = checker.resolveName(name, ts.SymbolFlags.Type, location, false);
86
+ const type = sym ? checker.getDeclaredTypeOfSymbol(sym) : undefined;
87
+ names.set(name, type);
88
+ return type;
89
+ };
24
90
  const computeUnhandled = (ctx) => {
25
91
  if (unhandledCache)
26
92
  return unhandledCache;
@@ -39,7 +105,7 @@ function createExceptionsChannel() {
39
105
  equals,
40
106
  widen,
41
107
  transfer(ctx) {
42
- const env = makeEnv(ctx.checker, ctx.dispatch, ctx.sinks, ctx.fn, ctx.summaryOf, ctx.resolveCall, typeAt);
108
+ const env = makeEnv(ctx.checker, throwIndex, ctx.fn, ctx.summaryOf, ctx.resolveCall, typeAt, undefined, undefined, importsFor, namedTypeAt);
43
109
  const body = bodyOf(ctx.fn.node);
44
110
  let value = body ? escapeOf(env, body, undefined) : bottom();
45
111
  const decl = declaredExceptions(ctx.fn.node, ctx.checker);
@@ -49,12 +115,12 @@ function createExceptionsChannel() {
49
115
  },
50
116
  diagnose(ctx) {
51
117
  const out = [];
52
- const base = makeEnv(ctx.checker, ctx.dispatch, ctx.sinks, ctx.fn, ctx.summaryOf, ctx.resolveCall, typeAt);
53
- const env = reportMode(ctx) === 'all'
54
- ? { ...base, escapeCache: new Map() }
118
+ const mode = reportMode(ctx);
119
+ const base = makeEnv(ctx.checker, throwIndex, ctx.fn, ctx.summaryOf, ctx.resolveCall, typeAt, new Map(), new Map(), importsFor, namedTypeAt, mode);
120
+ const env = mode === 'all'
121
+ ? base
55
122
  : {
56
123
  ...base,
57
- escapeCache: new Map(),
58
124
  unhandled: computeUnhandled(ctx),
59
125
  };
60
126
  const body = bodyOf(ctx.fn.node);
@@ -72,28 +138,33 @@ function createExceptionsChannel() {
72
138
  });
73
139
  }
74
140
  }
75
- if (errorCauseEnabled(ctx) && body)
141
+ if (body) {
76
142
  checkErrorCause(body, out);
77
- if (ctx.isBoundary && body)
143
+ }
144
+ if (body) {
78
145
  walkDiagnostics(env, ctx, body, undefined, undefined, out);
146
+ }
79
147
  return out;
80
148
  },
81
149
  };
82
150
  }
83
- function makeEnv(checker, dispatch, sinks, fn, summaryOf, resolveCall, typeAt) {
151
+ function makeEnv(checker, throwIndex, fn, summaryOf, resolveCall, typeAt, escapeCache, callCache, importsFor, namedTypeAt, report = undefined) {
84
152
  const symbols = paramSymbols(checker, fn.node);
85
153
  return {
86
154
  checker,
87
- dispatch,
88
- sinks,
155
+ throwIndex,
89
156
  fn,
90
157
  summaryOf,
91
158
  resolveCall,
92
- escapeCache: undefined,
159
+ escapeCache,
160
+ callCache,
161
+ importsFor,
162
+ namedTypeAt: (name, location) => namedTypeAt(checker, name, location),
93
163
  typeTable: new Map(),
94
164
  typeAt: (node) => typeAt(checker, node),
95
165
  paramSymbols: symbols,
96
166
  fromCallbacks: new Set(),
167
+ reportMode: report,
97
168
  };
98
169
  }
99
170
  function escapeOf(env, node, binding) {
@@ -112,7 +183,7 @@ function escapeOf(env, node, binding) {
112
183
  if (ts.isThrowStatement(n)) {
113
184
  if (n.expression && !isBindingRef(env, n.expression, binding)) {
114
185
  const thrown = valueOfType(env, env.typeAt(n.expression));
115
- acc = join(acc, withOrigin(thrown, originOf(n)));
186
+ acc = join(acc, withOrigin(thrown, originOf(n, n.getSourceFile())));
116
187
  }
117
188
  if (n.expression)
118
189
  ts.forEachChild(n.expression, visit);
@@ -310,6 +381,10 @@ function isSubclassOf(c, base, seen = new Set()) {
310
381
  return false;
311
382
  }
312
383
  function callEscape(env, call) {
384
+ const cached = env.callCache?.get(call);
385
+ if (cached) {
386
+ return cached;
387
+ }
313
388
  detectParamCall(env, call);
314
389
  const res = env.resolveCall(call);
315
390
  let v = bottom();
@@ -321,15 +396,59 @@ function callEscape(env, call) {
321
396
  v = join(v, env.summaryOf(f).value);
322
397
  }
323
398
  }
324
- if (res.overlay)
399
+ if (res.overlay) {
325
400
  v = join(v, overlayValue(env, res, call));
326
- if (res.unresolved && !res.overlay && env.dispatch === 'pessimist')
327
- v = join(v, top());
328
- const sink = matchSink(env, call);
329
- if (sink)
330
- v = applySink(v, sink);
401
+ }
402
+ else if (res.targets.length === 0) {
403
+ const derived = deriveForCall(env, call);
404
+ if (derived)
405
+ v = join(v, derived);
406
+ }
407
+ env.callCache?.set(call, v);
331
408
  return v;
332
409
  }
410
+ function deriveForCall(env, call) {
411
+ const info = importInfoForCall(env, call);
412
+ if (!info) {
413
+ return undefined;
414
+ }
415
+ const summary = deriveThrows(env.throwIndex, {
416
+ awaited: ts.isCallExpression(call) && isAwaited(call),
417
+ exportName: info.exportName,
418
+ importerFileName: call.getSourceFile().fileName,
419
+ memberName: info.memberName,
420
+ specifier: info.specifier,
421
+ });
422
+ if (!summary) {
423
+ return undefined;
424
+ }
425
+ let v = bottom();
426
+ for (const [cls, origins] of summary.classes) {
427
+ let cv = namedValue(env, cls, call);
428
+ for (const origin of origins) {
429
+ cv = withOrigin(cv, origin);
430
+ }
431
+ v = join(v, cv);
432
+ }
433
+ return v;
434
+ }
435
+ function importInfoForCall(env, call) {
436
+ const imports = env.importsFor(call.getSourceFile());
437
+ const callee = call.expression;
438
+ if (ts.isIdentifier(callee)) {
439
+ return imports.get(callee.text);
440
+ }
441
+ if (ts.isPropertyAccessExpression(callee) && ts.isIdentifier(callee.expression)) {
442
+ const imported = imports.get(callee.expression.text);
443
+ return imported?.isNamespace
444
+ ? {
445
+ ...imported,
446
+ exportName: callee.name.text,
447
+ }
448
+ : undefined;
449
+ }
450
+ return undefined;
451
+ }
333
452
  function overlayValue(env, res, call) {
334
453
  const entry = (res.overlay?.entry ?? {});
335
454
  let v = bottom();
@@ -349,11 +468,9 @@ function overlayValue(env, res, call) {
349
468
  return v;
350
469
  }
351
470
  function namedValue(env, name, location) {
352
- const sym = env.checker.resolveName(name, ts.SymbolFlags.Type, location, false);
353
- if (sym) {
354
- const t = env.checker.getDeclaredTypeOfSymbol(sym);
355
- if (t)
356
- return valueOfType(env, t);
471
+ const type = env.namedTypeAt(name, location);
472
+ if (type) {
473
+ return valueOfType(env, type);
357
474
  }
358
475
  return single(name, name);
359
476
  }
@@ -367,33 +484,6 @@ function detectParamCall(env, call) {
367
484
  if (idx !== undefined)
368
485
  env.fromCallbacks.add(idx);
369
486
  }
370
- function matchSink(env, call) {
371
- if (!ts.isCallExpression(call))
372
- return undefined;
373
- const names = calleeSelectors(call.expression);
374
- for (const s of env.sinks)
375
- if (names.has(s.callee))
376
- return s;
377
- return undefined;
378
- }
379
- function applySink(v, sink) {
380
- if (!sink.absorbs)
381
- return bottom();
382
- if (v.top)
383
- return v;
384
- const absorb = new Set(sink.absorbs);
385
- const kept = new Map();
386
- const keptOrigins = new Map();
387
- for (const [k, d] of v.types) {
388
- if (absorb.has(d))
389
- continue;
390
- kept.set(k, d);
391
- const o = v.origins.get(k);
392
- if (o)
393
- keptOrigins.set(k, o);
394
- }
395
- return { top: false, types: kept, origins: keptOrigins };
396
- }
397
487
  function reportMode(ctx) {
398
488
  const cc = ctx.channelConfig;
399
489
  if (typeof cc === 'object' && cc !== null) {
@@ -403,15 +493,8 @@ function reportMode(ctx) {
403
493
  }
404
494
  return 'consumers';
405
495
  }
406
- function consumersOnly(ctx) {
407
- const mode = reportMode(ctx);
408
- return mode === 'consumers' || mode === 'cross-module';
409
- }
410
- function errorCauseEnabled(ctx) {
411
- const cc = ctx.channelConfig;
412
- return (typeof cc === 'object' &&
413
- cc !== null &&
414
- cc['errorCause'] === true);
496
+ function consumersOnly(env) {
497
+ return env.reportMode === 'consumers' || env.reportMode === 'cross-module';
415
498
  }
416
499
  function hasCauseArg(node) {
417
500
  for (const arg of node.arguments ?? []) {
@@ -482,19 +565,15 @@ function packageRootOf(fileName) {
482
565
  }
483
566
  return root;
484
567
  }
485
- function crossesPackageBoundary(env, ctx, call) {
486
- const res = env.resolveCall(call);
487
- if (res.targets.length === 0)
488
- return true;
489
- const home = packageRootOf(ctx.fn.fileName);
490
- return res.targets.some((t) => packageRootOf(t.fileName) !== home);
568
+ function normalizeSlashes(fileName) {
569
+ return fileName.replace(/\\/g, '/');
491
570
  }
492
- function crossesFileBoundary(env, ctx, call) {
571
+ function crossesBoundary(env, ctx, call, homeOf) {
493
572
  const res = env.resolveCall(call);
494
573
  if (res.targets.length === 0)
495
574
  return true;
496
- const home = ctx.fn.fileName.replace(/\\/g, '/');
497
- return res.targets.some((t) => t.fileName.replace(/\\/g, '/') !== home);
575
+ const home = homeOf(ctx.fn.fileName);
576
+ return res.targets.some((t) => homeOf(t.fileName) !== home);
498
577
  }
499
578
  function reachesTop(env, rem) {
500
579
  const u = env.unhandled;
@@ -506,6 +585,9 @@ function reachesTop(env, rem) {
506
585
  return false;
507
586
  }
508
587
  function walkDiagnostics(env, ctx, node, binding, remainder, out) {
588
+ const homeOf = env.reportMode === 'cross-module'
589
+ ? normalizeSlashes
590
+ : packageRootOf;
509
591
  const visit = (n) => {
510
592
  if (isFunctionLike(n))
511
593
  return;
@@ -515,7 +597,7 @@ function walkDiagnostics(env, ctx, node, binding, remainder, out) {
515
597
  }
516
598
  if (ts.isThrowStatement(n)) {
517
599
  if (n.expression) {
518
- if (!consumersOnly(ctx)) {
600
+ if (!consumersOnly(env)) {
519
601
  if (isBindingRef(env, n.expression, binding)) {
520
602
  if (remainder && !isEmpty(remainder))
521
603
  out.push(throwDiagnostic(ctx, n, remainder));
@@ -532,13 +614,11 @@ function walkDiagnostics(env, ctx, node, binding, remainder, out) {
532
614
  }
533
615
  if (ts.isCallExpression(n) || ts.isNewExpression(n)) {
534
616
  const rem = callEscape(env, n);
535
- const mode = reportMode(ctx);
617
+ const mode = env.reportMode;
536
618
  const report = mode === 'all'
537
619
  ? true
538
- : mode === 'cross-module'
539
- ? crossesFileBoundary(env, ctx, n) && reachesTop(env, rem)
540
- : crossesPackageBoundary(env, ctx, n) &&
541
- reachesTop(env, rem);
620
+ : crossesBoundary(env, ctx, n, homeOf) &&
621
+ reachesTop(env, rem);
542
622
  if (!isEmpty(rem) && report)
543
623
  out.push(callDiagnostic(env, ctx, n, rem));
544
624
  ts.forEachChild(n, visit);
@@ -562,22 +642,8 @@ function handleTry(env, ctx, n, binding, remainder, out) {
562
642
  if (n.finallyBlock)
563
643
  walkDiagnostics(env, ctx, n.finallyBlock, binding, remainder, out);
564
644
  }
565
- function originOf(node) {
566
- const sf = node.getSourceFile();
567
- const start = node.getStart(sf);
568
- const { line, character } = sf.getLineAndCharacterOfPosition(start);
569
- const raw = node.getText(sf).replace(/\s+/g, ' ').trim();
570
- return {
571
- fileName: sf.fileName,
572
- pos: start,
573
- end: node.getEnd(),
574
- line: line + 1,
575
- column: character + 1,
576
- text: raw.length > 120 ? `${raw.slice(0, 117)}…` : raw,
577
- };
578
- }
579
645
  function relatedFromOrigins(origins) {
580
- return origins.slice(0, 8).map((o) => ({
646
+ return origins.map((o) => ({
581
647
  message: o.text,
582
648
  location: {
583
649
  fileName: o.fileName,
@@ -599,7 +665,7 @@ function callDiagnostic(env, ctx, call, rem) {
599
665
  location: locationOf(call, call.getSourceFile()),
600
666
  related: origins.length > 0
601
667
  ? relatedFromOrigins(origins)
602
- : buildRelated(ctx, res.targets),
668
+ : buildRelated(res.targets),
603
669
  };
604
670
  }
605
671
  function throwDiagnostic(ctx, node, rem) {
@@ -607,7 +673,7 @@ function throwDiagnostic(ctx, node, rem) {
607
673
  channel: 'exceptions',
608
674
  message: `Throw may throw ${render(rem)} with no catch on the path to \`${ctx.fn.name}\``,
609
675
  location: locationOf(node, node.getSourceFile()),
610
- related: buildRelated(ctx, []),
676
+ related: [],
611
677
  };
612
678
  }
613
679
  function calleeDisplay(res, call) {
@@ -615,16 +681,16 @@ function calleeDisplay(res, call) {
615
681
  return res.overlay.symbol;
616
682
  if (res.targets[0])
617
683
  return res.targets[0].name;
618
- const callee = ts.isCallExpression(call) || ts.isNewExpression(call)
619
- ? call.expression
620
- : undefined;
621
- if (callee && ts.isPropertyAccessExpression(callee))
684
+ const callee = call.expression;
685
+ if (ts.isPropertyAccessExpression(callee)) {
622
686
  return callee.getText();
623
- if (callee && ts.isIdentifier(callee))
687
+ }
688
+ if (ts.isIdentifier(callee)) {
624
689
  return callee.text;
690
+ }
625
691
  return undefined;
626
692
  }
627
- function buildRelated(ctx, targets) {
693
+ function buildRelated(targets) {
628
694
  const related = [];
629
695
  for (const t of targets) {
630
696
  related.push({
@@ -632,19 +698,13 @@ function buildRelated(ctx, targets) {
632
698
  location: locationOf(t.node, t.sourceFile),
633
699
  });
634
700
  }
635
- for (const f of ctx.pathToBoundary(ctx.fn)) {
636
- related.push({
637
- message: `on the path to boundary via ${f.name}`,
638
- location: locationOf(f.node, f.sourceFile),
639
- });
640
- }
641
701
  return related;
642
702
  }
643
703
  function valueOfType(env, type) {
644
704
  let v = bottom();
645
705
  if (!type)
646
706
  return v;
647
- for (const t of constituentsOf(type)) {
707
+ for (const t of constituents(type)) {
648
708
  const r = refOfType(env.checker, t);
649
709
  if (r.top) {
650
710
  v = join(v, top());
@@ -0,0 +1,49 @@
1
+ import * as ts from '../adapter.js';
2
+ import { API } from 'typescript/unstable/sync';
3
+ import type { ExceptionOrigin } from './value.js';
4
+ type ImportTarget = {
5
+ readonly exportName: string;
6
+ readonly specifier: string;
7
+ };
8
+ type FileIndex = {
9
+ readonly classes: Map<string, ts.Node>;
10
+ readonly exportsByName: Map<string, ts.Node>;
11
+ readonly fns: Map<string, ts.Node>;
12
+ readonly imports: Map<string, ImportTarget>;
13
+ readonly namespaces: Map<string, string>;
14
+ readonly reexportAll: string | undefined;
15
+ readonly reexports: Map<string, ImportTarget>;
16
+ };
17
+ type ParsedFile = {
18
+ readonly fileIndex: FileIndex | null;
19
+ readonly mtimeMs: number;
20
+ readonly size: number;
21
+ readonly sourceFile: ts.SourceFile | null;
22
+ };
23
+ type Cached = {
24
+ readonly async: boolean;
25
+ readonly classes: Map<string, ExceptionOrigin[]>;
26
+ } | null;
27
+ type ThrowIndex = {
28
+ api: API | null;
29
+ readonly contents: Map<string, string>;
30
+ nextProject: number;
31
+ readonly parsed: Map<string, ParsedFile>;
32
+ readonly resolved: Map<string, string | undefined>;
33
+ readonly snapshots: ReturnType<API['updateSnapshot']>[];
34
+ readonly summaries: Map<string, Cached>;
35
+ };
36
+ type DerivedSummary = {
37
+ readonly classes: ReadonlyMap<string, ReadonlyArray<ExceptionOrigin>>;
38
+ };
39
+ type DeriveParams = {
40
+ readonly awaited: boolean;
41
+ readonly exportName: string;
42
+ readonly importerFileName: string;
43
+ readonly memberName: string | undefined;
44
+ readonly specifier: string;
45
+ };
46
+ declare function createThrowIndex(): ThrowIndex;
47
+ declare function disposeThrowIndex(index: ThrowIndex): void;
48
+ declare function deriveThrows(index: ThrowIndex, params: DeriveParams): DerivedSummary | undefined;
49
+ export { createThrowIndex, deriveThrows, disposeThrowIndex, type DerivedSummary, type ThrowIndex };