@cplieger/deadset-ts 7.2.0-dev.3 → 8.0.0-dev.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 (153) hide show
  1. package/dist/bin/mapper-connection.js +7 -4
  2. package/dist/src/analysis.js +116 -16
  3. package/dist/src/augmentations.js +21 -8
  4. package/dist/src/automatic-types.js +189 -0
  5. package/dist/src/base-url.js +18 -0
  6. package/dist/src/component-files.js +96 -31
  7. package/dist/src/components.js +7 -6
  8. package/dist/src/config.js +1 -0
  9. package/dist/src/configuration-files.js +54 -15
  10. package/dist/src/configured-declarations.js +24 -2
  11. package/dist/src/conformance-record.js +2 -2
  12. package/dist/src/contextual-uses.js +26 -26
  13. package/dist/src/convention-rows.js +75 -0
  14. package/dist/src/conventions.js +101 -5
  15. package/dist/src/decorator.js +21 -18
  16. package/dist/src/dependencies.js +185 -30
  17. package/dist/src/destructuring.js +77 -2
  18. package/dist/src/discover.js +188 -85
  19. package/dist/src/edges.js +1 -1
  20. package/dist/src/entry-point-gaps.js +7 -10
  21. package/dist/src/entry-points.js +112 -11
  22. package/dist/src/findings/completion.js +116 -21
  23. package/dist/src/findings/dependencies-and-module-machinery.js +71 -25
  24. package/dist/src/findings/emitters.js +1 -1
  25. package/dist/src/findings/intra-function.js +44 -13
  26. package/dist/src/findings/non-code-artifacts.js +66 -33
  27. package/dist/src/findings/unused-declarations.js +21 -1
  28. package/dist/src/findings/visibility-narrowing.js +22 -3
  29. package/dist/src/generated-file.js +11 -0
  30. package/dist/src/git-ignore.js +86 -0
  31. package/dist/src/graph.js +4 -1
  32. package/dist/src/import-bindings.js +97 -0
  33. package/dist/src/indexed-access.js +130 -28
  34. package/dist/src/interface-satisfaction.js +30 -12
  35. package/dist/src/intra-function-parts.js +313 -50
  36. package/dist/src/inventory.js +63 -8
  37. package/dist/src/json-document.js +5 -5
  38. package/dist/src/kinds.js +13 -13
  39. package/dist/src/matrix.js +18 -9
  40. package/dist/src/mdx-entries.js +197 -0
  41. package/dist/src/module-declarations.js +9 -13
  42. package/dist/src/namespace-objects.js +28 -18
  43. package/dist/src/overrides.js +45 -9
  44. package/dist/src/paths.js +9 -0
  45. package/dist/src/print.js +1 -0
  46. package/dist/src/ref.js +10 -0
  47. package/dist/src/references.js +29 -13
  48. package/dist/src/reflective-lookup.js +8 -6
  49. package/dist/src/report.js +4 -2
  50. package/dist/src/reporters/template.js +22 -13
  51. package/dist/src/resolve.js +2 -0
  52. package/dist/src/roots.js +110 -38
  53. package/dist/src/schema.js +1 -0
  54. package/dist/src/serialization-contract.js +97 -20
  55. package/dist/src/session.js +26 -1
  56. package/dist/src/source-files.js +39 -14
  57. package/dist/src/spelled-names.js +58 -0
  58. package/dist/src/suppress-file.js +12 -4
  59. package/dist/src/suppress-inline.js +21 -3
  60. package/dist/src/suppress.js +7 -5
  61. package/dist/src/sweep.js +27 -10
  62. package/dist/src/symbol-keys.js +103 -2
  63. package/dist/src/template-field.js +9 -6
  64. package/dist/src/test-support.js +121 -17
  65. package/dist/src/type-errors.js +116 -35
  66. package/dist/src/type-parameter-reads.js +172 -0
  67. package/dist/src/value-reach.js +17 -5
  68. package/dist/src/verbs/analyze.js +19 -1
  69. package/dist/src/verbs/explain.js +4 -2
  70. package/dist/src/version-range.js +10 -5
  71. package/dist/src/version.js +1 -1
  72. package/dist/src/workflow-steps.js +119 -22
  73. package/dist/src/workspace-programs.js +7 -3
  74. package/dist/src/workspace-resolution.js +72 -13
  75. package/dist/src/workspace.js +1 -1
  76. package/jsr.json +1 -1
  77. package/package.json +2 -2
  78. package/src/analysis.ts +175 -16
  79. package/src/augmentations.ts +21 -10
  80. package/src/automatic-types.ts +246 -0
  81. package/src/base-url.ts +24 -0
  82. package/src/component-files.ts +116 -31
  83. package/src/components.ts +7 -6
  84. package/src/config.ts +3 -0
  85. package/src/configuration-files.ts +80 -18
  86. package/src/configured-declarations.ts +33 -4
  87. package/src/conformance-record.ts +2 -2
  88. package/src/contextual-uses.ts +27 -27
  89. package/src/convention-rows.ts +103 -0
  90. package/src/conventions.ts +121 -7
  91. package/src/decorator.ts +28 -18
  92. package/src/dependencies.ts +249 -43
  93. package/src/destructuring.ts +93 -2
  94. package/src/discover.ts +234 -86
  95. package/src/edges.ts +1 -1
  96. package/src/entry-point-gaps.ts +8 -11
  97. package/src/entry-points.ts +133 -11
  98. package/src/finding.ts +10 -0
  99. package/src/findings/completion.ts +147 -24
  100. package/src/findings/dependencies-and-module-machinery.ts +90 -28
  101. package/src/findings/emitters.ts +1 -1
  102. package/src/findings/intra-function.ts +56 -14
  103. package/src/findings/non-code-artifacts.ts +81 -41
  104. package/src/findings/unused-declarations.ts +25 -1
  105. package/src/findings/visibility-narrowing.ts +32 -3
  106. package/src/generated-file.ts +16 -0
  107. package/src/git-ignore.ts +98 -0
  108. package/src/graph.ts +6 -0
  109. package/src/host.ts +5 -9
  110. package/src/import-bindings.ts +128 -0
  111. package/src/indexed-access.ts +152 -30
  112. package/src/interface-satisfaction.ts +33 -13
  113. package/src/intra-function-parts.ts +415 -64
  114. package/src/inventory.ts +83 -7
  115. package/src/json-document.ts +7 -7
  116. package/src/kinds.ts +13 -13
  117. package/src/matrix.ts +32 -14
  118. package/src/mdx-entries.ts +241 -0
  119. package/src/module-declarations.ts +11 -13
  120. package/src/namespace-objects.ts +34 -21
  121. package/src/overrides.ts +56 -9
  122. package/src/paths.ts +10 -0
  123. package/src/print.ts +1 -0
  124. package/src/ref.ts +12 -0
  125. package/src/references.ts +38 -17
  126. package/src/reflective-lookup.ts +9 -7
  127. package/src/report.ts +16 -3
  128. package/src/reporters/template.ts +21 -13
  129. package/src/resolve.ts +3 -0
  130. package/src/roots.ts +163 -45
  131. package/src/schema.ts +1 -0
  132. package/src/serialization-contract.ts +108 -17
  133. package/src/session.ts +29 -1
  134. package/src/source-files.ts +66 -16
  135. package/src/spelled-names.ts +102 -0
  136. package/src/suppress-file.ts +14 -3
  137. package/src/suppress-inline.ts +21 -2
  138. package/src/suppress.ts +9 -5
  139. package/src/sweep.ts +32 -11
  140. package/src/symbol-keys.ts +129 -2
  141. package/src/template-field.ts +9 -6
  142. package/src/test-support.ts +149 -16
  143. package/src/type-errors.ts +132 -41
  144. package/src/type-parameter-reads.ts +227 -0
  145. package/src/value-reach.ts +19 -6
  146. package/src/verbs/analyze.ts +28 -1
  147. package/src/verbs/explain.ts +5 -2
  148. package/src/version-range.ts +10 -5
  149. package/src/version.ts +1 -1
  150. package/src/workflow-steps.ts +127 -22
  151. package/src/workspace-programs.ts +7 -3
  152. package/src/workspace-resolution.ts +86 -14
  153. package/src/workspace.ts +1 -1
@@ -4,7 +4,7 @@
4
4
  * that parameter, and a call of a method of a generic receiver fixes the receiver's by its
5
5
  * type arguments. The type query of a type-query alias is no reference.
6
6
  */
7
- import { isArrowFunction, isBindingElement, isCallExpression, isClassDeclaration, isClassExpression, isFunctionDeclaration, isFunctionExpression, isFunctionTypeNode, isIdentifier, isIndexedAccessTypeNode, isInterfaceDeclaration, isLiteralTypeNode, isMappedTypeNode, isMethodDeclaration, isMethodSignatureDeclaration, isNewExpression, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectBindingPattern, isParenthesizedTypeNode, isPropertyAccessExpression, isPropertySignatureDeclaration, isStringLiteral, isTypeAliasDeclaration, isTypeOperatorNode, isTypeReferenceNode, isUnionTypeNode, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
7
+ import { isArrowFunction, isBindingElement, isCallExpression, isClassDeclaration, isClassExpression, isConstructorDeclaration, isConstructorTypeNode, isFunctionDeclaration, isFunctionExpression, isFunctionTypeNode, isIdentifier, isIndexedAccessTypeNode, isInterfaceDeclaration, isLiteralTypeNode, isMappedTypeNode, isMethodDeclaration, isMethodSignatureDeclaration, isNewExpression, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectBindingPattern, isParenthesizedTypeNode, isPropertyAccessExpression, isPropertyAssignment, isPropertySignatureDeclaration, isStringLiteral, isTypeAliasDeclaration, isTypeOperatorNode, isTypeReferenceNode, isUnionTypeNode, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
8
8
  import { SignatureKind, SymbolFlags, } from "@typescript/native/sync";
9
9
  import { nodeKey } from "./inventory.js";
10
10
  import { renderPosition } from "./position.js";
@@ -17,12 +17,25 @@ function isGeneric(node) {
17
17
  isArrowFunction(node) ||
18
18
  isFunctionExpression(node) ||
19
19
  isFunctionTypeNode(node) ||
20
+ isConstructorTypeNode(node) ||
20
21
  isTypeAliasDeclaration(node) ||
21
22
  isInterfaceDeclaration(node) ||
22
23
  isClassDeclaration(node) ||
23
24
  isClassExpression(node)) &&
24
25
  node.typeParameters !== undefined);
25
26
  }
27
+ /** Whether a function declares no type parameter and a parameter whose type holds `keyof`. */
28
+ function takesKeyof(node) {
29
+ if (!(isFunctionDeclaration(node) ||
30
+ isMethodDeclaration(node) ||
31
+ isMethodSignatureDeclaration(node) ||
32
+ isArrowFunction(node) ||
33
+ isFunctionExpression(node)) ||
34
+ node.typeParameters !== undefined) {
35
+ return false;
36
+ }
37
+ return node.parameters.some((parameter) => parameter.type !== undefined && keyofOperands(parameter.type).length > 0);
38
+ }
26
39
  /** Whether one generic is a receiver's: a class or an interface whose methods it parameterizes. */
27
40
  function isReceiver(node) {
28
41
  return isInterfaceDeclaration(node) || isClassDeclaration(node) || isClassExpression(node);
@@ -57,8 +70,8 @@ function unwrappedType(node) {
57
70
  function literalNames(index) {
58
71
  const node = unwrappedType(index);
59
72
  if (isUnionTypeNode(node)) {
60
- const names = node.types.map(literalNames);
61
- return names.every((one) => one !== undefined) ? names.flat() : undefined;
73
+ const names = node.types.flatMap((one) => literalNames(one) ?? []);
74
+ return names.length > 0 ? names : undefined;
62
75
  }
63
76
  if (!isLiteralTypeNode(node)) {
64
77
  return undefined;
@@ -69,7 +82,7 @@ function literalNames(index) {
69
82
  }
70
83
  return isNumericLiteral(literal) ? [String(Number(literal.text))] : undefined;
71
84
  }
72
- /** The name a literal type carries, a union's each, or none where a constituent is no literal. */
85
+ /** The names the literal constituents of a type carry: a key the type names is one the access requires. */
73
86
  function literalTypeNames(type, parts) {
74
87
  const names = [];
75
88
  for (const part of parts(type)) {
@@ -79,9 +92,6 @@ function literalTypeNames(type, parts) {
79
92
  else if (part.isNumberLiteralType()) {
80
93
  names.push(String(part.value));
81
94
  }
82
- else {
83
- return undefined;
84
- }
85
95
  }
86
96
  return names;
87
97
  }
@@ -140,16 +150,21 @@ function calledName(generic) {
140
150
  }
141
151
  const parent = generic.parent;
142
152
  return parent !== undefined &&
143
- (isVariableDeclaration(parent) || isPropertySignatureDeclaration(parent)) &&
153
+ (isVariableDeclaration(parent) ||
154
+ isPropertySignatureDeclaration(parent) ||
155
+ isPropertyAssignment(parent)) &&
144
156
  isIdentifier(parent.name)
145
157
  ? parent.name.text
146
158
  : undefined;
147
159
  }
148
160
  /** The generic a declaration a symbol names is: the function a variable is initialized with included. */
149
161
  function genericOf(node) {
150
- if (isGeneric(node) || isReceiverMember(node)) {
162
+ if (isGeneric(node) || isReceiverMember(node) || takesKeyof(node)) {
151
163
  return node;
152
164
  }
165
+ if (isConstructorDeclaration(node) && isGeneric(node.parent)) {
166
+ return node.parent;
167
+ }
153
168
  if (isPropertySignatureDeclaration(node)) {
154
169
  // The typings mark the annotation present; a signature written without one has none.
155
170
  const declared = node.type;
@@ -238,6 +253,8 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
238
253
  const carried = new Map();
239
254
  const names = new Set();
240
255
  const sites = [];
256
+ /** Accesses indexed by a type parameter whose constraint is no `keyof`: it requires each key it names. */
257
+ const constrained = [];
241
258
  /** Calls passing an argument, which a generic declared outside the own files may fix. */
242
259
  const argumentCalls = [];
243
260
  const carry = (generic, one) => {
@@ -263,14 +280,23 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
263
280
  const own = held.declarations.get(nodeKey(file, node));
264
281
  const holder = own ?? from;
265
282
  const inside = isGeneric(node) ? [...enclosing, node] : enclosing;
266
- if (isGeneric(node)) {
283
+ if (isGeneric(node) || takesKeyof(node)) {
267
284
  carriedIn(node).forEach((one) => carry(node, one));
268
285
  }
269
286
  if (isIndexedAccessTypeNode(node) && !aliasTypes.has(node)) {
270
287
  const literal = literalNames(node.indexType);
288
+ const parameter = literal === undefined ? namedParameter(node.indexType, inside) : undefined;
289
+ const constraint = parameter === undefined
290
+ ? undefined
291
+ : parameter.generic.typeParameters?.[parameter.index]?.constraint;
271
292
  if (literal !== undefined) {
272
293
  accesses.push({ file, from: holder, at: node, object: node.objectType, index: literal });
273
294
  }
295
+ else if (constraint !== undefined &&
296
+ keyofOperands(constraint).length === 0 &&
297
+ namedParameter(node.objectType, inside) === undefined) {
298
+ constrained.push({ file, from: holder, at: node, object: node.objectType, constraint });
299
+ }
274
300
  }
275
301
  if (isTypeReferenceNode(node) &&
276
302
  node.typeArguments !== undefined &&
@@ -287,7 +313,7 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
287
313
  if (name !== undefined) {
288
314
  const site = { file, from: holder, node, name, enclosing: inside };
289
315
  sites.push(site);
290
- if (isCallExpression(node) && node.arguments.length > 0) {
316
+ if (argumentsOf(node).length > 0) {
291
317
  argumentCalls.push(site);
292
318
  }
293
319
  }
@@ -300,6 +326,35 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
300
326
  visit(child, fileId, []);
301
327
  });
302
328
  }
329
+ /** The literal keys one constraint names, through the type aliases it references. */
330
+ const requiredNames = (node, seen) => {
331
+ const type = unwrappedType(node);
332
+ if (isUnionTypeNode(type)) {
333
+ return type.types.flatMap((one) => requiredNames(one, seen));
334
+ }
335
+ if (!isTypeReferenceNode(type) || type.typeArguments !== undefined) {
336
+ return literalNames(type) ?? [];
337
+ }
338
+ const [symbol] = queries.symbolsAt([type.typeName]);
339
+ if (symbol === UNANSWERED || symbol === undefined) {
340
+ return [];
341
+ }
342
+ return symbol.declarations.flatMap((handle) => {
343
+ const declared = project.declarationAt(handle)?.node;
344
+ return declared !== undefined &&
345
+ isTypeAliasDeclaration(declared) &&
346
+ declared.typeParameters === undefined &&
347
+ !seen.has(declared)
348
+ ? requiredNames(declared.type, new Set([...seen, declared]))
349
+ : [];
350
+ });
351
+ };
352
+ for (const { constraint, ...access } of constrained) {
353
+ const index = requiredNames(constraint, new Set());
354
+ if (index.length > 0) {
355
+ accesses.push({ ...access, index });
356
+ }
357
+ }
303
358
  function partsOf(type) {
304
359
  const parts = queries.constituents(type);
305
360
  return parts === UNANSWERED ? [type] : parts;
@@ -322,11 +377,13 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
322
377
  * variable holding the callee is initialized with.
323
378
  */
324
379
  const receiverTypeOf = (callee) => {
380
+ let operand;
325
381
  if (isPropertyAccessExpression(callee)) {
326
382
  const type = queries.typeAt(callee.expression);
327
- const args = type === UNANSWERED || type === undefined ? [] : queries.typeArguments(type);
328
- if (type !== UNANSWERED && type !== undefined && args !== UNANSWERED && args.length > 0) {
329
- return type;
383
+ operand = type === UNANSWERED ? undefined : type;
384
+ const args = operand === undefined ? [] : queries.typeArguments(operand);
385
+ if (operand !== undefined && args !== UNANSWERED && args.length > 0) {
386
+ return operand;
330
387
  }
331
388
  }
332
389
  const name = isPropertyAccessExpression(callee) ? callee.name : callee;
@@ -335,7 +392,7 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
335
392
  ? named
336
393
  : queries.aliased(named);
337
394
  if (symbol === UNANSWERED || symbol === undefined) {
338
- return undefined;
395
+ return operand;
339
396
  }
340
397
  for (const handle of symbol.declarations) {
341
398
  const node = project.declarationAt(handle)?.node;
@@ -355,7 +412,40 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
355
412
  return type;
356
413
  }
357
414
  }
358
- return undefined;
415
+ return operand;
416
+ };
417
+ /**
418
+ * The instantiation of `owner` a receiver's type is, or the first one among the base
419
+ * types it extends, breadth first: a subclass fixes its base's type parameters, and
420
+ * `this` stands for its class.
421
+ */
422
+ const instantiationOf = (type, owner) => {
423
+ const seen = new Set();
424
+ for (let queue = [type]; queue.length > 0;) {
425
+ const next = [];
426
+ for (const at of queue) {
427
+ if (seen.has(at.id)) {
428
+ continue;
429
+ }
430
+ seen.add(at.id);
431
+ const target = at.isTypeReference() ? queries.targetOf(at) : at;
432
+ const symbol = target === UNANSWERED ? undefined : queries.symbolOfType(target);
433
+ const declares = symbol !== undefined &&
434
+ symbol !== UNANSWERED &&
435
+ symbol.declarations.some((handle) => project.declarationAt(handle)?.node === owner);
436
+ if (declares) {
437
+ return at;
438
+ }
439
+ const constraint = at.isTypeParameter() ? queries.constraintOf(at) : undefined;
440
+ const bases = at.isTypeParameter() ? [] : queries.baseTypes(at);
441
+ next.push(...(bases === UNANSWERED ? [] : bases));
442
+ if (constraint !== undefined && constraint !== UNANSWERED) {
443
+ next.push(constraint);
444
+ }
445
+ }
446
+ queue = next;
447
+ }
448
+ return type;
359
449
  };
360
450
  /** What one site fixes for one side of a carried access. */
361
451
  const fixedAt = (site, side, generic) => {
@@ -365,7 +455,9 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
365
455
  const { node } = site;
366
456
  if (side.kind === "receiver") {
367
457
  const callee = isCallExpression(node) ? node.expression : undefined;
368
- const receiver = callee === undefined ? undefined : receiverTypeOf(callee);
458
+ const owner = receiverOf(generic);
459
+ const typed = callee === undefined ? undefined : receiverTypeOf(callee);
460
+ const receiver = typed === undefined || owner === undefined ? typed : instantiationOf(typed, owner);
369
461
  if (receiver === undefined) {
370
462
  return undefined;
371
463
  }
@@ -389,7 +481,7 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
389
481
  if (isTypeReferenceNode(node)) {
390
482
  return undefined;
391
483
  }
392
- const at = (generic.parameters ?? []).findIndex((parameter) => {
484
+ const at = parametersOf(generic).findIndex((parameter) => {
393
485
  const type = parameter.type === undefined ? undefined : unwrappedType(parameter.type);
394
486
  return (type !== undefined &&
395
487
  isTypeReferenceNode(type) &&
@@ -482,9 +574,7 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
482
574
  // by its type parameters and its receiver's. Only a call passing an argument the compiler
483
575
  // types as a literal can fix an index, so only such a call's signature is resolved.
484
576
  const outside = argumentCalls.filter((site) => !resolvedGenerics.has(site));
485
- const argumentNodes = argumentCalls.flatMap((site) => [
486
- ...site.node.arguments,
487
- ]);
577
+ const argumentNodes = argumentCalls.flatMap((site) => argumentsOf(site.node));
488
578
  const argumentTypes = queries.typesAt(argumentNodes);
489
579
  const literalArgument = new Set();
490
580
  argumentTypes.forEach((type, at) => {
@@ -492,13 +582,13 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
492
582
  if (node !== undefined &&
493
583
  type !== UNANSWERED &&
494
584
  type !== undefined &&
495
- (literalTypeNames(type, partsOf)?.length ?? 0) > 0) {
585
+ literalTypeNames(type, partsOf).length > 0) {
496
586
  literalArgument.add(node);
497
587
  }
498
588
  });
499
589
  const own = project.ownPaths();
500
590
  for (const site of outside) {
501
- if (!site.node.arguments.some((one) => literalArgument.has(one))) {
591
+ if (!argumentsOf(site.node).some((one) => literalArgument.has(one))) {
502
592
  continue;
503
593
  }
504
594
  const resolved = queries.resolvedSignature(site.node);
@@ -516,7 +606,7 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
516
606
  }
517
607
  }
518
608
  for (const site of argumentCalls) {
519
- if (site.node.arguments.some((one) => literalArgument.has(one))) {
609
+ if (argumentsOf(site.node).some((one) => literalArgument.has(one))) {
520
610
  accesses.push(...instantiatedAccesses(site));
521
611
  }
522
612
  }
@@ -536,7 +626,7 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
536
626
  generic === undefined) {
537
627
  return [];
538
628
  }
539
- const count = site.node.arguments.length;
629
+ const count = argumentsOf(site.node).length;
540
630
  const parameters = [];
541
631
  for (let at = 0; at < count; at += 1) {
542
632
  const type = queries.parameterType(generic, at);
@@ -573,13 +663,13 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
573
663
  }
574
664
  const names = access.index.isTypeParameter()
575
665
  ? parameters.flatMap((parameter, at) => {
576
- if (parameter.id !== access.index.id) {
666
+ if (!partsOf(parameter).some((part) => part.id === access.index.id)) {
577
667
  return [];
578
668
  }
579
669
  const passed = queries.typeAtPosition(resolved, at);
580
- return passed === UNANSWERED ? [] : (literalTypeNames(passed, partsOf) ?? []);
670
+ return passed === UNANSWERED ? [] : literalTypeNames(passed, partsOf);
581
671
  })
582
- : (literalTypeNames(access.index, partsOf) ?? []);
672
+ : literalTypeNames(access.index, partsOf);
583
673
  if (names.length > 0) {
584
674
  found.push({
585
675
  file: site.file,
@@ -643,6 +733,18 @@ export function indexedAccessReferences(project, held, chains, root, testFiles)
643
733
  }
644
734
  return found;
645
735
  }
736
+ /** The arguments a call or a `new` expression passes, none for a type reference. */
737
+ function argumentsOf(node) {
738
+ return isTypeReferenceNode(node) ? [] : (node.arguments ?? []);
739
+ }
740
+ /** The parameters a site's arguments bind: a class's are its constructor's. */
741
+ function parametersOf(generic) {
742
+ if (isClassDeclaration(generic) || isClassExpression(generic)) {
743
+ const constructor = generic.members.find(isConstructorDeclaration);
744
+ return constructor?.parameters ?? [];
745
+ }
746
+ return generic.parameters ?? [];
747
+ }
646
748
  /** What makes two carried accesses one: the kind and position of each side, or its written node. */
647
749
  function sideKey(one) {
648
750
  const key = (side) => side.kind === "written" ? ["written", side.node.pos, side.node.end] : [side.kind, side.index];
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * The interface-satisfaction class: a member is held back when a value of its class
3
- * reaches a position the checker types as an interface requiring that member, through an
4
- * `implements` entry, a typed initializer, an assignment, an argument, a return, an array
5
- * element, an object property or an `as` or `satisfies` operand. `this` is a value of its
6
- * class, and a position typed by a type parameter reaches its constraint. The contextual
7
- * lookup has no batch form, so it is asked only of a value typed as a target class.
3
+ * reaches a position typed as an interface, or an object type a type alias names, that
4
+ * requires the member: an `implements` entry, a typed initializer, an assignment, an
5
+ * argument, a return, an array element, an object property or an `as` or `satisfies`
6
+ * operand. `this` is a value of its class; a type parameter reaches its constraint. The
7
+ * contextual lookup has no batch form, so it is asked only of a value of a target class.
8
8
  */
9
- import { isCallExpression, isClassDeclaration, isClassExpression, isClassStaticBlockDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isHeritageClause, isMethodDeclaration, isNewExpression, isObjectLiteralExpression, isSetAccessorDeclaration, ModifierFlags, SyntaxKind, } from "@typescript/native/ast";
9
+ import { isCallExpression, isClassDeclaration, isClassExpression, isClassStaticBlockDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isHeritageClause, isMethodDeclaration, isNewExpression, isObjectLiteralExpression, isSetAccessorDeclaration, isTypeLiteralNode, ModifierFlags, SyntaxKind, } from "@typescript/native/ast";
10
10
  import { SymbolFlags } from "@typescript/native/sync";
11
11
  import { aliasChains } from "./alias-chain.js";
12
12
  import { emptyImplementation } from "./implementations.js";
@@ -14,6 +14,10 @@ import { nodeKey } from "./inventory.js";
14
14
  import { renderPosition } from "./position.js";
15
15
  import { must } from "./query.js";
16
16
  import { handedOn, valuesOf } from "./value-flow.js";
17
+ /** Whether a type alias names one type: the client's type object carries the alias it was written through. */
18
+ function aliased(type) {
19
+ return type.aliasSymbol !== undefined;
20
+ }
17
21
  /** Whether one node declares a static member, whose `this` is the class itself. */
18
22
  function isStatic(node) {
19
23
  const flags = node.modifierFlags ?? 0;
@@ -146,19 +150,33 @@ export function interfaceSatisfaction(input) {
146
150
  return generic === undefined ? [] : [{ owner: generic, type: part }];
147
151
  });
148
152
  const interfaceNames = new Map();
149
- /** The interface types one position's type is or holds, each with the interface's name. */
153
+ /**
154
+ * The interface types one position's type is or holds, each with the interface's name:
155
+ * an interface, or an object type literal a type alias names, directly or as a
156
+ * constituent of an intersection the alias names.
157
+ */
150
158
  const interfacesOf = (type) => partsOf(type).flatMap((part) => {
151
159
  if (part.isTypeParameter()) {
152
160
  const constraint = must(queries.constraintOf(part));
153
161
  return constraint === undefined ? [] : interfacesOf(constraint);
154
162
  }
155
- if (!interfaceNames.has(part.id)) {
163
+ const named = aliased(part) ? part : aliased(type) ? type : undefined;
164
+ const key = `${String(part.id)}:${String(named?.id ?? "")}`;
165
+ if (!interfaceNames.has(key)) {
156
166
  const symbol = part.isObjectType() ? must(queries.symbolOfType(part)) : undefined;
157
- interfaceNames.set(part.id, symbol !== undefined && (symbol.flags & SymbolFlags.Interface) !== 0
158
- ? symbol.name
159
- : undefined);
167
+ const flags = symbol?.flags ?? 0;
168
+ interfaceNames.set(key, (flags & SymbolFlags.Interface) !== 0
169
+ ? symbol?.name
170
+ : (flags & SymbolFlags.TypeLiteral) !== 0 &&
171
+ named !== undefined &&
172
+ symbol?.declarations.some((handle) => {
173
+ const node = project.declarationAt(handle)?.node;
174
+ return node !== undefined && isTypeLiteralNode(node);
175
+ }) === true
176
+ ? must(queries.typeToString(named))
177
+ : undefined);
160
178
  }
161
- const name = interfaceNames.get(part.id);
179
+ const name = interfaceNames.get(key);
162
180
  return name === undefined ? [] : [{ type: part, name }];
163
181
  });
164
182
  /**