@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.21
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.
- package/README.md +3 -1
- package/THIRD_PARTY_NOTICES.md +27 -0
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/alias-chain.js +35 -9
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +274 -496
- package/dist/src/augmentations.js +64 -3
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/bindings.js +382 -0
- package/dist/src/commands/held.js +499 -0
- package/dist/src/commands/read.js +161 -0
- package/dist/src/commands/shell.js +169 -0
- package/dist/src/commands/tools.js +1847 -0
- package/dist/src/component-files.js +3 -2
- package/dist/src/component-layer.js +4 -2
- package/dist/src/config.js +6 -82
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/consumers.js +10 -38
- package/dist/src/contextual-uses.js +57 -26
- package/dist/src/contract/config.generated.js +561 -0
- package/dist/src/contract/contract.generated.js +1370 -0
- package/dist/src/contract/report.generated.js +866 -0
- package/dist/src/dependencies.js +165 -122
- package/dist/src/destructuring.js +1 -19
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +181 -168
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
- package/dist/src/entries/conventions.js +740 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
- package/dist/src/entries/run-directories.js +77 -0
- package/dist/src/entries/sources.js +144 -0
- package/dist/src/entries/static-module.js +670 -0
- package/dist/src/entries/test-runners.js +650 -0
- package/dist/src/entries/workflow-steps.js +345 -0
- package/dist/src/exemptions/argument-places.js +131 -0
- package/dist/src/exemptions/calls.js +338 -0
- package/dist/src/exemptions/classes.js +13 -0
- package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
- package/dist/src/exemptions/detectors.js +48 -0
- package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
- package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
- package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
- package/dist/src/exemptions/generated-file.js +241 -0
- package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
- package/dist/src/exemptions/installed-globals.js +173 -0
- package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
- package/dist/src/exemptions/lifecycle.js +150 -0
- package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
- package/dist/src/exemptions/serialization-contract.js +1276 -0
- package/dist/src/exemptions/sites.js +182 -0
- package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
- package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
- package/dist/src/exposure.js +400 -0
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +3 -26
- package/dist/src/findings/completion.js +109 -56
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +27 -41
- package/dist/src/{implementations.js → findings/implementations.js} +3 -3
- package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +16 -13
- package/dist/src/findings/non-code-artifacts.js +17 -12
- package/dist/src/findings/reads-and-writes.js +86 -27
- package/dist/src/findings/self-check.js +44 -30
- package/dist/src/findings/unused-declarations.js +29 -45
- package/dist/src/findings/visibility-narrowing.js +23 -31
- package/dist/src/findings-pass.js +13 -21
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +67 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/git-ignore.js +39 -26
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/index/values.js +124 -0
- package/dist/src/index.js +2 -2
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/intra-function-parts.js +63 -43
- package/dist/src/inventory/commonjs.js +507 -0
- package/dist/src/inventory/enumerate.js +167 -0
- package/dist/src/inventory/syntax.js +236 -0
- package/dist/src/inventory.js +323 -724
- package/dist/src/javascript-file.js +48 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +126 -107
- package/dist/src/kinds.js +3 -366
- package/dist/src/{components.js → liveness/components.js} +2 -3
- package/dist/src/{graph.js → liveness/graph.js} +52 -28
- package/dist/src/liveness/matrix.js +99 -0
- package/dist/src/liveness/sweep.js +558 -0
- package/dist/src/load/classify.js +289 -0
- package/dist/src/load/diagnostics.js +87 -0
- package/dist/src/load/discover.js +285 -0
- package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
- package/dist/src/load/expected-module.js +136 -0
- package/dist/src/load/load.js +27 -0
- package/dist/src/load/module-lookup.js +37 -0
- package/dist/src/load/package-scope.js +56 -0
- package/dist/src/load/plan.js +313 -0
- package/dist/src/load/specifiers.js +113 -0
- package/dist/src/load/synthesize.js +152 -0
- package/dist/src/load/test-globals.js +207 -0
- package/dist/src/load/test-joins.js +82 -0
- package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
- package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
- package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
- package/dist/src/{workspace.js → load/workspace.js} +62 -124
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +82 -16
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +134 -0
- package/dist/src/position.js +43 -1
- package/dist/src/print.js +11 -79
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +95 -0
- package/dist/src/ref.js +12 -20
- package/dist/src/references/read-rule.js +1 -0
- package/dist/src/references/read-rules.js +48 -0
- package/dist/src/references/sink.js +237 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +117 -1074
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +57 -41
- package/dist/src/reporters/annotations.js +15 -8
- package/dist/src/reporters/sarif.js +16 -10
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +246 -730
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
- package/dist/src/roots/manifest.js +216 -0
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +487 -0
- package/dist/src/roots/unseen-loads.js +236 -0
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -343
- package/dist/src/scope.js +38 -115
- package/dist/src/session.js +37 -29
- package/dist/src/source-files.js +6 -10
- package/dist/src/stores.js +4 -2
- package/dist/src/suppress-file.js +25 -28
- package/dist/src/suppress-inline.js +36 -83
- package/dist/src/suppress.js +50 -71
- package/dist/src/symbol-keys.js +92 -88
- package/dist/src/tests/file-class.js +76 -0
- package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
- package/dist/src/{test-support.js → tests/support.js} +5 -12
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +298 -0
- package/dist/src/text/yaml.js +684 -0
- package/dist/src/type-errors.js +11 -232
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/vendor/unbash/ansi-c.js +132 -0
- package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
- package/dist/src/vendor/unbash/arithmetic.js +591 -0
- package/dist/src/vendor/unbash/assignment.js +131 -0
- package/dist/src/vendor/unbash/chars.js +48 -0
- package/dist/src/vendor/unbash/command.js +41 -0
- package/dist/src/vendor/unbash/expansion.js +80 -0
- package/dist/src/vendor/unbash/glob.js +268 -0
- package/dist/src/vendor/unbash/heredoc.js +27 -0
- package/dist/src/vendor/unbash/internal-types.js +1 -0
- package/dist/src/vendor/unbash/lexer.js +4274 -0
- package/dist/src/vendor/unbash/limits.js +3 -0
- package/dist/src/vendor/unbash/parser.js +1366 -0
- package/dist/src/vendor/unbash/parts.js +57 -0
- package/dist/src/vendor/unbash/substitution-context.js +8 -0
- package/dist/src/vendor/unbash/traversal.js +212 -0
- package/dist/src/vendor/unbash/types.js +1 -0
- package/dist/src/vendor/unbash/word-value.js +61 -0
- package/dist/src/vendor/unbash/word.js +40 -0
- package/dist/src/verbs/analyze.js +194 -127
- package/dist/src/verbs/describe.js +13 -18
- package/dist/src/verbs/explain.js +85 -139
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +6 -4
- package/dist/src/verbs/print-retained.js +30 -6
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +14 -3
- package/jsr.json +2 -1
- package/package.json +14 -8
- package/src/alias-chain.ts +40 -11
- package/src/amd.ts +130 -0
- package/src/analysis.ts +426 -733
- package/src/augmentations.ts +93 -4
- package/src/automatic-types.ts +12 -30
- package/src/bindings.ts +460 -0
- package/src/commands/held.ts +632 -0
- package/src/commands/read.ts +242 -0
- package/src/commands/shell.ts +228 -0
- package/src/commands/tools.ts +2382 -0
- package/src/component-files.ts +4 -2
- package/src/component-layer.ts +4 -2
- package/src/config.ts +31 -302
- package/src/conformance-record.ts +2 -2
- package/src/consumers.ts +16 -66
- package/src/contextual-uses.ts +66 -34
- package/src/contract/config.generated.ts +821 -0
- package/src/contract/contract.generated.ts +1453 -0
- package/src/contract/report.generated.ts +1241 -0
- package/src/dependencies.ts +223 -128
- package/src/destructuring.ts +1 -31
- package/src/edges.ts +41 -140
- package/src/element-access.ts +190 -187
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
- package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
- package/src/{conventions.ts → entries/conventions.ts} +367 -583
- package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
- package/src/entries/run-directories.ts +108 -0
- package/src/entries/sources.ts +266 -0
- package/src/entries/static-module.ts +858 -0
- package/src/entries/test-runners.ts +835 -0
- package/src/entries/workflow-steps.ts +432 -0
- package/src/exemptions/argument-places.ts +198 -0
- package/src/exemptions/calls.ts +483 -0
- package/src/exemptions/classes.ts +49 -0
- package/src/exemptions/decorator.ts +56 -0
- package/src/exemptions/detectors.ts +75 -0
- package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
- package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
- package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
- package/src/exemptions/generated-file.ts +318 -0
- package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
- package/src/exemptions/installed-globals.ts +255 -0
- package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
- package/src/exemptions/lifecycle.ts +286 -0
- package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
- package/src/exemptions/serialization-contract.ts +1729 -0
- package/src/exemptions/sites.ts +293 -0
- package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
- package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
- package/src/exposure.ts +492 -0
- package/src/extensions.ts +45 -0
- package/src/facts.ts +46 -0
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +15 -25
- package/src/finding.ts +10 -10
- package/src/findings/boundary.ts +11 -0
- package/src/findings/completion.ts +133 -64
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +9 -10
- package/src/findings/emitters.ts +38 -52
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
- package/src/findings/interfaces.ts +7 -9
- package/src/findings/intra-function.ts +16 -14
- package/src/findings/non-code-artifacts.ts +24 -15
- package/src/findings/reads-and-writes.ts +118 -41
- package/src/findings/self-check.ts +51 -38
- package/src/findings/unused-declarations.ts +31 -49
- package/src/findings/visibility-narrowing.ts +36 -40
- package/src/findings-pass.ts +15 -31
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +96 -0
- package/src/fs/tree.ts +110 -0
- package/src/git-ignore.ts +50 -26
- package/src/host.ts +12 -5
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/index/values.ts +170 -0
- package/src/index.ts +2 -2
- package/src/indexed-access.ts +570 -527
- package/src/intra-function-parts.ts +73 -44
- package/src/inventory/commonjs.ts +696 -0
- package/src/inventory/enumerate.ts +203 -0
- package/src/inventory/syntax.ts +311 -0
- package/src/inventory.ts +442 -895
- package/src/javascript-file.ts +54 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +133 -122
- package/src/kinds.ts +5 -413
- package/src/{components.ts → liveness/components.ts} +4 -6
- package/src/{graph.ts → liveness/graph.ts} +100 -35
- package/src/liveness/matrix.ts +162 -0
- package/src/liveness/sweep.ts +855 -0
- package/src/load/classify.ts +433 -0
- package/src/load/diagnostics.ts +154 -0
- package/src/load/discover.ts +471 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +194 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/package-scope.ts +74 -0
- package/src/load/plan.ts +513 -0
- package/src/load/specifiers.ts +171 -0
- package/src/load/synthesize.ts +230 -0
- package/src/load/test-globals.ts +251 -0
- package/src/load/test-joins.ts +98 -0
- package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
- package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/partial.ts +3 -2
- package/src/paths.ts +92 -16
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +189 -0
- package/src/position.ts +44 -1
- package/src/print.ts +12 -92
- package/src/product.ts +18 -0
- package/src/query.ts +201 -10
- package/src/ref.ts +12 -20
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +314 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +187 -1450
- package/src/report-schema.ts +68 -0
- package/src/report.ts +103 -226
- package/src/reporters/annotations.ts +22 -11
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -4
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +29 -16
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +284 -1115
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
- package/src/roots/manifest.ts +303 -0
- package/src/roots/published-reach.ts +486 -0
- package/src/{roots.ts → roots/root-set.ts} +286 -469
- package/src/roots/unseen-loads.ts +345 -0
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -388
- package/src/scope.ts +46 -138
- package/src/session.ts +87 -55
- package/src/source-files.ts +6 -11
- package/src/stores.ts +15 -3
- package/src/suppress-file.ts +24 -33
- package/src/suppress-inline.ts +55 -91
- package/src/suppress.ts +78 -79
- package/src/symbol-keys.ts +104 -107
- package/src/tests/file-class.ts +135 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +15 -21
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.ts +388 -0
- package/src/text/yaml.ts +747 -0
- package/src/type-errors.ts +18 -288
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/vendor/unbash/LICENSE +15 -0
- package/src/vendor/unbash/VENDORED.md +16 -0
- package/src/vendor/unbash/ansi-c.ts +132 -0
- package/src/vendor/unbash/arithmetic-parts.ts +53 -0
- package/src/vendor/unbash/arithmetic.ts +641 -0
- package/src/vendor/unbash/assignment.ts +163 -0
- package/src/vendor/unbash/chars.ts +48 -0
- package/src/vendor/unbash/command.ts +47 -0
- package/src/vendor/unbash/expansion.ts +144 -0
- package/src/vendor/unbash/glob.ts +284 -0
- package/src/vendor/unbash/heredoc.ts +34 -0
- package/src/vendor/unbash/internal-types.ts +94 -0
- package/src/vendor/unbash/lexer.ts +4352 -0
- package/src/vendor/unbash/limits.ts +3 -0
- package/src/vendor/unbash/parser.ts +1612 -0
- package/src/vendor/unbash/parts.ts +96 -0
- package/src/vendor/unbash/substitution-context.ts +20 -0
- package/src/vendor/unbash/traversal.ts +182 -0
- package/src/vendor/unbash/types.ts +660 -0
- package/src/vendor/unbash/word-value.ts +64 -0
- package/src/vendor/unbash/word.ts +50 -0
- package/src/verbs/analyze.ts +255 -164
- package/src/verbs/describe.ts +19 -17
- package/src/verbs/explain.ts +93 -169
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +36 -6
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/dist/src/base-url.js +0 -18
- package/dist/src/calls.js +0 -155
- package/dist/src/conventions.js +0 -937
- package/dist/src/discover.js +0 -468
- package/dist/src/entry-points.js +0 -529
- package/dist/src/exempt-classes.js +0 -75
- package/dist/src/exempt.js +0 -209
- package/dist/src/generated-file.js +0 -95
- package/dist/src/glob.js +0 -65
- package/dist/src/manifest.js +0 -165
- package/dist/src/matrix.js +0 -246
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/roots.js +0 -672
- package/dist/src/serialization-contract.js +0 -611
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/sweep.js +0 -224
- package/dist/src/test-joins.js +0 -101
- package/dist/src/value-flow.js +0 -74
- package/dist/src/version.js +0 -7
- package/dist/src/workflow-steps.js +0 -185
- package/src/base-url.ts +0 -24
- package/src/calls.ts +0 -225
- package/src/decorator.ts +0 -78
- package/src/discover.ts +0 -653
- package/src/entry-points.ts +0 -687
- package/src/exempt-classes.ts +0 -123
- package/src/exempt.ts +0 -323
- package/src/generated-file.ts +0 -111
- package/src/glob.ts +0 -67
- package/src/manifest.ts +0 -234
- package/src/matrix.ts +0 -423
- package/src/pnpm-workspace.ts +0 -135
- package/src/serialization-contract.ts +0 -849
- package/src/setup-failure.ts +0 -39
- package/src/sweep.ts +0 -347
- package/src/test-joins.ts +0 -120
- package/src/value-flow.ts +0 -104
- package/src/version.ts +0 -7
- package/src/workflow-steps.ts +0 -216
package/src/analysis.ts
CHANGED
|
@@ -6,131 +6,90 @@
|
|
|
6
6
|
* another project's checker, which holds only for views the session hands out.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { isStringLiteralLikeNode } from "@typescript/native/ast";
|
|
9
|
+
import { isStringLiteralLikeNode, type SourceFile } from "@typescript/native/ast";
|
|
10
10
|
import { lineOf, readComponent } from "./component-files.ts";
|
|
11
|
-
import { kindOf, type
|
|
12
|
-
import {
|
|
13
|
-
consumerLoads,
|
|
14
|
-
consumerReferences,
|
|
15
|
-
moduleIdentity,
|
|
16
|
-
type LoadedConsumer,
|
|
17
|
-
} from "./consumers.ts";
|
|
11
|
+
import { kindOf, type PartialConfig, type Provenance, type ResolvedConfig } from "./config.ts";
|
|
12
|
+
import { consumerReferences } from "./consumers.ts";
|
|
18
13
|
import {
|
|
19
14
|
configuredDeclarations,
|
|
20
15
|
configuredRef,
|
|
21
16
|
declarationsNamed,
|
|
22
|
-
} from "./configured-declarations.ts";
|
|
23
|
-
import { decorator } from "./decorator.ts";
|
|
17
|
+
} from "./roots/configured-declarations.ts";
|
|
24
18
|
import { configurationNeeds, dependenciesOf, projectNeeds } from "./dependencies.ts";
|
|
19
|
+
import { carriersOf, NO_CARRIERS, type Carriers } from "./exposure.ts";
|
|
25
20
|
import { deprecatedDeclarations, type Deprecation } from "./deprecation.ts";
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
renderDiagnostic,
|
|
33
|
-
targetRelative,
|
|
34
|
-
withBaseUrlPaths,
|
|
35
|
-
type LocatedDiagnostic,
|
|
36
|
-
type NotBuilt,
|
|
37
|
-
} from "./discover.ts";
|
|
38
|
-
import {
|
|
39
|
-
conventionFailuresFor,
|
|
40
|
-
generatedFiles,
|
|
41
|
-
readConventions,
|
|
42
|
-
type AppliedConvention,
|
|
43
|
-
type ConventionManifest,
|
|
44
|
-
type Conventions,
|
|
45
|
-
} from "./conventions.ts";
|
|
21
|
+
import { moduleIdentity, type LoadedConsumer, type NotBuilt } from "./load/discover.ts";
|
|
22
|
+
import type { LibraryUnfound } from "./load/classify.ts";
|
|
23
|
+
import { loadRun, type LoadedRun } from "./load/load.ts";
|
|
24
|
+
import type { AppliedConvention } from "./entries/conventions.ts";
|
|
25
|
+
import { readSources, type SourceFacts } from "./entries/sources.ts";
|
|
26
|
+
import { readWorkflows, type Workflows } from "./entries/workflow-steps.ts";
|
|
46
27
|
import { readEdgeSides } from "./edges.ts";
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import { inOperandNames } from "./in-operands.ts";
|
|
28
|
+
import { bindingsOf, distinctBindings, type BindingRecord } from "./bindings.ts";
|
|
29
|
+
import { generatedFilesOf, type GeneratedFact } from "./exemptions/generated-file.ts";
|
|
30
|
+
import { inOperandNames } from "./findings/in-operands.ts";
|
|
50
31
|
import { sourceFilesOf } from "./source-files.ts";
|
|
51
|
-
import {
|
|
52
|
-
|
|
53
|
-
heldRecords,
|
|
54
|
-
disabledClasses,
|
|
55
|
-
exemptionsOf,
|
|
56
|
-
holdingWhile,
|
|
57
|
-
isUnansweredRecord,
|
|
58
|
-
retainedIn,
|
|
59
|
-
type Detector,
|
|
60
|
-
type Detectors,
|
|
61
|
-
} from "./exempt.ts";
|
|
62
|
-
import type { TSExemptionClass } from "./exempt-classes.ts";
|
|
32
|
+
import { DETECTORS, detection } from "./exemptions/detectors.ts";
|
|
33
|
+
import { exemptionsOf, settle, type Detectors, type Exemption } from "./exemptions/lifecycle.ts";
|
|
63
34
|
import { heldByInclusion, sourcePaths, sourceTree } from "./file-facts.ts";
|
|
64
|
-
import { globExpression } from "./glob.ts";
|
|
65
35
|
import type { Finding } from "./finding.ts";
|
|
66
36
|
import { findingsPass, recordedFindings, rowKey, type PassResult } from "./findings-pass.ts";
|
|
67
37
|
import type { EmitterInput } from "./findings/emitter.ts";
|
|
68
38
|
import { unmatchedRootFindings, type SelfCheckFacts } from "./findings/self-check.ts";
|
|
69
|
-
import { frameworkLifecycle } from "./framework-lifecycle.ts";
|
|
70
39
|
import type { Host } from "./host.ts";
|
|
71
|
-
import { implementations, mergeImplementations } from "./implementations.ts";
|
|
72
|
-
import { injectionContainer } from "./injection-container.ts";
|
|
73
|
-
import { interfaceSatisfaction, settledSatisfaction } from "./interface-satisfaction.ts";
|
|
40
|
+
import { implementations, mergeImplementations } from "./findings/implementations.ts";
|
|
74
41
|
import { intraFunctionFacts, projectParts, type ProjectParts } from "./intra-function-parts.ts";
|
|
75
|
-
import {
|
|
76
|
-
import {
|
|
77
|
-
import {
|
|
78
|
-
|
|
79
|
-
matrixOf,
|
|
80
|
-
referenceKey,
|
|
81
|
-
sweepMatrix,
|
|
82
|
-
type Configured,
|
|
83
|
-
type Matrix,
|
|
84
|
-
type SweepResult,
|
|
85
|
-
} from "./matrix.ts";
|
|
42
|
+
import { type Inventory, type InventorySymbol } from "./inventory.ts";
|
|
43
|
+
import { inventory } from "./inventory/enumerate.ts";
|
|
44
|
+
import { readManifest, type ManifestEntry } from "./roots/manifest.ts";
|
|
45
|
+
import { matrixOf, referenceKey, type Configured, type Matrix } from "./liveness/matrix.ts";
|
|
86
46
|
import {
|
|
47
|
+
ancestors,
|
|
87
48
|
dirnamePath,
|
|
88
49
|
extensionOf,
|
|
89
50
|
joinPath,
|
|
90
|
-
normalizePath,
|
|
91
51
|
relativePath,
|
|
92
52
|
resolvePath,
|
|
93
53
|
} from "./paths.ts";
|
|
94
54
|
import type { UnansweredQuestion } from "./query.ts";
|
|
95
55
|
import { byPosition, isComponentFile, type Position } from "./position.ts";
|
|
96
|
-
import {
|
|
97
|
-
import {
|
|
98
|
-
import {
|
|
99
|
-
pathsOf,
|
|
100
|
-
readErrors,
|
|
101
|
-
skippedRoots,
|
|
102
|
-
skippedUnits,
|
|
103
|
-
type SkippedUnit,
|
|
104
|
-
} from "./type-errors.ts";
|
|
105
|
-
import { reflectiveLookup } from "./reflective-lookup.ts";
|
|
106
|
-
import { references, testFileRulesOf, type Reference, type TestFileRule } from "./references.ts";
|
|
56
|
+
import type { TypeErrorSkip, UnansweredCount } from "./report.ts";
|
|
57
|
+
import { skippedUnits, type SkippedUnit } from "./type-errors.ts";
|
|
58
|
+
import { references, type Reference } from "./references.ts";
|
|
107
59
|
import {
|
|
108
|
-
|
|
60
|
+
rootSet,
|
|
109
61
|
unmatchedEverywhere,
|
|
110
62
|
type RootKind,
|
|
111
|
-
type RootOptions,
|
|
112
63
|
type Roots,
|
|
113
|
-
|
|
64
|
+
type HeldScripts,
|
|
65
|
+
} from "./roots/root-set.ts";
|
|
114
66
|
import type { Scope } from "./scope.ts";
|
|
115
|
-
import {
|
|
116
|
-
import { outsideTestReferences, testFilesAt, type OutsideTest } from "./outside
|
|
117
|
-
import {
|
|
118
|
-
import {
|
|
67
|
+
import { decodedMembers, type Decoded } from "./exemptions/serialization-contract.ts";
|
|
68
|
+
import { outsideTestReferences, testFilesAt, type OutsideTest } from "./tests/outside.ts";
|
|
69
|
+
import type { UnseenLoad } from "./roots/unseen-loads.ts";
|
|
70
|
+
import type { UnresolvedSpecifier } from "./load/specifiers.ts";
|
|
71
|
+
import { formedForNode } from "./load/synthesize.ts";
|
|
72
|
+
import type { UnreadInput } from "./load/plan.ts";
|
|
73
|
+
import { GLOBALS_RUNNER, namesTestGlobals } from "./load/test-globals.ts";
|
|
119
74
|
import {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
type
|
|
125
|
-
|
|
126
|
-
} from "./
|
|
75
|
+
targetTestFile,
|
|
76
|
+
testFilePaths,
|
|
77
|
+
testFileRulesOf,
|
|
78
|
+
withheldBy,
|
|
79
|
+
type TestFileRule,
|
|
80
|
+
} from "./tests/file-class.ts";
|
|
81
|
+
import { testSupportFiles, type TestEvidence } from "./tests/support.ts";
|
|
82
|
+
import type { Engine, ProjectView } from "./session.ts";
|
|
127
83
|
import { accessorsOf, storesOf } from "./stores.ts";
|
|
128
84
|
import { isPartKind, type SuppressionRecord, type Suppressions, type Verdict } from "./suppress.ts";
|
|
129
85
|
import { bindRows, readBaseline, readIgnoreFile, type Recorded } from "./suppress-file.ts";
|
|
130
86
|
import { inlineDirectives, inlineSuppressions, type InlineDirective } from "./suppress-inline.ts";
|
|
131
|
-
import
|
|
132
|
-
import {
|
|
133
|
-
import {
|
|
87
|
+
import { sweep, type Sweep, type SweepPolicy } from "./liveness/sweep.ts";
|
|
88
|
+
import type { Mode } from "./tests/file-class.ts";
|
|
89
|
+
import { bytewise } from "./text/compare.ts";
|
|
90
|
+
import { holdsManifest, manifestAt } from "./fs/manifest.ts";
|
|
91
|
+
import { runDirectories } from "./entries/run-directories.ts";
|
|
92
|
+
import { globExpression } from "./text/glob.ts";
|
|
134
93
|
|
|
135
94
|
/** The setting whose source decides where a finding about a configured root sits. */
|
|
136
95
|
const ROOTS_SETTING = "roots.patterns";
|
|
@@ -187,14 +146,6 @@ function documentOf(
|
|
|
187
146
|
return relativePath(resolvePath(host.workingDirectory(), targetRoot), document) ?? "";
|
|
188
147
|
}
|
|
189
148
|
|
|
190
|
-
/** Two strings ordered bytewise. */
|
|
191
|
-
function compare(a: string, b: string): number {
|
|
192
|
-
if (a === b) {
|
|
193
|
-
return 0;
|
|
194
|
-
}
|
|
195
|
-
return a < b ? -1 : 1;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
149
|
/** What every stage after the root set reads of one project. */
|
|
199
150
|
interface ProjectRead {
|
|
200
151
|
readonly configuration: string;
|
|
@@ -211,10 +162,14 @@ interface ProjectRead {
|
|
|
211
162
|
readonly typeErrorSkips: readonly TypeErrorSkip[];
|
|
212
163
|
/** The lines each of those skips withholds every finding on. */
|
|
213
164
|
readonly skipped: readonly SkippedUnit[];
|
|
214
|
-
/** The project's generated files, by path below the target root, each with
|
|
215
|
-
readonly generated: ReadonlyMap<string,
|
|
216
|
-
/** The
|
|
217
|
-
readonly
|
|
165
|
+
/** The project's generated files, by path below the target root, each with what decided it. */
|
|
166
|
+
readonly generated: ReadonlyMap<string, GeneratedFact>;
|
|
167
|
+
/** The binding identities its generated files publish (`bindings.6`, `bindings.7`). */
|
|
168
|
+
readonly bindings: readonly BindingRecord[];
|
|
169
|
+
/** What the project's entry sources enter and name, read once. */
|
|
170
|
+
readonly sources: SourceFacts;
|
|
171
|
+
/** Whether the run formed the program to resolve its modules as Node does (program.36). */
|
|
172
|
+
readonly formedForNode: boolean;
|
|
218
173
|
}
|
|
219
174
|
|
|
220
175
|
/** One target project the run analyzes, as its stage is handed it. */
|
|
@@ -224,346 +179,67 @@ interface OpenedProject {
|
|
|
224
179
|
readonly read: () => ProjectRead;
|
|
225
180
|
}
|
|
226
181
|
|
|
227
|
-
/** What a run
|
|
228
|
-
interface
|
|
229
|
-
|
|
230
|
-
readonly loaded: readonly LoadedConsumer[];
|
|
182
|
+
/** What reading a loaded run's projects answered. */
|
|
183
|
+
interface ProjectsRead<Answer> {
|
|
184
|
+
readonly answers: readonly Answer[];
|
|
231
185
|
/** Every reference a consumer makes to a declaration of the target, each once. */
|
|
232
186
|
readonly references: readonly Reference[];
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
/** What a run read of its projects: each target project's answer, and its consumers. */
|
|
236
|
-
interface ReadProjects<Answer> {
|
|
237
|
-
readonly answers: readonly Answer[];
|
|
238
|
-
readonly consumers: ConsumerReads;
|
|
239
|
-
/** The derived configurations the run dropped, in the order it met them. */
|
|
240
|
-
readonly notBuilt: readonly NotBuilt[];
|
|
241
|
-
/** Every question the checker could not answer, each once. */
|
|
242
|
-
readonly unanswered: readonly UnansweredQuestion[];
|
|
243
|
-
/** Per configuration whose component files the run cannot read, the reason. */
|
|
244
|
-
readonly componentsUnread: readonly ComponentsUnread[];
|
|
245
|
-
/** Per analyzed configuration, each library it names that the compiler cannot find. */
|
|
246
|
-
readonly librariesUnfound: readonly LibraryUnfound[];
|
|
247
|
-
/** The convention rows the run applied. */
|
|
248
|
-
readonly conventionsApplied: readonly AppliedConvention[];
|
|
249
|
-
/** The dependencies the applied rows' short names use. */
|
|
250
|
-
readonly conventionUses: readonly string[];
|
|
251
|
-
/** The directory of every workspace member, absolute. */
|
|
252
|
-
readonly memberDirs: readonly string[];
|
|
253
|
-
/** The directory of every nested package, absolute. */
|
|
254
|
-
readonly nestedDirs: readonly string[];
|
|
187
|
+
/** The declarations a consumer's read rules held, each once. */
|
|
188
|
+
readonly consumerHeld: readonly string[];
|
|
255
189
|
/** The test files below the target root no project the run reads holds, parsed. */
|
|
256
190
|
readonly outsideTests: readonly OutsideTest[];
|
|
191
|
+
/** The target root's workflow steps, git hooks and makefile, read once for every project. */
|
|
192
|
+
readonly workflows: Workflows;
|
|
257
193
|
}
|
|
258
194
|
|
|
259
195
|
/**
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
|
|
263
|
-
function conventionManifests(
|
|
264
|
-
host: Host,
|
|
265
|
-
targetRoot: string,
|
|
266
|
-
memberDirs: readonly string[],
|
|
267
|
-
nestedDirs: readonly string[],
|
|
268
|
-
): readonly ConventionManifest[] {
|
|
269
|
-
const found = new Map<string, ConventionManifest>();
|
|
270
|
-
if (host.kindOf(joinPath(targetRoot, "package.json")) === "file") {
|
|
271
|
-
found.set(targetRoot, { dir: targetRoot, path: "package.json" });
|
|
272
|
-
}
|
|
273
|
-
for (const [dirs, nested] of [
|
|
274
|
-
[memberDirs, false],
|
|
275
|
-
[nestedDirs, true],
|
|
276
|
-
] as const) {
|
|
277
|
-
for (const dir of dirs) {
|
|
278
|
-
const below = relativePath(targetRoot, dir);
|
|
279
|
-
if (below !== undefined && !found.has(dir)) {
|
|
280
|
-
found.set(dir, { dir, path: `${below}/package.json`, nested });
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return [...found.values()];
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* The nested packages of a run: each directory below the target root, in no `node_modules`
|
|
289
|
-
* directory and none of `known`, that holds a `package.json` and lies at or above one of
|
|
290
|
-
* `files`, the program's source files and the compiler configuration files, in path order.
|
|
291
|
-
*/
|
|
292
|
-
function nestedPackageDirs(
|
|
293
|
-
host: Host,
|
|
294
|
-
targetRoot: string,
|
|
295
|
-
files: Iterable<string>,
|
|
296
|
-
known: ReadonlySet<string>,
|
|
297
|
-
): readonly string[] {
|
|
298
|
-
const seen = new Set<string>();
|
|
299
|
-
const found: string[] = [];
|
|
300
|
-
for (const file of files) {
|
|
301
|
-
for (
|
|
302
|
-
let dir = dirnamePath(file);
|
|
303
|
-
dir !== targetRoot && !seen.has(dir) && relativePath(targetRoot, dir) !== undefined;
|
|
304
|
-
dir = dirnamePath(dir)
|
|
305
|
-
) {
|
|
306
|
-
seen.add(dir);
|
|
307
|
-
const below = relativePath(targetRoot, dir) ?? "";
|
|
308
|
-
if (
|
|
309
|
-
!below.split("/").includes("node_modules") &&
|
|
310
|
-
!known.has(dir) &&
|
|
311
|
-
host.kindOf(joinPath(dir, "package.json")) === "file"
|
|
312
|
-
) {
|
|
313
|
-
found.push(dir);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return found.sort(compare);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Reads every project the scope discovers, and each declared consumer's, in one snapshot,
|
|
322
|
-
* each checked for errors first. `stage` is handed a target project and enumerates and roots
|
|
323
|
-
* it if it reads it; a consumer project is read for its references to the target. A type error
|
|
324
|
-
* in an own file skips the unit holding it. A guess that does not load or meets a setup failure
|
|
325
|
-
* is dropped into `notBuilt` (see {@link isGuess}); any other such project fails the run, as
|
|
326
|
-
* does a run whose every guess was dropped.
|
|
196
|
+
* Reads every project the load phase analyzes through `stage`, which enumerates and roots one
|
|
197
|
+
* if it reads it, and each declared consumer's project for its references to the target,
|
|
198
|
+
* in the same snapshot. A type error in an own file skips the unit holding it.
|
|
327
199
|
*/
|
|
328
200
|
function readProjects<Answer>(
|
|
329
201
|
engine: Engine,
|
|
330
202
|
host: Host,
|
|
331
203
|
scope: Scope,
|
|
332
|
-
config:
|
|
204
|
+
config: PartialConfig,
|
|
333
205
|
stage: <Brand>(project: ProjectView<Brand>, opened: OpenedProject) => Answer,
|
|
334
|
-
):
|
|
206
|
+
): LoadedRun<ProjectsRead<Answer>> {
|
|
335
207
|
const targetRoot = scope.target.path;
|
|
336
|
-
const discovered = discoverProjects(engine, host, scope, config.analysis.configurations);
|
|
337
|
-
if (discovered.configFiles.length === 0 && discovered.notBuilt.length === 0) {
|
|
338
|
-
throw new DiscoveryError(
|
|
339
|
-
`${targetRoot} holds no compiler configuration, so the run holds no program`,
|
|
340
|
-
[],
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
const ids = new Map(discovered.projects.map((project) => [project.configFile, project.id]));
|
|
344
|
-
const loads = consumerLoads(engine, host, scope, discovered.configFiles);
|
|
345
|
-
const consumerOf = new Map(
|
|
346
|
-
loads.flatMap((load) =>
|
|
347
|
-
load.configFiles.map((configFile) => [configFile, load.consumer] as const),
|
|
348
|
-
),
|
|
349
|
-
);
|
|
350
208
|
const absoluteRoot = resolvePath(host.workingDirectory(), targetRoot);
|
|
351
|
-
const
|
|
352
|
-
engine,
|
|
353
|
-
host,
|
|
354
|
-
absoluteRoot,
|
|
355
|
-
discovered.configFiles,
|
|
356
|
-
readManifest(host, targetRoot),
|
|
357
|
-
);
|
|
209
|
+
const testPatterns = config.ts.test_files.map(globExpression);
|
|
358
210
|
const parse = (fileName: string, text: string) => engine.parseSourceFile(fileName, text);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
let conventions = readConventions(host, parse, [], config.ts.disabledConventions);
|
|
364
|
-
let options: RootOptions & { readonly parse: typeof parse; readonly conventions: Conventions };
|
|
365
|
-
const readManifests = (opened: readonly OpenedFiles[]): void => {
|
|
366
|
-
nestedDirs = nestedPackageDirs(
|
|
367
|
-
host,
|
|
368
|
-
normalizePath(absoluteRoot),
|
|
369
|
-
opened
|
|
370
|
-
.filter((one) => !consumerOf.has(one.configFile))
|
|
371
|
-
.flatMap((one) => [one.configFile, ...one.fileNames()]),
|
|
372
|
-
new Set(memberDirs),
|
|
373
|
-
);
|
|
374
|
-
conventions = readConventions(
|
|
211
|
+
return loadRun(engine, host, scope, config, ({ plan, classified, runFiles }) => {
|
|
212
|
+
const { packages, conventions } = plan;
|
|
213
|
+
const workflows = readWorkflows(host, targetRoot);
|
|
214
|
+
const options = {
|
|
375
215
|
host,
|
|
216
|
+
manifest: packages.manifest,
|
|
217
|
+
otherPackages: packages.entries,
|
|
218
|
+
patterns: config.roots.patterns,
|
|
219
|
+
entryFiles: config.ts.entry_files,
|
|
376
220
|
parse,
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
options = {
|
|
381
|
-
host,
|
|
382
|
-
manifest: workspace?.manifest ?? readManifest(host, targetRoot),
|
|
383
|
-
otherPackages: [
|
|
384
|
-
...(workspace?.entries ?? []),
|
|
385
|
-
...packageEntries(host, normalizePath(absoluteRoot), nestedDirs),
|
|
386
|
-
],
|
|
387
|
-
patterns: config.rootPatterns,
|
|
388
|
-
entryFiles: config.ts.entryFiles,
|
|
389
|
-
conventions,
|
|
390
|
-
testFiles: config.ts.testFiles,
|
|
391
|
-
parse,
|
|
392
|
-
publishedAPI: config.targetKind !== "" && kindOf(config.targetKind, LANGUAGE) === "library",
|
|
393
|
-
publishedMembers: new Set(
|
|
394
|
-
(workspace?.entries ?? []).filter((entry) => entry.published).map((entry) => entry.dir),
|
|
395
|
-
),
|
|
396
|
-
runFiles: new Set(
|
|
397
|
-
opened.flatMap((one) =>
|
|
398
|
-
one.fileNames().map((name) => resolvePath(host.workingDirectory(), name)),
|
|
399
|
-
),
|
|
400
|
-
),
|
|
221
|
+
publishedAPI: config.target.kind !== undefined && kindOf(config.target.kind) === "library",
|
|
222
|
+
publishedMembers: packages.published,
|
|
223
|
+
runFiles,
|
|
401
224
|
};
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
const dropped = (configFile: string, error: string): void => {
|
|
405
|
-
notBuilt.push({
|
|
406
|
-
id: ids.get(configFile) ?? configFile,
|
|
407
|
-
configFile,
|
|
408
|
-
error: targetRelative(error, absoluteRoot),
|
|
409
|
-
});
|
|
410
|
-
};
|
|
411
|
-
const failures: LocatedDiagnostic[] = [];
|
|
412
|
-
const unbuildable: SetupFailure[] = [];
|
|
413
|
-
const setupDropped: SetupFailure[] = [];
|
|
414
|
-
const librariesUnfound: LibraryUnfound[] = [];
|
|
415
|
-
const consumed = new Map<string, Reference>();
|
|
416
|
-
const heldFiles = new Set<string>();
|
|
417
|
-
let outsideTests: readonly OutsideTest[] = [];
|
|
418
|
-
const setupMet = (configFile: string, met: readonly SetupFailure[]): void => {
|
|
419
|
-
const [first] = met;
|
|
420
|
-
if (first !== undefined && isGuess(discovered, configFile)) {
|
|
421
|
-
dropped(configFile, setupLine(first));
|
|
422
|
-
setupDropped.push(...met);
|
|
423
|
-
} else {
|
|
424
|
-
unbuildable.push(...met);
|
|
425
|
-
}
|
|
426
|
-
};
|
|
427
|
-
const testPatterns = config.ts.testFiles.map(globExpression);
|
|
428
|
-
const joins = discovered.derived
|
|
429
|
-
? joinedTestFiles(engine, host, absoluteRoot, discovered.configFiles, testPatterns)
|
|
430
|
-
: new Map<string, readonly string[]>();
|
|
431
|
-
const programs = withBaseUrlPaths(
|
|
432
|
-
engine,
|
|
433
|
-
host,
|
|
434
|
-
[...discovered.configFiles, ...consumerOf.keys()],
|
|
435
|
-
workspace?.programs ?? new Map(),
|
|
436
|
-
);
|
|
437
|
-
const session = runSession(
|
|
438
|
-
engine,
|
|
439
|
-
[...discovered.configFiles, ...consumerOf.keys()],
|
|
440
|
-
(opened) => {
|
|
441
|
-
const consumer = consumerOf.get(opened.configFile);
|
|
442
|
-
const setup = consumer === undefined ? workspace?.unbuildable(opened.configFile) : undefined;
|
|
443
|
-
if (setup !== undefined) {
|
|
444
|
-
setupMet(opened.configFile, [
|
|
445
|
-
{ setupClass: "workspace-member-without-source", detail: setup },
|
|
446
|
-
]);
|
|
447
|
-
return undefined;
|
|
448
|
-
}
|
|
449
|
-
const referenceOnly =
|
|
450
|
-
workspace === undefined || consumer !== undefined
|
|
451
|
-
? () => false
|
|
452
|
-
: workspace.referenceOnly(opened.configFile, opened.rootFiles);
|
|
453
|
-
const project =
|
|
454
|
-
workspace === undefined || consumer !== undefined
|
|
455
|
-
? opened
|
|
456
|
-
: ownedAs(opened, (file, fromExternalLibrary) =>
|
|
457
|
-
workspace.ownFile(file, fromExternalLibrary),
|
|
458
|
-
);
|
|
459
|
-
const raw = projectErrors(diagnosticsOf(project));
|
|
460
|
-
const errors = { load: raw.load, check: ownErrors(raw.check, referenceOnly) };
|
|
461
|
-
const [unloaded] = errors.load;
|
|
462
|
-
if (
|
|
463
|
-
unloaded !== undefined &&
|
|
464
|
-
consumer === undefined &&
|
|
465
|
-
isGuess(discovered, project.configFile)
|
|
466
|
-
) {
|
|
467
|
-
dropped(
|
|
468
|
-
project.configFile,
|
|
469
|
-
renderDiagnostic(unloaded, (path) => relativePath(absoluteRoot, path) ?? path),
|
|
470
|
-
);
|
|
471
|
-
return undefined;
|
|
472
|
-
}
|
|
473
|
-
if (errors.load.length > 0) {
|
|
474
|
-
failures.push(...errors.load);
|
|
475
|
-
return undefined;
|
|
476
|
-
}
|
|
477
|
-
const reading = readErrors(project, errors.check, {
|
|
478
|
-
host,
|
|
479
|
-
targetRoot:
|
|
480
|
-
consumer === undefined
|
|
481
|
-
? absoluteRoot
|
|
482
|
-
: resolvePath(host.workingDirectory(), consumer.path),
|
|
483
|
-
paths: pathsOf(engine, project.configFile),
|
|
484
|
-
});
|
|
485
|
-
if (consumer !== undefined && reading.missing.length > 0) {
|
|
486
|
-
unbuildable.push(
|
|
487
|
-
...reading.missing.map((one) => ({
|
|
488
|
-
setupClass: "missing-consumer" as const,
|
|
489
|
-
detail: `the consumer ${consumer.path} does not build, its dependencies not installed: ${one.detail}`,
|
|
490
|
-
})),
|
|
491
|
-
);
|
|
492
|
-
return undefined;
|
|
493
|
-
}
|
|
494
|
-
if (reading.missing.length > 0) {
|
|
495
|
-
setupMet(project.configFile, reading.missing);
|
|
496
|
-
return undefined;
|
|
497
|
-
}
|
|
498
|
-
const unconventional =
|
|
499
|
-
consumer === undefined
|
|
500
|
-
? conventionFailuresFor(
|
|
501
|
-
conventions,
|
|
502
|
-
project.configFile,
|
|
503
|
-
project.ownSourceFiles().map((file) => file.fileName),
|
|
504
|
-
)
|
|
505
|
-
: [];
|
|
506
|
-
if (unconventional.length > 0) {
|
|
507
|
-
setupMet(project.configFile, unconventional);
|
|
508
|
-
return undefined;
|
|
509
|
-
}
|
|
510
|
-
if (consumer !== undefined) {
|
|
511
|
-
for (const reference of consumerReferences(
|
|
512
|
-
project,
|
|
513
|
-
host,
|
|
514
|
-
targetRoot,
|
|
515
|
-
{
|
|
516
|
-
id: consumer.id,
|
|
517
|
-
root: consumer.path,
|
|
518
|
-
},
|
|
519
|
-
config,
|
|
520
|
-
)) {
|
|
521
|
-
consumed.set(referenceKey(reference), reference);
|
|
522
|
-
}
|
|
523
|
-
return undefined;
|
|
524
|
-
}
|
|
525
|
-
librariesUnfound.push(
|
|
526
|
-
...raw.unfound.map((one) => ({
|
|
527
|
-
configFile: project.configFile,
|
|
528
|
-
error: renderDiagnostic(one, (path) => relativePath(absoluteRoot, path) ?? path),
|
|
529
|
-
})),
|
|
530
|
-
);
|
|
531
|
-
const missingGlobal = raw.unfound.find(
|
|
532
|
-
({ diagnostic }) => diagnostic.code === MISSING_GLOBAL_TYPE,
|
|
533
|
-
);
|
|
534
|
-
const skips =
|
|
535
|
-
missingGlobal === undefined
|
|
536
|
-
? reading.skips
|
|
537
|
-
: [
|
|
538
|
-
...reading.skips,
|
|
539
|
-
...project.ownSourceFiles().map((file) => ({
|
|
540
|
-
record: {
|
|
541
|
-
path: relativePath(absoluteRoot, file.fileName) ?? file.fileName,
|
|
542
|
-
line: 1,
|
|
543
|
-
message: missingGlobal.diagnostic.text,
|
|
544
|
-
},
|
|
545
|
-
file,
|
|
546
|
-
unit: file,
|
|
547
|
-
})),
|
|
548
|
-
];
|
|
549
|
-
const configuration = ids.get(project.configFile) ?? project.configFile;
|
|
225
|
+
const heldFiles = new Set<string>();
|
|
226
|
+
const answers = classified.analyzed.map(({ plan: planned, project, skips, referenceOnly }) => {
|
|
550
227
|
const read = (): ProjectRead => {
|
|
551
228
|
const held = inventory(project, host, targetRoot);
|
|
552
|
-
const found = roots(project, held, targetRoot, options);
|
|
553
|
-
const kept = skippedRoots(project, held, skips);
|
|
554
|
-
const rooted =
|
|
555
|
-
kept.length === 0
|
|
556
|
-
? found
|
|
557
|
-
: {
|
|
558
|
-
...found,
|
|
559
|
-
liveUnderReachability: [
|
|
560
|
-
...found.liveUnderReachability,
|
|
561
|
-
...kept.map((id) => ({ id, kind: "type-error" as const, source: "" })),
|
|
562
|
-
],
|
|
563
|
-
};
|
|
564
229
|
const own = sourceFilesOf(project, targetRoot);
|
|
230
|
+
const sources = readSources({
|
|
231
|
+
host,
|
|
232
|
+
targetRoot,
|
|
233
|
+
files: own,
|
|
234
|
+
parse,
|
|
235
|
+
testFiles: config.ts.test_files,
|
|
236
|
+
conventions,
|
|
237
|
+
workflows,
|
|
238
|
+
});
|
|
239
|
+
const rooted = rootSet(project, held, targetRoot, { ...options, sources, skips });
|
|
240
|
+
const generated = generatedFilesOf(own, sources.generated);
|
|
565
241
|
return {
|
|
566
|
-
configuration,
|
|
242
|
+
configuration: planned.id,
|
|
567
243
|
configFile: project.configFile,
|
|
568
244
|
held,
|
|
569
245
|
rooted,
|
|
@@ -573,71 +249,53 @@ function readProjects<Answer>(
|
|
|
573
249
|
.ownSourceFiles()
|
|
574
250
|
.filter((file) => referenceOnly(file.fileName))
|
|
575
251
|
.flatMap((file) => relativePath(absoluteRoot, file.fileName) ?? []),
|
|
576
|
-
generated
|
|
577
|
-
|
|
252
|
+
generated,
|
|
253
|
+
bindings: bindingsOf(
|
|
254
|
+
own.byPath,
|
|
255
|
+
generated,
|
|
256
|
+
new Map(
|
|
257
|
+
held.symbols
|
|
258
|
+
.filter((one) => one.kind === "file")
|
|
259
|
+
.map((one) => [one.position.path, one.ref]),
|
|
260
|
+
),
|
|
261
|
+
),
|
|
262
|
+
sources,
|
|
263
|
+
formedForNode: formedForNode(planned),
|
|
578
264
|
};
|
|
579
265
|
};
|
|
580
266
|
for (const file of project.ownSourceFiles()) {
|
|
581
267
|
heldFiles.add(relativePath(absoluteRoot, file.fileName) ?? file.fileName);
|
|
582
268
|
}
|
|
583
|
-
return stage(project, { configuration, read });
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
()
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
},
|
|
597
|
-
readManifests,
|
|
598
|
-
);
|
|
599
|
-
for (const configFile of session.unopened) {
|
|
600
|
-
if (consumerOf.has(configFile) || !isGuess(discovered, configFile)) {
|
|
601
|
-
throw new DiscoveryError(`${configFile} opened no project`, []);
|
|
269
|
+
return stage(project, { configuration: planned.id, read });
|
|
270
|
+
});
|
|
271
|
+
const consumed = new Map<string, Reference>();
|
|
272
|
+
const consumerHeld = new Set<string>();
|
|
273
|
+
for (const { project, consumer } of classified.consumed) {
|
|
274
|
+
const side = { id: consumer.id, root: consumer.path };
|
|
275
|
+
const read = consumerReferences(project, host, targetRoot, side, config, parse);
|
|
276
|
+
for (const reference of read.references) {
|
|
277
|
+
consumed.set(referenceKey(reference), reference);
|
|
278
|
+
}
|
|
279
|
+
for (const id of read.held) {
|
|
280
|
+
consumerHeld.add(id);
|
|
281
|
+
}
|
|
602
282
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
`${String(failures.length)} error(s), so no answer was produced`,
|
|
611
|
-
failures,
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
const answers = session.projects.filter((answer): answer is Answer => answer !== undefined);
|
|
615
|
-
const [first] = notBuilt;
|
|
616
|
-
if (answers.length === 0 && setupDropped.length > 0) {
|
|
617
|
-
throw new SetupError(setupDropped);
|
|
618
|
-
}
|
|
619
|
-
if (answers.length === 0 && first !== undefined) {
|
|
620
|
-
throw new DiscoveryError(
|
|
621
|
-
`no configuration discovery derived could be built; ${first.id}: ${first.error}`,
|
|
622
|
-
[],
|
|
283
|
+
const outsideTests = testFilesAt(
|
|
284
|
+
host,
|
|
285
|
+
targetRoot,
|
|
286
|
+
sourcePaths(host, targetRoot).filter(
|
|
287
|
+
(path) => !heldFiles.has(path) && testPatterns.some((pattern) => pattern.test(path)),
|
|
288
|
+
),
|
|
289
|
+
parse,
|
|
623
290
|
);
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
answers,
|
|
627
|
-
consumers: {
|
|
628
|
-
loaded: loads.map((load) => load.consumer),
|
|
291
|
+
return {
|
|
292
|
+
answers,
|
|
629
293
|
references: [...consumed.values()],
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
conventionsApplied: conventions.applied,
|
|
636
|
-
conventionUses: conventions.uses,
|
|
637
|
-
memberDirs,
|
|
638
|
-
nestedDirs,
|
|
639
|
-
outsideTests,
|
|
640
|
-
};
|
|
294
|
+
consumerHeld: [...consumerHeld],
|
|
295
|
+
outsideTests,
|
|
296
|
+
workflows,
|
|
297
|
+
};
|
|
298
|
+
});
|
|
641
299
|
}
|
|
642
300
|
|
|
643
301
|
/** The projects one run analyzes, and what reading them left out. */
|
|
@@ -655,7 +313,12 @@ interface RunProjects {
|
|
|
655
313
|
* for the errors and setup failures that decide whether it is analyzed, dropped or
|
|
656
314
|
* fails the run, exactly as the analysis reads them.
|
|
657
315
|
*/
|
|
658
|
-
export function runProjects(
|
|
316
|
+
export function runProjects(
|
|
317
|
+
engine: Engine,
|
|
318
|
+
host: Host,
|
|
319
|
+
scope: Scope,
|
|
320
|
+
config: PartialConfig,
|
|
321
|
+
): RunProjects {
|
|
659
322
|
const read = readProjects(
|
|
660
323
|
engine,
|
|
661
324
|
host,
|
|
@@ -663,7 +326,11 @@ export function runProjects(engine: Engine, host: Host, scope: Scope, config: Co
|
|
|
663
326
|
config,
|
|
664
327
|
(_project, opened) => opened.configuration,
|
|
665
328
|
);
|
|
666
|
-
return {
|
|
329
|
+
return {
|
|
330
|
+
configurations: read.result.answers,
|
|
331
|
+
notBuilt: read.classified.notBuilt,
|
|
332
|
+
unanswered: read.unanswered,
|
|
333
|
+
};
|
|
667
334
|
}
|
|
668
335
|
|
|
669
336
|
/**
|
|
@@ -676,12 +343,12 @@ export function runRoots(
|
|
|
676
343
|
engine: Engine,
|
|
677
344
|
host: Host,
|
|
678
345
|
scope: Scope,
|
|
679
|
-
config:
|
|
346
|
+
config: ResolvedConfig,
|
|
680
347
|
provenance: Provenance,
|
|
681
348
|
): RunRoots {
|
|
682
349
|
const targetRoot = scope.target.path;
|
|
683
350
|
const read = readProjects(engine, host, scope, config, (_project, opened) => opened.read());
|
|
684
|
-
const projects = read.answers;
|
|
351
|
+
const projects = read.result.answers;
|
|
685
352
|
|
|
686
353
|
const configurations: string[] = [];
|
|
687
354
|
const merged = new Map<string, Omit<RunRoot, "configurations"> & { configurations: string[] }>();
|
|
@@ -712,10 +379,12 @@ export function runRoots(
|
|
|
712
379
|
|
|
713
380
|
const ordered = [...merged.values()].sort(
|
|
714
381
|
(a, b) =>
|
|
715
|
-
byPosition(a.position, b.position) ||
|
|
382
|
+
byPosition(a.position, b.position) ||
|
|
383
|
+
bytewise(a.kind, b.kind) ||
|
|
384
|
+
bytewise(a.source, b.source),
|
|
716
385
|
);
|
|
717
386
|
const unmatched = unmatchedEverywhere(
|
|
718
|
-
config.
|
|
387
|
+
config.roots.patterns,
|
|
719
388
|
projects.map((answer) => answer.rooted),
|
|
720
389
|
);
|
|
721
390
|
return {
|
|
@@ -725,58 +394,39 @@ export function runRoots(
|
|
|
725
394
|
unmatched,
|
|
726
395
|
documentOf(host, provenance, ROOTS_SETTING, targetRoot),
|
|
727
396
|
),
|
|
728
|
-
notBuilt: read.notBuilt,
|
|
397
|
+
notBuilt: read.classified.notBuilt,
|
|
729
398
|
unanswered: read.unanswered,
|
|
730
399
|
};
|
|
731
400
|
}
|
|
732
401
|
|
|
402
|
+
/** The production mode a configuration sets: a consumer's test reference is classed as `analysis.consumer_tests` says. */
|
|
403
|
+
export function productionMode(config: PartialConfig): Mode {
|
|
404
|
+
return {
|
|
405
|
+
production: true,
|
|
406
|
+
consumerTestsProduction: config.analysis.consumer_tests === "production",
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
733
410
|
/** The run's sweep, beside the matrix it judged. */
|
|
734
411
|
export interface RunSweep {
|
|
735
412
|
readonly matrix: Matrix;
|
|
736
|
-
readonly sweep:
|
|
737
|
-
/** The exemption records that hold under the sweep. */
|
|
738
|
-
readonly exempt: readonly Exemption[];
|
|
739
|
-
/**
|
|
740
|
-
* The exemption records that held back a declaration some configuration of the run
|
|
741
|
-
* would otherwise judge dead, in the declarations' site order.
|
|
742
|
-
*/
|
|
743
|
-
readonly retained: readonly Exemption[];
|
|
413
|
+
readonly sweep: Sweep;
|
|
744
414
|
/** The derived configurations the run dropped. */
|
|
745
415
|
readonly notBuilt: readonly NotBuilt[];
|
|
746
416
|
/** Every question the checker could not answer, each once. */
|
|
747
417
|
readonly unanswered: readonly UnansweredQuestion[];
|
|
748
|
-
/**
|
|
749
|
-
* Every declaration an unanswered question could have kept live, and every one only
|
|
750
|
-
* such a declaration keeps live. The run reports none of them.
|
|
751
|
-
*/
|
|
752
|
-
readonly heldByUnanswered: readonly string[];
|
|
753
418
|
/** The lines of the units type errors skipped, on which the run reports nothing. */
|
|
754
419
|
readonly skipped: readonly SkippedUnit[];
|
|
755
|
-
/** The component files the run read, by path below the target root, each once. */
|
|
756
|
-
readonly componentFiles: readonly string[];
|
|
757
420
|
}
|
|
758
421
|
|
|
759
422
|
/** One `<script` start tag of a component file the run read no block for. */
|
|
760
|
-
|
|
423
|
+
interface ComponentWarning {
|
|
761
424
|
/** The file, below the target root. */
|
|
762
425
|
readonly path: string;
|
|
763
426
|
readonly line: number;
|
|
764
427
|
readonly reason: string;
|
|
765
428
|
}
|
|
766
429
|
|
|
767
|
-
/** The exemption classes this analyzer detects, each by its detector; any other retains nothing. */
|
|
768
|
-
export const DETECTORS: Detectors = new Map<TSExemptionClass, Detector>([
|
|
769
|
-
["interface-satisfaction", interfaceSatisfaction],
|
|
770
|
-
["enum-group", enumGroup],
|
|
771
|
-
["generated-file", generatedFile],
|
|
772
|
-
["template-field", templateField],
|
|
773
|
-
["reflective-lookup", reflectiveLookup],
|
|
774
|
-
["decorator", decorator],
|
|
775
|
-
["injection-container", injectionContainer],
|
|
776
|
-
["framework-lifecycle", frameworkLifecycle],
|
|
777
|
-
["serialization-contract", serializationContract],
|
|
778
|
-
]);
|
|
779
|
-
|
|
780
430
|
/** What the sweep of one run reads of each project, beside what a caller's stage adds. */
|
|
781
431
|
interface SweptProject<Extra> {
|
|
782
432
|
readonly configFile: string;
|
|
@@ -784,6 +434,10 @@ interface SweptProject<Extra> {
|
|
|
784
434
|
readonly exempt: readonly Exemption[];
|
|
785
435
|
/** The declarations of the project an unanswered question could have kept live. */
|
|
786
436
|
readonly unanswered: readonly string[];
|
|
437
|
+
/** The data members a generic declared outside the analysis fills, which it may read. */
|
|
438
|
+
readonly filledOutside: readonly string[];
|
|
439
|
+
/** What only a bundler's retry of an import Node leaves unresolved names (program.38). */
|
|
440
|
+
readonly possiblyLoaded: readonly string[];
|
|
787
441
|
readonly typeErrorSkips: readonly TypeErrorSkip[];
|
|
788
442
|
readonly skipped: readonly SkippedUnit[];
|
|
789
443
|
/** The component files the project holds of its own, by path below the target root. */
|
|
@@ -791,6 +445,7 @@ interface SweptProject<Extra> {
|
|
|
791
445
|
readonly componentWarnings: readonly ComponentWarning[];
|
|
792
446
|
/** The manifest entries the project reads back to no file of its own. */
|
|
793
447
|
readonly unmappedEntries: readonly ManifestEntry[];
|
|
448
|
+
readonly heldScripts: readonly HeldScripts[];
|
|
794
449
|
readonly extra: Extra;
|
|
795
450
|
}
|
|
796
451
|
|
|
@@ -798,12 +453,17 @@ interface SweptProject<Extra> {
|
|
|
798
453
|
interface ReadProject<Extra> {
|
|
799
454
|
readonly projectRead: ProjectRead;
|
|
800
455
|
readonly references: readonly Reference[];
|
|
456
|
+
/** The declarations its read rules held where the checker did not answer. */
|
|
457
|
+
readonly held: readonly string[];
|
|
458
|
+
readonly possiblyLoaded: readonly string[];
|
|
801
459
|
readonly testFiles: readonly string[];
|
|
802
460
|
readonly evidence: readonly Exemption[];
|
|
803
461
|
readonly componentFiles: readonly string[];
|
|
804
462
|
readonly componentWarnings: readonly ComponentWarning[];
|
|
805
463
|
/** Per own file below the target root, the module specifiers its imports write. */
|
|
806
464
|
readonly imports: ReadonlyMap<string, readonly string[]>;
|
|
465
|
+
/** The data members its production code decodes into. */
|
|
466
|
+
readonly decoded: Decoded;
|
|
807
467
|
readonly extra: Extra;
|
|
808
468
|
}
|
|
809
469
|
|
|
@@ -816,6 +476,8 @@ interface ReadRun<Extra> {
|
|
|
816
476
|
readonly projects: readonly SweptProject<Extra>[];
|
|
817
477
|
/** Every declared consumer, each loaded, in the scope's order. */
|
|
818
478
|
readonly consumers: readonly LoadedConsumer[];
|
|
479
|
+
/** Whether the scope declares a consumer, loaded or not. */
|
|
480
|
+
readonly declaresConsumers: boolean;
|
|
819
481
|
/** The derived configurations the run dropped. */
|
|
820
482
|
readonly notBuilt: readonly NotBuilt[];
|
|
821
483
|
/** Every question the checker could not answer, each once. */
|
|
@@ -824,6 +486,10 @@ interface ReadRun<Extra> {
|
|
|
824
486
|
readonly componentsUnread: readonly ComponentsUnread[];
|
|
825
487
|
/** Per analyzed configuration, each library it names that the compiler cannot find. */
|
|
826
488
|
readonly librariesUnfound: readonly LibraryUnfound[];
|
|
489
|
+
/** The relative specifiers of the run's unchecked JavaScript files that resolve to no file. */
|
|
490
|
+
readonly unresolvedSpecifiers: readonly UnresolvedSpecifier[];
|
|
491
|
+
/** The inputs the run could not read. */
|
|
492
|
+
readonly unread: readonly UnreadInput[];
|
|
827
493
|
/** The convention rows the run applied. */
|
|
828
494
|
readonly conventionsApplied: readonly AppliedConvention[];
|
|
829
495
|
/** The dependencies the applied rows' short names use. */
|
|
@@ -832,6 +498,8 @@ interface ReadRun<Extra> {
|
|
|
832
498
|
readonly memberDirs: readonly string[];
|
|
833
499
|
/** The directory of every nested package, absolute. */
|
|
834
500
|
readonly nestedDirs: readonly string[];
|
|
501
|
+
/** The target root's workflow steps, git hooks and makefile, read once. */
|
|
502
|
+
readonly workflows: Workflows;
|
|
835
503
|
}
|
|
836
504
|
|
|
837
505
|
/** The manifest section of a package test evidence counts, and the sections that keep one out of it. */
|
|
@@ -855,20 +523,9 @@ function testEvidence(
|
|
|
855
523
|
}
|
|
856
524
|
}
|
|
857
525
|
const manifests = new Map<string, Readonly<Record<string, unknown>> | undefined>();
|
|
858
|
-
const
|
|
526
|
+
const manifestIn = (dir: string): Readonly<Record<string, unknown>> | undefined => {
|
|
859
527
|
if (!manifests.has(dir)) {
|
|
860
|
-
|
|
861
|
-
try {
|
|
862
|
-
value = JSON.parse(host.readFile(joinPath(dir, "package.json")));
|
|
863
|
-
} catch {
|
|
864
|
-
value = undefined;
|
|
865
|
-
}
|
|
866
|
-
manifests.set(
|
|
867
|
-
dir,
|
|
868
|
-
typeof value === "object" && value !== null && !Array.isArray(value)
|
|
869
|
-
? (value as Record<string, unknown>)
|
|
870
|
-
: undefined,
|
|
871
|
-
);
|
|
528
|
+
manifests.set(dir, manifestAt(host, dir));
|
|
872
529
|
}
|
|
873
530
|
return manifests.get(dir);
|
|
874
531
|
};
|
|
@@ -878,16 +535,14 @@ function testEvidence(
|
|
|
878
535
|
return {
|
|
879
536
|
imports,
|
|
880
537
|
devDependency: (path, name) => {
|
|
881
|
-
for (
|
|
882
|
-
const manifest =
|
|
538
|
+
for (const dir of ancestors(dirnamePath(joinPath(root, path)), root)) {
|
|
539
|
+
const manifest = manifestIn(dir);
|
|
883
540
|
const other = OTHER_SECTIONS.some((one) => declares(manifest?.[one], name));
|
|
884
541
|
if (declares(manifest?.[DEV_SECTION], name) || other) {
|
|
885
542
|
return !other;
|
|
886
543
|
}
|
|
887
|
-
if (normalizePath(dir) === normalizePath(root) || dirnamePath(dir) === dir) {
|
|
888
|
-
return false;
|
|
889
|
-
}
|
|
890
544
|
}
|
|
545
|
+
return false;
|
|
891
546
|
},
|
|
892
547
|
};
|
|
893
548
|
}
|
|
@@ -902,7 +557,7 @@ function readRun<Extra>(
|
|
|
902
557
|
engine: Engine,
|
|
903
558
|
host: Host,
|
|
904
559
|
scope: Scope,
|
|
905
|
-
config:
|
|
560
|
+
config: ResolvedConfig,
|
|
906
561
|
mode: Mode,
|
|
907
562
|
detectors: Detectors,
|
|
908
563
|
extra: <Brand>(
|
|
@@ -910,50 +565,55 @@ function readRun<Extra>(
|
|
|
910
565
|
read: ProjectRead,
|
|
911
566
|
references: readonly Reference[],
|
|
912
567
|
testFiles: readonly string[],
|
|
568
|
+
unseenLoads: readonly UnseenLoad[],
|
|
913
569
|
) => Extra,
|
|
914
570
|
): ReadRun<Extra> {
|
|
915
571
|
const targetRoot = scope.target.path;
|
|
916
|
-
const disabled = disabledClasses(config);
|
|
917
|
-
const templates = disabled.has("template-field")
|
|
918
|
-
? { delimiters: config.analysis.templateDelimiters, files: [] }
|
|
919
|
-
: readTemplates(host, targetRoot, config.analysis);
|
|
920
572
|
const consumers = scope.consumers.map((consumer) => consumer.path);
|
|
573
|
+
const detect = detection(host, targetRoot, config, consumers, detectors);
|
|
574
|
+
const directories = runDirectories(host, targetRoot, (fileName, text) =>
|
|
575
|
+
engine.parseSourceFile(fileName, text),
|
|
576
|
+
);
|
|
921
577
|
const read = readProjects<ReadProject<Extra>>(engine, host, scope, config, (project, opened) => {
|
|
922
578
|
const projectRead = opened.read();
|
|
579
|
+
const testFile = targetTestFile(projectRead.sources.testFiles);
|
|
923
580
|
const resolved = references(project, projectRead.held, targetRoot, {
|
|
924
|
-
|
|
925
|
-
|
|
581
|
+
testFile,
|
|
582
|
+
directories,
|
|
583
|
+
formedForNode: projectRead.formedForNode,
|
|
926
584
|
});
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
project,
|
|
930
|
-
held: projectRead.held,
|
|
931
|
-
targetRoot,
|
|
932
|
-
templates,
|
|
933
|
-
ts: config.ts,
|
|
934
|
-
consumers,
|
|
935
|
-
...(config.analysis.generatedFiles === "include"
|
|
936
|
-
? {}
|
|
937
|
-
: { generated: projectRead.generated }),
|
|
938
|
-
},
|
|
939
|
-
detectors,
|
|
940
|
-
disabled,
|
|
941
|
-
);
|
|
585
|
+
const testFiles = testFilePaths(project, targetRoot, testFile);
|
|
586
|
+
const evidence = detect({ project, held: projectRead.held, generated: projectRead.generated });
|
|
942
587
|
const components = project.ownSourceFiles().filter(isComponentFile);
|
|
588
|
+
const injected = project.program
|
|
589
|
+
.getSourceFileNames()
|
|
590
|
+
.some((name) => name.endsWith(`/node_modules/${GLOBALS_RUNNER}/globals.d.ts`));
|
|
943
591
|
const pathOf = (file: (typeof components)[number]): string =>
|
|
944
592
|
relativePath(targetRoot, file.fileName) ?? file.fileName;
|
|
945
593
|
return {
|
|
946
594
|
projectRead,
|
|
947
595
|
references: resolved.references,
|
|
948
|
-
|
|
596
|
+
held: resolved.held,
|
|
597
|
+
possiblyLoaded: resolved.possiblyLoaded,
|
|
598
|
+
testFiles,
|
|
949
599
|
evidence,
|
|
950
600
|
componentFiles: components.map(pathOf),
|
|
951
601
|
imports: new Map(
|
|
952
602
|
project.ownSourceFiles().flatMap((file) => {
|
|
953
603
|
const path = relativePath(targetRoot, file.fileName);
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
604
|
+
if (path === undefined) {
|
|
605
|
+
return [];
|
|
606
|
+
}
|
|
607
|
+
const specifiers = file.imports.filter(isStringLiteralLikeNode).map((one) => one.text);
|
|
608
|
+
// A file calling the globals a program declares is written for their runner.
|
|
609
|
+
return [
|
|
610
|
+
[
|
|
611
|
+
path,
|
|
612
|
+
injected && namesTestGlobals(project, file)
|
|
613
|
+
? [...specifiers, GLOBALS_RUNNER]
|
|
614
|
+
: specifiers,
|
|
615
|
+
],
|
|
616
|
+
];
|
|
957
617
|
}),
|
|
958
618
|
),
|
|
959
619
|
componentWarnings: components.flatMap((file) =>
|
|
@@ -963,15 +623,30 @@ function readRun<Extra>(
|
|
|
963
623
|
reason: warning.reason,
|
|
964
624
|
})),
|
|
965
625
|
),
|
|
966
|
-
|
|
626
|
+
decoded: decodedMembers(
|
|
627
|
+
project,
|
|
628
|
+
projectRead.held,
|
|
629
|
+
productionFiles(project, targetRoot, testFiles),
|
|
630
|
+
consumers,
|
|
631
|
+
),
|
|
632
|
+
extra: extra(
|
|
633
|
+
project,
|
|
634
|
+
projectRead,
|
|
635
|
+
resolved.references,
|
|
636
|
+
testFiles,
|
|
637
|
+
resolved.unseenLoads.map((position) => ({
|
|
638
|
+
configuration: projectRead.configuration,
|
|
639
|
+
position,
|
|
640
|
+
})),
|
|
641
|
+
),
|
|
967
642
|
};
|
|
968
643
|
});
|
|
969
|
-
const outsidePaths = read.outsideTests.map((one) => one.path);
|
|
970
|
-
const withOutside = read.answers.map((one) => ({
|
|
644
|
+
const outsidePaths = read.result.outsideTests.map((one) => one.path);
|
|
645
|
+
const withOutside = read.result.answers.map((one) => ({
|
|
971
646
|
...one,
|
|
972
647
|
references: [
|
|
973
648
|
...one.references,
|
|
974
|
-
...outsideTestReferences(read.outsideTests, one.projectRead.held, targetRoot),
|
|
649
|
+
...outsideTestReferences(read.result.outsideTests, one.projectRead.held, targetRoot),
|
|
975
650
|
],
|
|
976
651
|
testFiles: [...one.testFiles, ...outsidePaths],
|
|
977
652
|
}));
|
|
@@ -980,30 +655,51 @@ function readRun<Extra>(
|
|
|
980
655
|
const { support, testUsed } = testSupportFiles(
|
|
981
656
|
withOutside.flatMap((one) => one.projectRead.held.symbols),
|
|
982
657
|
withOutside.flatMap((one) => one.references),
|
|
983
|
-
|
|
658
|
+
// An outside declaration naming a global augmentation calls nothing of its file.
|
|
659
|
+
withOutside.flatMap((one) =>
|
|
660
|
+
one.projectRead.rooted.liveUnderReachability.filter(
|
|
661
|
+
(root) => root.kind !== "global-augmentation",
|
|
662
|
+
),
|
|
663
|
+
),
|
|
984
664
|
withOutside.flatMap((one) => one.testFiles),
|
|
985
665
|
testEvidence(host, targetRoot, withOutside),
|
|
986
666
|
);
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
667
|
+
// A member a decode fills or a copy carries is written: a value decoded and sent again carries it on.
|
|
668
|
+
const written = new Set([
|
|
669
|
+
...countedWrites(
|
|
670
|
+
[...withOutside.flatMap((one) => one.references), ...read.result.references],
|
|
671
|
+
support,
|
|
672
|
+
mode,
|
|
673
|
+
),
|
|
674
|
+
...withOutside.flatMap((one) => [
|
|
675
|
+
...one.decoded.filled,
|
|
676
|
+
...one.decoded.parsed,
|
|
677
|
+
...one.decoded.copied,
|
|
678
|
+
]),
|
|
679
|
+
]);
|
|
680
|
+
const settled = settle(
|
|
681
|
+
withOutside.map((one) => ({
|
|
682
|
+
records: one.evidence,
|
|
683
|
+
held: one.projectRead.held,
|
|
684
|
+
testFiles: new Set([...one.testFiles, ...support]),
|
|
685
|
+
})),
|
|
686
|
+
{
|
|
687
|
+
references: [...withOutside.flatMap((one) => one.references), ...read.result.references],
|
|
688
|
+
written,
|
|
689
|
+
mode,
|
|
690
|
+
},
|
|
990
691
|
);
|
|
991
692
|
const answers = withOutside.map((one, index): SweptProject<Extra> => {
|
|
992
693
|
const { projectRead } = one;
|
|
993
|
-
const
|
|
994
|
-
const
|
|
995
|
-
mode,
|
|
996
|
-
testFiles: new Set([...one.testFiles, ...support]),
|
|
997
|
-
});
|
|
998
|
-
const exempt = detected.records;
|
|
999
|
-
const made = supportReferences([...one.references, ...(satisfied?.references ?? [])], support);
|
|
694
|
+
const exempt = settled[index]?.records ?? [];
|
|
695
|
+
const made = [...one.references, ...(settled[index]?.references ?? [])];
|
|
1000
696
|
const held = new Set(projectRead.held.symbols.map((symbol) => symbol.position.path));
|
|
1001
|
-
const supportFiles = [...support].filter((path) => held.has(path)).sort();
|
|
1002
|
-
const testUsedFiles = [...testUsed].filter((path) => held.has(path)).sort();
|
|
697
|
+
const supportFiles = [...support].filter((path) => held.has(path)).sort(bytewise);
|
|
698
|
+
const testUsedFiles = [...testUsed].filter((path) => held.has(path)).sort(bytewise);
|
|
1003
699
|
const configured: Configured = {
|
|
1004
700
|
configuration: projectRead.configuration,
|
|
1005
701
|
symbols: projectRead.held.symbols,
|
|
1006
|
-
references:
|
|
702
|
+
references: made,
|
|
1007
703
|
roots: projectRead.rooted.liveUnderReachability,
|
|
1008
704
|
testFiles: [...one.testFiles, ...supportFiles],
|
|
1009
705
|
...(supportFiles.length === 0 ? {} : { supportFiles }),
|
|
@@ -1023,20 +719,23 @@ function readRun<Extra>(
|
|
|
1023
719
|
unanswered: [
|
|
1024
720
|
...projectRead.held.unanswered,
|
|
1025
721
|
...projectRead.rooted.unanswered,
|
|
1026
|
-
...made
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
...
|
|
722
|
+
...made.filter((reference) => reference.guessed === true).map((reference) => reference.to),
|
|
723
|
+
...one.held,
|
|
724
|
+
...exempt.filter((record) => record.unanswered === true).map((record) => record.id),
|
|
725
|
+
...one.decoded.unanswered,
|
|
1030
726
|
],
|
|
727
|
+
filledOutside: one.decoded.filled,
|
|
728
|
+
possiblyLoaded: one.possiblyLoaded,
|
|
1031
729
|
typeErrorSkips: projectRead.typeErrorSkips,
|
|
1032
730
|
unmappedEntries: projectRead.rooted.unmappedEntries,
|
|
731
|
+
heldScripts: projectRead.rooted.heldScripts,
|
|
1033
732
|
skipped: projectRead.skipped,
|
|
1034
733
|
componentFiles: one.componentFiles,
|
|
1035
734
|
componentWarnings: one.componentWarnings,
|
|
1036
735
|
extra: one.extra,
|
|
1037
736
|
};
|
|
1038
737
|
});
|
|
1039
|
-
const consumed = read.
|
|
738
|
+
const consumed = read.result.references;
|
|
1040
739
|
const projects = answers.map((one) =>
|
|
1041
740
|
consumed.length === 0
|
|
1042
741
|
? one
|
|
@@ -1054,80 +753,41 @@ function readRun<Extra>(
|
|
|
1054
753
|
unansweredHeld: [
|
|
1055
754
|
...new Set([
|
|
1056
755
|
...answers.flatMap((one) => one.unanswered),
|
|
1057
|
-
...consumed.filter((one) => one.
|
|
756
|
+
...consumed.filter((one) => one.guessed === true).map((one) => one.to),
|
|
757
|
+
...read.result.consumerHeld,
|
|
1058
758
|
]),
|
|
1059
759
|
],
|
|
1060
760
|
projects,
|
|
1061
|
-
consumers: read.consumers
|
|
1062
|
-
|
|
761
|
+
consumers: read.plan.discovery.consumers,
|
|
762
|
+
declaresConsumers: scope.consumers.length > 0,
|
|
763
|
+
notBuilt: read.classified.notBuilt,
|
|
1063
764
|
unanswered: read.unanswered,
|
|
1064
|
-
componentsUnread: read.componentsUnread,
|
|
1065
|
-
librariesUnfound: read.librariesUnfound,
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
765
|
+
componentsUnread: read.plan.workspace?.componentsUnread ?? [],
|
|
766
|
+
librariesUnfound: read.classified.librariesUnfound,
|
|
767
|
+
unresolvedSpecifiers: read.classified.unresolvedSpecifiers,
|
|
768
|
+
unread: read.plan.unread,
|
|
769
|
+
conventionsApplied: read.plan.conventions.applied,
|
|
770
|
+
conventionUses: read.plan.conventions.uses,
|
|
771
|
+
memberDirs: read.plan.packages.members,
|
|
772
|
+
nestedDirs: read.plan.packages.nested,
|
|
773
|
+
workflows: read.result.workflows,
|
|
1070
774
|
};
|
|
1071
775
|
}
|
|
1072
776
|
|
|
1073
777
|
/**
|
|
1074
|
-
* The
|
|
1075
|
-
*
|
|
1076
|
-
* keeps the file live, so each file's markup joins only once a sweep without it finds the
|
|
1077
|
-
* file live, until a sweep finds no further file live.
|
|
1078
|
-
*/
|
|
1079
|
-
function holdingSweep<Extra>(
|
|
1080
|
-
read: ReadRun<Extra>,
|
|
1081
|
-
input: Pick<SweepInput, "marked" | "mode">,
|
|
1082
|
-
): { readonly swept: SweepInput; readonly result: SweepResult } {
|
|
1083
|
-
const paths = new Set(read.exempt.flatMap((record) => record.whileLive ?? []));
|
|
1084
|
-
let live = new Set<string>();
|
|
1085
|
-
for (;;) {
|
|
1086
|
-
const swept: SweepInput = {
|
|
1087
|
-
...input,
|
|
1088
|
-
exempt: holdingWhile(read.exempt, live),
|
|
1089
|
-
unanswered: read.unansweredHeld,
|
|
1090
|
-
};
|
|
1091
|
-
const result = sweepMatrix(read.matrix, swept);
|
|
1092
|
-
const next = new Set(liveFilesAt(read.matrix, result, paths).map((one) => one.position.path));
|
|
1093
|
-
if (next.size === live.size) {
|
|
1094
|
-
return { swept, result };
|
|
1095
|
-
}
|
|
1096
|
-
live = next;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
/**
|
|
1101
|
-
* The test references exemption evidence written in a test file makes: each is a read of
|
|
1102
|
-
* the declaration it would retain, made by the test file at the evidence's site.
|
|
778
|
+
* The declarations a write the mode counts stores into, a write a test-support file
|
|
779
|
+
* makes being a test's.
|
|
1103
780
|
*/
|
|
1104
|
-
function
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
.filter((symbol) => symbol.kind === "file")
|
|
1114
|
-
.map((symbol) => [symbol.position.path, symbol.id]),
|
|
781
|
+
function countedWrites(
|
|
782
|
+
references: readonly Reference[],
|
|
783
|
+
support: ReadonlySet<string>,
|
|
784
|
+
mode: Mode,
|
|
785
|
+
): ReadonlySet<string> {
|
|
786
|
+
return new Set(
|
|
787
|
+
references.flatMap((reference) =>
|
|
788
|
+
reference.use === "write" && !withheldBy(mode, reference, support) ? [reference.to] : [],
|
|
789
|
+
),
|
|
1115
790
|
);
|
|
1116
|
-
return inTestFiles.flatMap((record) => {
|
|
1117
|
-
const from = files.get(record.site.path);
|
|
1118
|
-
return from === undefined
|
|
1119
|
-
? []
|
|
1120
|
-
: [
|
|
1121
|
-
{
|
|
1122
|
-
from,
|
|
1123
|
-
to: record.id,
|
|
1124
|
-
position: record.site,
|
|
1125
|
-
use: "read",
|
|
1126
|
-
resolution: "syntax",
|
|
1127
|
-
test: true,
|
|
1128
|
-
},
|
|
1129
|
-
];
|
|
1130
|
-
});
|
|
1131
791
|
}
|
|
1132
792
|
|
|
1133
793
|
/**
|
|
@@ -1138,8 +798,9 @@ function writtenOnly<Extra>(read: ReadRun<Extra>, mode: Mode): ReadonlySet<strin
|
|
|
1138
798
|
const written = new Set<string>();
|
|
1139
799
|
const readSome = new Set<string>();
|
|
1140
800
|
for (const { configured } of read.projects) {
|
|
801
|
+
const support = new Set(configured.supportFiles ?? []);
|
|
1141
802
|
for (const reference of configured.references) {
|
|
1142
|
-
if (mode
|
|
803
|
+
if (withheldBy(mode, reference, support)) {
|
|
1143
804
|
continue;
|
|
1144
805
|
}
|
|
1145
806
|
if (reference.use === "write" && reference.consumer === undefined) {
|
|
@@ -1152,62 +813,27 @@ function writtenOnly<Extra>(read: ReadRun<Extra>, mode: Mode): ReadonlySet<strin
|
|
|
1152
813
|
return new Set([...written].filter((id) => !readSome.has(id)));
|
|
1153
814
|
}
|
|
1154
815
|
|
|
1155
|
-
/**
|
|
1156
|
-
* The sweep of a run read once, under one set of marks. Where a question went unanswered,
|
|
1157
|
-
* the run is swept once more without what that question could have kept live and without
|
|
1158
|
-
* the references that stood in for its answer, and every declaration that sweep judges
|
|
1159
|
-
* dead and this one judges live, or dead by another rule, is held by the gap too, as is
|
|
1160
|
-
* every declaration that makes such a reference.
|
|
1161
|
-
*/
|
|
816
|
+
/** The sweep of a run read once, under one set of marks. */
|
|
1162
817
|
function sweptOf<Extra>(
|
|
1163
818
|
read: ReadRun<Extra>,
|
|
1164
|
-
input: Pick<
|
|
819
|
+
input: Pick<SweepPolicy, "marked" | "mode">,
|
|
1165
820
|
): RunSweep {
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
if (held.size > 0) {
|
|
1170
|
-
// What a declaration reads where the checker did not answer is unknown, so a rule
|
|
1171
|
-
// over what it reads, the test of dead code among them, cannot judge it.
|
|
1172
|
-
for (const { configured } of read.projects) {
|
|
1173
|
-
for (const reference of configured.references) {
|
|
1174
|
-
if (reference.resolution === "by-name") {
|
|
1175
|
-
held.add(reference.from);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
const dead = new Map(result.candidates.map((candidate) => [candidate.id, candidate]));
|
|
1180
|
-
const answered = matrixOf(
|
|
1181
|
-
read.projects.map(({ configured }) => ({
|
|
1182
|
-
...configured,
|
|
1183
|
-
references: configured.references.filter((one) => one.resolution !== "by-name"),
|
|
1184
|
-
})),
|
|
1185
|
-
);
|
|
1186
|
-
const bare: SweepInput = {
|
|
1187
|
-
...swept,
|
|
1188
|
-
exempt: exempt.filter((record) => !isUnansweredRecord(record)),
|
|
1189
|
-
unanswered: [],
|
|
1190
|
-
};
|
|
1191
|
-
for (const candidate of sweepMatrix(answered, bare).candidates) {
|
|
1192
|
-
const kept = dead.get(candidate.id);
|
|
1193
|
-
if (
|
|
1194
|
-
kept?.testOfDeadCode !== candidate.testOfDeadCode ||
|
|
1195
|
-
kept.relation !== candidate.relation
|
|
1196
|
-
) {
|
|
1197
|
-
held.add(candidate.id);
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
821
|
+
const componentFiles = [...new Set(read.projects.flatMap((one) => one.componentFiles))].sort(
|
|
822
|
+
bytewise,
|
|
823
|
+
);
|
|
1201
824
|
return {
|
|
1202
825
|
matrix: read.matrix,
|
|
1203
|
-
sweep:
|
|
1204
|
-
|
|
1205
|
-
|
|
826
|
+
sweep: sweep(read.matrix, {
|
|
827
|
+
...input,
|
|
828
|
+
exempt: read.exempt,
|
|
829
|
+
unanswered: read.unansweredHeld,
|
|
830
|
+
componentFiles,
|
|
831
|
+
unseenCallers: !read.declaresConsumers,
|
|
832
|
+
writeOnly: writtenOnly(read, input.mode),
|
|
833
|
+
}),
|
|
1206
834
|
notBuilt: read.notBuilt,
|
|
1207
835
|
unanswered: read.unanswered,
|
|
1208
|
-
heldByUnanswered: [...held],
|
|
1209
836
|
skipped: read.projects.flatMap((one) => one.skipped),
|
|
1210
|
-
componentFiles: [...new Set(read.projects.flatMap((one) => one.componentFiles))].sort(compare),
|
|
1211
837
|
};
|
|
1212
838
|
}
|
|
1213
839
|
|
|
@@ -1223,8 +849,8 @@ export function runSweep(
|
|
|
1223
849
|
engine: Engine,
|
|
1224
850
|
host: Host,
|
|
1225
851
|
scope: Scope,
|
|
1226
|
-
config:
|
|
1227
|
-
input: Pick<
|
|
852
|
+
config: ResolvedConfig,
|
|
853
|
+
input: Pick<SweepPolicy, "marked" | "mode">,
|
|
1228
854
|
detectors: Detectors = DETECTORS,
|
|
1229
855
|
): RunSweep {
|
|
1230
856
|
return sweptOf(
|
|
@@ -1240,12 +866,27 @@ interface EmitterExtra {
|
|
|
1240
866
|
readonly needs: ReturnType<typeof projectNeeds>;
|
|
1241
867
|
readonly implementations: ReturnType<typeof implementations>;
|
|
1242
868
|
readonly heldByInclusion: readonly string[];
|
|
1243
|
-
readonly generated:
|
|
869
|
+
readonly generated: ReadonlyMap<string, GeneratedFact>;
|
|
870
|
+
readonly bindings: readonly BindingRecord[];
|
|
1244
871
|
readonly inOperands: readonly string[];
|
|
1245
872
|
readonly rooted: Roots;
|
|
1246
873
|
readonly directives: readonly InlineDirective[];
|
|
1247
874
|
readonly declarationsNamed: readonly boolean[];
|
|
1248
875
|
readonly parts: ProjectParts;
|
|
876
|
+
readonly unseenLoads: readonly UnseenLoad[];
|
|
877
|
+
readonly carriers: Carriers;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/** The project's own files below the target root that are no test file. */
|
|
881
|
+
function productionFiles<Brand>(
|
|
882
|
+
project: ProjectView<Brand>,
|
|
883
|
+
targetRoot: string,
|
|
884
|
+
testFiles: readonly string[],
|
|
885
|
+
): readonly SourceFile[] {
|
|
886
|
+
const tests = new Set(testFiles);
|
|
887
|
+
return [...sourceFilesOf(project, targetRoot).byPath].flatMap(([path, file]) =>
|
|
888
|
+
tests.has(path) ? [] : [file],
|
|
889
|
+
);
|
|
1249
890
|
}
|
|
1250
891
|
|
|
1251
892
|
/** Reads a run's projects with every per-project fact an emitter reads. */
|
|
@@ -1253,7 +894,7 @@ export function readEmitterRun(
|
|
|
1253
894
|
engine: Engine,
|
|
1254
895
|
host: Host,
|
|
1255
896
|
scope: Scope,
|
|
1256
|
-
config:
|
|
897
|
+
config: ResolvedConfig,
|
|
1257
898
|
mode: Mode,
|
|
1258
899
|
detectors: Detectors,
|
|
1259
900
|
): ReadRun<EmitterExtra> {
|
|
@@ -1265,15 +906,22 @@ export function readEmitterRun(
|
|
|
1265
906
|
config,
|
|
1266
907
|
mode,
|
|
1267
908
|
detectors,
|
|
1268
|
-
(project, read, references, testFiles) => ({
|
|
909
|
+
(project, read, references, testFiles, unseenLoads) => ({
|
|
1269
910
|
deprecation: deprecatedDeclarations(project, read.held),
|
|
1270
911
|
accessors: accessorsOf(project, read.held),
|
|
1271
|
-
needs: projectNeeds(
|
|
1272
|
-
|
|
912
|
+
needs: projectNeeds(
|
|
913
|
+
project,
|
|
914
|
+
read.held,
|
|
915
|
+
host,
|
|
916
|
+
targetRoot,
|
|
917
|
+
(fileName, text) => engine.parseSourceFile(fileName, text),
|
|
918
|
+
read.sources.configuration,
|
|
919
|
+
read.sources.workflows,
|
|
1273
920
|
),
|
|
1274
921
|
implementations: implementations(project, read.held),
|
|
1275
922
|
heldByInclusion: heldByInclusion(project, targetRoot),
|
|
1276
|
-
generated:
|
|
923
|
+
generated: read.generated,
|
|
924
|
+
bindings: read.bindings,
|
|
1277
925
|
inOperands: inOperandNames(project, targetRoot, testFiles),
|
|
1278
926
|
rooted: read.rooted,
|
|
1279
927
|
directives: inlineDirectives(project, read.held, targetRoot).filter(
|
|
@@ -1281,9 +929,12 @@ export function readEmitterRun(
|
|
|
1281
929
|
),
|
|
1282
930
|
declarationsNamed: declarationsNamed(project, read.held, configuredDeclarations(config)),
|
|
1283
931
|
parts: projectParts(project, read.held, references, targetRoot),
|
|
932
|
+
unseenLoads,
|
|
933
|
+
// Only a closed world reports an unnecessary export, which is all the carriers decide.
|
|
934
|
+
carriers: config.consumers.complete ? carriersOf(project, read.held) : NO_CARRIERS,
|
|
1284
935
|
}),
|
|
1285
936
|
);
|
|
1286
|
-
// Whether a declaration carries the marker decides its code, so one whose
|
|
937
|
+
// Whether a declaration carries the marker decides its code, so one whose answer went
|
|
1287
938
|
// unread is reported by nothing.
|
|
1288
939
|
const unread = run.projects.flatMap((one) => one.extra.deprecation.unanswered);
|
|
1289
940
|
return unread.length === 0
|
|
@@ -1335,24 +986,19 @@ function judgedMembers(
|
|
|
1335
986
|
|
|
1336
987
|
/** The directory of the nearest `package.json` at or above a file, inside `root`, else `root`. */
|
|
1337
988
|
function nearestManifestDir(host: Host, root: string, file: string): string {
|
|
1338
|
-
|
|
1339
|
-
if (host.kindOf(joinPath(dir, "package.json")) === "file") {
|
|
1340
|
-
return dir;
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
return root;
|
|
989
|
+
return ancestors(dirnamePath(file), root).find((dir) => holdsManifest(host, dir)) ?? root;
|
|
1344
990
|
}
|
|
1345
991
|
|
|
1346
992
|
/**
|
|
1347
993
|
* The input every emitter reads over one sweep of a read run: the facts beside the sweep
|
|
1348
|
-
* each
|
|
994
|
+
* each emitter reads, every per-project one read in the same session as the sweep.
|
|
1349
995
|
*/
|
|
1350
996
|
export function emitterInputOver(
|
|
1351
997
|
host: Host,
|
|
1352
998
|
scope: Scope,
|
|
1353
|
-
config:
|
|
999
|
+
config: ResolvedConfig,
|
|
1354
1000
|
read: ReadRun<EmitterExtra>,
|
|
1355
|
-
input: Pick<
|
|
1001
|
+
input: Pick<SweepPolicy, "marked" | "mode">,
|
|
1356
1002
|
selfCheck: SelfCheckFacts,
|
|
1357
1003
|
): EmitterInput {
|
|
1358
1004
|
const targetRoot = scope.target.path;
|
|
@@ -1366,14 +1012,16 @@ export function emitterInputOver(
|
|
|
1366
1012
|
stores: storesOf(
|
|
1367
1013
|
projects.map((one) => ({
|
|
1368
1014
|
references: one.configured.references,
|
|
1015
|
+
support: new Set(one.configured.supportFiles ?? []),
|
|
1369
1016
|
accessors: one.extra.accessors,
|
|
1370
1017
|
})),
|
|
1371
|
-
swept.exempt,
|
|
1018
|
+
swept.sweep.exempt,
|
|
1372
1019
|
input.mode,
|
|
1373
1020
|
),
|
|
1374
1021
|
dependencies: dependenciesOf(
|
|
1375
1022
|
host,
|
|
1376
1023
|
targetRoot,
|
|
1024
|
+
read.workflows,
|
|
1377
1025
|
[...projects.map((one) => one.extra.needs), configurationNeeds(read.conventionUses)],
|
|
1378
1026
|
swept.sweep.candidates.map((candidate) => candidate.id),
|
|
1379
1027
|
members.read,
|
|
@@ -1384,8 +1032,19 @@ export function emitterInputOver(
|
|
|
1384
1032
|
files: {
|
|
1385
1033
|
tree: sourceTree(host, targetRoot),
|
|
1386
1034
|
heldByInclusion: new Set(projects.flatMap((one) => one.extra.heldByInclusion)),
|
|
1387
|
-
generated: new Set(projects.flatMap((one) => one.extra.generated)),
|
|
1035
|
+
generated: new Set(projects.flatMap((one) => [...one.extra.generated.keys()])),
|
|
1388
1036
|
inOperands: new Set(projects.flatMap((one) => one.extra.inOperands)),
|
|
1037
|
+
unseenLoads: projects.flatMap((one) => one.extra.unseenLoads),
|
|
1038
|
+
unwrittenRuns: new Set(
|
|
1039
|
+
projects.flatMap((one) =>
|
|
1040
|
+
one.heldScripts
|
|
1041
|
+
.filter((held) => held.unwritten)
|
|
1042
|
+
.map(
|
|
1043
|
+
(held) =>
|
|
1044
|
+
relativePath(resolvePath(host.workingDirectory(), targetRoot), held.dir) ?? ".",
|
|
1045
|
+
),
|
|
1046
|
+
),
|
|
1047
|
+
),
|
|
1389
1048
|
},
|
|
1390
1049
|
boundary: {
|
|
1391
1050
|
consumers: {
|
|
@@ -1394,12 +1053,25 @@ export function emitterInputOver(
|
|
|
1394
1053
|
},
|
|
1395
1054
|
encapsulated: readManifest(host, targetRoot).declaresExports,
|
|
1396
1055
|
edges: readEdgeSides(host, targetRoot),
|
|
1056
|
+
filledOutside: new Set(projects.flatMap((one) => one.filledOutside)),
|
|
1057
|
+
possiblyLoaded: new Set(projects.flatMap((one) => one.possiblyLoaded)),
|
|
1058
|
+
carriers: {
|
|
1059
|
+
named: new Map(
|
|
1060
|
+
[
|
|
1061
|
+
...Map.groupBy(
|
|
1062
|
+
projects.flatMap((one) => [...one.extra.carriers.named]),
|
|
1063
|
+
([id]) => id,
|
|
1064
|
+
),
|
|
1065
|
+
].map(([id, entries]) => [id, [...new Set(entries.flatMap(([, named]) => named))]]),
|
|
1066
|
+
),
|
|
1067
|
+
unread: new Set(projects.flatMap((one) => [...one.extra.carriers.unread])),
|
|
1068
|
+
},
|
|
1397
1069
|
},
|
|
1398
1070
|
selfCheck,
|
|
1399
1071
|
intraFunction: intraFunctionFacts(
|
|
1400
1072
|
projects.map((one) => one.extra.parts),
|
|
1401
1073
|
projects.flatMap((one) => one.configured.references),
|
|
1402
|
-
new Set([...swept.exempt.map((one) => one.id), ...swept.
|
|
1074
|
+
new Set([...swept.sweep.exempt.map((one) => one.id), ...swept.sweep.held]),
|
|
1403
1075
|
),
|
|
1404
1076
|
};
|
|
1405
1077
|
}
|
|
@@ -1429,14 +1101,14 @@ interface AnalysisReader {
|
|
|
1429
1101
|
* directives, the ignore file's entries and the baseline's rows are bound before any
|
|
1430
1102
|
* sweep, and the run is swept once under every bound record's mark and once under none,
|
|
1431
1103
|
* so a record is decided against the finding its code would have produced. The
|
|
1432
|
-
*
|
|
1104
|
+
* configuration family reports the refused suppressions and the roots that named nothing.
|
|
1433
1105
|
* Beside the inputs it answers the projects and test-file rules a report names.
|
|
1434
1106
|
*/
|
|
1435
1107
|
function readAnalysis(
|
|
1436
1108
|
engine: Engine,
|
|
1437
1109
|
host: Host,
|
|
1438
1110
|
scope: Scope,
|
|
1439
|
-
config:
|
|
1111
|
+
config: ResolvedConfig,
|
|
1440
1112
|
provenance: Provenance,
|
|
1441
1113
|
mode: Mode,
|
|
1442
1114
|
detectors: Detectors,
|
|
@@ -1457,7 +1129,7 @@ function readAnalysis(
|
|
|
1457
1129
|
configFile: one.configFile,
|
|
1458
1130
|
})),
|
|
1459
1131
|
testFileRules: testFileRulesOf(
|
|
1460
|
-
config.ts.
|
|
1132
|
+
config.ts.test_files,
|
|
1461
1133
|
read.projects.flatMap((one) => one.configured.testFiles),
|
|
1462
1134
|
read.projects.flatMap((one) => one.configured.supportFiles ?? []),
|
|
1463
1135
|
),
|
|
@@ -1474,8 +1146,16 @@ function readAnalysis(
|
|
|
1474
1146
|
unanswered: read.unanswered,
|
|
1475
1147
|
componentsUnread: read.componentsUnread,
|
|
1476
1148
|
librariesUnfound: read.librariesUnfound,
|
|
1149
|
+
unresolvedSpecifiers: read.unresolvedSpecifiers,
|
|
1150
|
+
unread: read.unread,
|
|
1477
1151
|
conventionsApplied: read.conventionsApplied,
|
|
1478
1152
|
unmappedEntries: unmappedEverywhere(read.projects),
|
|
1153
|
+
heldScripts: read.projects.flatMap((one) =>
|
|
1154
|
+
one.heldScripts.map((held) => ({ ...held, configFile: one.configFile })),
|
|
1155
|
+
),
|
|
1156
|
+
unseenLoads: read.projects.flatMap((one) => one.extra.unseenLoads),
|
|
1157
|
+
generated: new Map(read.projects.flatMap((one) => [...one.extra.generated])),
|
|
1158
|
+
bindings: distinctBindings(read.projects.flatMap((one) => one.extra.bindings)),
|
|
1479
1159
|
},
|
|
1480
1160
|
configured: read.projects.map((one) => one.configured),
|
|
1481
1161
|
symbols,
|
|
@@ -1487,7 +1167,7 @@ function readAnalysis(
|
|
|
1487
1167
|
function inputsOver(
|
|
1488
1168
|
host: Host,
|
|
1489
1169
|
scope: Scope,
|
|
1490
|
-
config:
|
|
1170
|
+
config: ResolvedConfig,
|
|
1491
1171
|
provenance: Provenance,
|
|
1492
1172
|
mode: Mode,
|
|
1493
1173
|
read: ReadRun<EmitterExtra>,
|
|
@@ -1501,7 +1181,7 @@ function inputsOver(
|
|
|
1501
1181
|
const facts: SelfCheckFacts = {
|
|
1502
1182
|
refusals: suppressions.refusals,
|
|
1503
1183
|
unmatchedRoots: unmatchedEverywhere(
|
|
1504
|
-
config.
|
|
1184
|
+
config.roots.patterns,
|
|
1505
1185
|
read.projects.map((one) => one.extra.rooted),
|
|
1506
1186
|
),
|
|
1507
1187
|
rootsDocument: documentOf(host, provenance, ROOTS_SETTING, targetRoot),
|
|
@@ -1570,10 +1250,22 @@ interface RunFacts {
|
|
|
1570
1250
|
readonly componentsUnread: readonly ComponentsUnread[];
|
|
1571
1251
|
/** Per analyzed configuration, each library it names that the compiler cannot find. */
|
|
1572
1252
|
readonly librariesUnfound: readonly LibraryUnfound[];
|
|
1253
|
+
/** The relative specifiers of the run's unchecked JavaScript files that resolve to no file. */
|
|
1254
|
+
readonly unresolvedSpecifiers: readonly UnresolvedSpecifier[];
|
|
1255
|
+
/** The inputs the run could not read. */
|
|
1256
|
+
readonly unread: readonly UnreadInput[];
|
|
1573
1257
|
/** The convention rows the run applied. */
|
|
1574
1258
|
readonly conventionsApplied: readonly AppliedConvention[];
|
|
1575
1259
|
/** The manifest entries no project of the run reads back to a file, each once. */
|
|
1576
1260
|
readonly unmappedEntries: readonly ManifestEntry[];
|
|
1261
|
+
/** Per project, by its compiler configuration file, each package whose command strings name files it holds. */
|
|
1262
|
+
readonly heldScripts: readonly (HeldScripts & { readonly configFile: string })[];
|
|
1263
|
+
/** The loads of production files whose target the run cannot resolve, per configuration. */
|
|
1264
|
+
readonly unseenLoads: readonly UnseenLoad[];
|
|
1265
|
+
/** Every generated file of the run, by its path below the target root, each once. */
|
|
1266
|
+
readonly generated: ReadonlyMap<string, GeneratedFact>;
|
|
1267
|
+
/** Every binding record the run's generated files publish, each once. */
|
|
1268
|
+
readonly bindings: readonly BindingRecord[];
|
|
1577
1269
|
}
|
|
1578
1270
|
|
|
1579
1271
|
/** One configuration whose component files a run cannot read. */
|
|
@@ -1582,13 +1274,6 @@ interface ComponentsUnread {
|
|
|
1582
1274
|
readonly reason: string;
|
|
1583
1275
|
}
|
|
1584
1276
|
|
|
1585
|
-
/** One library an analyzed configuration names that the compiler cannot find. */
|
|
1586
|
-
interface LibraryUnfound {
|
|
1587
|
-
readonly configFile: string;
|
|
1588
|
-
/** The compiler's error, rendered as a dropped configuration's is. */
|
|
1589
|
-
readonly error: string;
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
1277
|
/** The findings of one run, beside what a report states about the run itself. */
|
|
1593
1278
|
export interface RunAnalysis {
|
|
1594
1279
|
readonly result: PassResult;
|
|
@@ -1601,7 +1286,7 @@ export interface RunAnalysis {
|
|
|
1601
1286
|
|
|
1602
1287
|
/**
|
|
1603
1288
|
* The analysis of the run the scope and the configuration describe: the run read with its
|
|
1604
|
-
* suppressions bound, every
|
|
1289
|
+
* suppressions bound, every emitter's findings with the suppressions applied and the
|
|
1605
1290
|
* declared edges evaluated, the projects and test-file rules the report names, and the sweep
|
|
1606
1291
|
* an explanation reads.
|
|
1607
1292
|
*/
|
|
@@ -1609,7 +1294,7 @@ export function runAnalysis(
|
|
|
1609
1294
|
engine: Engine,
|
|
1610
1295
|
host: Host,
|
|
1611
1296
|
scope: Scope,
|
|
1612
|
-
config:
|
|
1297
|
+
config: ResolvedConfig,
|
|
1613
1298
|
provenance: Provenance,
|
|
1614
1299
|
mode: Mode,
|
|
1615
1300
|
detectors: Detectors = DETECTORS,
|
|
@@ -1621,14 +1306,22 @@ export function runAnalysis(
|
|
|
1621
1306
|
|
|
1622
1307
|
/**
|
|
1623
1308
|
* One count per configuration of the run in which the checker left a question unanswered:
|
|
1624
|
-
* the questions asked in its project,
|
|
1309
|
+
* the questions asked in its project, a formed program's manifest that does not parse or cannot
|
|
1310
|
+
* be read and a package whose command strings name files the project holds each counted as one, and the
|
|
1311
|
+
* declarations of its own the run holds for them.
|
|
1625
1312
|
*/
|
|
1626
1313
|
export function unansweredCounts(analysis: RunAnalysis): readonly UnansweredCount[] {
|
|
1627
|
-
const held = new Set(analysis.swept.
|
|
1314
|
+
const held = new Set(analysis.swept.sweep.held);
|
|
1628
1315
|
return analysis.run.projects.flatMap((project) => {
|
|
1629
|
-
const questions =
|
|
1630
|
-
(one) => one.configFile === project.configFile
|
|
1631
|
-
|
|
1316
|
+
const questions =
|
|
1317
|
+
analysis.run.unanswered.filter((one) => one.configFile === project.configFile).length +
|
|
1318
|
+
analysis.run.unread.filter(
|
|
1319
|
+
(one) => one.kind === "manifest" && one.configFile === project.configFile,
|
|
1320
|
+
).length +
|
|
1321
|
+
analysis.run.heldScripts.filter(
|
|
1322
|
+
(one) => one.configFile === project.configFile && one.files.length > 0,
|
|
1323
|
+
).length;
|
|
1324
|
+
|
|
1632
1325
|
if (questions === 0) {
|
|
1633
1326
|
return [];
|
|
1634
1327
|
}
|
|
@@ -1665,7 +1358,7 @@ export function runBaselineWrite(
|
|
|
1665
1358
|
engine: Engine,
|
|
1666
1359
|
host: Host,
|
|
1667
1360
|
scope: Scope,
|
|
1668
|
-
config:
|
|
1361
|
+
config: ResolvedConfig,
|
|
1669
1362
|
provenance: Provenance,
|
|
1670
1363
|
mode: Mode,
|
|
1671
1364
|
reason: string,
|