@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,48 @@
|
|
|
1
|
+
import { LANGUAGE_ROWS } from "./contract/contract.generated.js";
|
|
2
|
+
import { globExpression } from "./text/glob.js";
|
|
3
|
+
export const JAVASCRIPT_FILE = /\.(?:js|jsx|mjs|cjs)$/u;
|
|
4
|
+
/** The patterns the TypeScript row of `languages.json` skips files by, each matched against a name alone. */
|
|
5
|
+
const MINIFIED_NAMES = LANGUAGE_ROWS.ts.skippedFiles.map((pattern) => ({
|
|
6
|
+
pattern,
|
|
7
|
+
expression: globExpression(pattern),
|
|
8
|
+
}));
|
|
9
|
+
const MINIFIED_BYTES = 10_240;
|
|
10
|
+
const MINIFIED_LINE = 500;
|
|
11
|
+
/** What a minified file is decided by where its text is not read. */
|
|
12
|
+
const LONG_LINES = "long lines";
|
|
13
|
+
/** The skipped-file pattern one file's name matches, which decides it minified without its text. */
|
|
14
|
+
export function minifiedByName(fileName) {
|
|
15
|
+
const name = fileName.slice(fileName.lastIndexOf("/") + 1);
|
|
16
|
+
return MINIFIED_NAMES.find((one) => one.expression.test(name))?.pattern;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* What decides one JavaScript file minified: the skipped-file pattern its name matches, or
|
|
20
|
+
* {@link LONG_LINES} for a text of the size whose mean line is longer than the limit;
|
|
21
|
+
* undefined for a file that is not minified.
|
|
22
|
+
*/
|
|
23
|
+
export function minifiedBy(fileName, text) {
|
|
24
|
+
if (!JAVASCRIPT_FILE.test(fileName)) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const named = minifiedByName(fileName);
|
|
28
|
+
if (named !== undefined) {
|
|
29
|
+
return named;
|
|
30
|
+
}
|
|
31
|
+
// A UTF-16 unit encodes to at most three UTF-8 bytes, so a shorter text is below the size.
|
|
32
|
+
if (text.length * 3 < MINIFIED_BYTES) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const lines = text.split(/\r?\n/u).length;
|
|
36
|
+
return utf8Bytes(text) >= MINIFIED_BYTES && text.length / lines > MINIFIED_LINE
|
|
37
|
+
? LONG_LINES
|
|
38
|
+
: undefined;
|
|
39
|
+
}
|
|
40
|
+
/** The length of a text in UTF-8, a lone surrogate counting as the three bytes of U+FFFD. */
|
|
41
|
+
function utf8Bytes(text) {
|
|
42
|
+
let bytes = 0;
|
|
43
|
+
for (const character of text) {
|
|
44
|
+
const point = character.codePointAt(0) ?? 0;
|
|
45
|
+
bytes += point < 0x80 ? 1 : point < 0x800 ? 2 : point < 0x10000 ? 3 : 4;
|
|
46
|
+
}
|
|
47
|
+
return bytes;
|
|
48
|
+
}
|
|
@@ -1,106 +1,228 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A
|
|
3
|
-
*
|
|
2
|
+
* A text that is not one strict JSON document: a syntax error, data after the value, a
|
|
3
|
+
* member one object writes twice, or nesting past {@link MAX_DEPTH}. `place` is the
|
|
4
|
+
* value the fault is in, followed by the member written twice.
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
export class StrictJSONError extends Error {
|
|
7
|
+
offset;
|
|
8
|
+
place;
|
|
9
|
+
constructor(reason, offset, place) {
|
|
10
|
+
super(reason);
|
|
11
|
+
this.name = "StrictJSONError";
|
|
12
|
+
this.offset = offset;
|
|
13
|
+
this.place = place;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* How deep values may nest. A document this analyzer reads nests a few levels, and a
|
|
18
|
+
* bound turns a document built to exhaust the stack into a refusal.
|
|
19
|
+
*/
|
|
20
|
+
const MAX_DEPTH = 1000;
|
|
21
|
+
const SPACE = /[ \t\n\r]*/uy;
|
|
22
|
+
const STRING = /"(?:[ !#$%&'()*+,\-./0-9:;<=>?@A-Z[\]-\u{10FFFF}]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"/uy;
|
|
23
|
+
const NUMBER = /-?(?:0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?/uy;
|
|
24
|
+
const LITERALS = new Map([
|
|
25
|
+
["true", true],
|
|
26
|
+
["false", false],
|
|
27
|
+
["null", null],
|
|
28
|
+
]);
|
|
29
|
+
/** One member name spelled as a JSON Pointer token. */
|
|
30
|
+
const escaped = (name) => name.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
31
|
+
/** The member names and indexes a JSON Pointer holds, unescaped. */
|
|
32
|
+
export function pointerSegments(pointer) {
|
|
33
|
+
return pointer === ""
|
|
34
|
+
? []
|
|
35
|
+
: pointer
|
|
36
|
+
.slice(1)
|
|
37
|
+
.split("/")
|
|
38
|
+
.map((token) => token.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
39
|
+
}
|
|
40
|
+
/** The JSON Pointer of a place written as segments. */
|
|
41
|
+
export function pointerOf(segments) {
|
|
42
|
+
return segments.map((segment) => `/${escaped(segment)}`).join("");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The place a JSON Pointer names inside `value`, followed by `member` where it is not
|
|
46
|
+
* empty: a pointer's text does not say whether a segment of digits is an index, so the
|
|
47
|
+
* value it points into does.
|
|
48
|
+
*/
|
|
49
|
+
export function placeIn(value, pointer, member = "") {
|
|
50
|
+
const place = [];
|
|
51
|
+
let held = value;
|
|
52
|
+
for (const segment of pointerSegments(pointer)) {
|
|
53
|
+
if (Array.isArray(held)) {
|
|
54
|
+
place.push(Number(segment));
|
|
55
|
+
held = held[Number(segment)];
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
place.push(segment);
|
|
59
|
+
held = isRecord(held) ? held[segment] : undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return member === "" ? place : [...place, member];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A place as a refusal names it: member names joined by full stops and an index in
|
|
66
|
+
* square brackets, as `ts.serializers[0].returns`.
|
|
67
|
+
*/
|
|
68
|
+
export function dotted(place) {
|
|
69
|
+
let path = "";
|
|
70
|
+
for (const segment of place) {
|
|
71
|
+
path +=
|
|
72
|
+
typeof segment === "number" ? `[${String(segment)}]` : path === "" ? segment : `.${segment}`;
|
|
73
|
+
}
|
|
74
|
+
return path;
|
|
75
|
+
}
|
|
76
|
+
class Reader {
|
|
12
77
|
at = 0;
|
|
13
|
-
|
|
78
|
+
path = [];
|
|
79
|
+
fractions = new Map();
|
|
80
|
+
starts = new Map();
|
|
81
|
+
text;
|
|
82
|
+
records;
|
|
83
|
+
constructor(text, records) {
|
|
14
84
|
this.text = text;
|
|
15
|
-
this.
|
|
16
|
-
}
|
|
17
|
-
run() {
|
|
18
|
-
this.value("document");
|
|
85
|
+
this.records = records;
|
|
19
86
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
87
|
+
read() {
|
|
88
|
+
const value = this.value(0);
|
|
89
|
+
this.match(SPACE);
|
|
90
|
+
if (this.at < this.text.length) {
|
|
91
|
+
this.fail("data follows the document's value");
|
|
23
92
|
}
|
|
93
|
+
return value;
|
|
24
94
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
95
|
+
fail(reason, offset = this.at, member = "") {
|
|
96
|
+
throw new StrictJSONError(reason, offset, member === "" ? [...this.path] : [...this.path, member]);
|
|
97
|
+
}
|
|
98
|
+
match(pattern) {
|
|
99
|
+
pattern.lastIndex = this.at;
|
|
100
|
+
const found = pattern.exec(this.text)?.[0];
|
|
101
|
+
this.at = found === undefined ? this.at : pattern.lastIndex;
|
|
102
|
+
return found;
|
|
103
|
+
}
|
|
104
|
+
expect(char, what) {
|
|
105
|
+
this.match(SPACE);
|
|
106
|
+
if (this.text[this.at] !== char) {
|
|
107
|
+
this.fail(`${what} is expected`);
|
|
30
108
|
}
|
|
31
109
|
this.at += 1;
|
|
32
|
-
return JSON.parse(this.text.slice(start, this.at));
|
|
33
110
|
}
|
|
34
|
-
value(
|
|
35
|
-
this.
|
|
36
|
-
if (
|
|
37
|
-
this.
|
|
111
|
+
value(depth) {
|
|
112
|
+
this.match(SPACE);
|
|
113
|
+
if (depth > MAX_DEPTH) {
|
|
114
|
+
this.fail(`values nest deeper than ${String(MAX_DEPTH)} levels`);
|
|
38
115
|
}
|
|
39
116
|
const char = this.text[this.at];
|
|
40
117
|
if (char === "{") {
|
|
41
|
-
this.object(
|
|
118
|
+
return this.object(depth);
|
|
42
119
|
}
|
|
43
|
-
|
|
44
|
-
this.
|
|
120
|
+
if (char === "[") {
|
|
121
|
+
return this.array(depth);
|
|
45
122
|
}
|
|
46
|
-
|
|
47
|
-
|
|
123
|
+
const string = this.match(STRING);
|
|
124
|
+
if (string !== undefined) {
|
|
125
|
+
return JSON.parse(string);
|
|
48
126
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
127
|
+
NUMBER.lastIndex = this.at;
|
|
128
|
+
const number = NUMBER.exec(this.text);
|
|
129
|
+
if (number !== null) {
|
|
130
|
+
this.at = NUMBER.lastIndex;
|
|
131
|
+
if (number[1] !== undefined || number[2] !== undefined) {
|
|
132
|
+
this.fractions.set(pointerOf(this.path.map(String)), number[0]);
|
|
52
133
|
}
|
|
134
|
+
return Number(number[0]);
|
|
53
135
|
}
|
|
136
|
+
for (const [literal, held] of LITERALS) {
|
|
137
|
+
if (this.text.startsWith(literal, this.at)) {
|
|
138
|
+
this.at += literal.length;
|
|
139
|
+
return held;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return this.fail(char === undefined ? "the document ends where a value is expected" : "a value is expected");
|
|
54
143
|
}
|
|
55
|
-
object(
|
|
56
|
-
const
|
|
144
|
+
object(depth) {
|
|
145
|
+
const held = {};
|
|
57
146
|
this.at += 1;
|
|
147
|
+
this.match(SPACE);
|
|
148
|
+
if (this.text[this.at] === "}") {
|
|
149
|
+
this.at += 1;
|
|
150
|
+
return held;
|
|
151
|
+
}
|
|
58
152
|
for (;;) {
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
153
|
+
this.match(SPACE);
|
|
154
|
+
const offset = this.at;
|
|
155
|
+
const spelled = this.match(STRING);
|
|
156
|
+
if (spelled === undefined) {
|
|
157
|
+
return this.fail("a member name is expected");
|
|
63
158
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
159
|
+
const name = JSON.parse(spelled);
|
|
160
|
+
if (Object.hasOwn(held, name)) {
|
|
161
|
+
this.fail(`the member ${JSON.stringify(name)} is written twice, so neither value is chosen`, offset, name);
|
|
67
162
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.
|
|
163
|
+
this.expect(":", "a colon after the member name");
|
|
164
|
+
if (depth === 1 && this.path[0] === this.records) {
|
|
165
|
+
this.match(SPACE);
|
|
166
|
+
this.starts.set(name, this.at);
|
|
72
167
|
}
|
|
73
|
-
|
|
74
|
-
|
|
168
|
+
this.path.push(name);
|
|
169
|
+
Object.defineProperty(held, name, {
|
|
170
|
+
value: this.value(depth + 1),
|
|
171
|
+
enumerable: true,
|
|
172
|
+
writable: true,
|
|
173
|
+
configurable: true,
|
|
174
|
+
});
|
|
175
|
+
this.path.pop();
|
|
176
|
+
this.match(SPACE);
|
|
177
|
+
const next = this.text[this.at];
|
|
75
178
|
this.at += 1;
|
|
76
|
-
|
|
179
|
+
if (next === "}") {
|
|
180
|
+
return held;
|
|
181
|
+
}
|
|
182
|
+
if (next !== ",") {
|
|
183
|
+
this.at -= 1;
|
|
184
|
+
this.fail("a comma or a closing brace is expected");
|
|
185
|
+
}
|
|
77
186
|
}
|
|
78
187
|
}
|
|
79
|
-
|
|
188
|
+
array(depth) {
|
|
189
|
+
const held = [];
|
|
190
|
+
const records = depth === 1 && this.path[0] === this.records;
|
|
80
191
|
this.at += 1;
|
|
192
|
+
this.match(SPACE);
|
|
193
|
+
if (this.text[this.at] === "]") {
|
|
194
|
+
this.at += 1;
|
|
195
|
+
return held;
|
|
196
|
+
}
|
|
81
197
|
for (;;) {
|
|
82
|
-
this.
|
|
83
|
-
if (
|
|
84
|
-
this.at
|
|
85
|
-
return;
|
|
198
|
+
this.match(SPACE);
|
|
199
|
+
if (records) {
|
|
200
|
+
this.starts.set(held.length, this.at);
|
|
86
201
|
}
|
|
87
|
-
|
|
88
|
-
|
|
202
|
+
this.path.push(held.length);
|
|
203
|
+
held.push(this.value(depth + 1));
|
|
204
|
+
this.path.pop();
|
|
205
|
+
this.match(SPACE);
|
|
206
|
+
const next = this.text[this.at];
|
|
207
|
+
this.at += 1;
|
|
208
|
+
if (next === "]") {
|
|
209
|
+
return held;
|
|
210
|
+
}
|
|
211
|
+
if (next !== ",") {
|
|
212
|
+
this.at -= 1;
|
|
213
|
+
this.fail("a comma or a closing bracket is expected");
|
|
89
214
|
}
|
|
90
|
-
this.value(element);
|
|
91
215
|
}
|
|
92
216
|
}
|
|
93
217
|
}
|
|
94
218
|
/**
|
|
95
|
-
*
|
|
96
|
-
* records
|
|
97
|
-
* later value silently replacing the earlier one, so a document holding one is one a
|
|
98
|
-
* reader names rather than reads.
|
|
219
|
+
* Reads `text` as one strict JSON document, or throws a {@link StrictJSONError}.
|
|
220
|
+
* `records` names the top-level member whose values' offsets the read keeps.
|
|
99
221
|
*/
|
|
100
|
-
export function
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
return {
|
|
222
|
+
export function readStrict(text, records) {
|
|
223
|
+
const reader = new Reader(text, records);
|
|
224
|
+
const value = reader.read();
|
|
225
|
+
return { value, fractions: reader.fractions, starts: reader.starts };
|
|
104
226
|
}
|
|
105
227
|
/**
|
|
106
228
|
* One offset of a document as a finding carries it: the line counted from one, and the
|
|
@@ -111,3 +233,12 @@ export function positionAt(text, file, offset) {
|
|
|
111
233
|
const lineStart = before.lastIndexOf("\n") + 1;
|
|
112
234
|
return { path: file, line: before.split("\n").length, column: offset - lineStart + 1 };
|
|
113
235
|
}
|
|
236
|
+
/** A strict read's fault with the line and column it is at, as a refusal states it. */
|
|
237
|
+
export function locatedFault(text, error) {
|
|
238
|
+
const { line, column } = positionAt(text, "", error.offset);
|
|
239
|
+
return `line ${String(line)}, column ${String(column)}: ${error.message}`;
|
|
240
|
+
}
|
|
241
|
+
/** Whether a decoded JSON value is an object: not `null` and not an array. */
|
|
242
|
+
export function isRecord(value) {
|
|
243
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
244
|
+
}
|
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
* that holds `keyof X`, the literal the other side has names the member of `X` under that
|
|
5
5
|
* key, because deleting the member makes the comparison a type error.
|
|
6
6
|
*/
|
|
7
|
-
import { isBinaryExpression, isCaseClause, isElementAccessExpression, isIdentifier,
|
|
7
|
+
import { isBinaryExpression, isCaseClause, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isPropertyAccessExpression, isStringLiteral, isSwitchStatement, isTypeOperatorNode, SyntaxKind, } from "@typescript/native/ast";
|
|
8
8
|
import { SymbolFlags } from "@typescript/native/sync";
|
|
9
|
-
import { nodeKey } from "./inventory.js";
|
|
10
|
-
import { renderPosition } from "./position.js";
|
|
11
9
|
import { UNANSWERED } from "./query.js";
|
|
10
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
12
11
|
/** The operators that compare their operands for equality. */
|
|
13
12
|
const EQUALITIES = new Set([
|
|
14
13
|
SyntaxKind.EqualsEqualsEqualsToken,
|
|
@@ -16,12 +15,9 @@ const EQUALITIES = new Set([
|
|
|
16
15
|
SyntaxKind.EqualsEqualsToken,
|
|
17
16
|
SyntaxKind.ExclamationEqualsToken,
|
|
18
17
|
]);
|
|
19
|
-
function unwrapped(node) {
|
|
20
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
21
|
-
}
|
|
22
18
|
/** The name node an operand's symbol is read at: an identifier, or a property access's name. */
|
|
23
19
|
function nameOf(node) {
|
|
24
|
-
const at =
|
|
20
|
+
const at = parenthesesRemoved(node);
|
|
25
21
|
if (isIdentifier(at)) {
|
|
26
22
|
return at;
|
|
27
23
|
}
|
|
@@ -57,114 +53,137 @@ function literalNames(parts) {
|
|
|
57
53
|
return names;
|
|
58
54
|
}
|
|
59
55
|
/**
|
|
60
|
-
* The
|
|
61
|
-
*
|
|
56
|
+
* The reads the key comparisons of a side's files make of the members their literal side
|
|
57
|
+
* names, each made by the declaration holding the comparison. A question the checker leaves
|
|
58
|
+
* unanswered holds what its answer could have read.
|
|
62
59
|
*/
|
|
63
|
-
export
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
60
|
+
export const keyofComparisons = {
|
|
61
|
+
start() {
|
|
62
|
+
const comparisons = [];
|
|
63
|
+
return {
|
|
64
|
+
visit(node, { file, from }) {
|
|
65
|
+
if (isBinaryExpression(node) && EQUALITIES.has(node.operatorToken.kind)) {
|
|
66
|
+
comparisons.push({ file, from, keyed: node.left, other: node.right });
|
|
67
|
+
comparisons.push({ file, from, keyed: node.right, other: node.left });
|
|
68
|
+
}
|
|
69
|
+
if (isSwitchStatement(node)) {
|
|
70
|
+
for (const clause of node.caseBlock.clauses) {
|
|
71
|
+
if (isCaseClause(clause)) {
|
|
72
|
+
comparisons.push({ file, from, keyed: node.expression, other: clause.expression });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
reads({ project, chains }) {
|
|
78
|
+
const queries = project.queries;
|
|
79
|
+
const found = [];
|
|
80
|
+
const named = comparisons.flatMap((one) => {
|
|
81
|
+
const name = nameOf(one.keyed);
|
|
82
|
+
return name === undefined || isElementAccessExpression(parenthesesRemoved(one.other))
|
|
83
|
+
? []
|
|
84
|
+
: [{ ...one, name }];
|
|
85
|
+
});
|
|
86
|
+
if (named.length === 0) {
|
|
87
|
+
return found;
|
|
88
|
+
}
|
|
89
|
+
// The operand's own declaration states the key type, which the checker resolves to
|
|
90
|
+
// the literals it admits and so no longer names the type the key indexes.
|
|
91
|
+
const symbols = queries.symbolsAt(named.map((one) => one.name));
|
|
92
|
+
const keyed = named.flatMap((one, at) => {
|
|
93
|
+
const asked = symbols[at];
|
|
94
|
+
const symbol = asked === UNANSWERED || asked === undefined || (asked.flags & SymbolFlags.Alias) === 0
|
|
95
|
+
? asked
|
|
96
|
+
: queries.aliased(asked);
|
|
97
|
+
if (symbol === UNANSWERED) {
|
|
98
|
+
const text = literalText(one.other);
|
|
99
|
+
found.push({
|
|
100
|
+
kind: "held",
|
|
101
|
+
from: one.from,
|
|
102
|
+
...(text === undefined ? {} : { names: [text] }),
|
|
85
103
|
});
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
if (symbol === undefined) {
|
|
107
|
+
return [];
|
|
86
108
|
}
|
|
109
|
+
const operands = symbol.declarations.flatMap((handle) => {
|
|
110
|
+
const declared = project.declarationAt(handle)?.node?.type;
|
|
111
|
+
return declared === undefined ? [] : keyofOperands(declared);
|
|
112
|
+
});
|
|
113
|
+
return operands.length === 0 ? [] : [{ ...one, operands }];
|
|
114
|
+
});
|
|
115
|
+
if (keyed.length === 0) {
|
|
116
|
+
return found;
|
|
87
117
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
const named = comparisons.flatMap((one) => {
|
|
98
|
-
const name = nameOf(one.keyed);
|
|
99
|
-
return name === undefined || isElementAccessExpression(unwrapped(one.other))
|
|
100
|
-
? []
|
|
101
|
-
: [{ ...one, name }];
|
|
102
|
-
});
|
|
103
|
-
if (named.length === 0) {
|
|
104
|
-
return [];
|
|
105
|
-
}
|
|
106
|
-
// The operand's own declaration states the key type, which the checker resolves to
|
|
107
|
-
// the literals it admits and so no longer names the type the key indexes.
|
|
108
|
-
const symbols = queries.symbolsAt(named.map((one) => one.name));
|
|
109
|
-
const keyed = named.flatMap((one, at) => {
|
|
110
|
-
const asked = symbols[at];
|
|
111
|
-
const symbol = asked === UNANSWERED || asked === undefined || (asked.flags & SymbolFlags.Alias) === 0
|
|
112
|
-
? asked
|
|
113
|
-
: queries.aliased(asked);
|
|
114
|
-
if (symbol === UNANSWERED || symbol === undefined) {
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
const operands = symbol.declarations.flatMap((handle) => {
|
|
118
|
-
const declared = project.declarationAt(handle)?.node?.type;
|
|
119
|
-
return declared === undefined ? [] : keyofOperands(declared);
|
|
120
|
-
});
|
|
121
|
-
return operands.length === 0 ? [] : [{ ...one, operands }];
|
|
122
|
-
});
|
|
123
|
-
if (keyed.length === 0) {
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
const nodes = keyed.flatMap((one) => [one.other, ...one.operands]);
|
|
127
|
-
const types = queries.typesAt(nodes);
|
|
128
|
-
const typeOf = new Map();
|
|
129
|
-
nodes.forEach((node, at) => {
|
|
130
|
-
const type = types[at];
|
|
131
|
-
if (type !== UNANSWERED && type !== undefined) {
|
|
132
|
-
typeOf.set(node, type);
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
const partsOf = (type) => {
|
|
136
|
-
const parts = queries.constituents(type);
|
|
137
|
-
return parts === UNANSWERED ? [type] : parts;
|
|
138
|
-
};
|
|
139
|
-
const found = [];
|
|
140
|
-
for (const one of keyed) {
|
|
141
|
-
const literal = typeOf.get(one.other);
|
|
142
|
-
const names = literal === undefined ? [] : literalNames(partsOf(literal));
|
|
143
|
-
if (names.length === 0) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const position = renderPosition(one.file, root, one.other.getStart());
|
|
147
|
-
for (const operand of one.operands) {
|
|
148
|
-
const object = typeOf.get(operand);
|
|
149
|
-
for (const part of object === undefined ? [] : partsOf(object)) {
|
|
150
|
-
const properties = queries.propertiesOf(part);
|
|
151
|
-
for (const property of properties === UNANSWERED ? [] : properties) {
|
|
152
|
-
if (!names.includes(property.name)) {
|
|
153
|
-
continue;
|
|
118
|
+
const nodes = keyed.flatMap((one) => [one.other, ...one.operands]);
|
|
119
|
+
const types = queries.typesAt(nodes);
|
|
120
|
+
const typeOf = new Map();
|
|
121
|
+
nodes.forEach((node, at) => {
|
|
122
|
+
const type = types[at];
|
|
123
|
+
if (type !== undefined) {
|
|
124
|
+
typeOf.set(node, type);
|
|
154
125
|
}
|
|
155
|
-
|
|
126
|
+
});
|
|
127
|
+
const partsOf = (type) => {
|
|
128
|
+
const parts = queries.constituents(type);
|
|
129
|
+
return parts === UNANSWERED ? [type] : parts;
|
|
130
|
+
};
|
|
131
|
+
for (const one of keyed) {
|
|
132
|
+
const literal = typeOf.get(one.other);
|
|
133
|
+
const objects = one.operands.map((operand) => typeOf.get(operand));
|
|
134
|
+
if (literal === UNANSWERED) {
|
|
135
|
+
const known = objects.filter((type) => type !== undefined && type !== UNANSWERED);
|
|
156
136
|
found.push({
|
|
137
|
+
kind: "held",
|
|
157
138
|
from: one.from,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
use: "read",
|
|
161
|
-
resolution: "keyed",
|
|
162
|
-
test: testFiles.has(position.path),
|
|
139
|
+
types: known.flatMap(partsOf),
|
|
140
|
+
...(known.length < objects.length ? { members: true } : {}),
|
|
163
141
|
});
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const names = literal === undefined ? [] : literalNames(partsOf(literal));
|
|
145
|
+
if (names.length === 0) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
for (const object of objects) {
|
|
149
|
+
if (object === UNANSWERED) {
|
|
150
|
+
found.push({ kind: "held", from: one.from, names });
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
for (const part of object === undefined ? [] : partsOf(object)) {
|
|
154
|
+
const properties = queries.propertiesOf(part);
|
|
155
|
+
if (properties === UNANSWERED) {
|
|
156
|
+
found.push({ kind: "held", from: one.from, names });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
for (const property of properties) {
|
|
160
|
+
if (!names.includes(property.name)) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
for (const to of chains.declarationsOf(property)) {
|
|
164
|
+
found.push({
|
|
165
|
+
kind: "named",
|
|
166
|
+
from: one.from,
|
|
167
|
+
to,
|
|
168
|
+
file: one.file,
|
|
169
|
+
at: one.other,
|
|
170
|
+
use: "read",
|
|
171
|
+
via: "keyed",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
164
176
|
}
|
|
165
177
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
178
|
+
return found;
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
/** The text a string or number literal operand spells, where it is one. */
|
|
184
|
+
function literalText(node) {
|
|
185
|
+
const at = parenthesesRemoved(node);
|
|
186
|
+
return isStringLiteral(at) || isNumericLiteral(at) || isNoSubstitutionTemplateLiteral(at)
|
|
187
|
+
? at.text
|
|
188
|
+
: undefined;
|
|
170
189
|
}
|