@cplieger/deadset-ts 6.1.1-dev.1 → 7.0.0-dev.2

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 (98) hide show
  1. package/dist/src/analysis.js +45 -32
  2. package/dist/src/component-layer.js +1 -1
  3. package/dist/src/configuration-files.js +227 -27
  4. package/dist/src/conformance-record.js +2 -2
  5. package/dist/src/contextual-uses.js +68 -10
  6. package/dist/src/convention-rows.js +48 -0
  7. package/dist/src/conventions.js +80 -0
  8. package/dist/src/dependencies.js +121 -46
  9. package/dist/src/discover.js +1 -1
  10. package/dist/src/edges.js +1 -1
  11. package/dist/src/exempt-classes.js +9 -22
  12. package/dist/src/exempt.js +3 -15
  13. package/dist/src/findings/completion.js +41 -11
  14. package/dist/src/findings/dependencies-and-module-machinery.js +6 -26
  15. package/dist/src/findings/emitters.js +0 -4
  16. package/dist/src/findings/self-check.js +14 -10
  17. package/dist/src/html-entries.js +29 -14
  18. package/dist/src/indexed-access.js +377 -81
  19. package/dist/src/intra-function-parts.js +57 -11
  20. package/dist/src/inventory.js +3 -12
  21. package/dist/src/kinds.js +6 -6
  22. package/dist/src/references.js +62 -23
  23. package/dist/src/report.js +3 -0
  24. package/dist/src/roots.js +96 -7
  25. package/dist/src/run.js +0 -2
  26. package/dist/src/schema.js +1 -1
  27. package/dist/src/scope.js +2 -2
  28. package/dist/src/session.js +6 -2
  29. package/dist/src/source-files.js +1 -0
  30. package/dist/src/suppress-inline.js +1 -1
  31. package/dist/src/suppress.js +15 -16
  32. package/dist/src/sweep.js +29 -17
  33. package/dist/src/symbol-keys.js +114 -0
  34. package/dist/src/test-joins.js +101 -0
  35. package/dist/src/version.js +1 -1
  36. package/dist/src/workflow-steps.js +21 -15
  37. package/dist/src/workspace-programs.js +1 -4
  38. package/dist/src/workspace-resolution.js +0 -2
  39. package/dist/src/workspace.js +0 -3
  40. package/jsr.json +1 -1
  41. package/package.json +2 -1
  42. package/src/analysis.ts +55 -47
  43. package/src/calls.ts +3 -3
  44. package/src/component-files.ts +7 -7
  45. package/src/component-layer.ts +2 -2
  46. package/src/components.ts +1 -1
  47. package/src/config.ts +4 -4
  48. package/src/configuration-files.ts +246 -28
  49. package/src/conformance-record.ts +2 -2
  50. package/src/contextual-uses.ts +99 -13
  51. package/src/convention-rows.ts +76 -0
  52. package/src/conventions.ts +102 -0
  53. package/src/dependencies.ts +148 -56
  54. package/src/discover.ts +3 -3
  55. package/src/edges.ts +3 -3
  56. package/src/entry-points.ts +1 -1
  57. package/src/exempt-classes.ts +10 -24
  58. package/src/exempt.ts +5 -29
  59. package/src/file-facts.ts +1 -1
  60. package/src/finding.ts +5 -1
  61. package/src/findings/completion.ts +53 -11
  62. package/src/findings/dependencies-and-module-machinery.ts +9 -28
  63. package/src/findings/emitters.ts +3 -8
  64. package/src/findings/self-check.ts +17 -14
  65. package/src/findings-pass.ts +2 -2
  66. package/src/graph.ts +2 -2
  67. package/src/html-entries.ts +34 -16
  68. package/src/indexed-access.ts +476 -102
  69. package/src/intra-function-parts.ts +84 -12
  70. package/src/inventory.ts +5 -33
  71. package/src/json-document.ts +1 -1
  72. package/src/kinds.ts +7 -6
  73. package/src/manifest.ts +1 -1
  74. package/src/namespace-objects.ts +1 -1
  75. package/src/pnpm-workspace.ts +1 -1
  76. package/src/references.ts +93 -33
  77. package/src/report.ts +8 -4
  78. package/src/roots.ts +129 -9
  79. package/src/run.ts +0 -2
  80. package/src/schema.ts +2 -2
  81. package/src/scope.ts +2 -2
  82. package/src/session.ts +7 -3
  83. package/src/source-files.ts +3 -0
  84. package/src/stores.ts +1 -1
  85. package/src/suppress-inline.ts +3 -3
  86. package/src/suppress.ts +21 -24
  87. package/src/sweep.ts +29 -17
  88. package/src/symbol-keys.ts +172 -0
  89. package/src/template-field.ts +1 -1
  90. package/src/test-joins.ts +120 -0
  91. package/src/value-reach.ts +1 -1
  92. package/src/verbs/verb.ts +1 -4
  93. package/src/version.ts +1 -1
  94. package/src/workflow-steps.ts +23 -16
  95. package/src/workspace-programs.ts +3 -10
  96. package/src/workspace-resolution.ts +0 -3
  97. package/src/workspace-run.ts +1 -1
  98. package/src/workspace.ts +1 -9
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import {
9
+ isArrayBindingPattern,
9
10
  isArrowFunction,
10
11
  isAwaitExpression,
11
12
  isBigIntLiteral,
@@ -55,10 +56,12 @@ import {
55
56
  isVoidExpression,
56
57
  NodeFlags,
57
58
  SyntaxKind,
59
+ type ArrowFunction,
58
60
  type BindingName,
59
61
  type Block,
60
62
  type CallExpression,
61
63
  type CatchClause,
64
+ type FunctionExpression,
62
65
  type Identifier,
63
66
  type Node,
64
67
  type SourceFile,
@@ -473,6 +476,7 @@ export function projectParts<Brand>(
473
476
  const calls = new Map<string, boolean>();
474
477
  const specifiers = new Set<string>();
475
478
  const sites: { readonly file: SourceFile; readonly declared: Declared }[] = [];
479
+ const contextual: ContextualParameter[] = [];
476
480
 
477
481
  for (const file of files) {
478
482
  const declarationAt = (node: Node): string | undefined => {
@@ -624,15 +628,25 @@ export function projectParts<Brand>(
624
628
  });
625
629
  const reader = readers.get(one.signature);
626
630
  if (reader !== undefined) {
627
- parts.push(...parameterParts(file, targetRoot, one.id, one.signature, reader, ids, false));
631
+ const found = parameterParts(file, targetRoot, one.id, one.signature, reader, ids, false);
632
+ parts.push(...found.parts);
633
+ contextual.push(...found.contextual);
628
634
  }
629
635
  }
630
636
  for (const one of walk.values) {
631
637
  const reader = readers.get(one.signature);
632
638
  if (reader !== undefined) {
633
- parts.push(
634
- ...parameterParts(file, targetRoot, one.holder, one.signature, reader, ids, true),
639
+ const found = parameterParts(
640
+ file,
641
+ targetRoot,
642
+ one.holder,
643
+ one.signature,
644
+ reader,
645
+ ids,
646
+ true,
635
647
  );
648
+ parts.push(...found.parts);
649
+ contextual.push(...found.contextual);
636
650
  }
637
651
  }
638
652
  walk.catches.forEach(({ name, holder }, at) => {
@@ -677,7 +691,7 @@ export function projectParts<Brand>(
677
691
  }
678
692
 
679
693
  parts.push(...resultParts(project, targetRoot, sites, references, calls));
680
- return { parts, signatures, calls, specifiers };
694
+ return { parts: withContextualRead(project, parts, contextual), signatures, calls, specifiers };
681
695
  }
682
696
 
683
697
  /**
@@ -743,9 +757,38 @@ function parameterNames(signature: SignatureNode): ParameterName[] {
743
757
  return found;
744
758
  }
745
759
 
760
+ /** An unread name of a parameter that a contextual type of its function expression keeps. */
761
+ interface ContextualParameter {
762
+ readonly part: PartFact;
763
+ readonly signature: ArrowFunction | FunctionExpression;
764
+ }
765
+
766
+ /**
767
+ * The parts with each name of `contextual` read where the compiler gives its function a
768
+ * contextual type: the inference of the call holding the function may read a parameter's
769
+ * annotation, and the code handing the argument may act on what an object pattern reads.
770
+ * A question the checker leaves unanswered keeps the name read.
771
+ */
772
+ function withContextualRead<Brand>(
773
+ project: ProjectView<Brand>,
774
+ parts: readonly PartFact[],
775
+ contextual: readonly ContextualParameter[],
776
+ ): readonly PartFact[] {
777
+ if (contextual.length === 0) {
778
+ return parts;
779
+ }
780
+ const signatures = [...new Set(contextual.map((one) => one.signature))];
781
+ const answers = project.queries.contextualTypes(signatures);
782
+ const typed = new Set(signatures.filter((_signature, at) => answers[at] !== undefined));
783
+ const read = new Set(contextual.filter((one) => typed.has(one.signature)).map((one) => one.part));
784
+ return parts.map((part) => (read.has(part) ? { ...part, used: true } : part));
785
+ }
786
+
746
787
  /**
747
- * Each name one function's parameters bind and whether the function reads it. A binding
748
- * pattern counts as read where its function reads any name it binds.
788
+ * Each name one function's parameters bind and whether the function reads it, and the
789
+ * unread names a contextual type of a function expression may keep: those of a parameter
790
+ * that carries a type annotation or is an object binding pattern. A binding pattern counts
791
+ * as read where its function reads any name it binds.
749
792
  */
750
793
  function parameterParts(
751
794
  file: SourceFile,
@@ -755,7 +798,7 @@ function parameterParts(
755
798
  reader: { readonly names: readonly ParameterName[]; readonly uses: readonly Identifier[] },
756
799
  ids: ReadonlyMap<Node, Answer<number>>,
757
800
  inValue: boolean,
758
- ): PartFact[] {
801
+ ): { readonly parts: PartFact[]; readonly contextual: ContextualParameter[] } {
759
802
  // A function that reads `arguments` reads every parameter by position.
760
803
  const readsArguments =
761
804
  !isArrowFunction(signature) && identifiersNaming(signature, new Set(["arguments"])).length > 0;
@@ -766,11 +809,14 @@ function parameterParts(
766
809
  );
767
810
  const lastRead = Math.max(-1, ...reader.names.filter((_, at) => read[at]).map((one) => one.at));
768
811
  const found: PartFact[] = [];
812
+ const contextual: ContextualParameter[] = [];
813
+ const expression =
814
+ isArrowFunction(signature) || isFunctionExpression(signature) ? signature : undefined;
769
815
  reader.names.forEach(({ name, at, pattern, exempt }, index) => {
770
816
  if (exempt) {
771
817
  return;
772
818
  }
773
- found.push({
819
+ const part: PartFact = {
774
820
  code: UNUSED_PARAMETER,
775
821
  declaration,
776
822
  kind: "parameter",
@@ -779,9 +825,19 @@ function parameterParts(
779
825
  message: `parameter ${name.text} is never read in the body`,
780
826
  used: read[index] === true,
781
827
  parameter: { beforeARead: !pattern && at < lastRead, inValue },
782
- });
828
+ };
829
+ found.push(part);
830
+ const parameter = signature.parameters[at];
831
+ if (
832
+ expression !== undefined &&
833
+ !part.used &&
834
+ parameter !== undefined &&
835
+ (parameter.type !== undefined || isObjectBindingPattern(parameter.name))
836
+ ) {
837
+ contextual.push({ part, signature: expression });
838
+ }
783
839
  });
784
- return found;
840
+ return { parts: found, contextual };
785
841
  }
786
842
 
787
843
  /** One local a block declares by name, and every identifier of the block that spells it. */
@@ -792,6 +848,22 @@ interface Local {
792
848
  readonly uses: readonly Identifier[];
793
849
  }
794
850
 
851
+ /**
852
+ * The names one declaration binds that a write of its initializer stores each on its own:
853
+ * the declared name, or each element name of an array binding pattern at any depth.
854
+ */
855
+ function arrayPatternNames(name: BindingName): readonly Identifier[] {
856
+ if (isIdentifier(name)) {
857
+ return [name];
858
+ }
859
+ if (!isArrayBindingPattern(name)) {
860
+ return [];
861
+ }
862
+ return name.elements.flatMap((element) =>
863
+ isBindingElement(element) && element.name !== undefined ? arrayPatternNames(element.name) : [],
864
+ );
865
+ }
866
+
795
867
  /** The locals one block declares with `let` or `const`, each with the names that spell it. */
796
868
  function localsOf(block: Block): readonly Local[] {
797
869
  const declared: { name: Identifier; statement: number; initialized: boolean }[] = [];
@@ -807,9 +879,9 @@ function localsOf(block: Block): readonly Local[] {
807
879
  return;
808
880
  }
809
881
  for (const declaration of list.declarations) {
810
- if (isIdentifier(declaration.name)) {
882
+ for (const name of arrayPatternNames(declaration.name)) {
811
883
  declared.push({
812
- name: declaration.name,
884
+ name,
813
885
  statement: at,
814
886
  initialized: declaration.initializer !== undefined,
815
887
  });
package/src/inventory.ts CHANGED
@@ -139,8 +139,6 @@ export interface InventoryCost {
139
139
 
140
140
  /** One project's declarations, in position order, and what reading them cost. */
141
141
  export interface Inventory {
142
- /** The compiler configuration the project was opened from. */
143
- readonly configFile: string;
144
142
  readonly symbols: readonly InventorySymbol[];
145
143
  /**
146
144
  * Each declaring node's {@link nodeKey} mapped to the identifier of the declaration
@@ -154,20 +152,6 @@ export interface Inventory {
154
152
  */
155
153
  readonly declarations: ReadonlyMap<string, string>;
156
154
  readonly cost: InventoryCost;
157
- /**
158
- * The module specifiers of the bare star re-exports the project's files carry, in
159
- * the order they were read. A bare star re-export declares nothing here: the names
160
- * it carries forward are the declarations of the module it names, so it is a
161
- * reference to that module and not a declaration of this one.
162
- */
163
- readonly starReExports: readonly string[];
164
- /**
165
- * The number of member declarations that were left out because the file declaring
166
- * them is not one of the target's own files. Such a declaration belongs to another
167
- * program, so the target's inventory does not name it, and the count is reported so
168
- * that the omission is a number rather than a silence.
169
- */
170
- readonly outsideOwnFiles: number;
171
155
  /**
172
156
  * The declarations whose module, namespace or container table the checker did not
173
157
  * answer, in position order: whether each is exported, and which members a table
@@ -534,9 +518,7 @@ export function inventory<Brand>(
534
518
  const byNode = new Map<string, Building>();
535
519
  const exportScopes: ExportScope[] = [];
536
520
  const containers: Container[] = [];
537
- const starReExports: string[] = [];
538
521
  const modules: (readonly [Building, string])[] = [];
539
- let outsideOwnFiles = 0;
540
522
 
541
523
  const keep = (record: Building): Building => {
542
524
  building.push(record);
@@ -782,14 +764,10 @@ export function inventory<Brand>(
782
764
  }
783
765
  }
784
766
 
785
- function walkExportDeclaration(
786
- node: { readonly exportClause?: Node; readonly moduleSpecifier?: Node },
787
- owner: Building,
788
- ): void {
767
+ function walkExportDeclaration(node: { readonly exportClause?: Node }, owner: Building): void {
789
768
  const clause = node.exportClause;
769
+ // A bare star re-export declares nothing: the names it carries are the named module's.
790
770
  if (clause === undefined) {
791
- const specifier = node.moduleSpecifier;
792
- starReExports.push(specifier === undefined ? "" : literalTextOf(specifier));
793
771
  return;
794
772
  }
795
773
  if (isNamespaceExport(clause)) {
@@ -876,7 +854,7 @@ export function inventory<Brand>(
876
854
  memberTables += 1;
877
855
  const table = project.queries.membersOf(symbol);
878
856
  if (isAnswered(table)) {
879
- outsideOwnFiles += readTable(container, table, seen, false);
857
+ readTable(container, table, seen, false);
880
858
  } else {
881
859
  unansweredOwners.add(container.owner);
882
860
  }
@@ -885,7 +863,7 @@ export function inventory<Brand>(
885
863
  memberTables += 1;
886
864
  const table = project.queries.exportsOf(symbol);
887
865
  if (isAnswered(table)) {
888
- outsideOwnFiles += readTable(container, table, seen, container.isClass);
866
+ readTable(container, table, seen, container.isClass);
889
867
  } else {
890
868
  unansweredOwners.add(container.owner);
891
869
  }
@@ -905,8 +883,7 @@ export function inventory<Brand>(
905
883
  table: ReadonlyMap<string, TSSymbol>,
906
884
  seen: Map<string, Building>,
907
885
  areStatic: boolean,
908
- ): number {
909
- let outside = 0;
886
+ ): void {
910
887
  for (const [, member] of table) {
911
888
  const declarations = member.declarations
912
889
  .map((handle) => project.declarationAt(handle))
@@ -916,7 +893,6 @@ export function inventory<Brand>(
916
893
  }
917
894
  const own = declarations.filter((held) => ownFiles.has(held.node.getSourceFile().fileName));
918
895
  if (own.length === 0) {
919
- outside += declarations.length;
920
896
  continue;
921
897
  }
922
898
  // A merged symbol's table holds the members every one of its declarations writes,
@@ -925,7 +901,6 @@ export function inventory<Brand>(
925
901
  keepMember(container, held.node, seen, areStatic);
926
902
  }
927
903
  }
928
- return outside;
929
904
  }
930
905
 
931
906
  /**
@@ -1017,14 +992,11 @@ export function inventory<Brand>(
1017
992
  .sort((a, b) => byPosition(a.position, b.position) || (a.ref < b.ref ? -1 : 1));
1018
993
 
1019
994
  return {
1020
- configFile: project.configFile,
1021
995
  symbols,
1022
996
  declarations: new Map(
1023
997
  [...byNode].map(([key, record]) => [key, positionKey(record.position)] as const),
1024
998
  ),
1025
999
  cost: { batches: 1, exportTables, memberTables },
1026
- starReExports,
1027
- outsideOwnFiles,
1028
1000
  unanswered: symbols
1029
1001
  .filter((symbol) => underUnanswered(byId.get(symbol.id), unansweredOwners))
1030
1002
  .map((symbol) => symbol.id),
@@ -100,7 +100,7 @@ class Walk {
100
100
  }
101
101
 
102
102
  /** What a walk of one document found. */
103
- export interface DocumentWalk {
103
+ interface DocumentWalk {
104
104
  /** The offset of the brace opening each object of the document's array member, in order. */
105
105
  readonly opened: readonly number[];
106
106
  /** The first member one object writes twice, at any depth, as the offset of its name. */
package/src/kinds.ts CHANGED
@@ -101,7 +101,7 @@ const ROWS: readonly KindRow[] = [
101
101
  code: "DS1101",
102
102
  name: "unnecessary-export",
103
103
  languages: ["go", "ts"],
104
- rule: "An exported symbol whose every reference is inside the symbol's own package or module, reported as a candidate for unexporting. The subject is a package-level declaration or a method. Three subjects are excluded. An interface method is excluded because its exportedness is the contract of the interface that declares it. A struct field is excluded because an encoder reads it by name. A method that satisfies an interface some symbol uses as a type is excluded because it cannot be unexported without its type ceasing to satisfy that interface. The finding names the narrower visibility the references support. A declared cross-language edge counts as an out-of-package reference. Where the edge's other side is unknown to the analyzer, the finding is emitted pending.",
104
+ rule: "An exported symbol whose every reference is inside the symbol's own package or module, reported as a candidate for unexporting. The subject is a package-level declaration or a method. Three subjects are excluded. An interface method is excluded because its exportedness is the contract of the interface that declares it. A struct field is excluded because an encoder reads it by name. A method that satisfies an interface some symbol uses as a type is excluded because it cannot be unexported without its type ceasing to satisfy that interface, and so is a method whose name and signature are those of a method of an exported interface type declared by a package outside the target that the import closure holds, because that interface fixes them whether or not the program converts the method's type to it. The finding names the narrower visibility the references support. A declared cross-language edge counts as an out-of-package reference. Where the edge's other side is unknown to the analyzer, the finding is emitted pending. A reference from a Go external test package, a test file whose package clause names its directory's package with the suffix _test, is a reference from outside the package, because that test builds as another package and needs the export.",
105
105
  precondition:
106
106
  "Closed world only. A Go main package, and an internal/ directory tree for importers outside its parent, are closed worlds whatever the configuration declares, because no other program can import them, so this finding is reported there always. A published package is a closed world only when the configuration declares the consumer set complete and every declared consumer loads. A library with no consumer loaded and no complete consumer set declared gets this finding on its internal/ tree and its main packages and never on its published API. A symbol the rule of DS1301 holds for is not reported under this code, whatever severity the configuration gives DS1301, because the write-only finding names the defect to fix first. A type that a parameter or a result of an exported function or method of its own package names is not reported when a reference from outside the package references that function or method, because the caller holds values of the type, and unexporting it would leave an exported signature naming a type its callers cannot name.",
107
107
  defaultSeverity: "warn",
@@ -113,7 +113,7 @@ const ROWS: readonly KindRow[] = [
113
113
  code: "DS1102",
114
114
  name: "unnecessary-exposure",
115
115
  languages: ["go"],
116
- rule: "An exported symbol of a non-internal package whose every reference is inside the target module, reported as a candidate for relocation behind an internal boundary. The subject is a package-level declaration or a method. Three subjects are excluded. An interface method is excluded because its exportedness is the contract of the interface that declares it. A struct field is excluded because an encoder reads it by name. A method that satisfies an interface some symbol uses as a type is excluded because it cannot be unexported without its type ceasing to satisfy that interface. The finding names the narrower visibility the references support. A declared cross-language edge counts as an out-of-package reference. Where the edge's other side is unknown to the analyzer, the finding is emitted pending.",
116
+ rule: "An exported symbol of a non-internal package whose every reference is inside the target module, reported as a candidate for relocation behind an internal boundary. The subject is a package-level declaration or a method. Three subjects are excluded. An interface method is excluded because its exportedness is the contract of the interface that declares it. A struct field is excluded because an encoder reads it by name. A method that satisfies an interface some symbol uses as a type is excluded because it cannot be unexported without its type ceasing to satisfy that interface, and so is a method whose name and signature are those of a method of an exported interface type declared by a package outside the target that the import closure holds, because that interface fixes them whether or not the program converts the method's type to it. The finding names the narrower visibility the references support. A declared cross-language edge counts as an out-of-package reference. Where the edge's other side is unknown to the analyzer, the finding is emitted pending. A reference from a Go external test package, a test file whose package clause names its directory's package with the suffix _test, is a reference from outside the package, because that test builds as another package and needs the export.",
117
117
  precondition:
118
118
  "Closed world only. Reported always for a main package and an internal/ directory tree, and for a published package only when the configuration declares the consumer set complete and every declared consumer loads. A library with no consumer loaded and no complete consumer set declared gets this finding on its internal/ tree and its main packages and never on its published API. A symbol the rule of DS1301 holds for is not reported under this code, whatever severity the configuration gives DS1301, because the write-only finding names the defect to fix first. A type that a parameter or a result of an exported function or method of its own package names is not reported when a reference from outside the target module references that function or method, because the caller holds values of the type, and moving it behind an internal boundary would leave an exported signature naming a type its callers cannot name.",
119
119
  defaultSeverity: "warn",
@@ -235,7 +235,7 @@ const ROWS: readonly KindRow[] = [
235
235
  languages: ["go", "ts"],
236
236
  rule: "A directly declared dependency that no import in the target needs. On the Go side, a direct require whose module provides no package any target package or test variant imports. On the TypeScript side, a manifest dependency, development dependency or peer dependency the project's import closure does not need. A deletion finding whose fix would remove the last use of a dependency names that dependency.",
237
237
  precondition:
238
- "On the Go side the rule is the semantics of `go mod tidy -diff` exactly: a requirement marked indirect is never reported, because it exists to pin a transitive version and removing it changes the build list. On the TypeScript side the import closure is the files of the run's projects, and four more dependencies are needed. The first is one whose installed manifest declares a command, because a command is run by name rather than imported. The second is one that the installed manifest of a needed dependency declares as a peer and does not mark optional. The third is every required peer of a dependency so held, to a fixpoint. The fourth is one that a string names under a manifest key of an applied convention row, as grammar/analysis.md states. An installed manifest is the package's manifest in the nearest node_modules directory at or above the target, and a dependency with none is decided by the import closure alone.",
238
+ "On the Go side the rule is the semantics of `go mod tidy -diff` exactly: a requirement marked indirect is never reported, because it exists to pin a transitive version and removing it changes the build list. On the TypeScript side the import closure is the files of the run's projects, and a call of `import.meta.resolve` or of `require.resolve` in them, whatever `require` names, whose first argument is a string literal or a template literal with no substitution needs each dependency an import of that specifier needs. Three more dependencies are needed: one whose command a script entry or a workflow step runs, one that a string of a configuration file names, and one that a string names under a manifest key or a package key of an applied convention row, each as grammar/analysis.md states. A command no script entry and no workflow step runs needs nothing, and a peer the installed manifest of a needed dependency requires is needed only as any other dependency is, because the package manager installs a required peer itself. A dependency of a manifest whose directory holds source only in configurations the run lists in configurations_not_built is reported at the reachability class possible, because the source that may import it was not analyzed. An installed manifest is the package's manifest in the nearest node_modules directory at or above the target, and a dependency with none is decided by the import closure alone.",
239
239
  defaultSeverity: "deny",
240
240
  maxClass: "certain",
241
241
  fixability: "manual",
@@ -319,7 +319,7 @@ const ROWS: readonly KindRow[] = [
319
319
  languages: ["go", "ts"],
320
320
  rule: "A parameter with no reference inside its function body, on a function whose signature is free to change.",
321
321
  precondition:
322
- "The signature must be free, defined as follows: the function is not a method retained by interface satisfaction, is not used as a value, is not a go:linkname or cgo target, is not a function the Go test driver runs (a test, benchmark or fuzz test of a test file, or TestMain), and is not a stub whose body is empty or only panics. A parameter its body never names is dead whatever the callers, so a published declaration of a library is reported too, with the fixability the vocabulary gives the kind: the signature change is a breaking change. In TypeScript a caller may pass a function used as a value more arguments than it declares parameters, so in such a function whose signature is free but for that use, a parameter its body never reads is reported when its body reads no parameter after it, and an unread parameter before the last read one is not. A TypeScript parameter that is a binding pattern is judged by the names it binds: each name the body never reads is reported wherever the pattern stands, because removing it from the pattern moves no argument, except a name beside a rest element of the same object pattern, whose removal changes what that element holds, and the pattern counts as a read parameter when the body reads any name it binds. A rest parameter is judged as the last parameter. A TypeScript `this` parameter declares the type of `this` and receives no argument, so it is never reported. No name exempts a parameter. A TypeScript parameter whose name starts with an underscore is judged as any other is, and a Go parameter named by the blank identifier declares no name a body could read and is never reported.",
322
+ "The signature must be free, defined as follows: the function is not a method retained by interface satisfaction, is not a method whose name and signature are those of a method of an exported interface type declared by a package outside the target that the import closure holds, is not used as a value, is not a go:linkname or cgo target, is not a function the Go test driver runs (a test, benchmark or fuzz test of a test file, or TestMain), and is not a stub whose body is empty or only panics. A function literal or function expression that initializes a variable the program only calls, never passing, storing, returning or assigning it, is called by name and is not used as a value. A parameter its body never names is dead whatever the callers, so a published declaration of a library is reported too, with the fixability the vocabulary gives the kind: the signature change is a breaking change. In TypeScript a caller may pass a function used as a value more arguments than it declares parameters, so in such a function whose signature is free but for that use, a parameter its body never reads is reported when its body reads no parameter after it, and an unread parameter before the last read one is not. A parameter of a TypeScript function expression or arrow function that the compiler gives a contextual type is not reported when it carries a type annotation, because the inference of the call that holds the function may read the annotation, or when it is an object binding pattern, because the pattern reads each property it names from the argument and the code that hands the argument may act on that read. No name such a pattern binds is reported either. Any other TypeScript parameter that is a binding pattern is judged by the names it binds: each name the body never reads is reported wherever the pattern stands, because removing it from the pattern moves no argument, except a name beside a rest element of the same object pattern, whose removal changes what that element holds, and the pattern counts as a read parameter when the body reads any name it binds. A rest parameter is judged as the last parameter. A TypeScript `this` parameter declares the type of `this` and receives no argument, so it is never reported. No name exempts a parameter. A TypeScript parameter whose name starts with an underscore is judged as any other is, and a Go parameter named by the blank identifier declares no name a body could read and is never reported.",
323
323
  defaultSeverity: "warn",
324
324
  maxClass: "certain",
325
325
  fixability: "manual",
@@ -330,8 +330,9 @@ const ROWS: readonly KindRow[] = [
330
330
  code: "DS1802",
331
331
  name: "unused-receiver",
332
332
  languages: ["go"],
333
- rule: "A named method receiver with no reference inside the method body, on a method whose signature is free to change. Go permits a method with no receiver name, so the fix deletes an identifier and changes no signature.",
334
- precondition: "The same free-signature rule as unused-parameter, applied to the receiver.",
333
+ rule: "A named method receiver with no reference inside the method body. Go permits a method with no receiver name, so the fix deletes an identifier and changes no signature.",
334
+ precondition:
335
+ "None beyond the rule. Deleting a receiver name changes no signature, so a method retained by interface satisfaction, a method used as a value and a stub are reported as any other method is.",
335
336
  defaultSeverity: "warn",
336
337
  maxClass: "certain",
337
338
  fixability: "deletable",
package/src/manifest.ts CHANGED
@@ -15,7 +15,7 @@ const MANIFEST = "package.json";
15
15
  const LEGACY_MEMBERS = ["main", "module", "types"] as const;
16
16
 
17
17
  /** What reaches one entry point the manifest names. */
18
- export type EntryRole =
18
+ type EntryRole =
19
19
  /** A consumer importing the package, which is a caller the analysis cannot see. */
20
20
  | "import"
21
21
  /** A shell running the package's command, which is a caller that exists. */
@@ -34,7 +34,7 @@ import {
34
34
  } from "@typescript/native/unstable/ast";
35
35
 
36
36
  /** What one use of a namespace object reads beyond the names the checker resolves. */
37
- export type NamespaceUse =
37
+ type NamespaceUse =
38
38
  /** Every export of the module `specifier` names. */
39
39
  | { readonly kind: "whole"; readonly specifier: Node }
40
40
  /** The export a literal index names, the literal being the node to resolve. */
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  /** What the document says about `packages`. */
9
- export type PnpmPackages =
9
+ type PnpmPackages =
10
10
  | { readonly kind: "listed"; readonly patterns: readonly string[] }
11
11
  /** The document declares no `packages` key. */
12
12
  | { readonly kind: "absent" }