@cplieger/deadset-ts 8.0.0-dev.15 → 8.0.0-dev.17
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/dist/src/alias-chain.js +0 -5
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +94 -54
- package/dist/src/augmentations.js +23 -24
- package/dist/src/bindings.js +382 -0
- package/dist/src/calls.js +25 -8
- package/dist/src/commands/read.js +6 -7
- package/dist/src/commands/tools.js +5 -9
- package/dist/src/component-files.js +3 -2
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +9 -10
- package/dist/src/contextual-uses.js +1 -17
- package/dist/src/contract/config.generated.js +5 -2
- package/dist/src/contract/contract.generated.js +119 -2
- package/dist/src/contract/report.generated.js +6 -2
- package/dist/src/dependencies.js +98 -71
- package/dist/src/destructuring.js +1 -19
- package/dist/src/element-access.js +179 -164
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +22 -64
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
- package/dist/src/entries/conventions.js +739 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +9 -12
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +3 -3
- 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 +684 -0
- package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/findings/completion.js +40 -4
- package/dist/src/findings/emitters.js +5 -8
- package/dist/src/{implementations.js → findings/implementations.js} +3 -3
- package/dist/src/{in-operands.js → findings/in-operands.js} +2 -2
- package/dist/src/findings/self-check.js +36 -20
- package/dist/src/findings-pass.js +5 -6
- package/dist/src/framework-lifecycle.js +42 -15
- package/dist/src/fs/manifest.js +15 -20
- package/dist/src/generated-file.js +172 -29
- package/dist/src/graph.js +14 -8
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/index.js +1 -1
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/injection-container.js +1 -1
- package/dist/src/interface-satisfaction.js +1 -1
- package/dist/src/inventory/commonjs.js +62 -17
- package/dist/src/inventory/enumerate.js +2 -1
- package/dist/src/javascript-file.js +26 -11
- package/dist/src/keyof-comparisons.js +124 -103
- package/dist/src/load/classify.js +28 -9
- package/dist/src/load/diagnostics.js +8 -1
- package/dist/src/load/discover.js +15 -7
- package/dist/src/load/expected-module.js +2 -2
- package/dist/src/load/plan.js +2 -2
- package/dist/src/load/specifiers.js +2 -4
- package/dist/src/load/synthesize.js +10 -5
- package/dist/src/load/workspace-manifests.js +1 -1
- package/dist/src/load/workspace-resolution.js +2 -2
- package/dist/src/matrix.js +12 -17
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/paths.js +56 -1
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +134 -0
- package/dist/src/references/read-rule.js +1 -0
- package/dist/src/references/read-rules.js +48 -0
- package/dist/src/references/sink.js +151 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +111 -1116
- package/dist/src/resolve.js +1 -1
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +7 -4
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
- package/dist/src/{manifest.js → roots/manifest.js} +4 -4
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +489 -0
- package/dist/src/roots/unseen-loads.js +236 -0
- package/dist/src/serialization-contract.js +9 -4
- package/dist/src/source-files.js +5 -9
- package/dist/src/stores.js +4 -2
- package/dist/src/suppress.js +30 -32
- package/dist/src/sweep.js +25 -13
- package/dist/src/symbol-keys.js +89 -83
- 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/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/verbs/analyze.js +15 -3
- package/dist/src/verbs/describe.js +5 -3
- package/dist/src/verbs/explain.js +50 -28
- package/dist/src/verbs/print-retained.js +2 -2
- package/jsr.json +1 -1
- package/package.json +3 -3
- package/src/alias-chain.ts +0 -7
- package/src/amd.ts +130 -0
- package/src/analysis.ts +156 -70
- package/src/augmentations.ts +41 -27
- package/src/automatic-types.ts +1 -1
- package/src/bindings.ts +460 -0
- package/src/calls.ts +25 -7
- package/src/commands/read.ts +6 -8
- package/src/commands/tools.ts +5 -11
- package/src/component-files.ts +4 -2
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +12 -11
- package/src/contextual-uses.ts +2 -22
- package/src/contract/config.generated.ts +5 -2
- package/src/contract/contract.generated.ts +138 -2
- package/src/contract/report.generated.ts +6 -2
- package/src/dependencies.ts +117 -71
- package/src/destructuring.ts +1 -31
- package/src/element-access.ts +188 -182
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +33 -82
- package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
- package/src/{conventions.ts → entries/conventions.ts} +349 -523
- package/src/{html-entries.ts → entries/html-entries.ts} +19 -18
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +5 -5
- 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 +868 -0
- package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
- package/src/exempt.ts +3 -2
- package/src/extensions.ts +45 -0
- package/src/facts.ts +46 -0
- package/src/file-facts.ts +1 -1
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +43 -4
- package/src/findings/emitter.ts +1 -1
- package/src/findings/emitters.ts +14 -10
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
- package/src/findings/self-check.ts +41 -22
- package/src/findings/visibility-narrowing.ts +1 -1
- package/src/findings-pass.ts +5 -12
- package/src/framework-lifecycle.ts +43 -15
- package/src/fs/manifest.ts +25 -21
- package/src/generated-file.ts +240 -36
- package/src/graph.ts +27 -11
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/index.ts +1 -1
- package/src/indexed-access.ts +570 -527
- package/src/injection-container.ts +1 -1
- package/src/interface-satisfaction.ts +1 -1
- package/src/inventory/commonjs.ts +102 -17
- package/src/inventory/enumerate.ts +2 -1
- package/src/javascript-file.ts +29 -12
- package/src/keyof-comparisons.ts +131 -116
- package/src/load/classify.ts +49 -13
- package/src/load/diagnostics.ts +11 -1
- package/src/load/discover.ts +27 -11
- package/src/load/expected-module.ts +8 -2
- package/src/load/plan.ts +11 -2
- package/src/load/specifiers.ts +8 -5
- package/src/load/synthesize.ts +12 -6
- package/src/load/test-globals.ts +1 -1
- package/src/load/workspace-manifests.ts +1 -1
- package/src/load/workspace-resolution.ts +9 -2
- package/src/load/workspace-run.ts +1 -1
- package/src/matrix.ts +13 -17
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/paths.ts +65 -1
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +189 -0
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +213 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +174 -1492
- package/src/report.ts +2 -2
- package/src/resolve.ts +1 -1
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +10 -7
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
- package/src/{manifest.ts → roots/manifest.ts} +5 -5
- package/src/roots/published-reach.ts +481 -0
- package/src/{roots.ts → roots/root-set.ts} +203 -630
- package/src/roots/unseen-loads.ts +345 -0
- package/src/serialization-contract.ts +9 -4
- package/src/source-files.ts +5 -10
- package/src/stores.ts +13 -2
- package/src/suppress.ts +48 -33
- package/src/sweep.ts +37 -14
- package/src/symbol-keys.ts +102 -102
- package/src/tests/file-class.ts +118 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +15 -21
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/verbs/analyze.ts +19 -5
- package/src/verbs/describe.ts +5 -2
- package/src/verbs/explain.ts +75 -32
- package/src/verbs/print-retained.ts +2 -2
- package/dist/src/build-scripts.js +0 -418
- package/dist/src/conventions.js +0 -907
- package/dist/src/entry-points.js +0 -444
- package/dist/src/own-body.js +0 -28
- package/dist/src/roots.js +0 -865
- package/dist/src/unseen-loads.js +0 -189
- package/src/build-scripts.ts +0 -536
- package/src/entry-points.ts +0 -584
- package/src/own-body.ts +0 -42
- package/src/unseen-loads.ts +0 -282
package/src/verbs/analyze.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CONTRACT_VERSION, EXIT_CLEAN, type Format } from "../contract/contract.generated.ts";
|
|
2
2
|
import {
|
|
3
|
+
productionMode,
|
|
3
4
|
runAnalysis,
|
|
4
5
|
runBaselineWrite,
|
|
5
6
|
unansweredCounts,
|
|
@@ -9,10 +10,11 @@ import {
|
|
|
9
10
|
import { kindOf } from "../config.ts";
|
|
10
11
|
import { CONFORMANCE, DECLARED_GAPS } from "../conformance.ts";
|
|
11
12
|
import { analyzerProvenance, verdictOf } from "../findings-pass.ts";
|
|
13
|
+
import { factsDocument } from "../facts.ts";
|
|
12
14
|
import { dirnamePath, joinPath, normalizePath, relativePath, resolvePath } from "../paths.ts";
|
|
13
15
|
import type { Host } from "../host.ts";
|
|
14
|
-
import type { ManifestEntry } from "../manifest.ts";
|
|
15
|
-
import type { HeldScripts } from "../roots.ts";
|
|
16
|
+
import type { ManifestEntry } from "../roots/manifest.ts";
|
|
17
|
+
import type { HeldScripts } from "../roots/root-set.ts";
|
|
16
18
|
import { moduleIdentity, type NotBuilt } from "../load/discover.ts";
|
|
17
19
|
import { partialNotes } from "../partial.ts";
|
|
18
20
|
import {
|
|
@@ -29,7 +31,7 @@ import { RENDERINGS } from "../reporters/reporters.ts";
|
|
|
29
31
|
import { parseTemplate, TemplateError, type Template } from "../reporters/template.ts";
|
|
30
32
|
import { resolve } from "../resolve.ts";
|
|
31
33
|
import { otherSchemeRows, rowReason, writeBaseline, type Recorded } from "../suppress-file.ts";
|
|
32
|
-
import type { UnseenLoad } from "../unseen-loads.ts";
|
|
34
|
+
import type { UnseenLoad } from "../roots/unseen-loads.ts";
|
|
33
35
|
import type { UnreadInput } from "../load/plan.ts";
|
|
34
36
|
import type { UnresolvedSpecifier } from "../load/specifiers.ts";
|
|
35
37
|
|
|
@@ -42,7 +44,7 @@ import { ownVersion } from "./version.ts";
|
|
|
42
44
|
|
|
43
45
|
/** The options `analyze` takes beside the ones every verb takes. */
|
|
44
46
|
export const ANALYZE_OPTIONS: VerbOptions = {
|
|
45
|
-
plain: ["report", "baseline-write", "exit-code", "template"],
|
|
47
|
+
plain: ["report", "facts", "baseline-write", "exit-code", "template"],
|
|
46
48
|
repeatable: ["format"],
|
|
47
49
|
};
|
|
48
50
|
|
|
@@ -258,6 +260,7 @@ function templateOf(
|
|
|
258
260
|
/** Every document one invocation asked for: the report, each rendering beside it, a baseline. */
|
|
259
261
|
interface Documents {
|
|
260
262
|
readonly report: string;
|
|
263
|
+
readonly facts: string | undefined;
|
|
261
264
|
readonly formats: readonly Format[];
|
|
262
265
|
readonly baseline: string | undefined;
|
|
263
266
|
}
|
|
@@ -286,8 +289,13 @@ export const analyzeVerb: Verb = ({ err, host, inputs, scope, openClient, option
|
|
|
286
289
|
const { config, provenance } = resolve(inputs());
|
|
287
290
|
const invoked = host.workingDirectory();
|
|
288
291
|
const baseline = option("baseline-write");
|
|
292
|
+
const facts = option("facts");
|
|
293
|
+
if (facts === "") {
|
|
294
|
+
throw new UsageError("--facts names the path the facts document is written to, and named none");
|
|
295
|
+
}
|
|
289
296
|
const documents: Documents = {
|
|
290
297
|
report: resolvePath(invoked, reportPath),
|
|
298
|
+
facts: facts === undefined ? undefined : resolvePath(invoked, facts),
|
|
291
299
|
formats: formatsOf(repeated("format"), config.reporters.formats),
|
|
292
300
|
baseline: baseline === undefined ? undefined : resolvePath(invoked, baseline),
|
|
293
301
|
};
|
|
@@ -299,7 +307,7 @@ export const analyzeVerb: Verb = ({ err, host, inputs, scope, openClient, option
|
|
|
299
307
|
|
|
300
308
|
let recorded: readonly Recorded[];
|
|
301
309
|
const root = runRelative(invoked, targetRoot);
|
|
302
|
-
const mode =
|
|
310
|
+
const mode = productionMode(config);
|
|
303
311
|
let analysis: RunAnalysis;
|
|
304
312
|
if (documents.baseline === undefined) {
|
|
305
313
|
analysis = runAnalysis(openClient(config), host, scoped, config, provenance, mode);
|
|
@@ -378,6 +386,12 @@ export const analyzeVerb: Verb = ({ err, host, inputs, scope, openClient, option
|
|
|
378
386
|
);
|
|
379
387
|
}
|
|
380
388
|
writeDocument(host, documents.report, "name a path the run can write", () => json(report));
|
|
389
|
+
const factsPath = documents.facts;
|
|
390
|
+
if (factsPath !== undefined) {
|
|
391
|
+
writeDocument(host, factsPath, "name a path the run can write", () => [
|
|
392
|
+
factsDocument(version, run.generated, run.bindings),
|
|
393
|
+
]);
|
|
394
|
+
}
|
|
381
395
|
const options = {
|
|
382
396
|
readSource: (path: string) => host.readFile(joinPath(targetRoot, path)),
|
|
383
397
|
template,
|
package/src/verbs/describe.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
CONTRACT_VERSION,
|
|
3
3
|
EXIT_CLEAN,
|
|
4
4
|
EXIT_USAGE,
|
|
5
|
+
FACTS_VERSION,
|
|
5
6
|
SCHEMA_VERSIONS,
|
|
6
7
|
} from "../contract/contract.generated.ts";
|
|
7
8
|
import { CONFORMANCE, type Conformance } from "../conformance.ts";
|
|
@@ -11,8 +12,9 @@ import { ownVersion } from "./version.ts";
|
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* The document `describe` writes: the analyzer, the Contract version it implements, the
|
|
14
|
-
* report schema versions it reads, the languages it claims,
|
|
15
|
-
* the conformance corpus, a member the document omits where
|
|
15
|
+
* report schema versions it reads, the languages it claims, the facts version it writes,
|
|
16
|
+
* and its recorded result over the conformance corpus, a member the document omits where
|
|
17
|
+
* no run is recorded.
|
|
16
18
|
*/
|
|
17
19
|
export function describeDocument(version: string, recorded: Conformance | undefined): string {
|
|
18
20
|
const document = {
|
|
@@ -21,6 +23,7 @@ export function describeDocument(version: string, recorded: Conformance | undefi
|
|
|
21
23
|
contract_version: CONTRACT_VERSION,
|
|
22
24
|
schema_versions_accepted: SCHEMA_VERSIONS,
|
|
23
25
|
languages: [LANGUAGE],
|
|
26
|
+
facts_version_written: FACTS_VERSION,
|
|
24
27
|
...(recorded === undefined
|
|
25
28
|
? {}
|
|
26
29
|
: {
|
package/src/verbs/explain.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EXIT_CLEAN, EXIT_USAGE } from "../contract/contract.generated.ts";
|
|
2
|
-
import { runAnalysis, type RunAnalysis } from "../analysis.ts";
|
|
2
|
+
import { productionMode, runAnalysis, type RunAnalysis } from "../analysis.ts";
|
|
3
3
|
import { listing } from "../components.ts";
|
|
4
4
|
import type { Cascade } from "../config.ts";
|
|
5
5
|
import type { CompletedFinding } from "../finding.ts";
|
|
@@ -10,8 +10,10 @@ import { partialNotes } from "../partial.ts";
|
|
|
10
10
|
import { resolvePath } from "../paths.ts";
|
|
11
11
|
import { positionKey } from "../position.ts";
|
|
12
12
|
import type { Reference } from "../references.ts";
|
|
13
|
+
import type { Mode } from "../sweep.ts";
|
|
14
|
+
import { madeByTestCode, withheldBy } from "../tests/file-class.ts";
|
|
13
15
|
import { resolve } from "../resolve.ts";
|
|
14
|
-
import type { Root } from "../roots.ts";
|
|
16
|
+
import type { Root } from "../roots/root-set.ts";
|
|
15
17
|
import { type Verb, type VerbOptions } from "./verb.ts";
|
|
16
18
|
import { UsageError } from "../usage.ts";
|
|
17
19
|
import { bytewise } from "../text/compare.ts";
|
|
@@ -141,15 +143,20 @@ type Hop =
|
|
|
141
143
|
| { readonly k: "reference"; readonly reference: Reference }
|
|
142
144
|
| { readonly k: "export"; readonly reference: Reference; readonly to: string };
|
|
143
145
|
|
|
144
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* Where a path starts: a root of the run, or a reference a loaded consumer or a test file no
|
|
148
|
+
* project holds makes.
|
|
149
|
+
*/
|
|
145
150
|
type Origin =
|
|
146
151
|
| { readonly k: "root"; readonly root: Root }
|
|
147
|
-
| { readonly k: "consumer"; readonly consumer: string }
|
|
152
|
+
| { readonly k: "consumer"; readonly consumer: string }
|
|
153
|
+
| { readonly k: "unheld"; readonly file: string };
|
|
148
154
|
|
|
149
155
|
/**
|
|
150
|
-
* The shortest path from a root
|
|
151
|
-
* from every root at once in the order the run names them,
|
|
152
|
-
*
|
|
156
|
+
* The shortest path from a root, a loaded consumer or a test file no project holds to one
|
|
157
|
+
* declaration, walked breadth first from every root at once in the order the run names them,
|
|
158
|
+
* a reference of a consumer or of such a file being the first hop of a path of its own, as
|
|
159
|
+
* the sweep seeds them, and following the references the sweep follows: a
|
|
153
160
|
* reference that reads a module reaches what the module exports, and an evaluation or a root
|
|
154
161
|
* reaches the module alone. Under `production` no reference a test file made is followed,
|
|
155
162
|
* which is the set the report's sweep counts.
|
|
@@ -157,18 +164,26 @@ type Origin =
|
|
|
157
164
|
function shortestPath(
|
|
158
165
|
analysis: RunAnalysis,
|
|
159
166
|
to: string,
|
|
160
|
-
|
|
167
|
+
mode: Mode,
|
|
168
|
+
support: ReadonlySet<string>,
|
|
161
169
|
): { readonly origin: Origin; readonly path: readonly Hop[] } | undefined {
|
|
162
170
|
const graph = analysis.swept.matrix.union;
|
|
163
171
|
const out = new Map<string, Reference[]>();
|
|
164
|
-
const consumed:
|
|
172
|
+
const consumed: { readonly reference: Reference; readonly origin: Origin }[] = [];
|
|
165
173
|
for (const reference of referencesOf(analysis.configured)) {
|
|
166
|
-
if (
|
|
174
|
+
if (withheldBy(mode, reference, support)) {
|
|
167
175
|
continue;
|
|
168
176
|
}
|
|
169
177
|
const { consumer } = reference;
|
|
170
178
|
if (consumer !== undefined) {
|
|
171
|
-
consumed.push({
|
|
179
|
+
consumed.push({ reference, origin: { k: "consumer", consumer } });
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (reference.unheld === true) {
|
|
183
|
+
consumed.push({
|
|
184
|
+
reference,
|
|
185
|
+
origin: { k: "unheld", file: reference.from.replace(/#$/u, "") },
|
|
186
|
+
});
|
|
172
187
|
continue;
|
|
173
188
|
}
|
|
174
189
|
const held = out.get(reference.from);
|
|
@@ -210,13 +225,12 @@ function shortestPath(
|
|
|
210
225
|
for (const root of rootsOf(analysis.configured)) {
|
|
211
226
|
enter({ at: root.id, hop: undefined, previous: -1, origin: { k: "root", root } });
|
|
212
227
|
}
|
|
213
|
-
// A
|
|
214
|
-
// hops do.
|
|
228
|
+
// A consumed reference is one hop long, so it joins the walk where the roots' first hops do.
|
|
215
229
|
const firstHops = steps.length;
|
|
216
230
|
for (let head = 0; ; head += 1) {
|
|
217
231
|
if (head === firstHops) {
|
|
218
|
-
for (const reference of consumed) {
|
|
219
|
-
follow(reference, -1,
|
|
232
|
+
for (const { reference, origin } of consumed) {
|
|
233
|
+
follow(reference, -1, origin);
|
|
220
234
|
}
|
|
221
235
|
}
|
|
222
236
|
const step = steps[head];
|
|
@@ -237,17 +251,35 @@ function shortestPath(
|
|
|
237
251
|
return undefined;
|
|
238
252
|
}
|
|
239
253
|
|
|
254
|
+
/** Where a path starts, as a line names it. */
|
|
255
|
+
function originText(origin: Origin): string {
|
|
256
|
+
switch (origin.k) {
|
|
257
|
+
case "root":
|
|
258
|
+
return `root ${origin.root.kind} ${origin.root.id}`;
|
|
259
|
+
case "consumer":
|
|
260
|
+
return `consumer ${origin.consumer}`;
|
|
261
|
+
case "unheld":
|
|
262
|
+
return `test file no project holds ${origin.file}`;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
240
266
|
/** What made a reference: a declaration of the target, or a loaded consumer. */
|
|
241
267
|
function madeBy(reference: Reference): string {
|
|
242
268
|
return reference.consumer === undefined ? reference.from : `consumer ${reference.consumer}`;
|
|
243
269
|
}
|
|
244
270
|
|
|
245
|
-
|
|
246
|
-
|
|
271
|
+
/** One reference of an answer, marked where test code made it, a test-support file's included. */
|
|
272
|
+
function referenceLine(reference: Reference, tail: string, support: ReadonlySet<string>): string {
|
|
273
|
+
return ` reference: ${positionKey(reference.position)}\t${reference.use}\t${tail}${madeByTestCode(reference, support) ? "\tfrom a test file" : ""}\n`;
|
|
247
274
|
}
|
|
248
275
|
|
|
249
276
|
/** Why a declaration no finding names and no exemption held back is live, or how it fell. */
|
|
250
|
-
function liveness(
|
|
277
|
+
function liveness(
|
|
278
|
+
analysis: RunAnalysis,
|
|
279
|
+
subject: InventorySymbol,
|
|
280
|
+
cascade: Cascade,
|
|
281
|
+
mode: Mode,
|
|
282
|
+
): string {
|
|
251
283
|
const { sweep } = analysis.swept;
|
|
252
284
|
const candidate = sweep.candidates.find((one) => one.id === subject.id);
|
|
253
285
|
if (candidate === undefined && !judged(subject.kind)) {
|
|
@@ -258,23 +290,30 @@ function liveness(analysis: RunAnalysis, subject: InventorySymbol, cascade: Casc
|
|
|
258
290
|
for (const root of rootsOf(analysis.configured).filter((one) => one.id === subject.id)) {
|
|
259
291
|
text += ` root: ${root.kind}${root.source === "" ? "" : `\tnamed by ${root.source}`}\n`;
|
|
260
292
|
}
|
|
293
|
+
const support = new Set(analysis.configured.flatMap((one) => one.supportFiles ?? []));
|
|
261
294
|
const found =
|
|
262
|
-
shortestPath(analysis, subject.id,
|
|
295
|
+
shortestPath(analysis, subject.id, mode, support) ??
|
|
296
|
+
shortestPath(analysis, subject.id, { production: false }, support);
|
|
263
297
|
if (found !== undefined && found.path.length > 0) {
|
|
264
298
|
const { origin } = found;
|
|
265
|
-
text += ` reached from: ${origin
|
|
299
|
+
text += ` reached from: ${originText(origin)}\n`;
|
|
266
300
|
for (const hop of found.path) {
|
|
267
|
-
text += referenceLine(
|
|
301
|
+
text += referenceLine(
|
|
302
|
+
hop.reference,
|
|
303
|
+
`${madeBy(hop.reference)} -> ${hop.reference.to}`,
|
|
304
|
+
support,
|
|
305
|
+
);
|
|
268
306
|
if (hop.k === "export") {
|
|
269
307
|
text += ` export: ${hop.reference.to} -> ${hop.to}\n`;
|
|
270
308
|
}
|
|
271
309
|
}
|
|
272
310
|
} else if (found === undefined) {
|
|
273
311
|
const references = referencesOf(analysis.configured).filter((one) => one.to === subject.id);
|
|
274
|
-
text +=
|
|
312
|
+
text +=
|
|
313
|
+
" unreachable: no path of references reaches it from a root, a loaded consumer or a test file no project holds\n";
|
|
275
314
|
text += ` references: ${String(references.length)}\n`;
|
|
276
315
|
for (const reference of references) {
|
|
277
|
-
text += referenceLine(reference, `from ${madeBy(reference)}
|
|
316
|
+
text += referenceLine(reference, `from ${madeBy(reference)}`, support);
|
|
278
317
|
}
|
|
279
318
|
}
|
|
280
319
|
if (candidate !== undefined) {
|
|
@@ -332,7 +371,12 @@ function namedElsewhere(findings: readonly CompletedFinding[], subject: Inventor
|
|
|
332
371
|
}
|
|
333
372
|
|
|
334
373
|
/** The one explanation that applies to a declaration, built whole before it is written. */
|
|
335
|
-
function explanation(
|
|
374
|
+
function explanation(
|
|
375
|
+
analysis: RunAnalysis,
|
|
376
|
+
subject: InventorySymbol,
|
|
377
|
+
cascade: Cascade,
|
|
378
|
+
mode: Mode,
|
|
379
|
+
): string {
|
|
336
380
|
const graph = analysis.swept.matrix.union;
|
|
337
381
|
const at = graph.at(subject.id);
|
|
338
382
|
let text = `symbol: ${subject.ref}\n`;
|
|
@@ -352,7 +396,7 @@ function explanation(analysis: RunAnalysis, subject: InventorySymbol, cascade: C
|
|
|
352
396
|
text +=
|
|
353
397
|
"answer: held\n held by: a question the checker did not answer, which could have kept it live, so no finding names it\n";
|
|
354
398
|
} else {
|
|
355
|
-
text += liveness(analysis, subject, cascade);
|
|
399
|
+
text += liveness(analysis, subject, cascade, mode);
|
|
356
400
|
}
|
|
357
401
|
return text + namedElsewhere(analysis.result.findings, subject);
|
|
358
402
|
}
|
|
@@ -361,17 +405,16 @@ function explanation(analysis: RunAnalysis, subject: InventorySymbol, cascade: C
|
|
|
361
405
|
* Explains one symbol from the analysis the report is built from: why a reported symbol is
|
|
362
406
|
* reported, which exemption classes held a retained one back, that an unanswered question held
|
|
363
407
|
* a held one, and for any other declaration the relations that hold it live and the shortest
|
|
364
|
-
* path from a root
|
|
365
|
-
* request naming no one declaration exits with the usage
|
|
366
|
-
* matches it. Where the analysis was partial, the error stream says so.
|
|
408
|
+
* path from a root, a loaded consumer or a test file no project holds, or the references it
|
|
409
|
+
* has where no path reaches it. A request naming no one declaration exits with the usage
|
|
410
|
+
* code and names what partially matches it. Where the analysis was partial, the error stream says so.
|
|
367
411
|
*/
|
|
368
412
|
export const explainVerb: Verb = ({ out, err, host, inputs, scope, openClient, option }) => {
|
|
369
413
|
const named = namedSymbol(option);
|
|
370
414
|
const { config, provenance } = resolve(inputs());
|
|
371
415
|
const scoped = scope();
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
});
|
|
416
|
+
const mode = productionMode(config);
|
|
417
|
+
const analysis = runAnalysis(openClient(config), host, scoped, config, provenance, mode);
|
|
375
418
|
const { subject, candidates } = subjectOf(analysis.swept.matrix.union.symbols, named);
|
|
376
419
|
const notes = partialNotes({
|
|
377
420
|
notBuilt: analysis.run.notBuilt,
|
|
@@ -387,7 +430,7 @@ export const explainVerb: Verb = ({ out, err, host, inputs, scope, openClient, o
|
|
|
387
430
|
err.write(" no symbol of the target partially matches it either\n");
|
|
388
431
|
}
|
|
389
432
|
} else {
|
|
390
|
-
out.write(explanation(analysis, subject, config.reporters.cascade));
|
|
433
|
+
out.write(explanation(analysis, subject, config.reporters.cascade, mode));
|
|
391
434
|
}
|
|
392
435
|
for (const note of notes) {
|
|
393
436
|
diagnose(err, note);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EXIT_CLEAN } from "../contract/contract.generated.ts";
|
|
2
|
-
import { runSweep } from "../analysis.ts";
|
|
2
|
+
import { productionMode, runSweep } from "../analysis.ts";
|
|
3
3
|
import { retainedLines } from "../exempt.ts";
|
|
4
4
|
import { partialNotes } from "../partial.ts";
|
|
5
5
|
import { resolvePath } from "../paths.ts";
|
|
@@ -19,7 +19,7 @@ export const printRetainedVerb: Verb = ({ out, err, host, inputs, scope, openCli
|
|
|
19
19
|
const scoped = scope();
|
|
20
20
|
const swept = runSweep(openClient(config), host, scoped, config, {
|
|
21
21
|
marked: [],
|
|
22
|
-
mode:
|
|
22
|
+
mode: productionMode(config),
|
|
23
23
|
});
|
|
24
24
|
for (const line of retainedLines(swept.matrix.union.symbols, swept.retained)) {
|
|
25
25
|
out.write(`${line}\n`);
|