@cplieger/deadset-ts 8.0.0-dev.6 → 8.0.0-dev.8
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/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/analysis.js +37 -56
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/build-scripts.js +17 -29
- 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 +27 -168
- package/dist/src/configured-declarations.js +15 -20
- package/dist/src/consumers.js +2 -2
- package/dist/src/contract/config.generated.js +544 -0
- package/dist/src/contract/contract.generated.js +13 -0
- package/dist/src/contract/report.generated.js +3 -2
- package/dist/src/conventions.js +20 -60
- package/dist/src/dependencies.js +25 -43
- package/dist/src/discover.js +14 -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 +3 -10
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +0 -4
- package/dist/src/exempt.js +6 -22
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +5 -4
- package/dist/src/findings/emitters.js +1 -1
- package/dist/src/findings/intra-function.js +1 -1
- package/dist/src/findings/non-code-artifacts.js +2 -2
- package/dist/src/findings/reads-and-writes.js +2 -1
- package/dist/src/findings/self-check.js +3 -2
- package/dist/src/findings/unused-declarations.js +1 -1
- package/dist/src/findings/visibility-narrowing.js +2 -2
- package/dist/src/findings-pass.js +7 -12
- package/dist/src/framework-lifecycle.js +7 -7
- package/dist/src/fs/document.js +59 -0
- package/dist/src/fs/manifest.js +43 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/git-ignore.js +34 -25
- package/dist/src/html-entries.js +6 -33
- package/dist/src/in-operands.js +2 -1
- package/dist/src/injection-container.js +1 -1
- package/dist/src/intra-function-parts.js +10 -13
- package/dist/src/inventory.js +2 -21
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +0 -7
- package/dist/src/manifest.js +5 -43
- package/dist/src/mdx-entries.js +3 -26
- 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/references.js +14 -27
- package/dist/src/report-schema.js +3 -225
- package/dist/src/report.js +22 -31
- package/dist/src/reporters/sarif.js +4 -2
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +245 -724
- package/dist/src/roots.js +7 -17
- package/dist/src/run.js +55 -61
- package/dist/src/schema.js +320 -343
- package/dist/src/scope.js +34 -103
- package/dist/src/serialization-contract.js +5 -9
- package/dist/src/session.js +2 -1
- package/dist/src/suppress-file.js +21 -25
- package/dist/src/suppress.js +3 -3
- package/dist/src/symbol-keys.js +3 -5
- package/dist/src/template-field.js +9 -19
- package/dist/src/test-globals.js +6 -28
- package/dist/src/test-joins.js +6 -6
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/{yaml-document.js → text/yaml.js} +38 -0
- package/dist/src/type-errors.js +14 -38
- package/dist/src/unseen-loads.js +2 -9
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/verbs/analyze.js +25 -26
- package/dist/src/verbs/describe.js +4 -4
- package/dist/src/verbs/explain.js +8 -6
- package/dist/src/verbs/print-projects.js +4 -3
- package/dist/src/verbs/print-retained.js +2 -1
- package/dist/src/verbs/print-roots.js +2 -1
- package/dist/src/verbs/version.js +2 -1
- package/dist/src/workflow-steps.js +9 -46
- package/dist/src/workspace-manifests.js +2 -2
- package/dist/src/workspace-programs.js +5 -3
- package/dist/src/workspace-resolution.js +13 -17
- package/dist/src/workspace.js +28 -116
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/analysis.ts +55 -76
- package/src/automatic-types.ts +11 -29
- package/src/build-scripts.ts +17 -38
- package/src/component-layer.ts +4 -2
- package/src/components.ts +2 -4
- package/src/config.ts +31 -296
- package/src/configuration-files.ts +27 -170
- package/src/configured-declarations.ts +18 -23
- package/src/consumers.ts +4 -4
- package/src/contract/config.generated.ts +798 -0
- package/src/contract/contract.generated.ts +25 -0
- package/src/contract/report.generated.ts +3 -2
- package/src/conventions.ts +26 -74
- package/src/dependencies.ts +32 -50
- package/src/discover.ts +15 -40
- 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 +2 -13
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +0 -5
- package/src/exempt.ts +8 -30
- package/src/file-facts.ts +6 -24
- package/src/findings/completion.ts +5 -6
- package/src/findings/emitter.ts +2 -2
- package/src/findings/emitters.ts +1 -1
- package/src/findings/intra-function.ts +1 -1
- package/src/findings/non-code-artifacts.ts +4 -4
- package/src/findings/reads-and-writes.ts +2 -1
- package/src/findings/self-check.ts +3 -2
- package/src/findings/unused-declarations.ts +1 -1
- package/src/findings/visibility-narrowing.ts +2 -2
- package/src/findings-pass.ts +9 -15
- package/src/framework-lifecycle.ts +7 -7
- package/src/fs/document.ts +74 -0
- package/src/fs/manifest.ts +52 -0
- package/src/fs/tree.ts +110 -0
- package/src/git-ignore.ts +38 -25
- package/src/host.ts +12 -5
- package/src/html-entries.ts +6 -33
- package/src/in-operands.ts +2 -1
- package/src/injection-container.ts +1 -1
- package/src/intra-function-parts.ts +10 -14
- package/src/inventory.ts +2 -20
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +0 -8
- package/src/manifest.ts +5 -46
- package/src/mdx-entries.ts +3 -26
- package/src/partial.ts +2 -1
- 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/references.ts +14 -29
- package/src/report-schema.ts +3 -301
- package/src/report.ts +24 -34
- package/src/reporters/sarif.ts +4 -4
- package/src/reporters/template.ts +4 -20
- package/src/resolve.ts +283 -1114
- package/src/roots.ts +7 -20
- package/src/run.ts +57 -75
- package/src/schema.ts +391 -388
- package/src/scope.ts +40 -126
- package/src/serialization-contract.ts +5 -10
- package/src/session.ts +2 -1
- package/src/suppress-file.ts +21 -29
- package/src/suppress.ts +3 -3
- package/src/symbol-keys.ts +2 -5
- package/src/template-field.ts +15 -25
- package/src/test-globals.ts +9 -27
- package/src/test-joins.ts +6 -8
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/shell.ts +161 -0
- package/src/{yaml-document.ts → text/yaml.ts} +46 -0
- package/src/type-errors.ts +25 -36
- package/src/unseen-loads.ts +1 -12
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/verbs/analyze.ts +32 -42
- package/src/verbs/describe.ts +4 -4
- package/src/verbs/explain.ts +8 -10
- package/src/verbs/print-projects.ts +4 -3
- package/src/verbs/print-retained.ts +2 -1
- package/src/verbs/print-roots.ts +2 -1
- package/src/verbs/verb.ts +2 -2
- package/src/verbs/version.ts +2 -1
- package/src/workflow-steps.ts +9 -44
- package/src/workspace-manifests.ts +2 -2
- package/src/workspace-programs.ts +5 -3
- package/src/workspace-resolution.ts +21 -17
- package/src/workspace.ts +35 -121
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
package/dist/src/kinds.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { KIND_ROWS } from "./contract/contract.generated.js";
|
|
2
2
|
/** Every live row of the issue-kind vocabulary, by its code, in ascending code order. */
|
|
3
3
|
export const KINDS = new Map(KIND_ROWS.map((one) => [one.code, one]));
|
|
4
|
-
/**
|
|
5
|
-
* The code of every live issue kind, in ascending order. A severity key names one of
|
|
6
|
-
* them or a family prefix whose range holds one; a key naming a retired code, an
|
|
7
|
-
* unassigned code or a range holding no live kind is an unimplemented key, so every
|
|
8
|
-
* severity a configuration sets is one some analyzer reports under.
|
|
9
|
-
*/
|
|
10
|
-
export const LIVE_CODES = KIND_ROWS.map((one) => one.code);
|
|
11
4
|
/** The issue-kind codes whose severity the Contract fixes, in ascending order. */
|
|
12
5
|
export const FIXED_SEVERITY_CODES = KIND_ROWS.filter((one) => one.fixed).map((one) => one.code);
|
package/dist/src/manifest.js
CHANGED
|
@@ -4,14 +4,13 @@
|
|
|
4
4
|
* shell running its command or one of its scripts. {@link readManifest} reads one
|
|
5
5
|
* directory's manifest, {@link packageEntries} those of the packages below the target root.
|
|
6
6
|
*/
|
|
7
|
-
import { isAbsolutePath,
|
|
7
|
+
import { isAbsolutePath, relativePath, resolvePath } from "./paths.js";
|
|
8
|
+
import { isRecord } from "./json-document.js";
|
|
9
|
+
import { MANIFEST, manifestAt } from "./fs/manifest.js";
|
|
10
|
+
import { scriptTokens } from "./text/shell.js";
|
|
8
11
|
/** The manifest's own name. */
|
|
9
|
-
const MANIFEST = "package.json";
|
|
10
12
|
/** The three members that name an entry point beside `exports` and `bin`. */
|
|
11
13
|
const LEGACY_MEMBERS = ["main", "module", "types"];
|
|
12
|
-
function isRecord(value) {
|
|
13
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
|
-
}
|
|
15
14
|
/**
|
|
16
15
|
* Whether one member's value names a file of this package rather than another
|
|
17
16
|
* package or a URL. A target written with no leading dot is a path too, which is
|
|
@@ -23,21 +22,6 @@ function isTarget(value, requireDot) {
|
|
|
23
22
|
}
|
|
24
23
|
return !requireDot || value.startsWith("./");
|
|
25
24
|
}
|
|
26
|
-
/** Where a script's command line splits into tokens: white space and the shell's operators. */
|
|
27
|
-
const SCRIPT_SEPARATORS = /\s+|&&|\|\||;|\|/u;
|
|
28
|
-
/** A token written inside one pair of quotes. */
|
|
29
|
-
const QUOTED = /^(["'])(.*)\1$/su;
|
|
30
|
-
/**
|
|
31
|
-
* Every token one script's command line holds, each with one pair of enclosing quotes
|
|
32
|
-
* removed. A token holding a wildcard is a pattern rather than a path, and names no
|
|
33
|
-
* entry point.
|
|
34
|
-
*/
|
|
35
|
-
export function scriptTokens(command) {
|
|
36
|
-
return command
|
|
37
|
-
.split(SCRIPT_SEPARATORS)
|
|
38
|
-
.map((token) => token.replace(QUOTED, "$2"))
|
|
39
|
-
.filter((token) => token !== "" && !token.includes("*"));
|
|
40
|
-
}
|
|
41
25
|
/** One member's spelling below another: `exports` then `exports["."]`. */
|
|
42
26
|
function below(member, key) {
|
|
43
27
|
return `${member}[${JSON.stringify(key)}]`;
|
|
@@ -69,28 +53,6 @@ function exportTargets(value, member, found) {
|
|
|
69
53
|
exportTargets(held, below(member, key), found);
|
|
70
54
|
}
|
|
71
55
|
}
|
|
72
|
-
/** The manifest at the target root, decoded, or undefined where there is none to read. */
|
|
73
|
-
function manifestOf(host, targetRoot) {
|
|
74
|
-
let text;
|
|
75
|
-
try {
|
|
76
|
-
text = host.readFile(joinPath(targetRoot, MANIFEST));
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
let value;
|
|
82
|
-
try {
|
|
83
|
-
value = JSON.parse(text);
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// A manifest this program cannot read names no entry point, which is the same
|
|
87
|
-
// answer as an absent one. What a manifest's contents say is not refused here:
|
|
88
|
-
// the package manager owns that refusal, and an analysis of a tree it rejects
|
|
89
|
-
// is not the run's subject.
|
|
90
|
-
return undefined;
|
|
91
|
-
}
|
|
92
|
-
return isRecord(value) ? value : undefined;
|
|
93
|
-
}
|
|
94
56
|
/**
|
|
95
57
|
* What the manifest in `targetRoot` declares about where its package is entered.
|
|
96
58
|
*
|
|
@@ -99,7 +61,7 @@ function manifestOf(host, targetRoot) {
|
|
|
99
61
|
* it and there is one such configuration per project, while there is one manifest.
|
|
100
62
|
*/
|
|
101
63
|
export function readManifest(host, targetRoot) {
|
|
102
|
-
const manifest =
|
|
64
|
+
const manifest = manifestAt(host, targetRoot);
|
|
103
65
|
if (manifest === undefined) {
|
|
104
66
|
return { entries: [], declaresExports: false };
|
|
105
67
|
}
|
package/dist/src/mdx-entries.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { resolveRelativeSpecifier } from "./configuration-files.js";
|
|
7
7
|
import { dirnamePath, joinPath, resolvePath } from "./paths.js";
|
|
8
|
-
|
|
9
|
-
const SKIPPED = new Set(["node_modules", ".git"]);
|
|
8
|
+
import { filesBelow } from "./fs/tree.js";
|
|
10
9
|
/** The extensions of a document whose imports an MDX compiler reads. */
|
|
11
10
|
const DOCUMENT = /\.mdx?$/u;
|
|
12
11
|
/** A fence line, its marker run and what follows it captured. */
|
|
@@ -100,29 +99,6 @@ function clauseNames(clause) {
|
|
|
100
99
|
}
|
|
101
100
|
return names;
|
|
102
101
|
}
|
|
103
|
-
/** Every document below `dir`, outside every skipped directory, by absolute path. */
|
|
104
|
-
function documents(host, dir) {
|
|
105
|
-
let entries;
|
|
106
|
-
try {
|
|
107
|
-
entries = host.readDirectory(dir);
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
return [];
|
|
111
|
-
}
|
|
112
|
-
const found = [];
|
|
113
|
-
for (const entry of entries) {
|
|
114
|
-
const path = joinPath(dir, entry.name);
|
|
115
|
-
if (entry.directory) {
|
|
116
|
-
if (!SKIPPED.has(entry.name)) {
|
|
117
|
-
found.push(...documents(host, path));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
else if (DOCUMENT.test(entry.name)) {
|
|
121
|
-
found.push(path);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return found.sort();
|
|
125
|
-
}
|
|
126
102
|
/** The relative specifiers one document's import lines name, its fenced code blocks skipped. */
|
|
127
103
|
function importedBy(text) {
|
|
128
104
|
const found = [];
|
|
@@ -165,7 +141,8 @@ function documentImports(host, root) {
|
|
|
165
141
|
if (known !== undefined) {
|
|
166
142
|
return known;
|
|
167
143
|
}
|
|
168
|
-
const found =
|
|
144
|
+
const found = filesBelow(host, root, (name) => DOCUMENT.test(name)).flatMap((below) => {
|
|
145
|
+
const path = joinPath(root, below);
|
|
169
146
|
try {
|
|
170
147
|
return [{ path, imports: importedBy(host.readFile(path)) }];
|
|
171
148
|
}
|
package/dist/src/partial.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { relativePath } from "./paths.js";
|
|
2
|
+
import { bytewise } from "./text/compare.js";
|
|
2
3
|
/** A count with its noun, so a line reads for one as well as for several. */
|
|
3
4
|
function counted(n, one, many) {
|
|
4
5
|
return `${String(n)} ${n === 1 ? one : many}`;
|
|
@@ -10,7 +11,7 @@ function counted(n, one, many) {
|
|
|
10
11
|
*/
|
|
11
12
|
export function partialNotes(partial) {
|
|
12
13
|
const notes = [...partial.notBuilt]
|
|
13
|
-
.sort((a, b) => (a.id
|
|
14
|
+
.sort((a, b) => bytewise(a.id, b.id))
|
|
14
15
|
.map((one) => `the derived configuration ${one.id} was not built and is not analyzed: ${one.error}`);
|
|
15
16
|
if (partial.unanswered.length > 0) {
|
|
16
17
|
const byProject = new Map();
|
package/dist/src/paths.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Filesystem paths
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* They are written here rather than taken from the platform's own library because
|
|
6
|
-
* every module below the command line stays free of the platform, and because the
|
|
7
|
-
* supported platform set is one, so a second spelling would be a rule nothing
|
|
8
|
-
* exercises.
|
|
2
|
+
* Filesystem paths as the supported platform spells them: a solidus between segments, a
|
|
3
|
+
* leading one for an absolute path. They are written here rather than taken from the
|
|
4
|
+
* platform's library so every module below the command line stays free of the platform.
|
|
9
5
|
*/
|
|
10
6
|
const SEPARATOR = "/";
|
|
11
7
|
/** Whether one path names a place without a directory to resolve it against. */
|
|
@@ -61,6 +57,24 @@ export function dirnamePath(path) {
|
|
|
61
57
|
}
|
|
62
58
|
return cut === 0 ? SEPARATOR : normalized.slice(0, cut);
|
|
63
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* `dir` and every directory above it, nearest first, normalized. With `top`, the list ends
|
|
62
|
+
* at `top` and is empty where `dir` is neither `top` nor below it; without, it ends at the
|
|
63
|
+
* root of the path.
|
|
64
|
+
*/
|
|
65
|
+
export function ancestors(dir, top) {
|
|
66
|
+
const end = top === undefined ? undefined : normalizePath(top);
|
|
67
|
+
const found = [];
|
|
68
|
+
for (let at = normalizePath(dir);; at = dirnamePath(at)) {
|
|
69
|
+
if (end !== undefined && at !== end && relativePath(end, at) === undefined) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
found.push(at);
|
|
73
|
+
if (at === end || dirnamePath(at) === at) {
|
|
74
|
+
return found;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
64
78
|
/**
|
|
65
79
|
* The extension of one path's last segment, from its last full stop, or the empty string
|
|
66
80
|
* where it has none. A segment that only starts with a full stop has none.
|
|
@@ -92,14 +106,11 @@ export function queriedModulePath(specifier) {
|
|
|
92
106
|
return raw ? undefined : specifier.slice(0, query);
|
|
93
107
|
}
|
|
94
108
|
/**
|
|
95
|
-
* One path as it reads below a root, or undefined when it is not below the root
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* The caller resolves both against the same directory before calling: a relative
|
|
102
|
-
* root and an absolute path are two spellings this cannot reconcile.
|
|
109
|
+
* One path as it reads below a root, or undefined when it is not strictly below the root:
|
|
110
|
+
* the root itself is not below itself. Both are normalized, then compared lexically, so a
|
|
111
|
+
* root and a path spelled through different symbolic links name nothing in common. The
|
|
112
|
+
* caller resolves both against the same directory first: a relative root and an absolute
|
|
113
|
+
* path cannot be reconciled.
|
|
103
114
|
*/
|
|
104
115
|
export function relativePath(root, path) {
|
|
105
116
|
const at = normalizePath(root);
|
package/dist/src/position.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { relativePath } from "./paths.js";
|
|
2
|
+
import { bytewise } from "./text/compare.js";
|
|
2
3
|
/**
|
|
3
4
|
* A file the program holds whose path is not below the target root, which leaves
|
|
4
5
|
* the analysis unable to name a declaration it found. It ends the run rather than
|
|
@@ -58,7 +59,7 @@ export function positionKey(position) {
|
|
|
58
59
|
*/
|
|
59
60
|
export function byPosition(a, b) {
|
|
60
61
|
if (a.path !== b.path) {
|
|
61
|
-
return a.path
|
|
62
|
+
return bytewise(a.path, b.path);
|
|
62
63
|
}
|
|
63
64
|
if (a.line !== b.line) {
|
|
64
65
|
return a.line - b.line;
|
package/dist/src/print.js
CHANGED
|
@@ -1,83 +1,15 @@
|
|
|
1
|
-
import { renderOrigin
|
|
2
|
-
|
|
3
|
-
function declarationOf(entry) {
|
|
4
|
-
switch (entry.shape) {
|
|
5
|
-
case "symbol":
|
|
6
|
-
return { symbol: entry.symbol };
|
|
7
|
-
case "module":
|
|
8
|
-
return { module: entry.module, name: entry.name };
|
|
9
|
-
case "global":
|
|
10
|
-
return { global: entry.global };
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
/** One provider entry as a document writes it: the members of its shape alone. */
|
|
14
|
-
function providerOf(entry) {
|
|
15
|
-
const installed = { name: entry.name, languages: entry.languages, command: entry.command };
|
|
16
|
-
if (entry.shape === "installed") {
|
|
17
|
-
return installed;
|
|
18
|
-
}
|
|
19
|
-
return { ...installed, source: entry.source, version: entry.version, digest: entry.digest };
|
|
20
|
-
}
|
|
1
|
+
import { renderOrigin } from "./config.js";
|
|
2
|
+
import { bytewise } from "./text/compare.js";
|
|
21
3
|
/**
|
|
22
|
-
* The resolved configuration and its provenance as one JSON object, indented,
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* object is a declared key resolution ignores. Keys are written in the schema's
|
|
28
|
-
* order and the severity and provenance objects in ascending key order, so one
|
|
29
|
-
* configuration renders to one string whatever order a source named its settings
|
|
30
|
-
* in.
|
|
4
|
+
* The resolved configuration and its provenance as one JSON object, indented, ending
|
|
5
|
+
* in a newline: the configuration in the order resolution gives it, then the provenance
|
|
6
|
+
* object in ascending key order. Read back as a repository configuration it resolves to
|
|
7
|
+
* the same configuration, because resolution checks the provenance object and then
|
|
8
|
+
* ignores it.
|
|
31
9
|
*/
|
|
32
10
|
export function printConfig(config, provenance) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
languages: config.analysis.languages,
|
|
38
|
-
min_confidence: config.analysis.minConfidence,
|
|
39
|
-
generated_files: config.analysis.generatedFiles,
|
|
40
|
-
consumer_tests: config.analysis.consumerTests,
|
|
41
|
-
configurations: config.analysis.configurations.map((entry) => entry.shape === "project"
|
|
42
|
-
? { id: entry.id, project: entry.project }
|
|
43
|
-
: { id: entry.id, os: entry.os, arch: entry.arch, tags: entry.tags }),
|
|
44
|
-
matrix: { complete: config.analysis.matrixComplete },
|
|
45
|
-
template_dirs: config.analysis.templateDirs,
|
|
46
|
-
template_delimiters: {
|
|
47
|
-
left: config.analysis.templateDelimiters.left,
|
|
48
|
-
right: config.analysis.templateDelimiters.right,
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
consumers: { complete: config.consumersComplete },
|
|
52
|
-
roots: { patterns: config.rootPatterns },
|
|
53
|
-
severity: Object.fromEntries([...config.severity].sort(([a], [b]) => (a < b ? -1 : 1))),
|
|
54
|
-
exemptions: { disabled: config.exemptionsDisabled },
|
|
55
|
-
reporters: {
|
|
56
|
-
formats: config.reporters.formats,
|
|
57
|
-
sort: config.reporters.sort,
|
|
58
|
-
cascade: config.reporters.cascade,
|
|
59
|
-
max_findings: config.reporters.maxFindings,
|
|
60
|
-
fail_on: config.reporters.failOn,
|
|
61
|
-
},
|
|
62
|
-
providers: { analyzers: config.providers.analyzers.map(providerOf) },
|
|
63
|
-
go: {},
|
|
64
|
-
ts: {
|
|
65
|
-
test_files: config.ts.testFiles,
|
|
66
|
-
entry_files: config.ts.entryFiles,
|
|
67
|
-
component_extensions: config.ts.componentExtensions,
|
|
68
|
-
disabled_conventions: config.ts.disabledConventions,
|
|
69
|
-
injection_registrations: config.ts.injectionRegistrations.map(declarationOf),
|
|
70
|
-
lifecycle_contracts: config.ts.lifecycleContracts.map((entry) => ({
|
|
71
|
-
components: entry.components.map(declarationOf),
|
|
72
|
-
bases: entry.bases.map(declarationOf),
|
|
73
|
-
members: entry.members,
|
|
74
|
-
})),
|
|
75
|
-
serializers: config.ts.serializers.map(declarationOf),
|
|
76
|
-
roots_complete: config.ts.rootsComplete,
|
|
77
|
-
},
|
|
78
|
-
provenance: Object.fromEntries([...provenance]
|
|
79
|
-
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
80
|
-
.map(([path, origin]) => [path, renderOrigin(origin)])),
|
|
81
|
-
};
|
|
82
|
-
return `${JSON.stringify(document, undefined, 2)}\n`;
|
|
11
|
+
const origins = [...provenance]
|
|
12
|
+
.sort(([a], [b]) => bytewise(a, b))
|
|
13
|
+
.map(([path, origin]) => [path, renderOrigin(origin)]);
|
|
14
|
+
return `${JSON.stringify({ ...config, provenance: Object.fromEntries(origins) }, undefined, 2)}\n`;
|
|
83
15
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LANGUAGE_ROWS } from "./contract/contract.generated.js";
|
|
2
|
+
/** The language this analyzer reads. */
|
|
3
|
+
export const LANGUAGE = "ts";
|
|
4
|
+
/** The analyzer's name: the one its language's row names, which every output spells it with. */
|
|
5
|
+
export const PRODUCT = LANGUAGE_ROWS[LANGUAGE].analyzer;
|
|
6
|
+
/** Writes one diagnostic line to the error stream, named for the analyzer. */
|
|
7
|
+
export function diagnose(err, text) {
|
|
8
|
+
err.write(`${PRODUCT}: ${text}\n`);
|
|
9
|
+
}
|
|
10
|
+
/** The text one thrown value carries. */
|
|
11
|
+
export function message(error) {
|
|
12
|
+
return error instanceof Error ? error.message : String(error);
|
|
13
|
+
}
|
package/dist/src/references.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { isArrayLiteralExpression, isAsExpression, isBinaryExpression, isCallExpression, isDecorator, isDeleteExpression, isElementAccessExpression, isExportDeclaration, isExpressionStatement, isExternalModuleReference, isForInStatement, isForOfStatement, isForStatement, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isInterfaceDeclaration, isMetaProperty, isModuleBlock, isModuleDeclaration, isNewExpression, isNamespaceExport, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isParenthesizedExpression, isPostfixUnaryExpression, isPrefixUnaryExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, isStringLiteral, isVoidExpression, SyntaxKind, } from "@typescript/native/ast";
|
|
2
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
2
3
|
import { aliasChains } from "./alias-chain.js";
|
|
3
4
|
import { contextualUses } from "./contextual-uses.js";
|
|
4
5
|
import { destructuring, propertyReadsOf } from "./destructuring.js";
|
|
5
6
|
import { specifierCandidates } from "./configuration-files.js";
|
|
6
7
|
import { namespaceUses } from "./namespace-objects.js";
|
|
7
|
-
import { globExpression } from "./glob.js";
|
|
8
8
|
import { declarationsByName, isParameterProperty, nodeKey, } from "./inventory.js";
|
|
9
9
|
import { ambientGlobalInterfaces, augmentationReferences } from "./augmentations.js";
|
|
10
10
|
import { elementAccessReferences } from "./element-access.js";
|
|
@@ -20,6 +20,8 @@ import { typeParameterReads } from "./type-parameter-reads.js";
|
|
|
20
20
|
import { typeQueryAliases } from "./type-query-alias.js";
|
|
21
21
|
import { computedKeyNames, iterationReferences, keyNameOf, keyedUses, } from "./symbol-keys.js";
|
|
22
22
|
import { handedOn, valuesOf } from "./value-flow.js";
|
|
23
|
+
import { bytewise } from "./text/compare.js";
|
|
24
|
+
import { globExpression } from "./text/glob.js";
|
|
23
25
|
/**
|
|
24
26
|
* The operators whose left side one assignment stores into. A compound assignment is
|
|
25
27
|
* among them: where its value is discarded it reads its target only to write the result
|
|
@@ -77,14 +79,6 @@ function valueDiscarded(node) {
|
|
|
77
79
|
function isName(node) {
|
|
78
80
|
return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateIdentifier;
|
|
79
81
|
}
|
|
80
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
81
|
-
function unparenthesized(node) {
|
|
82
|
-
let held = node;
|
|
83
|
-
while (isParenthesizedExpression(held)) {
|
|
84
|
-
held = held.expression;
|
|
85
|
-
}
|
|
86
|
-
return held;
|
|
87
|
-
}
|
|
88
82
|
/**
|
|
89
83
|
* Records the name one store writes into.
|
|
90
84
|
*
|
|
@@ -94,7 +88,7 @@ function unparenthesized(node) {
|
|
|
94
88
|
* target writes each name it binds, through its spreads and nested patterns.
|
|
95
89
|
*/
|
|
96
90
|
function markWrite(target, writes, accesses) {
|
|
97
|
-
const held =
|
|
91
|
+
const held = parenthesesRemoved(target);
|
|
98
92
|
if (isName(held)) {
|
|
99
93
|
writes.add(held.pos);
|
|
100
94
|
return;
|
|
@@ -109,7 +103,7 @@ function markWrite(target, writes, accesses) {
|
|
|
109
103
|
accesses.add(held);
|
|
110
104
|
// A store through a member's value lands in storage every holder of the value
|
|
111
105
|
// reads, so it reads the member; a variable only ever stored into stays written.
|
|
112
|
-
if (!isPropertyAccessExpression(
|
|
106
|
+
if (!isPropertyAccessExpression(parenthesesRemoved(held.expression))) {
|
|
113
107
|
markWrite(held.expression, writes, accesses);
|
|
114
108
|
}
|
|
115
109
|
return;
|
|
@@ -181,7 +175,7 @@ function markStores(node, writes, reads, accesses) {
|
|
|
181
175
|
}
|
|
182
176
|
/** Whether one node is `import.meta.url`. */
|
|
183
177
|
function isImportMetaURL(node) {
|
|
184
|
-
const at =
|
|
178
|
+
const at = parenthesesRemoved(node);
|
|
185
179
|
return (isPropertyAccessExpression(at) &&
|
|
186
180
|
isMetaProperty(at.expression) &&
|
|
187
181
|
at.expression.keywordToken === SyntaxKind.ImportKeyword &&
|
|
@@ -190,7 +184,7 @@ function isImportMetaURL(node) {
|
|
|
190
184
|
/** The module URL one node builds, where it builds one. */
|
|
191
185
|
function moduleURLOf(node) {
|
|
192
186
|
const relative = (argument) => {
|
|
193
|
-
const at = argument === undefined ? undefined :
|
|
187
|
+
const at = argument === undefined ? undefined : parenthesesRemoved(argument);
|
|
194
188
|
return at !== undefined &&
|
|
195
189
|
(isStringLiteral(at) || isNoSubstitutionTemplateLiteral(at)) &&
|
|
196
190
|
/^\.\.?\//u.test(at.text)
|
|
@@ -205,7 +199,7 @@ function moduleURLOf(node) {
|
|
|
205
199
|
: undefined;
|
|
206
200
|
}
|
|
207
201
|
if (isCallExpression(node)) {
|
|
208
|
-
const callee =
|
|
202
|
+
const callee = parenthesesRemoved(node.expression);
|
|
209
203
|
const specifier = relative(node.arguments[0]);
|
|
210
204
|
if (specifier !== undefined &&
|
|
211
205
|
isPropertyAccessExpression(callee) &&
|
|
@@ -490,7 +484,7 @@ export function testFileRulesOf(testFiles, paths, supportFiles = []) {
|
|
|
490
484
|
};
|
|
491
485
|
}),
|
|
492
486
|
...(support === 0 ? [] : [{ rule: TEST_SUPPORT_RULE, matched: support }]),
|
|
493
|
-
].sort((a, b) =>
|
|
487
|
+
].sort((a, b) => bytewise(a.rule, b.rule));
|
|
494
488
|
}
|
|
495
489
|
const importedCache = new WeakMap();
|
|
496
490
|
/**
|
|
@@ -609,20 +603,13 @@ function aloneIn(file, uses, writes, found) {
|
|
|
609
603
|
.filter(([, nodes]) => nodes.some((node) => inside(node, write.value)) &&
|
|
610
604
|
nodes.every((node) => sameTarget.some((one) => inside(node, one.value))))
|
|
611
605
|
.map(([name]) => name)
|
|
612
|
-
.sort(
|
|
606
|
+
.sort(bytewise);
|
|
613
607
|
if (names.length > 0) {
|
|
614
608
|
result.push({ index: write.index, names });
|
|
615
609
|
}
|
|
616
610
|
}
|
|
617
611
|
return result;
|
|
618
612
|
}
|
|
619
|
-
/** Two strings ordered bytewise, which is the order every set of a run is read in. */
|
|
620
|
-
function compare(a, b) {
|
|
621
|
-
if (a === b) {
|
|
622
|
-
return 0;
|
|
623
|
-
}
|
|
624
|
-
return a < b ? -1 : 1;
|
|
625
|
-
}
|
|
626
613
|
/**
|
|
627
614
|
* Every reference one project's own files make to the project's own declarations, in
|
|
628
615
|
* position order, and the files the test-file rules classified.
|
|
@@ -1192,14 +1179,14 @@ export function references(project, held, targetRoot, options) {
|
|
|
1192
1179
|
const scripts = new Set(walked.filter((one) => one.file.externalModuleIndicator === undefined).map((one) => one.fileId));
|
|
1193
1180
|
found.push(...augmentationReferences(held, found, scripts, libraryMerged(scripts)));
|
|
1194
1181
|
found.sort((a, b) => byPosition(a.position, b.position) ||
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1182
|
+
bytewise(a.to, b.to) ||
|
|
1183
|
+
bytewise(a.from, b.from) ||
|
|
1184
|
+
bytewise(a.use, b.use));
|
|
1198
1185
|
return {
|
|
1199
1186
|
references: consumer === undefined
|
|
1200
1187
|
? found
|
|
1201
1188
|
: found.map((reference) => ({ ...reference, consumer: consumer.id })),
|
|
1202
|
-
testFilePaths: tests.sort(
|
|
1189
|
+
testFilePaths: tests.sort(bytewise),
|
|
1203
1190
|
cost: {
|
|
1204
1191
|
batched,
|
|
1205
1192
|
fileBatches,
|