@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
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
* one or more codes and a reason, and binding to every declaration that begins on the line
|
|
4
4
|
* below it, or on its own line where it trails a token there.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { CODE } from "./contract/contract.generated.js";
|
|
7
|
+
import { SyntaxKind } from "@typescript/native/ast";
|
|
7
8
|
import { importBindings } from "./import-bindings.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
9
|
+
import { nodeKey } from "./inventory.js";
|
|
10
|
+
import { relativePath } from "./paths.js";
|
|
11
|
+
import { byPosition, lineEnd, positionKey, renderPosition, startLine, tokenStart, } from "./position.js";
|
|
10
12
|
import { importRef } from "./ref.js";
|
|
11
|
-
import {
|
|
12
|
-
import { isPartKind, SUPPRESSION_WITHOUT_REASON, SuppressionError, siteText, } from "./suppress.js";
|
|
13
|
+
import { isPartKind, SuppressionError, siteText, } from "./suppress.js";
|
|
13
14
|
/**
|
|
14
15
|
* The three expressions the grammar applies to the text of each line comment, in this
|
|
15
16
|
* order: a comment in the namespace, a well-formed directive, and a directive that lacks
|
|
@@ -54,43 +55,6 @@ const LITERALS = new Set([
|
|
|
54
55
|
SyntaxKind.RegularExpressionLiteral,
|
|
55
56
|
SyntaxKind.JsxText,
|
|
56
57
|
]);
|
|
57
|
-
/** Whether one character ends a line, under the language's line terminators. */
|
|
58
|
-
function endsLine(char) {
|
|
59
|
-
return char === "\n" || char === "\r" || char === "\u2028" || char === "\u2029";
|
|
60
|
-
}
|
|
61
|
-
/** The offset where the line holding `from` ends. */
|
|
62
|
-
function lineEnd(text, from) {
|
|
63
|
-
let at = from;
|
|
64
|
-
while (at < text.length && !endsLine(text[at])) {
|
|
65
|
-
at += 1;
|
|
66
|
-
}
|
|
67
|
-
return at;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* The offset of the first token at or after `from`: whitespace, comments and a leading
|
|
71
|
-
* hashbang are trivia.
|
|
72
|
-
*/
|
|
73
|
-
export function tokenStart(text, from) {
|
|
74
|
-
let at = from;
|
|
75
|
-
if (at === 0 && text.startsWith("#!")) {
|
|
76
|
-
at = lineEnd(text, 0);
|
|
77
|
-
}
|
|
78
|
-
for (;;) {
|
|
79
|
-
if (/\s/u.test(text[at] ?? "")) {
|
|
80
|
-
at += 1;
|
|
81
|
-
}
|
|
82
|
-
else if (text.startsWith("//", at)) {
|
|
83
|
-
at = lineEnd(text, at);
|
|
84
|
-
}
|
|
85
|
-
else if (text.startsWith("/*", at)) {
|
|
86
|
-
const close = text.indexOf("*/", at + 2);
|
|
87
|
-
at = close < 0 ? text.length : close + 2;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
return at;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
58
|
/**
|
|
95
59
|
* Every `//` line comment of one file, in file order. The text between tokens is read as
|
|
96
60
|
* the language reads it: a block comment holds no line comment, and the literal tokens the
|
|
@@ -139,55 +103,42 @@ function lineComments(file) {
|
|
|
139
103
|
function bindingKey(one) {
|
|
140
104
|
return `${one.declared?.id ?? ""}\u0000${one.part.id}`;
|
|
141
105
|
}
|
|
106
|
+
/** The placed declarations of a project by the path of the file each is in. */
|
|
107
|
+
function placedByPath(held, symbols) {
|
|
108
|
+
const byPath = new Map();
|
|
109
|
+
for (const [id, placed] of held.placement) {
|
|
110
|
+
const one = symbols.get(id);
|
|
111
|
+
const holder = symbols.get(placed.holder);
|
|
112
|
+
if (one === undefined || holder === undefined) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const at = byPath.get(one.position.path) ?? [];
|
|
116
|
+
at.push({ one, holder, startLines: placed.startLines, partLines: placed.partLines });
|
|
117
|
+
byPath.set(one.position.path, at);
|
|
118
|
+
}
|
|
119
|
+
return byPath;
|
|
120
|
+
}
|
|
142
121
|
/**
|
|
143
|
-
* The declarations of one file by the line each
|
|
144
|
-
*
|
|
145
|
-
* keyword, and a variable written on a later line of the statement also begins there. A
|
|
146
|
-
* function also begins, for a directive, on the line of each of its parameters, and a
|
|
147
|
-
* class, for a part kind, on the lines of its constructor and its constructor's parameters.
|
|
122
|
+
* The declarations of one file by the line a directive binds each on, as the inventory
|
|
123
|
+
* places them, and each import binding of the file on its statement's lines.
|
|
148
124
|
*/
|
|
149
|
-
function declarationLines(file,
|
|
125
|
+
function declarationLines(file, placed, held, targetRoot) {
|
|
150
126
|
const below = new Map();
|
|
151
|
-
const add = (
|
|
152
|
-
const line = file.getLineAndCharacterOfPosition(tokenStart(file.text, offset)).line + 1;
|
|
127
|
+
const add = (line, one) => {
|
|
153
128
|
const at = below.get(line) ?? [];
|
|
154
129
|
if (!at.some((known) => bindingKey(known) === bindingKey(one))) {
|
|
155
130
|
at.push(one);
|
|
156
131
|
}
|
|
157
132
|
below.set(line, at);
|
|
158
133
|
};
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
};
|
|
163
|
-
const visit = (node) => {
|
|
164
|
-
const one = declaredAt(node);
|
|
165
|
-
const owner = isConstructorDeclaration(node) ? declaredAt(node.parent) : undefined;
|
|
166
|
-
if (owner !== undefined && isConstructorDeclaration(node)) {
|
|
167
|
-
for (const at of [node, ...node.parameters.filter((one) => !isParameterProperty(one))]) {
|
|
168
|
-
add(at.pos, { declared: undefined, part: owner });
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
const holder = one !== undefined && isParameterProperty(node) ? declaredAt(node.parent.parent) : one;
|
|
172
|
-
if (one !== undefined && holder !== undefined) {
|
|
173
|
-
add(node.pos, { declared: one, part: holder });
|
|
134
|
+
for (const { one, holder, startLines, partLines } of placed) {
|
|
135
|
+
for (const line of startLines) {
|
|
136
|
+
add(line, { declared: one, part: holder });
|
|
174
137
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// line above it, inside the parameter list, and the directive binds the function.
|
|
178
|
-
for (const parameter of signatureOf(node)?.parameters ?? []) {
|
|
179
|
-
add(parameter.pos, { declared: one, part: one });
|
|
180
|
-
}
|
|
181
|
-
const list = node.parent;
|
|
182
|
-
if (node.kind === SyntaxKind.VariableDeclaration &&
|
|
183
|
-
list.kind === SyntaxKind.VariableDeclarationList &&
|
|
184
|
-
list.parent.kind === SyntaxKind.VariableStatement) {
|
|
185
|
-
add(list.parent.pos, { declared: one, part: one });
|
|
186
|
-
}
|
|
138
|
+
for (const line of partLines) {
|
|
139
|
+
add(line, { declared: undefined, part: one });
|
|
187
140
|
}
|
|
188
|
-
|
|
189
|
-
};
|
|
190
|
-
file.forEachChild(visit);
|
|
141
|
+
}
|
|
191
142
|
// An import binding is a subject of its own, bound on its line as a declaration is.
|
|
192
143
|
const fileId = held.declarations.get(nodeKey(file, file));
|
|
193
144
|
const moduleRef = held.symbols.find((symbol) => symbol.id === fileId)?.ref ?? "";
|
|
@@ -199,7 +150,7 @@ function declarationLines(file, held, symbols, targetRoot) {
|
|
|
199
150
|
statement = statement.parent;
|
|
200
151
|
}
|
|
201
152
|
for (const at of [statement.pos, name.getStart()]) {
|
|
202
|
-
add(at, { declared: one, part: one });
|
|
153
|
+
add(startLine(file, at), { declared: one, part: one });
|
|
203
154
|
}
|
|
204
155
|
}
|
|
205
156
|
return below;
|
|
@@ -220,13 +171,15 @@ export function inlineDirectives(project, held, targetRoot) {
|
|
|
220
171
|
const symbols = new Map(held.symbols
|
|
221
172
|
.filter((symbol) => symbol.kind !== "file")
|
|
222
173
|
.map((symbol) => [symbol.id, { id: symbol.id, ref: symbol.ref, position: symbol.position }]));
|
|
174
|
+
const placed = placedByPath(held, symbols);
|
|
223
175
|
const found = [];
|
|
224
176
|
for (const file of project.ownSourceFiles()) {
|
|
225
177
|
const comments = lineComments(file).filter((comment) => CANDIDATE.test(comment.text));
|
|
226
178
|
if (comments.length === 0) {
|
|
227
179
|
continue;
|
|
228
180
|
}
|
|
229
|
-
const
|
|
181
|
+
const path = relativePath(targetRoot, file.fileName) ?? "";
|
|
182
|
+
const below = declarationLines(file, placed.get(path) ?? [], held, targetRoot);
|
|
230
183
|
for (const comment of comments) {
|
|
231
184
|
const site = renderPosition(file, targetRoot, comment.offset);
|
|
232
185
|
const target = trails(file, comment.offset) ? site.line : site.line + 1;
|
|
@@ -274,7 +227,7 @@ export function inlineSuppressions(perProject) {
|
|
|
274
227
|
case "no-reason":
|
|
275
228
|
for (const code of directive.codes) {
|
|
276
229
|
refusals.push({
|
|
277
|
-
reported:
|
|
230
|
+
reported: CODE.suppressionWithoutReason,
|
|
278
231
|
code,
|
|
279
232
|
symbol: "",
|
|
280
233
|
path: site.path,
|
package/dist/src/suppress.js
CHANGED
|
@@ -4,25 +4,20 @@
|
|
|
4
4
|
* ignore entry or a baseline row. A bound record marks its declaration live before the
|
|
5
5
|
* sweep, unless its code reports a part or a dependency row, and is in effect when it
|
|
6
6
|
* withholds a finding its code would have produced there, dormant when the configuration
|
|
7
|
-
* withholds every such finding anyway, and stale otherwise.
|
|
7
|
+
* or a hold withholds every such finding anyway, and stale otherwise.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { KIND_ROWS, REMEDIES, SYMBOL_SUBJECTS, } from "./contract/contract.generated.js";
|
|
10
|
+
import { UsageError } from "./usage.js";
|
|
10
11
|
import { positionKey } from "./position.js";
|
|
11
12
|
import { isRef } from "./ref.js";
|
|
12
|
-
/** The code a suppression that carries no reason is reported under. */
|
|
13
|
-
export const SUPPRESSION_WITHOUT_REASON = "DS1701";
|
|
14
|
-
/** The code an ignore entry or a baseline row that names no path is reported under. */
|
|
15
|
-
export const UNSCOPED_ENTRY = "DS1702";
|
|
16
|
-
/** The code a suppression that withholds nothing is reported under. */
|
|
17
|
-
export const STALE_SUPPRESSION = "DS1703";
|
|
18
13
|
/**
|
|
19
14
|
* A directive, an entry or a document the grammar refuses before any finding exists: an
|
|
20
15
|
* instruction the analysis cannot carry out. It is a malformed input, so the command line
|
|
21
16
|
* answers it with the usage code.
|
|
22
17
|
*/
|
|
23
|
-
export class SuppressionError extends
|
|
18
|
+
export class SuppressionError extends UsageError {
|
|
24
19
|
constructor(mechanism, at, text, want) {
|
|
25
|
-
super(
|
|
20
|
+
super(`${mechanism} ${at}: ${text}: want ${want}`);
|
|
26
21
|
this.name = "SuppressionError";
|
|
27
22
|
}
|
|
28
23
|
}
|
|
@@ -71,73 +66,54 @@ export function isSymbolRef(value) {
|
|
|
71
66
|
export function blankReason(reason) {
|
|
72
67
|
return reason === undefined || /^[ \t\r\n]*$/u.test(reason);
|
|
73
68
|
}
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const ROW_SUBJECTS = new Map([
|
|
89
|
-
["file", ["DS1501", "DS1502"]],
|
|
90
|
-
...DEPENDENCY_SUBJECTS,
|
|
91
|
-
["root", ["DS1704"]],
|
|
92
|
-
["configured-declaration", ["DS1706"]],
|
|
93
|
-
["suppression", ["DS1701", "DS1702", "DS1703"]],
|
|
94
|
-
["edge", ["DS1705"]],
|
|
95
|
-
]);
|
|
69
|
+
/** No hold. */
|
|
70
|
+
const NO_HOLDS = { withholds: () => false, holdsRecord: () => false };
|
|
71
|
+
/** The subject of the kind each live code names. */
|
|
72
|
+
const SUBJECT_OF_CODE = new Map(KIND_ROWS.map((row) => [row.code, row.subject]));
|
|
73
|
+
/** The subject a finding about one symbol kind is about. */
|
|
74
|
+
function subjectOf(kind) {
|
|
75
|
+
return Object.hasOwn(SYMBOL_SUBJECTS, kind)
|
|
76
|
+
? SYMBOL_SUBJECTS[kind]
|
|
77
|
+
: undefined;
|
|
78
|
+
}
|
|
79
|
+
/** Whether a subject is a row of a document rather than a declaration of the program. */
|
|
80
|
+
function rowOf(subject) {
|
|
81
|
+
return subject === "file" || subject === "dependency" || subject === "record";
|
|
82
|
+
}
|
|
96
83
|
/** Whether a finding's subject is a row of a document rather than a declaration. */
|
|
97
84
|
export function isRowSubject(kind) {
|
|
98
|
-
return
|
|
85
|
+
return rowOf(subjectOf(kind));
|
|
99
86
|
}
|
|
100
|
-
/**
|
|
101
|
-
export function
|
|
102
|
-
return
|
|
87
|
+
/** The subject a code reports, which kinds.json's remedies table answers for. */
|
|
88
|
+
export function subjectOfCode(code) {
|
|
89
|
+
return SUBJECT_OF_CODE.get(code);
|
|
103
90
|
}
|
|
104
|
-
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
export function
|
|
110
|
-
return [
|
|
91
|
+
/**
|
|
92
|
+
* Whether a record of `mechanism` can name a finding about `subject`, as kinds.json's
|
|
93
|
+
* remedies table lists the suppressions of each subject. A subject the table does not
|
|
94
|
+
* know is a declaration's.
|
|
95
|
+
*/
|
|
96
|
+
export function names(subject, mechanism) {
|
|
97
|
+
return REMEDIES[subject ?? "declaration"].suppressions.includes(mechanism);
|
|
111
98
|
}
|
|
112
|
-
/** Whether a
|
|
113
|
-
export function
|
|
114
|
-
return
|
|
99
|
+
/** Whether a finding about a symbol of `kind` is one a record of `mechanism` can name. */
|
|
100
|
+
export function namesKind(kind, mechanism) {
|
|
101
|
+
return names(subjectOf(kind), mechanism);
|
|
115
102
|
}
|
|
116
103
|
/**
|
|
117
|
-
*
|
|
104
|
+
* Whether a finding's subject is a part of the declaration its reference names: a part
|
|
118
105
|
* has no reference of its own, so a finding about one names the declaration that holds
|
|
119
106
|
* it, and the part is decided inside that declaration whatever uses it.
|
|
120
107
|
*/
|
|
121
|
-
const PART_SUBJECTS = new Set([
|
|
122
|
-
"parameter",
|
|
123
|
-
"receiver",
|
|
124
|
-
"result",
|
|
125
|
-
"statement",
|
|
126
|
-
"case",
|
|
127
|
-
"store",
|
|
128
|
-
]);
|
|
129
|
-
/** Whether a finding's subject is a part of the declaration its reference names. */
|
|
130
108
|
export function isPartSubject(kind) {
|
|
131
|
-
return
|
|
109
|
+
return subjectOf(kind) === "part";
|
|
132
110
|
}
|
|
133
|
-
/** The prefix of the codes of the part kinds, the intra-function range. */
|
|
134
|
-
const PART_KIND_PREFIX = "DS18";
|
|
135
111
|
/**
|
|
136
112
|
* Whether a code is a part kind, whose record withholds its finding and marks nothing:
|
|
137
113
|
* the record says the part is wanted, not that the declaration holding it is.
|
|
138
114
|
*/
|
|
139
115
|
export function isPartKind(code) {
|
|
140
|
-
return
|
|
116
|
+
return SUBJECT_OF_CODE.get(code) === "part";
|
|
141
117
|
}
|
|
142
118
|
/** One finding's identity: its code and the position of the thing it names. */
|
|
143
119
|
function claimKey(finding) {
|
|
@@ -155,14 +131,13 @@ export function pairs(record, finding) {
|
|
|
155
131
|
if (record.code !== finding.code) {
|
|
156
132
|
return false;
|
|
157
133
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
record.symbol === finding.symbol.ref &&
|
|
161
|
-
record.path === finding.position.path);
|
|
162
|
-
}
|
|
163
|
-
if (ROW_SUBJECTS.has(finding.symbol.kind)) {
|
|
134
|
+
const subject = subjectOf(finding.symbol.kind);
|
|
135
|
+
if (!names(subject, record.mechanism)) {
|
|
164
136
|
return false;
|
|
165
137
|
}
|
|
138
|
+
if (subject === "dependency") {
|
|
139
|
+
return record.symbol === finding.symbol.ref && record.path === finding.position.path;
|
|
140
|
+
}
|
|
166
141
|
if (record.bound !== "" && record.bound === positionKey(finding.position)) {
|
|
167
142
|
return true;
|
|
168
143
|
}
|
|
@@ -174,10 +149,10 @@ export function pairs(record, finding) {
|
|
|
174
149
|
* there: swept with no mark for a liveness kind, and as swept otherwise. The first record
|
|
175
150
|
* in reading order claims a finding, so a second naming it is stale; a part-kind record
|
|
176
151
|
* claims every finding of its code about a part of its declaration. A record is dormant
|
|
177
|
-
* when the dials withhold every finding it claims,
|
|
178
|
-
*
|
|
152
|
+
* when the dials or `holds` withhold every finding it claims, or when it claims none and
|
|
153
|
+
* its code is at `allow` or a hold keeps its declaration live.
|
|
179
154
|
*/
|
|
180
|
-
export function ledgerOf(records, would, dials) {
|
|
155
|
+
export function ledgerOf(records, would, dials, holds = NO_HOLDS) {
|
|
181
156
|
const taken = new Set();
|
|
182
157
|
const verdicts = [];
|
|
183
158
|
for (const record of records) {
|
|
@@ -185,13 +160,17 @@ export function ledgerOf(records, would, dials) {
|
|
|
185
160
|
const first = would.find(open);
|
|
186
161
|
const claimed = first === undefined ? [] : isPartKind(record.code) ? would.filter(open) : [first];
|
|
187
162
|
if (claimed.length === 0) {
|
|
188
|
-
verdicts.push(record.bound !== "" && dials.allows(record.code)
|
|
163
|
+
verdicts.push(record.bound !== "" && (dials.allows(record.code) || holds.holdsRecord(record))
|
|
164
|
+
? "dormant"
|
|
165
|
+
: "stale");
|
|
189
166
|
continue;
|
|
190
167
|
}
|
|
191
168
|
for (const finding of claimed) {
|
|
192
169
|
taken.add(claimKey(finding));
|
|
193
170
|
}
|
|
194
|
-
verdicts.push(claimed.every((finding) => dials.withholds(finding)
|
|
171
|
+
verdicts.push(claimed.every((finding) => dials.withholds(finding) || holds.withholds(finding))
|
|
172
|
+
? "dormant"
|
|
173
|
+
: "in-effect");
|
|
195
174
|
}
|
|
196
175
|
return {
|
|
197
176
|
verdicts,
|
package/dist/src/symbol-keys.js
CHANGED
|
@@ -5,16 +5,12 @@
|
|
|
5
5
|
* No name node resolves to such a member: the key's name resolves to the constant. An
|
|
6
6
|
* iteration reads the member its well-known iteration symbol keys.
|
|
7
7
|
*/
|
|
8
|
-
import { isComputedPropertyName, isForOfStatement, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral,
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { isAnswered } from "./query.js";
|
|
8
|
+
import { isComputedPropertyName, isForOfStatement, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isPropertyAccessExpression, isSpreadElement, isStringLiteral, } from "@typescript/native/ast";
|
|
9
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
10
|
+
import { isAnswered, UNANSWERED } from "./query.js";
|
|
12
11
|
/** The identifier an element access's argument names its key by, where it is a name. */
|
|
13
12
|
export function keyNameOf(argument) {
|
|
14
|
-
|
|
15
|
-
while (isParenthesizedExpression(at)) {
|
|
16
|
-
at = at.expression;
|
|
17
|
-
}
|
|
13
|
+
const at = parenthesesRemoved(argument);
|
|
18
14
|
if (isIdentifier(at)) {
|
|
19
15
|
return at;
|
|
20
16
|
}
|
|
@@ -129,87 +125,95 @@ function wellKnownName(name) {
|
|
|
129
125
|
: undefined;
|
|
130
126
|
}
|
|
131
127
|
/**
|
|
132
|
-
* The
|
|
133
|
-
*
|
|
134
|
-
* `
|
|
135
|
-
*
|
|
128
|
+
* The reads the iterations of a side's files make of the iteration members of the values they
|
|
129
|
+
* iterate: a `for…of` statement and a spread element read `[Symbol.iterator]`, and a
|
|
130
|
+
* `for await…of` statement reads `[Symbol.asyncIterator]` and, which it falls back to,
|
|
131
|
+
* `[Symbol.iterator]`. Each is made by the declaration holding it. A value whose type or
|
|
132
|
+
* members the checker leaves unanswered holds the members those names could spell.
|
|
136
133
|
*/
|
|
137
|
-
export
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
const visit = (node, from) => {
|
|
147
|
-
const holder = held.declarations.get(nodeKey(file, node)) ?? from;
|
|
148
|
-
if (isForOfStatement(node)) {
|
|
149
|
-
const protocols = node.awaitModifier === undefined ? ["iterator"] : ["asyncIterator", "iterator"];
|
|
150
|
-
iterated.push({ file, from: holder, operand: node.expression, protocols });
|
|
151
|
-
}
|
|
152
|
-
else if (isSpreadElement(node)) {
|
|
153
|
-
iterated.push({ file, from: holder, operand: node.expression, protocols: ["iterator"] });
|
|
154
|
-
}
|
|
155
|
-
node.forEachChild((child) => {
|
|
156
|
-
visit(child, holder);
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
file.forEachChild((child) => {
|
|
160
|
-
visit(child, fileId);
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
if (iterated.length === 0) {
|
|
164
|
-
return [];
|
|
165
|
-
}
|
|
166
|
-
const types = queries.typesAt(iterated.map((one) => one.operand));
|
|
167
|
-
const members = new Map();
|
|
168
|
-
const membersOf = (type) => {
|
|
169
|
-
const known = members.get(type.id);
|
|
170
|
-
if (known !== undefined) {
|
|
171
|
-
return known;
|
|
172
|
-
}
|
|
173
|
-
const keyed = [];
|
|
174
|
-
const properties = queries.propertiesOf(type);
|
|
175
|
-
for (const property of isAnswered(properties) ? properties : []) {
|
|
176
|
-
for (const handle of property.declarations) {
|
|
177
|
-
const node = ownPaths.has(handle.path) ? project.declarationAt(handle)?.node : undefined;
|
|
178
|
-
const name = wellKnownName(node?.name);
|
|
179
|
-
if (name !== undefined) {
|
|
180
|
-
keyed.push({ name, ids: chains.declarationsOf(property) });
|
|
181
|
-
break;
|
|
134
|
+
export const iteration = {
|
|
135
|
+
start() {
|
|
136
|
+
const iterated = [];
|
|
137
|
+
return {
|
|
138
|
+
visit(node, { file, from }) {
|
|
139
|
+
if (isForOfStatement(node)) {
|
|
140
|
+
const protocols = node.awaitModifier === undefined ? ["iterator"] : ["asyncIterator", "iterator"];
|
|
141
|
+
iterated.push({ file, from, operand: node.expression, protocols });
|
|
182
142
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
members.set(type.id, keyed);
|
|
186
|
-
return keyed;
|
|
187
|
-
};
|
|
188
|
-
const found = [];
|
|
189
|
-
iterated.forEach((one, index) => {
|
|
190
|
-
const type = types[index];
|
|
191
|
-
if (type === undefined || !isAnswered(type)) {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
const parts = type.isUnionType() || type.isIntersectionType() ? queries.constituents(type) : [type];
|
|
195
|
-
const position = renderPosition(one.file, root, one.operand.getStart());
|
|
196
|
-
for (const part of isAnswered(parts) ? parts : []) {
|
|
197
|
-
for (const member of membersOf(part)) {
|
|
198
|
-
if (!one.protocols.includes(member.name)) {
|
|
199
|
-
continue;
|
|
143
|
+
else if (isSpreadElement(node)) {
|
|
144
|
+
iterated.push({ file, from, operand: node.expression, protocols: ["iterator"] });
|
|
200
145
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
use: "read",
|
|
207
|
-
resolution: "keyed",
|
|
208
|
-
test: testFiles.has(position.path),
|
|
209
|
-
});
|
|
146
|
+
},
|
|
147
|
+
reads({ project, chains }) {
|
|
148
|
+
const found = [];
|
|
149
|
+
if (iterated.length === 0) {
|
|
150
|
+
return found;
|
|
210
151
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
152
|
+
const queries = project.queries;
|
|
153
|
+
const ownPaths = project.ownPaths();
|
|
154
|
+
const types = queries.typesAt(iterated.map((one) => one.operand));
|
|
155
|
+
const members = new Map();
|
|
156
|
+
const membersOf = (type) => {
|
|
157
|
+
const known = members.get(type.id);
|
|
158
|
+
if (known !== undefined) {
|
|
159
|
+
return known;
|
|
160
|
+
}
|
|
161
|
+
const properties = queries.propertiesOf(type);
|
|
162
|
+
const keyed = [];
|
|
163
|
+
for (const property of isAnswered(properties) ? properties : []) {
|
|
164
|
+
for (const handle of property.declarations) {
|
|
165
|
+
const node = ownPaths.has(handle.path)
|
|
166
|
+
? project.declarationAt(handle)?.node
|
|
167
|
+
: undefined;
|
|
168
|
+
const name = wellKnownName(node?.name);
|
|
169
|
+
if (name !== undefined) {
|
|
170
|
+
keyed.push({ name, ids: chains.declarationsOf(property) });
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const result = isAnswered(properties) ? keyed : UNANSWERED;
|
|
176
|
+
members.set(type.id, result);
|
|
177
|
+
return result;
|
|
178
|
+
};
|
|
179
|
+
// A member a well-known symbol keys is named by the symbol's computed name.
|
|
180
|
+
const spelled = (protocols) => protocols.map((protocol) => `Symbol.${protocol}`);
|
|
181
|
+
iterated.forEach((one, index) => {
|
|
182
|
+
const type = types[index];
|
|
183
|
+
if (type === UNANSWERED) {
|
|
184
|
+
found.push({ kind: "held", from: one.from, names: spelled(one.protocols) });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (type === undefined) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const parts = type.isUnionType() || type.isIntersectionType() ? queries.constituents(type) : [type];
|
|
191
|
+
for (const part of isAnswered(parts) ? parts : [type]) {
|
|
192
|
+
const keyed = membersOf(part);
|
|
193
|
+
if (keyed === UNANSWERED) {
|
|
194
|
+
found.push({ kind: "held", from: one.from, names: spelled(one.protocols) });
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
for (const member of keyed) {
|
|
198
|
+
if (!one.protocols.includes(member.name)) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
for (const to of member.ids) {
|
|
202
|
+
found.push({
|
|
203
|
+
kind: "named",
|
|
204
|
+
from: one.from,
|
|
205
|
+
to,
|
|
206
|
+
file: one.file,
|
|
207
|
+
at: one.operand,
|
|
208
|
+
use: "read",
|
|
209
|
+
via: "keyed",
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
return found;
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The file classes the run counts references by. A test file is one a `ts.test_files`
|
|
3
|
+
* pattern or a test runner's row names (the test-runner entry source decides which), a test
|
|
4
|
+
* file no project holds, or a consumer's file a pattern names below the consumer's root.
|
|
5
|
+
* A test-support file is test code as well, decided once the references are known
|
|
6
|
+
* (`support.ts`), so a reference carries only whether a test file made it and the counters
|
|
7
|
+
* read the support class beside it.
|
|
8
|
+
*/
|
|
9
|
+
import { renderPosition } from "../position.js";
|
|
10
|
+
import { bytewise } from "../text/compare.js";
|
|
11
|
+
import { globExpression } from "../text/glob.js";
|
|
12
|
+
/** The test files of the target: each file the test-runner source names, by its file name. */
|
|
13
|
+
export function targetTestFile(named) {
|
|
14
|
+
return (file) => named.has(file.fileName);
|
|
15
|
+
}
|
|
16
|
+
/** The test files a pattern names, each by its path below `root`: a consumer's, below the consumer's root. */
|
|
17
|
+
export function patternTestFile(patterns, root) {
|
|
18
|
+
const expressions = patterns.map(globExpression);
|
|
19
|
+
return (file) => {
|
|
20
|
+
const path = renderPosition(file, root, 0).path;
|
|
21
|
+
return expressions.some((expression) => expression.test(path));
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** The own files of a project that are test files, by their path below `root`, ascending. */
|
|
25
|
+
export function testFilePaths(project, root, testFile) {
|
|
26
|
+
return project
|
|
27
|
+
.ownSourceFiles()
|
|
28
|
+
.filter(testFile)
|
|
29
|
+
.map((file) => renderPosition(file, root, 0).path)
|
|
30
|
+
.sort(bytewise);
|
|
31
|
+
}
|
|
32
|
+
/** Whether test code made one reference: a test file, or a test-support file of the target. */
|
|
33
|
+
export function madeByTestCode(reference, support) {
|
|
34
|
+
return (reference.test || (reference.consumer === undefined && support.has(reference.position.path)));
|
|
35
|
+
}
|
|
36
|
+
/** Whether the mode classes a reference test code made as a test one: any but a loaded consumer's it classes as production. */
|
|
37
|
+
export function classedAsTest(test, consumer, mode) {
|
|
38
|
+
return test && !(consumer && mode.consumerTestsProduction === true);
|
|
39
|
+
}
|
|
40
|
+
/** Whether a production mode counts no reference of this one: test code made it, as the mode classes it. */
|
|
41
|
+
export function withheldBy(mode, reference, support) {
|
|
42
|
+
return (mode.production &&
|
|
43
|
+
classedAsTest(madeByTestCode(reference, support), reference.consumer !== undefined, mode));
|
|
44
|
+
}
|
|
45
|
+
/** Whether a production mode follows no edge like this one: {@link withheldBy} for a graph edge. */
|
|
46
|
+
export function edgeWithheldBy(mode, edge) {
|
|
47
|
+
return mode.production && classedAsTest(edge.test, edge.consumer, mode);
|
|
48
|
+
}
|
|
49
|
+
/** The rule a file the analysis classified as test-support code is counted under. */
|
|
50
|
+
const TEST_SUPPORT_RULE = "test-support";
|
|
51
|
+
/**
|
|
52
|
+
* The name one test-file rule takes. A rule's name is a word list the report's own
|
|
53
|
+
* vocabulary spells, which cannot carry a pattern, so a rule is named by the place of
|
|
54
|
+
* its pattern in the configured list.
|
|
55
|
+
*/
|
|
56
|
+
function patternRule(index) {
|
|
57
|
+
return `test-file-pattern-${String(index + 1)}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The rules over the test files of several projects at once, ordered by rule: a file two
|
|
61
|
+
* projects hold is one file, so each rule counts the distinct paths it matches.
|
|
62
|
+
*/
|
|
63
|
+
export function testFileRulesOf(testFiles, paths, supportFiles = []) {
|
|
64
|
+
const distinct = [...new Set(paths)];
|
|
65
|
+
const support = new Set(supportFiles).size;
|
|
66
|
+
return [
|
|
67
|
+
...testFiles.map((pattern, index) => {
|
|
68
|
+
const expression = globExpression(pattern);
|
|
69
|
+
return {
|
|
70
|
+
rule: patternRule(index),
|
|
71
|
+
matched: distinct.filter((path) => expression.test(path)).length,
|
|
72
|
+
};
|
|
73
|
+
}),
|
|
74
|
+
...(support === 0 ? [] : [{ rule: TEST_SUPPORT_RULE, matched: support }]),
|
|
75
|
+
].sort((a, b) => bytewise(a.rule, b.rule));
|
|
76
|
+
}
|