@cplieger/deadset-ts 8.0.0-dev.15 → 8.0.0-dev.17

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 (207) hide show
  1. package/dist/src/alias-chain.js +0 -5
  2. package/dist/src/amd.js +81 -0
  3. package/dist/src/analysis.js +94 -54
  4. package/dist/src/augmentations.js +23 -24
  5. package/dist/src/bindings.js +382 -0
  6. package/dist/src/calls.js +25 -8
  7. package/dist/src/commands/read.js +6 -7
  8. package/dist/src/commands/tools.js +5 -9
  9. package/dist/src/component-files.js +3 -2
  10. package/dist/src/conformance-record.js +1 -1
  11. package/dist/src/consumers.js +9 -10
  12. package/dist/src/contextual-uses.js +1 -17
  13. package/dist/src/contract/config.generated.js +5 -2
  14. package/dist/src/contract/contract.generated.js +119 -2
  15. package/dist/src/contract/report.generated.js +6 -2
  16. package/dist/src/dependencies.js +98 -71
  17. package/dist/src/destructuring.js +1 -19
  18. package/dist/src/element-access.js +179 -164
  19. package/dist/src/entries/build-scripts.js +222 -0
  20. package/dist/src/{configuration-files.js → entries/configuration-files.js} +22 -64
  21. package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
  22. package/dist/src/entries/conventions.js +739 -0
  23. package/dist/src/{html-entries.js → entries/html-entries.js} +9 -12
  24. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +3 -3
  25. package/dist/src/entries/run-directories.js +77 -0
  26. package/dist/src/entries/sources.js +144 -0
  27. package/dist/src/entries/static-module.js +670 -0
  28. package/dist/src/entries/test-runners.js +684 -0
  29. package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
  30. package/dist/src/extensions.js +37 -0
  31. package/dist/src/facts.js +38 -0
  32. package/dist/src/findings/completion.js +40 -4
  33. package/dist/src/findings/emitters.js +5 -8
  34. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  35. package/dist/src/{in-operands.js → findings/in-operands.js} +2 -2
  36. package/dist/src/findings/self-check.js +36 -20
  37. package/dist/src/findings-pass.js +5 -6
  38. package/dist/src/framework-lifecycle.js +42 -15
  39. package/dist/src/fs/manifest.js +15 -20
  40. package/dist/src/generated-file.js +172 -29
  41. package/dist/src/graph.js +14 -8
  42. package/dist/src/import-bindings.js +73 -28
  43. package/dist/src/index/sites.js +557 -0
  44. package/dist/src/index.js +1 -1
  45. package/dist/src/indexed-access.js +523 -478
  46. package/dist/src/injection-container.js +1 -1
  47. package/dist/src/interface-satisfaction.js +1 -1
  48. package/dist/src/inventory/commonjs.js +62 -17
  49. package/dist/src/inventory/enumerate.js +2 -1
  50. package/dist/src/javascript-file.js +26 -11
  51. package/dist/src/keyof-comparisons.js +124 -103
  52. package/dist/src/load/classify.js +28 -9
  53. package/dist/src/load/diagnostics.js +8 -1
  54. package/dist/src/load/discover.js +15 -7
  55. package/dist/src/load/expected-module.js +2 -2
  56. package/dist/src/load/plan.js +2 -2
  57. package/dist/src/load/specifiers.js +2 -4
  58. package/dist/src/load/synthesize.js +10 -5
  59. package/dist/src/load/workspace-manifests.js +1 -1
  60. package/dist/src/load/workspace-resolution.js +2 -2
  61. package/dist/src/matrix.js +12 -17
  62. package/dist/src/module-declarations.js +70 -85
  63. package/dist/src/overrides.js +134 -112
  64. package/dist/src/paths.js +56 -1
  65. package/dist/src/platform-calls.js +78 -0
  66. package/dist/src/platform-symbols.js +134 -0
  67. package/dist/src/references/read-rule.js +1 -0
  68. package/dist/src/references/read-rules.js +48 -0
  69. package/dist/src/references/sink.js +151 -0
  70. package/dist/src/references/sources.js +450 -0
  71. package/dist/src/references.js +111 -1116
  72. package/dist/src/resolve.js +1 -1
  73. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +7 -4
  74. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
  75. package/dist/src/{manifest.js → roots/manifest.js} +4 -4
  76. package/dist/src/roots/published-reach.js +412 -0
  77. package/dist/src/roots/root-set.js +489 -0
  78. package/dist/src/roots/unseen-loads.js +236 -0
  79. package/dist/src/serialization-contract.js +9 -4
  80. package/dist/src/source-files.js +5 -9
  81. package/dist/src/stores.js +4 -2
  82. package/dist/src/suppress.js +30 -32
  83. package/dist/src/sweep.js +25 -13
  84. package/dist/src/symbol-keys.js +89 -83
  85. package/dist/src/tests/file-class.js +76 -0
  86. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  87. package/dist/src/{test-support.js → tests/support.js} +5 -12
  88. package/dist/src/type-parameter-reads.js +178 -139
  89. package/dist/src/unimplemented-callees.js +262 -242
  90. package/dist/src/verbs/analyze.js +15 -3
  91. package/dist/src/verbs/describe.js +5 -3
  92. package/dist/src/verbs/explain.js +50 -28
  93. package/dist/src/verbs/print-retained.js +2 -2
  94. package/jsr.json +1 -1
  95. package/package.json +3 -3
  96. package/src/alias-chain.ts +0 -7
  97. package/src/amd.ts +130 -0
  98. package/src/analysis.ts +156 -70
  99. package/src/augmentations.ts +41 -27
  100. package/src/automatic-types.ts +1 -1
  101. package/src/bindings.ts +460 -0
  102. package/src/calls.ts +25 -7
  103. package/src/commands/read.ts +6 -8
  104. package/src/commands/tools.ts +5 -11
  105. package/src/component-files.ts +4 -2
  106. package/src/conformance-record.ts +1 -1
  107. package/src/consumers.ts +12 -11
  108. package/src/contextual-uses.ts +2 -22
  109. package/src/contract/config.generated.ts +5 -2
  110. package/src/contract/contract.generated.ts +138 -2
  111. package/src/contract/report.generated.ts +6 -2
  112. package/src/dependencies.ts +117 -71
  113. package/src/destructuring.ts +1 -31
  114. package/src/element-access.ts +188 -182
  115. package/src/entries/build-scripts.ts +292 -0
  116. package/src/{configuration-files.ts → entries/configuration-files.ts} +33 -82
  117. package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
  118. package/src/{conventions.ts → entries/conventions.ts} +349 -523
  119. package/src/{html-entries.ts → entries/html-entries.ts} +19 -18
  120. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +5 -5
  121. package/src/entries/run-directories.ts +108 -0
  122. package/src/entries/sources.ts +266 -0
  123. package/src/entries/static-module.ts +858 -0
  124. package/src/entries/test-runners.ts +868 -0
  125. package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
  126. package/src/exempt.ts +3 -2
  127. package/src/extensions.ts +45 -0
  128. package/src/facts.ts +46 -0
  129. package/src/file-facts.ts +1 -1
  130. package/src/findings/boundary.ts +2 -0
  131. package/src/findings/completion.ts +43 -4
  132. package/src/findings/emitter.ts +1 -1
  133. package/src/findings/emitters.ts +14 -10
  134. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  135. package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
  136. package/src/findings/self-check.ts +41 -22
  137. package/src/findings/visibility-narrowing.ts +1 -1
  138. package/src/findings-pass.ts +5 -12
  139. package/src/framework-lifecycle.ts +43 -15
  140. package/src/fs/manifest.ts +25 -21
  141. package/src/generated-file.ts +240 -36
  142. package/src/graph.ts +27 -11
  143. package/src/import-bindings.ts +98 -29
  144. package/src/index/sites.ts +781 -0
  145. package/src/index.ts +1 -1
  146. package/src/indexed-access.ts +570 -527
  147. package/src/injection-container.ts +1 -1
  148. package/src/interface-satisfaction.ts +1 -1
  149. package/src/inventory/commonjs.ts +102 -17
  150. package/src/inventory/enumerate.ts +2 -1
  151. package/src/javascript-file.ts +29 -12
  152. package/src/keyof-comparisons.ts +131 -116
  153. package/src/load/classify.ts +49 -13
  154. package/src/load/diagnostics.ts +11 -1
  155. package/src/load/discover.ts +27 -11
  156. package/src/load/expected-module.ts +8 -2
  157. package/src/load/plan.ts +11 -2
  158. package/src/load/specifiers.ts +8 -5
  159. package/src/load/synthesize.ts +12 -6
  160. package/src/load/test-globals.ts +1 -1
  161. package/src/load/workspace-manifests.ts +1 -1
  162. package/src/load/workspace-resolution.ts +9 -2
  163. package/src/load/workspace-run.ts +1 -1
  164. package/src/matrix.ts +13 -17
  165. package/src/module-declarations.ts +74 -98
  166. package/src/overrides.ts +162 -134
  167. package/src/paths.ts +65 -1
  168. package/src/platform-calls.ts +119 -0
  169. package/src/platform-symbols.ts +189 -0
  170. package/src/references/read-rule.ts +60 -0
  171. package/src/references/read-rules.ts +55 -0
  172. package/src/references/sink.ts +213 -0
  173. package/src/references/sources.ts +632 -0
  174. package/src/references.ts +174 -1492
  175. package/src/report.ts +2 -2
  176. package/src/resolve.ts +1 -1
  177. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +10 -7
  178. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
  179. package/src/{manifest.ts → roots/manifest.ts} +5 -5
  180. package/src/roots/published-reach.ts +481 -0
  181. package/src/{roots.ts → roots/root-set.ts} +203 -630
  182. package/src/roots/unseen-loads.ts +345 -0
  183. package/src/serialization-contract.ts +9 -4
  184. package/src/source-files.ts +5 -10
  185. package/src/stores.ts +13 -2
  186. package/src/suppress.ts +48 -33
  187. package/src/sweep.ts +37 -14
  188. package/src/symbol-keys.ts +102 -102
  189. package/src/tests/file-class.ts +118 -0
  190. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  191. package/src/{test-support.ts → tests/support.ts} +15 -21
  192. package/src/type-parameter-reads.ts +187 -158
  193. package/src/unimplemented-callees.ts +297 -280
  194. package/src/verbs/analyze.ts +19 -5
  195. package/src/verbs/describe.ts +5 -2
  196. package/src/verbs/explain.ts +75 -32
  197. package/src/verbs/print-retained.ts +2 -2
  198. package/dist/src/build-scripts.js +0 -418
  199. package/dist/src/conventions.js +0 -907
  200. package/dist/src/entry-points.js +0 -444
  201. package/dist/src/own-body.js +0 -28
  202. package/dist/src/roots.js +0 -865
  203. package/dist/src/unseen-loads.js +0 -189
  204. package/src/build-scripts.ts +0 -536
  205. package/src/entry-points.ts +0 -584
  206. package/src/own-body.ts +0 -42
  207. package/src/unseen-loads.ts +0 -282
@@ -63,9 +63,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
63
63
  const privateNames = new Set(held.symbols
64
64
  .filter((symbol) => symbol.visibility === "private-name")
65
65
  .map((symbol) => symbol.id));
66
- let batches = 0;
67
- let lookups = 0;
68
- const batchesOf = (count) => Math.ceil(count / cap);
69
66
  const parts = new Map();
70
67
  /** The object types one type is: itself, or its constituents at any depth. */
71
68
  const partsOf = (type) => {
@@ -75,7 +72,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
75
72
  }
76
73
  let found = [];
77
74
  if (type.isUnionType() || type.isIntersectionType()) {
78
- lookups += 1;
79
75
  const constituents = queries.constituents(type);
80
76
  found = isAnswered(constituents) ? constituents.flatMap(partsOf) : [];
81
77
  }
@@ -94,7 +90,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
94
90
  }
95
91
  const table = new Map();
96
92
  const read = properties.of(type);
97
- lookups += read.asked ? 1 : 0;
98
93
  for (const property of isAnswered(read.properties) ? read.properties : []) {
99
94
  table.set(property.name, {
100
95
  ids: chains
@@ -112,7 +107,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
112
107
  return table;
113
108
  };
114
109
  const writes = [];
115
- batches += batchesOf(literals.length);
116
110
  const contexts = queries.contextualTypes(literals.map((one) => one.literal), cap);
117
111
  // A computed name that is not literal text names the property the literal declares
118
112
  // under the checker's own key, which is how a type declares a member a unique symbol
@@ -123,7 +117,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
123
117
  const name = propertyName(property);
124
118
  return name !== undefined && name.text === undefined ? [name.node] : [];
125
119
  }));
126
- batches += batchesOf(computed.length);
127
120
  const keys = new Map();
128
121
  (computed.length === 0
129
122
  ? []
@@ -152,7 +145,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
152
145
  }
153
146
  });
154
147
  const carried = flows.filter((flow) => !isObjectLiteralExpression(flow.value));
155
- batches += batchesOf(carried.length);
156
148
  const types = queries.typesAt(carried.map((flow) => flow.value), cap);
157
149
  /** The members a position may read structurally: those of object types, not of classes. */
158
150
  const readable = (member) => [
@@ -198,11 +190,9 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
198
190
  if (elements.has(type.id)) {
199
191
  return elements.get(type.id);
200
192
  }
201
- lookups += 1;
202
193
  const isArray = queries.isArray(type);
203
194
  let element;
204
195
  if (isAnswered(isArray) && isArray) {
205
- lookups += 1;
206
196
  const held = queries.typeArguments(type);
207
197
  element = isAnswered(held) ? held[0] : undefined;
208
198
  }
@@ -216,7 +206,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
216
206
  if (known !== undefined) {
217
207
  return known;
218
208
  }
219
- lookups += type.isTypeReference() ? 1 : 0;
220
209
  const held = queries.typeArguments(type);
221
210
  const found = isAnswered(held) ? held : [];
222
211
  argumentsOf.set(type.id, found);
@@ -232,18 +221,15 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
232
221
  if (known !== undefined) {
233
222
  return known;
234
223
  }
235
- lookups += 1;
236
224
  let kind = SignatureKind.Call;
237
225
  let signatures = queries.signaturesOf(type, kind);
238
226
  if (isAnswered(signatures) && signatures.length === 0) {
239
- lookups += 1;
240
227
  kind = SignatureKind.Construct;
241
228
  signatures = queries.signaturesOf(type, kind);
242
229
  }
243
230
  const called = (isAnswered(signatures) ? signatures : []).map((signature) => {
244
231
  const parameters = signature.parameters.map((_parameter, index) => queries.parameterType(signature, index));
245
232
  const result = queries.returnTypeOf(signature);
246
- lookups += parameters.length + 1;
247
233
  return {
248
234
  kind,
249
235
  parameters: parameters.map((one) => (isAnswered(one) ? one : undefined)),
@@ -335,7 +321,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
335
321
  const type = types[index];
336
322
  return type === undefined || !isAnswered(type) || !mayCarry(type) ? [] : [{ flow, type }];
337
323
  });
338
- batches += batchesOf(sourced.length);
339
324
  const positions = queries.contextualTypes(sourced.map((one) => one.flow.value), cap);
340
325
  const reads = [];
341
326
  // A literal property writes a position's members once, however many values carry it there.
@@ -408,7 +393,6 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
408
393
  return known;
409
394
  };
410
395
  const spreads = literals.flatMap(({ literal, from }) => literal.properties.flatMap((property) => isSpreadAssignment(property) ? [{ value: property.expression, from }] : []));
411
- batches += batchesOf(spreads.length);
412
396
  const spreadTypes = queries.typesAt(spreads.map((one) => one.value), cap);
413
397
  spreads.forEach(({ value, from }, index) => {
414
398
  const type = spreadTypes[index];
@@ -426,5 +410,5 @@ export function contextualUses(project, held, chains, literals, flows, cap, prop
426
410
  reads.push({ at: value, from, ids });
427
411
  }
428
412
  });
429
- return { writes, reads, batches, lookups };
413
+ return { writes, reads };
430
414
  }
@@ -273,7 +273,7 @@ export const SETTINGS = [
273
273
  role: "setting",
274
274
  read: true,
275
275
  default: [
276
- "**/*.test.{ts,tsx,mts,cts}",
276
+ "**/*.test.{ts,tsx,mts,cts,js,jsx,mjs,cjs}",
277
277
  "**/*.test-d.{ts,tsx,mts,cts}",
278
278
  "**/*.spec-d.{ts,tsx,mts,cts}",
279
279
  "**/*.spec.*",
@@ -483,7 +483,10 @@ export const SETTINGS = [
483
483
  key: "provenance",
484
484
  role: "ignored",
485
485
  read: true,
486
- value: { type: "string", pattern: "^(default|(repository|central|flag): [^\\r\\n]+)$" },
486
+ value: {
487
+ type: "string",
488
+ pattern: "^(default|(repository|central|flag): ([^\\r\\n]|[\\r\\n])+)$",
489
+ },
487
490
  keyPattern: "^[a-z][a-z_]*(\\.[A-Za-z0-9_]+)*$",
488
491
  },
489
492
  ];
@@ -2,6 +2,7 @@
2
2
  export const CONTRACT_VERSION = "8.0.0";
3
3
  export const SCHEMA_VERSIONS = ["9.0.0"];
4
4
  export const SCHEMA_VERSION = "9.0.0";
5
+ export const FACTS_VERSION = "1.0.0";
5
6
  export const CORPUS_VERSION = "6.0.0";
6
7
  export const CODE_PREFIX = "DS";
7
8
  export const FAMILY_KEY_LENGTH = 4;
@@ -25,16 +26,19 @@ export const LANGUAGE_ROWS = {
25
26
  analyzer: "deadset-go",
26
27
  markers: ["go.mod"],
27
28
  skippedDirectories: ["node_modules", "testdata", "vendor", ".*", "_*"],
29
+ skippedFiles: ["_*", ".*"],
28
30
  },
29
31
  ts: {
30
32
  analyzer: "deadset-ts",
31
33
  markers: ["tsconfig*.json", "jsconfig*.json"],
32
34
  skippedDirectories: ["node_modules", ".git"],
35
+ skippedFiles: ["*.min.js", "*.min.cjs", "*.min.mjs"],
33
36
  },
34
37
  proto: {
35
38
  analyzer: "deadset-proto",
36
39
  markers: ["buf.yaml", "buf.work.yaml"],
37
40
  skippedDirectories: ["node_modules", "vendor", ".*"],
41
+ skippedFiles: [],
38
42
  },
39
43
  };
40
44
  export const EXIT_CLEAN = 0;
@@ -441,8 +445,8 @@ export const KIND_ROWS = [
441
445
  languages: ["go", "ts"],
442
446
  subject: "dependency",
443
447
  holdsLive: false,
444
- 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. On the TypeScript side, a needed dependency whose every use is written inside declarations that are members of the run's dead components, or at the top level of a file reported under DS1602, that no command runs and that no needed dependency used otherwise names as a peer, is reported as well, dead only through that code: at the reachability class possible where one of those declarations belongs to a library's published API, and found under reachability alone where one of those declarations or files is, so at probable unless ts.roots_complete is true. A use the configuration makes, a use an unanswered specifier may make and an import none of whose bindings is used are uses by live code.",
445
- precondition: "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. A `@types/<name>` package in a type root of a compiler configuration that lists no `types`, a `node_modules/@types` directory at or above the configuration's directory or a `typeRoots` entry naming one, is needed by a use, in a file of that configuration, of a global name or an ambient module that one of the package's declaration files declares, which resolves to no declaration of the program: a compiler before version 6 includes every package of the type roots where `types` is not listed, and version 6 and later include none, so the program the analysis builds holds none of those declarations. A package's declaration files are the file its `types` or `typings` names, else its `index.d.ts`, and each file a `/// <reference path>` of one of them reaches inside the package. A global is a top-level declaration of such a file that is no module, or a declaration of a `declare global` block of one that is, and an ambient module is a `declare module` with a string name of a file that is no module. A name that names a member, a property or a label is no use of a global. Four more dependencies are needed: one whose command a script entry, a workflow step or a git hook 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/conventions.md states, and one that a needed dependency names as a peer, as stated below. A command no script entry, workflow step or git hook runs needs nothing. A declared dependency that the installed manifest of a needed declared dependency names in its peerDependencies is needed, and so on until no further dependency joins. A peer dependency is a package the needed dependency expects beside it at a version its manifest states, whether or not it imports the package, and the project's declaration is what keeps that package present at a version the project chooses, so removing the declaration can break the needed dependency where nothing the analysis reads imports the peer. A peer that peerDependenciesMeta marks optional is needed in the same way, because the needed dependency's manifest still names it as a package it works with, and a package manager may leave an optional peer out where the project does not declare it, so the project's declaration is what keeps it present for the needed dependency. A declared dependency that only dependencies nothing needs name as a peer is needed by nothing. 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 directory of the manifest that declares the dependency, and a dependency with none is decided by the import closure alone. On the TypeScript side, the dependencies judged are those of every manifest grammar/analysis/program.md says the analysis reads, a nested package's among them, each read against its own directory: a dependency is needed by a use written in a file at or below the directory of the manifest that declares it where no manifest between them declares a dependency of the same name, so a use below a nested manifest that declares the same dependency needs that nested manifest's declaration only, by a use no one file holds, and as a peer of a needed dependency of the same manifest or of a manifest below it. A dependency a nested package's manifest declares whose installed manifest the analysis cannot find is not judged, because no run requires a nested package to be installed and its commands and peers cannot be read, while a workspace member's and the target's own are judged as above.",
448
+ 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. On the TypeScript side, a needed dependency whose every use is written inside declarations that are members of the run's dead components, or at the top level of a file reported under DS1602, that no command runs and that no needed dependency used otherwise names as a peer, is reported as well, dead only through that code: at the reachability class possible where one of those declarations belongs to a library's published API, and found under reachability alone where one of those declarations or files is, so at probable unless ts.roots_complete is true. A use the configuration makes, a use an unanswered specifier or callee may make and an import none of whose bindings is used are uses by live code.",
449
+ precondition: "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 `require()` call as `roots.23` reads one, or a call of `import.meta.resolve`, of `require.resolve`, whatever `require` names, or of `resolve` on another name that is such a `require`, in them, whose first argument is a string literal or a template literal with no substitution needs each dependency an import of that specifier needs. A `@types/<name>` package in a type root of a compiler configuration that lists no `types`, a `node_modules/@types` directory at or above the configuration's directory or a `typeRoots` entry naming one, is needed by a use, in a file of that configuration, of a global name or an ambient module that one of the package's declaration files declares, which resolves to no declaration of the program: a compiler before version 6 includes every package of the type roots where `types` is not listed, and version 6 and later include none, so the program the analysis builds holds none of those declarations. A package's declaration files are the file its `types` or `typings` names, else its `index.d.ts`, and each file a `/// <reference path>` of one of them reaches inside the package. A global is a top-level declaration of such a file that is no module, or a declaration of a `declare global` block of one that is, and an ambient module is a `declare module` with a string name of a file that is no module. A name that names a member, a property or a label is no use of a global. Four more dependencies are needed: one whose command a script entry, a workflow step or a git hook 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/conventions.md states, and one that a needed dependency names as a peer, as stated below. A command no script entry, workflow step or git hook runs needs nothing. A declared dependency that the installed manifest of a needed declared dependency names in its peerDependencies is needed, and so on until no further dependency joins. A peer dependency is a package the needed dependency expects beside it at a version its manifest states, whether or not it imports the package, and the project's declaration is what keeps that package present at a version the project chooses, so removing the declaration can break the needed dependency where nothing the analysis reads imports the peer. A peer that peerDependenciesMeta marks optional is needed in the same way, because the needed dependency's manifest still names it as a package it works with, and a package manager may leave an optional peer out where the project does not declare it, so the project's declaration is what keeps it present for the needed dependency. A declared dependency that only dependencies nothing needs name as a peer is needed by nothing. 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 directory of the manifest that declares the dependency, and a dependency with none is decided by the import closure alone. On the TypeScript side, the dependencies judged are those of every manifest grammar/analysis/program.md says the analysis reads, a nested package's among them, each read against its own directory: a dependency is needed by a use written in a file at or below the directory of the manifest that declares it where no manifest between them declares a dependency of the same name, so a use below a nested manifest that declares the same dependency needs that nested manifest's declaration only, by a use no one file holds, and as a peer of a needed dependency of the same manifest or of a manifest below it. A dependency a nested package's manifest declares whose installed manifest the analysis cannot find is not judged, because no run requires a nested package to be installed and its commands and peers cannot be read, while a workspace member's and the target's own are judged as above.",
446
450
  details: { dependency_class: "required" },
447
451
  defaultEnabled: true,
448
452
  defaultSeverity: "deny",
@@ -708,6 +712,38 @@ export const SYMBOL_SUBJECTS = {
708
712
  "configured-declaration": "record",
709
713
  edge: "record",
710
714
  };
715
+ export const REMEDIES = {
716
+ declaration: {
717
+ names: "a declaration",
718
+ suppressions: ["inline", "ignore", "baseline"],
719
+ remedy: "delete the symbol, or wire it up so the program uses it",
720
+ },
721
+ binding: {
722
+ names: "an import binding",
723
+ suppressions: ["inline", "ignore", "baseline"],
724
+ remedy: "delete the import, or use what it binds",
725
+ },
726
+ part: {
727
+ names: "a part of a declaration",
728
+ suppressions: ["inline", "ignore", "baseline"],
729
+ remedy: "remove the part, or use it",
730
+ },
731
+ file: {
732
+ names: "a file",
733
+ suppressions: [],
734
+ remedy: "delete the file, name it as a root, or build it in a configuration of the build matrix",
735
+ },
736
+ dependency: {
737
+ names: "a dependency row",
738
+ suppressions: ["ignore", "baseline"],
739
+ remedy: "remove the dependency",
740
+ },
741
+ record: {
742
+ names: "a record of deadset's own configuration",
743
+ suppressions: [],
744
+ remedy: "correct or remove the record the finding names",
745
+ },
746
+ };
711
747
  export const EXEMPTION_CLASSES = [
712
748
  {
713
749
  class: "interface-satisfaction",
@@ -1220,6 +1256,86 @@ export const EVIDENCE = [
1220
1256
  codes: ["DS1801", "DS1802", "DS1803", "DS1804", "DS1805"],
1221
1257
  },
1222
1258
  ];
1259
+ /** The generators whose TypeScript output a generated file is matched against, in the document's order. */
1260
+ export const GENERATORS = [
1261
+ {
1262
+ id: "protoc-gen-es-2",
1263
+ plugin: "protoc-gen-es",
1264
+ header: "^// @generated by protoc-gen-es v2\\.",
1265
+ versions: { min: "v2.10.0", max: "v2.16.0" },
1266
+ cell: "exact",
1267
+ },
1268
+ {
1269
+ id: "protoc-gen-es-2-fallback",
1270
+ plugin: "protoc-gen-es",
1271
+ header: "^// @generated by protoc-gen-es v2\\.",
1272
+ cell: "fallback",
1273
+ },
1274
+ {
1275
+ id: "protoc-gen-es-1",
1276
+ plugin: "protoc-gen-es",
1277
+ header: "^// @generated by protoc-gen-es v1\\.",
1278
+ cell: "exact",
1279
+ },
1280
+ {
1281
+ id: "protoc-gen-connect-es-1",
1282
+ plugin: "protoc-gen-connect-es",
1283
+ header: "^// @generated by protoc-gen-connect-es v1\\.",
1284
+ cell: "exact",
1285
+ },
1286
+ {
1287
+ id: "ts-proto-2-output-schema",
1288
+ plugin: "ts-proto",
1289
+ header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
1290
+ versions: { min: "v2.11.4", max: "v2.15.0" },
1291
+ cell: "exact",
1292
+ },
1293
+ {
1294
+ id: "ts-proto-2",
1295
+ plugin: "ts-proto",
1296
+ header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
1297
+ versions: { min: "v2.11.4", max: "v2.15.0" },
1298
+ cell: "rpc-types-fallback",
1299
+ },
1300
+ {
1301
+ id: "ts-proto-2-types",
1302
+ plugin: "ts-proto",
1303
+ header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
1304
+ versions: { min: "v2.11.4", max: "v2.15.0" },
1305
+ cell: "fallback",
1306
+ },
1307
+ {
1308
+ id: "ts-proto-2-fallback",
1309
+ plugin: "ts-proto",
1310
+ header: "^// Code generated by protoc-gen-ts_proto\\. DO NOT EDIT\\.$",
1311
+ cell: "fallback",
1312
+ },
1313
+ {
1314
+ id: "protoc-gen-js",
1315
+ plugin: "protoc-gen-js",
1316
+ header: "^// GENERATED CODE -- DO NOT EDIT!$",
1317
+ cell: "fallback",
1318
+ },
1319
+ {
1320
+ id: "protoc-gen-grpc-web",
1321
+ plugin: "protoc-gen-grpc-web",
1322
+ header: "^// Code generated by protoc-gen-grpc-web\\. DO NOT EDIT\\.$",
1323
+ cell: "fallback",
1324
+ },
1325
+ {
1326
+ id: "protobuf-ts",
1327
+ plugin: "protobuf-ts",
1328
+ header: "^// @generated by protobuf-ts ",
1329
+ cell: "fallback",
1330
+ },
1331
+ { id: "ts-protoc-gen", plugin: "ts-protoc-gen", header: "^// package: ", cell: "fallback" },
1332
+ {
1333
+ id: "protoc-gen-es-unsupported",
1334
+ plugin: "protoc-gen-es",
1335
+ header: "^// @generated by protoc-gen-es v(?:0|[3-9]|[1-9][0-9]+)\\.",
1336
+ cell: "unsupported",
1337
+ },
1338
+ ];
1223
1339
  /** Each group of failure classes, and the text opening the line that names one of its failures. */
1224
1340
  export const FAILURE_PREFIXES = { setup: "setup failure: ", run: "run failure: " };
1225
1341
  /** Each failure class the Contract names, and its group. */
@@ -1230,6 +1346,7 @@ export const FAILURE_CLASSES = {
1230
1346
  "workspace-member-without-source": "setup",
1231
1347
  "convention-not-literal": "setup",
1232
1348
  "no-program": "setup",
1349
+ "unreadable-configuration": "setup",
1233
1350
  "unreadable-document": "setup",
1234
1351
  "missing-import-path": "setup",
1235
1352
  "binding-undecodable": "setup",
@@ -43,6 +43,11 @@ export const REPORT_SCHEMAS = {
43
43
  },
44
44
  else: { properties: { configurations: { minItems: 1 }, target: { required: ["kind"] } } },
45
45
  },
46
+ {
47
+ if: { required: ["merged_from"], properties: { merged_from: { maxItems: 0 } } },
48
+ then: { properties: { analyzer: { properties: { languages: { maxItems: 0 } } } } },
49
+ else: { properties: { analyzer: { properties: { languages: { minItems: 1 } } } } },
50
+ },
46
51
  ],
47
52
  properties: {
48
53
  schema_version: { type: "string", pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+$" },
@@ -59,7 +64,6 @@ export const REPORT_SCHEMAS = {
59
64
  },
60
65
  languages: {
61
66
  type: "array",
62
- minItems: 1,
63
67
  uniqueItems: true,
64
68
  items: { type: "string", enum: ["go", "ts", "proto"] },
65
69
  },
@@ -95,7 +99,7 @@ export const REPORT_SCHEMAS = {
95
99
  pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?(\\+[0-9A-Za-z.-]+)?$",
96
100
  },
97
101
  digest: { type: "string", pattern: "^sha256:[0-9a-f]{64}$" },
98
- languages: { $ref: "#/properties/analyzer/properties/languages" },
102
+ languages: { $ref: "#/properties/analyzer/properties/languages", minItems: 1 },
99
103
  totals: { $ref: "#/properties/totals" },
100
104
  },
101
105
  },
@@ -7,15 +7,19 @@
7
7
  * itself is that dependency's need, not the target's.
8
8
  */
9
9
  import { isArrayLiteralExpression, isCallExpression, isExportDeclaration, isExpressionStatement, isExternalModuleReference, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isMetaProperty, isNamespaceExport, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isStringLiteral, isNoSubstitutionTemplateLiteral, SyntaxKind, } from "@typescript/native/ast";
10
+ import { amdLoadOf, amdPlatform } from "./amd.js";
10
11
  import { automaticTypes } from "./automatic-types.js";
11
- import { configurationFiles, declaredIn as declaredBeside, dependenciesNamed, moduleStrings, outsideChain, } from "./configuration-files.js";
12
+ import { declaredIn as declaredBeside, dependenciesNamed, moduleStrings, outsideChain, } from "./entries/configuration-files.js";
13
+ import { declarationBindings } from "./import-bindings.js";
12
14
  import { nodeKey } from "./inventory.js";
13
15
  import { packageScope } from "./load/package-scope.js";
14
- import { ancestors, dirnamePath, isAbsolutePath, joinPath, relativePath, resolvePath, } from "./paths.js";
16
+ import { ancestors, cannotStartPackageName, dirnamePath, joinPath, relativePath, resolvePath, } from "./paths.js";
15
17
  import { UNANSWERED } from "./query.js";
16
18
  import { sourceFilesOf } from "./source-files.js";
17
- import { manifestCommands, nodemonTexts } from "./manifest.js";
18
- import { commandFileTexts, workflowCommands } from "./workflow-steps.js";
19
+ import { manifestCommands, nodemonTexts } from "./roots/manifest.js";
20
+ import { writtenName } from "./platform-calls.js";
21
+ import { callsPlatform } from "./platform-symbols.js";
22
+ import { parenthesesRemoved } from "./unwrap.js";
19
23
  import { pathsNamed, preloadedPackages, readCommands, } from "./commands/read.js";
20
24
  import { heldNames } from "./text/named-files.js";
21
25
  import { bytewise } from "./text/compare.js";
@@ -151,7 +155,7 @@ function configurationPackages(host, configFile, options, programPackages, parse
151
155
  }
152
156
  seen.add(file);
153
157
  for (const entry of extendsOf(host, file, parse)) {
154
- if (entry.startsWith(".") || isAbsolutePath(entry)) {
158
+ if (cannotStartPackageName(entry)) {
155
159
  const local = resolvePath(dirnamePath(file), entry);
156
160
  pending.push(local.endsWith(".json") ? local : `${local}.json`);
157
161
  }
@@ -176,36 +180,19 @@ function importOf(specifier) {
176
180
  }
177
181
  /** The local names one import declaration binds. */
178
182
  function bindingsOf(node) {
179
- if (node === undefined) {
180
- return [];
181
- }
182
- if (isImportEqualsDeclaration(node)) {
183
- return [node.name];
184
- }
185
- if (!isImportDeclaration(node) || node.importClause === undefined) {
186
- return [];
187
- }
188
- const clause = node.importClause;
189
- const names = clause.name === undefined ? [] : [clause.name];
190
- const bindings = clause.namedBindings;
191
- if (bindings !== undefined) {
192
- if (bindings.kind === SyntaxKind.NamespaceImport) {
193
- names.push(bindings.name);
194
- }
195
- else {
196
- names.push(...bindings.elements.map((element) => element.name));
197
- }
198
- }
199
- return names;
183
+ return node !== undefined && (isImportDeclaration(node) || isImportEqualsDeclaration(node))
184
+ ? declarationBindings(node).map((binding) => binding.name)
185
+ : [];
200
186
  }
201
187
  /**
202
188
  * Every package one project needs, and which declaration each use is written in.
203
189
  * One local walk and one batched resolution per file: a use of an import binding is
204
190
  * an identifier resolving to the binding's own symbol, so a local declaration that
205
- * shadows the name is not one. A string of a configuration file uses each dependency
206
- * the manifest beside the file declares that it spells.
191
+ * shadows the name is not one. A string of a configuration file, as the entry sources
192
+ * read them in `configuration`, uses each dependency the manifest beside the file
193
+ * declares that it spells.
207
194
  */
208
- export function projectNeeds(project, held, host, targetRoot, parse) {
195
+ export function projectNeeds(project, held, host, targetRoot, parse, configuration, workflows) {
209
196
  const programPackages = new Set();
210
197
  for (const name of project.program.getSourceFileNames()) {
211
198
  const named = packageOfPath(name);
@@ -256,7 +243,6 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
256
243
  return names;
257
244
  };
258
245
  const files = sourceFilesOf(project, targetRoot);
259
- const configuration = configurationFiles(host, targetRoot, files, parse);
260
246
  for (const { file, manifestDir } of configuration.modules) {
261
247
  const names = declaredAt(joinPath(manifestDir, MANIFEST));
262
248
  for (const { node, text } of moduleStrings(file)) {
@@ -271,7 +257,7 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
271
257
  }
272
258
  }
273
259
  }
274
- const ranFiles = outsideChain(host, targetRoot, files, parse, scriptRunFiles(host, targetRoot, files));
260
+ const ranFiles = outsideChain(host, targetRoot, files, parse, scriptRunFiles(host, targetRoot, files, workflows));
275
261
  for (const { file, manifestDirs } of [...configuration.outside, ...ranFiles]) {
276
262
  for (const manifestDir of manifestDirs) {
277
263
  const names = declaredAt(joinPath(manifestDir, MANIFEST));
@@ -288,7 +274,7 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
288
274
  * workflow step or git hook names, with the target root's: a path `pathsNamed` reads, below the
289
275
  * target root and in no `node_modules`.
290
276
  */
291
- function scriptRunFiles(host, targetRoot, files) {
277
+ function scriptRunFiles(host, targetRoot, files, workflows) {
292
278
  const root = resolvePath(host.workingDirectory(), targetRoot);
293
279
  const dirs = new Set([root]);
294
280
  for (const name of files.byName.keys()) {
@@ -300,12 +286,7 @@ function scriptRunFiles(host, targetRoot, files) {
300
286
  }
301
287
  }
302
288
  const named = new Map([
303
- [
304
- root,
305
- workflowReadings(host, root)
306
- .flatMap(pathsNamed)
307
- .map((one) => one.path),
308
- ],
289
+ [root, workflows.readings.flatMap(pathsNamed).map((one) => one.path)],
309
290
  ]);
310
291
  for (const dir of dirs) {
311
292
  const read = readDocument(host, joinPath(dir, MANIFEST));
@@ -341,19 +322,9 @@ function manifestUses(host, dir, manifest) {
341
322
  return { ...uses, held: [uses.held, ...texts].join("\n") };
342
323
  }
343
324
  /** What the target root's workflow steps, git hooks and recipes use, held with their files' whole text. */
344
- function workflowUses(host, targetRoot) {
345
- const uses = usesOf(workflowReadings(host, targetRoot));
346
- return { ...uses, held: [uses.held, ...commandFileTexts(host, targetRoot)].join("\n") };
347
- }
348
- /**
349
- * What the target root's workflow steps, git hooks, hook managers and recipes run, each held
350
- * with the directory the file writes for it.
351
- */
352
- function workflowReadings(host, targetRoot) {
353
- return workflowCommands(host, targetRoot).map(({ text, dir, writtenDirectory }) => {
354
- const reading = readCommands(text, dir);
355
- return { ...reading, held: [reading.held, writtenDirectory ?? ""].join("\n") };
356
- });
325
+ function workflowUses(workflows) {
326
+ const uses = usesOf(workflows.readings);
327
+ return { ...uses, held: [uses.held, ...workflows.texts].join("\n") };
357
328
  }
358
329
  function usesOf(readings) {
359
330
  return {
@@ -439,7 +410,16 @@ function fileNeeds(project, held, file, { programPackages, automatic }, use) {
439
410
  if (names.size > 0 || automatic.globals.size > 0) {
440
411
  visit(file);
441
412
  }
442
- const asked = [...specifiers, ...bindings.map(({ node }) => node), ...candidates, ...globals];
413
+ const loads = runtimeLoads(file);
414
+ const callees = loads.flatMap((load) => load.callees);
415
+ const amdCallees = new Set(loads.flatMap((load) => (load.amd ? load.callees : [])));
416
+ const asked = [
417
+ ...specifiers,
418
+ ...bindings.map(({ node }) => node),
419
+ ...candidates,
420
+ ...globals,
421
+ ...callees,
422
+ ];
443
423
  const handles = asked.map((node) => project.handle(node));
444
424
  const resolved = project.symbolsAt(handles);
445
425
  const packagesOf = new Map();
@@ -510,33 +490,80 @@ function fileNeeds(project, held, file, { programPackages, automatic }, use) {
510
490
  for (const reference of file.typeReferenceDirectives) {
511
491
  use(ownersOf(file, held, file), typePackages(reference.fileName, programPackages));
512
492
  }
513
- for (const specifier of resolvedSpecifiers(file)) {
514
- const named = packageOfSpecifier(specifier.text);
515
- if (named !== undefined) {
493
+ // A callee the checker leaves unanswered may be a require, so its call holds the
494
+ // dependency it names by live code, as program.33 holds one.
495
+ const calleesAt = unresolvedAt + globals.length;
496
+ const decided = new Map();
497
+ const requires = new Set();
498
+ const unansweredCallees = new Set();
499
+ callees.forEach((callee, index) => {
500
+ const symbol = resolved[calleesAt + index];
501
+ if (symbol === UNANSWERED) {
502
+ unansweredCallees.add(callee);
503
+ return;
504
+ }
505
+ // The decision reads the callee's symbol, its written name and its platform name, and nothing else.
506
+ const platform = amdCallees.has(callee) ? amdPlatform(callee) : "require";
507
+ const key = symbol === undefined ? undefined : `${symbol.id}\u0000${platform}\u0000${callee.text}`;
508
+ const answer = (key === undefined ? undefined : decided.get(key)) ??
509
+ callsPlatform(project, platform, callee, symbol);
510
+ if (key !== undefined) {
511
+ decided.set(key, answer);
512
+ }
513
+ if (answer) {
514
+ requires.add(callee);
515
+ }
516
+ });
517
+ for (const { specifier, named, callees: through } of loads) {
518
+ if (through.length === 0 || through.some((one) => requires.has(one))) {
516
519
  use(ownersOf(file, held, specifier), [named]);
517
520
  }
521
+ else if (through.some((one) => unansweredCallees.has(one))) {
522
+ use([PROJECT_OWNER], [named]);
523
+ }
518
524
  }
519
525
  return resolved.slice(0, specifiers.length).includes(UNANSWERED);
520
526
  }
521
527
  /**
522
- * The literal specifiers one file asks the runtime to resolve, through `import.meta.resolve`
523
- * or `require.resolve`, each of which needs the package it names installed.
528
+ * The calls one file may load or resolve a package with at run time, each of whose first
529
+ * argument is literal text naming a package: a `require()` call, which the compiler lists among
530
+ * a file's imports only in a JavaScript file and only through the bare name; a `.resolve` of
531
+ * another name, which needs it where that name is a `require`; and `import.meta.resolve` or
532
+ * a `.resolve` of the name `require`, whatever it names, a use where it stands; and each id of
533
+ * an AMD dependency list (references-ts.37), which needs it where the call is AMD's.
524
534
  */
525
- function resolvedSpecifiers(file) {
535
+ function runtimeLoads(file) {
526
536
  const found = [];
527
- if (!file.text.includes(".resolve(")) {
528
- return found;
529
- }
530
537
  const visit = (node) => {
531
- if (isCallExpression(node) && isPropertyAccessExpression(node.expression)) {
532
- const callee = node.expression;
538
+ const amd = amdLoadOf(node);
539
+ if (amd !== undefined) {
540
+ for (const { id } of amd.ids) {
541
+ const named = packageOfSpecifier(id.text);
542
+ if (named !== undefined) {
543
+ found.push({ specifier: id, named, callees: [amd.callee], amd: true });
544
+ }
545
+ }
546
+ }
547
+ else if (isCallExpression(node)) {
533
548
  const [argument] = node.arguments;
534
- const receiver = callee.expression;
535
- const resolving = callee.name.text === "resolve" &&
536
- ((isMetaProperty(receiver) && receiver.name.text === "meta") ||
537
- (isIdentifier(receiver) && receiver.text === "require"));
538
- if (resolving && argument !== undefined && isLiteralText(argument)) {
539
- found.push(argument);
549
+ if (argument !== undefined && isLiteralText(argument)) {
550
+ const named = packageOfSpecifier(argument.text);
551
+ const callee = parenthesesRemoved(node.expression);
552
+ const receiver = isPropertyAccessExpression(callee) && callee.name.text === "resolve"
553
+ ? parenthesesRemoved(callee.expression)
554
+ : undefined;
555
+ const stands = receiver !== undefined &&
556
+ ((isMetaProperty(receiver) && receiver.name.text === "meta") ||
557
+ (isIdentifier(receiver) && receiver.text === "require"));
558
+ const callees = stands
559
+ ? []
560
+ : [
561
+ writtenName(callee),
562
+ receiver === undefined ? undefined : writtenName(receiver),
563
+ ].filter((one) => one !== undefined);
564
+ if (named !== undefined && (stands || callees.length > 0)) {
565
+ found.push({ specifier: argument, named, callees, amd: false });
566
+ }
540
567
  }
541
568
  }
542
569
  node.forEachChild(visit);
@@ -727,7 +754,7 @@ function addNeededPeers(declared, peers, needed, ran) {
727
754
  * manifest declares nothing, nor does a nested package's uninstalled dependency, because
728
755
  * no run requires a nested package to be installed.
729
756
  */
730
- export function dependenciesOf(host, targetRoot, perProject, candidates, members = [], unbuiltMembers = [], nested = []) {
757
+ export function dependenciesOf(host, targetRoot, workflows, perProject, candidates, members = [], unbuiltMembers = [], nested = []) {
731
758
  const root = resolvePath(host.workingDirectory(), targetRoot);
732
759
  const scopeOf = packageScope(host, targetRoot);
733
760
  const manifests = new Map([[root, MANIFEST]]);
@@ -744,7 +771,7 @@ export function dependenciesOf(host, targetRoot, perProject, candidates, members
744
771
  unbuilt.add(path);
745
772
  }
746
773
  }
747
- const workflow = workflowUses(host, targetRoot);
774
+ const workflow = workflowUses(workflows);
748
775
  const declared = [];
749
776
  const ran = new Set();
750
777
  const peers = new Map();