@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/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. It is disposed once when the last
226
- * project has been visited, and the client is released after it, whether the visit
227
- * completed or threw.
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 projects = snapshot.getProjects().map((project) => visit(viewOf(project)));
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, and which
3
- * dead component each belongs to. Reference counting holds a declaration live when any
4
- * declaration references it, whatever that one's own liveness, and no root plays a part;
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 sweep's answer. */
58
- export interface SweepResult {
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, and the components
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): SweepResult {
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
- // A reference to a file is a reference to the module's namespace, which reaches what
158
- // the module exports as well as its top level. A root does not expand: a file a
159
- // runtime runs without reading its exports is a root by itself.
160
- const enter = (at: number, viaReference: boolean): void => {
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 (!viaReference || expanded[at] === true) {
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, true);
173
+ enter(edge.to, !edge.evaluation);
180
174
  }
181
175
  }
182
176
  };