@loose-ends/core 0.0.0-stage → 1.1.1
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 +15 -2
- package/dist/check.d.ts +65 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +102 -0
- package/dist/check.js.map +1 -0
- package/dist/cleanup.d.ts +57 -0
- package/dist/cleanup.d.ts.map +1 -0
- package/dist/cleanup.js +226 -0
- package/dist/cleanup.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +279 -0
- package/dist/config.js.map +1 -0
- package/dist/coverage.d.ts +17 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +110 -0
- package/dist/coverage.js.map +1 -0
- package/dist/dependencies.d.ts +17 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +323 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/directives.d.ts +25 -0
- package/dist/directives.d.ts.map +1 -0
- package/dist/directives.js +107 -0
- package/dist/directives.js.map +1 -0
- package/dist/discover.d.ts +15 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +39 -0
- package/dist/discover.js.map +1 -0
- package/dist/explain.d.ts +43 -0
- package/dist/explain.d.ts.map +1 -0
- package/dist/explain.js +108 -0
- package/dist/explain.js.map +1 -0
- package/dist/findings.d.ts +80 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +258 -0
- package/dist/findings.js.map +1 -0
- package/dist/frameworks.d.ts +41 -0
- package/dist/frameworks.d.ts.map +1 -0
- package/dist/frameworks.js +436 -0
- package/dist/frameworks.js.map +1 -0
- package/dist/git.d.ts +36 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +194 -0
- package/dist/git.js.map +1 -0
- package/dist/graph.d.ts +79 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +319 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/java/link.d.ts +38 -0
- package/dist/java/link.d.ts.map +1 -0
- package/dist/java/link.js +166 -0
- package/dist/java/link.js.map +1 -0
- package/dist/java/packages.d.ts +8 -0
- package/dist/java/packages.d.ts.map +1 -0
- package/dist/java/packages.js +150 -0
- package/dist/java/packages.js.map +1 -0
- package/dist/java/parse.d.ts +46 -0
- package/dist/java/parse.d.ts.map +1 -0
- package/dist/java/parse.js +366 -0
- package/dist/java/parse.js.map +1 -0
- package/dist/java/project.d.ts +27 -0
- package/dist/java/project.d.ts.map +1 -0
- package/dist/java/project.js +119 -0
- package/dist/java/project.js.map +1 -0
- package/dist/java/roots.d.ts +4 -0
- package/dist/java/roots.d.ts.map +1 -0
- package/dist/java/roots.js +240 -0
- package/dist/java/roots.js.map +1 -0
- package/dist/liveness.d.ts +54 -0
- package/dist/liveness.d.ts.map +1 -0
- package/dist/liveness.js +135 -0
- package/dist/liveness.js.map +1 -0
- package/dist/parse.d.ts +166 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +473 -0
- package/dist/parse.js.map +1 -0
- package/dist/paths.d.ts +16 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +33 -0
- package/dist/paths.js.map +1 -0
- package/dist/python/link.d.ts +52 -0
- package/dist/python/link.d.ts.map +1 -0
- package/dist/python/link.js +339 -0
- package/dist/python/link.js.map +1 -0
- package/dist/python/packages.d.ts +12 -0
- package/dist/python/packages.d.ts.map +1 -0
- package/dist/python/packages.js +310 -0
- package/dist/python/packages.js.map +1 -0
- package/dist/python/parse.d.ts +13 -0
- package/dist/python/parse.d.ts.map +1 -0
- package/dist/python/parse.js +577 -0
- package/dist/python/parse.js.map +1 -0
- package/dist/python/project.d.ts +36 -0
- package/dist/python/project.d.ts.map +1 -0
- package/dist/python/project.js +225 -0
- package/dist/python/project.js.map +1 -0
- package/dist/python/resolve.d.ts +34 -0
- package/dist/python/resolve.d.ts.map +1 -0
- package/dist/python/resolve.js +152 -0
- package/dist/python/resolve.js.map +1 -0
- package/dist/python/roots.d.ts +4 -0
- package/dist/python/roots.d.ts.map +1 -0
- package/dist/python/roots.js +307 -0
- package/dist/python/roots.js.map +1 -0
- package/dist/python/tokenize.d.ts +44 -0
- package/dist/python/tokenize.d.ts.map +1 -0
- package/dist/python/tokenize.js +250 -0
- package/dist/python/tokenize.js.map +1 -0
- package/dist/python/toml.d.ts +8 -0
- package/dist/python/toml.d.ts.map +1 -0
- package/dist/python/toml.js +193 -0
- package/dist/python/toml.js.map +1 -0
- package/dist/report/common.d.ts +17 -0
- package/dist/report/common.d.ts.map +1 -0
- package/dist/report/common.js +55 -0
- package/dist/report/common.js.map +1 -0
- package/dist/report/json.d.ts +46 -0
- package/dist/report/json.d.ts.map +1 -0
- package/dist/report/json.js +21 -0
- package/dist/report/json.js.map +1 -0
- package/dist/report/markdown.d.ts +11 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +62 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/rules.d.ts +7 -0
- package/dist/report/rules.d.ts.map +1 -0
- package/dist/report/rules.js +48 -0
- package/dist/report/rules.js.map +1 -0
- package/dist/report/sarif.d.ts +68 -0
- package/dist/report/sarif.d.ts.map +1 -0
- package/dist/report/sarif.js +55 -0
- package/dist/report/sarif.js.map +1 -0
- package/dist/report/text.d.ts +10 -0
- package/dist/report/text.d.ts.map +1 -0
- package/dist/report/text.js +75 -0
- package/dist/report/text.js.map +1 -0
- package/dist/resolve.d.ts +58 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +285 -0
- package/dist/resolve.js.map +1 -0
- package/dist/roots.d.ts +45 -0
- package/dist/roots.d.ts.map +1 -0
- package/dist/roots.js +163 -0
- package/dist/roots.js.map +1 -0
- package/dist/superseded.d.ts +25 -0
- package/dist/superseded.d.ts.map +1 -0
- package/dist/superseded.js +138 -0
- package/dist/superseded.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace.d.ts +43 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +159 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +40 -4
package/README.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @loose-ends/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Liveness Graph engine behind [Loose Ends](https://github.com/sid732/loose-ends).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { check, scan, analyze, explain, loadConfig, formatReport } from "@loose-ends/core";
|
|
7
|
+
|
|
8
|
+
const result = check({ root: process.cwd(), base: "origin/main" });
|
|
9
|
+
console.log(formatReport(result, "text"));
|
|
10
|
+
process.exitCode = result.passed ? 0 : 1;
|
|
11
|
+
|
|
12
|
+
const analysis = analyze(loadConfig(process.cwd()));
|
|
13
|
+
console.log(explain(analysis, "src/lib/format.ts#formatUser"));
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
See [docs/architecture.md](https://github.com/sid732/loose-ends/blob/main/docs/architecture.md).
|
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ChangedFile } from "./git.js";
|
|
2
|
+
import { type Finding } from "./findings.js";
|
|
3
|
+
import { type Analysis, type AnalyzeOptions, type LivenessSummary } from "./liveness.js";
|
|
4
|
+
import type { FindingKind, LooseEndsConfig } from "./types.js";
|
|
5
|
+
export interface CheckOptions {
|
|
6
|
+
/** Project root (working tree). */
|
|
7
|
+
root: string;
|
|
8
|
+
/** Base revision. Defaults to the merge base with origin/HEAD, main, or master. */
|
|
9
|
+
base?: string;
|
|
10
|
+
/** Head revision. Defaults to the working tree, including uncommitted changes. */
|
|
11
|
+
head?: string;
|
|
12
|
+
config?: Partial<LooseEndsConfig>;
|
|
13
|
+
/** Extra hooks applied to both analyses. */
|
|
14
|
+
analyze?: AnalyzeOptions;
|
|
15
|
+
/** Post-process findings, e.g. to add superseded or dependency findings. */
|
|
16
|
+
extend?: (ctx: CheckContext) => Finding[];
|
|
17
|
+
}
|
|
18
|
+
export interface CheckContext {
|
|
19
|
+
config: LooseEndsConfig;
|
|
20
|
+
base: Analysis;
|
|
21
|
+
head: Analysis;
|
|
22
|
+
changed: ChangedFile[];
|
|
23
|
+
findings: Finding[];
|
|
24
|
+
}
|
|
25
|
+
export interface RevisionInfo {
|
|
26
|
+
ref: string;
|
|
27
|
+
commit?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface CheckResult {
|
|
30
|
+
mode: "check" | "scan";
|
|
31
|
+
config: LooseEndsConfig;
|
|
32
|
+
base?: RevisionInfo;
|
|
33
|
+
head: RevisionInfo;
|
|
34
|
+
changed: ChangedFile[];
|
|
35
|
+
findings: Finding[];
|
|
36
|
+
/** Findings that count toward failure (unsuppressed and in `failOn`). */
|
|
37
|
+
failing: Finding[];
|
|
38
|
+
summary: {
|
|
39
|
+
before?: LivenessSummary;
|
|
40
|
+
after: LivenessSummary;
|
|
41
|
+
byKind: Partial<Record<FindingKind, number>>;
|
|
42
|
+
suppressed: number;
|
|
43
|
+
};
|
|
44
|
+
passed: boolean;
|
|
45
|
+
/** Present when the caller asked to keep analyses for further inspection. */
|
|
46
|
+
analyses?: {
|
|
47
|
+
base?: Analysis;
|
|
48
|
+
head: Analysis;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Compare a change against its base and report new loose ends. */
|
|
52
|
+
export declare function check(options: CheckOptions & {
|
|
53
|
+
keepAnalyses?: boolean;
|
|
54
|
+
}): CheckResult;
|
|
55
|
+
export interface ScanOptions {
|
|
56
|
+
root: string;
|
|
57
|
+
config?: Partial<LooseEndsConfig>;
|
|
58
|
+
analyze?: AnalyzeOptions;
|
|
59
|
+
extend?: (analysis: Analysis, findings: Finding[]) => Finding[];
|
|
60
|
+
}
|
|
61
|
+
/** Whole-project report of unreachable code, independent of any change. */
|
|
62
|
+
export declare function scan(options: ScanOptions & {
|
|
63
|
+
keepAnalyses?: boolean;
|
|
64
|
+
}): CheckResult;
|
|
65
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,UAAU,CAAC;AAKtD,OAAO,EAA+D,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAE1G,OAAO,EAAsB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7G,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,yEAAyE;IACzE,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,eAAe,CAAC;QACzB,KAAK,EAAE,eAAe,CAAC;QACvB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,MAAM,EAAE,OAAO,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;CAChD;AAED,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,WAAW,CA6CrF;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;CACjE;AAED,2EAA2E;AAC3E,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,WAAW,CAiBnF"}
|
package/dist/check.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { changedFiles, defaultBase, isGitRepo, mergeBase, revParse, snapshot } from "./git.js";
|
|
2
|
+
import { loadConfig } from "./config.js";
|
|
3
|
+
import { annotateCoverage, loadCoverage } from "./coverage.js";
|
|
4
|
+
import { dependencyFindings, scanDependencyFindings } from "./dependencies.js";
|
|
5
|
+
import { applySuppressions, compareAnalyses, renameMap, scanFindings } from "./findings.js";
|
|
6
|
+
import { detectSuperseded } from "./superseded.js";
|
|
7
|
+
import { analyze, summarize } from "./liveness.js";
|
|
8
|
+
/** Compare a change against its base and report new loose ends. */
|
|
9
|
+
export function check(options) {
|
|
10
|
+
const config = loadConfig(options.root, options.config);
|
|
11
|
+
if (!isGitRepo(config.root))
|
|
12
|
+
throw new Error(`${config.root} is not inside a git repository; use scan for a whole-project report`);
|
|
13
|
+
const baseRef = options.base ?? defaultBase(config.root);
|
|
14
|
+
if (!baseRef)
|
|
15
|
+
throw new Error("could not find a base branch (tried origin/HEAD, main, master); pass --base");
|
|
16
|
+
const headRef = options.head;
|
|
17
|
+
const headCommit = headRef ? revParse(config.root, headRef) : revParse(config.root, "HEAD");
|
|
18
|
+
if (headRef && !headCommit)
|
|
19
|
+
throw new Error(`unknown head revision "${headRef}"`);
|
|
20
|
+
const baseCommit = mergeBase(config.root, baseRef, headCommit ?? "HEAD");
|
|
21
|
+
const snapshots = [];
|
|
22
|
+
try {
|
|
23
|
+
const baseSnap = snapshot(config.root, baseCommit);
|
|
24
|
+
snapshots.push(baseSnap);
|
|
25
|
+
let headRoot = config.root;
|
|
26
|
+
if (headRef) {
|
|
27
|
+
const headSnap = snapshot(config.root, headRef);
|
|
28
|
+
snapshots.push(headSnap);
|
|
29
|
+
headRoot = headSnap.root;
|
|
30
|
+
}
|
|
31
|
+
const base = analyze({ ...config, root: baseSnap.root }, options.analyze);
|
|
32
|
+
const head = analyze({ ...config, root: headRoot }, options.analyze);
|
|
33
|
+
const changed = changedFiles(config.root, baseCommit, headRef);
|
|
34
|
+
let findings = compareAnalyses(base, head, { changed });
|
|
35
|
+
findings = detectSuperseded(base, head, changed, findings, renameMap(changed));
|
|
36
|
+
findings = [...findings, ...dependencyFindings(base, head)];
|
|
37
|
+
if (options.extend)
|
|
38
|
+
findings = [...findings, ...options.extend({ config, base, head, changed, findings })];
|
|
39
|
+
const { invalid } = applySuppressions(head, findings);
|
|
40
|
+
findings = [...findings, ...invalid];
|
|
41
|
+
if (config.coverage)
|
|
42
|
+
annotateCoverage(findings, loadCoverage(config.root, config.coverage), config.coverage);
|
|
43
|
+
return finish({
|
|
44
|
+
mode: "check",
|
|
45
|
+
config,
|
|
46
|
+
base: { ref: baseRef, commit: baseCommit },
|
|
47
|
+
head: { ref: headRef ?? "working tree", commit: headCommit },
|
|
48
|
+
changed,
|
|
49
|
+
findings,
|
|
50
|
+
before: summarize(base),
|
|
51
|
+
after: summarize(head),
|
|
52
|
+
analyses: options.keepAnalyses ? { base, head } : undefined,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
for (const snap of snapshots)
|
|
57
|
+
snap.dispose();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Whole-project report of unreachable code, independent of any change. */
|
|
61
|
+
export function scan(options) {
|
|
62
|
+
const config = loadConfig(options.root, options.config);
|
|
63
|
+
const head = analyze(config, options.analyze);
|
|
64
|
+
let findings = [...scanFindings(head), ...scanDependencyFindings(head)];
|
|
65
|
+
if (options.extend)
|
|
66
|
+
findings = [...findings, ...options.extend(head, findings)];
|
|
67
|
+
const { invalid } = applySuppressions(head, findings);
|
|
68
|
+
findings = [...findings, ...invalid];
|
|
69
|
+
if (config.coverage)
|
|
70
|
+
annotateCoverage(findings, loadCoverage(config.root, config.coverage), config.coverage);
|
|
71
|
+
return finish({
|
|
72
|
+
mode: "scan",
|
|
73
|
+
config,
|
|
74
|
+
head: { ref: "working tree", commit: isGitRepo(config.root) ? revParse(config.root, "HEAD") : undefined },
|
|
75
|
+
changed: [],
|
|
76
|
+
findings,
|
|
77
|
+
after: summarize(head),
|
|
78
|
+
analyses: options.keepAnalyses ? { head } : undefined,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function finish(input) {
|
|
82
|
+
const order = { error: 0, warning: 1, info: 2 };
|
|
83
|
+
const findings = input.findings.sort((a, b) => order[a.severity] - order[b.severity] || (a.file ?? "").localeCompare(b.file ?? "") || (a.line ?? 0) - (b.line ?? 0) || a.kind.localeCompare(b.kind));
|
|
84
|
+
const failing = findings.filter((f) => !f.suppressed && input.config.failOn.includes(f.kind));
|
|
85
|
+
const byKind = {};
|
|
86
|
+
for (const f of findings)
|
|
87
|
+
if (!f.suppressed)
|
|
88
|
+
byKind[f.kind] = (byKind[f.kind] ?? 0) + 1;
|
|
89
|
+
return {
|
|
90
|
+
mode: input.mode,
|
|
91
|
+
config: input.config,
|
|
92
|
+
base: input.base,
|
|
93
|
+
head: input.head,
|
|
94
|
+
changed: input.changed,
|
|
95
|
+
findings,
|
|
96
|
+
failing,
|
|
97
|
+
summary: { before: input.before, after: input.after, byKind, suppressed: findings.filter((f) => f.suppressed).length },
|
|
98
|
+
passed: failing.length === 0,
|
|
99
|
+
analyses: input.analyses,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Finding } from "./findings.js";
|
|
2
|
+
import type { Analysis } from "./liveness.js";
|
|
3
|
+
export type CleanupAction = {
|
|
4
|
+
type: "delete-file";
|
|
5
|
+
path: string;
|
|
6
|
+
finding: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: "remove-declaration";
|
|
9
|
+
path: string;
|
|
10
|
+
symbol: string;
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
line: number;
|
|
14
|
+
finding: string;
|
|
15
|
+
};
|
|
16
|
+
export interface CleanupPlan {
|
|
17
|
+
actions: CleanupAction[];
|
|
18
|
+
skipped: Array<{
|
|
19
|
+
target: string;
|
|
20
|
+
reason: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Turn findings into deletions. Only unsuppressed, deterministic findings are
|
|
25
|
+
* used. Anything that would leave a dangling import or a partial statement is
|
|
26
|
+
* skipped with a reason, not guessed at.
|
|
27
|
+
*/
|
|
28
|
+
export declare function planCleanup(analysis: Analysis, findings: Finding[]): CleanupPlan;
|
|
29
|
+
/** Apply a plan to a directory. Returns the files that were touched. */
|
|
30
|
+
export declare function applyCleanup(root: string, plan: CleanupPlan): string[];
|
|
31
|
+
export interface CheckRun {
|
|
32
|
+
command: string;
|
|
33
|
+
exitCode: number;
|
|
34
|
+
durationMs: number;
|
|
35
|
+
/** Last lines of combined output. */
|
|
36
|
+
output: string;
|
|
37
|
+
}
|
|
38
|
+
export interface Verification {
|
|
39
|
+
passed: boolean;
|
|
40
|
+
checks: CheckRun[];
|
|
41
|
+
/** Unified diff of the cleanup, relative to the project root. */
|
|
42
|
+
patch: string;
|
|
43
|
+
touched: string[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Apply the plan to a scratch copy of the project, run the configured checks
|
|
47
|
+
* there, and return a patch. The working tree is never modified.
|
|
48
|
+
*/
|
|
49
|
+
export declare function verifyCleanup(root: string, plan: CleanupPlan, checks: string[], options?: {
|
|
50
|
+
timeoutMs?: number;
|
|
51
|
+
}): Verification;
|
|
52
|
+
/** Produce the cleanup patch without running checks. */
|
|
53
|
+
export declare function cleanupPatch(root: string, plan: CleanupPlan): {
|
|
54
|
+
patch: string;
|
|
55
|
+
touched: string[];
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../src/cleanup.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5H,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAID;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,WAAW,CA6ChF;AAoBD,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,CAiCtE;AAkCD,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAoBnI;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAGlG"}
|
package/dist/cleanup.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { cpSync, existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { basename, dirname, join } from "node:path";
|
|
5
|
+
import { fileId, symbolId } from "./graph.js";
|
|
6
|
+
const REMOVABLE = new Set(["orphaned-addition", "newly-orphaned", "superseded", "orphaned"]);
|
|
7
|
+
/**
|
|
8
|
+
* Turn findings into deletions. Only unsuppressed, deterministic findings are
|
|
9
|
+
* used. Anything that would leave a dangling import or a partial statement is
|
|
10
|
+
* skipped with a reason, not guessed at.
|
|
11
|
+
*/
|
|
12
|
+
export function planCleanup(analysis, findings) {
|
|
13
|
+
const plan = { actions: [], skipped: [] };
|
|
14
|
+
const candidates = findings.filter((f) => REMOVABLE.has(f.kind) && !f.suppressed && f.file);
|
|
15
|
+
const deletedFiles = new Set(candidates.filter((f) => !f.symbol).map((f) => f.file));
|
|
16
|
+
for (const f of candidates) {
|
|
17
|
+
const file = f.file;
|
|
18
|
+
if (!analysis.graph.modules.has(file)) {
|
|
19
|
+
plan.skipped.push({ target: f.target, reason: "file is not part of the analyzed tree" });
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (!f.symbol) {
|
|
23
|
+
const importers = importersOf(analysis, file, undefined).filter((p) => !deletedFiles.has(p));
|
|
24
|
+
if (importers.length) {
|
|
25
|
+
plan.skipped.push({ target: f.target, reason: `still imported (without being used) by ${importers.join(", ")}` });
|
|
26
|
+
deletedFiles.delete(file);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
plan.actions.push({ type: "delete-file", path: file, finding: f.id });
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (deletedFiles.has(file))
|
|
33
|
+
continue;
|
|
34
|
+
const node = analysis.graph.nodes.get(symbolId(file, f.symbol));
|
|
35
|
+
const decl = node?.declaration;
|
|
36
|
+
if (!decl) {
|
|
37
|
+
plan.skipped.push({ target: f.target, reason: "re-export alias; edit the export list by hand" });
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (decl.statementSize > 1) {
|
|
41
|
+
plan.skipped.push({ target: f.target, reason: "declared together with other names in one statement" });
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const info = analysis.graph.modules.get(file);
|
|
45
|
+
if (info.localExports.some((e) => e.local === decl.name)) {
|
|
46
|
+
plan.skipped.push({ target: f.target, reason: "also listed in an `export { }` clause" });
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const importers = decl.exportedAs.flatMap((name) => importersOf(analysis, file, name)).filter((p) => !deletedFiles.has(p));
|
|
50
|
+
if (importers.length) {
|
|
51
|
+
plan.skipped.push({ target: f.target, reason: `still imported (without being used) by ${[...new Set(importers)].join(", ")}` });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
plan.actions.push({ type: "remove-declaration", path: file, symbol: decl.name, start: decl.start, end: decl.end, line: decl.line, finding: f.id });
|
|
55
|
+
}
|
|
56
|
+
return plan;
|
|
57
|
+
}
|
|
58
|
+
/** Files with an import of `file` (or of `name` from it). */
|
|
59
|
+
function importersOf(analysis, file, name) {
|
|
60
|
+
const out = new Set();
|
|
61
|
+
for (const edge of analysis.graph.in(fileId(file))) {
|
|
62
|
+
if (edge.kind === "contains")
|
|
63
|
+
continue;
|
|
64
|
+
const from = analysis.graph.nodes.get(edge.from)?.file;
|
|
65
|
+
if (!from || from === file)
|
|
66
|
+
continue;
|
|
67
|
+
if (name === undefined) {
|
|
68
|
+
out.add(from);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const info = analysis.graph.modules.get(from);
|
|
72
|
+
const imports = info?.imports.some((r) => r.bindings.some((b) => b.imported === name)) ?? false;
|
|
73
|
+
if (imports)
|
|
74
|
+
out.add(from);
|
|
75
|
+
}
|
|
76
|
+
return [...out].sort();
|
|
77
|
+
}
|
|
78
|
+
/** Apply a plan to a directory. Returns the files that were touched. */
|
|
79
|
+
export function applyCleanup(root, plan) {
|
|
80
|
+
const touched = new Set();
|
|
81
|
+
const removals = new Map();
|
|
82
|
+
for (const action of plan.actions) {
|
|
83
|
+
if (action.type === "delete-file") {
|
|
84
|
+
const abs = join(root, action.path);
|
|
85
|
+
if (existsSync(abs))
|
|
86
|
+
unlinkSync(abs);
|
|
87
|
+
touched.add(action.path);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const list = removals.get(action.path) ?? [];
|
|
91
|
+
list.push({ start: action.start, end: action.end });
|
|
92
|
+
removals.set(action.path, list);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const [path, ranges] of removals) {
|
|
96
|
+
const abs = join(root, path);
|
|
97
|
+
if (!existsSync(abs))
|
|
98
|
+
continue;
|
|
99
|
+
let text = readFileSync(abs, "utf8");
|
|
100
|
+
for (const { start, end } of ranges.sort((a, b) => b.start - a.start)) {
|
|
101
|
+
const lineStart = removeLeadingComments(text, start, path.endsWith(".py"));
|
|
102
|
+
let stop = end;
|
|
103
|
+
while (stop < text.length && (text[stop] === " " || text[stop] === "\t"))
|
|
104
|
+
stop++;
|
|
105
|
+
if (text[stop] === "\r")
|
|
106
|
+
stop++;
|
|
107
|
+
if (text[stop] === "\n")
|
|
108
|
+
stop++;
|
|
109
|
+
if (text[stop] === "\n" && (lineStart === 0 || text[lineStart - 1] === "\n") && (lineStart < 2 || text[lineStart - 2] === "\n"))
|
|
110
|
+
stop++;
|
|
111
|
+
text = text.slice(0, lineStart) + text.slice(stop);
|
|
112
|
+
}
|
|
113
|
+
// Removing a declaration can leave stacked or trailing blank lines behind. Python style keeps two between definitions.
|
|
114
|
+
text = text.replace(path.endsWith(".py") ? /\n{4,}/g : /\n{3,}/g, path.endsWith(".py") ? "\n\n\n" : "\n\n").replace(/\s+$/, "") + "\n";
|
|
115
|
+
writeFileSync(abs, text);
|
|
116
|
+
touched.add(path);
|
|
117
|
+
}
|
|
118
|
+
return [...touched].sort();
|
|
119
|
+
}
|
|
120
|
+
/** Extend a removal back over JSDoc/line comments (or Python `#` comments) attached to the declaration. */
|
|
121
|
+
function removeLeadingComments(text, start, python = false) {
|
|
122
|
+
let pos = start;
|
|
123
|
+
for (;;) {
|
|
124
|
+
let lineStart = text.lastIndexOf("\n", pos - 1) + 1;
|
|
125
|
+
if (text.slice(lineStart, pos).trim() !== "")
|
|
126
|
+
return pos;
|
|
127
|
+
if (lineStart === 0)
|
|
128
|
+
return 0;
|
|
129
|
+
const prevEnd = lineStart - 1;
|
|
130
|
+
const prevStart = text.lastIndexOf("\n", prevEnd - 1) + 1;
|
|
131
|
+
const prev = text.slice(prevStart, prevEnd).trim();
|
|
132
|
+
if (python) {
|
|
133
|
+
if (prev.startsWith("#") && !prev.startsWith("#!")) {
|
|
134
|
+
pos = prevStart;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
return lineStart;
|
|
138
|
+
}
|
|
139
|
+
if (prev.startsWith("//") || prev.endsWith("*/") || prev.startsWith("*")) {
|
|
140
|
+
if (prev.endsWith("*/") && !prev.startsWith("/*")) {
|
|
141
|
+
const open = text.lastIndexOf("/*", prevEnd);
|
|
142
|
+
if (open === -1)
|
|
143
|
+
return lineStart;
|
|
144
|
+
lineStart = text.lastIndexOf("\n", open - 1) + 1;
|
|
145
|
+
pos = lineStart;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
pos = prevStart;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
return lineStart;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const SKIP_COPY = new Set(["node_modules", ".git", ".next", ".turbo", "coverage", ".cache"]);
|
|
155
|
+
/**
|
|
156
|
+
* Apply the plan to a scratch copy of the project, run the configured checks
|
|
157
|
+
* there, and return a patch. The working tree is never modified.
|
|
158
|
+
*/
|
|
159
|
+
export function verifyCleanup(root, plan, checks, options = {}) {
|
|
160
|
+
const sandbox = mkdtempSync(join(tmpdir(), "loose-ends-verify-"));
|
|
161
|
+
const copy = join(sandbox, basename(root));
|
|
162
|
+
try {
|
|
163
|
+
cpSync(root, copy, { recursive: true, filter: (src) => !SKIP_COPY.has(basename(src)) || src === root });
|
|
164
|
+
linkNodeModules(root, copy);
|
|
165
|
+
const touched = applyCleanup(copy, plan);
|
|
166
|
+
const patch = diff(root, copy, touched);
|
|
167
|
+
const runs = [];
|
|
168
|
+
for (const command of checks) {
|
|
169
|
+
const started = Date.now();
|
|
170
|
+
const result = spawnSync(command, { cwd: copy, shell: true, encoding: "utf8", timeout: options.timeoutMs ?? 10 * 60_000, env: { ...process.env, CI: "1" } });
|
|
171
|
+
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trimEnd().split("\n").slice(-40).join("\n");
|
|
172
|
+
runs.push({ command, exitCode: result.status ?? 1, durationMs: Date.now() - started, output });
|
|
173
|
+
if (result.status !== 0)
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
return { passed: runs.every((r) => r.exitCode === 0), checks: runs, patch, touched };
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
rmSync(sandbox, { recursive: true, force: true });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Produce the cleanup patch without running checks. */
|
|
183
|
+
export function cleanupPatch(root, plan) {
|
|
184
|
+
const result = verifyCleanup(root, plan, []);
|
|
185
|
+
return { patch: result.patch, touched: result.touched };
|
|
186
|
+
}
|
|
187
|
+
/** Symlink every node_modules directory (root and workspace packages) into the copy. */
|
|
188
|
+
function linkNodeModules(root, copy, rel = "", depth = 0) {
|
|
189
|
+
const dir = join(root, rel);
|
|
190
|
+
if (depth > 4 || !existsSync(dir))
|
|
191
|
+
return;
|
|
192
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
193
|
+
if (!entry.isDirectory())
|
|
194
|
+
continue;
|
|
195
|
+
const child = rel ? `${rel}/${entry.name}` : entry.name;
|
|
196
|
+
if (entry.name === "node_modules") {
|
|
197
|
+
if (existsSync(join(copy, dirname(child))))
|
|
198
|
+
symlinkSync(join(root, child), join(copy, child), "dir");
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (SKIP_COPY.has(entry.name) || entry.name.startsWith("."))
|
|
202
|
+
continue;
|
|
203
|
+
linkNodeModules(root, copy, child, depth + 1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function diff(root, copy, touched) {
|
|
207
|
+
const parts = [];
|
|
208
|
+
for (const path of touched) {
|
|
209
|
+
const before = join(root, path);
|
|
210
|
+
const after = join(copy, path);
|
|
211
|
+
const result = spawnSync("git", ["diff", "--no-index", "--no-color", "--", before, existsSync(after) ? after : "/dev/null"], { encoding: "utf8" });
|
|
212
|
+
const text = (result.stdout ?? "")
|
|
213
|
+
.split(before)
|
|
214
|
+
.join(`/${path}`)
|
|
215
|
+
.split(after)
|
|
216
|
+
.join(`/${path}`)
|
|
217
|
+
.replace(/^diff --git a\/+(\S+) b\/+\S+$/m, `diff --git a/${path} b/${path}`)
|
|
218
|
+
.replace(/^--- a\/+.*$/m, `--- a/${path}`)
|
|
219
|
+
.replace(/^\+\+\+ b\/+.*$/m, `+++ b/${path}`)
|
|
220
|
+
.replace(/^diff --git a\/(.+) b\/dev\/null$/m, `diff --git a/${path} b/${path}`);
|
|
221
|
+
if (text)
|
|
222
|
+
parts.push(text.endsWith("\n") ? text : text + "\n");
|
|
223
|
+
}
|
|
224
|
+
return parts.join("");
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../src/cleanup.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { FindingKind, Language, LooseEndsConfig } from "./types.js";
|
|
2
|
+
export declare const CONFIG_FILES: readonly ["loose-ends.config.json", ".loose-endsrc.json"];
|
|
3
|
+
export declare const SOURCE_EXTENSIONS: readonly [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
4
|
+
export declare const DEFAULT_INCLUDE: string[];
|
|
5
|
+
export declare const LANGUAGES: readonly ["javascript", "python", "java"];
|
|
6
|
+
/** File extensions of each language. */
|
|
7
|
+
export declare const LANGUAGE_EXTENSIONS: Record<Language, RegExp>;
|
|
8
|
+
export declare const DEFAULT_EXCLUDE: string[];
|
|
9
|
+
export declare const DEFAULT_TEST_PATTERNS: string[];
|
|
10
|
+
export declare const DEFAULT_FAIL_ON: FindingKind[];
|
|
11
|
+
export declare const FINDING_KINDS: readonly FindingKind[];
|
|
12
|
+
export declare class ConfigError extends Error {
|
|
13
|
+
readonly source?: string | undefined;
|
|
14
|
+
constructor(message: string, source?: string | undefined);
|
|
15
|
+
}
|
|
16
|
+
export declare function defaultConfig(root: string): LooseEndsConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Load configuration for a project root. Looks for `loose-ends.config.json`,
|
|
19
|
+
* `.loose-endsrc.json`, then a `looseEnds` key in package.json.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadConfig(root: string, overrides?: Partial<LooseEndsConfig>): LooseEndsConfig;
|
|
22
|
+
type RawConfig = Partial<Omit<LooseEndsConfig, "root" | "source">> & {
|
|
23
|
+
extendInclude?: string[];
|
|
24
|
+
extendExclude?: string[];
|
|
25
|
+
extendTestPatterns?: string[];
|
|
26
|
+
};
|
|
27
|
+
/** Validate an untyped config object. Throws ConfigError with a precise message. */
|
|
28
|
+
export declare function parseConfig(raw: unknown, source?: string): RawConfig;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,WAAW,EAAiB,QAAQ,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AAElH,eAAO,MAAM,YAAY,2DAA4D,CAAC;AAEtF,eAAO,MAAM,iBAAiB,yEAA0E,CAAC;AAEzG,eAAO,MAAM,eAAe,UAAiF,CAAC;AAE9G,eAAO,MAAM,SAAS,2CAA4C,CAAC;AAEnE,wCAAwC;AACxC,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAIxD,CAAC;AAEF,eAAO,MAAM,eAAe,UAkC3B,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAsBjC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,WAAW,EAKxC,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAY/C,CAAC;AAIF,qBAAa,WAAY,SAAQ,KAAK;IACP,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;gBAAzC,OAAO,EAAE,MAAM,EAAW,MAAM,CAAC,EAAE,MAAM,YAAA;CAItD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAgB3D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,CAAC,eAAe,CAAM,GAAG,eAAe,CAMlG;AAyBD,KAAK,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,GAAG;IACnE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAoFpE"}
|