@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/THIRD_PARTY_NOTICES.md +27 -0
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/alias-chain.js +35 -9
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +274 -496
- package/dist/src/augmentations.js +64 -3
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/bindings.js +382 -0
- package/dist/src/commands/held.js +499 -0
- package/dist/src/commands/read.js +161 -0
- package/dist/src/commands/shell.js +169 -0
- package/dist/src/commands/tools.js +1847 -0
- package/dist/src/component-files.js +3 -2
- package/dist/src/component-layer.js +4 -2
- package/dist/src/config.js +6 -82
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/consumers.js +10 -38
- package/dist/src/contextual-uses.js +57 -26
- package/dist/src/contract/config.generated.js +561 -0
- package/dist/src/contract/contract.generated.js +1370 -0
- package/dist/src/contract/report.generated.js +866 -0
- package/dist/src/dependencies.js +165 -122
- package/dist/src/destructuring.js +1 -19
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +181 -168
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
- package/dist/src/entries/conventions.js +740 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
- package/dist/src/entries/run-directories.js +77 -0
- package/dist/src/entries/sources.js +144 -0
- package/dist/src/entries/static-module.js +670 -0
- package/dist/src/entries/test-runners.js +650 -0
- package/dist/src/entries/workflow-steps.js +345 -0
- package/dist/src/exemptions/argument-places.js +131 -0
- package/dist/src/exemptions/calls.js +338 -0
- package/dist/src/exemptions/classes.js +13 -0
- package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
- package/dist/src/exemptions/detectors.js +48 -0
- package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
- package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
- package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
- package/dist/src/exemptions/generated-file.js +241 -0
- package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
- package/dist/src/exemptions/installed-globals.js +173 -0
- package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
- package/dist/src/exemptions/lifecycle.js +150 -0
- package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
- package/dist/src/exemptions/serialization-contract.js +1276 -0
- package/dist/src/exemptions/sites.js +182 -0
- package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
- package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
- package/dist/src/exposure.js +400 -0
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +3 -26
- package/dist/src/findings/completion.js +109 -56
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +27 -41
- package/dist/src/{implementations.js → findings/implementations.js} +3 -3
- package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +16 -13
- package/dist/src/findings/non-code-artifacts.js +17 -12
- package/dist/src/findings/reads-and-writes.js +86 -27
- package/dist/src/findings/self-check.js +44 -30
- package/dist/src/findings/unused-declarations.js +29 -45
- package/dist/src/findings/visibility-narrowing.js +23 -31
- package/dist/src/findings-pass.js +13 -21
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +67 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/git-ignore.js +39 -26
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/index/values.js +124 -0
- package/dist/src/index.js +2 -2
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/intra-function-parts.js +63 -43
- package/dist/src/inventory/commonjs.js +507 -0
- package/dist/src/inventory/enumerate.js +167 -0
- package/dist/src/inventory/syntax.js +236 -0
- package/dist/src/inventory.js +323 -724
- package/dist/src/javascript-file.js +48 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +126 -107
- package/dist/src/kinds.js +3 -366
- package/dist/src/{components.js → liveness/components.js} +2 -3
- package/dist/src/{graph.js → liveness/graph.js} +52 -28
- package/dist/src/liveness/matrix.js +99 -0
- package/dist/src/liveness/sweep.js +558 -0
- package/dist/src/load/classify.js +289 -0
- package/dist/src/load/diagnostics.js +87 -0
- package/dist/src/load/discover.js +285 -0
- package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
- package/dist/src/load/expected-module.js +136 -0
- package/dist/src/load/load.js +27 -0
- package/dist/src/load/module-lookup.js +37 -0
- package/dist/src/load/package-scope.js +56 -0
- package/dist/src/load/plan.js +313 -0
- package/dist/src/load/specifiers.js +113 -0
- package/dist/src/load/synthesize.js +152 -0
- package/dist/src/load/test-globals.js +207 -0
- package/dist/src/load/test-joins.js +82 -0
- package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
- package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
- package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
- package/dist/src/{workspace.js → load/workspace.js} +62 -124
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +82 -16
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +134 -0
- package/dist/src/position.js +43 -1
- package/dist/src/print.js +11 -79
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +95 -0
- package/dist/src/ref.js +12 -20
- package/dist/src/references/read-rule.js +1 -0
- package/dist/src/references/read-rules.js +48 -0
- package/dist/src/references/sink.js +237 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +117 -1074
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +57 -41
- package/dist/src/reporters/annotations.js +15 -8
- package/dist/src/reporters/sarif.js +16 -10
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +246 -730
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
- package/dist/src/roots/manifest.js +216 -0
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +487 -0
- package/dist/src/roots/unseen-loads.js +236 -0
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -343
- package/dist/src/scope.js +38 -115
- package/dist/src/session.js +37 -29
- package/dist/src/source-files.js +6 -10
- package/dist/src/stores.js +4 -2
- package/dist/src/suppress-file.js +25 -28
- package/dist/src/suppress-inline.js +36 -83
- package/dist/src/suppress.js +50 -71
- package/dist/src/symbol-keys.js +92 -88
- package/dist/src/tests/file-class.js +76 -0
- package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
- package/dist/src/{test-support.js → tests/support.js} +5 -12
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +298 -0
- package/dist/src/text/yaml.js +684 -0
- package/dist/src/type-errors.js +11 -232
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/vendor/unbash/ansi-c.js +132 -0
- package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
- package/dist/src/vendor/unbash/arithmetic.js +591 -0
- package/dist/src/vendor/unbash/assignment.js +131 -0
- package/dist/src/vendor/unbash/chars.js +48 -0
- package/dist/src/vendor/unbash/command.js +41 -0
- package/dist/src/vendor/unbash/expansion.js +80 -0
- package/dist/src/vendor/unbash/glob.js +268 -0
- package/dist/src/vendor/unbash/heredoc.js +27 -0
- package/dist/src/vendor/unbash/internal-types.js +1 -0
- package/dist/src/vendor/unbash/lexer.js +4274 -0
- package/dist/src/vendor/unbash/limits.js +3 -0
- package/dist/src/vendor/unbash/parser.js +1366 -0
- package/dist/src/vendor/unbash/parts.js +57 -0
- package/dist/src/vendor/unbash/substitution-context.js +8 -0
- package/dist/src/vendor/unbash/traversal.js +212 -0
- package/dist/src/vendor/unbash/types.js +1 -0
- package/dist/src/vendor/unbash/word-value.js +61 -0
- package/dist/src/vendor/unbash/word.js +40 -0
- package/dist/src/verbs/analyze.js +194 -127
- package/dist/src/verbs/describe.js +13 -18
- package/dist/src/verbs/explain.js +85 -139
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +6 -4
- package/dist/src/verbs/print-retained.js +30 -6
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +14 -3
- package/jsr.json +2 -1
- package/package.json +14 -8
- package/src/alias-chain.ts +40 -11
- package/src/amd.ts +130 -0
- package/src/analysis.ts +426 -733
- package/src/augmentations.ts +93 -4
- package/src/automatic-types.ts +12 -30
- package/src/bindings.ts +460 -0
- package/src/commands/held.ts +632 -0
- package/src/commands/read.ts +242 -0
- package/src/commands/shell.ts +228 -0
- package/src/commands/tools.ts +2382 -0
- package/src/component-files.ts +4 -2
- package/src/component-layer.ts +4 -2
- package/src/config.ts +31 -302
- package/src/conformance-record.ts +2 -2
- package/src/consumers.ts +16 -66
- package/src/contextual-uses.ts +66 -34
- package/src/contract/config.generated.ts +821 -0
- package/src/contract/contract.generated.ts +1453 -0
- package/src/contract/report.generated.ts +1241 -0
- package/src/dependencies.ts +223 -128
- package/src/destructuring.ts +1 -31
- package/src/edges.ts +41 -140
- package/src/element-access.ts +190 -187
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
- package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
- package/src/{conventions.ts → entries/conventions.ts} +367 -583
- package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
- package/src/entries/run-directories.ts +108 -0
- package/src/entries/sources.ts +266 -0
- package/src/entries/static-module.ts +858 -0
- package/src/entries/test-runners.ts +835 -0
- package/src/entries/workflow-steps.ts +432 -0
- package/src/exemptions/argument-places.ts +198 -0
- package/src/exemptions/calls.ts +483 -0
- package/src/exemptions/classes.ts +49 -0
- package/src/exemptions/decorator.ts +56 -0
- package/src/exemptions/detectors.ts +75 -0
- package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
- package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
- package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
- package/src/exemptions/generated-file.ts +318 -0
- package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
- package/src/exemptions/installed-globals.ts +255 -0
- package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
- package/src/exemptions/lifecycle.ts +286 -0
- package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
- package/src/exemptions/serialization-contract.ts +1729 -0
- package/src/exemptions/sites.ts +293 -0
- package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
- package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
- package/src/exposure.ts +492 -0
- package/src/extensions.ts +45 -0
- package/src/facts.ts +46 -0
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +15 -25
- package/src/finding.ts +10 -10
- package/src/findings/boundary.ts +11 -0
- package/src/findings/completion.ts +133 -64
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +9 -10
- package/src/findings/emitters.ts +38 -52
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
- package/src/findings/interfaces.ts +7 -9
- package/src/findings/intra-function.ts +16 -14
- package/src/findings/non-code-artifacts.ts +24 -15
- package/src/findings/reads-and-writes.ts +118 -41
- package/src/findings/self-check.ts +51 -38
- package/src/findings/unused-declarations.ts +31 -49
- package/src/findings/visibility-narrowing.ts +36 -40
- package/src/findings-pass.ts +15 -31
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +96 -0
- package/src/fs/tree.ts +110 -0
- package/src/git-ignore.ts +50 -26
- package/src/host.ts +12 -5
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/index/values.ts +170 -0
- package/src/index.ts +2 -2
- package/src/indexed-access.ts +570 -527
- package/src/intra-function-parts.ts +73 -44
- package/src/inventory/commonjs.ts +696 -0
- package/src/inventory/enumerate.ts +203 -0
- package/src/inventory/syntax.ts +311 -0
- package/src/inventory.ts +442 -895
- package/src/javascript-file.ts +54 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +133 -122
- package/src/kinds.ts +5 -413
- package/src/{components.ts → liveness/components.ts} +4 -6
- package/src/{graph.ts → liveness/graph.ts} +100 -35
- package/src/liveness/matrix.ts +162 -0
- package/src/liveness/sweep.ts +855 -0
- package/src/load/classify.ts +433 -0
- package/src/load/diagnostics.ts +154 -0
- package/src/load/discover.ts +471 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +194 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/package-scope.ts +74 -0
- package/src/load/plan.ts +513 -0
- package/src/load/specifiers.ts +171 -0
- package/src/load/synthesize.ts +230 -0
- package/src/load/test-globals.ts +251 -0
- package/src/load/test-joins.ts +98 -0
- package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
- package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/partial.ts +3 -2
- package/src/paths.ts +92 -16
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +189 -0
- package/src/position.ts +44 -1
- package/src/print.ts +12 -92
- package/src/product.ts +18 -0
- package/src/query.ts +201 -10
- package/src/ref.ts +12 -20
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +314 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +187 -1450
- package/src/report-schema.ts +68 -0
- package/src/report.ts +103 -226
- package/src/reporters/annotations.ts +22 -11
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -4
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +29 -16
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +284 -1115
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
- package/src/roots/manifest.ts +303 -0
- package/src/roots/published-reach.ts +486 -0
- package/src/{roots.ts → roots/root-set.ts} +286 -469
- package/src/roots/unseen-loads.ts +345 -0
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -388
- package/src/scope.ts +46 -138
- package/src/session.ts +87 -55
- package/src/source-files.ts +6 -11
- package/src/stores.ts +15 -3
- package/src/suppress-file.ts +24 -33
- package/src/suppress-inline.ts +55 -91
- package/src/suppress.ts +78 -79
- package/src/symbol-keys.ts +104 -107
- package/src/tests/file-class.ts +135 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +15 -21
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.ts +388 -0
- package/src/text/yaml.ts +747 -0
- package/src/type-errors.ts +18 -288
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/vendor/unbash/LICENSE +15 -0
- package/src/vendor/unbash/VENDORED.md +16 -0
- package/src/vendor/unbash/ansi-c.ts +132 -0
- package/src/vendor/unbash/arithmetic-parts.ts +53 -0
- package/src/vendor/unbash/arithmetic.ts +641 -0
- package/src/vendor/unbash/assignment.ts +163 -0
- package/src/vendor/unbash/chars.ts +48 -0
- package/src/vendor/unbash/command.ts +47 -0
- package/src/vendor/unbash/expansion.ts +144 -0
- package/src/vendor/unbash/glob.ts +284 -0
- package/src/vendor/unbash/heredoc.ts +34 -0
- package/src/vendor/unbash/internal-types.ts +94 -0
- package/src/vendor/unbash/lexer.ts +4352 -0
- package/src/vendor/unbash/limits.ts +3 -0
- package/src/vendor/unbash/parser.ts +1612 -0
- package/src/vendor/unbash/parts.ts +96 -0
- package/src/vendor/unbash/substitution-context.ts +20 -0
- package/src/vendor/unbash/traversal.ts +182 -0
- package/src/vendor/unbash/types.ts +660 -0
- package/src/vendor/unbash/word-value.ts +64 -0
- package/src/vendor/unbash/word.ts +50 -0
- package/src/verbs/analyze.ts +255 -164
- package/src/verbs/describe.ts +19 -17
- package/src/verbs/explain.ts +93 -169
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +36 -6
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/dist/src/base-url.js +0 -18
- package/dist/src/calls.js +0 -155
- package/dist/src/conventions.js +0 -937
- package/dist/src/discover.js +0 -468
- package/dist/src/entry-points.js +0 -529
- package/dist/src/exempt-classes.js +0 -75
- package/dist/src/exempt.js +0 -209
- package/dist/src/generated-file.js +0 -95
- package/dist/src/glob.js +0 -65
- package/dist/src/manifest.js +0 -165
- package/dist/src/matrix.js +0 -246
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/roots.js +0 -672
- package/dist/src/serialization-contract.js +0 -611
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/sweep.js +0 -224
- package/dist/src/test-joins.js +0 -101
- package/dist/src/value-flow.js +0 -74
- package/dist/src/version.js +0 -7
- package/dist/src/workflow-steps.js +0 -185
- package/src/base-url.ts +0 -24
- package/src/calls.ts +0 -225
- package/src/decorator.ts +0 -78
- package/src/discover.ts +0 -653
- package/src/entry-points.ts +0 -687
- package/src/exempt-classes.ts +0 -123
- package/src/exempt.ts +0 -323
- package/src/generated-file.ts +0 -111
- package/src/glob.ts +0 -67
- package/src/manifest.ts +0 -234
- package/src/matrix.ts +0 -423
- package/src/pnpm-workspace.ts +0 -135
- package/src/serialization-contract.ts +0 -849
- package/src/setup-failure.ts +0 -39
- package/src/sweep.ts +0 -347
- package/src/test-joins.ts +0 -120
- package/src/value-flow.ts +0 -104
- package/src/version.ts +0 -7
- package/src/workflow-steps.ts +0 -216
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The calls and decorators of one project that the configured classes read: what each
|
|
3
|
+
* call invokes, a call through a method of `Function.prototype` included, and which of the
|
|
4
|
+
* target's classes a call passes or a decorator is attached to. A class is passed by each
|
|
5
|
+
* value an argument can carry ({@link carriedValues}), named directly or through
|
|
6
|
+
* variables, and a decorator written as a call is a call.
|
|
7
|
+
*/
|
|
8
|
+
import { isArrayLiteralExpression, isArrowFunction, isBindingElement, isCallExpression, isDecorator, isFunctionDeclaration, isFunctionExpression, isIdentifier, isMethodDeclaration, isParameterDeclaration, isPropertyAccessExpression, isPropertyAssignment, isPropertyDeclaration, isShorthandPropertyAssignment, isSpreadElement, isVariableDeclaration, } from "@typescript/native/ast";
|
|
9
|
+
import { ObjectFlags, SymbolFlags, } from "@typescript/native/sync";
|
|
10
|
+
import { resolvedTargets } from "../alias-chain.js";
|
|
11
|
+
import { carriedValues, nameOf } from "../index/values.js";
|
|
12
|
+
import { must } from "../query.js";
|
|
13
|
+
import { parenthesesRemoved, unwrapped } from "../unwrap.js";
|
|
14
|
+
/** The callee one decorator names: its expression, or the callee of the call it writes. */
|
|
15
|
+
export function decoratorCallee(decorator) {
|
|
16
|
+
const expression = decorator.expression;
|
|
17
|
+
return nameOf(isCallExpression(expression) ? expression.expression : expression);
|
|
18
|
+
}
|
|
19
|
+
/** How one decorator is spelled in a record: its expression, without a call's arguments. */
|
|
20
|
+
export function spelledDecorator(decorator) {
|
|
21
|
+
const expression = decorator.expression;
|
|
22
|
+
const named = isCallExpression(expression) ? expression.expression : expression;
|
|
23
|
+
return `@${named.getText().replace(/\s+/gu, "")}`;
|
|
24
|
+
}
|
|
25
|
+
/** The decorators written on one declaration. */
|
|
26
|
+
export function decoratorsOf(node) {
|
|
27
|
+
return (node.modifiers ?? []).filter(isDecorator);
|
|
28
|
+
}
|
|
29
|
+
/** The methods of `Function.prototype` that invoke a function with arguments of their own. */
|
|
30
|
+
const FUNCTION_METHODS = new Set(["call", "apply", "bind"]);
|
|
31
|
+
/** The interfaces of the standard library that declare those methods for a function value. */
|
|
32
|
+
const FUNCTION_INTERFACES = new Set([
|
|
33
|
+
"Function",
|
|
34
|
+
"CallableFunction",
|
|
35
|
+
"NewableFunction",
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* The invocation a call writes through a method of `Function.prototype`, read from
|
|
39
|
+
* the syntax alone: `f.call(self, a)`, `f.apply(self, [a])`, `f.bind(self, a)`, which
|
|
40
|
+
* passes `a` though nothing calls the bound function there, because the bound function
|
|
41
|
+
* carries `a` to wherever it is called and that call is not followed, and
|
|
42
|
+
* `f.bind(self, a)(b)`, which passes `b` after it. An `apply` argument
|
|
43
|
+
* that is no array literal is the value of the first parameter, whose elements it
|
|
44
|
+
* carries. Whether the method is the prototype's is resolution's to say.
|
|
45
|
+
*/
|
|
46
|
+
function throughMethod(call) {
|
|
47
|
+
const expression = parenthesesRemoved(call.expression);
|
|
48
|
+
if (isPropertyAccessExpression(expression) && FUNCTION_METHODS.has(expression.name.text)) {
|
|
49
|
+
const [, ...rest] = call.arguments;
|
|
50
|
+
let passed = rest;
|
|
51
|
+
let listed = false;
|
|
52
|
+
if (expression.name.text === "apply") {
|
|
53
|
+
const list = rest[0] === undefined ? undefined : parenthesesRemoved(rest[0]);
|
|
54
|
+
listed = list !== undefined && !isArrayLiteralExpression(list);
|
|
55
|
+
passed = list === undefined ? [] : isArrayLiteralExpression(list) ? list.elements : [list];
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
method: expression.name,
|
|
59
|
+
invocation: { callee: expression.expression, arguments: passed, indirect: true, listed },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (isCallExpression(expression)) {
|
|
63
|
+
const bound = parenthesesRemoved(expression.expression);
|
|
64
|
+
if (isPropertyAccessExpression(bound) && bound.name.text === "bind") {
|
|
65
|
+
return {
|
|
66
|
+
method: bound.name,
|
|
67
|
+
invocation: {
|
|
68
|
+
callee: bound.expression,
|
|
69
|
+
arguments: [...expression.arguments.slice(1), ...call.arguments],
|
|
70
|
+
indirect: true,
|
|
71
|
+
listed: false,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* What each of a project's calls invokes. A call through `call`, `apply` or `bind`
|
|
80
|
+
* invokes the function the method is read from only where the method is the standard
|
|
81
|
+
* library's: the program's own `call` and `Reflect.apply` pass nothing on.
|
|
82
|
+
*/
|
|
83
|
+
export function invocations(project, calls) {
|
|
84
|
+
const forms = new Map();
|
|
85
|
+
for (const call of calls) {
|
|
86
|
+
const form = throughMethod(call);
|
|
87
|
+
if (form !== undefined) {
|
|
88
|
+
forms.set(call, form);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const callees = resolvedTargets(project, [
|
|
92
|
+
...calls.flatMap((call) => nameOf(call.expression) ?? []),
|
|
93
|
+
...[...forms.values()].flatMap((form) => {
|
|
94
|
+
const name = nameOf(form.invocation.callee);
|
|
95
|
+
return name === undefined ? [form.method] : [form.method, name];
|
|
96
|
+
}),
|
|
97
|
+
]);
|
|
98
|
+
const standard = (method) => method.declarations.some((handle) => project.program.getSourceFileMetadata(handle.path)?.isDefaultLibrary === true) && FUNCTION_INTERFACES.has(must(project.queries.parentOf(method))?.name ?? "");
|
|
99
|
+
const of = (call) => {
|
|
100
|
+
const form = forms.get(call);
|
|
101
|
+
const method = form === undefined ? undefined : callees.get(form.method);
|
|
102
|
+
return form !== undefined && method !== undefined && standard(method)
|
|
103
|
+
? form.invocation
|
|
104
|
+
: { callee: call.expression, arguments: call.arguments, indirect: false, listed: false };
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
of,
|
|
108
|
+
callee: (call) => {
|
|
109
|
+
const name = nameOf(of(call).callee);
|
|
110
|
+
return name === undefined ? undefined : callees.get(name);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/** The declaration a shorthand property's value resolves to, an import followed to what it names. */
|
|
115
|
+
function shorthandTarget(project, node) {
|
|
116
|
+
const value = must(project.shorthandValueAt(project.handle(node)));
|
|
117
|
+
if (value === undefined || (value.flags & SymbolFlags.Alias) === 0) {
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
const aliased = must(project.queries.aliased(value));
|
|
121
|
+
return aliased.declarations.length === 0 ? undefined : aliased;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* What one carried value holds: the declaration its name resolves to, and the classes and
|
|
125
|
+
* functions the checker's type at it holds ({@link constructedAt}). `known` holds names
|
|
126
|
+
* already resolved in a batch.
|
|
127
|
+
*/
|
|
128
|
+
function heldBy(project, value, known) {
|
|
129
|
+
const { name } = value;
|
|
130
|
+
if (name === undefined) {
|
|
131
|
+
return { named: undefined, typed: constructedAt(project, value.site) };
|
|
132
|
+
}
|
|
133
|
+
if (value.shorthand) {
|
|
134
|
+
return { named: shorthandTarget(project, name), typed: [] };
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
named: known?.get(name) ?? resolvedTargets(project, [name]).get(name),
|
|
138
|
+
typed: constructedAt(project, value.site),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/** The classes of the target each call passes, by the call, as {@link classesCarried} reads its invocation's arguments. */
|
|
142
|
+
export function classesPassed(project, held, chains, sites, calls) {
|
|
143
|
+
const carried = classesCarried(project, held, chains, sites, calls.map((call) => sites.invocations.of(call).arguments));
|
|
144
|
+
return new Map(calls.map((call, at) => [call, carried[at] ?? []]));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The classes of the target each group of written values carries: each class a value
|
|
148
|
+
* can carry holds as a constructor, as the checker types it. A name whose type erases
|
|
149
|
+
* the class is followed through what its declaration binds ({@link boundTo}) and, for a
|
|
150
|
+
* parameter, through what each call of its function passes at its place, so a class
|
|
151
|
+
* handed to a wrapper is passed. A class is used at each value that carries it. A class
|
|
152
|
+
* of another program is carried by nothing.
|
|
153
|
+
*/
|
|
154
|
+
export function classesCarried(project, held, chains, sites, groups) {
|
|
155
|
+
const { invocations: invoked } = sites;
|
|
156
|
+
const passed = groups.map((written) => written.flatMap(carriedValues));
|
|
157
|
+
const targets = resolvedTargets(project, passed.flat().flatMap((value) => (value.shorthand ? [] : (value.name ?? []))));
|
|
158
|
+
const classes = new Set(held.symbols.filter((symbol) => symbol.kind === "class").map((symbol) => symbol.id));
|
|
159
|
+
let calling;
|
|
160
|
+
const callsOfFunction = (symbol) => {
|
|
161
|
+
calling ??= callsByDeclaration(project, sites.calls.map((one) => one.call), invoked);
|
|
162
|
+
return symbol.declarations.flatMap((handle) => calling?.get(keyOf(handle)) ?? []);
|
|
163
|
+
};
|
|
164
|
+
const classesOf = (value, seen) => {
|
|
165
|
+
const { named, typed } = heldBy(project, value, targets);
|
|
166
|
+
return [
|
|
167
|
+
...typed.flatMap((symbol) => chains.declarationsOf(symbol).filter((id) => classes.has(id))),
|
|
168
|
+
...(named === undefined ? [] : reached(named, seen)),
|
|
169
|
+
];
|
|
170
|
+
};
|
|
171
|
+
const reached = (symbol, seen) => {
|
|
172
|
+
const ids = chains.declarationsOf(symbol).filter((id) => classes.has(id));
|
|
173
|
+
if (ids.length > 0 || seen.has(symbol.id)) {
|
|
174
|
+
return ids;
|
|
175
|
+
}
|
|
176
|
+
seen.add(symbol.id);
|
|
177
|
+
const through = (written) => carriedValues(written).flatMap((value) => classesOf(value, seen));
|
|
178
|
+
return symbol.declarations.flatMap((handle) => {
|
|
179
|
+
const node = project.declarationAt(handle)?.node;
|
|
180
|
+
if (node === undefined) {
|
|
181
|
+
return [];
|
|
182
|
+
}
|
|
183
|
+
if (isParameterDeclaration(node)) {
|
|
184
|
+
return argumentsAt(project, node, callsOfFunction, invoked).flatMap(through);
|
|
185
|
+
}
|
|
186
|
+
const bound = boundTo(project, node);
|
|
187
|
+
return [
|
|
188
|
+
...(bound.written === undefined ? [] : through(bound.written)),
|
|
189
|
+
...bound.symbols.flatMap((next) => reached(next, seen)),
|
|
190
|
+
];
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
return passed.map((values) => {
|
|
194
|
+
const uses = new Map();
|
|
195
|
+
for (const value of values) {
|
|
196
|
+
for (const id of classesOf(value, new Set())) {
|
|
197
|
+
uses.set(`${id}\u0000${String(value.site.pos)}`, { id, site: value.site });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return [...uses.values()];
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The symbols of the classes and functions the checker's type at one expression holds as
|
|
205
|
+
* values, each member of a union: the static side of a class or a function is an
|
|
206
|
+
* anonymous type its declaration's symbol names, which an instance's type is not.
|
|
207
|
+
*/
|
|
208
|
+
function constructedAt(project, written) {
|
|
209
|
+
return heldIn(project, must(project.queries.typeAt(unwrapped(written))));
|
|
210
|
+
}
|
|
211
|
+
/** The classes and functions one type holds as values, as {@link constructedAt} reads them. */
|
|
212
|
+
function heldIn(project, type) {
|
|
213
|
+
const { queries } = project;
|
|
214
|
+
return (type === undefined ? [] : must(queries.constituents(type))).flatMap((part) => {
|
|
215
|
+
if (!part.isObjectType() || (part.objectFlags & ObjectFlags.Anonymous) === 0) {
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
return must(queries.symbolOfType(part)) ?? [];
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* What a variable, a property or a destructured binding binds its name to: a variable's
|
|
223
|
+
* or a property's initializer, the value a shorthand property names, or the property of
|
|
224
|
+
* the destructured value a binding element reads.
|
|
225
|
+
*/
|
|
226
|
+
function boundTo(project, node) {
|
|
227
|
+
if (isShorthandPropertyAssignment(node)) {
|
|
228
|
+
const value = shorthandTarget(project, node);
|
|
229
|
+
return { symbols: value === undefined ? [] : [value] };
|
|
230
|
+
}
|
|
231
|
+
if (isBindingElement(node)) {
|
|
232
|
+
const key = node.propertyName ?? node.name;
|
|
233
|
+
if (key === undefined || !isIdentifier(key)) {
|
|
234
|
+
return { symbols: [] };
|
|
235
|
+
}
|
|
236
|
+
const source = must(project.queries.typeAt(node.parent));
|
|
237
|
+
const property = source === undefined
|
|
238
|
+
? undefined
|
|
239
|
+
: must(project.queries.propertiesOf(source)).find((one) => one.name === key.text);
|
|
240
|
+
return { symbols: property === undefined ? [] : [property] };
|
|
241
|
+
}
|
|
242
|
+
const written = initializerOf(node);
|
|
243
|
+
return written === undefined ? { symbols: [] } : { written, symbols: [] };
|
|
244
|
+
}
|
|
245
|
+
/** The value a variable or a property declaration binds its name to, where it writes one. */
|
|
246
|
+
function initializerOf(node) {
|
|
247
|
+
return isVariableDeclaration(node) || isPropertyAssignment(node) || isPropertyDeclaration(node)
|
|
248
|
+
? node.initializer
|
|
249
|
+
: undefined;
|
|
250
|
+
}
|
|
251
|
+
/** The key of one declaration a symbol names, the same for each symbol the checker makes of it. */
|
|
252
|
+
function keyOf(handle) {
|
|
253
|
+
return `${handle.path}#${String(handle.index)}`;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Every call of the project by the declarations its invoked function can be: the function
|
|
257
|
+
* or the method it names, or else each function the checker's type at it holds, wherever
|
|
258
|
+
* that value came from. A name is also followed through what its binding copies
|
|
259
|
+
* ({@link boundTo}), which is how a call reaches a function an annotation erases.
|
|
260
|
+
* Only the target's own declarations are keys, as only its own functions are asked for.
|
|
261
|
+
*/
|
|
262
|
+
function callsByDeclaration(project, calls, invoked) {
|
|
263
|
+
const own = project.ownPaths();
|
|
264
|
+
const named = new Map();
|
|
265
|
+
const keysOf = (symbol, seen) => {
|
|
266
|
+
const known = named.get(symbol.id);
|
|
267
|
+
if (known !== undefined || seen.has(symbol.id)) {
|
|
268
|
+
return known ?? [];
|
|
269
|
+
}
|
|
270
|
+
seen.add(symbol.id);
|
|
271
|
+
const keys = symbol.declarations
|
|
272
|
+
.filter((handle) => own.has(handle.path))
|
|
273
|
+
.flatMap((handle) => {
|
|
274
|
+
const node = project.declarationAt(handle)?.node;
|
|
275
|
+
const bound = node === undefined ? { symbols: [] } : boundTo(project, node);
|
|
276
|
+
const copied = [
|
|
277
|
+
...bound.symbols,
|
|
278
|
+
...(bound.written === undefined ? [] : carriedValues(bound.written)).flatMap((value) => {
|
|
279
|
+
const { named: next, typed } = heldBy(project, value);
|
|
280
|
+
return [...typed, ...(next === undefined ? [] : [next])];
|
|
281
|
+
}),
|
|
282
|
+
];
|
|
283
|
+
return [keyOf(handle), ...copied.flatMap((next) => keysOf(next, seen))];
|
|
284
|
+
});
|
|
285
|
+
named.set(symbol.id, keys);
|
|
286
|
+
return keys;
|
|
287
|
+
};
|
|
288
|
+
const declared = (call) => ((invoked.callee(call)?.flags ?? 0) & (SymbolFlags.Function | SymbolFlags.Method)) !== 0;
|
|
289
|
+
const typed = calls.filter((call) => !declared(call));
|
|
290
|
+
const types = new Map(project.queries
|
|
291
|
+
.typesAt(typed.map((call) => unwrapped(invoked.of(call).callee)))
|
|
292
|
+
.map((type, index) => [typed[index], must(type)]));
|
|
293
|
+
const found = new Map();
|
|
294
|
+
for (const call of calls) {
|
|
295
|
+
const callee = invoked.callee(call);
|
|
296
|
+
const held = [
|
|
297
|
+
...(callee === undefined ? [] : [callee]),
|
|
298
|
+
...(types.has(call) ? heldIn(project, types.get(call)) : []),
|
|
299
|
+
];
|
|
300
|
+
for (const key of new Set(held.flatMap((symbol) => keysOf(symbol, new Set())))) {
|
|
301
|
+
found.set(key, [...(found.get(key) ?? []), call]);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return found;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* What each call of the function a parameter belongs to passes at the parameter's place,
|
|
308
|
+
* every argument from there on for a rest parameter, as the call's invocation binds them.
|
|
309
|
+
* The function is the one the checker's type at its own declaration names, so a function
|
|
310
|
+
* with no name of its own is called too. A `this` parameter takes no place, and an
|
|
311
|
+
* argument at or after a spread argument passes at every place the spread's length can
|
|
312
|
+
* move it to.
|
|
313
|
+
*/
|
|
314
|
+
function argumentsAt(project, parameter, callsOfFunction, invoked) {
|
|
315
|
+
const owner = parameter.parent;
|
|
316
|
+
if (!isFunctionDeclaration(owner) &&
|
|
317
|
+
!isMethodDeclaration(owner) &&
|
|
318
|
+
!isArrowFunction(owner) &&
|
|
319
|
+
!isFunctionExpression(owner)) {
|
|
320
|
+
return [];
|
|
321
|
+
}
|
|
322
|
+
const calls = new Set(constructedAt(project, owner).flatMap(callsOfFunction));
|
|
323
|
+
const [first] = owner.parameters;
|
|
324
|
+
const erased = first !== undefined && isIdentifier(first.name) && first.name.text === "this";
|
|
325
|
+
const place = owner.parameters.indexOf(parameter) - (erased ? 1 : 0);
|
|
326
|
+
const rest = parameter.dotDotDotToken !== undefined;
|
|
327
|
+
return [...calls].flatMap((call) => {
|
|
328
|
+
let spreads = 0;
|
|
329
|
+
return invoked.of(call).arguments.flatMap((argument, index) => {
|
|
330
|
+
const spread = isSpreadElement(argument);
|
|
331
|
+
const earliest = index - spreads;
|
|
332
|
+
spreads += spread ? 1 : 0;
|
|
333
|
+
const open = spread || earliest < index;
|
|
334
|
+
const lands = open ? rest || earliest <= place : rest ? index >= place : index === place;
|
|
335
|
+
return lands ? [spread ? argument.expression : argument] : [];
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EXEMPTION_CLASSES } from "../contract/contract.generated.js";
|
|
2
|
+
function runsOnTS(row) {
|
|
3
|
+
const languages = row.languages;
|
|
4
|
+
return languages.includes("ts");
|
|
5
|
+
}
|
|
6
|
+
const TS_ROWS = EXEMPTION_CLASSES.filter(runsOnTS);
|
|
7
|
+
/** The classes that run on TypeScript, in the vocabulary's order. */
|
|
8
|
+
export const TS_EXEMPTION_CLASSES = TS_ROWS.map((row) => row.class);
|
|
9
|
+
const VISIBILITY = new Map(TS_ROWS.map((row) => [row.class, row.typescriptVisibility]));
|
|
10
|
+
/** Which private members one class that runs on TypeScript may retain. */
|
|
11
|
+
export function typescriptVisibilityOf(exemptionClass) {
|
|
12
|
+
return VISIBILITY.get(exemptionClass) ?? { private: false, privateName: false };
|
|
13
|
+
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* static members of a decorated class included.
|
|
8
8
|
*/
|
|
9
9
|
import { decoratorsOf, spelledDecorator } from "./calls.js";
|
|
10
|
-
import { isParameterProperty
|
|
11
|
-
import { renderPosition } from "
|
|
10
|
+
import { isParameterProperty } from "../inventory.js";
|
|
11
|
+
import { renderPosition } from "../position.js";
|
|
12
12
|
/** The kinds of declaration a decorator is attached to and holds back. */
|
|
13
13
|
const DECORATED = new Set(["class", "method", "class-member"]);
|
|
14
14
|
/**
|
|
@@ -16,7 +16,7 @@ const DECORATED = new Set(["class", "method", "class-member"]);
|
|
|
16
16
|
* class, recorded at the decorator.
|
|
17
17
|
*/
|
|
18
18
|
export function decorator(input) {
|
|
19
|
-
const {
|
|
19
|
+
const { held, sites, targetRoot } = input;
|
|
20
20
|
const byId = new Map(held.symbols.map((symbol) => [symbol.id, symbol]));
|
|
21
21
|
const membersOf = new Map();
|
|
22
22
|
for (const symbol of held.symbols) {
|
|
@@ -30,32 +30,21 @@ export function decorator(input) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
const decorated = [];
|
|
34
33
|
// A decorated class's container passes each constructor argument, which keeps the
|
|
35
|
-
// parameter, not the member a parameter property stores it in.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
node.forEachChild(visit);
|
|
55
|
-
};
|
|
56
|
-
file.forEachChild(visit);
|
|
57
|
-
}
|
|
58
|
-
return decorated.flatMap(({ symbol, detail, site }) => (symbol.kind === "class"
|
|
59
|
-
? (membersOf.get(symbol.id) ?? []).filter((member) => !parameterMembers.has(member.id))
|
|
60
|
-
: [symbol]).map((member) => ({ id: member.id, detail, site })));
|
|
34
|
+
// parameter, not the member a parameter property stores it in. A parameter property's
|
|
35
|
+
// decorator is attached to its parameter, and to no member.
|
|
36
|
+
return sites.decorated.flatMap(({ id, node }) => {
|
|
37
|
+
const symbol = byId.get(id);
|
|
38
|
+
if (symbol === undefined || !DECORATED.has(symbol.kind) || isParameterProperty(node)) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const members = symbol.kind === "class"
|
|
42
|
+
? (membersOf.get(symbol.id) ?? []).filter((member) => !sites.parameterProperties.has(member.id))
|
|
43
|
+
: [symbol];
|
|
44
|
+
return decoratorsOf(node).flatMap((attached) => {
|
|
45
|
+
const detail = `decorated by ${spelledDecorator(attached)}`;
|
|
46
|
+
const site = renderPosition(node.getSourceFile(), targetRoot, attached.getStart());
|
|
47
|
+
return members.map((member) => ({ id: member.id, detail, site }));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
61
50
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The exemption classes this analyzer detects, each by its detector, and what their
|
|
3
|
+
* detection reads of the run once for every project. A class without a detector here
|
|
4
|
+
* retains nothing.
|
|
5
|
+
*/
|
|
6
|
+
import { decorator } from "./decorator.js";
|
|
7
|
+
import { enumGroup } from "./enum-group.js";
|
|
8
|
+
import { frameworkLifecycle } from "./framework-lifecycle.js";
|
|
9
|
+
import { generatedFile } from "./generated-file.js";
|
|
10
|
+
import { injectionContainer } from "./injection-container.js";
|
|
11
|
+
import { interfaceSatisfaction } from "./interface-satisfaction.js";
|
|
12
|
+
import { detect } from "./lifecycle.js";
|
|
13
|
+
import { reflectiveLookup } from "./reflective-lookup.js";
|
|
14
|
+
import { serializationContract } from "./serialization-contract.js";
|
|
15
|
+
import { readTemplates, templateField } from "./template-field.js";
|
|
16
|
+
export const DETECTORS = new Map([
|
|
17
|
+
["interface-satisfaction", interfaceSatisfaction],
|
|
18
|
+
["enum-group", enumGroup],
|
|
19
|
+
["generated-file", generatedFile],
|
|
20
|
+
["template-field", templateField],
|
|
21
|
+
["reflective-lookup", reflectiveLookup],
|
|
22
|
+
["decorator", decorator],
|
|
23
|
+
["injection-container", injectionContainer],
|
|
24
|
+
["framework-lifecycle", frameworkLifecycle],
|
|
25
|
+
["serialization-contract", serializationContract],
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* The detection of one run: what every project's detectors read of the run, read once,
|
|
29
|
+
* and a function that runs them over one project. A switched-off class reads nothing,
|
|
30
|
+
* its templates included, and generated files are held only where the configuration
|
|
31
|
+
* leaves them out of the analysis.
|
|
32
|
+
*/
|
|
33
|
+
export function detection(host, targetRoot, config, consumers, detectors) {
|
|
34
|
+
const disabled = new Set(config.exemptions.disabled);
|
|
35
|
+
const templates = disabled.has("template-field")
|
|
36
|
+
? { delimiters: config.analysis.template_delimiters, files: [] }
|
|
37
|
+
: readTemplates(host, targetRoot, config.analysis);
|
|
38
|
+
const included = config.analysis.generated_files === "include";
|
|
39
|
+
return ({ project, held, generated }) => detect({
|
|
40
|
+
project,
|
|
41
|
+
held,
|
|
42
|
+
targetRoot,
|
|
43
|
+
templates,
|
|
44
|
+
ts: config.ts,
|
|
45
|
+
consumers,
|
|
46
|
+
...(included ? {} : { generated }),
|
|
47
|
+
}, detectors, disabled);
|
|
48
|
+
}
|
|
@@ -6,24 +6,17 @@
|
|
|
6
6
|
* or `unknown` expression asserted to it, or bound to a variable or returned from a
|
|
7
7
|
* function it annotates, where a number counts too. An enum's own value converts nothing.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral,
|
|
9
|
+
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral, isParenthesizedTypeNode, isPropertyAccessExpression, isReturnStatement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
|
+
import { parenthesesRemoved } from "../unwrap.js";
|
|
10
11
|
import { TypeFlags } from "@typescript/native/sync";
|
|
11
|
-
import { aliasChains } from "
|
|
12
|
-
import { nodeKey } from "
|
|
13
|
-
import { renderPosition } from "
|
|
14
|
-
import { isAnswered, UNANSWERED } from "
|
|
12
|
+
import { aliasChains } from "../alias-chain.js";
|
|
13
|
+
import { nodeKey } from "../inventory.js";
|
|
14
|
+
import { renderPosition } from "../position.js";
|
|
15
|
+
import { isAnswered, UNANSWERED } from "../query.js";
|
|
16
|
+
import { ERASED } from "./value-reach.js";
|
|
15
17
|
/** The operand types a conversion produces an enum value from. */
|
|
16
18
|
const NUMBER = TypeFlags.NumberLike;
|
|
17
19
|
const STRING = TypeFlags.StringLike;
|
|
18
|
-
const DECODED = TypeFlags.Any | TypeFlags.Unknown;
|
|
19
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
20
|
-
function unparenthesized(node) {
|
|
21
|
-
let held = node;
|
|
22
|
-
while (isParenthesizedExpression(held)) {
|
|
23
|
-
held = held.expression;
|
|
24
|
-
}
|
|
25
|
-
return held;
|
|
26
|
-
}
|
|
27
20
|
/**
|
|
28
21
|
* The name node a type node names its declaration by: the identifier of a type
|
|
29
22
|
* reference, the right side of a qualified one, through parentheses. A type that is no
|
|
@@ -45,7 +38,7 @@ function typeName(type) {
|
|
|
45
38
|
}
|
|
46
39
|
/** The name node an expression names an object by: an identifier, or a property access's name. */
|
|
47
40
|
function objectName(expression) {
|
|
48
|
-
const held =
|
|
41
|
+
const held = parenthesesRemoved(expression);
|
|
49
42
|
if (isIdentifier(held)) {
|
|
50
43
|
return held;
|
|
51
44
|
}
|
|
@@ -135,7 +128,7 @@ function detailOf(project, site, enumName, operand) {
|
|
|
135
128
|
if (parts.some((part) => (part.flags & STRING) !== 0)) {
|
|
136
129
|
return site.form === "assertion" ? "converted from string" : undefined;
|
|
137
130
|
}
|
|
138
|
-
if (parts.some((part) => (part.flags &
|
|
131
|
+
if (parts.some((part) => (part.flags & ERASED) !== 0)) {
|
|
139
132
|
return `decoded as ${enumName}`;
|
|
140
133
|
}
|
|
141
134
|
return undefined;
|
|
@@ -6,12 +6,11 @@
|
|
|
6
6
|
* either stores. A store into an erased property of a type the analyzed program does not
|
|
7
7
|
* declare hands the value to the code that declares it.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression,
|
|
10
|
-
import { SymbolFlags
|
|
11
|
-
import { must } from "
|
|
12
|
-
import { checkedTypes } from "./value-reach.js";
|
|
13
|
-
|
|
14
|
-
const ERASED = TypeFlags.Any | TypeFlags.Unknown;
|
|
9
|
+
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadElement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
|
+
import { SymbolFlags } from "@typescript/native/sync";
|
|
11
|
+
import { must } from "../query.js";
|
|
12
|
+
import { checkedTypes, ERASED } from "./value-reach.js";
|
|
13
|
+
import { parenthesesRemoved } from "../unwrap.js";
|
|
15
14
|
/** The array methods whose arguments become elements of the array they are called on. */
|
|
16
15
|
const ELEMENT_STORES = new Set(["push", "unshift"]);
|
|
17
16
|
/** The name an element access's literal index spells, or none. */
|
|
@@ -20,9 +19,6 @@ function literalKey(node) {
|
|
|
20
19
|
? node.text
|
|
21
20
|
: undefined;
|
|
22
21
|
}
|
|
23
|
-
function unwrapped(node) {
|
|
24
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
25
|
-
}
|
|
26
22
|
/**
|
|
27
23
|
* Whether a variable declaration's type can differ from what is stored in it: it carries an
|
|
28
24
|
* annotation, or it has neither an annotation nor an initializer, so its type evolves.
|
|
@@ -76,8 +72,8 @@ function propertyAt(source, name) {
|
|
|
76
72
|
* here, and a default value is stored in its target too.
|
|
77
73
|
*/
|
|
78
74
|
function patternTargets(pattern, from, out) {
|
|
79
|
-
const target =
|
|
80
|
-
const source = from.path.length === 0 ?
|
|
75
|
+
const target = parenthesesRemoved(pattern);
|
|
76
|
+
const source = from.path.length === 0 ? parenthesesRemoved(from.value) : from.value;
|
|
81
77
|
const into = (element, step, literal) => {
|
|
82
78
|
patternTargets(element, literal === undefined
|
|
83
79
|
? { value: from.value, path: [...from.path, step] }
|