@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/indexed-access.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
isPropertyAccessExpression,
|
|
32
32
|
isPropertyAssignment,
|
|
33
33
|
isPropertySignatureDeclaration,
|
|
34
|
+
isSourceFile,
|
|
34
35
|
isStringLiteral,
|
|
35
36
|
isTypeAliasDeclaration,
|
|
36
37
|
isTypeOperatorNode,
|
|
@@ -52,12 +53,9 @@ import {
|
|
|
52
53
|
type Symbol as TSSymbol,
|
|
53
54
|
type Type,
|
|
54
55
|
} from "@typescript/native/sync";
|
|
55
|
-
import
|
|
56
|
-
import { nodeKey, type Inventory } from "./inventory.ts";
|
|
57
|
-
import { renderPosition } from "./position.ts";
|
|
56
|
+
import { nodeKey } from "./inventory.ts";
|
|
58
57
|
import { UNANSWERED } from "./query.ts";
|
|
59
|
-
import type {
|
|
60
|
-
import type { ProjectView } from "./session.ts";
|
|
58
|
+
import type { Read, ReadRule } from "./references/read-rule.ts";
|
|
61
59
|
import { typeQueryAliases } from "./type-query-alias.ts";
|
|
62
60
|
|
|
63
61
|
/** A declaration that declares type parameters, by the kinds of node that can. */
|
|
@@ -384,548 +382,593 @@ function carriedIn(generic: Generic): readonly Carried[] {
|
|
|
384
382
|
return found;
|
|
385
383
|
}
|
|
386
384
|
|
|
387
|
-
/**
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
project: ProjectView<Brand>,
|
|
394
|
-
held: Inventory,
|
|
395
|
-
chains: AliasChains,
|
|
396
|
-
root: string,
|
|
397
|
-
testFiles: ReadonlySet<string>,
|
|
398
|
-
): readonly Reference[] {
|
|
399
|
-
const queries = project.queries;
|
|
400
|
-
const accesses: Access[] = [];
|
|
401
|
-
const carried = new Map<Generic, Carried[]>();
|
|
402
|
-
const names = new Set<string>();
|
|
403
|
-
const sites: Site[] = [];
|
|
404
|
-
/** Accesses indexed by a type parameter whose constraint is no `keyof`: it requires each key it names. */
|
|
405
|
-
const constrained: (Omit<Access, "index"> & { readonly constraint: TypeNode })[] = [];
|
|
406
|
-
/** Calls passing an argument, which a generic declared outside the own files may fix. */
|
|
407
|
-
const argumentCalls: Site[] = [];
|
|
408
|
-
|
|
409
|
-
const carry = (generic: Generic, one: Carried): boolean => {
|
|
410
|
-
const known = carried.get(generic) ?? [];
|
|
411
|
-
const same = known.some(
|
|
412
|
-
(other) => JSON.stringify(sideKey(other)) === JSON.stringify(sideKey(one)),
|
|
413
|
-
);
|
|
414
|
-
if (same) {
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
carried.set(generic, [...known, one]);
|
|
418
|
-
const name = calledName(generic);
|
|
419
|
-
if (name !== undefined) {
|
|
420
|
-
names.add(name);
|
|
385
|
+
/** The generics enclosing one node, itself included, outermost first. */
|
|
386
|
+
function enclosingGenerics(node: Node): readonly Generic[] {
|
|
387
|
+
const found: Generic[] = [];
|
|
388
|
+
for (let at = node; !isSourceFile(at); at = at.parent) {
|
|
389
|
+
if (isGeneric(at)) {
|
|
390
|
+
found.push(at);
|
|
421
391
|
}
|
|
422
|
-
|
|
423
|
-
|
|
392
|
+
}
|
|
393
|
+
return found.reverse();
|
|
394
|
+
}
|
|
424
395
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
)?.constraint;
|
|
449
|
-
if (literal !== undefined) {
|
|
450
|
-
accesses.push({ file, from: holder, at: node, object: node.objectType, index: literal });
|
|
451
|
-
} else if (
|
|
452
|
-
constraint !== undefined &&
|
|
453
|
-
keyofOperands(constraint).length === 0 &&
|
|
454
|
-
namedParameter(node.objectType, inside) === undefined
|
|
455
|
-
) {
|
|
456
|
-
constrained.push({ file, from: holder, at: node, object: node.objectType, constraint });
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
if (
|
|
460
|
-
isTypeReferenceNode(node) &&
|
|
461
|
-
node.typeArguments !== undefined &&
|
|
462
|
-
isIdentifier(node.typeName)
|
|
463
|
-
) {
|
|
464
|
-
sites.push({ file, from: holder, node, name: node.typeName.text, enclosing: inside });
|
|
396
|
+
/**
|
|
397
|
+
* The reads the indexed-access types of a side's files make of the members they name, each
|
|
398
|
+
* made by the declaration that holds the type, the reference or the call, or by the file. A
|
|
399
|
+
* question the checker leaves unanswered holds what its answer could have read.
|
|
400
|
+
*/
|
|
401
|
+
export const indexedAccess: ReadRule = {
|
|
402
|
+
start() {
|
|
403
|
+
const accesses: Access[] = [];
|
|
404
|
+
const carried = new Map<Generic, Carried[]>();
|
|
405
|
+
const names = new Set<string>();
|
|
406
|
+
const sites: Site[] = [];
|
|
407
|
+
/** Accesses indexed by a type parameter whose constraint is no `keyof`: it requires each key it names. */
|
|
408
|
+
const constrained: (Omit<Access, "index"> & { readonly constraint: TypeNode })[] = [];
|
|
409
|
+
/** Calls passing an argument, which a generic declared outside the own files may fix. */
|
|
410
|
+
const argumentCalls: Site[] = [];
|
|
411
|
+
|
|
412
|
+
const carry = (generic: Generic, one: Carried): boolean => {
|
|
413
|
+
const known = carried.get(generic) ?? [];
|
|
414
|
+
const same = known.some(
|
|
415
|
+
(other) => JSON.stringify(sideKey(other)) === JSON.stringify(sideKey(one)),
|
|
416
|
+
);
|
|
417
|
+
if (same) {
|
|
418
|
+
return false;
|
|
465
419
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
: isPropertyAccessExpression(callee) && isIdentifier(callee.name)
|
|
471
|
-
? callee.name.text
|
|
472
|
-
: undefined;
|
|
473
|
-
if (name !== undefined) {
|
|
474
|
-
const site = { file, from: holder, node, name, enclosing: inside };
|
|
475
|
-
sites.push(site);
|
|
476
|
-
if (argumentsOf(node).length > 0) {
|
|
477
|
-
argumentCalls.push(site);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
420
|
+
carried.set(generic, [...known, one]);
|
|
421
|
+
const name = calledName(generic);
|
|
422
|
+
if (name !== undefined) {
|
|
423
|
+
names.add(name);
|
|
480
424
|
}
|
|
481
|
-
|
|
482
|
-
visit(child, holder, inside);
|
|
483
|
-
});
|
|
425
|
+
return true;
|
|
484
426
|
};
|
|
485
|
-
file.forEachChild((child) => {
|
|
486
|
-
visit(child, fileId, []);
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
427
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
if (!isTypeReferenceNode(type) || type.typeArguments !== undefined) {
|
|
497
|
-
return literalNames(type) ?? [];
|
|
498
|
-
}
|
|
499
|
-
const [symbol] = queries.symbolsAt([type.typeName]);
|
|
500
|
-
if (symbol === UNANSWERED || symbol === undefined) {
|
|
501
|
-
return [];
|
|
502
|
-
}
|
|
503
|
-
return symbol.declarations.flatMap((handle) => {
|
|
504
|
-
const declared = project.declarationAt(handle)?.node;
|
|
505
|
-
return declared !== undefined &&
|
|
506
|
-
isTypeAliasDeclaration(declared) &&
|
|
507
|
-
declared.typeParameters === undefined &&
|
|
508
|
-
!seen.has(declared)
|
|
509
|
-
? requiredNames(declared.type, new Set([...seen, declared]))
|
|
510
|
-
: [];
|
|
511
|
-
});
|
|
512
|
-
};
|
|
513
|
-
for (const { constraint, ...access } of constrained) {
|
|
514
|
-
const index = requiredNames(constraint, new Set());
|
|
515
|
-
if (index.length > 0) {
|
|
516
|
-
accesses.push({ ...access, index });
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
function partsOf(type: Type): readonly Type[] {
|
|
521
|
-
const parts = queries.constituents(type);
|
|
522
|
-
return parts === UNANSWERED ? [type] : parts;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
/** The generics one symbol declares, through the alias it may be. */
|
|
526
|
-
const genericsOf = (symbol: TSSymbol): readonly Generic[] => {
|
|
527
|
-
const target = (symbol.flags & SymbolFlags.Alias) === 0 ? symbol : queries.aliased(symbol);
|
|
528
|
-
if (target === UNANSWERED) {
|
|
529
|
-
return [];
|
|
530
|
-
}
|
|
531
|
-
return target.declarations.flatMap((handle) => {
|
|
532
|
-
const node = project.declarationAt(handle)?.node;
|
|
533
|
-
const generic = node === undefined ? undefined : genericOf(node);
|
|
534
|
-
return generic === undefined ? [] : [generic];
|
|
535
|
-
});
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* The type a call's callee is read off: the receiver of a property access, the value an
|
|
540
|
-
* object binding pattern destructures the callee from, or the value whose member a
|
|
541
|
-
* variable holding the callee is initialized with.
|
|
542
|
-
*/
|
|
543
|
-
const receiverTypeOf = (callee: Expression): Type | undefined => {
|
|
544
|
-
let operand: Type | undefined;
|
|
545
|
-
if (isPropertyAccessExpression(callee)) {
|
|
546
|
-
const type = queries.typeAt(callee.expression);
|
|
547
|
-
operand = type === UNANSWERED ? undefined : type;
|
|
548
|
-
const args = operand === undefined ? [] : queries.typeArguments(operand);
|
|
549
|
-
if (operand !== undefined && args !== UNANSWERED && args.length > 0) {
|
|
550
|
-
return operand;
|
|
428
|
+
const aliasTypes = new Map<SourceFile, ReadonlySet<Node>>();
|
|
429
|
+
const aliasTypesOf = (file: SourceFile): ReadonlySet<Node> => {
|
|
430
|
+
let known = aliasTypes.get(file);
|
|
431
|
+
if (known === undefined) {
|
|
432
|
+
known = new Set(typeQueryAliases(file).map((alias) => alias.type));
|
|
433
|
+
aliasTypes.set(file, known);
|
|
551
434
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
return operand;
|
|
561
|
-
}
|
|
562
|
-
for (const handle of symbol.declarations) {
|
|
563
|
-
const node = project.declarationAt(handle)?.node;
|
|
564
|
-
const holder =
|
|
565
|
-
node !== undefined &&
|
|
566
|
-
isBindingElement(node) &&
|
|
567
|
-
isObjectBindingPattern(node.parent) &&
|
|
568
|
-
isVariableDeclaration(node.parent.parent)
|
|
569
|
-
? node.parent.parent.initializer
|
|
570
|
-
: node !== undefined &&
|
|
571
|
-
isVariableDeclaration(node) &&
|
|
572
|
-
node.initializer !== undefined &&
|
|
573
|
-
isPropertyAccessExpression(node.initializer)
|
|
574
|
-
? node.initializer.expression
|
|
575
|
-
: undefined;
|
|
576
|
-
const type = holder === undefined ? undefined : queries.typeAt(holder);
|
|
577
|
-
if (type !== UNANSWERED && type !== undefined) {
|
|
578
|
-
return type;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
return operand;
|
|
582
|
-
};
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* The instantiation of `owner` a receiver's type is, or the first one among the base
|
|
586
|
-
* types it extends, breadth first: a subclass fixes its base's type parameters, and
|
|
587
|
-
* `this` stands for its class.
|
|
588
|
-
*/
|
|
589
|
-
const instantiationOf = (type: Type, owner: Node): Type | undefined => {
|
|
590
|
-
const seen = new Set<number>();
|
|
591
|
-
for (let queue = [type]; queue.length > 0;) {
|
|
592
|
-
const next: Type[] = [];
|
|
593
|
-
for (const at of queue) {
|
|
594
|
-
if (seen.has(at.id)) {
|
|
595
|
-
continue;
|
|
435
|
+
return known;
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
visit(node, { file, from }) {
|
|
439
|
+
const holder = from;
|
|
440
|
+
const inside = enclosingGenerics(node);
|
|
441
|
+
if (isGeneric(node) || takesKeyof(node)) {
|
|
442
|
+
carriedIn(node).forEach((one) => carry(node, one));
|
|
596
443
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
444
|
+
if (isIndexedAccessTypeNode(node) && !aliasTypesOf(file).has(node)) {
|
|
445
|
+
const literal = literalNames(node.indexType);
|
|
446
|
+
const parameter =
|
|
447
|
+
literal === undefined ? namedParameter(node.indexType, inside) : undefined;
|
|
448
|
+
const constraint =
|
|
449
|
+
parameter === undefined
|
|
450
|
+
? undefined
|
|
451
|
+
: (
|
|
452
|
+
parameter.generic.typeParameters?.[parameter.index] as
|
|
453
|
+
{ readonly constraint?: TypeNode } | undefined
|
|
454
|
+
)?.constraint;
|
|
455
|
+
if (literal !== undefined) {
|
|
456
|
+
accesses.push({
|
|
457
|
+
file,
|
|
458
|
+
from: holder,
|
|
459
|
+
at: node,
|
|
460
|
+
object: node.objectType,
|
|
461
|
+
index: literal,
|
|
462
|
+
});
|
|
463
|
+
} else if (
|
|
464
|
+
constraint !== undefined &&
|
|
465
|
+
keyofOperands(constraint).length === 0 &&
|
|
466
|
+
namedParameter(node.objectType, inside) === undefined
|
|
467
|
+
) {
|
|
468
|
+
constrained.push({ file, from: holder, at: node, object: node.objectType, constraint });
|
|
469
|
+
}
|
|
606
470
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
471
|
+
if (
|
|
472
|
+
isTypeReferenceNode(node) &&
|
|
473
|
+
node.typeArguments !== undefined &&
|
|
474
|
+
isIdentifier(node.typeName)
|
|
475
|
+
) {
|
|
476
|
+
sites.push({ file, from: holder, node, name: node.typeName.text, enclosing: inside });
|
|
477
|
+
}
|
|
478
|
+
if (isCallExpression(node) || isNewExpression(node)) {
|
|
479
|
+
const callee = node.expression;
|
|
480
|
+
const name = isIdentifier(callee)
|
|
481
|
+
? callee.text
|
|
482
|
+
: isPropertyAccessExpression(callee) && isIdentifier(callee.name)
|
|
483
|
+
? callee.name.text
|
|
484
|
+
: undefined;
|
|
485
|
+
if (name !== undefined) {
|
|
486
|
+
const site = { file, from: holder, node, name, enclosing: inside };
|
|
487
|
+
sites.push(site);
|
|
488
|
+
if (argumentsOf(node).length > 0) {
|
|
489
|
+
argumentCalls.push(site);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
reads({ project, chains }) {
|
|
495
|
+
const queries = project.queries;
|
|
496
|
+
const found: Read[] = [];
|
|
497
|
+
/**
|
|
498
|
+
* A site whose generic the checker cannot name may fix any generic of its name, whose
|
|
499
|
+
* accesses may then read any member.
|
|
500
|
+
*/
|
|
501
|
+
const holdSite = (site: Site): void => {
|
|
502
|
+
found.push({ kind: "held", from: site.from, members: true });
|
|
503
|
+
};
|
|
504
|
+
/** The literal keys one constraint names, through the type aliases it references. */
|
|
505
|
+
const requiredNames = (node: TypeNode, seen: ReadonlySet<Node>): readonly string[] => {
|
|
506
|
+
const type = unwrappedType(node);
|
|
507
|
+
if (isUnionTypeNode(type)) {
|
|
508
|
+
return type.types.flatMap((one) => requiredNames(one, seen));
|
|
509
|
+
}
|
|
510
|
+
if (!isTypeReferenceNode(type) || type.typeArguments !== undefined) {
|
|
511
|
+
return literalNames(type) ?? [];
|
|
512
|
+
}
|
|
513
|
+
const [symbol] = queries.symbolsAt([type.typeName]);
|
|
514
|
+
if (symbol === UNANSWERED || symbol === undefined) {
|
|
515
|
+
return [];
|
|
516
|
+
}
|
|
517
|
+
return symbol.declarations.flatMap((handle) => {
|
|
518
|
+
const declared = project.declarationAt(handle)?.node;
|
|
519
|
+
return declared !== undefined &&
|
|
520
|
+
isTypeAliasDeclaration(declared) &&
|
|
521
|
+
declared.typeParameters === undefined &&
|
|
522
|
+
!seen.has(declared)
|
|
523
|
+
? requiredNames(declared.type, new Set([...seen, declared]))
|
|
524
|
+
: [];
|
|
525
|
+
});
|
|
526
|
+
};
|
|
527
|
+
for (const { constraint, ...access } of constrained) {
|
|
528
|
+
const index = requiredNames(constraint, new Set());
|
|
529
|
+
if (index.length > 0) {
|
|
530
|
+
accesses.push({ ...access, index });
|
|
531
|
+
}
|
|
612
532
|
}
|
|
613
|
-
}
|
|
614
|
-
queue = next;
|
|
615
|
-
}
|
|
616
|
-
return type;
|
|
617
|
-
};
|
|
618
533
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
}
|
|
624
|
-
const { node } = site;
|
|
625
|
-
if (side.kind === "receiver") {
|
|
626
|
-
const callee = isCallExpression(node) ? node.expression : undefined;
|
|
627
|
-
const owner = receiverOf(generic);
|
|
628
|
-
const typed = callee === undefined ? undefined : receiverTypeOf(callee);
|
|
629
|
-
const receiver =
|
|
630
|
-
typed === undefined || owner === undefined ? typed : instantiationOf(typed, owner);
|
|
631
|
-
if (receiver === undefined) {
|
|
632
|
-
return undefined;
|
|
633
|
-
}
|
|
634
|
-
const args = queries.typeArguments(receiver);
|
|
635
|
-
const type = args === UNANSWERED ? undefined : args[side.index];
|
|
636
|
-
return type === undefined ? undefined : { kind: "type", type };
|
|
637
|
-
}
|
|
638
|
-
if (side.kind === "argument") {
|
|
639
|
-
const argument = isTypeReferenceNode(node) ? undefined : node.arguments?.[side.index];
|
|
640
|
-
const type = argument === undefined ? undefined : queries.typeAt(argument);
|
|
641
|
-
return type === UNANSWERED || type === undefined ? undefined : { kind: "type", type };
|
|
642
|
-
}
|
|
643
|
-
const written = node.typeArguments?.[side.index];
|
|
644
|
-
if (written !== undefined) {
|
|
645
|
-
const passed = namedParameter(written, site.enclosing);
|
|
646
|
-
const mapped = passed === undefined ? mappedConstraint(written) : undefined;
|
|
647
|
-
return passed !== undefined
|
|
648
|
-
? { kind: "passed", generic: passed.generic, index: passed.index }
|
|
649
|
-
: { kind: "node", node: mapped ?? written };
|
|
650
|
-
}
|
|
651
|
-
if (isTypeReferenceNode(node)) {
|
|
652
|
-
return undefined;
|
|
653
|
-
}
|
|
654
|
-
const at = parametersOf(generic).findIndex((parameter) => {
|
|
655
|
-
const type = parameter.type === undefined ? undefined : unwrappedType(parameter.type);
|
|
656
|
-
return (
|
|
657
|
-
type !== undefined &&
|
|
658
|
-
isTypeReferenceNode(type) &&
|
|
659
|
-
isIdentifier(type.typeName) &&
|
|
660
|
-
parameterAt(generic, type.typeName.text) === side.index
|
|
661
|
-
);
|
|
662
|
-
});
|
|
663
|
-
if (at < 0) {
|
|
664
|
-
return undefined;
|
|
665
|
-
}
|
|
666
|
-
const resolved = queries.resolvedSignature(node);
|
|
667
|
-
if (resolved === UNANSWERED || resolved === undefined) {
|
|
668
|
-
return undefined;
|
|
669
|
-
}
|
|
670
|
-
const type = queries.typeAtPosition(resolved, at);
|
|
671
|
-
return type === UNANSWERED ? undefined : { kind: "type", type };
|
|
672
|
-
};
|
|
534
|
+
function partsOf(type: Type): readonly Type[] {
|
|
535
|
+
const parts = queries.constituents(type);
|
|
536
|
+
return parts === UNANSWERED ? [type] : parts;
|
|
537
|
+
}
|
|
673
538
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
539
|
+
/** The generics one symbol declares, through the alias it may be. */
|
|
540
|
+
const genericsOf = (symbol: TSSymbol): readonly Generic[] => {
|
|
541
|
+
const target =
|
|
542
|
+
(symbol.flags & SymbolFlags.Alias) === 0 ? symbol : queries.aliased(symbol);
|
|
543
|
+
if (target === UNANSWERED) {
|
|
544
|
+
return [];
|
|
545
|
+
}
|
|
546
|
+
return target.declarations.flatMap((handle) => {
|
|
547
|
+
const node = project.declarationAt(handle)?.node;
|
|
548
|
+
const generic = node === undefined ? undefined : genericOf(node);
|
|
549
|
+
return generic === undefined ? [] : [generic];
|
|
550
|
+
});
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* The type a call's callee is read off: the receiver of a property access, the value an
|
|
555
|
+
* object binding pattern destructures the callee from, or the value whose member a
|
|
556
|
+
* variable holding the callee is initialized with.
|
|
557
|
+
*/
|
|
558
|
+
const receiverTypeOf = (callee: Expression): Type | undefined => {
|
|
559
|
+
let operand: Type | undefined;
|
|
560
|
+
if (isPropertyAccessExpression(callee)) {
|
|
561
|
+
const type = queries.typeAt(callee.expression);
|
|
562
|
+
operand = type === UNANSWERED ? undefined : type;
|
|
563
|
+
const args = operand === undefined ? [] : queries.typeArguments(operand);
|
|
564
|
+
if (operand !== undefined && args !== UNANSWERED && args.length > 0) {
|
|
565
|
+
return operand;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const name = isPropertyAccessExpression(callee) ? callee.name : callee;
|
|
569
|
+
const [named] = queries.symbolsAt([name]);
|
|
570
|
+
const symbol =
|
|
571
|
+
named === UNANSWERED || named === undefined || (named.flags & SymbolFlags.Alias) === 0
|
|
572
|
+
? named
|
|
573
|
+
: queries.aliased(named);
|
|
574
|
+
if (symbol === UNANSWERED || symbol === undefined) {
|
|
575
|
+
return operand;
|
|
576
|
+
}
|
|
577
|
+
for (const handle of symbol.declarations) {
|
|
578
|
+
const node = project.declarationAt(handle)?.node;
|
|
579
|
+
const holder =
|
|
580
|
+
node !== undefined &&
|
|
581
|
+
isBindingElement(node) &&
|
|
582
|
+
isObjectBindingPattern(node.parent) &&
|
|
583
|
+
isVariableDeclaration(node.parent.parent)
|
|
584
|
+
? node.parent.parent.initializer
|
|
585
|
+
: node !== undefined &&
|
|
586
|
+
isVariableDeclaration(node) &&
|
|
587
|
+
node.initializer !== undefined &&
|
|
588
|
+
isPropertyAccessExpression(node.initializer)
|
|
589
|
+
? node.initializer.expression
|
|
590
|
+
: undefined;
|
|
591
|
+
const type = holder === undefined ? undefined : queries.typeAt(holder);
|
|
592
|
+
if (type !== UNANSWERED && type !== undefined) {
|
|
593
|
+
return type;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return operand;
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* The instantiation of `owner` a receiver's type is, or the first one among the base
|
|
601
|
+
* types it extends, breadth first: a subclass fixes its base's type parameters, and
|
|
602
|
+
* `this` stands for its class.
|
|
603
|
+
*/
|
|
604
|
+
const instantiationOf = (type: Type, owner: Node): Type | undefined => {
|
|
605
|
+
const seen = new Set<number>();
|
|
606
|
+
for (let queue = [type]; queue.length > 0;) {
|
|
607
|
+
const next: Type[] = [];
|
|
608
|
+
for (const at of queue) {
|
|
609
|
+
if (seen.has(at.id)) {
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
seen.add(at.id);
|
|
613
|
+
const target = at.isTypeReference() ? queries.targetOf(at) : at;
|
|
614
|
+
const symbol = target === UNANSWERED ? undefined : queries.symbolOfType(target);
|
|
615
|
+
const declares =
|
|
616
|
+
symbol !== undefined &&
|
|
617
|
+
symbol !== UNANSWERED &&
|
|
618
|
+
symbol.declarations.some((handle) => project.declarationAt(handle)?.node === owner);
|
|
619
|
+
if (declares) {
|
|
620
|
+
return at;
|
|
621
|
+
}
|
|
622
|
+
const constraint = at.isTypeParameter() ? queries.constraintOf(at) : undefined;
|
|
623
|
+
const bases = at.isTypeParameter() ? [] : queries.baseTypes(at);
|
|
624
|
+
next.push(...(bases === UNANSWERED ? [] : bases));
|
|
625
|
+
if (constraint !== undefined && constraint !== UNANSWERED) {
|
|
626
|
+
next.push(constraint);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
queue = next;
|
|
630
|
+
}
|
|
631
|
+
return type;
|
|
632
|
+
};
|
|
711
633
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
if (
|
|
745
|
-
return;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
634
|
+
/** What one site fixes for one side of a carried access. */
|
|
635
|
+
const fixedAt = (site: Site, side: Side, generic: Generic): Fixed | undefined => {
|
|
636
|
+
if (side.kind === "written") {
|
|
637
|
+
return { kind: "node", node: side.node };
|
|
638
|
+
}
|
|
639
|
+
const { node } = site;
|
|
640
|
+
if (side.kind === "receiver") {
|
|
641
|
+
const callee = isCallExpression(node) ? node.expression : undefined;
|
|
642
|
+
const owner = receiverOf(generic);
|
|
643
|
+
const typed = callee === undefined ? undefined : receiverTypeOf(callee);
|
|
644
|
+
const receiver =
|
|
645
|
+
typed === undefined || owner === undefined ? typed : instantiationOf(typed, owner);
|
|
646
|
+
if (receiver === undefined) {
|
|
647
|
+
return undefined;
|
|
648
|
+
}
|
|
649
|
+
const args = queries.typeArguments(receiver);
|
|
650
|
+
const type = args === UNANSWERED ? undefined : args[side.index];
|
|
651
|
+
return type === undefined ? undefined : { kind: "type", type };
|
|
652
|
+
}
|
|
653
|
+
if (side.kind === "argument") {
|
|
654
|
+
const argument = isTypeReferenceNode(node) ? undefined : node.arguments?.[side.index];
|
|
655
|
+
const type = argument === undefined ? undefined : queries.typeAt(argument);
|
|
656
|
+
return type === UNANSWERED || type === undefined ? undefined : { kind: "type", type };
|
|
657
|
+
}
|
|
658
|
+
const written = node.typeArguments?.[side.index];
|
|
659
|
+
if (written !== undefined) {
|
|
660
|
+
const passed = namedParameter(written, site.enclosing);
|
|
661
|
+
const mapped = passed === undefined ? mappedConstraint(written) : undefined;
|
|
662
|
+
return passed !== undefined
|
|
663
|
+
? { kind: "passed", generic: passed.generic, index: passed.index }
|
|
664
|
+
: { kind: "node", node: mapped ?? written };
|
|
665
|
+
}
|
|
666
|
+
if (isTypeReferenceNode(node)) {
|
|
667
|
+
return undefined;
|
|
668
|
+
}
|
|
669
|
+
const at = parametersOf(generic).findIndex((parameter) => {
|
|
670
|
+
const type = parameter.type === undefined ? undefined : unwrappedType(parameter.type);
|
|
671
|
+
return (
|
|
672
|
+
type !== undefined &&
|
|
673
|
+
isTypeReferenceNode(type) &&
|
|
674
|
+
isIdentifier(type.typeName) &&
|
|
675
|
+
parameterAt(generic, type.typeName.text) === side.index
|
|
676
|
+
);
|
|
677
|
+
});
|
|
678
|
+
if (at < 0) {
|
|
679
|
+
return undefined;
|
|
680
|
+
}
|
|
681
|
+
const resolved = queries.resolvedSignature(node);
|
|
682
|
+
if (resolved === UNANSWERED || resolved === undefined) {
|
|
683
|
+
return undefined;
|
|
684
|
+
}
|
|
685
|
+
const type = queries.typeAtPosition(resolved, at);
|
|
686
|
+
return type === UNANSWERED ? undefined : { kind: "type", type };
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
/** Reads one carried access at one site: an access where both sides are fixed, a carry where one is passed on. */
|
|
690
|
+
const readAt = (site: Site, generic: Generic, one: Carried): boolean => {
|
|
691
|
+
const object = fixedAt(site, one.object, generic);
|
|
692
|
+
const index = object === undefined ? undefined : fixedAt(site, one.index, generic);
|
|
693
|
+
if (object === undefined || index === undefined) {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
const passed = [object, index].find((fixed) => fixed.kind === "passed");
|
|
697
|
+
if (passed !== undefined) {
|
|
698
|
+
const side = (fixed: Fixed): Side | undefined =>
|
|
699
|
+
fixed.kind === "passed"
|
|
700
|
+
? fixed.generic === passed.generic
|
|
701
|
+
? { kind: "parameter", index: fixed.index }
|
|
702
|
+
: undefined
|
|
703
|
+
: fixed.kind === "node"
|
|
704
|
+
? { kind: "written", node: fixed.node }
|
|
705
|
+
: undefined;
|
|
706
|
+
const objectSide = side(object);
|
|
707
|
+
const indexSide = side(index);
|
|
708
|
+
return objectSide !== undefined && indexSide !== undefined
|
|
709
|
+
? carry(passed.generic, { object: objectSide, index: indexSide })
|
|
710
|
+
: false;
|
|
711
|
+
}
|
|
712
|
+
const objectAt = concrete(object);
|
|
713
|
+
const indexAt = concrete(index);
|
|
714
|
+
if (objectAt === undefined || indexAt === undefined) {
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
accesses.push({
|
|
718
|
+
file: site.file,
|
|
719
|
+
from: site.from,
|
|
720
|
+
at: site.node,
|
|
721
|
+
object: objectAt,
|
|
722
|
+
index: "kind" in indexAt ? (literalNames(indexAt) ?? indexAt) : indexAt,
|
|
723
|
+
});
|
|
724
|
+
return false;
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
// A site passing a type parameter on carries the access to its own generic, so the
|
|
728
|
+
// sites are read again until no generic gains an access.
|
|
729
|
+
const resolvedGenerics = new Map<Site, readonly Generic[]>();
|
|
730
|
+
const read = new Set<string>();
|
|
731
|
+
for (let changed = true; changed;) {
|
|
732
|
+
changed = false;
|
|
733
|
+
const pending = sites.filter(
|
|
734
|
+
(site) => names.has(site.name) && !resolvedGenerics.has(site),
|
|
735
|
+
);
|
|
736
|
+
const typeSites = pending.filter((site) => isTypeReferenceNode(site.node));
|
|
737
|
+
const symbols =
|
|
738
|
+
typeSites.length === 0
|
|
739
|
+
? []
|
|
740
|
+
: queries.symbolsAt(
|
|
741
|
+
typeSites.map((site) => (site.node as TypeReferenceNode).typeName),
|
|
742
|
+
);
|
|
743
|
+
typeSites.forEach((site, at) => {
|
|
744
|
+
const symbol = symbols[at];
|
|
745
|
+
if (symbol === UNANSWERED) {
|
|
746
|
+
holdSite(site);
|
|
747
|
+
}
|
|
748
|
+
resolvedGenerics.set(
|
|
749
|
+
site,
|
|
750
|
+
symbol === UNANSWERED || symbol === undefined ? [] : genericsOf(symbol),
|
|
751
|
+
);
|
|
752
|
+
});
|
|
753
|
+
for (const site of pending.filter((one) => !isTypeReferenceNode(one.node))) {
|
|
754
|
+
const resolved = queries.resolvedSignature(site.node);
|
|
755
|
+
if (resolved === UNANSWERED) {
|
|
756
|
+
holdSite(site);
|
|
757
|
+
}
|
|
758
|
+
const declaration =
|
|
759
|
+
resolved === UNANSWERED || resolved?.declaration === undefined
|
|
760
|
+
? undefined
|
|
761
|
+
: project.declarationAt(resolved.declaration)?.node;
|
|
762
|
+
const generic = declaration === undefined ? undefined : genericOf(declaration);
|
|
763
|
+
resolvedGenerics.set(site, generic === undefined ? [] : [generic]);
|
|
764
|
+
}
|
|
765
|
+
sites.forEach((site, siteAt) => {
|
|
766
|
+
for (const generic of resolvedGenerics.get(site) ?? []) {
|
|
767
|
+
(carried.get(generic) ?? []).forEach((one, at) => {
|
|
768
|
+
const key = `${String(siteAt)}:${String(at)}:${nodeKey(generic.getSourceFile(), generic)}`;
|
|
769
|
+
if (read.has(key)) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
read.add(key);
|
|
773
|
+
changed = readAt(site, generic, one) || changed;
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
}
|
|
753
778
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
779
|
+
// A generic declared outside the project's own files carries what its own text indexes
|
|
780
|
+
// by its type parameters and its receiver's. Only a call passing an argument the compiler
|
|
781
|
+
// types as a literal can fix an index, so only such a call's signature is resolved.
|
|
782
|
+
const outside = argumentCalls.filter((site) => !resolvedGenerics.has(site));
|
|
783
|
+
const argumentNodes = argumentCalls.flatMap((site) => argumentsOf(site.node));
|
|
784
|
+
const argumentTypes = queries.typesAt(argumentNodes);
|
|
785
|
+
const literalArgument = new Set<Node>();
|
|
786
|
+
argumentTypes.forEach((type, at) => {
|
|
787
|
+
const node = argumentNodes[at];
|
|
788
|
+
if (
|
|
789
|
+
node !== undefined &&
|
|
790
|
+
type !== UNANSWERED &&
|
|
791
|
+
type !== undefined &&
|
|
792
|
+
literalTypeNames(type, partsOf).length > 0
|
|
793
|
+
) {
|
|
794
|
+
literalArgument.add(node);
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
const own = project.ownPaths();
|
|
798
|
+
for (const site of outside) {
|
|
799
|
+
if (!argumentsOf(site.node).some((one) => literalArgument.has(one))) {
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
const resolved = queries.resolvedSignature(site.node);
|
|
803
|
+
const handle =
|
|
804
|
+
resolved === UNANSWERED || resolved === undefined ? undefined : resolved.declaration;
|
|
805
|
+
if (handle === undefined || own.has(handle.path)) {
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
const node = project.declarationAt(handle)?.node;
|
|
809
|
+
const generic = node === undefined ? undefined : genericOf(node);
|
|
810
|
+
if (generic === undefined) {
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
813
|
+
for (const one of carriedIn(generic)) {
|
|
814
|
+
readAt(site, generic, one);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
for (const site of argumentCalls) {
|
|
818
|
+
if (argumentsOf(site.node).some((one) => literalArgument.has(one))) {
|
|
819
|
+
accesses.push(...instantiatedAccesses(site));
|
|
820
|
+
}
|
|
821
|
+
}
|
|
797
822
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
823
|
+
/**
|
|
824
|
+
* The indexed accesses the generic signature a call instantiates holds, read through the
|
|
825
|
+
* checker: the signature its receiver's instantiation gives, so an object type its
|
|
826
|
+
* receiver fixes is concrete whatever declaration spells the receiver's type, a type
|
|
827
|
+
* literal a generic function returns among them. An index naming a type parameter is the
|
|
828
|
+
* literal type the call passes at each parameter of that type.
|
|
829
|
+
*/
|
|
830
|
+
function instantiatedAccesses(site: Site): readonly Access[] {
|
|
831
|
+
const resolved = queries.resolvedSignature(site.node);
|
|
832
|
+
const generic =
|
|
833
|
+
resolved === UNANSWERED || resolved === undefined
|
|
834
|
+
? undefined
|
|
835
|
+
: queries.genericOf(resolved);
|
|
836
|
+
if (
|
|
837
|
+
resolved === UNANSWERED ||
|
|
838
|
+
resolved === undefined ||
|
|
839
|
+
generic === UNANSWERED ||
|
|
840
|
+
generic === undefined
|
|
841
|
+
) {
|
|
842
|
+
return [];
|
|
843
|
+
}
|
|
844
|
+
const count = argumentsOf(site.node).length;
|
|
845
|
+
const parameters: Type[] = [];
|
|
846
|
+
for (let at = 0; at < count; at += 1) {
|
|
847
|
+
const type = queries.parameterType(generic, at);
|
|
848
|
+
if (type !== UNANSWERED && type !== undefined) {
|
|
849
|
+
parameters[at] = type;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
const result = queries.returnTypeOf(generic);
|
|
853
|
+
const held: Type[] = [
|
|
854
|
+
...parameters,
|
|
855
|
+
...(result === UNANSWERED || result === undefined ? [] : [result]),
|
|
856
|
+
];
|
|
857
|
+
// A parameter of a callback and a type argument, a rest tuple's among them, hold the
|
|
858
|
+
// accesses one level down: `fn: (payload: M[K]) => void` and `...[M[K]]`.
|
|
859
|
+
const nested = held.flatMap((type) => [
|
|
860
|
+
...partsOf(type),
|
|
861
|
+
...partsOf(type).flatMap((part) => {
|
|
862
|
+
const args = queries.typeArguments(part);
|
|
863
|
+
const calls = queries.signaturesOf(part, SignatureKind.Call);
|
|
864
|
+
return [
|
|
865
|
+
...(args === UNANSWERED ? [] : args),
|
|
866
|
+
...(calls === UNANSWERED ? [] : calls).flatMap((signature) =>
|
|
867
|
+
signature.parameters.flatMap((_parameter, index) => {
|
|
868
|
+
const one = queries.parameterType(signature, index);
|
|
869
|
+
return one === UNANSWERED || one === undefined ? [] : [one];
|
|
870
|
+
}),
|
|
871
|
+
),
|
|
872
|
+
];
|
|
843
873
|
}),
|
|
844
|
-
)
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const access = queries.indexedAccessOf(type);
|
|
851
|
-
if (access === UNANSWERED || access === undefined || access.object.isTypeParameter()) {
|
|
852
|
-
continue;
|
|
853
|
-
}
|
|
854
|
-
const names = access.index.isTypeParameter()
|
|
855
|
-
? parameters.flatMap((parameter, at) => {
|
|
856
|
-
if (!partsOf(parameter).some((part) => part.id === access.index.id)) {
|
|
857
|
-
return [];
|
|
874
|
+
]);
|
|
875
|
+
const found: Access[] = [];
|
|
876
|
+
for (const type of nested) {
|
|
877
|
+
const access = queries.indexedAccessOf(type);
|
|
878
|
+
if (access === UNANSWERED || access === undefined || access.object.isTypeParameter()) {
|
|
879
|
+
continue;
|
|
858
880
|
}
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
881
|
+
const names = access.index.isTypeParameter()
|
|
882
|
+
? parameters.flatMap((parameter, at) => {
|
|
883
|
+
if (!partsOf(parameter).some((part) => part.id === access.index.id)) {
|
|
884
|
+
return [];
|
|
885
|
+
}
|
|
886
|
+
const passed = queries.typeAtPosition(resolved, at);
|
|
887
|
+
return passed === UNANSWERED ? [] : literalTypeNames(passed, partsOf);
|
|
888
|
+
})
|
|
889
|
+
: literalTypeNames(access.index, partsOf);
|
|
890
|
+
if (names.length > 0) {
|
|
891
|
+
found.push({
|
|
892
|
+
file: site.file,
|
|
893
|
+
from: site.from,
|
|
894
|
+
at: site.node,
|
|
895
|
+
object: access.object,
|
|
896
|
+
index: names,
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
return found;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
const typeNodes = accesses.flatMap((one) => [
|
|
904
|
+
...("kind" in one.object ? [one.object] : []),
|
|
905
|
+
...(!Array.isArray(one.index) && "kind" in one.index ? [one.index] : []),
|
|
906
|
+
]);
|
|
907
|
+
const typeOf = new Map<Node, Type | typeof UNANSWERED>();
|
|
908
|
+
queries.typesAt(typeNodes).forEach((answer, index) => {
|
|
909
|
+
const node = typeNodes[index];
|
|
910
|
+
if (answer !== undefined && node !== undefined) {
|
|
911
|
+
typeOf.set(node, answer);
|
|
912
|
+
}
|
|
870
913
|
});
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
return found;
|
|
874
|
-
}
|
|
914
|
+
const asType = (side: TypeNode | Type): Type | typeof UNANSWERED | undefined =>
|
|
915
|
+
"kind" in side ? typeOf.get(side) : side;
|
|
875
916
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
917
|
+
for (const access of accesses) {
|
|
918
|
+
const type = asType(access.object);
|
|
919
|
+
const indexType = Array.isArray(access.index)
|
|
920
|
+
? undefined
|
|
921
|
+
: asType(access.index as TypeNode | Type);
|
|
922
|
+
const accessed = Array.isArray(access.index)
|
|
923
|
+
? (access.index as readonly string[])
|
|
924
|
+
: indexType === undefined || indexType === UNANSWERED
|
|
925
|
+
? undefined
|
|
926
|
+
: literalTypeNames(indexType, partsOf);
|
|
927
|
+
if (type === UNANSWERED || indexType === UNANSWERED) {
|
|
928
|
+
found.push({
|
|
929
|
+
kind: "held",
|
|
930
|
+
from: access.from,
|
|
931
|
+
...(accessed === undefined ? {} : { names: accessed }),
|
|
932
|
+
...(type === UNANSWERED || type === undefined
|
|
933
|
+
? accessed === undefined
|
|
934
|
+
? { members: true as const }
|
|
935
|
+
: {}
|
|
936
|
+
: { types: partsOf(type) }),
|
|
937
|
+
});
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
if (type === undefined || accessed === undefined) {
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
for (const part of partsOf(type)) {
|
|
944
|
+
const properties = queries.propertiesOf(part);
|
|
945
|
+
if (properties === UNANSWERED) {
|
|
946
|
+
found.push({ kind: "held", from: access.from, names: accessed });
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
for (const property of properties) {
|
|
950
|
+
if (!accessed.includes(property.escapedName)) {
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
for (const to of chains.declarationsOf(property)) {
|
|
954
|
+
found.push({
|
|
955
|
+
kind: "named",
|
|
956
|
+
from: access.from,
|
|
957
|
+
to,
|
|
958
|
+
file: access.file,
|
|
959
|
+
at: access.at,
|
|
960
|
+
use: "read",
|
|
961
|
+
via: "batch",
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
923
966
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
967
|
+
return found;
|
|
968
|
+
},
|
|
969
|
+
};
|
|
970
|
+
},
|
|
971
|
+
};
|
|
929
972
|
|
|
930
973
|
/** The arguments a call or a `new` expression passes, none for a type reference. */
|
|
931
974
|
function argumentsOf(node: Site["node"]): readonly Expression[] {
|