@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.20
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 +2 -7
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +269 -432
- 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/calls.js +279 -43
- 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 +1 -1
- 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 +1369 -0
- package/dist/src/contract/report.generated.js +866 -0
- package/dist/src/dependencies.js +164 -121
- 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/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +1 -63
- package/dist/src/exempt.js +21 -66
- 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/framework-lifecycle.js +46 -19
- 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/generated-file.js +174 -28
- 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.js +2 -2
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/injection-container.js +2 -2
- package/dist/src/interface-satisfaction.js +1 -1
- 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 +47 -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/serialization-contract.js +601 -22
- 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/template-field.js +9 -19
- 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 +7 -5
- 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 +2 -9
- package/src/amd.ts +130 -0
- package/src/analysis.ts +424 -650
- package/src/augmentations.ts +93 -4
- package/src/automatic-types.ts +12 -30
- package/src/bindings.ts +460 -0
- package/src/calls.ts +338 -46
- 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 +1 -1
- 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 +1452 -0
- package/src/contract/report.generated.ts +1241 -0
- package/src/dependencies.ts +222 -127
- 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/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +1 -75
- package/src/exempt.ts +70 -98
- 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/framework-lifecycle.ts +47 -19
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +96 -0
- package/src/fs/tree.ts +110 -0
- package/src/generated-file.ts +242 -35
- 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.ts +2 -2
- package/src/indexed-access.ts +570 -527
- package/src/injection-container.ts +2 -2
- package/src/interface-satisfaction.ts +2 -2
- 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 +92 -0
- 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} +27 -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/serialization-contract.ts +769 -23
- 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/template-field.ts +15 -25
- 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 +7 -5
- 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/conventions.js +0 -937
- package/dist/src/discover.js +0 -468
- package/dist/src/entry-points.js +0 -529
- 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/setup-failure.js +0 -23
- package/dist/src/sweep.js +0 -224
- package/dist/src/test-joins.js +0 -101
- package/dist/src/version.js +0 -7
- package/dist/src/workflow-steps.js +0 -185
- package/src/base-url.ts +0 -24
- package/src/discover.ts +0 -653
- package/src/entry-points.ts +0 -687
- 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/setup-failure.ts +0 -39
- package/src/sweep.ts +0 -347
- package/src/test-joins.ts +0 -120
- package/src/version.ts +0 -7
- package/src/workflow-steps.ts +0 -216
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The command strings beside a target root's packages: a CI workflow's `run:` steps, the git
|
|
3
|
+
* hooks, the hook managers' commands and scripts and the makefile's recipe lines, each with the
|
|
4
|
+
* directory it runs in. A workflow or hook manager file is read by `text/yaml.ts`, and one it does not
|
|
5
|
+
* read gives no command; each command is read by `commands/read.ts`.
|
|
6
|
+
*/
|
|
7
|
+
import { pathsNamed, readCommands } from "../commands/read.js";
|
|
8
|
+
import { PART } from "../commands/shell.js";
|
|
9
|
+
import { isRecord } from "../json-document.js";
|
|
10
|
+
import { joinPath, resolvePath } from "../paths.js";
|
|
11
|
+
import { filesIn } from "../fs/tree.js";
|
|
12
|
+
import { yamlDocument } from "../text/yaml.js";
|
|
13
|
+
const WORKFLOWS = ".github/workflows";
|
|
14
|
+
/** The directories whose every file is a git hook script, run as the shell runs it. */
|
|
15
|
+
const HOOK_DIRS = [".husky", ".githooks"];
|
|
16
|
+
/** The key setting the directory a workflow step, or each step a `defaults.run` covers, runs in. */
|
|
17
|
+
const WORKING_DIRECTORY = "working-directory";
|
|
18
|
+
const HOOK_MANAGERS = [
|
|
19
|
+
{ name: ".pre-commit-config.yaml", key: "entry" },
|
|
20
|
+
...["lefthook.yml", "lefthook.yaml", ".lefthook.yml"].map((name) => ({
|
|
21
|
+
name,
|
|
22
|
+
key: "run",
|
|
23
|
+
dirKey: "root",
|
|
24
|
+
scripts: true,
|
|
25
|
+
})),
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* The directories lefthook searches for a hook's scripts after the file's `source_dir` and
|
|
29
|
+
* `source_dir_local`: https://github.com/evilmartians/lefthook/blob/master/internal/command/run.go
|
|
30
|
+
*/
|
|
31
|
+
const LEFTHOOK_DIRS = [".config/lefthook", ".config/lefthook-local"];
|
|
32
|
+
/** The names GNU make reads a makefile under, in the order it tries them. */
|
|
33
|
+
const MAKEFILES = ["GNUmakefile", "makefile", "Makefile"];
|
|
34
|
+
function readText(host, path) {
|
|
35
|
+
try {
|
|
36
|
+
return host.readFile(path);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** The text a YAML scalar's value stands for, or `undefined` for a collection or a null. */
|
|
43
|
+
function scalarText(value) {
|
|
44
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean"
|
|
45
|
+
? String(value)
|
|
46
|
+
: undefined;
|
|
47
|
+
}
|
|
48
|
+
/** The `defaults.run.working-directory` one mapping writes, as YAML decodes it. */
|
|
49
|
+
function defaultDirectory(mapping) {
|
|
50
|
+
const defaults = mapping["defaults"];
|
|
51
|
+
const run = isRecord(defaults) ? defaults["run"] : undefined;
|
|
52
|
+
return isRecord(run) ? scalarText(run[WORKING_DIRECTORY]) : undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Every command one workflow or hook manager file writes under `key`, in every mapping of the
|
|
56
|
+
* document, each with the directory it runs in: its mapping's `dirKey` value, else, in a workflow
|
|
57
|
+
* file, the innermost `defaults.run.working-directory` of a mapping holding it, else `root`. A
|
|
58
|
+
* file `yamlDocument` does not read gives none.
|
|
59
|
+
*/
|
|
60
|
+
function keyedCommands(text, root, key, dirKey) {
|
|
61
|
+
const found = [];
|
|
62
|
+
const visit = (node, inherited) => {
|
|
63
|
+
if (Array.isArray(node)) {
|
|
64
|
+
for (const item of node) {
|
|
65
|
+
visit(item, inherited);
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!isRecord(node)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const here = (dirKey === WORKING_DIRECTORY ? defaultDirectory(node) : undefined) ?? inherited;
|
|
73
|
+
const command = scalarText(node[key]);
|
|
74
|
+
if (command !== undefined && command.trim() !== "") {
|
|
75
|
+
const written = (dirKey === undefined ? undefined : scalarText(node[dirKey])) ?? here;
|
|
76
|
+
found.push({
|
|
77
|
+
text: command,
|
|
78
|
+
dir: written === undefined
|
|
79
|
+
? root
|
|
80
|
+
: written.includes("${{")
|
|
81
|
+
? undefined
|
|
82
|
+
: resolvePath(root, written),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
for (const value of Object.values(node)) {
|
|
86
|
+
visit(value, here);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
visit(yamlDocument(text), undefined);
|
|
90
|
+
return found;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The command lefthook runs for each script a lefthook file's hooks name, each key of a hook's
|
|
94
|
+
* `scripts` and each `script` of a job in its `jobs`, a group's among them, from each directory
|
|
95
|
+
* it searches: its `runner`, then the path `<dir>/<hook>/<name>` quoted as lefthook quotes it,
|
|
96
|
+
* run in the target root: https://lefthook.dev/configuration/Scripts/
|
|
97
|
+
*/
|
|
98
|
+
function lefthookScripts(text, root) {
|
|
99
|
+
const document = yamlDocument(text);
|
|
100
|
+
if (!isRecord(document)) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
const dirs = [
|
|
104
|
+
scalarText(document["source_dir"]) ?? ".lefthook/",
|
|
105
|
+
scalarText(document["source_dir_local"]) ?? ".lefthook-local/",
|
|
106
|
+
...LEFTHOOK_DIRS,
|
|
107
|
+
];
|
|
108
|
+
const found = [];
|
|
109
|
+
const add = (hook, name, runner) => {
|
|
110
|
+
for (const dir of dirs) {
|
|
111
|
+
const path = `'${joinPath(dir, hook, name).replaceAll("'", "'\\''")}'`;
|
|
112
|
+
found.push({
|
|
113
|
+
text: runner === undefined || runner.trim() === "" ? path : `${runner} ${path}`,
|
|
114
|
+
dir: root,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const jobs = (hook, list) => {
|
|
119
|
+
for (const job of Array.isArray(list) ? list : []) {
|
|
120
|
+
const script = isRecord(job) ? scalarText(job["script"]) : undefined;
|
|
121
|
+
if (isRecord(job) && script !== undefined) {
|
|
122
|
+
add(hook, script, scalarText(job["runner"]));
|
|
123
|
+
}
|
|
124
|
+
const group = isRecord(job) ? job["group"] : undefined;
|
|
125
|
+
jobs(hook, isRecord(group) ? group["jobs"] : undefined);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
for (const [hook, value] of Object.entries(document)) {
|
|
129
|
+
const scripts = isRecord(value) ? value["scripts"] : undefined;
|
|
130
|
+
for (const [name, options] of Object.entries(isRecord(scripts) ? scripts : {})) {
|
|
131
|
+
add(hook, name, isRecord(options) ? scalarText(options["runner"]) : undefined);
|
|
132
|
+
}
|
|
133
|
+
jobs(hook, isRecord(value) ? value["jobs"] : undefined);
|
|
134
|
+
}
|
|
135
|
+
return found;
|
|
136
|
+
}
|
|
137
|
+
/** The path of each git hook script at `root`, every file in {@link HOOK_DIRS}. */
|
|
138
|
+
function hookScripts(host, root) {
|
|
139
|
+
return HOOK_DIRS.flatMap((dir) => filesIn(host, joinPath(root, dir), () => true).map((name) => joinPath(root, dir, name)));
|
|
140
|
+
}
|
|
141
|
+
/** The makefile make reads at `root`, the first of {@link MAKEFILES} there. */
|
|
142
|
+
function makefileAt(host, root) {
|
|
143
|
+
return MAKEFILES.map((name) => joinPath(root, name)).find((candidate) => host.kindOf(candidate) === "file");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* One recipe line as make hands it to the shell: each `$$` a `$`, and each reference to a
|
|
147
|
+
* variable or a function, which make expands first, a part only the run knows:
|
|
148
|
+
* https://www.gnu.org/software/make/manual/html_node/Reference.html
|
|
149
|
+
*/
|
|
150
|
+
function expandedByMake(line) {
|
|
151
|
+
let expanded = "";
|
|
152
|
+
for (let at = 0; at < line.length; at += 1) {
|
|
153
|
+
const char = line.charAt(at);
|
|
154
|
+
const next = line.charAt(at + 1);
|
|
155
|
+
if (char !== "$") {
|
|
156
|
+
expanded += char;
|
|
157
|
+
}
|
|
158
|
+
else if (next === "$") {
|
|
159
|
+
expanded += "$";
|
|
160
|
+
at += 1;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
let end = at + 1;
|
|
164
|
+
if (next === "(" || next === "{") {
|
|
165
|
+
const close = next === "(" ? ")" : "}";
|
|
166
|
+
for (let depth = 0; end < line.length; end += 1) {
|
|
167
|
+
depth += line.charAt(end) === next ? 1 : line.charAt(end) === close ? -1 : 0;
|
|
168
|
+
if (depth === 0) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
expanded += PART;
|
|
174
|
+
at = Math.min(end, line.length);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return expanded;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Each recipe line of the target root's makefile: a line that starts with a tab, joined with
|
|
181
|
+
* the lines a trailing `\` continues it onto, less the `@`, `-` and `+` make reads before it,
|
|
182
|
+
* as make expands it. Make runs each line in a shell of its own.
|
|
183
|
+
*/
|
|
184
|
+
function recipeLines(host, root) {
|
|
185
|
+
const path = makefileAt(host, root);
|
|
186
|
+
const text = path === undefined ? undefined : readText(host, path);
|
|
187
|
+
return (text ?? "")
|
|
188
|
+
.replace(/\\\r?\n/gu, " ")
|
|
189
|
+
.split(/\r?\n/u)
|
|
190
|
+
.filter((line) => line.startsWith("\t"))
|
|
191
|
+
.map((line) => ({
|
|
192
|
+
text: expandedByMake(line.slice(1).replace(/^[@+-]+/u, "")),
|
|
193
|
+
dir: root,
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Every command the target root's workflow steps, git hooks, hook managers and makefile run:
|
|
198
|
+
* the `run:` steps of the workflow files in `.github/workflows`, each file in `.husky` and
|
|
199
|
+
* `.githooks` as one shell script, the `entry:` commands of `.pre-commit-config.yaml`, the
|
|
200
|
+
* `run:` commands and the scripts of a lefthook file and the makefile's recipe lines.
|
|
201
|
+
*/
|
|
202
|
+
export function workflowCommands(host, targetRoot) {
|
|
203
|
+
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
204
|
+
const workflows = filesIn(host, joinPath(root, WORKFLOWS), (name) => /\.ya?ml$/u.test(name));
|
|
205
|
+
return [
|
|
206
|
+
...workflows.flatMap((name) => keyedCommands(readText(host, joinPath(root, WORKFLOWS, name)) ?? "", root, "run", WORKING_DIRECTORY)),
|
|
207
|
+
...hookScripts(host, root).map((path) => ({
|
|
208
|
+
text: readText(host, path) ?? "",
|
|
209
|
+
dir: root,
|
|
210
|
+
})),
|
|
211
|
+
...HOOK_MANAGERS.flatMap(({ name, key, dirKey, scripts }) => {
|
|
212
|
+
const text = readText(host, joinPath(root, name)) ?? "";
|
|
213
|
+
return [
|
|
214
|
+
...keyedCommands(text, root, key, dirKey),
|
|
215
|
+
...(scripts === true ? lefthookScripts(text, root) : []),
|
|
216
|
+
];
|
|
217
|
+
}),
|
|
218
|
+
...recipeLines(host, root),
|
|
219
|
+
];
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The whole text of each file {@link workflowCommands} reads a command from, each workflow file,
|
|
223
|
+
* git hook, hook manager file and makefile at the target root, which the dependency rule reads.
|
|
224
|
+
*/
|
|
225
|
+
export function commandFileTexts(host, targetRoot) {
|
|
226
|
+
return commandFiles(host, targetRoot).flatMap(({ path }) => readText(host, path) ?? []);
|
|
227
|
+
}
|
|
228
|
+
/** Each file {@link workflowCommands} reads a command from, with the key a YAML file writes its commands under. */
|
|
229
|
+
function commandFiles(host, targetRoot) {
|
|
230
|
+
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
231
|
+
return [
|
|
232
|
+
...filesIn(host, joinPath(root, WORKFLOWS), (name) => /\.ya?ml$/u.test(name)).map((name) => ({
|
|
233
|
+
path: joinPath(root, WORKFLOWS, name),
|
|
234
|
+
key: "run",
|
|
235
|
+
})),
|
|
236
|
+
...hookScripts(host, root).map((path) => ({ path, key: undefined })),
|
|
237
|
+
...HOOK_MANAGERS.map(({ name, key }) => ({ path: joinPath(root, name), key })),
|
|
238
|
+
...[makefileAt(host, root) ?? []].flat().map((path) => ({ path, key: undefined })),
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* The filters of a workflow's `on` key, which name the files and refs whose change triggers it
|
|
243
|
+
* and run none: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onpushpull_requestpull_request_targetpathspaths-ignore
|
|
244
|
+
*/
|
|
245
|
+
const TRIGGER_FILTERS = new Set([
|
|
246
|
+
"paths",
|
|
247
|
+
"paths-ignore",
|
|
248
|
+
"branches",
|
|
249
|
+
"branches-ignore",
|
|
250
|
+
"tags",
|
|
251
|
+
"tags-ignore",
|
|
252
|
+
]);
|
|
253
|
+
/**
|
|
254
|
+
* The values of one YAML file that are no command, each with its key: every scalar but one
|
|
255
|
+
* written under `key`, which is read as a command string, and one of a trigger filter. A file
|
|
256
|
+
* `yamlDocument` does not read is one value, its whole text. No key and no comment is a value.
|
|
257
|
+
*/
|
|
258
|
+
function yamlValues(text, key) {
|
|
259
|
+
const document = yamlDocument(text);
|
|
260
|
+
if (document === undefined) {
|
|
261
|
+
return [{ text, shell: false }];
|
|
262
|
+
}
|
|
263
|
+
const found = [];
|
|
264
|
+
// `trigger` is 1 for the value of the top-level `on`, a map of events, and 2 for an event's.
|
|
265
|
+
const visit = (node, under, trigger = 0) => {
|
|
266
|
+
if (Array.isArray(node)) {
|
|
267
|
+
for (const item of node) {
|
|
268
|
+
visit(item, under);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else if (isRecord(node)) {
|
|
272
|
+
for (const [name, value] of Object.entries(node)) {
|
|
273
|
+
const on = node === document && (name === "on" || name === "true");
|
|
274
|
+
if ((name !== key || scalarText(value) === undefined) &&
|
|
275
|
+
!(trigger === 2 && TRIGGER_FILTERS.has(name))) {
|
|
276
|
+
visit(value, name, on ? 1 : trigger === 1 ? 2 : 0);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const value = scalarText(node);
|
|
282
|
+
if (value !== undefined) {
|
|
283
|
+
found.push({ text: value, shell: false, ...(under === undefined ? {} : { key: under }) });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
visit(document, undefined);
|
|
288
|
+
return found;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* The lines of a makefile that are no recipe line, joined with the lines a trailing `\`
|
|
292
|
+
* continues them onto, each without the comment a `#` make does not read as escaped starts.
|
|
293
|
+
*/
|
|
294
|
+
function makefileValues(text) {
|
|
295
|
+
return text
|
|
296
|
+
.replace(/\\\r?\n/gu, " ")
|
|
297
|
+
.split(/\r?\n/u)
|
|
298
|
+
.filter((line) => !line.startsWith("\t"))
|
|
299
|
+
.map((line) => line.replace(/(?<!\\)#.*$/u, ""))
|
|
300
|
+
.filter((line) => line.trim() !== "")
|
|
301
|
+
.map((line) => ({ text: line, shell: false }));
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* The texts layer 3 reads of the target root's command files: each command string, and each
|
|
305
|
+
* value of a workflow file, a hook manager file and the makefile that is no command.
|
|
306
|
+
*/
|
|
307
|
+
function heldTexts(host, targetRoot) {
|
|
308
|
+
const makefile = makefileAt(host, resolvePath(host.workingDirectory(), targetRoot));
|
|
309
|
+
return [
|
|
310
|
+
...workflowCommands(host, targetRoot).map(({ text }) => ({ text, shell: true })),
|
|
311
|
+
...commandFiles(host, targetRoot).flatMap(({ path, key }) => {
|
|
312
|
+
const text = readText(host, path);
|
|
313
|
+
return text === undefined
|
|
314
|
+
? []
|
|
315
|
+
: key !== undefined
|
|
316
|
+
? yamlValues(text, key)
|
|
317
|
+
: path === makefile
|
|
318
|
+
? makefileValues(text)
|
|
319
|
+
: [];
|
|
320
|
+
}),
|
|
321
|
+
];
|
|
322
|
+
}
|
|
323
|
+
/** Reads the target root's workflow steps, git hooks, hook managers and makefile. */
|
|
324
|
+
export function readWorkflows(host, targetRoot) {
|
|
325
|
+
return {
|
|
326
|
+
readings: workflowCommands(host, targetRoot).map(({ text, dir }) => readCommands(text, dir)),
|
|
327
|
+
texts: commandFileTexts(host, targetRoot),
|
|
328
|
+
held: heldTexts(host, targetRoot),
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The own files the target root's workflow steps, git hooks and recipes run or name, as
|
|
333
|
+
* `pathsNamed` reads each command.
|
|
334
|
+
*/
|
|
335
|
+
export function workflowEntries(workflows, files) {
|
|
336
|
+
const found = [];
|
|
337
|
+
for (const reading of workflows.readings) {
|
|
338
|
+
for (const { path, written } of pathsNamed(reading)) {
|
|
339
|
+
for (const file of files.named(path)) {
|
|
340
|
+
found.push({ file, source: written });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return found;
|
|
345
|
+
}
|
package/dist/src/enum-group.js
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* or `unknown` expression asserted to it, or bound to a variable or returned from a
|
|
7
7
|
* function it annotates, where a number counts too. An enum's own value converts nothing.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral,
|
|
9
|
+
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral, isParenthesizedTypeNode, isPropertyAccessExpression, isReturnStatement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
10
11
|
import { TypeFlags } from "@typescript/native/sync";
|
|
11
12
|
import { aliasChains } from "./alias-chain.js";
|
|
12
13
|
import { nodeKey } from "./inventory.js";
|
|
@@ -16,14 +17,6 @@ import { isAnswered, UNANSWERED } from "./query.js";
|
|
|
16
17
|
const NUMBER = TypeFlags.NumberLike;
|
|
17
18
|
const STRING = TypeFlags.StringLike;
|
|
18
19
|
const DECODED = TypeFlags.Any | TypeFlags.Unknown;
|
|
19
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
20
|
-
function unparenthesized(node) {
|
|
21
|
-
let held = node;
|
|
22
|
-
while (isParenthesizedExpression(held)) {
|
|
23
|
-
held = held.expression;
|
|
24
|
-
}
|
|
25
|
-
return held;
|
|
26
|
-
}
|
|
27
20
|
/**
|
|
28
21
|
* The name node a type node names its declaration by: the identifier of a type
|
|
29
22
|
* reference, the right side of a qualified one, through parentheses. A type that is no
|
|
@@ -45,7 +38,7 @@ function typeName(type) {
|
|
|
45
38
|
}
|
|
46
39
|
/** The name node an expression names an object by: an identifier, or a property access's name. */
|
|
47
40
|
function objectName(expression) {
|
|
48
|
-
const held =
|
|
41
|
+
const held = parenthesesRemoved(expression);
|
|
49
42
|
if (isIdentifier(held)) {
|
|
50
43
|
return held;
|
|
51
44
|
}
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* either stores. A store into an erased property of a type the analyzed program does not
|
|
7
7
|
* declare hands the value to the code that declares it.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression,
|
|
9
|
+
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadElement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
10
|
import { SymbolFlags, TypeFlags } from "@typescript/native/sync";
|
|
11
11
|
import { must } from "./query.js";
|
|
12
12
|
import { checkedTypes } from "./value-reach.js";
|
|
13
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
13
14
|
/** The types that keep nothing of the value they are given. */
|
|
14
15
|
const ERASED = TypeFlags.Any | TypeFlags.Unknown;
|
|
15
16
|
/** The array methods whose arguments become elements of the array they are called on. */
|
|
@@ -20,9 +21,6 @@ function literalKey(node) {
|
|
|
20
21
|
? node.text
|
|
21
22
|
: undefined;
|
|
22
23
|
}
|
|
23
|
-
function unwrapped(node) {
|
|
24
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
25
|
-
}
|
|
26
24
|
/**
|
|
27
25
|
* Whether a variable declaration's type can differ from what is stored in it: it carries an
|
|
28
26
|
* annotation, or it has neither an annotation nor an initializer, so its type evolves.
|
|
@@ -76,8 +74,8 @@ function propertyAt(source, name) {
|
|
|
76
74
|
* here, and a default value is stored in its target too.
|
|
77
75
|
*/
|
|
78
76
|
function patternTargets(pattern, from, out) {
|
|
79
|
-
const target =
|
|
80
|
-
const source = from.path.length === 0 ?
|
|
77
|
+
const target = parenthesesRemoved(pattern);
|
|
78
|
+
const source = from.path.length === 0 ? parenthesesRemoved(from.value) : from.value;
|
|
81
79
|
const into = (element, step, literal) => {
|
|
82
80
|
patternTargets(element, literal === undefined
|
|
83
81
|
? { value: from.value, path: [...from.path, step] }
|
|
@@ -1,62 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* The exemption classes of the Contract's vocabulary, in its order: each class's name, its
|
|
3
|
-
* languages and, for a TypeScript class, which private members it may retain. The rows are
|
|
4
|
-
* written out, as the fixed severity codes are, and a test holds them equal to the Contract.
|
|
5
|
-
* A class name is a type, so a table or a record naming a class outside the vocabulary, or
|
|
6
|
-
* one of another language only, does not compile.
|
|
7
|
-
*/
|
|
8
|
-
/** Every class of the vocabulary, in the order the Contract lists them. */
|
|
9
|
-
export const EXEMPTION_CLASSES = [
|
|
10
|
-
{
|
|
11
|
-
class: "interface-satisfaction",
|
|
12
|
-
languages: ["go", "ts"],
|
|
13
|
-
typescriptVisibility: { private: false, privateName: false },
|
|
14
|
-
},
|
|
15
|
-
{ class: "encoding-reflection", languages: ["go"] },
|
|
16
|
-
{ class: "format-verb-contract", languages: ["go"] },
|
|
17
|
-
{ class: "errors-duck-typing", languages: ["go"] },
|
|
18
|
-
{
|
|
19
|
-
class: "enum-group",
|
|
20
|
-
languages: ["go", "ts"],
|
|
21
|
-
typescriptVisibility: { private: false, privateName: false },
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
class: "generated-file",
|
|
25
|
-
languages: ["go", "ts"],
|
|
26
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
27
|
-
},
|
|
28
|
-
{ class: "linkname-cgo-asm-plugin", languages: ["go"] },
|
|
29
|
-
{
|
|
30
|
-
class: "template-field",
|
|
31
|
-
languages: ["go", "ts"],
|
|
32
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
class: "reflective-lookup",
|
|
36
|
-
languages: ["go", "ts"],
|
|
37
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
class: "decorator",
|
|
41
|
-
languages: ["ts"],
|
|
42
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
class: "injection-container",
|
|
46
|
-
languages: ["ts"],
|
|
47
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
class: "framework-lifecycle",
|
|
51
|
-
languages: ["ts"],
|
|
52
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
class: "serialization-contract",
|
|
56
|
-
languages: ["ts"],
|
|
57
|
-
typescriptVisibility: { private: true, privateName: false },
|
|
58
|
-
},
|
|
59
|
-
];
|
|
1
|
+
import { EXEMPTION_CLASSES } from "./contract/contract.generated.js";
|
|
60
2
|
function runsOnTS(row) {
|
|
61
3
|
const languages = row.languages;
|
|
62
4
|
return languages.includes("ts");
|
|
@@ -69,7 +11,3 @@ const VISIBILITY = new Map(TS_ROWS.map((row) => [row.class, row.typescriptVisibi
|
|
|
69
11
|
export function typescriptVisibilityOf(exemptionClass) {
|
|
70
12
|
return VISIBILITY.get(exemptionClass) ?? { private: false, privateName: false };
|
|
71
13
|
}
|
|
72
|
-
/** Whether one name is a class of the vocabulary, whichever language it runs on. */
|
|
73
|
-
export function isExemptionClass(name) {
|
|
74
|
-
return EXEMPTION_CLASSES.some((row) => row.class === name);
|
|
75
|
-
}
|
package/dist/src/exempt.js
CHANGED
|
@@ -6,26 +6,17 @@
|
|
|
6
6
|
* which records held something back. It names no class's detector: the composition
|
|
7
7
|
* hands it the table of the classes it has.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { EXEMPTION_CLASSES } from "./contract/contract.generated.js";
|
|
10
|
+
import { TS_EXEMPTION_CLASSES, typescriptVisibilityOf, } from "./exempt-classes.js";
|
|
11
11
|
import { byPosition, positionKey } from "./position.js";
|
|
12
12
|
import { Unanswerable } from "./query.js";
|
|
13
|
-
import {
|
|
13
|
+
import { bytewise } from "./text/compare.js";
|
|
14
14
|
/**
|
|
15
|
-
* The classes `exemptions.disabled` switches off. A
|
|
16
|
-
*
|
|
17
|
-
* switches nothing off here, so one configuration serves every analyzer.
|
|
15
|
+
* The classes `exemptions.disabled` switches off. A class that runs on another language
|
|
16
|
+
* only switches nothing off here, so one configuration serves every analyzer.
|
|
18
17
|
*/
|
|
19
18
|
export function disabledClasses(config) {
|
|
20
|
-
|
|
21
|
-
for (const name of config.exemptionsDisabled) {
|
|
22
|
-
if (!isExemptionClass(name)) {
|
|
23
|
-
const known = EXEMPTION_CLASSES.map((row) => row.class).join(", ");
|
|
24
|
-
throw new ConfigError("malformed", "exemptions.disabled", `exemptions.disabled: ${JSON.stringify(name)} is not an exemption class: the classes are ${known}`);
|
|
25
|
-
}
|
|
26
|
-
disabled.add(name);
|
|
27
|
-
}
|
|
28
|
-
return disabled;
|
|
19
|
+
return new Set(config.exemptions.disabled);
|
|
29
20
|
}
|
|
30
21
|
/**
|
|
31
22
|
* Whether a class whose row states `allowed` may retain a member of one visibility. A
|
|
@@ -40,20 +31,8 @@ function retainable(allowed, visibility) {
|
|
|
40
31
|
}
|
|
41
32
|
return true;
|
|
42
33
|
}
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
* back whole. A class with no row here holds back every declaration but a file.
|
|
46
|
-
*/
|
|
47
|
-
const RETAINABLE = new Map([
|
|
48
|
-
["interface-satisfaction", new Set(["method", "class-member"])],
|
|
49
|
-
["enum-group", new Set(["enum-member"])],
|
|
50
|
-
["injection-container", new Set(["method", "class-member"])],
|
|
51
|
-
["framework-lifecycle", new Set(["method", "class-member"])],
|
|
52
|
-
[
|
|
53
|
-
"serialization-contract",
|
|
54
|
-
new Set(["method", "class-member", "interface-method", "type-member"]),
|
|
55
|
-
],
|
|
56
|
-
]);
|
|
34
|
+
/** The kinds of declaration each class can hold back, which a detector that stops holds back whole. */
|
|
35
|
+
const RETAINABLE = new Map(EXEMPTION_CLASSES.flatMap((row) => "ts" in row.retainsKinds ? [[row.class, new Set(row.retainsKinds.ts)]] : []));
|
|
57
36
|
/** The detail of a record a detector that could not finish holds. */
|
|
58
37
|
const UNANSWERED_DETAIL = "kept live by a question the checker did not answer";
|
|
59
38
|
/** Whether one record is held by a detector that could not finish. */
|
|
@@ -76,7 +55,7 @@ function detected(exemptionClass, detect, input) {
|
|
|
76
55
|
}
|
|
77
56
|
const kinds = RETAINABLE.get(exemptionClass);
|
|
78
57
|
return input.held.symbols
|
|
79
|
-
.filter((symbol) =>
|
|
58
|
+
.filter((symbol) => kinds?.has(symbol.kind) === true)
|
|
80
59
|
.map((symbol) => ({ id: symbol.id, detail: UNANSWERED_DETAIL, site: symbol.position }));
|
|
81
60
|
}
|
|
82
61
|
}
|
|
@@ -106,11 +85,19 @@ export function evidenceRecords(input, detectors, disabled) {
|
|
|
106
85
|
site: evidence.site,
|
|
107
86
|
...(evidence.whileLive === undefined ? {} : { whileLive: evidence.whileLive }),
|
|
108
87
|
...(evidence.implementing === undefined ? {} : { implementing: evidence.implementing }),
|
|
88
|
+
...(evidence.whileWritten === undefined ? {} : { whileWritten: evidence.whileWritten }),
|
|
109
89
|
});
|
|
110
90
|
}
|
|
111
91
|
}
|
|
112
92
|
return found;
|
|
113
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* The records that hold given the declarations a write the mode counts stores into: one
|
|
96
|
+
* that holds only while written holds where its declaration is among them.
|
|
97
|
+
*/
|
|
98
|
+
export function writtenRecords(records, written) {
|
|
99
|
+
return records.flatMap(({ whileWritten, ...record }) => whileWritten === undefined || written.has(record.id) ? [record] : []);
|
|
100
|
+
}
|
|
114
101
|
/** The records that hold under one mode, beside the evidence a production mode found in a test file. */
|
|
115
102
|
export function heldRecords(records, holding) {
|
|
116
103
|
const found = [];
|
|
@@ -125,20 +112,13 @@ export function heldRecords(records, holding) {
|
|
|
125
112
|
}
|
|
126
113
|
return { records: exemptionsOf(found), inTestFiles };
|
|
127
114
|
}
|
|
128
|
-
/** Two strings ordered bytewise. */
|
|
129
|
-
function compare(a, b) {
|
|
130
|
-
if (a === b) {
|
|
131
|
-
return 0;
|
|
132
|
-
}
|
|
133
|
-
return a < b ? -1 : 1;
|
|
134
|
-
}
|
|
135
115
|
/**
|
|
136
116
|
* Records as a run holds them: ordered by site, then class, then declaration, and one
|
|
137
117
|
* per declaration, class, detail and file it holds while live, the one at the first
|
|
138
118
|
* site. A fact found at many sites, or by several projects, is one record.
|
|
139
119
|
*/
|
|
140
120
|
export function exemptionsOf(found) {
|
|
141
|
-
const ordered = [...found].sort((a, b) => byPosition(a.site, b.site) ||
|
|
121
|
+
const ordered = [...found].sort((a, b) => byPosition(a.site, b.site) || bytewise(a.class, b.class) || bytewise(a.id, b.id));
|
|
142
122
|
const seen = new Set();
|
|
143
123
|
return ordered.filter((record) => {
|
|
144
124
|
const fact = [record.id, record.class, record.detail, record.whileLive ?? ""].join("\u0000");
|
|
@@ -149,13 +129,6 @@ export function exemptionsOf(found) {
|
|
|
149
129
|
return true;
|
|
150
130
|
});
|
|
151
131
|
}
|
|
152
|
-
/**
|
|
153
|
-
* The records that hold while the component files at `live` are live: every record that
|
|
154
|
-
* holds whatever is live, and each one a live file's markup holds, as a record of the run.
|
|
155
|
-
*/
|
|
156
|
-
export function holdingWhile(records, live) {
|
|
157
|
-
return exemptionsOf(records.flatMap(({ whileLive, ...record }) => whileLive === undefined || live.has(whileLive) ? [record] : []));
|
|
158
|
-
}
|
|
159
132
|
/** The records per declaration, each declaration's in the order given. */
|
|
160
133
|
function byDeclaration(records) {
|
|
161
134
|
const grouped = new Map();
|
|
@@ -171,26 +144,8 @@ function byDeclaration(records) {
|
|
|
171
144
|
return grouped;
|
|
172
145
|
}
|
|
173
146
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* configuration answers, or one in `writeOnly`, which the run would report as written
|
|
177
|
-
* and never read without the record's read. A declaration a relation or a mark holds
|
|
178
|
-
* live in every configuration is held back by no record. The order is the
|
|
179
|
-
* declarations' site order, and for one declaration the input's.
|
|
180
|
-
*/
|
|
181
|
-
export function retainedIn(matrix, input, writeOnly = new Set()) {
|
|
182
|
-
const exempt = input.exempt ?? [];
|
|
183
|
-
if (exempt.length === 0) {
|
|
184
|
-
return [];
|
|
185
|
-
}
|
|
186
|
-
const bare = { marked: input.marked, mode: input.mode };
|
|
187
|
-
const dead = new Set(matrix.graphs.flatMap((graph) => sweep(graph, bare).candidates.map((candidate) => candidate.id)));
|
|
188
|
-
const held = byDeclaration(exempt.filter((record) => dead.has(record.id) || writeOnly.has(record.id)));
|
|
189
|
-
return matrix.union.symbols.flatMap((symbol) => held.get(symbol.id) ?? []);
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* One line per held-back declaration, in site order: its reference, then each record's
|
|
193
|
-
* class, site and detail, all separated by tabs.
|
|
147
|
+
* One line per held-back declaration, in site order: its reference and position, then
|
|
148
|
+
* each record's class, site and detail, all separated by tabs.
|
|
194
149
|
*/
|
|
195
150
|
export function retainedLines(symbols, retained) {
|
|
196
151
|
const held = byDeclaration(retained);
|
|
@@ -204,6 +159,6 @@ export function retainedLines(symbols, retained) {
|
|
|
204
159
|
positionKey(record.site),
|
|
205
160
|
record.detail,
|
|
206
161
|
]);
|
|
207
|
-
return [[symbol.ref, ...fields].join("\t")];
|
|
162
|
+
return [[symbol.ref, positionKey(symbol.position), ...fields].join("\t")];
|
|
208
163
|
});
|
|
209
164
|
}
|