@cplieger/deadset-ts 8.0.0-dev.1 → 8.0.0-dev.11
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 +1 -1
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/analysis.js +181 -341
- package/dist/src/augmentations.js +106 -13
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/build-scripts.js +425 -0
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +2 -3
- package/dist/src/config.js +6 -82
- package/dist/src/configuration-files.js +28 -176
- package/dist/src/configured-declarations.js +15 -20
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +3 -30
- package/dist/src/contextual-uses.js +56 -9
- package/dist/src/contract/config.generated.js +558 -0
- package/dist/src/contract/contract.generated.js +1244 -0
- package/dist/src/contract/report.generated.js +862 -0
- package/dist/src/convention-rows.js +73 -3
- package/dist/src/conventions.js +36 -66
- package/dist/src/dependencies.js +103 -40
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +2 -8
- package/dist/src/entry-points.js +11 -27
- 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 -40
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +139 -72
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +5 -5
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +13 -10
- package/dist/src/findings/non-code-artifacts.js +7 -8
- package/dist/src/findings/reads-and-writes.js +16 -13
- package/dist/src/findings/self-check.js +10 -12
- package/dist/src/findings/unused-declarations.js +41 -32
- package/dist/src/findings/visibility-narrowing.js +19 -16
- package/dist/src/findings-pass.js +8 -15
- package/dist/src/framework-lifecycle.js +7 -7
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +72 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/generated-file.js +7 -4
- package/dist/src/git-ignore.js +39 -26
- package/dist/src/graph.js +5 -3
- package/dist/src/html-entries.js +6 -33
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/injection-container.js +1 -1
- package/dist/src/intra-function-parts.js +63 -43
- package/dist/src/inventory.js +2 -21
- package/dist/src/javascript-file.js +33 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +3 -366
- package/dist/src/load/classify.js +270 -0
- package/dist/src/load/diagnostics.js +80 -0
- package/dist/src/load/discover.js +277 -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/plan.js +313 -0
- package/dist/src/load/specifiers.js +115 -0
- package/dist/src/load/synthesize.js +140 -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} +23 -65
- 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/manifest.js +49 -54
- package/dist/src/matrix.js +76 -4
- package/dist/src/mdx-entries.js +3 -26
- package/dist/src/outside-tests.js +1 -1
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +26 -15
- package/dist/src/position.js +2 -1
- package/dist/src/print.js +11 -79
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +1 -0
- package/dist/src/ref.js +1 -0
- package/dist/src/references.js +48 -30
- 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 +245 -729
- package/dist/src/roots.js +273 -87
- 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 +595 -21
- package/dist/src/session.js +34 -29
- package/dist/src/source-files.js +1 -1
- package/dist/src/suppress-file.js +25 -28
- package/dist/src/suppress-inline.js +3 -2
- package/dist/src/suppress.js +33 -51
- package/dist/src/sweep.js +7 -9
- package/dist/src/symbol-keys.js +3 -5
- package/dist/src/template-field.js +9 -19
- package/dist/src/test-support.js +8 -11
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +54 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/text/yaml.js +393 -0
- package/dist/src/type-errors.js +11 -232
- package/dist/src/unseen-loads.js +100 -0
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/verbs/analyze.js +166 -126
- package/dist/src/verbs/describe.js +9 -16
- package/dist/src/verbs/explain.js +10 -7
- 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 +4 -2
- 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/dist/src/workflow-steps.js +62 -64
- package/jsr.json +1 -1
- package/package.json +5 -4
- package/src/analysis.ts +245 -502
- package/src/augmentations.ts +135 -17
- package/src/automatic-types.ts +11 -29
- package/src/build-scripts.ts +543 -0
- package/src/component-layer.ts +4 -2
- package/src/components.ts +2 -4
- package/src/config.ts +31 -302
- package/src/configuration-files.ts +34 -179
- package/src/configured-declarations.ts +18 -23
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +6 -57
- package/src/contextual-uses.ts +64 -12
- package/src/contract/config.generated.ts +818 -0
- package/src/contract/contract.generated.ts +1308 -0
- package/src/contract/report.generated.ts +1237 -0
- package/src/convention-rows.ts +85 -3
- package/src/conventions.ts +46 -84
- package/src/dependencies.ts +118 -46
- package/src/edges.ts +41 -140
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +3 -9
- package/src/entry-points.ts +12 -38
- 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 +36 -50
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +9 -24
- package/src/finding.ts +14 -9
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +181 -84
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +8 -9
- package/src/findings/emitters.ts +7 -7
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +13 -11
- package/src/findings/non-code-artifacts.ts +9 -11
- package/src/findings/reads-and-writes.ts +20 -16
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +45 -32
- package/src/findings/visibility-narrowing.ts +20 -17
- package/src/findings-pass.ts +10 -19
- package/src/framework-lifecycle.ts +7 -7
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +92 -0
- package/src/fs/tree.ts +110 -0
- package/src/generated-file.ts +7 -4
- package/src/git-ignore.ts +50 -26
- package/src/graph.ts +5 -3
- package/src/host.ts +12 -5
- package/src/html-entries.ts +6 -33
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/injection-container.ts +1 -1
- package/src/intra-function-parts.ts +73 -44
- package/src/inventory.ts +2 -20
- package/src/javascript-file.ts +37 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +5 -413
- package/src/load/classify.ts +397 -0
- package/src/load/diagnostics.ts +144 -0
- package/src/load/discover.ts +455 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +188 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/plan.ts +504 -0
- package/src/load/specifiers.ts +168 -0
- package/src/load/synthesize.ts +211 -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} +33 -76
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/manifest.ts +81 -75
- package/src/matrix.ts +122 -4
- package/src/mdx-entries.ts +3 -26
- package/src/outside-tests.ts +1 -1
- package/src/partial.ts +3 -2
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +12 -92
- package/src/product.ts +18 -0
- package/src/query.ts +11 -0
- package/src/ref.ts +1 -0
- package/src/references.ts +52 -31
- package/src/report-schema.ts +68 -0
- package/src/report.ts +101 -224
- 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 +283 -1114
- package/src/roots.ts +339 -104
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -388
- package/src/scope.ts +46 -138
- package/src/serialization-contract.ts +763 -22
- package/src/session.ts +70 -54
- package/src/source-files.ts +1 -1
- package/src/suppress-file.ts +24 -33
- package/src/suppress-inline.ts +2 -2
- package/src/suppress.ts +43 -58
- package/src/sweep.ts +23 -9
- package/src/symbol-keys.ts +2 -5
- package/src/template-field.ts +15 -25
- package/src/test-support.ts +17 -13
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.inputs.json +1522 -0
- package/src/text/named-files.ts +68 -0
- package/src/text/shell.ts +161 -0
- package/src/text/yaml.ts +423 -0
- package/src/type-errors.ts +18 -288
- package/src/unseen-loads.ts +134 -0
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/verbs/analyze.ts +224 -162
- package/src/verbs/describe.ts +14 -15
- package/src/verbs/explain.ts +10 -11
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +4 -2
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/src/workflow-steps.ts +74 -64
- package/dist/src/base-url.js +0 -18
- package/dist/src/discover.js +0 -468
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/test-joins.js +0 -101
- package/dist/src/version.js +0 -7
- package/src/base-url.ts +0 -24
- package/src/discover.ts +0 -653
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
- package/src/setup-failure.ts +0 -39
- package/src/test-joins.ts +0 -120
- package/src/version.ts +0 -7
package/src/print.ts
CHANGED
|
@@ -1,96 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
type Config,
|
|
4
|
-
type DeclarationEntry,
|
|
5
|
-
type Provenance,
|
|
6
|
-
type Provider,
|
|
7
|
-
} from "./config.ts";
|
|
8
|
-
|
|
9
|
-
/** One declaration entry as a document writes it: the members of its shape alone. */
|
|
10
|
-
function declarationOf(entry: DeclarationEntry): Record<string, string> {
|
|
11
|
-
switch (entry.shape) {
|
|
12
|
-
case "symbol":
|
|
13
|
-
return { symbol: entry.symbol };
|
|
14
|
-
case "module":
|
|
15
|
-
return { module: entry.module, name: entry.name };
|
|
16
|
-
case "global":
|
|
17
|
-
return { global: entry.global };
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** One provider entry as a document writes it: the members of its shape alone. */
|
|
22
|
-
function providerOf(entry: Provider): Record<string, unknown> {
|
|
23
|
-
const installed = { name: entry.name, languages: entry.languages, command: entry.command };
|
|
24
|
-
if (entry.shape === "installed") {
|
|
25
|
-
return installed;
|
|
26
|
-
}
|
|
27
|
-
return { ...installed, source: entry.source, version: entry.version, digest: entry.digest };
|
|
28
|
-
}
|
|
1
|
+
import { renderOrigin, type Provenance, type ResolvedConfig } from "./config.ts";
|
|
2
|
+
import { bytewise } from "./text/compare.ts";
|
|
29
3
|
|
|
30
4
|
/**
|
|
31
|
-
* The resolved configuration and its provenance as one JSON object, indented,
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* object is a declared key resolution ignores. Keys are written in the schema's
|
|
37
|
-
* order and the severity and provenance objects in ascending key order, so one
|
|
38
|
-
* configuration renders to one string whatever order a source named its settings
|
|
39
|
-
* in.
|
|
5
|
+
* The resolved configuration and its provenance as one JSON object, indented, ending
|
|
6
|
+
* in a newline: the configuration in the order resolution gives it, then the provenance
|
|
7
|
+
* object in ascending key order. Read back as a repository configuration it resolves to
|
|
8
|
+
* the same configuration, because resolution checks the provenance object and then
|
|
9
|
+
* ignores it.
|
|
40
10
|
*/
|
|
41
|
-
export function printConfig(config:
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
languages: config.analysis.languages,
|
|
47
|
-
min_confidence: config.analysis.minConfidence,
|
|
48
|
-
generated_files: config.analysis.generatedFiles,
|
|
49
|
-
consumer_tests: config.analysis.consumerTests,
|
|
50
|
-
configurations: config.analysis.configurations.map((entry) =>
|
|
51
|
-
entry.shape === "project"
|
|
52
|
-
? { id: entry.id, project: entry.project }
|
|
53
|
-
: { id: entry.id, os: entry.os, arch: entry.arch, tags: entry.tags },
|
|
54
|
-
),
|
|
55
|
-
matrix: { complete: config.analysis.matrixComplete },
|
|
56
|
-
template_dirs: config.analysis.templateDirs,
|
|
57
|
-
template_delimiters: {
|
|
58
|
-
left: config.analysis.templateDelimiters.left,
|
|
59
|
-
right: config.analysis.templateDelimiters.right,
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
consumers: { complete: config.consumersComplete },
|
|
63
|
-
roots: { patterns: config.rootPatterns },
|
|
64
|
-
severity: Object.fromEntries([...config.severity].sort(([a], [b]) => (a < b ? -1 : 1))),
|
|
65
|
-
exemptions: { disabled: config.exemptionsDisabled },
|
|
66
|
-
reporters: {
|
|
67
|
-
formats: config.reporters.formats,
|
|
68
|
-
sort: config.reporters.sort,
|
|
69
|
-
cascade: config.reporters.cascade,
|
|
70
|
-
max_findings: config.reporters.maxFindings,
|
|
71
|
-
fail_on: config.reporters.failOn,
|
|
72
|
-
},
|
|
73
|
-
providers: { analyzers: config.providers.analyzers.map(providerOf) },
|
|
74
|
-
go: {},
|
|
75
|
-
ts: {
|
|
76
|
-
test_files: config.ts.testFiles,
|
|
77
|
-
entry_files: config.ts.entryFiles,
|
|
78
|
-
component_extensions: config.ts.componentExtensions,
|
|
79
|
-
disabled_conventions: config.ts.disabledConventions,
|
|
80
|
-
injection_registrations: config.ts.injectionRegistrations.map(declarationOf),
|
|
81
|
-
lifecycle_contracts: config.ts.lifecycleContracts.map((entry) => ({
|
|
82
|
-
components: entry.components.map(declarationOf),
|
|
83
|
-
bases: entry.bases.map(declarationOf),
|
|
84
|
-
members: entry.members,
|
|
85
|
-
})),
|
|
86
|
-
serializers: config.ts.serializers.map(declarationOf),
|
|
87
|
-
roots_complete: config.ts.rootsComplete,
|
|
88
|
-
},
|
|
89
|
-
provenance: Object.fromEntries(
|
|
90
|
-
[...provenance]
|
|
91
|
-
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
92
|
-
.map(([path, origin]) => [path, renderOrigin(origin)]),
|
|
93
|
-
),
|
|
94
|
-
};
|
|
95
|
-
return `${JSON.stringify(document, undefined, 2)}\n`;
|
|
11
|
+
export function printConfig(config: ResolvedConfig, provenance: Provenance): string {
|
|
12
|
+
const origins = [...provenance]
|
|
13
|
+
.sort(([a], [b]) => bytewise(a, b))
|
|
14
|
+
.map(([path, origin]): [string, string] => [path, renderOrigin(origin)]);
|
|
15
|
+
return `${JSON.stringify({ ...config, provenance: Object.fromEntries(origins) }, undefined, 2)}\n`;
|
|
96
16
|
}
|
package/src/product.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { LANGUAGE_ROWS } from "./contract/contract.generated.ts";
|
|
2
|
+
import type { Writer } from "./run.ts";
|
|
3
|
+
|
|
4
|
+
/** The language this analyzer reads. */
|
|
5
|
+
export const LANGUAGE = "ts";
|
|
6
|
+
|
|
7
|
+
/** The analyzer's name: the one its language's row names, which every output spells it with. */
|
|
8
|
+
export const PRODUCT = LANGUAGE_ROWS[LANGUAGE].analyzer;
|
|
9
|
+
|
|
10
|
+
/** Writes one diagnostic line to the error stream, named for the analyzer. */
|
|
11
|
+
export function diagnose(err: Writer, text: string): void {
|
|
12
|
+
err.write(`${PRODUCT}: ${text}\n`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** The text one thrown value carries. */
|
|
16
|
+
export function message(error: unknown): string {
|
|
17
|
+
return error instanceof Error ? error.message : String(error);
|
|
18
|
+
}
|
package/src/query.ts
CHANGED
|
@@ -211,6 +211,8 @@ export interface Queries {
|
|
|
211
211
|
symbolOfType(type: Type): Answer<TSSymbol | undefined>;
|
|
212
212
|
signaturesOf(type: Type, kind: SignatureKind): Answer<readonly Signature[]>;
|
|
213
213
|
resolvedSignature(node: Node): Answer<Signature | undefined>;
|
|
214
|
+
/** The signature each call-like node resolves to. */
|
|
215
|
+
resolvedSignatures(nodes: readonly Node[], cap?: number): Answer<Signature | undefined>[];
|
|
214
216
|
parameterType(signature: Signature, index: number): Answer<Type | undefined>;
|
|
215
217
|
/** The generic signature an instantiated one instantiates; none for another signature. */
|
|
216
218
|
genericOf(signature: Signature): Answer<Signature | undefined>;
|
|
@@ -544,6 +546,15 @@ export function queriesOf(
|
|
|
544
546
|
() => nodeLocation(node),
|
|
545
547
|
() => checker.getResolvedSignature(node),
|
|
546
548
|
),
|
|
549
|
+
resolvedSignatures: (nodes, cap = DEFAULT_BATCH_CAP) =>
|
|
550
|
+
each(
|
|
551
|
+
"getResolvedSignature",
|
|
552
|
+
nodes,
|
|
553
|
+
cap,
|
|
554
|
+
nodeLocation,
|
|
555
|
+
(node) => checker.getResolvedSignature.gen(node),
|
|
556
|
+
(node) => checker.getResolvedSignature(node),
|
|
557
|
+
),
|
|
547
558
|
parameterType: (signature, index) =>
|
|
548
559
|
one(
|
|
549
560
|
"getParameterType",
|
package/src/ref.ts
CHANGED
|
@@ -52,6 +52,7 @@ export const REF_EXPRESSIONS: readonly string[] = [
|
|
|
52
52
|
`^${SCOPE}#${TS_HEAD}:import$`,
|
|
53
53
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+$`,
|
|
54
54
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+:static$`,
|
|
55
|
+
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})+\\.${TS_QUOTED}:case$`,
|
|
55
56
|
`^${SCOPE}#${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?<${TS_IDENT}>$`,
|
|
56
57
|
`^${SCOPE}#(?:${TS_HEAD}(?:\\.${TS_MEMBER})*(?::static)?)?\\(${TS_IDENT}\\)$`,
|
|
57
58
|
`^${MANIFEST_SCOPE}#${TS_PACKAGE}:(?:dependency|dev-dependency|peer-dependency)$`,
|
package/src/references.ts
CHANGED
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
isIdentifier,
|
|
16
16
|
isImportDeclaration,
|
|
17
17
|
isImportEqualsDeclaration,
|
|
18
|
+
isInterfaceDeclaration,
|
|
18
19
|
isMetaProperty,
|
|
20
|
+
isModuleBlock,
|
|
21
|
+
isModuleDeclaration,
|
|
19
22
|
isNewExpression,
|
|
20
23
|
isNamespaceExport,
|
|
21
24
|
isNoSubstitutionTemplateLiteral,
|
|
@@ -35,13 +38,13 @@ import {
|
|
|
35
38
|
type ParameterDeclaration,
|
|
36
39
|
type SourceFile,
|
|
37
40
|
} from "@typescript/native/ast";
|
|
41
|
+
import { parenthesesRemoved } from "./unwrap.ts";
|
|
38
42
|
import type { Symbol as TSSymbol } from "@typescript/native/sync";
|
|
39
43
|
import { aliasChains, type ChainTarget } from "./alias-chain.ts";
|
|
40
44
|
import { contextualUses, type FlowAt, type LiteralAt } from "./contextual-uses.ts";
|
|
41
45
|
import { destructuring, propertyReadsOf, type PropertyRead } from "./destructuring.ts";
|
|
42
46
|
import { specifierCandidates } from "./configuration-files.ts";
|
|
43
47
|
import { namespaceUses } from "./namespace-objects.ts";
|
|
44
|
-
import { globExpression } from "./glob.ts";
|
|
45
48
|
import {
|
|
46
49
|
declarationsByName,
|
|
47
50
|
isParameterProperty,
|
|
@@ -49,7 +52,7 @@ import {
|
|
|
49
52
|
type Inventory,
|
|
50
53
|
type InventorySymbol,
|
|
51
54
|
} from "./inventory.ts";
|
|
52
|
-
import { augmentationReferences } from "./augmentations.ts";
|
|
55
|
+
import { ambientGlobalInterfaces, augmentationReferences } from "./augmentations.ts";
|
|
53
56
|
import { elementAccessReferences } from "./element-access.ts";
|
|
54
57
|
import { indexedAccessReferences } from "./indexed-access.ts";
|
|
55
58
|
import { keyofComparisonReferences } from "./keyof-comparisons.ts";
|
|
@@ -70,6 +73,8 @@ import {
|
|
|
70
73
|
type KeyedAccess,
|
|
71
74
|
} from "./symbol-keys.ts";
|
|
72
75
|
import { handedOn, valuesOf } from "./value-flow.ts";
|
|
76
|
+
import { bytewise } from "./text/compare.ts";
|
|
77
|
+
import { globExpression } from "./text/glob.ts";
|
|
73
78
|
|
|
74
79
|
/**
|
|
75
80
|
* Every use one project's own files make of the project's own declarations.
|
|
@@ -312,15 +317,6 @@ function isName(node: Node): boolean {
|
|
|
312
317
|
return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateIdentifier;
|
|
313
318
|
}
|
|
314
319
|
|
|
315
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
316
|
-
function unparenthesized(node: Node): Node {
|
|
317
|
-
let held = node;
|
|
318
|
-
while (isParenthesizedExpression(held)) {
|
|
319
|
-
held = held.expression;
|
|
320
|
-
}
|
|
321
|
-
return held;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
320
|
/**
|
|
325
321
|
* Records the name one store writes into.
|
|
326
322
|
*
|
|
@@ -330,7 +326,7 @@ function unparenthesized(node: Node): Node {
|
|
|
330
326
|
* target writes each name it binds, through its spreads and nested patterns.
|
|
331
327
|
*/
|
|
332
328
|
function markWrite(target: Node, writes: Set<number>, accesses: Set<Node>): void {
|
|
333
|
-
const held =
|
|
329
|
+
const held = parenthesesRemoved(target);
|
|
334
330
|
if (isName(held)) {
|
|
335
331
|
writes.add(held.pos);
|
|
336
332
|
return;
|
|
@@ -345,7 +341,7 @@ function markWrite(target: Node, writes: Set<number>, accesses: Set<Node>): void
|
|
|
345
341
|
accesses.add(held);
|
|
346
342
|
// A store through a member's value lands in storage every holder of the value
|
|
347
343
|
// reads, so it reads the member; a variable only ever stored into stays written.
|
|
348
|
-
if (!isPropertyAccessExpression(
|
|
344
|
+
if (!isPropertyAccessExpression(parenthesesRemoved(held.expression))) {
|
|
349
345
|
markWrite(held.expression, writes, accesses);
|
|
350
346
|
}
|
|
351
347
|
return;
|
|
@@ -521,7 +517,7 @@ interface FileSites {
|
|
|
521
517
|
|
|
522
518
|
/** Whether one node is `import.meta.url`. */
|
|
523
519
|
function isImportMetaURL(node: Node): boolean {
|
|
524
|
-
const at =
|
|
520
|
+
const at = parenthesesRemoved(node);
|
|
525
521
|
return (
|
|
526
522
|
isPropertyAccessExpression(at) &&
|
|
527
523
|
isMetaProperty(at.expression) &&
|
|
@@ -533,7 +529,7 @@ function isImportMetaURL(node: Node): boolean {
|
|
|
533
529
|
/** The module URL one node builds, where it builds one. */
|
|
534
530
|
function moduleURLOf(node: Node): ModuleURL | undefined {
|
|
535
531
|
const relative = (argument: Node | undefined): string | undefined => {
|
|
536
|
-
const at = argument === undefined ? undefined :
|
|
532
|
+
const at = argument === undefined ? undefined : parenthesesRemoved(argument);
|
|
537
533
|
return at !== undefined &&
|
|
538
534
|
(isStringLiteral(at) || isNoSubstitutionTemplateLiteral(at)) &&
|
|
539
535
|
/^\.\.?\//u.test(at.text)
|
|
@@ -548,7 +544,7 @@ function moduleURLOf(node: Node): ModuleURL | undefined {
|
|
|
548
544
|
: undefined;
|
|
549
545
|
}
|
|
550
546
|
if (isCallExpression(node)) {
|
|
551
|
-
const callee =
|
|
547
|
+
const callee = parenthesesRemoved(node.expression);
|
|
552
548
|
const specifier = relative(node.arguments[0]);
|
|
553
549
|
if (
|
|
554
550
|
specifier !== undefined &&
|
|
@@ -866,7 +862,7 @@ export function testFileRulesOf(
|
|
|
866
862
|
};
|
|
867
863
|
}),
|
|
868
864
|
...(support === 0 ? [] : [{ rule: TEST_SUPPORT_RULE, matched: support }]),
|
|
869
|
-
].sort((a, b) =>
|
|
865
|
+
].sort((a, b) => bytewise(a.rule, b.rule));
|
|
870
866
|
}
|
|
871
867
|
|
|
872
868
|
const importedCache = new WeakMap<
|
|
@@ -1000,7 +996,7 @@ function aloneIn(
|
|
|
1000
996
|
nodes.every((node) => sameTarget.some((one) => inside(node, one.value))),
|
|
1001
997
|
)
|
|
1002
998
|
.map(([name]) => name)
|
|
1003
|
-
.sort(
|
|
999
|
+
.sort(bytewise);
|
|
1004
1000
|
if (names.length > 0) {
|
|
1005
1001
|
result.push({ index: write.index, names });
|
|
1006
1002
|
}
|
|
@@ -1008,14 +1004,6 @@ function aloneIn(
|
|
|
1008
1004
|
return result;
|
|
1009
1005
|
}
|
|
1010
1006
|
|
|
1011
|
-
/** Two strings ordered bytewise, which is the order every set of a run is read in. */
|
|
1012
|
-
function compare(a: string, b: string): number {
|
|
1013
|
-
if (a === b) {
|
|
1014
|
-
return 0;
|
|
1015
|
-
}
|
|
1016
|
-
return a < b ? -1 : 1;
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
1007
|
/**
|
|
1020
1008
|
* Every reference one project's own files make to the project's own declarations, in
|
|
1021
1009
|
* position order, and the files the test-file rules classified.
|
|
@@ -1610,6 +1598,39 @@ export function references<Brand>(
|
|
|
1610
1598
|
}
|
|
1611
1599
|
}
|
|
1612
1600
|
|
|
1601
|
+
/** The ambient global interfaces of the walked files that merge into a declaration outside the project's own files. */
|
|
1602
|
+
const libraryMerged = (scripts: ReadonlySet<string>): ReadonlySet<string> => {
|
|
1603
|
+
const names = new Map<string, Node>();
|
|
1604
|
+
const visit = (node: Node): void => {
|
|
1605
|
+
if (isInterfaceDeclaration(node)) {
|
|
1606
|
+
const id = declaredAt(node);
|
|
1607
|
+
if (id !== undefined) {
|
|
1608
|
+
names.set(id, node.name);
|
|
1609
|
+
}
|
|
1610
|
+
} else if (isModuleDeclaration(node) || isModuleBlock(node)) {
|
|
1611
|
+
node.forEachChild(visit);
|
|
1612
|
+
}
|
|
1613
|
+
};
|
|
1614
|
+
for (const { file } of walked) {
|
|
1615
|
+
file.forEachChild(visit);
|
|
1616
|
+
}
|
|
1617
|
+
const global = new Set(ambientGlobalInterfaces(held, [...names.keys()], scripts));
|
|
1618
|
+
const asked = [...names].filter(([id]) => global.has(id));
|
|
1619
|
+
if (asked.length === 0) {
|
|
1620
|
+
return new Set();
|
|
1621
|
+
}
|
|
1622
|
+
const answers = project.symbolsAt(asked.map(([, name]) => project.handle(name)));
|
|
1623
|
+
return new Set(
|
|
1624
|
+
asked.flatMap(([id], at) => {
|
|
1625
|
+
const symbol = answers[at];
|
|
1626
|
+
return typeof symbol === "object" &&
|
|
1627
|
+
symbol.declarations.some((handle) => !ownPaths.has(handle.path))
|
|
1628
|
+
? [id]
|
|
1629
|
+
: [];
|
|
1630
|
+
}),
|
|
1631
|
+
);
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1613
1634
|
const usesOf = new Map(walked.map((one) => [one.file, one.uses]));
|
|
1614
1635
|
for (const [file, writes] of valued) {
|
|
1615
1636
|
const uses = usesOf.get(file) ?? [];
|
|
@@ -1637,13 +1658,13 @@ export function references<Brand>(
|
|
|
1637
1658
|
const scripts = new Set(
|
|
1638
1659
|
walked.filter((one) => one.file.externalModuleIndicator === undefined).map((one) => one.fileId),
|
|
1639
1660
|
);
|
|
1640
|
-
found.push(...augmentationReferences(held, found, scripts));
|
|
1661
|
+
found.push(...augmentationReferences(held, found, scripts, libraryMerged(scripts)));
|
|
1641
1662
|
found.sort(
|
|
1642
1663
|
(a, b) =>
|
|
1643
1664
|
byPosition(a.position, b.position) ||
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1665
|
+
bytewise(a.to, b.to) ||
|
|
1666
|
+
bytewise(a.from, b.from) ||
|
|
1667
|
+
bytewise(a.use, b.use),
|
|
1647
1668
|
);
|
|
1648
1669
|
|
|
1649
1670
|
return {
|
|
@@ -1651,7 +1672,7 @@ export function references<Brand>(
|
|
|
1651
1672
|
consumer === undefined
|
|
1652
1673
|
? found
|
|
1653
1674
|
: found.map((reference) => ({ ...reference, consumer: consumer.id })),
|
|
1654
|
-
testFilePaths: tests.sort(
|
|
1675
|
+
testFilePaths: tests.sort(bytewise),
|
|
1655
1676
|
cost: {
|
|
1656
1677
|
batched,
|
|
1657
1678
|
fileBatches,
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Holds a report to `contract/report.schema.json` and `contract/finding.schema.json`
|
|
3
|
+
* before it is written, reading the schemas the generator copies from the Contract, so
|
|
4
|
+
* this analyzer never writes a document a reader refuses.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { REPORT_SCHEMAS, type Report } from "./contract/report.generated.ts";
|
|
8
|
+
import { schemaRefusals, type SchemaRefusal } from "./schema.ts";
|
|
9
|
+
|
|
10
|
+
const reportSchema = schemaRefusals(REPORT_SCHEMAS, "report.schema.json");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* What the report schema refuses in one report document, none for an instance, and, as
|
|
14
|
+
* no schema keyword can state it, a components listing that is not one entry per
|
|
15
|
+
* component a finding or an edge evaluation's finding names.
|
|
16
|
+
*/
|
|
17
|
+
export function reportRefusals(document: unknown): readonly SchemaRefusal[] {
|
|
18
|
+
const found = reportSchema(document);
|
|
19
|
+
return found.length > 0 ? found : listingRefusals(document as Report);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The components listing held to the components the findings name, once each. */
|
|
23
|
+
function listingRefusals(report: Report): readonly SchemaRefusal[] {
|
|
24
|
+
if (report.components === undefined) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const refuse = (pointer: string, reason: string): SchemaRefusal[] => [
|
|
28
|
+
{ pointer, keyword: "components", reason, member: "" },
|
|
29
|
+
];
|
|
30
|
+
const listed = new Set<string>();
|
|
31
|
+
for (const [i, entry] of report.components.entries()) {
|
|
32
|
+
if (listed.has(entry.id)) {
|
|
33
|
+
return refuse(
|
|
34
|
+
`/components/${String(i)}`,
|
|
35
|
+
`the entry lists component ${entry.id} a second time`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
listed.add(entry.id);
|
|
39
|
+
}
|
|
40
|
+
const named = [
|
|
41
|
+
...report.findings.map(
|
|
42
|
+
(finding, i) => [`/findings/${String(i)}`, finding.component.id] as const,
|
|
43
|
+
),
|
|
44
|
+
...report.edge_evaluations.flatMap((one, i) =>
|
|
45
|
+
one.finding === undefined
|
|
46
|
+
? []
|
|
47
|
+
: [[`/edge_evaluations/${String(i)}/finding`, one.finding.component.id] as const],
|
|
48
|
+
),
|
|
49
|
+
];
|
|
50
|
+
for (const [pointer, id] of named) {
|
|
51
|
+
if (!listed.has(id)) {
|
|
52
|
+
return refuse(
|
|
53
|
+
pointer,
|
|
54
|
+
`the finding names component ${id}, which the components listing lacks`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const ids = new Set(named.map(([, id]) => id));
|
|
59
|
+
for (const [i, entry] of report.components.entries()) {
|
|
60
|
+
if (!ids.has(entry.id)) {
|
|
61
|
+
return refuse(
|
|
62
|
+
`/components/${String(i)}`,
|
|
63
|
+
`the entry lists component ${entry.id}, which no finding names`,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
}
|