@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
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The programs a run forms for the JavaScript files no compiler configuration lists: one per
|
|
3
|
+
* package, over the files git would track that are no build output, each written as a
|
|
4
|
+
* configuration only the snapshot holds, with the module system of the runtime its package
|
|
5
|
+
* is written for.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readCommands } from "../commands/read.ts";
|
|
9
|
+
import { CONVENTION_ROWS } from "../entries/convention-rows.ts";
|
|
10
|
+
import type { Conventions } from "../entries/conventions.ts";
|
|
11
|
+
import { holdsManifest, MANIFEST, readManifestAt, type ManifestRead } from "../fs/manifest.ts";
|
|
12
|
+
import { filesBelow } from "../fs/tree.ts";
|
|
13
|
+
import type { Host } from "../host.ts";
|
|
14
|
+
import { JAVASCRIPT_FILE, minifiedBy, minifiedByName } from "../javascript-file.ts";
|
|
15
|
+
import { isRecord } from "../json-document.ts";
|
|
16
|
+
import { manifestCommands } from "../roots/manifest.ts";
|
|
17
|
+
import { ancestors, dirnamePath, joinPath, relativePath } from "../paths.ts";
|
|
18
|
+
import type { Engine } from "../session.ts";
|
|
19
|
+
import { bytewise } from "../text/compare.ts";
|
|
20
|
+
import type { Configuration, Origin } from "./discover.ts";
|
|
21
|
+
import { writtenPath } from "./workspace-programs.ts";
|
|
22
|
+
|
|
23
|
+
/** The name a package's program is written beside, made free by {@link writtenPath}. */
|
|
24
|
+
const GROUP_CONFIGURATION = "jsconfig.json";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The options of a formed program before its runtime is chosen: unchecked JavaScript, no
|
|
28
|
+
* emit, no installed package's JavaScript, which is not the target's code and grows the
|
|
29
|
+
* program with the depth of `node_modules`, and every type package visible.
|
|
30
|
+
*/
|
|
31
|
+
const FORMED_OPTIONS = {
|
|
32
|
+
allowJs: true,
|
|
33
|
+
checkJs: false,
|
|
34
|
+
noEmit: true,
|
|
35
|
+
skipLibCheck: true,
|
|
36
|
+
maxNodeModuleJsDepth: 0,
|
|
37
|
+
target: "esnext",
|
|
38
|
+
jsx: "preserve",
|
|
39
|
+
resolveJsonModule: true,
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
interface CandidateContext {
|
|
43
|
+
/** The files a configuration of the run lists or a test file joins it with, absolute. */
|
|
44
|
+
readonly covered: ReadonlySet<string>;
|
|
45
|
+
/** The output and declaration directories of every configuration of the run, absolute. */
|
|
46
|
+
readonly outputs: readonly string[];
|
|
47
|
+
/** Whether git ignores one absolute path. */
|
|
48
|
+
readonly ignored: (path: string) => boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Whether one file is minified build output; one that cannot be read is left to the compiler. */
|
|
52
|
+
function minifiedFile(host: Host, file: string): boolean {
|
|
53
|
+
if (minifiedByName(file) !== undefined) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return minifiedBy(file, host.readFile(file)) !== undefined;
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The JavaScript files below `root` a program may be formed over: none in a skipped
|
|
65
|
+
* directory, none git ignores, none minified, none `context` covers and none below one of
|
|
66
|
+
* its output directories. A convention row's generated directory leaves out more, once the
|
|
67
|
+
* rows are read: {@link formedGroups}.
|
|
68
|
+
*/
|
|
69
|
+
export function candidateFiles(
|
|
70
|
+
host: Host,
|
|
71
|
+
root: string,
|
|
72
|
+
{ covered, outputs, ignored }: CandidateContext,
|
|
73
|
+
): readonly string[] {
|
|
74
|
+
return filesBelow(host, root, (name) => JAVASCRIPT_FILE.test(name))
|
|
75
|
+
.map((path) => joinPath(root, path))
|
|
76
|
+
.filter(
|
|
77
|
+
(file) =>
|
|
78
|
+
!covered.has(file) &&
|
|
79
|
+
!outputs.some((dir) => relativePath(dir, file) !== undefined) &&
|
|
80
|
+
!ignored(file) &&
|
|
81
|
+
!minifiedFile(host, file),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface Group {
|
|
86
|
+
/** The package's directory, absolute. */
|
|
87
|
+
readonly dir: string;
|
|
88
|
+
readonly manifest: ManifestRead;
|
|
89
|
+
/** Its files, absolute, in ascending order. */
|
|
90
|
+
readonly files: readonly string[];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The candidates below `root` grouped by package, in directory order, less every file below a
|
|
95
|
+
* directory an applied row of `conventions` names as generated: each file belongs to the
|
|
96
|
+
* nearest directory at or above it, up to `root`, that holds a `package.json`, a manifest that
|
|
97
|
+
* does not parse included, and to `root` where none does.
|
|
98
|
+
*/
|
|
99
|
+
export function formedGroups(
|
|
100
|
+
host: Host,
|
|
101
|
+
root: string,
|
|
102
|
+
candidates: readonly string[],
|
|
103
|
+
conventions: Conventions,
|
|
104
|
+
): readonly Group[] {
|
|
105
|
+
const generated = conventions.generated.map(({ dir, below }) => joinPath(dir, below));
|
|
106
|
+
const groups = new Map<string, string[]>();
|
|
107
|
+
for (const file of candidates) {
|
|
108
|
+
if (generated.some((dir) => relativePath(dir, file) !== undefined)) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const dir = packageOf(host, root, file);
|
|
112
|
+
groups.set(dir, [...(groups.get(dir) ?? []), file]);
|
|
113
|
+
}
|
|
114
|
+
return [...groups]
|
|
115
|
+
.sort(([a], [b]) => bytewise(a, b))
|
|
116
|
+
.map(([dir, files]) => ({
|
|
117
|
+
dir,
|
|
118
|
+
manifest: readManifestAt(host, dir),
|
|
119
|
+
files: files.sort(bytewise),
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The directory whose `package.json` groups one file: the nearest at or above it, up to `root`. */
|
|
124
|
+
export function packageOf(host: Host, root: string, file: string): string {
|
|
125
|
+
return ancestors(dirnamePath(file), root).find((at) => holdsManifest(host, at)) ?? root;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type Runtime = "bundler" | "node";
|
|
129
|
+
|
|
130
|
+
const RUNTIME_OPTIONS = {
|
|
131
|
+
bundler: { module: "preserve", moduleResolution: "bundler" },
|
|
132
|
+
node: { module: "nodenext", moduleResolution: "nodenext" },
|
|
133
|
+
} as const satisfies Record<Runtime, Readonly<Record<string, string>>>;
|
|
134
|
+
|
|
135
|
+
/** Whether one configuration is a program the run formed to resolve its modules as Node does. */
|
|
136
|
+
export function formedForNode(configuration: Configuration): boolean {
|
|
137
|
+
const options = configuration.written?.["compilerOptions"];
|
|
138
|
+
return isRecord(options) && options["moduleResolution"] === RUNTIME_OPTIONS.node.moduleResolution;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The manifest members that say a package is written for Node. */
|
|
142
|
+
const NODE_MEMBERS = ["main", "exports", "bin", "type"] as const;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Whether one manifest says its package runs under Node: a Node member, `engines.node`
|
|
146
|
+
* included, or a command string of it that runs a file with `node`, as `commands/read.ts` reads it.
|
|
147
|
+
*/
|
|
148
|
+
function writtenForNode(
|
|
149
|
+
host: Host,
|
|
150
|
+
dir: string,
|
|
151
|
+
manifest: Readonly<Record<string, unknown>>,
|
|
152
|
+
): boolean {
|
|
153
|
+
const { engines } = manifest;
|
|
154
|
+
return (
|
|
155
|
+
NODE_MEMBERS.some((member) => manifest[member] !== undefined) ||
|
|
156
|
+
(isRecord(engines) && engines["node"] !== undefined) ||
|
|
157
|
+
manifestCommands(host, dir, manifest).some(({ command }) =>
|
|
158
|
+
readCommands(command, dir).runs.some((run) => run.runtime === "node"),
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The manifests, by path as `conventions` names them, an applied row of a tool that bundles
|
|
165
|
+
* applies through.
|
|
166
|
+
*/
|
|
167
|
+
export function bundlingManifests(conventions: Conventions): ReadonlySet<string> {
|
|
168
|
+
return new Set(
|
|
169
|
+
conventions.applied
|
|
170
|
+
.filter((one) => CONVENTION_ROWS.some((row) => row.name === one.name && row.bundles === true))
|
|
171
|
+
.map((one) => one.manifest),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface FormedProgram {
|
|
176
|
+
readonly configuration: Configuration;
|
|
177
|
+
readonly group: Group;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
interface Forming {
|
|
181
|
+
/** The tree's root, absolute, which the manifest paths of `bundling` are read below. */
|
|
182
|
+
readonly root: string;
|
|
183
|
+
readonly origin: Origin;
|
|
184
|
+
/** The manifests a bundling row applies through, as {@link bundlingManifests} names them. */
|
|
185
|
+
readonly bundling: ReadonlySet<string>;
|
|
186
|
+
/** The name one group's program is given, by the group's manifest path, `undefined` for none. */
|
|
187
|
+
readonly idOf: (manifest: string | undefined) => string;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Each group's program, given the module system of the runtime its package is written for: a
|
|
192
|
+
* bundler's where a row of a tool that bundles applies through the group's manifest or the
|
|
193
|
+
* root's, else Node's where its manifest says the package runs under Node or a command string of
|
|
194
|
+
* it runs a file with `node`, under which a file's
|
|
195
|
+
* extension and its package's `type` decide its module format, else a bundler's, which reads a
|
|
196
|
+
* file with no module syntax as a classic script, as a browser loads it.
|
|
197
|
+
*/
|
|
198
|
+
export function formedPrograms(
|
|
199
|
+
engine: Engine,
|
|
200
|
+
host: Host,
|
|
201
|
+
groups: readonly Group[],
|
|
202
|
+
{ root, origin, bundling, idOf }: Forming,
|
|
203
|
+
): readonly FormedProgram[] {
|
|
204
|
+
return groups.map((group) => {
|
|
205
|
+
const manifest = group.manifest.kind === "absent" ? undefined : joinPath(group.dir, MANIFEST);
|
|
206
|
+
const below = manifest === undefined ? undefined : relativePath(root, manifest);
|
|
207
|
+
const runtime: Runtime =
|
|
208
|
+
!bundling.has(MANIFEST) &&
|
|
209
|
+
(below === undefined || !bundling.has(below)) &&
|
|
210
|
+
group.manifest.kind === "read" &&
|
|
211
|
+
writtenForNode(host, group.dir, group.manifest.manifest)
|
|
212
|
+
? "node"
|
|
213
|
+
: "bundler";
|
|
214
|
+
const configFile = writtenPath(host, joinPath(group.dir, GROUP_CONFIGURATION));
|
|
215
|
+
const written = {
|
|
216
|
+
compilerOptions: { ...FORMED_OPTIONS, ...RUNTIME_OPTIONS[runtime] },
|
|
217
|
+
files: group.files,
|
|
218
|
+
};
|
|
219
|
+
return {
|
|
220
|
+
group,
|
|
221
|
+
configuration: {
|
|
222
|
+
id: idOf(manifest),
|
|
223
|
+
configFile,
|
|
224
|
+
origin,
|
|
225
|
+
parsed: engine.parseConfigJson(written, configFile),
|
|
226
|
+
written,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The globals a test runner injects into every file it runs, which no import names: a
|
|
3
|
+
* Vitest configuration whose `test.globals` is `true` gives each test and each file it
|
|
4
|
+
* loads `describe`, `it`, `expect` and `vi` (https://vitest.dev/config/globals). A program
|
|
5
|
+
* analyzed without the runner's declarations of them reads every use as an error, so a
|
|
6
|
+
* configuration under such a runner is read with them; and a file that calls one is
|
|
7
|
+
* written for the runner, as one that imports it is.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
isAsExpression,
|
|
12
|
+
isBinaryExpression,
|
|
13
|
+
isCallExpression,
|
|
14
|
+
isExportAssignment,
|
|
15
|
+
isExpressionStatement,
|
|
16
|
+
isIdentifier,
|
|
17
|
+
isObjectLiteralExpression,
|
|
18
|
+
isParenthesizedExpression,
|
|
19
|
+
isPropertyAccessExpression,
|
|
20
|
+
isPropertyAssignment,
|
|
21
|
+
isSatisfiesExpression,
|
|
22
|
+
SyntaxKind,
|
|
23
|
+
type Node,
|
|
24
|
+
type SourceFile,
|
|
25
|
+
} from "@typescript/native/ast";
|
|
26
|
+
import type { ParseFile } from "../entries/configuration-files.ts";
|
|
27
|
+
import type { Host } from "../host.ts";
|
|
28
|
+
import { isRecord } from "../json-document.ts";
|
|
29
|
+
import { ancestors, dirnamePath, joinPath } from "../paths.ts";
|
|
30
|
+
import { UNANSWERED } from "../query.ts";
|
|
31
|
+
import type { ProjectView } from "../session.ts";
|
|
32
|
+
import { filesIn } from "../fs/tree.ts";
|
|
33
|
+
import { holdsManifest, INSTALLED_PACKAGES } from "../fs/manifest.ts";
|
|
34
|
+
import { isTargetConfiguration } from "./discover.ts";
|
|
35
|
+
import type { ProgramPlan } from "./plan.ts";
|
|
36
|
+
|
|
37
|
+
/** The test runner whose configuration injects the globals, and the `types` entry declaring them. */
|
|
38
|
+
export const GLOBALS_RUNNER = "vitest";
|
|
39
|
+
const GLOBALS_TYPES = "vitest/globals";
|
|
40
|
+
|
|
41
|
+
/** The configuration files the runner reads its settings from, by name. */
|
|
42
|
+
const RUNNER_CONFIG = /^(?:vitest|vite)\.config\.(?:js|mjs|cjs|ts|mts|cts)$/u;
|
|
43
|
+
|
|
44
|
+
/** The globals `vitest/globals` declares that a test or a helper calls or reads a member of. */
|
|
45
|
+
const GLOBAL_NAMES: ReadonlySet<string> = new Set([
|
|
46
|
+
"afterAll",
|
|
47
|
+
"afterEach",
|
|
48
|
+
"assert",
|
|
49
|
+
"assertType",
|
|
50
|
+
"beforeAll",
|
|
51
|
+
"beforeEach",
|
|
52
|
+
"bench",
|
|
53
|
+
"describe",
|
|
54
|
+
"expect",
|
|
55
|
+
"expectTypeOf",
|
|
56
|
+
"it",
|
|
57
|
+
"onTestFailed",
|
|
58
|
+
"onTestFinished",
|
|
59
|
+
"suite",
|
|
60
|
+
"test",
|
|
61
|
+
"vi",
|
|
62
|
+
"vitest",
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
/** The expression one wrapper that changes no value holds, and a call's first argument. */
|
|
66
|
+
function configObject(node: Node): Node | undefined {
|
|
67
|
+
let at: Node | undefined = node;
|
|
68
|
+
while (at !== undefined) {
|
|
69
|
+
if (isParenthesizedExpression(at) || isAsExpression(at) || isSatisfiesExpression(at)) {
|
|
70
|
+
at = at.expression;
|
|
71
|
+
} else if (isCallExpression(at)) {
|
|
72
|
+
at = at.arguments[0];
|
|
73
|
+
} else {
|
|
74
|
+
return at;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The value one object literal writes for one member as `name: value`. */
|
|
81
|
+
function member(object: Node | undefined, name: string): Node | undefined {
|
|
82
|
+
if (object === undefined || !isObjectLiteralExpression(object)) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
for (const property of object.properties) {
|
|
86
|
+
if (
|
|
87
|
+
isPropertyAssignment(property) &&
|
|
88
|
+
isIdentifier(property.name) &&
|
|
89
|
+
property.name.text === name
|
|
90
|
+
) {
|
|
91
|
+
return configObject(property.initializer);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Whether one runner configuration's default export sets `test.globals` to `true`. */
|
|
98
|
+
function setsGlobals(file: SourceFile): boolean {
|
|
99
|
+
for (const statement of file.statements) {
|
|
100
|
+
let exported: Node | undefined;
|
|
101
|
+
if (isExportAssignment(statement)) {
|
|
102
|
+
exported = statement.expression;
|
|
103
|
+
} else if (isExpressionStatement(statement) && isBinaryExpression(statement.expression)) {
|
|
104
|
+
const { left, operatorToken, right } = statement.expression;
|
|
105
|
+
if (
|
|
106
|
+
operatorToken.kind === SyntaxKind.EqualsToken &&
|
|
107
|
+
isPropertyAccessExpression(left) &&
|
|
108
|
+
isIdentifier(left.expression) &&
|
|
109
|
+
left.expression.text === "module" &&
|
|
110
|
+
isIdentifier(left.name) &&
|
|
111
|
+
left.name.text === "exports"
|
|
112
|
+
) {
|
|
113
|
+
exported = right;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const object = exported === undefined ? undefined : configObject(exported);
|
|
117
|
+
const globals = member(member(object, "test"), "globals");
|
|
118
|
+
if (globals?.kind === SyntaxKind.TrueKeyword) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Whether the runner's configuration in one manifest's directory injects the globals. */
|
|
126
|
+
function injectsGlobals(host: Host, parse: ParseFile, dir: string): boolean {
|
|
127
|
+
return filesIn(host, dir, (name) => RUNNER_CONFIG.test(name)).some((name) => {
|
|
128
|
+
const path = joinPath(dir, name);
|
|
129
|
+
try {
|
|
130
|
+
return setsGlobals(parse(path, host.readFile(path)));
|
|
131
|
+
} catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Whether a file declaring the globals is installed where the configuration resolves packages from. */
|
|
138
|
+
function globalsInstalled(host: Host, configFile: string): boolean {
|
|
139
|
+
return ancestors(dirnamePath(configFile)).some(
|
|
140
|
+
(dir) =>
|
|
141
|
+
host.kindOf(joinPath(dir, INSTALLED_PACKAGES, GLOBALS_RUNNER, "globals.d.ts")) === "file",
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** The directory of the manifest nearest one configuration file, at or above its own. */
|
|
146
|
+
function manifestDir(host: Host, configFile: string): string | undefined {
|
|
147
|
+
return ancestors(dirnamePath(configFile)).find((dir) => holdsManifest(host, dir));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function typesOf(value: unknown): readonly string[] | undefined {
|
|
151
|
+
return Array.isArray(value) && value.every((one) => typeof one === "string") ? value : undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The plans with the globals' declarations added to the `types` of each target configuration
|
|
156
|
+
* whose nearest manifest's runner configuration injects them and that can resolve them.
|
|
157
|
+
*/
|
|
158
|
+
export function testGlobals(
|
|
159
|
+
host: Host,
|
|
160
|
+
parse: ParseFile,
|
|
161
|
+
plans: readonly ProgramPlan[],
|
|
162
|
+
): readonly ProgramPlan[] {
|
|
163
|
+
const injects = new Map<string, boolean>();
|
|
164
|
+
return plans.map((plan): ProgramPlan => {
|
|
165
|
+
const dir = manifestDir(host, plan.configFile);
|
|
166
|
+
if (
|
|
167
|
+
!isTargetConfiguration(plan) ||
|
|
168
|
+
dir === undefined ||
|
|
169
|
+
!globalsInstalled(host, plan.configFile)
|
|
170
|
+
) {
|
|
171
|
+
return plan;
|
|
172
|
+
}
|
|
173
|
+
if (!injects.has(dir)) {
|
|
174
|
+
injects.set(dir, injectsGlobals(host, parse, dir));
|
|
175
|
+
}
|
|
176
|
+
const base = typesOf(plan.options.types) ?? [];
|
|
177
|
+
const { build } = plan;
|
|
178
|
+
if (injects.get(dir) !== true) {
|
|
179
|
+
return plan;
|
|
180
|
+
}
|
|
181
|
+
if (build.kind === "program") {
|
|
182
|
+
const listed = typesOf(build.params.compilerOptions.types) ?? base;
|
|
183
|
+
return listed.includes(GLOBALS_TYPES)
|
|
184
|
+
? plan
|
|
185
|
+
: {
|
|
186
|
+
...plan,
|
|
187
|
+
build: {
|
|
188
|
+
kind: "program",
|
|
189
|
+
params: {
|
|
190
|
+
...build.params,
|
|
191
|
+
compilerOptions: {
|
|
192
|
+
...build.params.compilerOptions,
|
|
193
|
+
types: [...listed, GLOBALS_TYPES],
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const written = build.kind === "configuration" ? build.value : { extends: plan.configFile };
|
|
200
|
+
const held = written["compilerOptions"];
|
|
201
|
+
const options = isRecord(held) ? held : {};
|
|
202
|
+
const listed = typesOf(options["types"]) ?? base;
|
|
203
|
+
return listed.includes(GLOBALS_TYPES)
|
|
204
|
+
? plan
|
|
205
|
+
: {
|
|
206
|
+
...plan,
|
|
207
|
+
build: {
|
|
208
|
+
kind: "configuration",
|
|
209
|
+
value: {
|
|
210
|
+
...written,
|
|
211
|
+
compilerOptions: { ...options, types: [...listed, GLOBALS_TYPES] },
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Whether one file names a global the runner injects, which is how a file written for the
|
|
220
|
+
* runner's globals reads: a call of one of the names or a read of a member of it that
|
|
221
|
+
* resolves to a declaration outside the project's own files, the runner's declaration
|
|
222
|
+
* file. A name the file binds, imported, declared or a parameter, resolves to its own.
|
|
223
|
+
*/
|
|
224
|
+
export function namesTestGlobals<Brand>(project: ProjectView<Brand>, file: SourceFile): boolean {
|
|
225
|
+
const named: Node[] = [];
|
|
226
|
+
const visit = (node: Node): void => {
|
|
227
|
+
const callee = isCallExpression(node)
|
|
228
|
+
? node.expression
|
|
229
|
+
: isPropertyAccessExpression(node)
|
|
230
|
+
? node.expression
|
|
231
|
+
: undefined;
|
|
232
|
+
if (callee !== undefined && isIdentifier(callee) && GLOBAL_NAMES.has(callee.text)) {
|
|
233
|
+
named.push(callee);
|
|
234
|
+
}
|
|
235
|
+
node.forEachChild(visit);
|
|
236
|
+
};
|
|
237
|
+
file.forEachChild(visit);
|
|
238
|
+
if (named.length === 0) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
const own = project.ownPaths();
|
|
242
|
+
return project
|
|
243
|
+
.symbolsAt(named.map((node) => project.handle(node)))
|
|
244
|
+
.some(
|
|
245
|
+
(symbol) =>
|
|
246
|
+
symbol === UNANSWERED ||
|
|
247
|
+
(symbol !== undefined &&
|
|
248
|
+
symbol.declarations.length > 0 &&
|
|
249
|
+
symbol.declarations.every((handle) => !own.has(handle.path))),
|
|
250
|
+
);
|
|
251
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The test files a derived matrix holds although no configuration's file list names them.
|
|
3
|
+
* The test runner compiles such a file with the options of the nearest compiler
|
|
4
|
+
* configuration at or above it, so the file joins that configuration's program as a file
|
|
5
|
+
* its list names, unless a `package.json` below that configuration's directory makes the
|
|
6
|
+
* file another package's, which its own test runner compiles.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { sourcePaths } from "../file-facts.ts";
|
|
10
|
+
import type { Host } from "../host.ts";
|
|
11
|
+
import { ancestors, dirnamePath, joinPath } from "../paths.ts";
|
|
12
|
+
import { bytewise } from "../text/compare.ts";
|
|
13
|
+
import { holdsManifest } from "../fs/manifest.ts";
|
|
14
|
+
import type { Configuration } from "./discover.ts";
|
|
15
|
+
import type { ProgramPlan } from "./plan.ts";
|
|
16
|
+
|
|
17
|
+
const PREFERRED = "/tsconfig.json";
|
|
18
|
+
|
|
19
|
+
/** The configurations of one directory in the order a file joins them: `tsconfig.json` first. */
|
|
20
|
+
function byPreference(a: string, b: string): number {
|
|
21
|
+
const first = a.endsWith(PREFERRED) ? 0 : 1;
|
|
22
|
+
const second = b.endsWith(PREFERRED) ? 0 : 1;
|
|
23
|
+
return first - second || bytewise(a, b);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Per configuration of `configurations`, the absolute paths of the test files that join it:
|
|
28
|
+
* each file below `root` a pattern of `patterns` names, that no configuration's file list
|
|
29
|
+
* holds, joins the configuration nearest at or above its directory when no `package.json`
|
|
30
|
+
* sits between them.
|
|
31
|
+
*/
|
|
32
|
+
export function joinedTestFiles(
|
|
33
|
+
host: Host,
|
|
34
|
+
root: string,
|
|
35
|
+
configurations: readonly Configuration[],
|
|
36
|
+
patterns: readonly RegExp[],
|
|
37
|
+
): ReadonlyMap<string, readonly string[]> {
|
|
38
|
+
const listed = new Set<string>();
|
|
39
|
+
const byDir = new Map<string, string[]>();
|
|
40
|
+
for (const { configFile, parsed } of configurations) {
|
|
41
|
+
parsed.fileNames.forEach((name) => listed.add(name));
|
|
42
|
+
const dir = dirnamePath(configFile);
|
|
43
|
+
byDir.set(dir, [...(byDir.get(dir) ?? []), configFile].sort(byPreference));
|
|
44
|
+
}
|
|
45
|
+
const joins = new Map<string, string[]>();
|
|
46
|
+
for (const path of sourcePaths(host, root)) {
|
|
47
|
+
const file = joinPath(root, path);
|
|
48
|
+
if (listed.has(file) || !patterns.some((pattern) => pattern.test(path))) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
for (const dir of ancestors(dirnamePath(file), root)) {
|
|
52
|
+
const [nearest] = byDir.get(dir) ?? [];
|
|
53
|
+
if (nearest !== undefined) {
|
|
54
|
+
joins.set(nearest, [...(joins.get(nearest) ?? []), file]);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
if (holdsManifest(host, dir)) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return joins;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The plans with each joined test file added to the configuration it joins: to a described
|
|
67
|
+
* program's root files, or to the file list of a configuration only the snapshot holds, which
|
|
68
|
+
* lists every file the configuration lists and the joined ones.
|
|
69
|
+
*/
|
|
70
|
+
export function joinedTests(
|
|
71
|
+
plans: readonly ProgramPlan[],
|
|
72
|
+
joins: ReadonlyMap<string, readonly string[]>,
|
|
73
|
+
): readonly ProgramPlan[] {
|
|
74
|
+
return plans.map((plan): ProgramPlan => {
|
|
75
|
+
const files = joins.get(plan.configFile);
|
|
76
|
+
const { build } = plan;
|
|
77
|
+
if (files === undefined) {
|
|
78
|
+
return plan;
|
|
79
|
+
}
|
|
80
|
+
if (build.kind === "program") {
|
|
81
|
+
return {
|
|
82
|
+
...plan,
|
|
83
|
+
build: {
|
|
84
|
+
kind: "program",
|
|
85
|
+
params: { ...build.params, rootFiles: [...(build.params.rootFiles ?? []), ...files] },
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const written = build.kind === "configuration" ? build.value : { extends: plan.configFile };
|
|
90
|
+
return {
|
|
91
|
+
...plan,
|
|
92
|
+
build: {
|
|
93
|
+
kind: "configuration",
|
|
94
|
+
value: { ...written, files: [...plan.parsed.fileNames, ...files], include: [] },
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { emittedFrom } from "./emit-map.ts";
|
|
10
|
-
import type { Host } from "
|
|
11
|
-
import { readManifest, type Manifest, type ManifestEntry } from "
|
|
12
|
-
import { joinPath, relativePath } from "
|
|
10
|
+
import type { Host } from "../host.ts";
|
|
11
|
+
import { readManifest, type Manifest, type ManifestEntry } from "../roots/manifest.ts";
|
|
12
|
+
import { joinPath, relativePath } from "../paths.ts";
|
|
13
13
|
import type { WorkspaceMember } from "./workspace.ts";
|
|
14
14
|
import type { WorkspaceResolver } from "./workspace-resolution.ts";
|
|
15
|
+
import { MANIFEST } from "../fs/manifest.ts";
|
|
15
16
|
|
|
16
17
|
/** The one character a subpath pattern of a manifest's `exports` holds. */
|
|
17
18
|
const SUBPATH_WILDCARD = "*";
|
|
@@ -84,8 +85,7 @@ export function memberEntries(
|
|
|
84
85
|
}
|
|
85
86
|
const manifest = readManifest(host, member.dir);
|
|
86
87
|
const where =
|
|
87
|
-
relativePath(targetRoot, joinPath(member.dir,
|
|
88
|
-
joinPath(member.dir, "package.json");
|
|
88
|
+
relativePath(targetRoot, joinPath(member.dir, MANIFEST)) ?? joinPath(member.dir, MANIFEST);
|
|
89
89
|
const kept = manifest.entries.flatMap((entry): ManifestEntry[] => {
|
|
90
90
|
const exported = entry.member.startsWith("exports");
|
|
91
91
|
if (member.private && exported) {
|