@cplieger/deadset-ts 3.0.0 → 3.1.0
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/src/alias-chain.js +96 -0
- package/dist/src/analysis.js +14 -13
- package/dist/src/graph.js +5 -1
- package/dist/src/matrix.js +138 -0
- package/dist/src/references.js +78 -100
- package/dist/src/roots.js +14 -37
- package/dist/src/session.js +16 -5
- package/dist/src/sweep.js +13 -17
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/alias-chain.ts +135 -0
- package/src/analysis.ts +21 -27
- package/src/components.ts +1 -1
- package/src/graph.ts +12 -3
- package/src/matrix.ts +212 -0
- package/src/references.ts +108 -113
- package/src/roots.ts +15 -46
- package/src/session.ts +18 -5
- package/src/sweep.ts +16 -22
package/src/session.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
} from "@typescript/native/unstable/sync";
|
|
13
13
|
import { isIdentifier } from "@typescript/native/unstable/ast";
|
|
14
14
|
import type { Node, SourceFile } from "@typescript/native/unstable/ast";
|
|
15
|
+
import { DiscoveryError } from "./discover.ts";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* The compiler the analysis reads through. It is a client over a protocol to a
|
|
@@ -218,13 +219,16 @@ export interface SessionResult<Result> {
|
|
|
218
219
|
|
|
219
220
|
/**
|
|
220
221
|
* Runs `visit` over every project the compiler configurations name, inside one
|
|
221
|
-
* snapshot of one client.
|
|
222
|
+
* snapshot of one client, in the order they are named, and answers in that order.
|
|
222
223
|
*
|
|
223
224
|
* The snapshot is opened once with every configuration, so each becomes a project
|
|
224
225
|
* with its own program and checker; it is never updated, because the analysis
|
|
225
|
-
* reads and the tree does not change under it.
|
|
226
|
-
*
|
|
227
|
-
*
|
|
226
|
+
* reads and the tree does not change under it. The order the snapshot lists its
|
|
227
|
+
* projects in is the compiler's own, so each named configuration is looked up in it
|
|
228
|
+
* instead, and a configuration the snapshot opened no project for ends the run: the
|
|
229
|
+
* run would otherwise answer for fewer projects than it was asked to analyze. The
|
|
230
|
+
* snapshot is disposed once when the last project has been visited, and the client
|
|
231
|
+
* is released after it, whether the visit completed or threw.
|
|
228
232
|
*/
|
|
229
233
|
export function runSession<Result>(
|
|
230
234
|
engine: Engine,
|
|
@@ -234,7 +238,16 @@ export function runSession<Result>(
|
|
|
234
238
|
try {
|
|
235
239
|
const snapshot = engine.updateSnapshot(configFiles);
|
|
236
240
|
try {
|
|
237
|
-
const
|
|
241
|
+
const opened = new Map(
|
|
242
|
+
snapshot.getProjects().map((project) => [project.configFileName, project]),
|
|
243
|
+
);
|
|
244
|
+
const projects = configFiles.map((configFile) => {
|
|
245
|
+
const project = opened.get(configFile);
|
|
246
|
+
if (project === undefined) {
|
|
247
|
+
throw new DiscoveryError(`${configFile} opened no project`, []);
|
|
248
|
+
}
|
|
249
|
+
return visit(viewOf(project));
|
|
250
|
+
});
|
|
238
251
|
return { projects, timing: engine.getTimingInfo() };
|
|
239
252
|
} finally {
|
|
240
253
|
snapshot.dispose();
|
package/src/sweep.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Which declarations of one graph are dead, under which liveness relation
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Which declarations of one graph are dead, and under which liveness relation.
|
|
3
|
+
* Reference counting holds a declaration live when any declaration references it,
|
|
4
|
+
* whatever that one's own liveness, or when it is a root of a kind that names a caller;
|
|
5
5
|
* reachability holds it live when a path of references reaches it from a root. So a
|
|
6
6
|
* declaration only unreachable ones reference is live under the first, dead under the second.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { componentsOf, type Component } from "./components.ts";
|
|
10
9
|
import { namesACaller, OUTSIDE, type Graph } from "./graph.ts";
|
|
11
10
|
|
|
12
11
|
/** The liveness relation that decided a declaration, as a finding spells it. */
|
|
@@ -54,8 +53,8 @@ export interface Candidate {
|
|
|
54
53
|
readonly testOfDeadCode: boolean;
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
/** One
|
|
58
|
-
export interface
|
|
56
|
+
/** One graph's answer: what each relation holds live, and what is dead. */
|
|
57
|
+
export interface Liveness {
|
|
59
58
|
/**
|
|
60
59
|
* Per declaration, the relations that hold it live, reference counting first. A
|
|
61
60
|
* declaration neither holds live has no entry.
|
|
@@ -63,8 +62,6 @@ export interface SweepResult {
|
|
|
63
62
|
readonly liveUnder: ReadonlyMap<string, readonly Relation[]>;
|
|
64
63
|
/** The dead declarations, in the order the inventory holds them. */
|
|
65
64
|
readonly candidates: readonly Candidate[];
|
|
66
|
-
/** The dead components, each before every component it reaches. */
|
|
67
|
-
readonly components: readonly Component[];
|
|
68
65
|
}
|
|
69
66
|
|
|
70
67
|
/**
|
|
@@ -72,10 +69,9 @@ export interface SweepResult {
|
|
|
72
69
|
*
|
|
73
70
|
* The order is the order the answers depend on: the callers and the marks are live
|
|
74
71
|
* before either relation runs, the candidate set is every judged declaration at least
|
|
75
|
-
* one relation does not hold live, the tests of dead code join it
|
|
76
|
-
* are computed over the set that results.
|
|
72
|
+
* one relation does not hold live, and the tests of dead code join it.
|
|
77
73
|
*/
|
|
78
|
-
export function sweep(graph: Graph, input: SweepInput):
|
|
74
|
+
export function sweep(graph: Graph, input: SweepInput): Liveness {
|
|
79
75
|
const marked = graph.symbols.map(() => false);
|
|
80
76
|
for (const id of input.marked) {
|
|
81
77
|
const at = graph.at(id);
|
|
@@ -136,11 +132,7 @@ export function sweep(graph: Graph, input: SweepInput): SweepResult {
|
|
|
136
132
|
});
|
|
137
133
|
});
|
|
138
134
|
|
|
139
|
-
return {
|
|
140
|
-
liveUnder: live,
|
|
141
|
-
candidates,
|
|
142
|
-
components: componentsOf(graph, dead, testOfDeadCode),
|
|
143
|
-
};
|
|
135
|
+
return { liveUnder: live, candidates };
|
|
144
136
|
}
|
|
145
137
|
|
|
146
138
|
/**
|
|
@@ -154,15 +146,17 @@ function reachable(graph: Graph, marked: readonly boolean[], mode: Mode): readon
|
|
|
154
146
|
const expanded = graph.symbols.map(() => false);
|
|
155
147
|
const queue: number[] = [];
|
|
156
148
|
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
160
|
-
|
|
149
|
+
// Reaching a file reaches its top level: the references written outside every
|
|
150
|
+
// declaration it holds. A reference that reads a file reads the module's namespace,
|
|
151
|
+
// which reaches what the module exports as well. An evaluation runs the top level
|
|
152
|
+
// and reads no export, and a root does not expand either: a file a runtime runs
|
|
153
|
+
// without reading its exports is a root by itself.
|
|
154
|
+
const enter = (at: number, expands: boolean): void => {
|
|
161
155
|
if (!reached[at]) {
|
|
162
156
|
reached[at] = true;
|
|
163
157
|
queue.push(at);
|
|
164
158
|
}
|
|
165
|
-
if (!
|
|
159
|
+
if (!expands || expanded[at] === true) {
|
|
166
160
|
return;
|
|
167
161
|
}
|
|
168
162
|
expanded[at] = true;
|
|
@@ -176,7 +170,7 @@ function reachable(graph: Graph, marked: readonly boolean[], mode: Mode): readon
|
|
|
176
170
|
if (!held && mode.production && edge.test) {
|
|
177
171
|
continue;
|
|
178
172
|
}
|
|
179
|
-
enter(edge.to,
|
|
173
|
+
enter(edge.to, !edge.evaluation);
|
|
180
174
|
}
|
|
181
175
|
}
|
|
182
176
|
};
|