@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/load/plan.ts
ADDED
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import type { CreateSnapshotProgramParams } from "@typescript/native/sync";
|
|
2
|
+
import type { PartialConfig } from "../config.ts";
|
|
3
|
+
import {
|
|
4
|
+
readConventions,
|
|
5
|
+
type ConventionManifest,
|
|
6
|
+
type Conventions,
|
|
7
|
+
} from "../entries/conventions.ts";
|
|
8
|
+
import { holdsManifest, inInstalledPackages, MANIFEST, readManifestAt } from "../fs/manifest.ts";
|
|
9
|
+
import { gitIgnored } from "../git-ignore.ts";
|
|
10
|
+
import type { Host } from "../host.ts";
|
|
11
|
+
import {
|
|
12
|
+
packageEntries,
|
|
13
|
+
readManifest,
|
|
14
|
+
type Manifest,
|
|
15
|
+
type ManifestEntry,
|
|
16
|
+
} from "../roots/manifest.ts";
|
|
17
|
+
import {
|
|
18
|
+
ancestors,
|
|
19
|
+
dirnamePath,
|
|
20
|
+
joinPath,
|
|
21
|
+
normalizePath,
|
|
22
|
+
relativePath,
|
|
23
|
+
resolvePath,
|
|
24
|
+
} from "../paths.ts";
|
|
25
|
+
import type { Scope } from "../scope.ts";
|
|
26
|
+
import type { Engine, ProgramBuild } from "../session.ts";
|
|
27
|
+
import { bytewise } from "../text/compare.ts";
|
|
28
|
+
import { globExpression } from "../text/glob.ts";
|
|
29
|
+
import {
|
|
30
|
+
consumerWithoutSources,
|
|
31
|
+
discoverProjects,
|
|
32
|
+
isTargetConfiguration,
|
|
33
|
+
targetWithoutSources,
|
|
34
|
+
type Configuration,
|
|
35
|
+
type Discovery,
|
|
36
|
+
type LoadedConsumer,
|
|
37
|
+
type Parsed,
|
|
38
|
+
} from "./discover.ts";
|
|
39
|
+
import { FailureExit } from "../failure.ts";
|
|
40
|
+
import {
|
|
41
|
+
bundlingManifests,
|
|
42
|
+
candidateFiles,
|
|
43
|
+
formedGroups,
|
|
44
|
+
formedPrograms,
|
|
45
|
+
packageOf,
|
|
46
|
+
} from "./synthesize.ts";
|
|
47
|
+
import { joinedTestFiles, joinedTests } from "./test-joins.ts";
|
|
48
|
+
import { testGlobals } from "./test-globals.ts";
|
|
49
|
+
import { findWorkspace, withFormed, type ParsedLayout, type Workspace } from "./workspace.ts";
|
|
50
|
+
import { workspacePrograms, writtenConfiguration, writtenFileOf } from "./workspace-programs.ts";
|
|
51
|
+
import { workspaceResolver } from "./workspace-resolution.ts";
|
|
52
|
+
import { layoutOf, workspaceRun, type WorkspaceRun } from "./workspace-run.ts";
|
|
53
|
+
|
|
54
|
+
export type CompilerOptions = Parsed["options"];
|
|
55
|
+
|
|
56
|
+
/** How the snapshot builds one configuration. */
|
|
57
|
+
export type Build =
|
|
58
|
+
/** The project the compiler opens for the configuration as it stands. */
|
|
59
|
+
| { readonly kind: "project" }
|
|
60
|
+
| { readonly kind: "program"; readonly params: CreateSnapshotProgramParams }
|
|
61
|
+
/** A configuration only the snapshot holds, which extends the one it stands for. */
|
|
62
|
+
| { readonly kind: "configuration"; readonly value: Readonly<Record<string, unknown>> };
|
|
63
|
+
|
|
64
|
+
/** One configuration of the run and how the snapshot builds it. */
|
|
65
|
+
export interface ProgramPlan extends Configuration {
|
|
66
|
+
/** The options the program is built with, the parse's own with `paths` read as {@link baseUrlPaths} states. */
|
|
67
|
+
readonly options: CompilerOptions;
|
|
68
|
+
readonly build: Build;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The manifests the run reads, each once, and what they decide before any project opens. */
|
|
72
|
+
interface PackageSet {
|
|
73
|
+
/** The target's own manifest, its targets read back to source where the target is a member. */
|
|
74
|
+
readonly manifest: Manifest;
|
|
75
|
+
/** The directory of every workspace member, absolute, in the workspace's order. */
|
|
76
|
+
readonly members: readonly string[];
|
|
77
|
+
/** The directory of every nested package, absolute, in path order. */
|
|
78
|
+
readonly nested: readonly string[];
|
|
79
|
+
/** The entry points the other members' and the nested packages' manifests name. */
|
|
80
|
+
readonly entries: readonly ManifestEntry[];
|
|
81
|
+
/** The directories of the members whose manifest is not private. */
|
|
82
|
+
readonly published: ReadonlySet<string>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The workspace one consumer sits in, or the fault of a declaration that cannot be read,
|
|
87
|
+
* which ends the run only where an import's membership depends on it.
|
|
88
|
+
*/
|
|
89
|
+
type ConsumerWorkspace = { readonly workspace: Workspace | undefined } | { readonly fault: string };
|
|
90
|
+
|
|
91
|
+
/** What a run opens and how it builds each program, decided before the snapshot. */
|
|
92
|
+
export interface RunPlan {
|
|
93
|
+
readonly discovery: Discovery;
|
|
94
|
+
readonly plans: readonly ProgramPlan[];
|
|
95
|
+
readonly packages: PackageSet;
|
|
96
|
+
/** The convention rows applied per package of {@link PackageSet}. */
|
|
97
|
+
readonly conventions: Conventions;
|
|
98
|
+
readonly workspace: WorkspaceRun | undefined;
|
|
99
|
+
/** The workspace each consumer sits in, by its directory, read from its own root. */
|
|
100
|
+
readonly consumerWorkspaces: ReadonlyMap<string, ConsumerWorkspace>;
|
|
101
|
+
/** The target root, absolute. */
|
|
102
|
+
readonly root: string;
|
|
103
|
+
/**
|
|
104
|
+
* The output and declaration directories of every configuration file of the run, absolute,
|
|
105
|
+
* whose paths name build output: no formed program's candidate lies below one, and no relative
|
|
106
|
+
* specifier of a configuration that does not check its JavaScript naming one is noted.
|
|
107
|
+
*/
|
|
108
|
+
readonly outputs: readonly string[];
|
|
109
|
+
/** The inputs the run could not read, in the order it met them. */
|
|
110
|
+
readonly unread: readonly UnreadInput[];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** One input the run could not read, which the error stream names. */
|
|
114
|
+
export type UnreadInput =
|
|
115
|
+
/**
|
|
116
|
+
* A `package.json` that does not parse, or cannot be read with the read's error as `reason`,
|
|
117
|
+
* whose group's manifest facts go unanswered.
|
|
118
|
+
*/
|
|
119
|
+
| {
|
|
120
|
+
readonly kind: "manifest";
|
|
121
|
+
readonly configFile: string;
|
|
122
|
+
readonly manifest: string;
|
|
123
|
+
readonly reason: string | undefined;
|
|
124
|
+
}
|
|
125
|
+
/** An ignore file that cannot be read, which then ignores nothing. */
|
|
126
|
+
| { readonly kind: "ignore-file"; readonly path: string; readonly reason: string };
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The `paths` one configuration's resolved options map under the compilers before version
|
|
130
|
+
* 7, each target absolute: a target is read against the effective `baseUrl`, and a specifier
|
|
131
|
+
* no other pattern maps is looked up below it. Undefined where no `baseUrl` is set, so the
|
|
132
|
+
* options' own `paths` stand. Version 7 reads no `baseUrl`:
|
|
133
|
+
* https://github.com/microsoft/TypeScript/issues/62207
|
|
134
|
+
*/
|
|
135
|
+
export function baseUrlPaths(options: CompilerOptions): Record<string, string[]> | undefined {
|
|
136
|
+
const baseUrl: unknown = Reflect.get(options, "baseUrl");
|
|
137
|
+
if (typeof baseUrl !== "string") {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
return Object.fromEntries(
|
|
141
|
+
Object.entries({ "*": ["*"], ...options.paths }).map(([key, targets]) => [
|
|
142
|
+
key,
|
|
143
|
+
targets.map((target) => resolvePath(baseUrl, target)),
|
|
144
|
+
]),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function planned(configuration: Configuration): ProgramPlan {
|
|
149
|
+
const { options } = configuration.parsed;
|
|
150
|
+
if (configuration.written !== undefined) {
|
|
151
|
+
return {
|
|
152
|
+
...configuration,
|
|
153
|
+
options,
|
|
154
|
+
build: { kind: "configuration", value: configuration.written },
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const paths = baseUrlPaths(options);
|
|
158
|
+
return {
|
|
159
|
+
...configuration,
|
|
160
|
+
options: paths === undefined ? options : { ...options, paths },
|
|
161
|
+
build:
|
|
162
|
+
paths === undefined
|
|
163
|
+
? { kind: "project" }
|
|
164
|
+
: {
|
|
165
|
+
kind: "configuration",
|
|
166
|
+
value: { extends: configuration.configFile, compilerOptions: { paths } },
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* The nested packages of a run: each directory below the target root, in no `node_modules`
|
|
173
|
+
* directory and none of `known`, that holds a `package.json` and lies at or above one of
|
|
174
|
+
* `files`, in path order.
|
|
175
|
+
*/
|
|
176
|
+
function nestedPackageDirs(
|
|
177
|
+
host: Host,
|
|
178
|
+
targetRoot: string,
|
|
179
|
+
files: Iterable<string>,
|
|
180
|
+
known: ReadonlySet<string>,
|
|
181
|
+
): readonly string[] {
|
|
182
|
+
const seen = new Set<string>();
|
|
183
|
+
const found: string[] = [];
|
|
184
|
+
for (const file of files) {
|
|
185
|
+
for (const dir of ancestors(dirnamePath(file), targetRoot)) {
|
|
186
|
+
if (seen.has(dir) || relativePath(targetRoot, dir) === undefined) {
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
seen.add(dir);
|
|
190
|
+
const below = relativePath(targetRoot, dir) ?? "";
|
|
191
|
+
if (!inInstalledPackages(below) && !known.has(dir) && holdsManifest(host, dir)) {
|
|
192
|
+
found.push(dir);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return found.sort(bytewise);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* The manifests conventions are applied from below `root`: its own, then each member's and
|
|
201
|
+
* each nested package's, each once.
|
|
202
|
+
*/
|
|
203
|
+
function conventionManifests(
|
|
204
|
+
host: Host,
|
|
205
|
+
root: string,
|
|
206
|
+
members: readonly string[],
|
|
207
|
+
nested: readonly string[],
|
|
208
|
+
): readonly ConventionManifest[] {
|
|
209
|
+
const found = new Map<string, ConventionManifest>();
|
|
210
|
+
if (holdsManifest(host, root)) {
|
|
211
|
+
found.set(root, { dir: root, path: MANIFEST });
|
|
212
|
+
}
|
|
213
|
+
for (const [dirs, isNested] of [
|
|
214
|
+
[members, false],
|
|
215
|
+
[nested, true],
|
|
216
|
+
] as const) {
|
|
217
|
+
for (const dir of dirs) {
|
|
218
|
+
const below = relativePath(root, dir);
|
|
219
|
+
if (below !== undefined && !found.has(dir)) {
|
|
220
|
+
found.set(dir, { dir, path: `${below}/${MANIFEST}`, nested: isNested });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return [...found.values()];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The workspace one consumer sits in, read from its own root with `parse` reading its members'
|
|
229
|
+
* configurations, the target's reused, and any other given the programs of `formed` as
|
|
230
|
+
* {@link withFormed} does.
|
|
231
|
+
*/
|
|
232
|
+
function consumerWorkspace(
|
|
233
|
+
host: Host,
|
|
234
|
+
consumer: LoadedConsumer,
|
|
235
|
+
target: Workspace | undefined,
|
|
236
|
+
parse: (configFile: string) => ParsedLayout | undefined,
|
|
237
|
+
formed: ReadonlyMap<string, readonly ParsedLayout[]>,
|
|
238
|
+
): ConsumerWorkspace {
|
|
239
|
+
try {
|
|
240
|
+
const found = findWorkspace(host, consumer.path, parse, target);
|
|
241
|
+
return {
|
|
242
|
+
workspace: found === undefined || found === target ? found : withFormed(host, found, formed),
|
|
243
|
+
};
|
|
244
|
+
} catch (error: unknown) {
|
|
245
|
+
if (!(error instanceof FailureExit)) {
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
return { fault: error.failures[0].detail };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* How the snapshot builds each program formed for a consumer that sits in a workspace, its
|
|
254
|
+
* member imports read from source as the target's are. A consumer's configuration read from a
|
|
255
|
+
* file resolves a member through what is installed, as the compiler does.
|
|
256
|
+
*/
|
|
257
|
+
function consumerPrograms(
|
|
258
|
+
engine: Engine,
|
|
259
|
+
host: Host,
|
|
260
|
+
plans: readonly ProgramPlan[],
|
|
261
|
+
places: ReadonlyMap<string, ConsumerWorkspace>,
|
|
262
|
+
): ReadonlyMap<string, Exclude<Build, { readonly kind: "project" }>> {
|
|
263
|
+
const byRoot = new Map<string, { workspace: Workspace; plans: ProgramPlan[] }>();
|
|
264
|
+
for (const plan of plans) {
|
|
265
|
+
const place = plan.consumer === undefined ? undefined : places.get(plan.consumer.path);
|
|
266
|
+
if (plan.written === undefined || place === undefined || !("workspace" in place)) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const { workspace } = place;
|
|
270
|
+
if (workspace !== undefined) {
|
|
271
|
+
const held = byRoot.get(workspace.root) ?? { workspace, plans: [] };
|
|
272
|
+
held.plans.push(plan);
|
|
273
|
+
byRoot.set(workspace.root, held);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return new Map(
|
|
277
|
+
[...byRoot.values()].flatMap(({ workspace, plans: held }) => [
|
|
278
|
+
...workspacePrograms(engine, host, held, workspaceResolver(host, workspace)).programs,
|
|
279
|
+
]),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function outputsOf({ parsed }: Configuration): readonly string[] {
|
|
284
|
+
return [parsed.options.outDir, parsed.options.declarationDir].filter((dir) => dir !== undefined);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* The plan of one run: the configurations discovery names and the programs formed for the
|
|
289
|
+
* JavaScript files none lists, each built through the steps in order (the `baseUrl` paths,
|
|
290
|
+
* the workspace members read from source, the test runner's globals, the joined test files),
|
|
291
|
+
* the package set and the convention rows. A formed program's files wait for the joins and
|
|
292
|
+
* the rows, and its module system is fixed before any workspace round reads it. A nested
|
|
293
|
+
* package is one at or above a file a target configuration lists, joins or is formed over.
|
|
294
|
+
*/
|
|
295
|
+
export function planRun(engine: Engine, host: Host, scope: Scope, config: PartialConfig): RunPlan {
|
|
296
|
+
const discovery = discoverProjects(engine, host, scope, config.analysis.configurations);
|
|
297
|
+
const root = resolvePath(host.workingDirectory(), scope.target.path);
|
|
298
|
+
const parse = (fileName: string, text: string) => engine.parseSourceFile(fileName, text);
|
|
299
|
+
const disabled = config.ts.disabled_conventions;
|
|
300
|
+
const outputs = discovery.configurations.flatMap(outputsOf);
|
|
301
|
+
const unread: UnreadInput[] = [];
|
|
302
|
+
const ignoredBelow = (dir: string): ((path: string) => boolean) =>
|
|
303
|
+
gitIgnored(host, dir, (path, reason) => {
|
|
304
|
+
if (!unread.some((one) => one.kind === "ignore-file" && one.path === path)) {
|
|
305
|
+
unread.push({ kind: "ignore-file", path, reason });
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
// Before any target step, so a consumer's failure is the one named, as discoverProjects orders them.
|
|
309
|
+
const consumerFormed = discovery.unconfigured.flatMap((consumer) => {
|
|
310
|
+
const consumerRoot = resolvePath(host.workingDirectory(), consumer.path);
|
|
311
|
+
const files = candidateFiles(host, consumerRoot, {
|
|
312
|
+
covered: new Set(),
|
|
313
|
+
outputs,
|
|
314
|
+
ignored: ignoredBelow(consumerRoot),
|
|
315
|
+
});
|
|
316
|
+
const rows = readConventions(
|
|
317
|
+
host,
|
|
318
|
+
parse,
|
|
319
|
+
conventionManifests(
|
|
320
|
+
host,
|
|
321
|
+
consumerRoot,
|
|
322
|
+
[],
|
|
323
|
+
[...new Set(files.map((file) => packageOf(host, consumerRoot, file)))].filter(
|
|
324
|
+
(dir) => dir !== consumerRoot,
|
|
325
|
+
),
|
|
326
|
+
),
|
|
327
|
+
disabled,
|
|
328
|
+
);
|
|
329
|
+
const programs = formedPrograms(engine, host, formedGroups(host, consumerRoot, files, rows), {
|
|
330
|
+
root: consumerRoot,
|
|
331
|
+
origin: "consumer",
|
|
332
|
+
bundling: bundlingManifests(rows),
|
|
333
|
+
idOf: (path) => path ?? consumerRoot,
|
|
334
|
+
});
|
|
335
|
+
if (programs.length === 0) {
|
|
336
|
+
throw consumerWithoutSources(consumer.path);
|
|
337
|
+
}
|
|
338
|
+
return programs.map((one) => ({ ...one, configuration: { ...one.configuration, consumer } }));
|
|
339
|
+
});
|
|
340
|
+
const readTargets = discovery.configurations.filter(isTargetConfiguration);
|
|
341
|
+
const manifest = readManifest(host, scope.target.path);
|
|
342
|
+
const found = findWorkspace(host, root, (configFile) => layoutOf(engine, configFile));
|
|
343
|
+
const joins =
|
|
344
|
+
discovery.mode === "derived"
|
|
345
|
+
? joinedTestFiles(host, root, readTargets, config.ts.test_files.map(globExpression))
|
|
346
|
+
: new Map<string, readonly string[]>();
|
|
347
|
+
const targetIgnored = ignoredBelow(root);
|
|
348
|
+
const covered = new Set([
|
|
349
|
+
...readTargets.flatMap(({ parsed }) => parsed.fileNames),
|
|
350
|
+
...[...joins.values()].flat(),
|
|
351
|
+
]);
|
|
352
|
+
const trees = discovery.targets.flatMap((target) => {
|
|
353
|
+
if (target.kind === "configuration") {
|
|
354
|
+
return [];
|
|
355
|
+
}
|
|
356
|
+
const dir = target.kind === "derived" ? root : dirnamePath(target.manifest);
|
|
357
|
+
const files = candidateFiles(host, dir, { covered, outputs, ignored: targetIgnored });
|
|
358
|
+
return [
|
|
359
|
+
{
|
|
360
|
+
target,
|
|
361
|
+
dir,
|
|
362
|
+
files:
|
|
363
|
+
target.kind === "derived"
|
|
364
|
+
? files
|
|
365
|
+
: files.filter((file) => packageOf(host, dir, file) === dir),
|
|
366
|
+
},
|
|
367
|
+
];
|
|
368
|
+
});
|
|
369
|
+
const members = found?.members.map((member) => member.dir) ?? [];
|
|
370
|
+
const nested = nestedPackageDirs(
|
|
371
|
+
host,
|
|
372
|
+
normalizePath(root),
|
|
373
|
+
[
|
|
374
|
+
...readTargets.flatMap((plan) => [
|
|
375
|
+
plan.configFile,
|
|
376
|
+
...plan.parsed.fileNames,
|
|
377
|
+
...(joins.get(plan.configFile) ?? []),
|
|
378
|
+
]),
|
|
379
|
+
...trees.flatMap(({ files }) => files),
|
|
380
|
+
],
|
|
381
|
+
new Set(members),
|
|
382
|
+
);
|
|
383
|
+
const conventions = readConventions(
|
|
384
|
+
host,
|
|
385
|
+
parse,
|
|
386
|
+
conventionManifests(host, root, members, nested),
|
|
387
|
+
disabled,
|
|
388
|
+
);
|
|
389
|
+
const bundling = bundlingManifests(conventions);
|
|
390
|
+
const formedFor = new Map(
|
|
391
|
+
trees.map(({ target, dir, files }) => {
|
|
392
|
+
const groups = formedGroups(host, dir, files, conventions);
|
|
393
|
+
const programs = formedPrograms(
|
|
394
|
+
engine,
|
|
395
|
+
host,
|
|
396
|
+
target.kind === "declared"
|
|
397
|
+
? [groups[0] ?? { dir, manifest: readManifestAt(host, dir), files: [] }]
|
|
398
|
+
: groups,
|
|
399
|
+
{
|
|
400
|
+
root,
|
|
401
|
+
origin: target.kind,
|
|
402
|
+
bundling,
|
|
403
|
+
idOf: (path) =>
|
|
404
|
+
target.kind === "declared"
|
|
405
|
+
? target.id
|
|
406
|
+
: path === undefined
|
|
407
|
+
? "."
|
|
408
|
+
: (relativePath(root, path) ?? path),
|
|
409
|
+
},
|
|
410
|
+
);
|
|
411
|
+
return [target, programs] as const;
|
|
412
|
+
}),
|
|
413
|
+
);
|
|
414
|
+
const targetFormed = [...formedFor.values()].flat();
|
|
415
|
+
if (readTargets.length + targetFormed.length === 0 && discovery.notBuilt.length === 0) {
|
|
416
|
+
throw targetWithoutSources(scope.target.path);
|
|
417
|
+
}
|
|
418
|
+
for (const { configuration, group } of [...targetFormed, ...consumerFormed]) {
|
|
419
|
+
if (group.manifest.kind === "malformed" || group.manifest.kind === "unread") {
|
|
420
|
+
unread.push({
|
|
421
|
+
kind: "manifest",
|
|
422
|
+
configFile: configuration.configFile,
|
|
423
|
+
manifest: joinPath(group.dir, MANIFEST),
|
|
424
|
+
reason: group.manifest.kind === "unread" ? group.manifest.reason : undefined,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
let plans: readonly ProgramPlan[] = [
|
|
429
|
+
...discovery.targets.flatMap((target) =>
|
|
430
|
+
target.kind === "configuration"
|
|
431
|
+
? [target.configuration]
|
|
432
|
+
: (formedFor.get(target) ?? []).map(({ configuration }) => configuration),
|
|
433
|
+
),
|
|
434
|
+
...discovery.configurations.filter((one) => !isTargetConfiguration(one)),
|
|
435
|
+
...consumerFormed.map(({ configuration }) => configuration),
|
|
436
|
+
].map(planned);
|
|
437
|
+
const formedLayouts = new Map<string, ParsedLayout[]>();
|
|
438
|
+
for (const { configuration, group } of [...targetFormed, ...consumerFormed]) {
|
|
439
|
+
formedLayouts.set(group.dir, [
|
|
440
|
+
...(formedLayouts.get(group.dir) ?? []),
|
|
441
|
+
{ fileNames: configuration.parsed.fileNames },
|
|
442
|
+
]);
|
|
443
|
+
}
|
|
444
|
+
const workspace = workspaceRun(
|
|
445
|
+
engine,
|
|
446
|
+
host,
|
|
447
|
+
root,
|
|
448
|
+
plans.filter(isTargetConfiguration),
|
|
449
|
+
manifest,
|
|
450
|
+
found === undefined ? undefined : withFormed(host, found, formedLayouts),
|
|
451
|
+
);
|
|
452
|
+
const consumerWorkspaces = new Map(
|
|
453
|
+
discovery.consumers.map((consumer) => [
|
|
454
|
+
consumer.path,
|
|
455
|
+
consumerWorkspace(
|
|
456
|
+
host,
|
|
457
|
+
consumer,
|
|
458
|
+
workspace?.workspace,
|
|
459
|
+
discovery.unconfigured.includes(consumer)
|
|
460
|
+
? (configFile) => layoutOf(engine, configFile)
|
|
461
|
+
: () => undefined,
|
|
462
|
+
formedLayouts,
|
|
463
|
+
),
|
|
464
|
+
]),
|
|
465
|
+
);
|
|
466
|
+
const consumerBuilds = consumerPrograms(engine, host, plans, consumerWorkspaces);
|
|
467
|
+
plans = plans.map((plan) => {
|
|
468
|
+
const build = workspace?.programs.get(plan.configFile) ?? consumerBuilds.get(plan.configFile);
|
|
469
|
+
return build === undefined ? plan : { ...plan, build };
|
|
470
|
+
});
|
|
471
|
+
plans = testGlobals(host, parse, plans);
|
|
472
|
+
plans = joinedTests(plans, joins);
|
|
473
|
+
const packages: PackageSet = {
|
|
474
|
+
manifest: workspace?.manifest ?? manifest,
|
|
475
|
+
members,
|
|
476
|
+
nested,
|
|
477
|
+
entries: [...(workspace?.entries ?? []), ...packageEntries(host, normalizePath(root), nested)],
|
|
478
|
+
published: new Set(
|
|
479
|
+
(workspace?.entries ?? []).filter((entry) => entry.published).map((entry) => entry.dir),
|
|
480
|
+
),
|
|
481
|
+
};
|
|
482
|
+
return {
|
|
483
|
+
discovery,
|
|
484
|
+
plans,
|
|
485
|
+
packages,
|
|
486
|
+
conventions,
|
|
487
|
+
workspace,
|
|
488
|
+
consumerWorkspaces,
|
|
489
|
+
root,
|
|
490
|
+
outputs,
|
|
491
|
+
unread,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/** How the snapshot builds each planned configuration other than by opening its project. */
|
|
496
|
+
export function programBuilds(
|
|
497
|
+
host: Host,
|
|
498
|
+
plans: readonly ProgramPlan[],
|
|
499
|
+
): ReadonlyMap<string, ProgramBuild> {
|
|
500
|
+
const builds = new Map<string, ProgramBuild>();
|
|
501
|
+
const formed = new Set(
|
|
502
|
+
plans.filter((plan) => plan.written !== undefined).map((plan) => plan.configFile),
|
|
503
|
+
);
|
|
504
|
+
for (const plan of plans) {
|
|
505
|
+
const { configFile, build } = plan;
|
|
506
|
+
if (build.kind === "program") {
|
|
507
|
+
builds.set(configFile, build);
|
|
508
|
+
} else if (build.kind === "configuration") {
|
|
509
|
+
builds.set(configFile, writtenConfiguration(writtenFileOf(host, plan, formed), build.value));
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return builds;
|
|
513
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The module specifiers of the JavaScript files a configuration does not check, read for what
|
|
3
|
+
* the compiler leaves unresolved. Unchecked JavaScript reports no unfound module, and a
|
|
4
|
+
* JavaScript file may name a file that is absent on purpose, so an unresolved one is no failure
|
|
5
|
+
* of the program: a relative one is noted, and only a configuration whose imported dependencies
|
|
6
|
+
* are none of them installed fails, because its program is not the one the project runs.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
isBinaryExpression,
|
|
11
|
+
isCallExpression,
|
|
12
|
+
isParenthesizedExpression,
|
|
13
|
+
isStringLiteralLikeNode,
|
|
14
|
+
isTryStatement,
|
|
15
|
+
SyntaxKind,
|
|
16
|
+
type Node,
|
|
17
|
+
type SourceFile,
|
|
18
|
+
type StringLiteralLikeNode,
|
|
19
|
+
} from "@typescript/native/ast";
|
|
20
|
+
import type { Program } from "@typescript/native/sync";
|
|
21
|
+
import { packageOfSpecifier } from "../dependencies.ts";
|
|
22
|
+
import type { Failure } from "../failure.ts";
|
|
23
|
+
import { readManifestAt } from "../fs/manifest.ts";
|
|
24
|
+
import type { Host } from "../host.ts";
|
|
25
|
+
import { JAVASCRIPT_FILE } from "../javascript-file.ts";
|
|
26
|
+
import {
|
|
27
|
+
ancestors,
|
|
28
|
+
dirnamePath,
|
|
29
|
+
isRelativeSpecifier,
|
|
30
|
+
relativePath,
|
|
31
|
+
resolvePath,
|
|
32
|
+
} from "../paths.ts";
|
|
33
|
+
import { renderPosition, type Position } from "../position.ts";
|
|
34
|
+
import { batched, type Engine, type ProjectView } from "../session.ts";
|
|
35
|
+
import { dependencySpecifiers } from "./module-lookup.ts";
|
|
36
|
+
|
|
37
|
+
/** One relative specifier of a JavaScript file that resolves to no file. */
|
|
38
|
+
export interface UnresolvedSpecifier {
|
|
39
|
+
readonly specifier: string;
|
|
40
|
+
readonly position: Position;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** What the specifiers of one project's unchecked JavaScript files say. */
|
|
44
|
+
interface SpecifierReading {
|
|
45
|
+
readonly unresolved: readonly UnresolvedSpecifier[];
|
|
46
|
+
/** The failure of a project whose imported dependencies are none of them installed. */
|
|
47
|
+
readonly uninstalled: Failure | undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether one specifier is loaded optionally: written inside a `try` block, or as a call whose
|
|
52
|
+
* result an `||` or a `??` falls back from, so the program is written for its absence.
|
|
53
|
+
*/
|
|
54
|
+
function optional(node: StringLiteralLikeNode): boolean {
|
|
55
|
+
const call = node.parent;
|
|
56
|
+
let operand: Node = call;
|
|
57
|
+
let parent = call.parent as Node | undefined;
|
|
58
|
+
while (parent !== undefined && isParenthesizedExpression(parent)) {
|
|
59
|
+
operand = parent;
|
|
60
|
+
parent = parent.parent;
|
|
61
|
+
}
|
|
62
|
+
if (
|
|
63
|
+
isCallExpression(call) &&
|
|
64
|
+
parent !== undefined &&
|
|
65
|
+
isBinaryExpression(parent) &&
|
|
66
|
+
parent.left === operand &&
|
|
67
|
+
(parent.operatorToken.kind === SyntaxKind.BarBarToken ||
|
|
68
|
+
parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken)
|
|
69
|
+
) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
for (let at: Node | undefined = node; at !== undefined; at = at.parent as Node | undefined) {
|
|
73
|
+
const above = at.parent as Node | undefined;
|
|
74
|
+
if (above !== undefined && isTryStatement(above) && above.tryBlock === at) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Whether a manifest at or above `dir`, no higher than `root`, declares the package `name`. A
|
|
83
|
+
* manifest that does not parse or cannot be read ends the search, because what it declares is
|
|
84
|
+
* unanswered and a manifest above it is another package's.
|
|
85
|
+
*/
|
|
86
|
+
function declared(host: Host, dir: string, root: string, name: string): boolean {
|
|
87
|
+
for (const at of ancestors(dir, root)) {
|
|
88
|
+
const read = readManifestAt(host, at);
|
|
89
|
+
if (read.kind === "malformed" || read.kind === "unread") {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (read.kind === "read" && dependencySpecifiers(read.manifest, name).length > 0) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** What a project's specifiers are read against. */
|
|
100
|
+
interface SpecifierContext {
|
|
101
|
+
/** Whether the project's options check its JavaScript files, which then report their own. */
|
|
102
|
+
readonly checked: boolean;
|
|
103
|
+
/** The target root, absolute. */
|
|
104
|
+
readonly root: string;
|
|
105
|
+
/** The directories a configuration of the run emits into, whose paths name build output. */
|
|
106
|
+
readonly outputs: readonly string[];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The specifiers of every JavaScript file of `project`, where its options do not check
|
|
111
|
+
* JavaScript, each asked of the compiler in batched round trips. A relative one naming a path
|
|
112
|
+
* below one of the run's output directories names build output, which a build writes later.
|
|
113
|
+
*/
|
|
114
|
+
export function readSpecifiers<Brand>(
|
|
115
|
+
engine: Engine,
|
|
116
|
+
host: Host,
|
|
117
|
+
project: ProjectView<Brand>,
|
|
118
|
+
{ checked, root, outputs }: SpecifierContext,
|
|
119
|
+
): SpecifierReading {
|
|
120
|
+
if (checked) {
|
|
121
|
+
return { unresolved: [], uninstalled: undefined };
|
|
122
|
+
}
|
|
123
|
+
const usages: { readonly file: SourceFile; readonly node: StringLiteralLikeNode }[] = [];
|
|
124
|
+
for (const file of project.ownSourceFiles()) {
|
|
125
|
+
if (JAVASCRIPT_FILE.test(file.fileName)) {
|
|
126
|
+
for (const node of file.imports) {
|
|
127
|
+
if (isStringLiteralLikeNode(node) && !optional(node)) {
|
|
128
|
+
usages.push({ file, node });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const answers = batched<
|
|
134
|
+
(typeof usages)[number],
|
|
135
|
+
ReturnType<Program["getResolvedModuleFromModuleSpecifier"]>
|
|
136
|
+
>(engine, usages, ({ file, node }) =>
|
|
137
|
+
project.program.getResolvedModuleFromModuleSpecifier.gen(node, file.fileName),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const unresolved: UnresolvedSpecifier[] = [];
|
|
141
|
+
let missing: { readonly file: SourceFile; readonly node: StringLiteralLikeNode } | undefined;
|
|
142
|
+
let installed = false;
|
|
143
|
+
for (const [at, usage] of usages.entries()) {
|
|
144
|
+
const resolved = (answers[at]?.resolvedFileName ?? "") !== "";
|
|
145
|
+
const specifier = usage.node.text;
|
|
146
|
+
const name = packageOfSpecifier(specifier);
|
|
147
|
+
if (isRelativeSpecifier(specifier)) {
|
|
148
|
+
const named = resolvePath(dirnamePath(usage.file.fileName), specifier);
|
|
149
|
+
if (!resolved && !outputs.some((dir) => relativePath(dir, named) !== undefined)) {
|
|
150
|
+
unresolved.push({
|
|
151
|
+
specifier,
|
|
152
|
+
position: renderPosition(usage.file, root, usage.node.getStart()),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
} else if (name !== undefined && declared(host, dirnamePath(usage.file.fileName), root, name)) {
|
|
156
|
+
installed ||= resolved;
|
|
157
|
+
missing ??= resolved ? undefined : usage;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (installed || missing === undefined) {
|
|
161
|
+
return { unresolved, uninstalled: undefined };
|
|
162
|
+
}
|
|
163
|
+
const { path, line } = renderPosition(missing.file, root, missing.node.getStart());
|
|
164
|
+
return {
|
|
165
|
+
unresolved,
|
|
166
|
+
uninstalled: {
|
|
167
|
+
failureClass: "missing-module",
|
|
168
|
+
detail: `${path}:${String(line)}: ${path} imports ${JSON.stringify(missing.node.text)}, a declared dependency, and no dependency the configuration's JavaScript files import is installed: run the package manager's install`,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|