@cplieger/deadset-ts 4.0.1 → 5.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 +4 -4
- package/dist/bin/component-mapper.js +5 -0
- package/dist/bin/mapper-connection.js +101 -0
- package/dist/bin/node-host.js +24 -2
- package/dist/src/analysis.js +301 -41
- package/dist/src/component-files.js +612 -0
- package/dist/src/component-layer.js +132 -0
- package/dist/src/config.js +9 -2
- package/dist/src/configuration-files.js +290 -0
- package/dist/src/conformance-record.js +3 -9
- package/dist/src/contextual-uses.js +240 -0
- package/dist/src/convention-rows.js +389 -0
- package/dist/src/conventions.js +565 -0
- package/dist/src/dependencies.js +36 -3
- package/dist/src/destructuring.js +6 -6
- package/dist/src/discover.js +10 -3
- package/dist/src/emit-map.js +72 -0
- package/dist/src/entry-point-gaps.js +81 -35
- package/dist/src/entry-points.js +50 -32
- package/dist/src/exempt-classes.js +6 -1
- package/dist/src/exempt.js +32 -20
- package/dist/src/findings/completion.js +46 -32
- package/dist/src/findings/emitters.js +22 -1
- package/dist/src/findings/interfaces.js +6 -2
- package/dist/src/findings/reads-and-writes.js +53 -9
- package/dist/src/findings/unused-declarations.js +47 -3
- package/dist/src/generated-file.js +24 -0
- package/dist/src/graph.js +13 -5
- package/dist/src/interface-satisfaction.js +2 -68
- package/dist/src/inventory.js +8 -3
- package/dist/src/kinds.js +6 -5
- package/dist/src/manifest.js +37 -11
- package/dist/src/matrix.js +21 -13
- package/dist/src/partial.js +3 -1
- package/dist/src/pnpm-workspace.js +120 -0
- package/dist/src/position.js +17 -2
- package/dist/src/print.js +2 -0
- package/dist/src/query.js +15 -0
- package/dist/src/references.js +404 -36
- package/dist/src/report.js +26 -6
- package/dist/src/reporters/annotations.js +10 -3
- package/dist/src/reporters/template.js +3 -0
- package/dist/src/resolve.js +37 -11
- package/dist/src/roots.js +37 -8
- package/dist/src/run.js +13 -3
- package/dist/src/schema.js +2 -0
- package/dist/src/session.js +141 -34
- package/dist/src/setup-failure.js +23 -0
- package/dist/src/source-files.js +4 -61
- package/dist/src/stores.js +3 -0
- package/dist/src/sweep.js +4 -2
- package/dist/src/template-field.js +38 -6
- package/dist/src/test-support.js +59 -0
- package/dist/src/type-errors.js +252 -0
- package/dist/src/type-query-alias.js +92 -0
- package/dist/src/value-flow.js +74 -0
- package/dist/src/verbs/analyze.js +24 -4
- package/dist/src/verbs/explain.js +4 -1
- package/dist/src/verbs/print-projects.js +17 -56
- package/dist/src/verbs/print-retained.js +7 -2
- package/dist/src/verbs/print-roots.js +7 -2
- package/dist/src/version-range.js +255 -0
- package/dist/src/version.js +1 -1
- package/dist/src/workspace-manifests.js +68 -0
- package/dist/src/workspace-programs.js +342 -0
- package/dist/src/workspace-resolution.js +307 -0
- package/dist/src/workspace-run.js +75 -0
- package/dist/src/workspace.js +358 -0
- package/jsr.json +1 -1
- package/package.json +3 -2
- package/src/analysis.ts +475 -72
- package/src/component-files.ts +718 -0
- package/src/component-layer.ts +160 -0
- package/src/config.ts +11 -2
- package/src/configuration-files.ts +370 -0
- package/src/conformance-record.ts +3 -10
- package/src/contextual-uses.ts +354 -0
- package/src/convention-rows.ts +448 -0
- package/src/conventions.ts +788 -0
- package/src/dependencies.ts +49 -2
- package/src/destructuring.ts +16 -6
- package/src/discover.ts +10 -6
- package/src/emit-map.ts +93 -0
- package/src/entry-point-gaps.ts +92 -38
- package/src/entry-points.ts +79 -36
- package/src/exempt-classes.ts +6 -1
- package/src/exempt.ts +69 -20
- package/src/file-facts.ts +2 -0
- package/src/findings/completion.ts +55 -36
- package/src/findings/emitters.ts +32 -1
- package/src/findings/interfaces.ts +9 -2
- package/src/findings/reads-and-writes.ts +70 -9
- package/src/findings/unused-declarations.ts +60 -3
- package/src/generated-file.ts +27 -0
- package/src/graph.ts +15 -4
- package/src/host.ts +23 -0
- package/src/index.ts +1 -1
- package/src/interface-satisfaction.ts +1 -92
- package/src/inventory.ts +17 -3
- package/src/kinds.ts +7 -5
- package/src/manifest.ts +47 -14
- package/src/matrix.ts +43 -15
- package/src/partial.ts +6 -1
- package/src/pnpm-workspace.ts +135 -0
- package/src/position.ts +23 -2
- package/src/print.ts +2 -0
- package/src/query.ts +26 -0
- package/src/references.ts +472 -40
- package/src/report.ts +56 -6
- package/src/reporters/annotations.ts +12 -3
- package/src/reporters/template.ts +3 -0
- package/src/resolve.ts +65 -11
- package/src/roots.ts +70 -9
- package/src/run.ts +15 -5
- package/src/schema.ts +2 -0
- package/src/session.ts +218 -37
- package/src/setup-failure.ts +39 -0
- package/src/source-files.ts +4 -66
- package/src/stores.ts +9 -0
- package/src/sweep.ts +9 -2
- package/src/template-field.ts +42 -7
- package/src/test-support.ts +77 -0
- package/src/type-errors.ts +340 -0
- package/src/type-query-alias.ts +133 -0
- package/src/value-flow.ts +104 -0
- package/src/verbs/analyze.ts +38 -4
- package/src/verbs/explain.ts +4 -1
- package/src/verbs/print-projects.ts +17 -69
- package/src/verbs/print-retained.ts +7 -2
- package/src/verbs/print-roots.ts +7 -2
- package/src/verbs/verb.ts +6 -3
- package/src/version-range.ts +309 -0
- package/src/version.ts +1 -1
- package/src/workspace-manifests.ts +100 -0
- package/src/workspace-programs.ts +486 -0
- package/src/workspace-resolution.ts +393 -0
- package/src/workspace-run.ts +148 -0
- package/src/workspace.ts +463 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
deadset-ts finds dead code in TypeScript projects, down to class members, type members and dead stores inside functions, and writes a report your CI can fail on.
|
|
6
6
|
|
|
7
|
-
It reads your `tsconfig.json` projects, `allowJs` JavaScript included, with the type information of TypeScript 7.1.0-dev.20261003.1, its one dependency. Your project keeps its own TypeScript version
|
|
7
|
+
It reads your `tsconfig.json` projects, `allowJs` JavaScript and Vue, Svelte and Astro scripts included, with the type information of TypeScript 7.1.0-dev.20261003.1, its one dependency. Your project keeps its own TypeScript version. A type error under that version skips the function or statement that holds it. deadset-ts reports and never edits your code. It is pre-release, tested only on Linux, needs Node.js 24 or later and is licensed under GPL-3.0-or-later.
|
|
8
8
|
|
|
9
9
|
## Why use it
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ deadset-ts is built for a CI gate on dead code. Each finding names code to delet
|
|
|
17
17
|
- The same tree gives the same report, and a baseline keyed on code and symbol survives moved lines.
|
|
18
18
|
- It writes text, JSON, GitHub annotations, SARIF 2.1.0 or a custom template.
|
|
19
19
|
|
|
20
|
-
Consider [Knip](https://knip.dev) if you want issues fixed with `--fix`, plugins for over 100 tools, or
|
|
20
|
+
Consider [Knip](https://knip.dev) if you want issues fixed with `--fix`, plugins for over 100 tools, or MDX files checked.
|
|
21
21
|
|
|
22
22
|
## Install
|
|
23
23
|
|
|
@@ -90,7 +90,7 @@ A TypeScript caller that imports the source sets `allowImportingTsExtensions`, b
|
|
|
90
90
|
|
|
91
91
|
## Related projects
|
|
92
92
|
|
|
93
|
-
deadset-ts implements the [deadset Contract](https://github.com/cplieger/deadset-spec), which fixes the issue codes, the report schema and the exit codes. It passes the Contract's conformance corpus except one reflective-lookup fixture, the gap [`conformance.json`](conformance.json) declares.
|
|
93
|
+
deadset-ts implements the [deadset Contract](https://github.com/cplieger/deadset-spec), which fixes the issue codes, the report schema and the exit codes. It passes every fixture of the Contract's conformance corpus except one reflective-lookup fixture, the gap [`conformance.json`](conformance.json) declares.
|
|
94
94
|
|
|
95
95
|
- [deadset-go](https://github.com/cplieger/deadset-go) is the same analysis for Go modules.
|
|
96
96
|
- [deadset](https://github.com/cplieger/deadset) runs both analyzers as one command and merges their reports, resolving the edges between Go and TypeScript code.
|
|
@@ -105,7 +105,7 @@ deadset-ts implements the [deadset Contract](https://github.com/cplieger/deadset
|
|
|
105
105
|
|
|
106
106
|
## Contributing
|
|
107
107
|
|
|
108
|
-
See [CONTRIBUTING.md](
|
|
108
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
109
109
|
|
|
110
110
|
## Disclaimer
|
|
111
111
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content mapper the compiler runs for component files: JSON-RPC 2.0 messages, each
|
|
3
|
+
* framed by a `Content-Length` header, over the process's standard streams. It answers
|
|
4
|
+
* `transform` with {@link componentModule} and keeps no state between requests.
|
|
5
|
+
* The protocol is the compiler's own:
|
|
6
|
+
* https://github.com/microsoft/TypeScript/blob/f9f8d01292562242b6e7c7142e46ed7e470926f9/tsc/internal/contentmapper/hostimpl.go
|
|
7
|
+
*/
|
|
8
|
+
import { componentModule } from "../src/component-files.js";
|
|
9
|
+
/** The JSON-RPC code of a method this mapper does not serve. */
|
|
10
|
+
const METHOD_NOT_FOUND = -32601;
|
|
11
|
+
/** The JSON-RPC code of a request whose parameters are not the protocol's. */
|
|
12
|
+
const INVALID_PARAMS = -32602;
|
|
13
|
+
const HEADER_END = new Uint8Array([0x0d, 0x0a, 0x0d, 0x0a]);
|
|
14
|
+
/** The offset of `needle` in `bytes` at or after `from`, or -1. */
|
|
15
|
+
function indexOf(bytes, needle, from) {
|
|
16
|
+
outer: for (let at = from; at + needle.length <= bytes.length; at += 1) {
|
|
17
|
+
for (let index = 0; index < needle.length; index += 1) {
|
|
18
|
+
if (bytes[at + index] !== needle[index]) {
|
|
19
|
+
continue outer;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return at;
|
|
23
|
+
}
|
|
24
|
+
return -1;
|
|
25
|
+
}
|
|
26
|
+
/** The answer to one message, or undefined for a notification, which takes none. */
|
|
27
|
+
function answer(message) {
|
|
28
|
+
if (message.id === undefined) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const reply = (result) => ({ jsonrpc: "2.0", id: message.id, result });
|
|
32
|
+
const fail = (code, text) => ({
|
|
33
|
+
jsonrpc: "2.0",
|
|
34
|
+
id: message.id,
|
|
35
|
+
error: { code, message: text },
|
|
36
|
+
});
|
|
37
|
+
switch (message.method) {
|
|
38
|
+
case "initialize":
|
|
39
|
+
return reply({ positionEncoding: "utf-16", diagnosticSource: "deadset-ts" });
|
|
40
|
+
case "openProject":
|
|
41
|
+
return reply({});
|
|
42
|
+
case "closeProject":
|
|
43
|
+
return reply(null);
|
|
44
|
+
case "transform": {
|
|
45
|
+
const content = typeof message.params === "object" && message.params !== null
|
|
46
|
+
? message.params.content
|
|
47
|
+
: undefined;
|
|
48
|
+
if (typeof content !== "string") {
|
|
49
|
+
return fail(INVALID_PARAMS, "transform: params.content is not a string");
|
|
50
|
+
}
|
|
51
|
+
const module = componentModule(content);
|
|
52
|
+
return reply({ text: module.text, extension: module.extension, mappings: module.mappings });
|
|
53
|
+
}
|
|
54
|
+
default:
|
|
55
|
+
return fail(METHOD_NOT_FOUND, `no method ${JSON.stringify(message.method)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A connection over one byte stream. A message whose body is not JSON is answered with
|
|
60
|
+
* nothing, because it carries no id to answer to.
|
|
61
|
+
*/
|
|
62
|
+
export function mapperConnection(write) {
|
|
63
|
+
const encoder = new TextEncoder();
|
|
64
|
+
const decoder = new TextDecoder();
|
|
65
|
+
let pending = new Uint8Array(0);
|
|
66
|
+
return {
|
|
67
|
+
receive(chunk) {
|
|
68
|
+
const joined = new Uint8Array(pending.length + chunk.length);
|
|
69
|
+
joined.set(pending);
|
|
70
|
+
joined.set(chunk, pending.length);
|
|
71
|
+
pending = joined;
|
|
72
|
+
for (;;) {
|
|
73
|
+
const headerEnd = indexOf(pending, HEADER_END, 0);
|
|
74
|
+
if (headerEnd < 0) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const header = decoder.decode(pending.subarray(0, headerEnd));
|
|
78
|
+
const length = Number(/content-length:\s*(\d+)/iu.exec(header)?.[1] ?? "0");
|
|
79
|
+
const bodyStart = headerEnd + HEADER_END.length;
|
|
80
|
+
if (pending.length < bodyStart + length) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const body = decoder.decode(pending.subarray(bodyStart, bodyStart + length));
|
|
84
|
+
pending = pending.slice(bodyStart + length);
|
|
85
|
+
let message;
|
|
86
|
+
try {
|
|
87
|
+
message = JSON.parse(body);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const reply = answer(message);
|
|
93
|
+
if (reply !== undefined) {
|
|
94
|
+
const bytes = encoder.encode(JSON.stringify(reply));
|
|
95
|
+
write(encoder.encode(`Content-Length: ${String(bytes.length)}\r\n\r\n`));
|
|
96
|
+
write(bytes);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
package/dist/bin/node-host.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import { closeSync, fchmodSync, fsyncSync, openSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeSync, } from "node:fs";
|
|
3
|
-
import {
|
|
2
|
+
import { closeSync, fchmodSync, fsyncSync, mkdtempSync, openSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeSync, } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { basename, dirname, extname, join } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
/** The name the manifest of this package declares. */
|
|
6
7
|
const PACKAGE_NAME = "@cplieger/deadset-ts";
|
|
@@ -75,6 +76,24 @@ function writeAtomically(path, pieces) {
|
|
|
75
76
|
throw error;
|
|
76
77
|
}
|
|
77
78
|
}
|
|
79
|
+
/** A new directory under the platform's temporary directory. */
|
|
80
|
+
function temporaryDirectory() {
|
|
81
|
+
const path = mkdtempSync(join(tmpdir(), "deadset-ts-mapper-"));
|
|
82
|
+
return {
|
|
83
|
+
path,
|
|
84
|
+
remove: () => {
|
|
85
|
+
rmSync(path, { recursive: true, force: true });
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The mapper beside this file, in the same form: the emitted tree runs the emitted
|
|
91
|
+
* mapper and a checkout runs the source through the runtime's own type stripping.
|
|
92
|
+
*/
|
|
93
|
+
function componentMapperCommand() {
|
|
94
|
+
const here = fileURLToPath(import.meta.url);
|
|
95
|
+
return [process.execPath, join(dirname(here), `component-mapper${extname(here)}`)];
|
|
96
|
+
}
|
|
78
97
|
/**
|
|
79
98
|
* The filesystem of the platform the command runs on, and the version of the
|
|
80
99
|
* package it was installed from.
|
|
@@ -98,10 +117,13 @@ export function nodeHost() {
|
|
|
98
117
|
}
|
|
99
118
|
return stat.isDirectory() ? "directory" : "file";
|
|
100
119
|
},
|
|
120
|
+
realPath: (path) => realpathSync(path),
|
|
101
121
|
analyzerVersion: () => {
|
|
102
122
|
found ??= readVersion();
|
|
103
123
|
return found;
|
|
104
124
|
},
|
|
105
125
|
writeDocument: writeAtomically,
|
|
126
|
+
temporaryDirectory,
|
|
127
|
+
componentMapperCommand,
|
|
106
128
|
};
|
|
107
129
|
}
|