@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/dist/src/references.js
CHANGED
|
@@ -1,461 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Every use one side's files make of the target's declarations: one walk and one batched
|
|
3
|
+
* resolution per file, never a reference query per symbol, whose answers would depend on the
|
|
4
|
+
* order the symbols are asked in. A reference carries its use, its position, the declaration
|
|
5
|
+
* enclosing it and whether a test file made it; it carries no mode: which references a run
|
|
6
|
+
* counts is the sweep's reading of this set.
|
|
7
|
+
*/
|
|
8
|
+
import { SyntaxKind } from "@typescript/native/ast";
|
|
2
9
|
import { aliasChains } from "./alias-chain.js";
|
|
10
|
+
import { augmentationReferences, mergedGlobalInterfaces } from "./augmentations.js";
|
|
3
11
|
import { contextualUses } from "./contextual-uses.js";
|
|
4
|
-
import { destructuring
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { ambientGlobalInterfaces, augmentationReferences } from "./augmentations.js";
|
|
10
|
-
import { elementAccessReferences } from "./element-access.js";
|
|
11
|
-
import { indexedAccessReferences } from "./indexed-access.js";
|
|
12
|
-
import { keyofComparisonReferences } from "./keyof-comparisons.js";
|
|
13
|
-
import { unimplementedCalleeReads } from "./unimplemented-callees.js";
|
|
14
|
-
import { moduleDeclarationReferences } from "./module-declarations.js";
|
|
15
|
-
import { overrideReferences } from "./overrides.js";
|
|
16
|
-
import { dirnamePath, queriedModulePath, relativePath, resolvePath } from "./paths.js";
|
|
17
|
-
import { byPosition, isComponentFile, renderPosition } from "./position.js";
|
|
12
|
+
import { destructuring } from "./destructuring.js";
|
|
13
|
+
import { bindingsOf } from "./import-bindings.js";
|
|
14
|
+
import { sitesOf } from "./index/sites.js";
|
|
15
|
+
import { nodeKey } from "./inventory.js";
|
|
16
|
+
import { relativePath } from "./paths.js";
|
|
18
17
|
import { DEFAULT_BATCH_CAP, propertyTables, UNANSWERED } from "./query.js";
|
|
19
|
-
import {
|
|
18
|
+
import { heldBy, READ_RULES } from "./references/read-rules.js";
|
|
19
|
+
import { Sink } from "./references/sink.js";
|
|
20
|
+
import { emitFile, prepared } from "./references/sources.js";
|
|
21
|
+
import { sourceFilesOf } from "./source-files.js";
|
|
22
|
+
import { bytewise } from "./text/compare.js";
|
|
20
23
|
import { typeQueryAliases } from "./type-query-alias.js";
|
|
21
|
-
import { computedKeyNames, iterationReferences, keyNameOf, keyedUses, } from "./symbol-keys.js";
|
|
22
|
-
import { handedOn, valuesOf } from "./value-flow.js";
|
|
23
|
-
/**
|
|
24
|
-
* The operators whose left side one assignment stores into. A compound assignment is
|
|
25
|
-
* among them: where its value is discarded it reads its target only to write the result
|
|
26
|
-
* back, so nothing else receives what it read.
|
|
27
|
-
*/
|
|
28
|
-
const ASSIGNMENTS = new Set([
|
|
29
|
-
SyntaxKind.EqualsToken,
|
|
30
|
-
SyntaxKind.PlusEqualsToken,
|
|
31
|
-
SyntaxKind.MinusEqualsToken,
|
|
32
|
-
SyntaxKind.AsteriskEqualsToken,
|
|
33
|
-
SyntaxKind.AsteriskAsteriskEqualsToken,
|
|
34
|
-
SyntaxKind.SlashEqualsToken,
|
|
35
|
-
SyntaxKind.PercentEqualsToken,
|
|
36
|
-
SyntaxKind.LessThanLessThanEqualsToken,
|
|
37
|
-
SyntaxKind.GreaterThanGreaterThanEqualsToken,
|
|
38
|
-
SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
|
|
39
|
-
SyntaxKind.AmpersandEqualsToken,
|
|
40
|
-
SyntaxKind.BarEqualsToken,
|
|
41
|
-
SyntaxKind.BarBarEqualsToken,
|
|
42
|
-
SyntaxKind.AmpersandAmpersandEqualsToken,
|
|
43
|
-
SyntaxKind.QuestionQuestionEqualsToken,
|
|
44
|
-
SyntaxKind.CaretEqualsToken,
|
|
45
|
-
]);
|
|
46
|
-
/**
|
|
47
|
-
* The assignments that read their target to decide whether to store at all, so the read
|
|
48
|
-
* carries information out whatever becomes of the result.
|
|
49
|
-
*/
|
|
50
|
-
const LOGICAL_ASSIGNMENTS = new Set([
|
|
51
|
-
SyntaxKind.BarBarEqualsToken,
|
|
52
|
-
SyntaxKind.AmpersandAmpersandEqualsToken,
|
|
53
|
-
SyntaxKind.QuestionQuestionEqualsToken,
|
|
54
|
-
]);
|
|
55
|
-
/**
|
|
56
|
-
* Whether the value of one store expression is discarded: it is a statement of its own, a
|
|
57
|
-
* clause of a `for` loop, the operand of `void`, or the left operand of a comma.
|
|
58
|
-
*/
|
|
59
|
-
function valueDiscarded(node) {
|
|
60
|
-
let child = node;
|
|
61
|
-
let parent = node.parent;
|
|
62
|
-
while (isParenthesizedExpression(parent)) {
|
|
63
|
-
child = parent;
|
|
64
|
-
parent = parent.parent;
|
|
65
|
-
}
|
|
66
|
-
if (isExpressionStatement(parent) || isVoidExpression(parent)) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
if (isForStatement(parent)) {
|
|
70
|
-
return parent.initializer === child || parent.incrementor === child;
|
|
71
|
-
}
|
|
72
|
-
return (isBinaryExpression(parent) &&
|
|
73
|
-
parent.operatorToken.kind === SyntaxKind.CommaToken &&
|
|
74
|
-
parent.left === child);
|
|
75
|
-
}
|
|
76
|
-
/** Whether one node is an identifier or a private name, the two forms a name takes. */
|
|
77
|
-
function isName(node) {
|
|
78
|
-
return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateIdentifier;
|
|
79
|
-
}
|
|
80
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
81
|
-
function unparenthesized(node) {
|
|
82
|
-
let held = node;
|
|
83
|
-
while (isParenthesizedExpression(held)) {
|
|
84
|
-
held = held.expression;
|
|
85
|
-
}
|
|
86
|
-
return held;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Records the name one store writes into.
|
|
90
|
-
*
|
|
91
|
-
* A property access writes the member it names. An element access writes the collection
|
|
92
|
-
* it stores into, since a collection a module only stores into holds nothing anything
|
|
93
|
-
* reads, and joins `accesses` for the member a unique-symbol key selects. A destructuring
|
|
94
|
-
* target writes each name it binds, through its spreads and nested patterns.
|
|
95
|
-
*/
|
|
96
|
-
function markWrite(target, writes, accesses) {
|
|
97
|
-
const held = unparenthesized(target);
|
|
98
|
-
if (isName(held)) {
|
|
99
|
-
writes.add(held.pos);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
if (isPropertyAccessExpression(held)) {
|
|
103
|
-
if (isName(held.name)) {
|
|
104
|
-
writes.add(held.name.pos);
|
|
105
|
-
}
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
if (isElementAccessExpression(held)) {
|
|
109
|
-
accesses.add(held);
|
|
110
|
-
// A store through a member's value lands in storage every holder of the value
|
|
111
|
-
// reads, so it reads the member; a variable only ever stored into stays written.
|
|
112
|
-
if (!isPropertyAccessExpression(unparenthesized(held.expression))) {
|
|
113
|
-
markWrite(held.expression, writes, accesses);
|
|
114
|
-
}
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (isArrayLiteralExpression(held)) {
|
|
118
|
-
for (const element of held.elements) {
|
|
119
|
-
markWrite(element, writes, accesses);
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (isObjectLiteralExpression(held)) {
|
|
124
|
-
for (const property of held.properties) {
|
|
125
|
-
if (isPropertyAssignment(property)) {
|
|
126
|
-
markWrite(property.initializer, writes, accesses);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (isShorthandPropertyAssignment(property)) {
|
|
130
|
-
markWrite(property.name, writes, accesses);
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
if (isSpreadAssignment(property)) {
|
|
134
|
-
markWrite(property.expression, writes, accesses);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (isSpreadElement(held)) {
|
|
140
|
-
markWrite(held.expression, writes, accesses);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Records every store one node performs: an assignment, a compound assignment, an
|
|
145
|
-
* increment or a decrement, a `delete`, and an iteration that assigns to a name declared
|
|
146
|
-
* elsewhere. An iteration that declares its own name stores into nothing the inventory
|
|
147
|
-
* holds. A store that reads its target as well records it in `reads`: a logical
|
|
148
|
-
* assignment, and a compound assignment, an increment or a decrement whose value is used.
|
|
149
|
-
*/
|
|
150
|
-
function markStores(node, writes, reads, accesses) {
|
|
151
|
-
if (isBinaryExpression(node)) {
|
|
152
|
-
const operator = node.operatorToken.kind;
|
|
153
|
-
if (ASSIGNMENTS.has(operator)) {
|
|
154
|
-
markWrite(node.left, writes, accesses.written);
|
|
155
|
-
if (LOGICAL_ASSIGNMENTS.has(operator) ||
|
|
156
|
-
(operator !== SyntaxKind.EqualsToken && !valueDiscarded(node))) {
|
|
157
|
-
markWrite(node.left, reads, accesses.read);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
if (isPrefixUnaryExpression(node) || isPostfixUnaryExpression(node)) {
|
|
163
|
-
if (node.operator === SyntaxKind.PlusPlusToken ||
|
|
164
|
-
node.operator === SyntaxKind.MinusMinusToken) {
|
|
165
|
-
markWrite(node.operand, writes, accesses.written);
|
|
166
|
-
if (!valueDiscarded(node)) {
|
|
167
|
-
markWrite(node.operand, reads, accesses.read);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (isDeleteExpression(node)) {
|
|
173
|
-
markWrite(node.expression, writes, accesses.written);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
if (isForInStatement(node) || isForOfStatement(node)) {
|
|
177
|
-
if (node.initializer.kind !== SyntaxKind.VariableDeclarationList) {
|
|
178
|
-
markWrite(node.initializer, writes, accesses.written);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/** Whether one node is `import.meta.url`. */
|
|
183
|
-
function isImportMetaURL(node) {
|
|
184
|
-
const at = unparenthesized(node);
|
|
185
|
-
return (isPropertyAccessExpression(at) &&
|
|
186
|
-
isMetaProperty(at.expression) &&
|
|
187
|
-
at.expression.keywordToken === SyntaxKind.ImportKeyword &&
|
|
188
|
-
at.name.text === "url");
|
|
189
|
-
}
|
|
190
|
-
/** The module URL one node builds, where it builds one. */
|
|
191
|
-
function moduleURLOf(node) {
|
|
192
|
-
const relative = (argument) => {
|
|
193
|
-
const at = argument === undefined ? undefined : unparenthesized(argument);
|
|
194
|
-
return at !== undefined &&
|
|
195
|
-
(isStringLiteral(at) || isNoSubstitutionTemplateLiteral(at)) &&
|
|
196
|
-
/^\.\.?\//u.test(at.text)
|
|
197
|
-
? at.text
|
|
198
|
-
: undefined;
|
|
199
|
-
};
|
|
200
|
-
if (isNewExpression(node) && isIdentifier(node.expression) && node.expression.text === "URL") {
|
|
201
|
-
const [reference, base] = node.arguments ?? [];
|
|
202
|
-
const specifier = relative(reference);
|
|
203
|
-
return specifier !== undefined && base !== undefined && isImportMetaURL(base)
|
|
204
|
-
? { specifier, constructor: node.expression, at: node }
|
|
205
|
-
: undefined;
|
|
206
|
-
}
|
|
207
|
-
if (isCallExpression(node)) {
|
|
208
|
-
const callee = unparenthesized(node.expression);
|
|
209
|
-
const specifier = relative(node.arguments[0]);
|
|
210
|
-
if (specifier !== undefined &&
|
|
211
|
-
isPropertyAccessExpression(callee) &&
|
|
212
|
-
isMetaProperty(callee.expression) &&
|
|
213
|
-
callee.expression.keywordToken === SyntaxKind.ImportKeyword &&
|
|
214
|
-
callee.name.text === "resolve") {
|
|
215
|
-
return { specifier, constructor: undefined, at: node };
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
/** Whether one node is a string literal or a template literal with no substitution. */
|
|
221
|
-
function isLiteralText(node) {
|
|
222
|
-
return node !== undefined && (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node));
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* The module specifier of the module one node evaluates, if it evaluates one: an import
|
|
226
|
-
* declaration, an import-equals declaration of an external module, an export
|
|
227
|
-
* declaration that names a module, and an `import()` call whose argument is literal
|
|
228
|
-
* text. A type-only form evaluates nothing. An `import()` of a computed argument names
|
|
229
|
-
* no module this pass can know.
|
|
230
|
-
*/
|
|
231
|
-
function evaluatedBy(node) {
|
|
232
|
-
if (isImportDeclaration(node)) {
|
|
233
|
-
return node.importClause?.phaseModifier === SyntaxKind.TypeKeyword
|
|
234
|
-
? undefined
|
|
235
|
-
: node.moduleSpecifier;
|
|
236
|
-
}
|
|
237
|
-
if (isExportDeclaration(node)) {
|
|
238
|
-
return node.isTypeOnly ? undefined : node.moduleSpecifier;
|
|
239
|
-
}
|
|
240
|
-
if (isImportEqualsDeclaration(node)) {
|
|
241
|
-
const reference = node.moduleReference;
|
|
242
|
-
return !node.isTypeOnly && isExternalModuleReference(reference)
|
|
243
|
-
? reference.expression
|
|
244
|
-
: undefined;
|
|
245
|
-
}
|
|
246
|
-
if (isCallExpression(node) && node.expression.kind === SyntaxKind.ImportKeyword) {
|
|
247
|
-
const [argument] = node.arguments;
|
|
248
|
-
return isLiteralText(argument) ? argument : undefined;
|
|
249
|
-
}
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* The own file a module specifier with a query evaluates ({@link queriedModulePath}): the
|
|
254
|
-
* checker resolves the whole specifier to whatever module declaration matches it.
|
|
255
|
-
*/
|
|
256
|
-
function queriedFile(file, specifier, fileIdByName) {
|
|
257
|
-
if (!isStringLiteral(specifier) && !isNoSubstitutionTemplateLiteral(specifier)) {
|
|
258
|
-
return undefined;
|
|
259
|
-
}
|
|
260
|
-
const path = queriedModulePath(specifier.text);
|
|
261
|
-
return path === undefined
|
|
262
|
-
? undefined
|
|
263
|
-
: fileIdByName.get(resolvePath(dirnamePath(file.fileName), path));
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* The re-exports one node writes, if it is an export declaration. A specifier and a
|
|
267
|
-
* namespace export are declarations whose names are where they are written, so no use is
|
|
268
|
-
* read from them; each references what it carries forward instead. A bare star declares
|
|
269
|
-
* nothing, so the declaration enclosing it, at the top level the file, references the
|
|
270
|
-
* module it names.
|
|
271
|
-
*/
|
|
272
|
-
function linksOf(file, node, declarations, enclosing) {
|
|
273
|
-
if (!isExportDeclaration(node)) {
|
|
274
|
-
return [];
|
|
275
|
-
}
|
|
276
|
-
const clause = node.exportClause;
|
|
277
|
-
const specifier = node.moduleSpecifier;
|
|
278
|
-
if (clause === undefined) {
|
|
279
|
-
return specifier === undefined
|
|
280
|
-
? []
|
|
281
|
-
: [{ node: specifier, at: specifier, from: enclosing, alias: false }];
|
|
282
|
-
}
|
|
283
|
-
if (isNamespaceExport(clause)) {
|
|
284
|
-
const from = declarations.get(nodeKey(file, clause));
|
|
285
|
-
return from === undefined
|
|
286
|
-
? []
|
|
287
|
-
: [{ node: clause.name, at: specifier ?? clause.name, from, alias: true }];
|
|
288
|
-
}
|
|
289
|
-
const found = [];
|
|
290
|
-
for (const element of clause.elements) {
|
|
291
|
-
const from = declarations.get(nodeKey(file, element));
|
|
292
|
-
if (from !== undefined) {
|
|
293
|
-
found.push({
|
|
294
|
-
node: element.name,
|
|
295
|
-
at: element.propertyName ?? element.name,
|
|
296
|
-
from,
|
|
297
|
-
alias: true,
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return found;
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Whether one object literal is a destructuring target, written on the left of an
|
|
305
|
-
* assignment or as a `for` loop's initializer, through the literals and spreads it nests in.
|
|
306
|
-
*/
|
|
307
|
-
function isAssignmentPattern(node) {
|
|
308
|
-
let child = node;
|
|
309
|
-
let parent = node.parent;
|
|
310
|
-
while (isParenthesizedExpression(parent) ||
|
|
311
|
-
isArrayLiteralExpression(parent) ||
|
|
312
|
-
isObjectLiteralExpression(parent) ||
|
|
313
|
-
isSpreadElement(parent) ||
|
|
314
|
-
isSpreadAssignment(parent) ||
|
|
315
|
-
(isPropertyAssignment(parent) && parent.initializer === child)) {
|
|
316
|
-
child = parent;
|
|
317
|
-
parent = parent.parent;
|
|
318
|
-
}
|
|
319
|
-
if (isBinaryExpression(parent)) {
|
|
320
|
-
return parent.operatorToken.kind === SyntaxKind.EqualsToken && parent.left === child;
|
|
321
|
-
}
|
|
322
|
-
return (isForInStatement(parent) || isForOfStatement(parent)) && parent.initializer === child;
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Every name node one file holds that is a use rather than a declaration, in source
|
|
326
|
-
* order, each with its enclosing declaration and its use, and every re-export the file
|
|
327
|
-
* writes. One walk answers all of it, because a second would have to agree with this one
|
|
328
|
-
* about which nodes are names. A declaration's own declared name is left out, which is
|
|
329
|
-
* what makes a declaration referenced only from its own site an unreferenced one, and so
|
|
330
|
-
* is every node of `unread`, a subtree that is no use.
|
|
331
|
-
*/
|
|
332
|
-
function sitesOf(file, declarations, fileId, unread) {
|
|
333
|
-
const found = [];
|
|
334
|
-
const reads = [];
|
|
335
|
-
const links = [];
|
|
336
|
-
const evaluations = [];
|
|
337
|
-
const wholes = [];
|
|
338
|
-
const urls = [];
|
|
339
|
-
const decorated = [];
|
|
340
|
-
const parameterWrites = [];
|
|
341
|
-
const namespaces = namespaceUses(file);
|
|
342
|
-
const literals = [];
|
|
343
|
-
const flows = [];
|
|
344
|
-
const writes = new Set();
|
|
345
|
-
const alsoRead = new Set();
|
|
346
|
-
const accesses = { written: new Set(), read: new Set() };
|
|
347
|
-
const keyed = [];
|
|
348
|
-
const declared = new Set();
|
|
349
|
-
const shorthands = new Map();
|
|
350
|
-
let enclosing = fileId;
|
|
351
|
-
const markNames = (node) => {
|
|
352
|
-
if (isShorthandPropertyAssignment(node)) {
|
|
353
|
-
shorthands.set(node.name.pos, node);
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
// A property access carries the member it names where a declaration carries its
|
|
357
|
-
// declared name, and it is the one form of the grammar that does.
|
|
358
|
-
if (isPropertyAccessExpression(node)) {
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
const named = node;
|
|
362
|
-
for (const name of [named.name, named.propertyName]) {
|
|
363
|
-
if (name !== undefined && isName(name)) {
|
|
364
|
-
declared.add(name.pos);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
const visit = (node) => {
|
|
369
|
-
if (unread.has(node)) {
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const namespace = namespaces.get(node);
|
|
373
|
-
if (namespace?.kind === "whole") {
|
|
374
|
-
wholes.push({ specifier: namespace.specifier, at: node, from: enclosing });
|
|
375
|
-
}
|
|
376
|
-
else if (namespace?.kind === "indexed") {
|
|
377
|
-
found.push({ node: namespace.literal, shorthand: undefined, from: enclosing, use: "read" });
|
|
378
|
-
}
|
|
379
|
-
if (isName(node)) {
|
|
380
|
-
if (!declared.has(node.pos)) {
|
|
381
|
-
const site = { node, shorthand: shorthands.get(node.pos), from: enclosing };
|
|
382
|
-
if (writes.has(node.pos)) {
|
|
383
|
-
found.push({ ...site, use: "write" });
|
|
384
|
-
}
|
|
385
|
-
if (!writes.has(node.pos) || alsoRead.has(node.pos)) {
|
|
386
|
-
found.push({ ...site, use: "read" });
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
markNames(node);
|
|
392
|
-
markStores(node, writes, alsoRead, accesses);
|
|
393
|
-
const key = isElementAccessExpression(node) ? keyNameOf(node.argumentExpression) : undefined;
|
|
394
|
-
if (key !== undefined && isElementAccessExpression(node)) {
|
|
395
|
-
const written = accesses.written.has(node);
|
|
396
|
-
keyed.push({
|
|
397
|
-
access: node,
|
|
398
|
-
key,
|
|
399
|
-
from: enclosing,
|
|
400
|
-
use: written ? (accesses.read.has(node) ? "both" : "write") : "read",
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
if (isObjectLiteralExpression(node) && !isAssignmentPattern(node)) {
|
|
404
|
-
literals.push({ literal: node, from: enclosing });
|
|
405
|
-
}
|
|
406
|
-
// An assertion needs only comparability, so no member of its operand is read by it.
|
|
407
|
-
for (const written of isAsExpression(node) ? [] : handedOn(node)) {
|
|
408
|
-
flows.push(...valuesOf(written).map((value) => ({ value, from: enclosing })));
|
|
409
|
-
}
|
|
410
|
-
for (const read of propertyReadsOf(node)) {
|
|
411
|
-
reads.push({ ...read, from: enclosing });
|
|
412
|
-
}
|
|
413
|
-
links.push(...linksOf(file, node, declarations, enclosing));
|
|
414
|
-
const evaluated = evaluatedBy(node);
|
|
415
|
-
if (evaluated !== undefined) {
|
|
416
|
-
evaluations.push({ node: evaluated, from: enclosing });
|
|
417
|
-
}
|
|
418
|
-
const url = moduleURLOf(node);
|
|
419
|
-
if (url !== undefined) {
|
|
420
|
-
urls.push(url);
|
|
421
|
-
}
|
|
422
|
-
const held = declarations.get(nodeKey(file, node));
|
|
423
|
-
const outer = enclosing;
|
|
424
|
-
// A parameter property's annotation, initializer and decorators stay with the
|
|
425
|
-
// parameter when the member goes, so they are written inside the constructor's class.
|
|
426
|
-
if (held !== undefined && isParameterProperty(node)) {
|
|
427
|
-
parameterWrites.push({
|
|
428
|
-
name: node.name,
|
|
429
|
-
from: outer,
|
|
430
|
-
member: held,
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
else if (held !== undefined) {
|
|
434
|
-
enclosing = held;
|
|
435
|
-
for (const modifier of node.modifiers ?? []) {
|
|
436
|
-
if (isDecorator(modifier)) {
|
|
437
|
-
decorated.push({ decorator: modifier, declaration: held });
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
node.forEachChild(visit);
|
|
442
|
-
enclosing = outer;
|
|
443
|
-
};
|
|
444
|
-
file.forEachChild(visit);
|
|
445
|
-
return {
|
|
446
|
-
uses: found,
|
|
447
|
-
literals,
|
|
448
|
-
flows,
|
|
449
|
-
reads,
|
|
450
|
-
links,
|
|
451
|
-
evaluations,
|
|
452
|
-
wholes,
|
|
453
|
-
urls,
|
|
454
|
-
decorated,
|
|
455
|
-
parameterWrites,
|
|
456
|
-
keyed,
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
24
|
/** The declaration kinds of a property an object literal declares. */
|
|
460
25
|
const LITERAL_PROPERTY_KINDS = new Set([
|
|
461
26
|
SyntaxKind.PropertyAssignment,
|
|
@@ -464,196 +29,20 @@ const LITERAL_PROPERTY_KINDS = new Set([
|
|
|
464
29
|
SyntaxKind.GetAccessor,
|
|
465
30
|
SyntaxKind.SetAccessor,
|
|
466
31
|
]);
|
|
467
|
-
/** The rule a file the analysis classified as test-support code is counted under. */
|
|
468
|
-
const TEST_SUPPORT_RULE = "test-support";
|
|
469
|
-
/**
|
|
470
|
-
* The name one test-file rule takes. A rule's name is a word list the report's own
|
|
471
|
-
* vocabulary spells, which cannot carry a pattern, so a rule is named by the place of
|
|
472
|
-
* its pattern in the configured list.
|
|
473
|
-
*/
|
|
474
|
-
function patternRule(index) {
|
|
475
|
-
return `test-file-pattern-${String(index + 1)}`;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* The rules over the test files of several projects at once, ordered by rule: a file two
|
|
479
|
-
* projects hold is one file, so each rule counts the distinct paths it matches.
|
|
480
|
-
*/
|
|
481
|
-
export function testFileRulesOf(testFiles, paths, supportFiles = []) {
|
|
482
|
-
const distinct = [...new Set(paths)];
|
|
483
|
-
const support = new Set(supportFiles).size;
|
|
484
|
-
return [
|
|
485
|
-
...testFiles.map((pattern, index) => {
|
|
486
|
-
const expression = globExpression(pattern);
|
|
487
|
-
return {
|
|
488
|
-
rule: patternRule(index),
|
|
489
|
-
matched: distinct.filter((path) => expression.test(path)).length,
|
|
490
|
-
};
|
|
491
|
-
}),
|
|
492
|
-
...(support === 0 ? [] : [{ rule: TEST_SUPPORT_RULE, matched: support }]),
|
|
493
|
-
].sort((a, b) => compare(a.rule, b.rule));
|
|
494
|
-
}
|
|
495
|
-
const importedCache = new WeakMap();
|
|
496
|
-
/**
|
|
497
|
-
* Each local name one file's imports bind, mapped to the names it imports: the
|
|
498
|
-
* exported name of a named import, `default` for a default import, and `undefined` for
|
|
499
|
-
* a namespace import or an import assignment, which binds a whole module.
|
|
500
|
-
*/
|
|
501
|
-
function importedNames(file) {
|
|
502
|
-
const known = importedCache.get(file);
|
|
503
|
-
if (known !== undefined) {
|
|
504
|
-
return known;
|
|
505
|
-
}
|
|
506
|
-
const names = new Map();
|
|
507
|
-
const bind = (local, imported) => {
|
|
508
|
-
names.set(local, [...(names.get(local) ?? []), imported]);
|
|
509
|
-
};
|
|
510
|
-
for (const statement of file.statements) {
|
|
511
|
-
if (isImportEqualsDeclaration(statement)) {
|
|
512
|
-
bind(statement.name.text, undefined);
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
const clause = isImportDeclaration(statement) ? statement.importClause : undefined;
|
|
516
|
-
if (clause === undefined) {
|
|
517
|
-
continue;
|
|
518
|
-
}
|
|
519
|
-
if (clause.name !== undefined) {
|
|
520
|
-
bind(clause.name.text, "default");
|
|
521
|
-
}
|
|
522
|
-
const bindings = clause.namedBindings;
|
|
523
|
-
if (bindings === undefined) {
|
|
524
|
-
continue;
|
|
525
|
-
}
|
|
526
|
-
if (bindings.kind === SyntaxKind.NamespaceImport) {
|
|
527
|
-
bind(bindings.name.text, undefined);
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
for (const element of bindings.elements) {
|
|
531
|
-
bind(element.name.text, element.propertyName?.text ?? element.name.text);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
importedCache.set(file, names);
|
|
536
|
-
return names;
|
|
537
|
-
}
|
|
538
|
-
/** The name node of every import binding one file's top level declares. */
|
|
539
|
-
function importBindings(file) {
|
|
540
|
-
const found = [];
|
|
541
|
-
for (const statement of file.statements) {
|
|
542
|
-
if (isImportEqualsDeclaration(statement)) {
|
|
543
|
-
found.push({ node: statement.name });
|
|
544
|
-
continue;
|
|
545
|
-
}
|
|
546
|
-
const clause = isImportDeclaration(statement) ? statement.importClause : undefined;
|
|
547
|
-
if (clause === undefined) {
|
|
548
|
-
continue;
|
|
549
|
-
}
|
|
550
|
-
if (clause.name !== undefined) {
|
|
551
|
-
found.push({ node: clause.name });
|
|
552
|
-
}
|
|
553
|
-
const bindings = clause.namedBindings;
|
|
554
|
-
if (bindings === undefined) {
|
|
555
|
-
continue;
|
|
556
|
-
}
|
|
557
|
-
if (bindings.kind === SyntaxKind.NamespaceImport) {
|
|
558
|
-
found.push({ node: bindings.name });
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
found.push(...bindings.elements.map((element) => ({ node: element.name })));
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
return found;
|
|
565
|
-
}
|
|
566
|
-
/** The value one assignment stores through the name it writes, where it is a plain assignment. */
|
|
567
|
-
function storedValue(name) {
|
|
568
|
-
let target = name;
|
|
569
|
-
if (isPropertyAccessExpression(name.parent) && name.parent.name === name) {
|
|
570
|
-
target = name.parent;
|
|
571
|
-
}
|
|
572
|
-
while (isParenthesizedExpression(target.parent)) {
|
|
573
|
-
target = target.parent;
|
|
574
|
-
}
|
|
575
|
-
const parent = target.parent;
|
|
576
|
-
return isBinaryExpression(parent) &&
|
|
577
|
-
parent.operatorToken.kind === SyntaxKind.EqualsToken &&
|
|
578
|
-
parent.left === target
|
|
579
|
-
? parent.right
|
|
580
|
-
: undefined;
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* The import bindings of one file that only the values written into one declaration
|
|
584
|
-
* use, for each write into it. A binding is named by an identifier that spells its
|
|
585
|
-
* local name and is not the member a property access names.
|
|
586
|
-
*/
|
|
587
|
-
function aloneIn(file, uses, writes, found) {
|
|
588
|
-
const bindings = new Set(importBindings(file).map((binding) => binding.node.getText()));
|
|
589
|
-
if (bindings.size === 0) {
|
|
590
|
-
return [];
|
|
591
|
-
}
|
|
592
|
-
const occurrences = new Map();
|
|
593
|
-
for (const site of uses) {
|
|
594
|
-
const text = site.node.getText();
|
|
595
|
-
const parent = site.node.parent;
|
|
596
|
-
if (!bindings.has(text) || (isPropertyAccessExpression(parent) && parent.name === site.node)) {
|
|
597
|
-
continue;
|
|
598
|
-
}
|
|
599
|
-
if (!occurrences.get(text)?.includes(site.node)) {
|
|
600
|
-
occurrences.set(text, [...(occurrences.get(text) ?? []), site.node]);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
const inside = (node, value) => node.pos >= value.pos && node.end <= value.end;
|
|
604
|
-
const result = [];
|
|
605
|
-
for (const write of writes) {
|
|
606
|
-
const to = found[write.index]?.to;
|
|
607
|
-
const sameTarget = writes.filter((one) => found[one.index]?.to === to);
|
|
608
|
-
const names = [...occurrences]
|
|
609
|
-
.filter(([, nodes]) => nodes.some((node) => inside(node, write.value)) &&
|
|
610
|
-
nodes.every((node) => sameTarget.some((one) => inside(node, one.value))))
|
|
611
|
-
.map(([name]) => name)
|
|
612
|
-
.sort(compare);
|
|
613
|
-
if (names.length > 0) {
|
|
614
|
-
result.push({ index: write.index, names });
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return result;
|
|
618
|
-
}
|
|
619
|
-
/** Two strings ordered bytewise, which is the order every set of a run is read in. */
|
|
620
|
-
function compare(a, b) {
|
|
621
|
-
if (a === b) {
|
|
622
|
-
return 0;
|
|
623
|
-
}
|
|
624
|
-
return a < b ? -1 : 1;
|
|
625
|
-
}
|
|
626
32
|
/**
|
|
627
|
-
* Every reference one
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
* walks the consumer's files instead and renders against its root, as
|
|
634
|
-
* {@link ReferenceOptions.consumer} states.
|
|
635
|
-
*
|
|
636
|
-
* The order is by the referencing position, then by the declaration named, the
|
|
637
|
-
* declaration referencing it and the use. That is a total order because one name
|
|
638
|
-
* references one declaration once from one declaration, while a chain of aliases reaches
|
|
639
|
-
* several declarations at one position and a bare star re-export's specifier both reads
|
|
640
|
-
* and evaluates the module it names.
|
|
33
|
+
* Every reference one side's files make to the target's declarations. `held` is the
|
|
34
|
+
* target's inventory over the files the project holds, where a resolved symbol is looked up;
|
|
35
|
+
* positions render against `targetRoot`, or a consumer's root as
|
|
36
|
+
* {@link ReferenceOptions.consumer} states. The order is by position, then the declaration
|
|
37
|
+
* named, the referencing declaration and the use: an alias chain or a bare star re-export
|
|
38
|
+
* names several at one position, and one name references one declaration once.
|
|
641
39
|
*/
|
|
642
40
|
export function references(project, held, targetRoot, options) {
|
|
643
41
|
const cap = options.batchCap ?? DEFAULT_BATCH_CAP;
|
|
644
42
|
const declarations = held.declarations;
|
|
645
|
-
const patterns = options.testFiles.map(globExpression);
|
|
646
|
-
const found = [];
|
|
647
|
-
const tests = [];
|
|
648
43
|
const chains = aliasChains(project, held);
|
|
649
44
|
const tables = propertyTables(project.queries);
|
|
650
|
-
const destructured = destructuring(project, cap, tables);
|
|
651
|
-
let batched = 0;
|
|
652
|
-
let fileBatches = 0;
|
|
653
|
-
let residueFallbacks = 0;
|
|
654
|
-
let shorthandLookups = 0;
|
|
655
45
|
const consumer = options.consumer;
|
|
656
|
-
const root = consumer?.root ?? targetRoot;
|
|
657
46
|
const files = consumer === undefined
|
|
658
47
|
? project.ownSourceFiles()
|
|
659
48
|
: project
|
|
@@ -662,6 +51,8 @@ export function references(project, held, targetRoot, options) {
|
|
|
662
51
|
relativePath(targetRoot, file.fileName) === undefined);
|
|
663
52
|
const ownPaths = project.ownPaths();
|
|
664
53
|
const fileIds = new Set(held.symbols.filter((symbol) => symbol.kind === "file").map((symbol) => symbol.id));
|
|
54
|
+
const declaredAt = (node) => declarations.get(nodeKey(node.getSourceFile(), node));
|
|
55
|
+
const sink = new Sink(consumer?.root ?? targetRoot, options.testFile, consumer, declaredAt);
|
|
665
56
|
let moduleBodies;
|
|
666
57
|
/**
|
|
667
58
|
* The declarations one module holds directly: a file's top level, or the body of a
|
|
@@ -671,21 +62,17 @@ export function references(project, held, targetRoot, options) {
|
|
|
671
62
|
if (moduleBodies === undefined) {
|
|
672
63
|
const byModule = new Map();
|
|
673
64
|
for (const symbol of held.symbols) {
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
const siblings = byModule.get(symbol.parent);
|
|
678
|
-
if (siblings === undefined) {
|
|
679
|
-
byModule.set(symbol.parent, [symbol]);
|
|
680
|
-
}
|
|
681
|
-
else {
|
|
682
|
-
siblings.push(symbol);
|
|
65
|
+
if (fileIds.has(symbol.parent) || held.modules.has(symbol.parent)) {
|
|
66
|
+
byModule.set(symbol.parent, [...(byModule.get(symbol.parent) ?? []), symbol]);
|
|
683
67
|
}
|
|
684
68
|
}
|
|
685
69
|
moduleBodies = byModule;
|
|
686
70
|
}
|
|
687
71
|
return moduleBodies.get(moduleId) ?? [];
|
|
688
72
|
};
|
|
73
|
+
const exportedBy = (ids) => [...ids].flatMap((id) => declaredIn(id)
|
|
74
|
+
.filter((symbol) => symbol.exported)
|
|
75
|
+
.map((symbol) => ({ id: symbol.id, stepped: false, guessed: true })));
|
|
689
76
|
const exportsCache = new Map();
|
|
690
77
|
/**
|
|
691
78
|
* Every declaration one module exports, each re-export walked along its chain. A module
|
|
@@ -693,9 +80,7 @@ export function references(project, held, targetRoot, options) {
|
|
|
693
80
|
*/
|
|
694
81
|
const exportsRead = (module) => {
|
|
695
82
|
if (module === UNANSWERED) {
|
|
696
|
-
return
|
|
697
|
-
.filter((symbol) => symbol.exported)
|
|
698
|
-
.map((symbol) => ({ id: symbol.id, stepped: false, guessed: true })));
|
|
83
|
+
return exportedBy(fileIds);
|
|
699
84
|
}
|
|
700
85
|
const known = exportsCache.get(module.id);
|
|
701
86
|
if (known !== undefined) {
|
|
@@ -703,41 +88,26 @@ export function references(project, held, targetRoot, options) {
|
|
|
703
88
|
}
|
|
704
89
|
const table = project.queries.exportsOfModule(module);
|
|
705
90
|
const read = table === UNANSWERED
|
|
706
|
-
? chains.declarationsOf(module)
|
|
707
|
-
.filter((symbol) => symbol.exported)
|
|
708
|
-
.map((symbol) => ({ id: symbol.id, stepped: false, guessed: true })))
|
|
91
|
+
? exportedBy(chains.declarationsOf(module))
|
|
709
92
|
: table.flatMap((exported) => chains.chainOf(exported));
|
|
710
93
|
exportsCache.set(module.id, read);
|
|
711
94
|
return read;
|
|
712
95
|
};
|
|
713
|
-
/** The identifier of the declaration one node of this program is, where it is one. */
|
|
714
|
-
const declaredAt = (node) => declarations.get(nodeKey(node.getSourceFile(), node));
|
|
715
|
-
/**
|
|
716
|
-
* The declarations one re-export carries forward: for an alias, the first link along
|
|
717
|
-
* its chain that the inventory declares, stepping over the links it does not, such as
|
|
718
|
-
* an import the re-export is written against; for a bare star, the module it names.
|
|
719
|
-
* Each later link is a declaration of its own that references the next, so one link
|
|
720
|
-
* per re-export is what lets a chain be followed one declaration at a time.
|
|
721
|
-
*/
|
|
722
|
-
const carriedBy = (link, symbol) => link.alias
|
|
723
|
-
? chains.nextDeclared(symbol)
|
|
724
|
-
: chains.declarationsOf(symbol).map((id) => ({ id, stepped: false, guessed: false }));
|
|
725
96
|
/**
|
|
726
|
-
* Every declaration bearing the name one node spells, or the name an import of its
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
97
|
+
* Every declaration bearing the name one node spells, or the name an import of its file
|
|
98
|
+
* binds that name to, which is what a reference the checker could not resolve is counted
|
|
99
|
+
* as (program.33): it may be a use of any of them. A name a namespace import binds may be
|
|
100
|
+
* a use of any file.
|
|
730
101
|
*/
|
|
731
102
|
const named = (node) => {
|
|
732
|
-
const byName = declarationsByName(held);
|
|
733
103
|
const text = node.getText();
|
|
734
|
-
const imported =
|
|
104
|
+
const imported = bindingsOf(node.getSourceFile()).filter((binding) => binding.name.text === text);
|
|
735
105
|
return [
|
|
736
106
|
...new Set([
|
|
737
|
-
...(byName.get(text) ?? []),
|
|
738
|
-
...imported.flatMap((
|
|
107
|
+
...(held.byName.get(text) ?? []),
|
|
108
|
+
...imported.flatMap((binding) => binding.imported === undefined ? [...fileIds] : (held.byName.get(binding.imported) ?? [])),
|
|
739
109
|
]),
|
|
740
|
-
];
|
|
110
|
+
].map((id) => ({ id, stepped: false, guessed: true }));
|
|
741
111
|
};
|
|
742
112
|
// A type-query alias's own type names its export without using it; a use of the
|
|
743
113
|
// global is the use, so it names every link of the export's chain as well.
|
|
@@ -753,7 +123,7 @@ export function references(project, held, targetRoot, options) {
|
|
|
753
123
|
return;
|
|
754
124
|
}
|
|
755
125
|
aliased.set(id, symbol === UNANSWERED
|
|
756
|
-
? (
|
|
126
|
+
? (held.byName.get(alias.name) ?? []).map((one) => ({
|
|
757
127
|
id: one,
|
|
758
128
|
stepped: true,
|
|
759
129
|
guessed: true,
|
|
@@ -778,25 +148,25 @@ export function references(project, held, targetRoot, options) {
|
|
|
778
148
|
}
|
|
779
149
|
return all;
|
|
780
150
|
};
|
|
781
|
-
|
|
782
|
-
const
|
|
783
|
-
if (site.shorthand !== undefined) {
|
|
784
|
-
shorthandLookups += 1;
|
|
785
|
-
return project.shorthandValueAt(project.handle(site.shorthand));
|
|
786
|
-
}
|
|
787
|
-
const batched = answered.get(site.node);
|
|
788
|
-
if (batched === UNANSWERED || typeof batched === "object") {
|
|
789
|
-
return batched;
|
|
790
|
-
}
|
|
791
|
-
residueFallbacks += 1;
|
|
792
|
-
return project.resolvedSymbolAt(project.handle(site.node));
|
|
793
|
-
};
|
|
794
|
-
const walked = files.map((file) => {
|
|
151
|
+
const rules = READ_RULES.map((rule) => rule.start());
|
|
152
|
+
const sites = files.map((file) => {
|
|
795
153
|
const fileId = declaredAt(file) ?? "";
|
|
796
|
-
return {
|
|
154
|
+
return {
|
|
155
|
+
file,
|
|
156
|
+
fileId,
|
|
157
|
+
...sitesOf(file, declarations, fileId, unread, (node, from) => {
|
|
158
|
+
for (const rule of rules) {
|
|
159
|
+
rule.visit(node, { file, from });
|
|
160
|
+
}
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
797
163
|
});
|
|
798
|
-
const
|
|
799
|
-
|
|
164
|
+
const loadable = sites
|
|
165
|
+
.filter((one) => fileIds.has(one.fileId))
|
|
166
|
+
.map(({ file, fileId }) => ({ file, fileId }));
|
|
167
|
+
const directories = options.directories;
|
|
168
|
+
const destructured = destructuring(project, cap, tables);
|
|
169
|
+
const contextual = contextualUses(project, held, chains, sites.flatMap((one) => one.literals), sites.flatMap((one) => one.flows), cap, tables);
|
|
800
170
|
const writtenBy = new Map();
|
|
801
171
|
for (const write of contextual.writes) {
|
|
802
172
|
const property = write.at.parent;
|
|
@@ -813,404 +183,77 @@ export function references(project, held, targetRoot, options) {
|
|
|
813
183
|
return known;
|
|
814
184
|
}
|
|
815
185
|
const found = [];
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
found.push({ id, stepped: true, guessed: false });
|
|
826
|
-
}
|
|
186
|
+
for (const handle of writtenBy.size === 0 ? [] : symbol.declarations) {
|
|
187
|
+
if (!LITERAL_PROPERTY_KINDS.has(handle.kind) || !ownPaths.has(handle.path)) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const node = project.declarationAt(handle)?.node;
|
|
191
|
+
const ids = node === undefined ? undefined : writtenBy.get(nodeKey(node.getSourceFile(), node));
|
|
192
|
+
for (const id of ids ?? []) {
|
|
193
|
+
if (!found.some((target) => target.id === id)) {
|
|
194
|
+
found.push({ id, stepped: true, guessed: false });
|
|
827
195
|
}
|
|
828
196
|
}
|
|
829
197
|
}
|
|
830
198
|
forwardedCache.set(symbol.id, found);
|
|
831
199
|
return found;
|
|
832
200
|
};
|
|
833
|
-
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
201
|
+
let ownFiles;
|
|
202
|
+
const pass = {
|
|
203
|
+
project,
|
|
204
|
+
held,
|
|
205
|
+
chains,
|
|
206
|
+
tables,
|
|
207
|
+
cap,
|
|
208
|
+
sink,
|
|
209
|
+
consumer: consumer !== undefined,
|
|
210
|
+
directories,
|
|
211
|
+
fileIds,
|
|
212
|
+
fileIdByName: new Map(loadable.map((one) => [one.file.fileName, one.fileId])),
|
|
213
|
+
loadableById: new Map(loadable.map((one) => [one.fileId, one.file])),
|
|
214
|
+
destructured,
|
|
215
|
+
unseenLoads: [],
|
|
216
|
+
formedForNode: options.formedForNode === true,
|
|
217
|
+
possiblyLoaded: new Set(),
|
|
218
|
+
declaredIn,
|
|
219
|
+
exportsRead,
|
|
220
|
+
named,
|
|
221
|
+
targetsOf: (symbol) => {
|
|
222
|
+
const through = forwarded(symbol);
|
|
223
|
+
return through.length === 0
|
|
224
|
+
? chains.chainOf(symbol)
|
|
225
|
+
: [...chains.chainOf(symbol), ...through];
|
|
226
|
+
},
|
|
227
|
+
throughAliases,
|
|
228
|
+
ownFiles: () => (ownFiles ??= sourceFilesOf(project, targetRoot)),
|
|
837
229
|
};
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
const test = patterns.some((pattern) => pattern.test(path)) ||
|
|
842
|
-
options.testFileNames?.has(file.fileName) === true;
|
|
843
|
-
testFile.set(file, test);
|
|
844
|
-
if (test) {
|
|
845
|
-
tests.push(path);
|
|
846
|
-
}
|
|
230
|
+
for (const site of contextual.writes) {
|
|
231
|
+
const file = site.at.getSourceFile();
|
|
232
|
+
sink.add(file, site.at, site.from, site.ids, "write", "contextual", site.at.parent);
|
|
847
233
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const holdsValue = (file, value) => {
|
|
851
|
-
if (value !== undefined) {
|
|
852
|
-
valued.set(file, [...(valued.get(file) ?? []), { index: found.length - 1, value }]);
|
|
853
|
-
}
|
|
854
|
-
};
|
|
855
|
-
for (const [use, sites] of [
|
|
856
|
-
["write", contextual.writes],
|
|
857
|
-
["read", contextual.reads],
|
|
858
|
-
]) {
|
|
859
|
-
for (const site of sites) {
|
|
860
|
-
const file = site.at.getSourceFile();
|
|
861
|
-
const position = renderPosition(file, root, site.at.getStart());
|
|
862
|
-
for (const id of site.ids) {
|
|
863
|
-
found.push({
|
|
864
|
-
from: site.from,
|
|
865
|
-
to: id,
|
|
866
|
-
position,
|
|
867
|
-
use,
|
|
868
|
-
resolution: "contextual",
|
|
869
|
-
test: testFile.get(file) === true,
|
|
870
|
-
});
|
|
871
|
-
if (use === "write") {
|
|
872
|
-
holdsValue(file, site.at.parent);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
}
|
|
234
|
+
for (const site of contextual.reads) {
|
|
235
|
+
sink.add(site.at.getSourceFile(), site.at, site.from, site.ids, "read", "contextual");
|
|
876
236
|
}
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
const test = testFile.get(file) === true;
|
|
880
|
-
// A component file's markup may use any binding its blocks declare at the top level.
|
|
881
|
-
const markup = isComponentFile(file);
|
|
882
|
-
const bindings = markup ? importBindings(file) : [];
|
|
883
|
-
// A decorator is written inside the declaration it is attached to and receives it,
|
|
884
|
-
// so the declaration is used where the decorator is written, whatever the
|
|
885
|
-
// decorator does with it.
|
|
886
|
-
for (const { decorator, declaration } of decorated) {
|
|
887
|
-
found.push({
|
|
888
|
-
from: declaration,
|
|
889
|
-
to: declaration,
|
|
890
|
-
position: renderPosition(file, root, decorator.getStart()),
|
|
891
|
-
use: "decorator",
|
|
892
|
-
resolution: "syntax",
|
|
893
|
-
test,
|
|
894
|
-
});
|
|
895
|
-
}
|
|
896
|
-
// The constructor stores its argument in the member a parameter property declares.
|
|
897
|
-
for (const { name, from, member } of parameterWrites) {
|
|
898
|
-
found.push({
|
|
899
|
-
from,
|
|
900
|
-
to: member,
|
|
901
|
-
position: renderPosition(file, root, name.getStart()),
|
|
902
|
-
use: "write",
|
|
903
|
-
resolution: "syntax",
|
|
904
|
-
test,
|
|
905
|
-
});
|
|
906
|
-
}
|
|
907
|
-
// One batch per capped run of the file's name nodes, the re-exports' nodes after
|
|
908
|
-
// the uses and the evaluated modules' specifiers last, each node once: a bare star
|
|
909
|
-
// re-export's specifier is a link and an evaluation both. A shorthand is left out
|
|
910
|
-
// of the batch: its name resolves to the property the literal declares, so the
|
|
911
|
-
// batch's answer for it would name something this project's inventory never holds.
|
|
912
|
-
const batching = [
|
|
913
|
-
...new Set([
|
|
914
|
-
...uses.filter((site) => site.shorthand === undefined).map((site) => site.node),
|
|
915
|
-
...links.map((link) => link.node),
|
|
916
|
-
...evaluations.map((evaluation) => evaluation.node),
|
|
917
|
-
...wholes.map((whole) => whole.specifier),
|
|
918
|
-
...urls.flatMap((url) => url.constructor ?? []),
|
|
919
|
-
...bindings.map((binding) => binding.node),
|
|
920
|
-
]),
|
|
921
|
-
];
|
|
922
|
-
const answered = new Map();
|
|
923
|
-
batched += batching.length;
|
|
924
|
-
for (let from = 0; from < batching.length; from += cap) {
|
|
925
|
-
const run = batching.slice(from, from + cap);
|
|
926
|
-
const answers = project.symbolsAt(run.map((node) => project.handle(node)), cap);
|
|
927
|
-
fileBatches += 1;
|
|
928
|
-
run.forEach((node, index) => {
|
|
929
|
-
const symbol = answers[index];
|
|
930
|
-
if (symbol !== undefined) {
|
|
931
|
-
answered.set(node, symbol);
|
|
932
|
-
}
|
|
933
|
-
});
|
|
934
|
-
}
|
|
935
|
-
for (const link of links) {
|
|
936
|
-
const symbol = answered.get(link.node);
|
|
937
|
-
if (symbol === undefined) {
|
|
938
|
-
continue;
|
|
939
|
-
}
|
|
940
|
-
const position = renderPosition(file, root, link.at.getStart());
|
|
941
|
-
const carried = symbol === UNANSWERED
|
|
942
|
-
? named(link.at).map((id) => ({ id, stepped: false, guessed: true }))
|
|
943
|
-
: carriedBy(link, symbol);
|
|
944
|
-
for (const target of carried) {
|
|
945
|
-
found.push({
|
|
946
|
-
from: link.from,
|
|
947
|
-
to: target.id,
|
|
948
|
-
position,
|
|
949
|
-
use: "read",
|
|
950
|
-
resolution: target.guessed ? "by-name" : link.alias ? "alias" : "batch",
|
|
951
|
-
test,
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
for (const evaluation of evaluations) {
|
|
956
|
-
const queried = queriedFile(file, evaluation.node, fileIdByName);
|
|
957
|
-
if (queried !== undefined) {
|
|
958
|
-
found.push({
|
|
959
|
-
from: evaluation.from,
|
|
960
|
-
to: queried,
|
|
961
|
-
position: renderPosition(file, root, evaluation.node.getStart()),
|
|
962
|
-
use: "evaluation",
|
|
963
|
-
resolution: "syntax",
|
|
964
|
-
test,
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
const module = answered.get(evaluation.node);
|
|
968
|
-
if (module === undefined) {
|
|
969
|
-
continue;
|
|
970
|
-
}
|
|
971
|
-
const position = renderPosition(file, root, evaluation.node.getStart());
|
|
972
|
-
// A module the checker could not resolve may be any file of the target.
|
|
973
|
-
const evaluated = module === UNANSWERED ? [...fileIds] : chains.declarationsOf(module);
|
|
974
|
-
for (const id of evaluated) {
|
|
975
|
-
if (fileIds.has(id)) {
|
|
976
|
-
found.push({
|
|
977
|
-
from: evaluation.from,
|
|
978
|
-
to: id,
|
|
979
|
-
position,
|
|
980
|
-
use: "evaluation",
|
|
981
|
-
resolution: module === UNANSWERED ? "by-name" : "batch",
|
|
982
|
-
test,
|
|
983
|
-
});
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
for (const url of urls) {
|
|
988
|
-
const constructor = url.constructor === undefined ? undefined : answered.get(url.constructor);
|
|
989
|
-
// An augmentation of the global `URL` merges into it, which keeps the
|
|
990
|
-
// library's declaration; a `URL` the target declares has no other.
|
|
991
|
-
if (typeof constructor === "object" &&
|
|
992
|
-
constructor.declarations.length > 0 &&
|
|
993
|
-
constructor.declarations.every((handle) => ownPaths.has(handle.path))) {
|
|
994
|
-
continue;
|
|
995
|
-
}
|
|
996
|
-
const loaded = specifierCandidates(dirnamePath(file.fileName), url.specifier)
|
|
997
|
-
.map((path) => fileIdByName.get(path))
|
|
998
|
-
.find((id) => id !== undefined);
|
|
999
|
-
if (loaded !== undefined) {
|
|
1000
|
-
found.push({
|
|
1001
|
-
from: fileId,
|
|
1002
|
-
to: loaded,
|
|
1003
|
-
position: renderPosition(file, root, url.at.getStart()),
|
|
1004
|
-
use: "evaluation",
|
|
1005
|
-
resolution: "syntax",
|
|
1006
|
-
test,
|
|
1007
|
-
});
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
for (const whole of wholes) {
|
|
1011
|
-
const module = answered.get(whole.specifier);
|
|
1012
|
-
if (module === undefined) {
|
|
1013
|
-
continue;
|
|
1014
|
-
}
|
|
1015
|
-
const position = renderPosition(file, root, whole.at.getStart());
|
|
1016
|
-
for (const target of exportsRead(module)) {
|
|
1017
|
-
found.push({
|
|
1018
|
-
from: whole.from,
|
|
1019
|
-
to: target.id,
|
|
1020
|
-
position,
|
|
1021
|
-
use: "read",
|
|
1022
|
-
resolution: target.guessed ? "by-name" : "batch",
|
|
1023
|
-
test,
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
if (markup) {
|
|
1028
|
-
for (const symbol of declaredIn(fileId)) {
|
|
1029
|
-
found.push({
|
|
1030
|
-
from: fileId,
|
|
1031
|
-
to: symbol.id,
|
|
1032
|
-
position: symbol.position,
|
|
1033
|
-
use: "read",
|
|
1034
|
-
resolution: "syntax",
|
|
1035
|
-
test,
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
for (const binding of bindings) {
|
|
1039
|
-
const symbol = answered.get(binding.node);
|
|
1040
|
-
if (symbol === undefined) {
|
|
1041
|
-
continue;
|
|
1042
|
-
}
|
|
1043
|
-
const position = renderPosition(file, root, binding.node.getStart());
|
|
1044
|
-
const chained = symbol === UNANSWERED
|
|
1045
|
-
? named(binding.node).map((id) => ({ id, stepped: false, guessed: true }))
|
|
1046
|
-
: chains.chainOf(symbol);
|
|
1047
|
-
// The markup may name any export of a module a binding's chain reaches, whether a
|
|
1048
|
-
// namespace import binds it or a named or default import of a namespace re-export.
|
|
1049
|
-
const targets = chained.flatMap((target) => [
|
|
1050
|
-
target,
|
|
1051
|
-
...declaredIn(target.id)
|
|
1052
|
-
.filter((one) => one.exported)
|
|
1053
|
-
.map((one) => ({ ...target, id: one.id })),
|
|
1054
|
-
]);
|
|
1055
|
-
for (const target of targets) {
|
|
1056
|
-
found.push({
|
|
1057
|
-
from: fileId,
|
|
1058
|
-
to: target.id,
|
|
1059
|
-
position,
|
|
1060
|
-
use: "read",
|
|
1061
|
-
resolution: target.guessed ? "by-name" : target.stepped ? "alias" : "batch",
|
|
1062
|
-
test,
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
// A pattern names a property of the value it destructures, which no name node of
|
|
1068
|
-
// the pattern resolves to: a shorthand's name is the local it binds.
|
|
1069
|
-
destructured.resolve(reads).forEach((symbol, index) => {
|
|
1070
|
-
const read = reads[index];
|
|
1071
|
-
if (symbol === undefined || read === undefined) {
|
|
1072
|
-
return;
|
|
1073
|
-
}
|
|
1074
|
-
const position = renderPosition(file, root, read.key.getStart());
|
|
1075
|
-
const targets = symbol === UNANSWERED
|
|
1076
|
-
? (declarationsByName(held).get(read.name) ?? []).map((id) => ({
|
|
1077
|
-
id,
|
|
1078
|
-
stepped: false,
|
|
1079
|
-
guessed: true,
|
|
1080
|
-
}))
|
|
1081
|
-
: targetsOf(symbol);
|
|
1082
|
-
for (const target of targets) {
|
|
1083
|
-
found.push({
|
|
1084
|
-
from: read.from,
|
|
1085
|
-
to: target.id,
|
|
1086
|
-
position,
|
|
1087
|
-
use: "read",
|
|
1088
|
-
resolution: target.guessed ? "by-name" : "destructured",
|
|
1089
|
-
test,
|
|
1090
|
-
});
|
|
1091
|
-
}
|
|
1092
|
-
});
|
|
1093
|
-
const resolvedKeys = keyed.flatMap((access) => {
|
|
1094
|
-
const symbol = isIdentifier(access.key) && keyNames.has(access.key.text)
|
|
1095
|
-
? answered.get(access.key)
|
|
1096
|
-
: undefined;
|
|
1097
|
-
return typeof symbol === "object" ? [{ access, symbol }] : [];
|
|
1098
|
-
});
|
|
1099
|
-
for (const { access, ids } of keyedUses(project, chains, resolvedKeys, tables, cap)) {
|
|
1100
|
-
const position = renderPosition(file, root, access.access.argumentExpression.getStart());
|
|
1101
|
-
for (const id of ids) {
|
|
1102
|
-
for (const use of access.use === "both" ? ["read", "write"] : [access.use]) {
|
|
1103
|
-
found.push({ from: access.from, to: id, position, use, resolution: "keyed", test });
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
for (const site of uses) {
|
|
1108
|
-
const direct = site.shorthand !== undefined
|
|
1109
|
-
? "shorthand"
|
|
1110
|
-
: typeof answered.get(site.node) === "object"
|
|
1111
|
-
? "batch"
|
|
1112
|
-
: "resolved-symbol";
|
|
1113
|
-
const symbol = symbolFor(site, answered);
|
|
1114
|
-
if (symbol === undefined) {
|
|
1115
|
-
continue;
|
|
1116
|
-
}
|
|
1117
|
-
const position = renderPosition(file, root, site.node.getStart());
|
|
1118
|
-
// A re-export something imports is used and so is the declaration behind it, so
|
|
1119
|
-
// the use names every link of the chain its name stands at the head of.
|
|
1120
|
-
const targets = throughAliases(symbol === UNANSWERED
|
|
1121
|
-
? named(site.node).map((id) => ({ id, stepped: false, guessed: true }))
|
|
1122
|
-
: targetsOf(symbol));
|
|
1123
|
-
for (const target of targets) {
|
|
1124
|
-
found.push({
|
|
1125
|
-
from: site.from,
|
|
1126
|
-
to: target.id,
|
|
1127
|
-
position,
|
|
1128
|
-
use: site.use,
|
|
1129
|
-
resolution: target.guessed ? "by-name" : target.stepped ? "alias" : direct,
|
|
1130
|
-
test,
|
|
1131
|
-
});
|
|
1132
|
-
if (site.use === "write") {
|
|
1133
|
-
holdsValue(file, storedValue(site.node));
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
237
|
+
for (const one of sites) {
|
|
238
|
+
emitFile(prepared(one, pass, loadable), pass);
|
|
1137
239
|
}
|
|
1138
|
-
|
|
1139
|
-
const
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
const id = declaredAt(node);
|
|
1144
|
-
if (id !== undefined) {
|
|
1145
|
-
names.set(id, node.name);
|
|
1146
|
-
}
|
|
240
|
+
const context = { project, held, chains };
|
|
241
|
+
for (const rule of rules) {
|
|
242
|
+
for (const read of rule.reads(context)) {
|
|
243
|
+
if (read.kind === "named") {
|
|
244
|
+
sink.add(read.file, read.at, read.from, [read.to], read.use, read.via, undefined, read.production);
|
|
1147
245
|
}
|
|
1148
|
-
else
|
|
1149
|
-
|
|
246
|
+
else {
|
|
247
|
+
sink.hold(heldBy(read, context));
|
|
1150
248
|
}
|
|
1151
|
-
};
|
|
1152
|
-
for (const { file } of walked) {
|
|
1153
|
-
file.forEachChild(visit);
|
|
1154
249
|
}
|
|
1155
|
-
const global = new Set(ambientGlobalInterfaces(held, [...names.keys()], scripts));
|
|
1156
|
-
const asked = [...names].filter(([id]) => global.has(id));
|
|
1157
|
-
if (asked.length === 0) {
|
|
1158
|
-
return new Set();
|
|
1159
|
-
}
|
|
1160
|
-
const answers = project.symbolsAt(asked.map(([, name]) => project.handle(name)));
|
|
1161
|
-
return new Set(asked.flatMap(([id], at) => {
|
|
1162
|
-
const symbol = answers[at];
|
|
1163
|
-
return typeof symbol === "object" &&
|
|
1164
|
-
symbol.declarations.some((handle) => !ownPaths.has(handle.path))
|
|
1165
|
-
? [id]
|
|
1166
|
-
: [];
|
|
1167
|
-
}));
|
|
1168
|
-
};
|
|
1169
|
-
const usesOf = new Map(walked.map((one) => [one.file, one.uses]));
|
|
1170
|
-
for (const [file, writes] of valued) {
|
|
1171
|
-
const uses = usesOf.get(file) ?? [];
|
|
1172
|
-
for (const { index, names } of aloneIn(file, uses, writes, found)) {
|
|
1173
|
-
const reference = found[index];
|
|
1174
|
-
if (reference !== undefined) {
|
|
1175
|
-
found[index] = { ...reference, alone: names };
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
let typedLookups = 0;
|
|
1180
|
-
if (consumer === undefined) {
|
|
1181
|
-
const before = options.requestCount?.() ?? 0;
|
|
1182
|
-
found.push(...overrideReferences(project, held, chains, new Set(tests)));
|
|
1183
|
-
found.push(...indexedAccessReferences(project, held, chains, root, new Set(tests)));
|
|
1184
|
-
found.push(...elementAccessReferences(project, held, chains, root, new Set(tests)));
|
|
1185
|
-
found.push(...keyofComparisonReferences(project, held, chains, root, new Set(tests)));
|
|
1186
|
-
found.push(...iterationReferences(project, held, chains, root, new Set(tests)));
|
|
1187
|
-
found.push(...typeParameterReads(project, held, chains, root, new Set(tests)));
|
|
1188
|
-
found.push(...unimplementedCalleeReads(project, held, chains, root, new Set(tests)));
|
|
1189
|
-
found.push(...moduleDeclarationReferences(project, held, root, new Set(tests)));
|
|
1190
|
-
typedLookups = (options.requestCount?.() ?? 0) - before;
|
|
1191
250
|
}
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
compare(a.to, b.to) ||
|
|
1196
|
-
compare(a.from, b.from) ||
|
|
1197
|
-
compare(a.use, b.use));
|
|
251
|
+
const merges = mergedGlobalInterfaces(project, held, pass.ownFiles());
|
|
252
|
+
sink.extend(augmentationReferences(held, sink.made, merges.scripts, merges.interfaces));
|
|
253
|
+
const finished = sink.finish(new Map(sites.map((one) => [one.file, one.uses])));
|
|
1198
254
|
return {
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
testFilePaths: tests.sort(compare),
|
|
1203
|
-
cost: {
|
|
1204
|
-
batched,
|
|
1205
|
-
fileBatches,
|
|
1206
|
-
residueFallbacks,
|
|
1207
|
-
shorthandLookups,
|
|
1208
|
-
aliasSteps: chains.steps,
|
|
1209
|
-
patternBatches: destructured.cost.patternBatches,
|
|
1210
|
-
patternLookups: destructured.cost.patternLookups,
|
|
1211
|
-
contextualBatches: contextual.batches,
|
|
1212
|
-
contextualLookups: contextual.lookups,
|
|
1213
|
-
typedLookups,
|
|
1214
|
-
},
|
|
255
|
+
...finished,
|
|
256
|
+
unseenLoads: pass.unseenLoads,
|
|
257
|
+
possiblyLoaded: [...pass.possiblyLoaded].sort(bytewise),
|
|
1215
258
|
};
|
|
1216
259
|
}
|