@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/entry-points.ts
DELETED
|
@@ -1,687 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The files a tool or the platform enters without any import naming them: the
|
|
3
|
-
* configuration files a tool loads by their file name and the files their strings
|
|
4
|
-
* name, the test files the runner executes, and a worker a call addresses by a string
|
|
5
|
-
* literal.
|
|
6
|
-
*
|
|
7
|
-
* Each rule is read from the program and nothing else: a file name the tool
|
|
8
|
-
* itself looks for, a literal written in a configuration file, or a literal
|
|
9
|
-
* argument of a call the checker resolves to the platform's own declaration. A
|
|
10
|
-
* value that is not a literal is not evaluated and not guessed, so a file it would
|
|
11
|
-
* have named is entered by nothing here.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
isArrayLiteralExpression,
|
|
16
|
-
isAsExpression,
|
|
17
|
-
isBinaryExpression,
|
|
18
|
-
isCallExpression,
|
|
19
|
-
isExportAssignment,
|
|
20
|
-
isIdentifier,
|
|
21
|
-
isMetaProperty,
|
|
22
|
-
isNewExpression,
|
|
23
|
-
isNoSubstitutionTemplateLiteral,
|
|
24
|
-
isObjectLiteralExpression,
|
|
25
|
-
isParenthesizedExpression,
|
|
26
|
-
isPropertyAccessExpression,
|
|
27
|
-
isPropertyAssignment,
|
|
28
|
-
isSatisfiesExpression,
|
|
29
|
-
isStringLiteral,
|
|
30
|
-
isTemplateExpression,
|
|
31
|
-
SyntaxKind,
|
|
32
|
-
type Node,
|
|
33
|
-
type SourceFile,
|
|
34
|
-
} from "@typescript/native/ast";
|
|
35
|
-
import { SymbolFlags } from "@typescript/native/sync";
|
|
36
|
-
import {
|
|
37
|
-
configurationFiles,
|
|
38
|
-
filesNamedBy,
|
|
39
|
-
moduleStrings,
|
|
40
|
-
type ParseFile,
|
|
41
|
-
} from "./configuration-files.ts";
|
|
42
|
-
import type { Selected } from "./conventions.ts";
|
|
43
|
-
import { globExpression } from "./glob.ts";
|
|
44
|
-
import type { Host } from "./host.ts";
|
|
45
|
-
import { htmlEntries } from "./html-entries.ts";
|
|
46
|
-
import { documentEntries } from "./mdx-entries.ts";
|
|
47
|
-
import { dirnamePath, relativePath, resolvePath } from "./paths.ts";
|
|
48
|
-
import { UNANSWERED } from "./query.ts";
|
|
49
|
-
import type { ProjectView } from "./session.ts";
|
|
50
|
-
import type { SourceFiles } from "./source-files.ts";
|
|
51
|
-
import { workflowEntries } from "./workflow-steps.ts";
|
|
52
|
-
|
|
53
|
-
/** Which rule entered a file. */
|
|
54
|
-
export type EntryRule =
|
|
55
|
-
/** A configuration module, by the form of its name. */
|
|
56
|
-
| "configuration-file"
|
|
57
|
-
/** A file a relative string of a configuration module or a JSON configuration file names. */
|
|
58
|
-
| "configuration-string"
|
|
59
|
-
/** The test runner: its workspace configuration, its setup files and the test files. */
|
|
60
|
-
| "test-runner"
|
|
61
|
-
/** The test files below the browser-test runner's test directory. */
|
|
62
|
-
| "browser-tests"
|
|
63
|
-
/** A worker or service worker a call addresses by a string literal. */
|
|
64
|
-
| "worker"
|
|
65
|
-
/** A file a module script of an HTML file below the target root loads. */
|
|
66
|
-
| "html-entry"
|
|
67
|
-
/** A file a `run:` step of a workflow in the target root's `.github/workflows` names. */
|
|
68
|
-
| "workflow-step"
|
|
69
|
-
/**
|
|
70
|
-
* A file a load whose path is computed may name: below the directory the literal
|
|
71
|
-
* start of an `import()` or `require()` argument names, or matched by the literal
|
|
72
|
-
* glob of `import.meta.glob`.
|
|
73
|
-
*/
|
|
74
|
-
| "computed-import"
|
|
75
|
-
/** A file an import line of a Markdown or MDX document below the target root names. */
|
|
76
|
-
| "document-import";
|
|
77
|
-
|
|
78
|
-
/** One file a rule enters. */
|
|
79
|
-
interface EntryPoint {
|
|
80
|
-
readonly file: SourceFile;
|
|
81
|
-
readonly rule: EntryRule;
|
|
82
|
-
/**
|
|
83
|
-
* What named the file: the file-name convention the tool looks for, the test-file
|
|
84
|
-
* pattern that classified it, or the literal a configuration or a call writes.
|
|
85
|
-
*/
|
|
86
|
-
readonly source: string;
|
|
87
|
-
/**
|
|
88
|
-
* Whether what the file exports is read too. A tool loading a configuration reads
|
|
89
|
-
* its default export; a runtime executing a test file or a worker runs its top
|
|
90
|
-
* level and names none of its exports.
|
|
91
|
-
*/
|
|
92
|
-
readonly exports: boolean;
|
|
93
|
-
/** Where the file is entered for some of its exports only, their export names. */
|
|
94
|
-
readonly names?: readonly string[];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** One file-name convention: the stems a tool looks for, under each extension it loads. */
|
|
98
|
-
interface Convention {
|
|
99
|
-
readonly rule: EntryRule;
|
|
100
|
-
readonly stems: readonly string[];
|
|
101
|
-
readonly extensions: readonly string[];
|
|
102
|
-
/** Whether the file is a test-runner configuration whose setup files are read. */
|
|
103
|
-
readonly testRunner: boolean;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** The extensions the test runner and the browser-test runner load a configuration from. */
|
|
107
|
-
const MODULE_EXTENSIONS = ["js", "mjs", "cjs", "ts", "mts", "cts"] as const;
|
|
108
|
-
|
|
109
|
-
/** The tool file names the configuration form does not cover. */
|
|
110
|
-
const CONVENTIONS: readonly Convention[] = [
|
|
111
|
-
{
|
|
112
|
-
rule: "test-runner",
|
|
113
|
-
stems: ["vitest.workspace", "vitest.projects"],
|
|
114
|
-
extensions: MODULE_EXTENSIONS,
|
|
115
|
-
testRunner: true,
|
|
116
|
-
},
|
|
117
|
-
];
|
|
118
|
-
|
|
119
|
-
/** The stem of the browser-test runner's configuration, whose test directory is read. */
|
|
120
|
-
const BROWSER_TEST_CONFIG = "playwright.config";
|
|
121
|
-
|
|
122
|
-
/** The browser-test runner's own test-file pattern, which holds where a configuration names none. */
|
|
123
|
-
const BROWSER_TEST_MATCH = "**/*.{spec,test}.{js,ts,jsx,tsx,cjs,cts,cjsx,ctsx,mjs,mts,mjsx,mtsx}";
|
|
124
|
-
|
|
125
|
-
/** The members of a test-runner configuration's `test` object that name setup files. */
|
|
126
|
-
const SETUP_MEMBERS = ["setupFiles", "globalSetup"] as const;
|
|
127
|
-
|
|
128
|
-
/** A member that moves the directory every path of a test-runner configuration is read from. */
|
|
129
|
-
const ROOT_MEMBER = "root";
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* A URL reference's scheme. A reference with none that does not start with a solidus is
|
|
133
|
-
* relative, the bare name included: https://url.spec.whatwg.org/#relative-url-string
|
|
134
|
-
*/
|
|
135
|
-
const URL_SCHEME = /^[a-z][a-z\d+.-]*:/iu;
|
|
136
|
-
|
|
137
|
-
/** The constructors whose first argument addresses a worker script. */
|
|
138
|
-
const WORKER_CONSTRUCTORS: ReadonlySet<string> = new Set(["Worker", "SharedWorker"]);
|
|
139
|
-
|
|
140
|
-
/** The file's name, the last segment of its path. */
|
|
141
|
-
function basename(path: string): string {
|
|
142
|
-
return path.slice(path.lastIndexOf("/") + 1);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** The convention one file name is, with the spelling a root reports it by. */
|
|
146
|
-
function conventionOf(
|
|
147
|
-
name: string,
|
|
148
|
-
): { readonly convention: Convention; readonly spelled: string } | undefined {
|
|
149
|
-
for (const convention of CONVENTIONS) {
|
|
150
|
-
for (const stem of convention.stems) {
|
|
151
|
-
if (convention.extensions.some((ext) => name === `${stem}.${ext}`)) {
|
|
152
|
-
return { convention, spelled: `${stem}.*` };
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return undefined;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** The text a string literal or a template with no substitution denotes. */
|
|
160
|
-
function literalOf(node: Node | undefined): string | undefined {
|
|
161
|
-
if (node !== undefined && (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node))) {
|
|
162
|
-
return node.text;
|
|
163
|
-
}
|
|
164
|
-
return undefined;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/** The expression a wrapper that changes no value holds: parentheses and type assertions. */
|
|
168
|
-
function unwrapped(node: Node): Node {
|
|
169
|
-
let at = node;
|
|
170
|
-
while (isParenthesizedExpression(at) || isAsExpression(at) || isSatisfiesExpression(at)) {
|
|
171
|
-
at = at.expression;
|
|
172
|
-
}
|
|
173
|
-
return at;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* The object literals one configuration file's default export is written as: the
|
|
178
|
-
* literal itself, or each literal argument of the call it is, at any depth of calls.
|
|
179
|
-
* A default export written as anything else, a name or a computation, yields none,
|
|
180
|
-
* because its value is not in the file's text.
|
|
181
|
-
*/
|
|
182
|
-
function configObjects(file: SourceFile): readonly Node[] {
|
|
183
|
-
const found: Node[] = [];
|
|
184
|
-
const collect = (node: Node): void => {
|
|
185
|
-
const at = unwrapped(node);
|
|
186
|
-
if (isObjectLiteralExpression(at)) {
|
|
187
|
-
found.push(at);
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
if (isCallExpression(at)) {
|
|
191
|
-
for (const argument of at.arguments) {
|
|
192
|
-
collect(argument);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
for (const statement of file.statements) {
|
|
197
|
-
if (isExportAssignment(statement) && !statement.isExportEquals) {
|
|
198
|
-
collect(statement.expression);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return found;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* The value one member of an object literal is written with, when it is written as
|
|
206
|
-
* `name: value`, and undefined where the literal writes no such member.
|
|
207
|
-
*/
|
|
208
|
-
function memberOf(object: Node, name: string): Node | undefined {
|
|
209
|
-
if (!isObjectLiteralExpression(object)) {
|
|
210
|
-
return undefined;
|
|
211
|
-
}
|
|
212
|
-
for (const property of object.properties) {
|
|
213
|
-
if (
|
|
214
|
-
isPropertyAssignment(property) &&
|
|
215
|
-
isIdentifier(property.name) &&
|
|
216
|
-
property.name.text === name
|
|
217
|
-
) {
|
|
218
|
-
return property.initializer;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return undefined;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* The strings one member holds, when it is written as a literal or an array of
|
|
226
|
-
* literals. `undefined` is a value the text does not state.
|
|
227
|
-
*/
|
|
228
|
-
function literalsOf(value: Node): readonly string[] | undefined {
|
|
229
|
-
const at = unwrapped(value);
|
|
230
|
-
const single = literalOf(at);
|
|
231
|
-
if (single !== undefined) {
|
|
232
|
-
return [single];
|
|
233
|
-
}
|
|
234
|
-
if (!isArrayLiteralExpression(at)) {
|
|
235
|
-
return undefined;
|
|
236
|
-
}
|
|
237
|
-
const found: string[] = [];
|
|
238
|
-
for (const element of at.elements) {
|
|
239
|
-
const text = literalOf(unwrapped(element));
|
|
240
|
-
if (text === undefined) {
|
|
241
|
-
return undefined;
|
|
242
|
-
}
|
|
243
|
-
found.push(text);
|
|
244
|
-
}
|
|
245
|
-
return found;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Whether a literal is a relative URL reference, which is also how the test runner reads a
|
|
250
|
-
* setup file's path against its root.
|
|
251
|
-
*/
|
|
252
|
-
function isRelative(text: string): boolean {
|
|
253
|
-
return text !== "" && !text.startsWith("/") && !URL_SCHEME.test(text);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/** Whether a module specifier is relative, which a bare name is not: it names a package. */
|
|
257
|
-
function isModuleRelative(text: string): boolean {
|
|
258
|
-
return text.startsWith("./") || text.startsWith("../");
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/** A URL reference with its query and its fragment removed, which name no part of the file. */
|
|
262
|
-
function pathPart(text: string): string {
|
|
263
|
-
const cut = text.search(/[?#]/u);
|
|
264
|
-
return cut < 0 ? text : text.slice(0, cut);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/** The own files one relative literal names, read against a directory. */
|
|
268
|
-
function filesNamed(files: SourceFiles, dir: string, text: string): readonly SourceFile[] {
|
|
269
|
-
if (!isRelative(text)) {
|
|
270
|
-
return [];
|
|
271
|
-
}
|
|
272
|
-
return files.named(resolvePath(dir, pathPart(text)));
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/** Whether one file name is the browser-test runner's configuration. */
|
|
276
|
-
function isBrowserTestConfig(name: string): boolean {
|
|
277
|
-
return MODULE_EXTENSIONS.some((ext) => name === `${BROWSER_TEST_CONFIG}.${ext}`);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* The files the configuration files of one project enter: each configuration module,
|
|
282
|
-
* with what it exports, and each own file a relative string of a configuration module
|
|
283
|
-
* or a JSON configuration file names, read against that file's directory. A string at a
|
|
284
|
-
* selection key of an applied convention row names no file.
|
|
285
|
-
*/
|
|
286
|
-
function configurationEntries(
|
|
287
|
-
host: Host,
|
|
288
|
-
targetRoot: string,
|
|
289
|
-
files: SourceFiles,
|
|
290
|
-
parse: ParseFile | undefined,
|
|
291
|
-
selected: ReadonlyMap<string, Selected>,
|
|
292
|
-
): readonly EntryPoint[] {
|
|
293
|
-
const { modules, documents, outside } = configurationFiles(host, targetRoot, files, parse);
|
|
294
|
-
const found: EntryPoint[] = [];
|
|
295
|
-
const unselected = (file: SourceFile): readonly string[] => {
|
|
296
|
-
const starts = selected.get(file.fileName)?.starts;
|
|
297
|
-
return moduleStrings(file)
|
|
298
|
-
.filter((one) => starts?.has(one.node.getStart()) !== true)
|
|
299
|
-
.map((one) => one.text);
|
|
300
|
-
};
|
|
301
|
-
const unselectedIn = (path: string, texts: readonly string[]): readonly string[] => {
|
|
302
|
-
const left = [...(selected.get(path)?.texts ?? [])];
|
|
303
|
-
return texts.filter((text) => {
|
|
304
|
-
const at = left.indexOf(text);
|
|
305
|
-
if (at < 0) {
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
308
|
-
left.splice(at, 1);
|
|
309
|
-
return false;
|
|
310
|
-
});
|
|
311
|
-
};
|
|
312
|
-
const strings = (dir: string, texts: readonly string[]): void => {
|
|
313
|
-
for (const text of texts) {
|
|
314
|
-
for (const file of filesNamedBy(files, dir, text)) {
|
|
315
|
-
found.push({ file, rule: "configuration-string", source: text, exports: true });
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
for (const { file, form } of modules) {
|
|
320
|
-
found.push({ file, rule: "configuration-file", source: form, exports: true });
|
|
321
|
-
strings(dirnamePath(file.fileName), unselected(file));
|
|
322
|
-
}
|
|
323
|
-
for (const document of documents) {
|
|
324
|
-
strings(dirnamePath(document.path), unselectedIn(document.path, document.strings));
|
|
325
|
-
}
|
|
326
|
-
for (const { file } of outside) {
|
|
327
|
-
strings(
|
|
328
|
-
dirnamePath(file.fileName),
|
|
329
|
-
moduleStrings(file).map((one) => one.text),
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
return found;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* The setup files one test-runner configuration names: every literal under
|
|
337
|
-
* `test.setupFiles` and `test.globalSetup`, read against the configuration's own
|
|
338
|
-
* directory. A configuration that moves its root names them against a directory its
|
|
339
|
-
* text may not state, so none is read from it.
|
|
340
|
-
*/
|
|
341
|
-
function setupFilesOf(file: SourceFile, files: SourceFiles): readonly EntryPoint[] {
|
|
342
|
-
const objects = configObjects(file);
|
|
343
|
-
const tests = objects
|
|
344
|
-
.map((object) => memberOf(object, "test"))
|
|
345
|
-
.filter((value): value is Node => value !== undefined)
|
|
346
|
-
.map(unwrapped);
|
|
347
|
-
if ([...objects, ...tests].some((object) => memberOf(object, ROOT_MEMBER) !== undefined)) {
|
|
348
|
-
return [];
|
|
349
|
-
}
|
|
350
|
-
const dir = dirnamePath(file.fileName);
|
|
351
|
-
const found: EntryPoint[] = [];
|
|
352
|
-
for (const test of tests) {
|
|
353
|
-
for (const name of SETUP_MEMBERS) {
|
|
354
|
-
const value = memberOf(test, name);
|
|
355
|
-
for (const text of value === undefined ? [] : (literalsOf(value) ?? [])) {
|
|
356
|
-
for (const named of filesNamed(files, dir, text)) {
|
|
357
|
-
found.push({ file: named, rule: "test-runner", source: text, exports: false });
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return found;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* The test files one browser-test configuration names: every own file below its
|
|
367
|
-
* test directory that its test-file pattern matches. The directory is the literal
|
|
368
|
-
* `testDir` reads against the configuration's directory, or that directory where no
|
|
369
|
-
* object of the configuration writes one; the pattern is the literal `testMatch`, or
|
|
370
|
-
* the runner's own where none is written. A member whose value is not a literal
|
|
371
|
-
* leaves the set unknown, and an unknown set enters nothing.
|
|
372
|
-
*/
|
|
373
|
-
function browserTestsOf(file: SourceFile, files: SourceFiles): readonly EntryPoint[] {
|
|
374
|
-
const objects = configObjects(file);
|
|
375
|
-
if (objects.length === 0) {
|
|
376
|
-
return [];
|
|
377
|
-
}
|
|
378
|
-
let testDir: string | undefined = ".";
|
|
379
|
-
let patterns: readonly string[] | undefined = [BROWSER_TEST_MATCH];
|
|
380
|
-
for (const object of objects) {
|
|
381
|
-
const dir = memberOf(object, "testDir");
|
|
382
|
-
if (dir !== undefined) {
|
|
383
|
-
testDir = literalOf(unwrapped(dir));
|
|
384
|
-
}
|
|
385
|
-
const match = memberOf(object, "testMatch");
|
|
386
|
-
if (match !== undefined) {
|
|
387
|
-
patterns = literalsOf(match);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (testDir === undefined || patterns === undefined) {
|
|
391
|
-
return [];
|
|
392
|
-
}
|
|
393
|
-
const under = resolvePath(dirnamePath(file.fileName), testDir);
|
|
394
|
-
const found: EntryPoint[] = [];
|
|
395
|
-
for (const pattern of patterns) {
|
|
396
|
-
const expression = globExpression(pattern);
|
|
397
|
-
for (const candidate of files.byName.values()) {
|
|
398
|
-
const below = relativePath(under, candidate.fileName);
|
|
399
|
-
if (below !== undefined && expression.test(below)) {
|
|
400
|
-
found.push({ file: candidate, rule: "browser-tests", source: pattern, exports: false });
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return found;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/** One call that addresses a worker, with the names the checker must resolve to the platform. */
|
|
408
|
-
interface WorkerSite {
|
|
409
|
-
readonly literal: string;
|
|
410
|
-
readonly platformNames: readonly Node[];
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* The address one worker argument writes: a relative literal, or a `URL` built from
|
|
415
|
-
* a literal against `import.meta.url`. Any other argument is computed and addresses
|
|
416
|
-
* nothing the text states.
|
|
417
|
-
*/
|
|
418
|
-
function workerAddress(
|
|
419
|
-
argument: Node | undefined,
|
|
420
|
-
): { readonly literal: string; readonly names: readonly Node[] } | undefined {
|
|
421
|
-
if (argument === undefined) {
|
|
422
|
-
return undefined;
|
|
423
|
-
}
|
|
424
|
-
const at = unwrapped(argument);
|
|
425
|
-
const literal = literalOf(at);
|
|
426
|
-
if (literal !== undefined) {
|
|
427
|
-
return { literal, names: [] };
|
|
428
|
-
}
|
|
429
|
-
if (!isNewExpression(at) || !isIdentifier(at.expression) || at.expression.text !== "URL") {
|
|
430
|
-
return undefined;
|
|
431
|
-
}
|
|
432
|
-
const [reference, base] = at.arguments ?? [];
|
|
433
|
-
const text = literalOf(reference === undefined ? undefined : unwrapped(reference));
|
|
434
|
-
if (text === undefined || base === undefined) {
|
|
435
|
-
return undefined;
|
|
436
|
-
}
|
|
437
|
-
const meta = unwrapped(base);
|
|
438
|
-
if (
|
|
439
|
-
!isPropertyAccessExpression(meta) ||
|
|
440
|
-
!isMetaProperty(meta.expression) ||
|
|
441
|
-
!isIdentifier(meta.name) ||
|
|
442
|
-
meta.name.text !== "url"
|
|
443
|
-
) {
|
|
444
|
-
return undefined;
|
|
445
|
-
}
|
|
446
|
-
return { literal: text, names: [at.expression] };
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Every call one file writes that addresses a worker: `new Worker(...)`,
|
|
451
|
-
* `new SharedWorker(...)` and `navigator.serviceWorker.register(...)`, each with an
|
|
452
|
-
* address its text states.
|
|
453
|
-
*/
|
|
454
|
-
function workerSitesOf(file: SourceFile): readonly WorkerSite[] {
|
|
455
|
-
const found: WorkerSite[] = [];
|
|
456
|
-
const visit = (node: Node): void => {
|
|
457
|
-
if (
|
|
458
|
-
isNewExpression(node) &&
|
|
459
|
-
isIdentifier(node.expression) &&
|
|
460
|
-
WORKER_CONSTRUCTORS.has(node.expression.text)
|
|
461
|
-
) {
|
|
462
|
-
const address = workerAddress(node.arguments?.[0]);
|
|
463
|
-
if (address !== undefined) {
|
|
464
|
-
found.push({
|
|
465
|
-
literal: address.literal,
|
|
466
|
-
platformNames: [node.expression, ...address.names],
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
if (isCallExpression(node)) {
|
|
471
|
-
const callee = node.expression;
|
|
472
|
-
if (
|
|
473
|
-
isPropertyAccessExpression(callee) &&
|
|
474
|
-
isIdentifier(callee.name) &&
|
|
475
|
-
callee.name.text === "register" &&
|
|
476
|
-
isPropertyAccessExpression(callee.expression) &&
|
|
477
|
-
isIdentifier(callee.expression.name) &&
|
|
478
|
-
callee.expression.name.text === "serviceWorker" &&
|
|
479
|
-
isIdentifier(callee.expression.expression) &&
|
|
480
|
-
callee.expression.expression.text === "navigator"
|
|
481
|
-
) {
|
|
482
|
-
const address = workerAddress(node.arguments[0]);
|
|
483
|
-
if (address !== undefined) {
|
|
484
|
-
found.push({
|
|
485
|
-
literal: address.literal,
|
|
486
|
-
platformNames: [callee.expression.expression, ...address.names],
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
node.forEachChild(visit);
|
|
492
|
-
};
|
|
493
|
-
file.forEachChild(visit);
|
|
494
|
-
return found;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* The workers one file addresses. A call's names must resolve to a symbol the platform
|
|
499
|
-
* declares, which a file of the target may augment and no import brings in; a name only
|
|
500
|
-
* the target declares is the target's own constructor or object, which addresses no
|
|
501
|
-
* worker this rule knows. One batch per file that writes such a call.
|
|
502
|
-
*/
|
|
503
|
-
function workersOf<Brand>(
|
|
504
|
-
project: ProjectView<Brand>,
|
|
505
|
-
file: SourceFile,
|
|
506
|
-
files: SourceFiles,
|
|
507
|
-
): readonly EntryPoint[] {
|
|
508
|
-
const sites = workerSitesOf(file);
|
|
509
|
-
if (sites.length === 0) {
|
|
510
|
-
return [];
|
|
511
|
-
}
|
|
512
|
-
const names = sites.flatMap((site) => site.platformNames);
|
|
513
|
-
const symbols = project.symbolsAt(names.map((name) => project.handle(name)));
|
|
514
|
-
const platform = new Set<Node>();
|
|
515
|
-
// A name the checker could not resolve is read as the platform's, so a worker it
|
|
516
|
-
// stands on is rooted rather than reported.
|
|
517
|
-
names.forEach((name, index) => {
|
|
518
|
-
const symbol = symbols[index];
|
|
519
|
-
if (symbol === UNANSWERED) {
|
|
520
|
-
platform.add(name);
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
if (
|
|
524
|
-
symbol !== undefined &&
|
|
525
|
-
(symbol.flags & SymbolFlags.Alias) === 0 &&
|
|
526
|
-
symbol.declarations.some((handle) => !files.byName.has(handle.path))
|
|
527
|
-
) {
|
|
528
|
-
platform.add(name);
|
|
529
|
-
}
|
|
530
|
-
});
|
|
531
|
-
const dir = dirnamePath(file.fileName);
|
|
532
|
-
const found: EntryPoint[] = [];
|
|
533
|
-
for (const site of sites) {
|
|
534
|
-
if (!site.platformNames.every((name) => platform.has(name))) {
|
|
535
|
-
continue;
|
|
536
|
-
}
|
|
537
|
-
for (const named of filesNamed(files, dir, site.literal)) {
|
|
538
|
-
found.push({ file: named, rule: "worker", source: site.literal, exports: false });
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return found;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
/** The literal text a computed path starts with: a template's head, or a concatenation's first literal. */
|
|
545
|
-
function leadingLiteral(node: Node): string | undefined {
|
|
546
|
-
const at = unwrapped(node);
|
|
547
|
-
if (isTemplateExpression(at)) {
|
|
548
|
-
return at.head.text;
|
|
549
|
-
}
|
|
550
|
-
if (isBinaryExpression(at) && at.operatorToken.kind === SyntaxKind.PlusToken) {
|
|
551
|
-
return literalOf(unwrapped(at.left)) ?? leadingLiteral(at.left);
|
|
552
|
-
}
|
|
553
|
-
return undefined;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
/** Whether one call is `import.meta.glob(...)`. */
|
|
557
|
-
function isMetaGlob(node: Node): boolean {
|
|
558
|
-
if (!isCallExpression(node) || !isPropertyAccessExpression(node.expression)) {
|
|
559
|
-
return false;
|
|
560
|
-
}
|
|
561
|
-
const { expression, name } = node.expression;
|
|
562
|
-
return (
|
|
563
|
-
isIdentifier(name) &&
|
|
564
|
-
name.text === "glob" &&
|
|
565
|
-
isMetaProperty(expression) &&
|
|
566
|
-
expression.keywordToken === SyntaxKind.ImportKeyword
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* The files one file loads by a computed path, each with what exports: every own file
|
|
572
|
-
* below the directory a relative literal start of an `import()` or `require()` argument
|
|
573
|
-
* names, other than the calling file's own directory or one holding it, which would name
|
|
574
|
-
* every sibling, and
|
|
575
|
-
* every own file a relative literal glob of `import.meta.glob` matches, both read against
|
|
576
|
-
* the calling file's directory, as a bundler's context module reads them.
|
|
577
|
-
*/
|
|
578
|
-
function computedImportsOf(file: SourceFile, files: SourceFiles): readonly EntryPoint[] {
|
|
579
|
-
const dir = dirnamePath(file.fileName);
|
|
580
|
-
const found: EntryPoint[] = [];
|
|
581
|
-
const below = (prefix: string): void => {
|
|
582
|
-
const target = resolvePath(dir, prefix);
|
|
583
|
-
if (
|
|
584
|
-
!isModuleRelative(prefix) ||
|
|
585
|
-
!prefix.endsWith("/") ||
|
|
586
|
-
target === dir ||
|
|
587
|
-
relativePath(target, dir) !== undefined
|
|
588
|
-
) {
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
for (const candidate of files.byName.values()) {
|
|
592
|
-
if (candidate !== file && relativePath(target, candidate.fileName) !== undefined) {
|
|
593
|
-
found.push({ file: candidate, rule: "computed-import", source: prefix, exports: true });
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
};
|
|
597
|
-
const globbed = (pattern: string): void => {
|
|
598
|
-
if (!isModuleRelative(pattern)) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
const expression = globExpression(resolvePath(dir, pattern));
|
|
602
|
-
for (const candidate of files.byName.values()) {
|
|
603
|
-
if (candidate !== file && expression.test(candidate.fileName)) {
|
|
604
|
-
found.push({ file: candidate, rule: "computed-import", source: pattern, exports: true });
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
const visit = (node: Node): void => {
|
|
609
|
-
if (isCallExpression(node)) {
|
|
610
|
-
const [first] = node.arguments;
|
|
611
|
-
const callee = node.expression;
|
|
612
|
-
const loads =
|
|
613
|
-
callee.kind === SyntaxKind.ImportKeyword ||
|
|
614
|
-
(isIdentifier(callee) && callee.text === "require");
|
|
615
|
-
if (loads && first !== undefined) {
|
|
616
|
-
const prefix = leadingLiteral(first);
|
|
617
|
-
if (prefix !== undefined) {
|
|
618
|
-
below(prefix);
|
|
619
|
-
}
|
|
620
|
-
} else if (isMetaGlob(node) && first !== undefined) {
|
|
621
|
-
for (const pattern of literalsOf(first) ?? []) {
|
|
622
|
-
globbed(pattern);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
node.forEachChild(visit);
|
|
627
|
-
};
|
|
628
|
-
file.forEachChild(visit);
|
|
629
|
-
return found;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Every file of one project the rules enter, in no particular order and possibly more
|
|
634
|
-
* than once: a file two rules enter appears once per rule.
|
|
635
|
-
*
|
|
636
|
-
* `testFiles` is the configuration's test-file patterns, matched against each
|
|
637
|
-
* file's path below the target root; a file one of them matches is a test file the
|
|
638
|
-
* runner executes.
|
|
639
|
-
*/
|
|
640
|
-
export function entryPoints<Brand>(
|
|
641
|
-
project: ProjectView<Brand>,
|
|
642
|
-
files: SourceFiles,
|
|
643
|
-
testFiles: readonly string[],
|
|
644
|
-
host: Host,
|
|
645
|
-
targetRoot: string,
|
|
646
|
-
parse?: ParseFile,
|
|
647
|
-
selected: ReadonlyMap<string, Selected> = new Map(),
|
|
648
|
-
): readonly EntryPoint[] {
|
|
649
|
-
const found: EntryPoint[] = [...configurationEntries(host, targetRoot, files, parse, selected)];
|
|
650
|
-
const tests = testFiles.map((pattern) => ({ pattern, expression: globExpression(pattern) }));
|
|
651
|
-
for (const [path, file] of files.byPath) {
|
|
652
|
-
const name = basename(path);
|
|
653
|
-
const named = conventionOf(name);
|
|
654
|
-
if (named !== undefined) {
|
|
655
|
-
found.push({ file, rule: named.convention.rule, source: named.spelled, exports: true });
|
|
656
|
-
if (named.convention.testRunner) {
|
|
657
|
-
found.push(...setupFilesOf(file, files));
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
if (isBrowserTestConfig(name)) {
|
|
661
|
-
found.push(...browserTestsOf(file, files));
|
|
662
|
-
}
|
|
663
|
-
for (const { pattern, expression } of tests) {
|
|
664
|
-
if (expression.test(path)) {
|
|
665
|
-
found.push({ file, rule: "test-runner", source: pattern, exports: false });
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
found.push(...workersOf(project, file, files));
|
|
669
|
-
found.push(...computedImportsOf(file, files));
|
|
670
|
-
}
|
|
671
|
-
for (const { file, source } of htmlEntries(host, targetRoot, files, parse)) {
|
|
672
|
-
found.push({ file, rule: "html-entry", source, exports: true });
|
|
673
|
-
}
|
|
674
|
-
for (const { file, source, names } of documentEntries(host, targetRoot, files)) {
|
|
675
|
-
found.push({
|
|
676
|
-
file,
|
|
677
|
-
rule: "document-import",
|
|
678
|
-
source,
|
|
679
|
-
exports: true,
|
|
680
|
-
...(names === undefined ? {} : { names }),
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
for (const { file, source } of workflowEntries(host, targetRoot, files)) {
|
|
684
|
-
found.push({ file, rule: "workflow-step", source, exports: true });
|
|
685
|
-
}
|
|
686
|
-
return found;
|
|
687
|
-
}
|