unguard 0.5.2 → 0.6.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 +45 -13
- package/dist/{chunk-XHJYPS37.js → chunk-LNO75X5O.js} +20 -16
- package/dist/chunk-LNO75X5O.js.map +1 -0
- package/dist/cli.js +56 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-XHJYPS37.js.map +0 -1
package/README.md
CHANGED
|
@@ -20,12 +20,44 @@ npx unguard
|
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
unguard src/
|
|
23
|
-
unguard src/ --strict
|
|
23
|
+
unguard src/ --strict # treat warnings as errors (CI)
|
|
24
24
|
unguard src/ --filter no-any-cast # run a single rule
|
|
25
|
+
unguard src/ --severity=error # only show errors
|
|
26
|
+
unguard src/ --format=flat # one-line-per-diagnostic, grepable
|
|
27
|
+
unguard src/ --format=flat | grep error
|
|
25
28
|
```
|
|
26
29
|
|
|
27
30
|
Add `unguard` to your lint check.
|
|
28
31
|
|
|
32
|
+
### Exit codes
|
|
33
|
+
|
|
34
|
+
| Code | Meaning |
|
|
35
|
+
| ---- | ------- |
|
|
36
|
+
| 0 | No issues |
|
|
37
|
+
| 1 | Warnings or info only |
|
|
38
|
+
| 2 | At least one error |
|
|
39
|
+
|
|
40
|
+
Use `--severity=error` in CI to only fail on errors:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
unguard src/ --severity=error || exit 1
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Output formats
|
|
47
|
+
|
|
48
|
+
**Grouped** (default) — diagnostics grouped by file:
|
|
49
|
+
|
|
50
|
+
```txt
|
|
51
|
+
src/lib/probe.ts
|
|
52
|
+
37:4 error Empty catch blocks hide failures... no-empty-catch
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Flat** (`--format=flat`) — one line per diagnostic, grepable:
|
|
56
|
+
|
|
57
|
+
```txt
|
|
58
|
+
src/lib/probe.ts:37:4 error [no-empty-catch] Empty catch blocks hide failures...
|
|
59
|
+
```
|
|
60
|
+
|
|
29
61
|
## Current Rules
|
|
30
62
|
|
|
31
63
|
### Type system evasion
|
|
@@ -33,7 +65,7 @@ Add `unguard` to your lint check.
|
|
|
33
65
|
| Rule | Severity | What it catches |
|
|
34
66
|
| ---- | -------- | --------------- |
|
|
35
67
|
| `no-any-cast` | error | `x as any` |
|
|
36
|
-
| `no-explicit-any-annotation` |
|
|
68
|
+
| `no-explicit-any-annotation` | error | `param: any`, `const x: any` |
|
|
37
69
|
| `no-type-assertion` | error | `x as unknown as T` |
|
|
38
70
|
| `no-ts-ignore` | error | `@ts-ignore` / `@ts-expect-error` |
|
|
39
71
|
|
|
@@ -41,10 +73,10 @@ Add `unguard` to your lint check.
|
|
|
41
73
|
|
|
42
74
|
| Rule | Severity | What it catches |
|
|
43
75
|
| ---- | -------- | --------------- |
|
|
44
|
-
| `no-optional-property-access` |
|
|
45
|
-
| `no-optional-element-access` |
|
|
46
|
-
| `no-optional-call` |
|
|
47
|
-
| `no-nullish-coalescing` |
|
|
76
|
+
| `no-optional-property-access` | info | `obj?.prop` |
|
|
77
|
+
| `no-optional-element-access` | info | `obj?.[key]` |
|
|
78
|
+
| `no-optional-call` | info | `fn?.()` |
|
|
79
|
+
| `no-nullish-coalescing` | info | `x ?? fallback` |
|
|
48
80
|
| `no-logical-or-fallback` | warning | `x \|\| fallback` |
|
|
49
81
|
| `no-null-ternary-normalization` | warning | `x == null ? fallback : x` |
|
|
50
82
|
| `no-non-null-assertion` | warning | `x!` |
|
|
@@ -55,7 +87,7 @@ Add `unguard` to your lint check.
|
|
|
55
87
|
|
|
56
88
|
| Rule | Severity | What it catches |
|
|
57
89
|
| ---- | -------- | --------------- |
|
|
58
|
-
| `no-empty-catch` | error | `catch {}` with no body |
|
|
90
|
+
| `no-empty-catch` | error | `catch {}` with no body (comments count as annotation) |
|
|
59
91
|
| `no-catch-return` | warning | `catch { return fallback }` without rethrowing |
|
|
60
92
|
| `no-error-rewrap` | error | `throw new Error(e.message)` without `{ cause: e }` |
|
|
61
93
|
|
|
@@ -63,7 +95,7 @@ Add `unguard` to your lint check.
|
|
|
63
95
|
|
|
64
96
|
| Rule | Severity | What it catches |
|
|
65
97
|
| ---- | -------- | --------------- |
|
|
66
|
-
| `no-inline-type-in-params` |
|
|
98
|
+
| `no-inline-type-in-params` | info | `fn(opts: { a: string; b: number })` |
|
|
67
99
|
| `prefer-default-param-value` | info | Optional param reassigned with `??` in the body |
|
|
68
100
|
| `prefer-required-param-with-guard` | info | `arg?: T` followed by `if (!arg) throw` |
|
|
69
101
|
|
|
@@ -71,10 +103,10 @@ Add `unguard` to your lint check.
|
|
|
71
103
|
|
|
72
104
|
| Rule | Severity | What it catches |
|
|
73
105
|
| ---- | -------- | --------------- |
|
|
74
|
-
| `duplicate-type-declaration` |
|
|
75
|
-
| `duplicate-type-name` |
|
|
76
|
-
| `duplicate-function-declaration` |
|
|
77
|
-
| `duplicate-function-name` |
|
|
106
|
+
| `duplicate-type-declaration` | error | Same type shape in multiple files |
|
|
107
|
+
| `duplicate-type-name` | error | Same exported type name, different shapes |
|
|
108
|
+
| `duplicate-function-declaration` | error | Same function body in multiple files |
|
|
109
|
+
| `duplicate-function-name` | error | Same exported function name, different bodies |
|
|
78
110
|
| `optional-arg-always-used` | warning | Optional param provided at every call site |
|
|
79
111
|
| `explicit-null-arg` | warning | `fn(null)` / `fn(undefined)` to project functions |
|
|
80
112
|
|
|
@@ -94,7 +126,7 @@ type AnyNode = Record<string, any>;
|
|
|
94
126
|
```
|
|
95
127
|
|
|
96
128
|
```txt
|
|
97
|
-
file.ts:2:31
|
|
129
|
+
file.ts:2:31 error Explicit `any` annotation ... (intentional escape hatch for untyped AST access)
|
|
98
130
|
```
|
|
99
131
|
|
|
100
132
|
## API
|
|
@@ -72,7 +72,7 @@ var noTsIgnore = {
|
|
|
72
72
|
// src/rules/single-file/no-nullish-coalescing.ts
|
|
73
73
|
var noNullishCoalescing = {
|
|
74
74
|
id: "no-nullish-coalescing",
|
|
75
|
-
severity: "
|
|
75
|
+
severity: "info",
|
|
76
76
|
message: "Nullish coalescing (??) masks a possibly-nullable type; if the type guarantees non-null, remove the fallback; if not, fix the type upstream",
|
|
77
77
|
visit(node, _parent, ctx) {
|
|
78
78
|
if (node.type !== "LogicalExpression") return;
|
|
@@ -194,7 +194,7 @@ var noAnyCast = {
|
|
|
194
194
|
// src/rules/single-file/no-explicit-any-annotation.ts
|
|
195
195
|
var noExplicitAnyAnnotation = {
|
|
196
196
|
id: "no-explicit-any-annotation",
|
|
197
|
-
severity: "
|
|
197
|
+
severity: "error",
|
|
198
198
|
message: "Explicit `any` annotation erases type safety; use a specific type, `unknown`, or a generic",
|
|
199
199
|
visit(node, parent, ctx) {
|
|
200
200
|
if (node.type !== "TSAnyKeyword") return;
|
|
@@ -206,7 +206,7 @@ var noExplicitAnyAnnotation = {
|
|
|
206
206
|
// src/rules/single-file/no-inline-type-in-params.ts
|
|
207
207
|
var noInlineTypeInParams = {
|
|
208
208
|
id: "no-inline-type-in-params",
|
|
209
|
-
severity: "
|
|
209
|
+
severity: "info",
|
|
210
210
|
message: "Inline type literal in annotation; extract to a named type for reuse and clarity",
|
|
211
211
|
visit(node, parent, ctx) {
|
|
212
212
|
if (node.type !== "TSTypeLiteral") return;
|
|
@@ -361,15 +361,16 @@ function isGuardBlock(block) {
|
|
|
361
361
|
// src/rules/cross-file/duplicate-type-declaration.ts
|
|
362
362
|
var duplicateTypeDeclaration = {
|
|
363
363
|
id: "duplicate-type-declaration",
|
|
364
|
-
severity: "
|
|
364
|
+
severity: "error",
|
|
365
365
|
message: "Identical type shape declared in multiple files; consolidate to a single definition",
|
|
366
366
|
analyze(project) {
|
|
367
367
|
const diagnostics = [];
|
|
368
368
|
for (const group of project.types.getDuplicateGroups()) {
|
|
369
369
|
const files = new Set(group.map((e) => e.file));
|
|
370
370
|
if (files.size < 2) continue;
|
|
371
|
-
|
|
372
|
-
|
|
371
|
+
const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
372
|
+
for (const entry of sorted.slice(1)) {
|
|
373
|
+
const others = sorted.filter((e) => e !== entry).map((e) => `${e.name} (${e.file}:${e.line})`).join(", ");
|
|
373
374
|
diagnostics.push({
|
|
374
375
|
ruleId: this.id,
|
|
375
376
|
severity: this.severity,
|
|
@@ -387,15 +388,16 @@ var duplicateTypeDeclaration = {
|
|
|
387
388
|
// src/rules/cross-file/duplicate-function-declaration.ts
|
|
388
389
|
var duplicateFunctionDeclaration = {
|
|
389
390
|
id: "duplicate-function-declaration",
|
|
390
|
-
severity: "
|
|
391
|
+
severity: "error",
|
|
391
392
|
message: "Identical function body declared in multiple files; consolidate to a single definition",
|
|
392
393
|
analyze(project) {
|
|
393
394
|
const diagnostics = [];
|
|
394
395
|
for (const group of project.functions.getDuplicateGroups()) {
|
|
395
396
|
const files = new Set(group.map((e) => e.file));
|
|
396
397
|
if (files.size < 2) continue;
|
|
397
|
-
|
|
398
|
-
|
|
398
|
+
const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
399
|
+
for (const entry of sorted.slice(1)) {
|
|
400
|
+
const others = sorted.filter((e) => e !== entry).map((e) => `${e.name} (${e.file}:${e.line})`).join(", ");
|
|
399
401
|
diagnostics.push({
|
|
400
402
|
ruleId: this.id,
|
|
401
403
|
severity: this.severity,
|
|
@@ -608,15 +610,16 @@ var explicitNullArg = {
|
|
|
608
610
|
// src/rules/cross-file/duplicate-function-name.ts
|
|
609
611
|
var duplicateFunctionName = {
|
|
610
612
|
id: "duplicate-function-name",
|
|
611
|
-
severity: "
|
|
613
|
+
severity: "error",
|
|
612
614
|
message: "Same function name exported from multiple files; consolidate or rename to avoid ambiguity",
|
|
613
615
|
analyze(project) {
|
|
614
616
|
const diagnostics = [];
|
|
615
617
|
for (const group of project.functions.getNameCollisionGroups()) {
|
|
616
618
|
const hashes = new Set(group.map((e) => e.hash));
|
|
617
619
|
if (hashes.size === 1) continue;
|
|
618
|
-
|
|
619
|
-
|
|
620
|
+
const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
621
|
+
for (const entry of sorted.slice(1)) {
|
|
622
|
+
const others = sorted.filter((e) => e !== entry).map((e) => `${e.file}:${e.line}`).join(", ");
|
|
620
623
|
diagnostics.push({
|
|
621
624
|
ruleId: this.id,
|
|
622
625
|
severity: this.severity,
|
|
@@ -634,15 +637,16 @@ var duplicateFunctionName = {
|
|
|
634
637
|
// src/rules/cross-file/duplicate-type-name.ts
|
|
635
638
|
var duplicateTypeName = {
|
|
636
639
|
id: "duplicate-type-name",
|
|
637
|
-
severity: "
|
|
640
|
+
severity: "error",
|
|
638
641
|
message: "Same type name exported from multiple files; consolidate or rename to avoid ambiguity",
|
|
639
642
|
analyze(project) {
|
|
640
643
|
const diagnostics = [];
|
|
641
644
|
for (const group of project.types.getNameCollisionGroups()) {
|
|
642
645
|
const hashes = new Set(group.map((e) => e.hash));
|
|
643
646
|
if (hashes.size === 1) continue;
|
|
644
|
-
|
|
645
|
-
|
|
647
|
+
const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
648
|
+
for (const entry of sorted.slice(1)) {
|
|
649
|
+
const others = sorted.filter((e) => e !== entry).map((e) => `${e.file}:${e.line}`).join(", ");
|
|
646
650
|
diagnostics.push({
|
|
647
651
|
ruleId: this.id,
|
|
648
652
|
severity: this.severity,
|
|
@@ -1131,4 +1135,4 @@ export {
|
|
|
1131
1135
|
allRules,
|
|
1132
1136
|
scan
|
|
1133
1137
|
};
|
|
1134
|
-
//# sourceMappingURL=chunk-
|
|
1138
|
+
//# sourceMappingURL=chunk-LNO75X5O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/narrow.ts","../src/rules/single-file/no-empty-catch.ts","../src/rules/single-file/no-non-null-assertion.ts","../src/rules/single-file/no-double-negation-coercion.ts","../src/rules/single-file/no-ts-ignore.ts","../src/rules/single-file/no-nullish-coalescing.ts","../src/rules/single-file/no-optional-call.ts","../src/rules/single-file/no-optional-property-access.ts","../src/rules/single-file/no-optional-element-access.ts","../src/utils/ast.ts","../src/rules/single-file/no-logical-or-fallback.ts","../src/rules/single-file/no-null-ternary-normalization.ts","../src/rules/single-file/no-any-cast.ts","../src/rules/single-file/no-explicit-any-annotation.ts","../src/rules/single-file/no-inline-type-in-params.ts","../src/rules/single-file/no-type-assertion.ts","../src/rules/single-file/no-redundant-existence-guard.ts","../src/rules/single-file/prefer-default-param-value.ts","../src/rules/single-file/prefer-required-param-with-guard.ts","../src/rules/cross-file/duplicate-type-declaration.ts","../src/rules/cross-file/duplicate-function-declaration.ts","../src/rules/cross-file/optional-arg-always-used.ts","../src/rules/single-file/no-catch-return.ts","../src/rules/single-file/no-error-rewrap.ts","../src/rules/cross-file/explicit-null-arg.ts","../src/rules/cross-file/duplicate-function-name.ts","../src/rules/cross-file/duplicate-type-name.ts","../src/rules/single-file/no-dynamic-import.ts","../src/rules/index.ts","../src/engine.ts","../src/rules/types.ts","../src/collect/index.ts","../src/utils/hash.ts","../src/collect/type-registry.ts","../src/collect/function-registry.ts"],"sourcesContent":["/**\n * Runtime node property access helpers.\n *\n * oxc-parser's runtime AST diverges from @oxc-project/types in some areas\n * (e.g., all literals use type \"Literal\" at runtime vs NullLiteral/StringLiteral in types).\n * These helpers provide typed access to common node shapes without `as any` casts.\n */\nimport type { Node } from \"oxc-parser\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional escape hatch for untyped AST access\ntype AnyNode = Record<string, any>;\n\n/** Safely access a property on any AST node. */\nexport function prop<T = unknown>(node: Node, key: string): T {\n return (node as AnyNode)[key] as T;\n}\n\n/** Get child node. Returns Node or null. */\nexport function child(node: Node, key: string): Node | null {\n const val = (node as AnyNode)[key];\n if (val === undefined || val === null) return null;\n return val as Node;\n}\n\n/** Get child nodes array. Returns Node[] or empty. */\nexport function children(node: Node, key: string): Node[] {\n const val = (node as AnyNode)[key];\n if (!Array.isArray(val)) return [];\n return val as Node[];\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child, children } from \"../../utils/narrow.ts\";\n\nexport const noEmptyCatch: SingleFileRule = {\n id: \"no-empty-catch\",\n severity: \"error\",\n message: \"Empty catch blocks hide failures; handle, annotate, or rethrow explicitly\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CatchClause\") return;\n const body = child(node, \"body\");\n if (body && body.type === \"BlockStatement\" && children(body, \"body\").length === 0) {\n const hasComment = ctx.comments.some((c) => c.start >= body.start && c.end <= body.end);\n if (hasComment) return;\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noNonNullAssertion: SingleFileRule = {\n id: \"no-non-null-assertion\",\n severity: \"warning\",\n message: \"Non-null assertion (!) overrides the type checker; narrow with a type guard or fix the type so it's not nullable\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSNonNullExpression\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child } from \"../../utils/narrow.ts\";\n\nexport const noDoubleNegationCoercion: SingleFileRule = {\n id: \"no-double-negation-coercion\",\n severity: \"info\",\n message: \"!! coercion hides intent; use an explicit check (!== null, !== undefined, .length > 0) so the condition documents what it tests\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"UnaryExpression\") return;\n if (prop<string>(node, \"operator\") !== \"!\") return;\n const arg = child(node, \"argument\");\n if (arg !== null && arg.type === \"UnaryExpression\" && prop<string>(arg, \"operator\") === \"!\") {\n ctx.report(node);\n }\n },\n};\n","import type { Node, Comment } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noTsIgnore: SingleFileRule = {\n id: \"no-ts-ignore\",\n severity: \"error\",\n message: \"@ts-ignore / @ts-expect-error suppresses type checking; fix the underlying type issue\",\n\n visit(_node: Node, _parent: Node | null, _ctx: VisitContext) {},\n\n visitComment(comment: Comment, ctx: VisitContext) {\n if (comment.value.includes(\"@ts-ignore\") || comment.value.includes(\"@ts-expect-error\")) {\n ctx.report(comment);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noNullishCoalescing: SingleFileRule = {\n id: \"no-nullish-coalescing\",\n severity: \"info\",\n message: \"Nullish coalescing (??) masks a possibly-nullable type; if the type guarantees non-null, remove the fallback; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"LogicalExpression\") return;\n if (prop<string>(node, \"operator\") !== \"??\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noOptionalCall: SingleFileRule = {\n id: \"no-optional-call\",\n severity: \"info\",\n message: \"Optional call (?.) assumes the function could be undefined; if the type guarantees it exists, call directly; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CallExpression\") return;\n if (!prop<boolean>(node, \"optional\")) return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noOptionalPropertyAccess: SingleFileRule = {\n id: \"no-optional-property-access\",\n severity: \"info\",\n message: \"Optional chaining (?.) assumes the object could be nullish; if the type guarantees it, use a direct access; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"MemberExpression\") return;\n if (prop<boolean>(node, \"optional\") && !prop<boolean>(node, \"computed\")) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noOptionalElementAccess: SingleFileRule = {\n id: \"no-optional-element-access\",\n severity: \"info\",\n message: \"Optional element access (?.[]) assumes the object could be nullish; if the type guarantees it, use a direct access; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"MemberExpression\") return;\n if (prop<boolean>(node, \"optional\") && prop<boolean>(node, \"computed\")) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport { prop } from \"./narrow.ts\";\n\n/** Check if a node is null or undefined literal. */\nexport function isNullish(node: Node): boolean {\n if (node.type === \"Literal\" && prop(node, \"value\") === null) return true;\n if (node.type === \"Identifier\" && prop<string>(node, \"name\") === \"undefined\") return true;\n return false;\n}\n\n/** Check if a node is a literal value. */\nexport function isLiteral(node: Node): boolean {\n switch (node.type) {\n case \"Literal\":\n case \"TemplateLiteral\":\n case \"ArrayExpression\":\n case \"ObjectExpression\":\n return true;\n case \"Identifier\":\n return prop<string>(node, \"name\") === \"undefined\";\n default:\n return false;\n }\n}\n\n/** Get source text for a node using its span. */\nexport function getNodeText(source: string, node: Node): string {\n return source.slice(node.start, node.end);\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child } from \"../../utils/narrow.ts\";\nimport { isLiteral } from \"../../utils/ast.ts\";\n\nexport const noLogicalOrFallback: SingleFileRule = {\n id: \"no-logical-or-fallback\",\n severity: \"warning\",\n message: \"|| with a literal fallback assumes the left side could be falsy; if the type guarantees a value, remove the fallback; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"LogicalExpression\") return;\n if (prop<string>(node, \"operator\") !== \"||\") return;\n const right = child(node, \"right\");\n if (right && isLiteral(right)) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child } from \"../../utils/narrow.ts\";\nimport { isNullish } from \"../../utils/ast.ts\";\n\nexport const noNullTernaryNormalization: SingleFileRule = {\n id: \"no-null-ternary-normalization\",\n severity: \"warning\",\n message: \"Ternary null-normalization (x == null ? fallback : x); if the type guarantees non-null, remove the ternary; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"ConditionalExpression\") return;\n const test = child(node, \"test\");\n if (test === null || test.type !== \"BinaryExpression\") return;\n const op = prop<string>(test, \"operator\");\n if (op !== \"===\" && op !== \"!==\" && op !== \"==\" && op !== \"!=\") return;\n const testLeft = child(test, \"left\");\n const testRight = child(test, \"right\");\n const hasNullishComparand =\n (testLeft !== null && isNullish(testLeft)) || (testRight !== null && isNullish(testRight));\n if (!hasNullishComparand) return;\n const consequent = child(node, \"consequent\");\n const alternate = child(node, \"alternate\");\n if ((consequent !== null && isNullish(consequent)) || (alternate !== null && isNullish(alternate))) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child } from \"../../utils/narrow.ts\";\n\nexport const noAnyCast: SingleFileRule = {\n id: \"no-any-cast\",\n severity: \"error\",\n message: \"Casting to `any` erases type safety; use a specific type or generic instead\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSAsExpression\") return;\n const typeAnno = child(node, \"typeAnnotation\");\n if (typeAnno !== null && typeAnno.type === \"TSAnyKeyword\") {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noExplicitAnyAnnotation: SingleFileRule = {\n id: \"no-explicit-any-annotation\",\n severity: \"error\",\n message: \"Explicit `any` annotation erases type safety; use a specific type, `unknown`, or a generic\",\n\n visit(node: Node, parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSAnyKeyword\") return;\n // Skip if inside a cast (covered by no-any-cast)\n if (parent !== null && parent.type === \"TSAsExpression\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noInlineTypeInParams: SingleFileRule = {\n id: \"no-inline-type-in-params\",\n severity: \"info\",\n message: \"Inline type literal in annotation; extract to a named type for reuse and clarity\",\n\n visit(node: Node, parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSTypeLiteral\") return;\n if (parent === null || parent.type !== \"TSTypeAnnotation\") return;\n\n if (!isTopLevelFunctionParam(ctx.source, node.start)) return;\n\n ctx.report(node);\n },\n};\n\nfunction isTopLevelFunctionParam(source: string, offset: number): boolean {\n // Only flag if the nearest enclosing \"{\" is the module scope (no enclosing brace)\n // or a plain function body. Skip anything nested inside classes, interfaces,\n // object literals (builder patterns), etc.\n let depth = 0;\n for (let i = offset - 1; i >= 0; i--) {\n if (source[i] === \"}\") depth++;\n if (source[i] === \"{\") {\n if (depth === 0) {\n // Found the enclosing \"{\". If it belongs to a function declaration\n // or arrow, that's fine (we're in a nested function param). But if\n // it's anything else (class, interface, object literal), skip.\n // In practice: only flag when there's NO enclosing \"{\" at all\n // (module-level function), or the enclosing block is a function body.\n const before = source.slice(Math.max(0, i - 150), i).trimEnd();\n // Function body: preceded by \")\" or \"=> {\" or similar\n if (/(\\)|\\bfunction\\b.*\\))\\s*$/.test(before)) {\n // Inside a function body — keep walking to check if that function\n // is itself top-level or nested\n depth--;\n continue;\n }\n // Anything else (class, interface, object, etc.) — not top-level\n return false;\n }\n depth--;\n }\n }\n // Reached beginning of file with no unmatched \"{\" — module scope\n return true;\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child } from \"../../utils/narrow.ts\";\n\nexport const noTypeAssertion: SingleFileRule = {\n id: \"no-type-assertion\",\n severity: \"error\",\n message: \"Double type assertion (`as unknown as T`) circumvents the type system; fix the upstream type or use a type guard\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSAsExpression\") return;\n // Check if the expression being cast is itself an `as unknown`\n const inner = child(node, \"expression\");\n if (inner === null || inner.type !== \"TSAsExpression\") return;\n const innerType = child(inner, \"typeAnnotation\");\n if (innerType === null || innerType.type !== \"TSUnknownKeyword\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child, prop } from \"../../utils/narrow.ts\";\n\nexport const noRedundantExistenceGuard: SingleFileRule = {\n id: \"no-redundant-existence-guard\",\n severity: \"warning\",\n message: \"Redundant existence guard (obj && obj.prop); if the type guarantees obj exists, remove the guard; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"IfStatement\") return;\n const test = child(node, \"test\");\n if (!test || test.type !== \"LogicalExpression\" || prop<string>(test, \"operator\") !== \"&&\") return;\n\n const left = child(test, \"left\");\n const right = child(test, \"right\");\n if (!left || left.type !== \"Identifier\") return;\n if (!right || right.type !== \"MemberExpression\") return;\n const obj = child(right, \"object\");\n if (!obj || obj.type !== \"Identifier\") return;\n if (prop<string>(left, \"name\") !== prop<string>(obj, \"name\")) return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child, children } from \"../../utils/narrow.ts\";\n\nexport const preferDefaultParamValue: SingleFileRule = {\n id: \"prefer-default-param-value\",\n severity: \"info\",\n message: \"Use a default parameter value instead of reassigning from nullish coalescing inside the body\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"FunctionDeclaration\" && node.type !== \"ArrowFunctionExpression\") return;\n const params = children(node, \"params\");\n const body = child(node, \"body\");\n if (body === null || body.type !== \"BlockStatement\") return;\n const stmts = children(body, \"body\");\n if (stmts.length === 0) return;\n\n const firstStmt = stmts[0];\n if (firstStmt.type !== \"ExpressionStatement\") return;\n const expr = child(firstStmt, \"expression\");\n if (expr === null || expr.type !== \"AssignmentExpression\" || prop<string>(expr, \"operator\") !== \"=\") return;\n\n const right = child(expr, \"right\");\n if (right === null || right.type !== \"LogicalExpression\" || prop<string>(right, \"operator\") !== \"??\") return;\n\n const assignee = child(expr, \"left\");\n const coalescedLeft = child(right, \"left\");\n if (assignee === null || assignee.type !== \"Identifier\") return;\n if (coalescedLeft === null || coalescedLeft.type !== \"Identifier\") return;\n if (prop<string>(assignee, \"name\") !== prop<string>(coalescedLeft, \"name\")) return;\n\n const assigneeName = prop<string>(assignee, \"name\");\n const isParam = params.some((p: Node) => {\n if (p.type === \"Identifier\") return prop<string>(p, \"name\") === assigneeName;\n if (p.type === \"AssignmentPattern\") {\n const left = child(p, \"left\");\n return left !== null && left.type === \"Identifier\" && prop<string>(left, \"name\") === assigneeName;\n }\n return false;\n });\n if (isParam) {\n ctx.report(firstStmt);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child, children } from \"../../utils/narrow.ts\";\n\nexport const preferRequiredParamWithGuard: SingleFileRule = {\n id: \"prefer-required-param-with-guard\",\n severity: \"info\",\n message: \"Optional param with immediate guard (if (!param) return/throw); make it required instead\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"FunctionDeclaration\" && node.type !== \"ArrowFunctionExpression\") return;\n const params = children(node, \"params\");\n const body = child(node, \"body\");\n if (body === null || body.type !== \"BlockStatement\") return;\n const stmts = children(body, \"body\");\n if (stmts.length === 0) return;\n\n const firstStmt = stmts[0];\n if (firstStmt.type !== \"IfStatement\") return;\n\n const test = child(firstStmt, \"test\");\n if (test === null) return;\n let guardedName: string | null = null;\n\n // Pattern 1: if (!param)\n if (test.type === \"UnaryExpression\" && prop<string>(test, \"operator\") === \"!\") {\n const arg = child(test, \"argument\");\n if (arg !== null && arg.type === \"Identifier\") guardedName = prop<string>(arg, \"name\");\n }\n // Pattern 2: if (param === undefined)\n if (test.type === \"BinaryExpression\") {\n const op = prop<string>(test, \"operator\");\n if (op === \"===\" || op === \"==\") {\n const left = child(test, \"left\");\n const right = child(test, \"right\");\n if (\n left !== null &&\n left.type === \"Identifier\" &&\n right !== null &&\n right.type === \"Identifier\" &&\n prop<string>(right, \"name\") === \"undefined\"\n ) {\n guardedName = prop<string>(left, \"name\");\n }\n }\n }\n\n if (guardedName === null) return;\n\n const consequent = child(firstStmt, \"consequent\");\n if (consequent === null) return;\n const isGuard =\n consequent.type === \"ReturnStatement\" ||\n consequent.type === \"ThrowStatement\" ||\n (consequent.type === \"BlockStatement\" && isGuardBlock(consequent));\n\n if (!isGuard) return;\n\n const isOptionalParam = params.some(\n (p: Node) => p.type === \"Identifier\" && prop<string>(p, \"name\") === guardedName && prop<boolean>(p, \"optional\") === true,\n );\n if (isOptionalParam) {\n ctx.report(firstStmt);\n }\n },\n};\n\nfunction isGuardBlock(block: Node): boolean {\n const body = children(block, \"body\");\n if (body.length !== 1) return false;\n const stmt = body[0];\n return stmt.type === \"ReturnStatement\" || stmt.type === \"ThrowStatement\";\n}\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateTypeDeclaration: CrossFileRule = {\n id: \"duplicate-type-declaration\",\n severity: \"error\",\n message: \"Identical type shape declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.types.getDuplicateGroups()) {\n // Only flag if types are in different files\n const files = new Set(group.map((e) => e.file));\n if (files.size < 2) continue;\n\n const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n for (const entry of sorted.slice(1)) {\n const others = sorted\n .filter((e) => e !== entry)\n .map((e) => `${e.name} (${e.file}:${e.line})`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Type \"${entry.name}\" has identical shape to: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateFunctionDeclaration: CrossFileRule = {\n id: \"duplicate-function-declaration\",\n severity: \"error\",\n message: \"Identical function body declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.functions.getDuplicateGroups()) {\n const files = new Set(group.map((e) => e.file));\n if (files.size < 2) continue;\n\n const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n for (const entry of sorted.slice(1)) {\n const others = sorted\n .filter((e) => e !== entry)\n .map((e) => `${e.name} (${e.file}:${e.line})`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Function \"${entry.name}\" has identical body to: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const optionalArgAlwaysUsed: CrossFileRule = {\n id: \"optional-arg-always-used\",\n severity: \"warning\",\n message: \"Optional parameter is always provided at every call site; make it required\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n for (const fn of project.functions.getAll()) {\n // Find optional params (by index)\n for (let i = 0; i < fn.params.length; i++) {\n const param = fn.params[i];\n if (!param.optional && !param.hasDefault) continue;\n\n // Find all call sites matching this function name\n const callSites = project.callSites.filter((c) => c.calleeName === fn.name);\n\n // Need at least 2 call sites to be meaningful\n if (callSites.length < 2) continue;\n\n // Check if every call site provides this positional argument\n const allProvide = callSites.every((c) => c.argCount > i);\n if (allProvide) {\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Optional parameter \"${param.name}\" is always provided at all ${callSites.length} call sites; make it required`,\n file: fn.file,\n line: fn.line,\n column: 1,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child, prop } from \"../../utils/narrow.ts\";\n\nexport const noCatchReturn: SingleFileRule = {\n id: \"no-catch-return\",\n severity: \"warning\",\n message:\n \"Catch block returns a fallback value, forcing callers to handle two data shapes; rethrow or let the error propagate\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CatchClause\") return;\n const body = child(node, \"body\");\n if (body === null) return;\n if (hasReturn(body) && !hasThrow(body)) {\n ctx.report(node);\n }\n },\n};\n\nfunction hasReturn(block: Node): boolean {\n return walkForType(block, \"ReturnStatement\");\n}\n\nfunction hasThrow(block: Node): boolean {\n return walkForType(block, \"ThrowStatement\");\n}\n\nfunction walkForType(root: Node, targetType: string): boolean {\n if (root.type === targetType) return true;\n const keys = Object.keys(root);\n for (const key of keys) {\n if (key === \"start\" || key === \"end\" || key === \"type\") continue;\n const val = prop<unknown>(root, key);\n if (val === null || val === undefined || typeof val !== \"object\") continue;\n // Skip nested function scopes — their returns/throws are their own\n if (isFunction(val as Node)) continue;\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item !== null && typeof item === \"object\" && \"type\" in item) {\n if (isFunction(item as Node)) continue;\n if (walkForType(item as Node, targetType)) return true;\n }\n }\n } else if (\"type\" in val) {\n if (walkForType(val as Node, targetType)) return true;\n }\n }\n return false;\n}\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\"\n );\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child, children } from \"../../utils/narrow.ts\";\n\nexport const noErrorRewrap: SingleFileRule = {\n id: \"no-error-rewrap\",\n severity: \"error\",\n message:\n \"Re-wrapped error loses the original stack trace and type; use { cause: originalError } to preserve the error chain\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CatchClause\") return;\n const param = child(node, \"param\");\n if (param === null || param.type !== \"Identifier\") return;\n const catchName = prop<string>(param, \"name\");\n const body = child(node, \"body\");\n if (body === null) return;\n findRewraps(body, catchName, ctx);\n },\n};\n\nfunction findRewraps(root: Node, catchName: string, ctx: VisitContext): void {\n if (root.type === \"ThrowStatement\") {\n const arg = child(root, \"argument\");\n if (arg !== null && arg.type === \"NewExpression\") {\n const args = children(arg, \"arguments\");\n if (args.length > 0 && referencesName(args, catchName) && !hasCauseArg(args)) {\n ctx.report(root);\n }\n }\n return;\n }\n // Skip nested function scopes\n if (\n root.type === \"FunctionDeclaration\" ||\n root.type === \"FunctionExpression\" ||\n root.type === \"ArrowFunctionExpression\"\n ) {\n return;\n }\n const keys = Object.keys(root);\n for (const key of keys) {\n if (key === \"start\" || key === \"end\" || key === \"type\") continue;\n const val = prop<unknown>(root, key);\n if (val === null || val === undefined || typeof val !== \"object\") continue;\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item !== null && typeof item === \"object\" && \"type\" in item) {\n findRewraps(item as Node, catchName, ctx);\n }\n }\n } else if (\"type\" in val) {\n findRewraps(val as Node, catchName, ctx);\n }\n }\n}\n\nfunction referencesName(nodes: Node[], name: string): boolean {\n for (const node of nodes) {\n if (containsIdentifier(node, name)) return true;\n }\n return false;\n}\n\nfunction containsIdentifier(root: Node, name: string): boolean {\n if (root.type === \"Identifier\" && prop<string>(root, \"name\") === name) return true;\n const keys = Object.keys(root);\n for (const key of keys) {\n if (key === \"start\" || key === \"end\" || key === \"type\") continue;\n const val = prop<unknown>(root, key);\n if (val === null || val === undefined || typeof val !== \"object\") continue;\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item !== null && typeof item === \"object\" && \"type\" in item) {\n if (containsIdentifier(item as Node, name)) return true;\n }\n }\n } else if (\"type\" in val) {\n if (containsIdentifier(val as Node, name)) return true;\n }\n }\n return false;\n}\n\nfunction hasCauseArg(args: Node[]): boolean {\n for (const arg of args) {\n if (arg.type === \"ObjectExpression\") {\n const props = children(arg, \"properties\");\n for (const p of props) {\n const key = child(p, \"key\");\n if (key !== null && key.type === \"Identifier\" && prop<string>(key, \"name\") === \"cause\") {\n return true;\n }\n }\n }\n }\n return false;\n}\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\nimport { children } from \"../../utils/narrow.ts\";\nimport { isNullish } from \"../../utils/ast.ts\";\n\nexport const explicitNullArg: CrossFileRule = {\n id: \"explicit-null-arg\",\n severity: \"warning\",\n message: \"Explicit null/undefined passed to a project function; consider redesigning the interface to not accept nullish values\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n // Build a set of known project function names for fast lookup\n const projectFnNames = new Set<string>();\n for (const fn of project.functions.getAll()) {\n projectFnNames.add(fn.name);\n }\n\n for (const site of project.callSites) {\n // Only flag calls to functions defined in the project\n if (!projectFnNames.has(site.calleeName)) continue;\n\n const args = children(site.node, \"arguments\");\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n if (isNullish(arg)) {\n const val = arg.type === \"Literal\" ? \"null\" : \"undefined\";\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Passing explicit ${val} to \"${site.calleeName}\" at argument ${i + 1}; consider redesigning the interface to not accept nullish values`,\n file: site.file,\n line: site.line,\n column: 1,\n });\n break; // one diagnostic per call site\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateFunctionName: CrossFileRule = {\n id: \"duplicate-function-name\",\n severity: \"error\",\n message: \"Same function name exported from multiple files; consolidate or rename to avoid ambiguity\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.functions.getNameCollisionGroups()) {\n // Skip groups already caught by duplicate-function-declaration (identical bodies)\n const hashes = new Set(group.map((e) => e.hash));\n if (hashes.size === 1) continue;\n\n const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n for (const entry of sorted.slice(1)) {\n const others = sorted\n .filter((e) => e !== entry)\n .map((e) => `${e.file}:${e.line}`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Exported function \"${entry.name}\" also defined in: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateTypeName: CrossFileRule = {\n id: \"duplicate-type-name\",\n severity: \"error\",\n message: \"Same type name exported from multiple files; consolidate or rename to avoid ambiguity\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.types.getNameCollisionGroups()) {\n // Skip groups already caught by duplicate-type-declaration (identical shapes)\n const hashes = new Set(group.map((e) => e.hash));\n if (hashes.size === 1) continue;\n\n const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n for (const entry of sorted.slice(1)) {\n const others = sorted\n .filter((e) => e !== entry)\n .map((e) => `${e.file}:${e.line}`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Exported type \"${entry.name}\" also defined in: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noDynamicImport: SingleFileRule = {\n id: \"no-dynamic-import\",\n severity: \"error\",\n message: \"Dynamic import() breaks static analysis and hides dependencies; use a static import instead\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"ImportExpression\") return;\n ctx.report(node);\n },\n};\n","import type { Rule } from \"./types.ts\";\n\nimport { noEmptyCatch } from \"./single-file/no-empty-catch.ts\";\nimport { noNonNullAssertion } from \"./single-file/no-non-null-assertion.ts\";\nimport { noDoubleNegationCoercion } from \"./single-file/no-double-negation-coercion.ts\";\nimport { noTsIgnore } from \"./single-file/no-ts-ignore.ts\";\nimport { noNullishCoalescing } from \"./single-file/no-nullish-coalescing.ts\";\nimport { noOptionalCall } from \"./single-file/no-optional-call.ts\";\nimport { noOptionalPropertyAccess } from \"./single-file/no-optional-property-access.ts\";\nimport { noOptionalElementAccess } from \"./single-file/no-optional-element-access.ts\";\nimport { noLogicalOrFallback } from \"./single-file/no-logical-or-fallback.ts\";\nimport { noNullTernaryNormalization } from \"./single-file/no-null-ternary-normalization.ts\";\nimport { noAnyCast } from \"./single-file/no-any-cast.ts\";\nimport { noExplicitAnyAnnotation } from \"./single-file/no-explicit-any-annotation.ts\";\nimport { noInlineTypeInParams } from \"./single-file/no-inline-type-in-params.ts\";\nimport { noTypeAssertion } from \"./single-file/no-type-assertion.ts\";\nimport { noRedundantExistenceGuard } from \"./single-file/no-redundant-existence-guard.ts\";\nimport { preferDefaultParamValue } from \"./single-file/prefer-default-param-value.ts\";\nimport { preferRequiredParamWithGuard } from \"./single-file/prefer-required-param-with-guard.ts\";\nimport { duplicateTypeDeclaration } from \"./cross-file/duplicate-type-declaration.ts\";\nimport { duplicateFunctionDeclaration } from \"./cross-file/duplicate-function-declaration.ts\";\nimport { optionalArgAlwaysUsed } from \"./cross-file/optional-arg-always-used.ts\";\nimport { noCatchReturn } from \"./single-file/no-catch-return.ts\";\nimport { noErrorRewrap } from \"./single-file/no-error-rewrap.ts\";\nimport { explicitNullArg } from \"./cross-file/explicit-null-arg.ts\";\nimport { duplicateFunctionName } from \"./cross-file/duplicate-function-name.ts\";\nimport { duplicateTypeName } from \"./cross-file/duplicate-type-name.ts\";\nimport { noDynamicImport } from \"./single-file/no-dynamic-import.ts\";\n\nexport const allRules: Rule[] = [\n noEmptyCatch,\n noNonNullAssertion,\n noDoubleNegationCoercion,\n noTsIgnore,\n noNullishCoalescing,\n noOptionalCall,\n noOptionalPropertyAccess,\n noOptionalElementAccess,\n noLogicalOrFallback,\n noNullTernaryNormalization,\n noAnyCast,\n noExplicitAnyAnnotation,\n noInlineTypeInParams,\n noTypeAssertion,\n noRedundantExistenceGuard,\n preferDefaultParamValue,\n preferRequiredParamWithGuard,\n duplicateTypeDeclaration,\n duplicateFunctionDeclaration,\n optionalArgAlwaysUsed,\n noCatchReturn,\n noErrorRewrap,\n explicitNullArg,\n duplicateFunctionName,\n duplicateTypeName,\n noDynamicImport,\n];\n","import { parseSync, type Comment } from \"oxc-parser\";\nimport { walk } from \"oxc-walker\";\nimport fg from \"fast-glob\";\nimport { readFileSync } from \"node:fs\";\nimport type { Node } from \"oxc-parser\";\nimport type { Diagnostic, SingleFileRule, CrossFileRule, Span, VisitContext } from \"./rules/types.ts\";\nimport { allRules } from \"./rules/index.ts\";\nimport { isSingleFileRule } from \"./rules/types.ts\";\nimport { collectProject } from \"./collect/index.ts\";\n\nexport interface ScanOptions {\n paths: string[];\n strict?: boolean;\n rules?: string[];\n}\n\nexport interface ScanResult {\n diagnostics: Diagnostic[];\n fileCount: number;\n}\n\nexport async function scan(options: ScanOptions): Promise<ScanResult> {\n const patterns = options.paths.length > 0 ? options.paths : [\".\"];\n const globs = patterns.map((p) => {\n if (p === \".\") return `./**/*.{ts,cts,mts,tsx}`;\n if (p.endsWith(\"/\")) return `${p}**/*.{ts,cts,mts,tsx}`;\n if (!p.includes(\"*\") && !p.endsWith(\".ts\") && !p.endsWith(\".tsx\") && !p.endsWith(\".cts\") && !p.endsWith(\".mts\")) {\n return `${p}/**/*.{ts,cts,mts,tsx}`;\n }\n return p;\n });\n\n const files = await fg(globs, {\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\", \"**/*.d.ts\", \"**/*.d.cts\", \"**/*.d.mts\"],\n absolute: true,\n });\n\n const activeRules = allRules.filter((r) => {\n if (options.rules && !options.rules.includes(r.id)) return false;\n return true;\n });\n\n const singleFileRules = activeRules.filter(isSingleFileRule);\n const crossFileRules = activeRules.filter((r): r is CrossFileRule => !isSingleFileRule(r));\n const diagnostics: Diagnostic[] = [];\n\n // Single-file pass: parse each file and run visitor rules\n for (const file of files) {\n const source = readFileSync(file, \"utf8\");\n const result = parseSync(file, source);\n const fileDiags = runSingleFileRules(singleFileRules, result.program, result.comments, source, file);\n annotate(fileDiags, result.comments, source);\n diagnostics.push(...fileDiags);\n }\n\n // Cross-file pass: collect project index and run analysis rules\n if (crossFileRules.length > 0 && files.length > 0) {\n const projectIndex = collectProject(files);\n for (const rule of crossFileRules) {\n const crossDiags = rule.analyze(projectIndex);\n for (const d of crossDiags) {\n const fileData = projectIndex.files.get(d.file);\n if (fileData !== undefined) annotate([d], fileData.comments, fileData.source);\n }\n diagnostics.push(...crossDiags);\n }\n }\n\n const seen = new Set<string>();\n const deduped: Diagnostic[] = [];\n for (const d of diagnostics) {\n const key = `${d.file}:${d.line}:${d.ruleId}`;\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(d);\n }\n\n if (options.strict) {\n for (const d of deduped) {\n d.severity = \"error\";\n }\n }\n\n return { diagnostics: deduped, fileCount: files.length };\n}\n\nexport function runSingleFileRules(\n rules: SingleFileRule[],\n program: Node,\n comments: Comment[],\n source: string,\n filename: string,\n): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n const makeCtx = (rule: SingleFileRule): VisitContext => ({\n filename,\n source,\n comments,\n report(span: Span, message?: string) {\n const pos = lineCol(source, span.start);\n diagnostics.push({\n ruleId: rule.id,\n severity: rule.severity,\n message: message === undefined ? rule.message : message,\n file: filename,\n ...pos,\n });\n },\n });\n\n const contexts = rules.map((r) => ({ rule: r, ctx: makeCtx(r) }));\n\n walk(program, {\n enter(node: Node, parent: Node | null) {\n for (const { rule, ctx } of contexts) {\n rule.visit(node, parent, ctx);\n }\n },\n });\n\n for (const { rule, ctx } of contexts) {\n if (rule.visitComment) {\n for (const comment of comments) {\n rule.visitComment(comment, ctx);\n }\n }\n }\n\n return diagnostics;\n}\n\ninterface Position {\n line: number;\n column: number;\n}\n\n/**\n * Attach annotations from comments to diagnostics.\n * A comment annotates a diagnostic if it ends on the line immediately above.\n * Consecutive line comments are joined into a single annotation.\n */\nfunction annotate(diagnostics: Diagnostic[], comments: Comment[], source: string): void {\n if (comments.length === 0 || diagnostics.length === 0) return;\n\n // Build a map: endLine -> comment\n const byEndLine = new Map<number, Comment[]>();\n for (const c of comments) {\n const endLine = lineAt(source, c.end);\n let list = byEndLine.get(endLine);\n if (list === undefined) {\n list = [];\n byEndLine.set(endLine, list);\n }\n list.push(c);\n }\n\n for (const d of diagnostics) {\n // Check inline comment on the same line first\n const inline = findInlineComment(d.line, byEndLine);\n if (inline !== null) {\n d.annotation = inline;\n continue;\n }\n // Then check comment(s) on the line above\n const above = collectAnnotation(d.line - 1, byEndLine, source);\n if (above !== null) d.annotation = above;\n }\n}\n\nfunction findInlineComment(diagLine: number, byEndLine: Map<number, Comment[]>): string | null {\n const commentsOnLine = byEndLine.get(diagLine);\n if (commentsOnLine === undefined || commentsOnLine.length === 0) return null;\n const comment = commentsOnLine.at(-1);\n if (comment === undefined) return null;\n // Only line comments (// ...) count as inline annotations, not block comments\n if (comment.type !== \"Line\") return null;\n const text = comment.value.trim();\n // Skip @expect annotations — those are for the test harness, not user annotations\n if (text.startsWith(\"@expect\")) return null;\n return text;\n}\n\nfunction collectAnnotation(\n commentEndLine: number,\n byEndLine: Map<number, Comment[]>,\n source: string,\n): string | null {\n const commentsOnLine = byEndLine.get(commentEndLine);\n if (commentsOnLine === undefined || commentsOnLine.length === 0) return null;\n const comment = commentsOnLine.at(-1);\n if (comment === undefined) return null;\n\n // Block comment: use its value directly\n if (comment.type === \"Block\") {\n return cleanBlockComment(comment.value);\n }\n\n // Line comment: walk upward to collect consecutive line comments\n const lines: string[] = [comment.value.trim()];\n let prevLine = commentEndLine - 1;\n for (;;) {\n const prev = byEndLine.get(prevLine);\n if (prev === undefined || prev.length === 0) break;\n const prevComment = prev.at(-1);\n if (prevComment === undefined || prevComment.type !== \"Line\") break;\n if (lineAt(source, prevComment.start) !== prevLine) break;\n lines.unshift(prevComment.value.trim());\n prevLine--;\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction cleanBlockComment(value: string): string {\n return value\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*\\*\\s?/, \"\").trim())\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n\nfunction lineAt(source: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset && i < source.length; i++) {\n if (source[i] === \"\\n\") line++;\n }\n return line;\n}\n\nfunction lineCol(source: string, offset: number): Position {\n let line = 1;\n let col = 1;\n for (let i = 0; i < offset && i < source.length; i++) {\n if (source[i] === \"\\n\") {\n line++;\n col = 1;\n } else {\n col++;\n }\n }\n return { line, column: col };\n}\n","import type { Node, Comment } from \"oxc-parser\";\n\nexport interface Diagnostic {\n ruleId: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n file: string;\n line: number;\n column: number;\n annotation?: string;\n}\n\nexport interface Span {\n start: number;\n end: number;\n}\n\nexport interface VisitContext {\n report(span: Span, message?: string): void;\n filename: string;\n source: string;\n comments: Comment[];\n}\n\nexport interface SingleFileRule {\n id: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n visit(node: Node, parent: Node | null, ctx: VisitContext): void;\n visitComment?(comment: Comment, ctx: VisitContext): void;\n}\n\nimport type { ProjectIndex } from \"../collect/index.ts\";\nexport type { ProjectIndex };\n\nexport interface CrossFileRule {\n id: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n analyze(project: ProjectIndex): Diagnostic[];\n}\n\nexport type Rule = SingleFileRule | CrossFileRule;\n\nexport function isSingleFileRule(r: Rule): r is SingleFileRule {\n return \"visit\" in r;\n}\n","import { parseSync, type Comment } from \"oxc-parser\";\nimport { walk } from \"oxc-walker\";\nimport { readFileSync } from \"node:fs\";\nimport type { Node } from \"oxc-parser\";\nimport { TypeRegistry } from \"./type-registry.ts\";\nimport { FunctionRegistry, type FunctionEntry, type ParamInfo } from \"./function-registry.ts\";\nimport { hashFunctionBody } from \"../utils/hash.ts\";\nimport { prop, child, children } from \"../utils/narrow.ts\";\n\nexport interface ProjectIndex {\n types: TypeRegistry;\n functions: FunctionRegistry;\n callSites: CallSite[];\n files: Map<string, { source: string; program: Node; comments: Comment[] }>;\n}\n\nexport interface CallSite {\n calleeName: string;\n file: string;\n line: number;\n argCount: number;\n node: Node;\n}\n\nexport function collectProject(files: string[]): ProjectIndex {\n const types = new TypeRegistry();\n const functions = new FunctionRegistry();\n const callSites: CallSite[] = [];\n const fileMap = new Map<string, { source: string; program: Node; comments: Comment[] }>();\n\n for (const file of files) {\n const source = readFileSync(file, \"utf8\");\n const result = parseSync(file, source);\n fileMap.set(file, { source, program: result.program, comments: result.comments });\n\n walk(result.program, {\n enter(node: Node, parent: Node | null) {\n collectTypes(node, parent, file, source, types);\n collectFunctions(node, parent, file, source, functions);\n collectCallSites(node, file, source, callSites);\n },\n });\n }\n\n return { types, functions, callSites, files: fileMap };\n}\n\nfunction lineAt(source: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset; i++) {\n if (source[i] === \"\\n\") line++;\n }\n return line;\n}\n\nfunction collectTypes(node: Node, parent: Node | null, file: string, source: string, registry: TypeRegistry): void {\n if (node.type === \"TSTypeAliasDeclaration\") {\n const id = child(node, \"id\");\n const typeAnno = child(node, \"typeAnnotation\");\n if (id && typeAnno) {\n registry.add(prop<string>(id, \"name\"), file, lineAt(source, node.start), typeAnno, source, isExported(parent));\n }\n }\n if (node.type === \"TSInterfaceDeclaration\") {\n const id = child(node, \"id\");\n const body = child(node, \"body\");\n if (id && body) {\n registry.add(prop<string>(id, \"name\"), file, lineAt(source, node.start), body, source, isExported(parent));\n }\n }\n}\n\nfunction isExported(parent: Node | null): boolean {\n if (parent === null) return false;\n return parent.type === \"ExportNamedDeclaration\" || parent.type === \"ExportDefaultDeclaration\";\n}\n\nfunction collectFunctions(node: Node, parent: Node | null, file: string, source: string, registry: FunctionRegistry): void {\n if (node.type === \"FunctionDeclaration\" || node.type === \"FunctionExpression\") {\n const id = child(node, \"id\");\n const body = child(node, \"body\");\n if (!id || !body) return;\n const name = prop<string>(id, \"name\");\n const params = extractParams(children(node, \"params\"), source);\n const hash = hashFunctionBody(body, source);\n const exported = isExported(parent);\n registry.add({ name, file, line: lineAt(source, node.start), hash, params, node, exported });\n }\n // Arrow functions assigned to const\n if (node.type === \"VariableDeclarator\") {\n const init = child(node, \"init\");\n const id = child(node, \"id\");\n if (init !== null && init.type === \"ArrowFunctionExpression\" && id !== null && id.type === \"Identifier\") {\n const body = child(init, \"body\");\n if (!body) return;\n const name = prop<string>(id, \"name\");\n const params = extractParams(children(init, \"params\"), source);\n const hash = hashFunctionBody(body, source);\n // Parent is VariableDeclaration; check if \"export\" precedes the declaration on the same line\n const lineStart = source.lastIndexOf(\"\\n\", node.start) + 1;\n const linePrefix = source.slice(lineStart, node.start);\n const exported = linePrefix.includes(\"export\");\n registry.add({ name, file, line: lineAt(source, node.start), hash, params, node, exported });\n }\n }\n}\n\nfunction paramName(node: Node, source: string): string {\n const name = prop<string>(node, \"name\");\n if (name !== undefined) return name;\n return source.slice(node.start, node.end);\n}\n\nfunction typeText(node: Node | null, source: string): string | null {\n if (node === null) return null;\n return source.slice(node.start, node.end);\n}\n\nfunction extractParams(params: Node[], source: string): ParamInfo[] {\n return params.map((p) => {\n if (p.type === \"AssignmentPattern\") {\n const left = child(p, \"left\");\n if (left === null) {\n return { name: \"?\", optional: false, hasDefault: true, typeText: null };\n }\n return {\n name: paramName(left, source),\n optional: prop<boolean>(left, \"optional\") === true,\n hasDefault: true,\n typeText: typeText(child(left, \"typeAnnotation\"), source),\n };\n }\n const typeAnno = child(p, \"typeAnnotation\");\n return {\n name: paramName(p, source),\n optional: prop<boolean>(p, \"optional\") === true,\n hasDefault: false,\n typeText: typeText(typeAnno, source),\n };\n });\n}\n\nfunction collectCallSites(node: Node, file: string, source: string, sites: CallSite[]): void {\n if (node.type !== \"CallExpression\") return;\n const callee = child(node, \"callee\");\n let calleeName: string | null = null;\n if (callee !== null && callee.type === \"Identifier\") {\n calleeName = prop<string>(callee, \"name\");\n } else if (callee !== null && callee.type === \"MemberExpression\" && prop<boolean>(callee, \"computed\") !== true) {\n const property = child(callee, \"property\");\n if (property) calleeName = prop<string>(property, \"name\");\n }\n if (calleeName) {\n sites.push({\n calleeName,\n file,\n line: lineAt(source, node.start),\n argCount: children(node, \"arguments\").length,\n node,\n });\n }\n}\n","import { createHash } from \"node:crypto\";\nimport type { Node } from \"oxc-parser\";\nimport { prop, child, children } from \"./narrow.ts\";\n\n/**\n * Create a structural hash of a type node.\n * Normalizes by sorting property names and stripping locations.\n */\nexport function hashTypeShape(node: Node, source: string): string {\n const normalized = normalizeTypeNode(node, source);\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeTypeNode(node: Node, source: string): string {\n if (node.type === \"TSTypeLiteral\") {\n const members = children(node, \"members\");\n const normalized = members.map((m) => normalizeTypeNode(m, source)).sort().join(\";\");\n return `{${normalized}}`;\n }\n if (node.type === \"TSInterfaceBody\") {\n const members = children(node, \"body\");\n const normalized = members.map((m) => normalizeTypeNode(m, source)).sort().join(\";\");\n return `{${normalized}}`;\n }\n if (node.type === \"TSPropertySignature\") {\n const key = child(node, \"key\");\n const rawName = key ? prop<string>(key, \"name\") : undefined;\n const keyName = rawName !== undefined ? rawName : key ? source.slice(key.start, key.end) : \"?\";\n const typeAnno = child(node, \"typeAnnotation\");\n const innerType = typeAnno ? child(typeAnno, \"typeAnnotation\") : null;\n const type = innerType ? normalizeTypeNode(innerType, source) : \"any\";\n const optional = prop<boolean>(node, \"optional\") ? \"?\" : \"\";\n return `${keyName}${optional}:${type}`;\n }\n if (node.type === \"TSTypeAnnotation\") {\n const inner = child(node, \"typeAnnotation\");\n return inner ? normalizeTypeNode(inner, source) : \"any\";\n }\n // Fallback: use source text with whitespace normalized\n return source.slice(node.start, node.end).replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Hash a function body for duplicate detection.\n * Normalizes whitespace.\n */\nexport function hashFunctionBody(node: Node, source: string): string {\n const bodyText = source.slice(node.start, node.end);\n const normalized = bodyText.replace(/\\s+/g, \" \").trim();\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n","import type { Node } from \"oxc-parser\";\nimport { hashTypeShape } from \"../utils/hash.ts\";\n\nexport interface TypeEntry {\n name: string;\n file: string;\n line: number;\n hash: string;\n node: Node;\n exported: boolean;\n}\n\nexport class TypeRegistry {\n private entries: TypeEntry[] = [];\n private byHash = new Map<string, TypeEntry[]>();\n\n add(name: string, file: string, line: number, typeNode: Node, source: string, exported: boolean): void {\n const hash = hashTypeShape(typeNode, source);\n const entry: TypeEntry = { name, file, line, hash, node: typeNode, exported };\n this.entries.push(entry);\n let list = this.byHash.get(hash);\n if (list === undefined) {\n list = [];\n this.byHash.set(hash, list);\n }\n list.push(entry);\n }\n\n getDuplicateGroups(): TypeEntry[][] {\n return [...this.byHash.values()].filter((group) => group.length > 1);\n }\n\n getAll(): TypeEntry[] {\n return this.entries;\n }\n\n getNameCollisionGroups(): TypeEntry[][] {\n const byName = new Map<string, TypeEntry[]>();\n for (const entry of this.entries) {\n if (!entry.exported) continue;\n let list = byName.get(entry.name);\n if (list === undefined) {\n list = [];\n byName.set(entry.name, list);\n }\n list.push(entry);\n }\n return [...byName.values()].filter((group) => {\n if (group.length < 2) return false;\n const files = new Set(group.map((e) => e.file));\n return files.size > 1;\n });\n }\n}\n","import type { Node } from \"oxc-parser\";\n\nexport interface ParamInfo {\n name: string;\n optional: boolean;\n hasDefault: boolean;\n typeText: string | null;\n}\n\nexport interface FunctionEntry {\n name: string;\n file: string;\n line: number;\n hash: string;\n params: ParamInfo[];\n node: Node;\n exported: boolean;\n}\n\nexport class FunctionRegistry {\n private entries: FunctionEntry[] = [];\n private byHash = new Map<string, FunctionEntry[]>();\n\n add(entry: FunctionEntry): void {\n this.entries.push(entry);\n let list = this.byHash.get(entry.hash);\n if (list === undefined) {\n list = [];\n this.byHash.set(entry.hash, list);\n }\n list.push(entry);\n }\n\n getDuplicateGroups(): FunctionEntry[][] {\n return [...this.byHash.values()].filter((group) => group.length > 1);\n }\n\n getAll(): FunctionEntry[] {\n return this.entries;\n }\n\n getByName(name: string): FunctionEntry[] {\n return this.entries.filter((e) => e.name === name);\n }\n\n getNameCollisionGroups(): FunctionEntry[][] {\n const byName = new Map<string, FunctionEntry[]>();\n for (const entry of this.entries) {\n if (!entry.exported) continue;\n let list = byName.get(entry.name);\n if (list === undefined) {\n list = [];\n byName.set(entry.name, list);\n }\n list.push(entry);\n }\n return [...byName.values()].filter((group) => {\n if (group.length < 2) return false;\n const files = new Set(group.map((e) => e.file));\n return files.size > 1;\n });\n }\n}\n"],"mappings":"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","names":["parseSync","walk","readFileSync","readFileSync","parseSync","walk","lineAt"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
scan
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LNO75X5O.js";
|
|
4
4
|
|
|
5
5
|
// src/cli.ts
|
|
6
6
|
import { relative } from "path";
|
|
7
7
|
import pc from "picocolors";
|
|
8
|
+
var SEVERITY_RANK = { info: 0, warning: 1, error: 2 };
|
|
9
|
+
function isSeverity(value) {
|
|
10
|
+
return value === "info" || value === "warning" || value === "error";
|
|
11
|
+
}
|
|
8
12
|
async function main(argv) {
|
|
9
13
|
const args = argv.slice(2);
|
|
10
14
|
const first = args[0];
|
|
@@ -15,22 +19,28 @@ async function main(argv) {
|
|
|
15
19
|
const userArgs = first === "scan" ? args.slice(1) : args;
|
|
16
20
|
const strict = userArgs.includes("--strict");
|
|
17
21
|
const filter = extractFlag(userArgs, "--filter");
|
|
22
|
+
const format = extractFlag(userArgs, "--format", "grouped");
|
|
23
|
+
const severityFilter = extractFlag(userArgs, "--severity");
|
|
18
24
|
const paths = userArgs.filter((a) => !a.startsWith("--"));
|
|
19
25
|
const result = await scan({
|
|
20
26
|
paths,
|
|
21
27
|
strict,
|
|
22
28
|
rules: filter ? [filter] : void 0
|
|
23
29
|
});
|
|
24
|
-
|
|
30
|
+
const minRank = severityFilter !== void 0 && isSeverity(severityFilter) ? SEVERITY_RANK[severityFilter] : 0;
|
|
31
|
+
const filtered = minRank > 0 ? result.diagnostics.filter((d) => SEVERITY_RANK[d.severity] >= minRank) : result.diagnostics;
|
|
32
|
+
if (filtered.length === 0) {
|
|
25
33
|
console.log(pc.green(`No issues found in ${result.fileCount} files.`));
|
|
26
34
|
return 0;
|
|
27
35
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
if (format === "flat") {
|
|
37
|
+
printDiagnosticsFlat(filtered);
|
|
38
|
+
} else {
|
|
39
|
+
printDiagnostics(filtered);
|
|
40
|
+
}
|
|
41
|
+
printSummary(filtered, result.fileCount);
|
|
42
|
+
const hasError = filtered.some((d) => d.severity === "error");
|
|
43
|
+
return hasError ? 2 : 1;
|
|
34
44
|
}
|
|
35
45
|
function printHelp() {
|
|
36
46
|
console.log(`unguard: data-shape static analyzer
|
|
@@ -40,21 +50,40 @@ Usage:
|
|
|
40
50
|
unguard [paths...] [options]
|
|
41
51
|
|
|
42
52
|
Options:
|
|
43
|
-
--strict
|
|
44
|
-
--filter <rule>
|
|
45
|
-
|
|
53
|
+
--strict Treat all warnings as errors
|
|
54
|
+
--filter <rule> Run only the specified rule
|
|
55
|
+
--severity <level> Show only diagnostics at this level or above (error, warning, info)
|
|
56
|
+
--format <mode> Output format: grouped (default) or flat
|
|
57
|
+
-h, --help Show this help
|
|
58
|
+
|
|
59
|
+
Exit codes:
|
|
60
|
+
0 No issues
|
|
61
|
+
1 Warnings or info only
|
|
62
|
+
2 At least one error
|
|
46
63
|
|
|
47
64
|
Examples:
|
|
48
65
|
unguard scan src
|
|
49
66
|
unguard scan src --strict
|
|
50
|
-
unguard scan src --filter no-empty-catch
|
|
67
|
+
unguard scan src --filter no-empty-catch
|
|
68
|
+
unguard scan src --severity=error
|
|
69
|
+
unguard scan src --format=flat | grep error`);
|
|
51
70
|
}
|
|
52
|
-
function extractFlag(args, flag) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
function extractFlag(args, flag, fallback) {
|
|
72
|
+
for (let i = 0; i < args.length; i++) {
|
|
73
|
+
const arg = args[i];
|
|
74
|
+
if (arg === void 0) continue;
|
|
75
|
+
if (arg === flag) {
|
|
76
|
+
const value = args[i + 1];
|
|
77
|
+
args.splice(i, 2);
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
if (arg.startsWith(flag + "=")) {
|
|
81
|
+
const value = arg.slice(flag.length + 1);
|
|
82
|
+
args.splice(i, 1);
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return fallback;
|
|
58
87
|
}
|
|
59
88
|
function printDiagnostics(diagnostics) {
|
|
60
89
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -82,6 +111,15 @@ function printDiagnostics(diagnostics) {
|
|
|
82
111
|
console.log();
|
|
83
112
|
}
|
|
84
113
|
}
|
|
114
|
+
function printDiagnosticsFlat(diagnostics) {
|
|
115
|
+
const cwdBase = process.cwd();
|
|
116
|
+
const cwd = cwdBase + "/";
|
|
117
|
+
for (const d of diagnostics) {
|
|
118
|
+
const rel = relative(cwdBase, d.file);
|
|
119
|
+
const msg = d.message.replaceAll(cwd, "");
|
|
120
|
+
console.log(`${rel}:${d.line}:${d.column} ${d.severity} [${d.ruleId}] ${msg}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
85
123
|
function printSummary(diagnostics, fileCount) {
|
|
86
124
|
const counts = /* @__PURE__ */ new Map();
|
|
87
125
|
for (const d of diagnostics) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { relative } from \"node:path\";\nimport pc from \"picocolors\";\nimport { scan } from \"./engine.ts\";\nimport type { Diagnostic } from \"./rules/types.ts\";\n\nexport async function main(argv: string[]): Promise<number> {\n const args = argv.slice(2);\n const first = args[0];\n\n if (first === \"-h\" || first === \"--help\") {\n printHelp();\n return 0;\n }\n\n const userArgs = first === \"scan\" ? args.slice(1) : args;\n const strict = userArgs.includes(\"--strict\");\n const filter = extractFlag(userArgs, \"--filter\");\n const paths = userArgs.filter((a) => !a.startsWith(\"--\"));\n\n const result = await scan({\n paths,\n strict,\n rules: filter ? [filter] : undefined,\n });\n\n
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { relative } from \"node:path\";\nimport pc from \"picocolors\";\nimport { scan } from \"./engine.ts\";\nimport type { Diagnostic } from \"./rules/types.ts\";\n\ntype Severity = \"info\" | \"warning\" | \"error\";\nconst SEVERITY_RANK: Record<Severity, number> = { info: 0, warning: 1, error: 2 };\n\nfunction isSeverity(value: string): value is Severity {\n return value === \"info\" || value === \"warning\" || value === \"error\";\n}\n\nexport async function main(argv: string[]): Promise<number> {\n const args = argv.slice(2);\n const first = args[0];\n\n if (first === \"-h\" || first === \"--help\") {\n printHelp();\n return 0;\n }\n\n const userArgs = first === \"scan\" ? args.slice(1) : args;\n const strict = userArgs.includes(\"--strict\");\n const filter = extractFlag(userArgs, \"--filter\");\n const format = extractFlag(userArgs, \"--format\", \"grouped\");\n const severityFilter = extractFlag(userArgs, \"--severity\");\n const paths = userArgs.filter((a) => !a.startsWith(\"--\"));\n\n const result = await scan({\n paths,\n strict,\n rules: filter ? [filter] : undefined,\n });\n\n const minRank = severityFilter !== undefined && isSeverity(severityFilter) ? SEVERITY_RANK[severityFilter] : 0;\n const filtered = minRank > 0 ? result.diagnostics.filter((d) => SEVERITY_RANK[d.severity] >= minRank) : result.diagnostics;\n\n if (filtered.length === 0) {\n console.log(pc.green(`No issues found in ${result.fileCount} files.`));\n return 0;\n }\n\n if (format === \"flat\") {\n printDiagnosticsFlat(filtered);\n } else {\n printDiagnostics(filtered);\n }\n printSummary(filtered, result.fileCount);\n\n const hasError = filtered.some((d) => d.severity === \"error\");\n return hasError ? 2 : 1;\n}\n\nfunction printHelp() {\n console.log(`unguard: data-shape static analyzer\n\nUsage:\n unguard scan [paths...] [options]\n unguard [paths...] [options]\n\nOptions:\n --strict Treat all warnings as errors\n --filter <rule> Run only the specified rule\n --severity <level> Show only diagnostics at this level or above (error, warning, info)\n --format <mode> Output format: grouped (default) or flat\n -h, --help Show this help\n\nExit codes:\n 0 No issues\n 1 Warnings or info only\n 2 At least one error\n\nExamples:\n unguard scan src\n unguard scan src --strict\n unguard scan src --filter no-empty-catch\n unguard scan src --severity=error\n unguard scan src --format=flat | grep error`);\n}\n\nfunction extractFlag(args: string[], flag: string, fallback?: string): string | undefined {\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n if (arg === flag) {\n const value = args[i + 1];\n args.splice(i, 2);\n return value;\n }\n if (arg.startsWith(flag + \"=\")) {\n const value = arg.slice(flag.length + 1);\n args.splice(i, 1);\n return value;\n }\n }\n return fallback;\n}\n\nfunction printDiagnostics(diagnostics: Diagnostic[]) {\n const byFile = new Map<string, Diagnostic[]>();\n for (const d of diagnostics) {\n let list = byFile.get(d.file);\n if (list === undefined) {\n list = [];\n byFile.set(d.file, list);\n }\n list.push(d);\n }\n\n const cwd = process.cwd() + \"/\";\n const cwdBase = process.cwd();\n\n for (const [file, diags] of byFile) {\n const rel = relative(cwdBase, file);\n console.log(pc.underline(rel));\n\n for (const d of diags) {\n const loc = `${d.line}:${d.column}`;\n const sev = d.severity === \"error\" ? pc.red(\"error\") : d.severity === \"warning\" ? pc.yellow(\"warning\") : pc.blue(\"info\");\n const msg = d.message.replaceAll(cwd, \"\");\n const rule = pc.dim(d.ruleId);\n const annotation = d.annotation !== undefined ? ` ${pc.cyan(d.annotation)}` : \"\";\n console.log(` ${pc.dim(loc.padEnd(10))} ${sev} ${msg} ${rule}${annotation}`);\n }\n\n console.log();\n }\n}\n\nfunction printDiagnosticsFlat(diagnostics: Diagnostic[]) {\n const cwdBase = process.cwd();\n const cwd = cwdBase + \"/\";\n\n for (const d of diagnostics) {\n const rel = relative(cwdBase, d.file);\n const msg = d.message.replaceAll(cwd, \"\");\n console.log(`${rel}:${d.line}:${d.column} ${d.severity} [${d.ruleId}] ${msg}`);\n }\n}\n\nfunction printSummary(diagnostics: Diagnostic[], fileCount: number) {\n const counts = new Map<string, number>();\n for (const d of diagnostics) {\n const prev = counts.get(d.ruleId);\n counts.set(d.ruleId, (prev === undefined ? 0 : prev) + 1);\n }\n\n const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]);\n const maxRule = Math.max(...sorted.map(([r]) => r.length));\n\n console.log(pc.bold(\"Summary\"));\n for (const [rule, count] of sorted) {\n console.log(` ${rule.padEnd(maxRule)} ${pc.bold(String(count))}`);\n }\n\n console.log(\n `\\n${pc.bold(String(diagnostics.length))} issue${diagnostics.length === 1 ? \"\" : \"s\"} in ${fileCount} files.`,\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/narrow.ts","../src/rules/single-file/no-empty-catch.ts","../src/rules/single-file/no-non-null-assertion.ts","../src/rules/single-file/no-double-negation-coercion.ts","../src/rules/single-file/no-ts-ignore.ts","../src/rules/single-file/no-nullish-coalescing.ts","../src/rules/single-file/no-optional-call.ts","../src/rules/single-file/no-optional-property-access.ts","../src/rules/single-file/no-optional-element-access.ts","../src/utils/ast.ts","../src/rules/single-file/no-logical-or-fallback.ts","../src/rules/single-file/no-null-ternary-normalization.ts","../src/rules/single-file/no-any-cast.ts","../src/rules/single-file/no-explicit-any-annotation.ts","../src/rules/single-file/no-inline-type-in-params.ts","../src/rules/single-file/no-type-assertion.ts","../src/rules/single-file/no-redundant-existence-guard.ts","../src/rules/single-file/prefer-default-param-value.ts","../src/rules/single-file/prefer-required-param-with-guard.ts","../src/rules/cross-file/duplicate-type-declaration.ts","../src/rules/cross-file/duplicate-function-declaration.ts","../src/rules/cross-file/optional-arg-always-used.ts","../src/rules/single-file/no-catch-return.ts","../src/rules/single-file/no-error-rewrap.ts","../src/rules/cross-file/explicit-null-arg.ts","../src/rules/cross-file/duplicate-function-name.ts","../src/rules/cross-file/duplicate-type-name.ts","../src/rules/single-file/no-dynamic-import.ts","../src/rules/index.ts","../src/engine.ts","../src/rules/types.ts","../src/collect/index.ts","../src/utils/hash.ts","../src/collect/type-registry.ts","../src/collect/function-registry.ts"],"sourcesContent":["/**\n * Runtime node property access helpers.\n *\n * oxc-parser's runtime AST diverges from @oxc-project/types in some areas\n * (e.g., all literals use type \"Literal\" at runtime vs NullLiteral/StringLiteral in types).\n * These helpers provide typed access to common node shapes without `as any` casts.\n */\nimport type { Node } from \"oxc-parser\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional escape hatch for untyped AST access\ntype AnyNode = Record<string, any>;\n\n/** Safely access a property on any AST node. */\nexport function prop<T = unknown>(node: Node, key: string): T {\n return (node as AnyNode)[key] as T;\n}\n\n/** Get child node. Returns Node or null. */\nexport function child(node: Node, key: string): Node | null {\n const val = (node as AnyNode)[key];\n if (val === undefined || val === null) return null;\n return val as Node;\n}\n\n/** Get child nodes array. Returns Node[] or empty. */\nexport function children(node: Node, key: string): Node[] {\n const val = (node as AnyNode)[key];\n if (!Array.isArray(val)) return [];\n return val as Node[];\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child, children } from \"../../utils/narrow.ts\";\n\nexport const noEmptyCatch: SingleFileRule = {\n id: \"no-empty-catch\",\n severity: \"error\",\n message: \"Empty catch blocks hide failures; handle, annotate, or rethrow explicitly\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CatchClause\") return;\n const body = child(node, \"body\");\n if (body && body.type === \"BlockStatement\" && children(body, \"body\").length === 0) {\n const hasComment = ctx.comments.some((c) => c.start >= body.start && c.end <= body.end);\n if (hasComment) return;\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noNonNullAssertion: SingleFileRule = {\n id: \"no-non-null-assertion\",\n severity: \"warning\",\n message: \"Non-null assertion (!) overrides the type checker; narrow with a type guard or fix the type so it's not nullable\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSNonNullExpression\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child } from \"../../utils/narrow.ts\";\n\nexport const noDoubleNegationCoercion: SingleFileRule = {\n id: \"no-double-negation-coercion\",\n severity: \"info\",\n message: \"!! coercion hides intent; use an explicit check (!== null, !== undefined, .length > 0) so the condition documents what it tests\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"UnaryExpression\") return;\n if (prop<string>(node, \"operator\") !== \"!\") return;\n const arg = child(node, \"argument\");\n if (arg !== null && arg.type === \"UnaryExpression\" && prop<string>(arg, \"operator\") === \"!\") {\n ctx.report(node);\n }\n },\n};\n","import type { Node, Comment } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noTsIgnore: SingleFileRule = {\n id: \"no-ts-ignore\",\n severity: \"error\",\n message: \"@ts-ignore / @ts-expect-error suppresses type checking; fix the underlying type issue\",\n\n visit(_node: Node, _parent: Node | null, _ctx: VisitContext) {},\n\n visitComment(comment: Comment, ctx: VisitContext) {\n if (comment.value.includes(\"@ts-ignore\") || comment.value.includes(\"@ts-expect-error\")) {\n ctx.report(comment);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noNullishCoalescing: SingleFileRule = {\n id: \"no-nullish-coalescing\",\n severity: \"warning\",\n message: \"Nullish coalescing (??) masks a possibly-nullable type; if the type guarantees non-null, remove the fallback; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"LogicalExpression\") return;\n if (prop<string>(node, \"operator\") !== \"??\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noOptionalCall: SingleFileRule = {\n id: \"no-optional-call\",\n severity: \"info\",\n message: \"Optional call (?.) assumes the function could be undefined; if the type guarantees it exists, call directly; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CallExpression\") return;\n if (!prop<boolean>(node, \"optional\")) return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noOptionalPropertyAccess: SingleFileRule = {\n id: \"no-optional-property-access\",\n severity: \"info\",\n message: \"Optional chaining (?.) assumes the object could be nullish; if the type guarantees it, use a direct access; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"MemberExpression\") return;\n if (prop<boolean>(node, \"optional\") && !prop<boolean>(node, \"computed\")) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop } from \"../../utils/narrow.ts\";\n\nexport const noOptionalElementAccess: SingleFileRule = {\n id: \"no-optional-element-access\",\n severity: \"info\",\n message: \"Optional element access (?.[]) assumes the object could be nullish; if the type guarantees it, use a direct access; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"MemberExpression\") return;\n if (prop<boolean>(node, \"optional\") && prop<boolean>(node, \"computed\")) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport { prop } from \"./narrow.ts\";\n\n/** Check if a node is null or undefined literal. */\nexport function isNullish(node: Node): boolean {\n if (node.type === \"Literal\" && prop(node, \"value\") === null) return true;\n if (node.type === \"Identifier\" && prop<string>(node, \"name\") === \"undefined\") return true;\n return false;\n}\n\n/** Check if a node is a literal value. */\nexport function isLiteral(node: Node): boolean {\n switch (node.type) {\n case \"Literal\":\n case \"TemplateLiteral\":\n case \"ArrayExpression\":\n case \"ObjectExpression\":\n return true;\n case \"Identifier\":\n return prop<string>(node, \"name\") === \"undefined\";\n default:\n return false;\n }\n}\n\n/** Get source text for a node using its span. */\nexport function getNodeText(source: string, node: Node): string {\n return source.slice(node.start, node.end);\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child } from \"../../utils/narrow.ts\";\nimport { isLiteral } from \"../../utils/ast.ts\";\n\nexport const noLogicalOrFallback: SingleFileRule = {\n id: \"no-logical-or-fallback\",\n severity: \"warning\",\n message: \"|| with a literal fallback assumes the left side could be falsy; if the type guarantees a value, remove the fallback; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"LogicalExpression\") return;\n if (prop<string>(node, \"operator\") !== \"||\") return;\n const right = child(node, \"right\");\n if (right && isLiteral(right)) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child } from \"../../utils/narrow.ts\";\nimport { isNullish } from \"../../utils/ast.ts\";\n\nexport const noNullTernaryNormalization: SingleFileRule = {\n id: \"no-null-ternary-normalization\",\n severity: \"warning\",\n message: \"Ternary null-normalization (x == null ? fallback : x); if the type guarantees non-null, remove the ternary; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"ConditionalExpression\") return;\n const test = child(node, \"test\");\n if (test === null || test.type !== \"BinaryExpression\") return;\n const op = prop<string>(test, \"operator\");\n if (op !== \"===\" && op !== \"!==\" && op !== \"==\" && op !== \"!=\") return;\n const testLeft = child(test, \"left\");\n const testRight = child(test, \"right\");\n const hasNullishComparand =\n (testLeft !== null && isNullish(testLeft)) || (testRight !== null && isNullish(testRight));\n if (!hasNullishComparand) return;\n const consequent = child(node, \"consequent\");\n const alternate = child(node, \"alternate\");\n if ((consequent !== null && isNullish(consequent)) || (alternate !== null && isNullish(alternate))) {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child } from \"../../utils/narrow.ts\";\n\nexport const noAnyCast: SingleFileRule = {\n id: \"no-any-cast\",\n severity: \"error\",\n message: \"Casting to `any` erases type safety; use a specific type or generic instead\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSAsExpression\") return;\n const typeAnno = child(node, \"typeAnnotation\");\n if (typeAnno !== null && typeAnno.type === \"TSAnyKeyword\") {\n ctx.report(node);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noExplicitAnyAnnotation: SingleFileRule = {\n id: \"no-explicit-any-annotation\",\n severity: \"warning\",\n message: \"Explicit `any` annotation erases type safety; use a specific type, `unknown`, or a generic\",\n\n visit(node: Node, parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSAnyKeyword\") return;\n // Skip if inside a cast (covered by no-any-cast)\n if (parent !== null && parent.type === \"TSAsExpression\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noInlineTypeInParams: SingleFileRule = {\n id: \"no-inline-type-in-params\",\n severity: \"warning\",\n message: \"Inline type literal in annotation; extract to a named type for reuse and clarity\",\n\n visit(node: Node, parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSTypeLiteral\") return;\n if (parent === null || parent.type !== \"TSTypeAnnotation\") return;\n\n if (!isTopLevelFunctionParam(ctx.source, node.start)) return;\n\n ctx.report(node);\n },\n};\n\nfunction isTopLevelFunctionParam(source: string, offset: number): boolean {\n // Only flag if the nearest enclosing \"{\" is the module scope (no enclosing brace)\n // or a plain function body. Skip anything nested inside classes, interfaces,\n // object literals (builder patterns), etc.\n let depth = 0;\n for (let i = offset - 1; i >= 0; i--) {\n if (source[i] === \"}\") depth++;\n if (source[i] === \"{\") {\n if (depth === 0) {\n // Found the enclosing \"{\". If it belongs to a function declaration\n // or arrow, that's fine (we're in a nested function param). But if\n // it's anything else (class, interface, object literal), skip.\n // In practice: only flag when there's NO enclosing \"{\" at all\n // (module-level function), or the enclosing block is a function body.\n const before = source.slice(Math.max(0, i - 150), i).trimEnd();\n // Function body: preceded by \")\" or \"=> {\" or similar\n if (/(\\)|\\bfunction\\b.*\\))\\s*$/.test(before)) {\n // Inside a function body — keep walking to check if that function\n // is itself top-level or nested\n depth--;\n continue;\n }\n // Anything else (class, interface, object, etc.) — not top-level\n return false;\n }\n depth--;\n }\n }\n // Reached beginning of file with no unmatched \"{\" — module scope\n return true;\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child } from \"../../utils/narrow.ts\";\n\nexport const noTypeAssertion: SingleFileRule = {\n id: \"no-type-assertion\",\n severity: \"error\",\n message: \"Double type assertion (`as unknown as T`) circumvents the type system; fix the upstream type or use a type guard\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"TSAsExpression\") return;\n // Check if the expression being cast is itself an `as unknown`\n const inner = child(node, \"expression\");\n if (inner === null || inner.type !== \"TSAsExpression\") return;\n const innerType = child(inner, \"typeAnnotation\");\n if (innerType === null || innerType.type !== \"TSUnknownKeyword\") return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child, prop } from \"../../utils/narrow.ts\";\n\nexport const noRedundantExistenceGuard: SingleFileRule = {\n id: \"no-redundant-existence-guard\",\n severity: \"warning\",\n message: \"Redundant existence guard (obj && obj.prop); if the type guarantees obj exists, remove the guard; if not, fix the type upstream\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"IfStatement\") return;\n const test = child(node, \"test\");\n if (!test || test.type !== \"LogicalExpression\" || prop<string>(test, \"operator\") !== \"&&\") return;\n\n const left = child(test, \"left\");\n const right = child(test, \"right\");\n if (!left || left.type !== \"Identifier\") return;\n if (!right || right.type !== \"MemberExpression\") return;\n const obj = child(right, \"object\");\n if (!obj || obj.type !== \"Identifier\") return;\n if (prop<string>(left, \"name\") !== prop<string>(obj, \"name\")) return;\n ctx.report(node);\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child, children } from \"../../utils/narrow.ts\";\n\nexport const preferDefaultParamValue: SingleFileRule = {\n id: \"prefer-default-param-value\",\n severity: \"info\",\n message: \"Use a default parameter value instead of reassigning from nullish coalescing inside the body\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"FunctionDeclaration\" && node.type !== \"ArrowFunctionExpression\") return;\n const params = children(node, \"params\");\n const body = child(node, \"body\");\n if (body === null || body.type !== \"BlockStatement\") return;\n const stmts = children(body, \"body\");\n if (stmts.length === 0) return;\n\n const firstStmt = stmts[0];\n if (firstStmt.type !== \"ExpressionStatement\") return;\n const expr = child(firstStmt, \"expression\");\n if (expr === null || expr.type !== \"AssignmentExpression\" || prop<string>(expr, \"operator\") !== \"=\") return;\n\n const right = child(expr, \"right\");\n if (right === null || right.type !== \"LogicalExpression\" || prop<string>(right, \"operator\") !== \"??\") return;\n\n const assignee = child(expr, \"left\");\n const coalescedLeft = child(right, \"left\");\n if (assignee === null || assignee.type !== \"Identifier\") return;\n if (coalescedLeft === null || coalescedLeft.type !== \"Identifier\") return;\n if (prop<string>(assignee, \"name\") !== prop<string>(coalescedLeft, \"name\")) return;\n\n const assigneeName = prop<string>(assignee, \"name\");\n const isParam = params.some((p: Node) => {\n if (p.type === \"Identifier\") return prop<string>(p, \"name\") === assigneeName;\n if (p.type === \"AssignmentPattern\") {\n const left = child(p, \"left\");\n return left !== null && left.type === \"Identifier\" && prop<string>(left, \"name\") === assigneeName;\n }\n return false;\n });\n if (isParam) {\n ctx.report(firstStmt);\n }\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child, children } from \"../../utils/narrow.ts\";\n\nexport const preferRequiredParamWithGuard: SingleFileRule = {\n id: \"prefer-required-param-with-guard\",\n severity: \"info\",\n message: \"Optional param with immediate guard (if (!param) return/throw); make it required instead\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"FunctionDeclaration\" && node.type !== \"ArrowFunctionExpression\") return;\n const params = children(node, \"params\");\n const body = child(node, \"body\");\n if (body === null || body.type !== \"BlockStatement\") return;\n const stmts = children(body, \"body\");\n if (stmts.length === 0) return;\n\n const firstStmt = stmts[0];\n if (firstStmt.type !== \"IfStatement\") return;\n\n const test = child(firstStmt, \"test\");\n if (test === null) return;\n let guardedName: string | null = null;\n\n // Pattern 1: if (!param)\n if (test.type === \"UnaryExpression\" && prop<string>(test, \"operator\") === \"!\") {\n const arg = child(test, \"argument\");\n if (arg !== null && arg.type === \"Identifier\") guardedName = prop<string>(arg, \"name\");\n }\n // Pattern 2: if (param === undefined)\n if (test.type === \"BinaryExpression\") {\n const op = prop<string>(test, \"operator\");\n if (op === \"===\" || op === \"==\") {\n const left = child(test, \"left\");\n const right = child(test, \"right\");\n if (\n left !== null &&\n left.type === \"Identifier\" &&\n right !== null &&\n right.type === \"Identifier\" &&\n prop<string>(right, \"name\") === \"undefined\"\n ) {\n guardedName = prop<string>(left, \"name\");\n }\n }\n }\n\n if (guardedName === null) return;\n\n const consequent = child(firstStmt, \"consequent\");\n if (consequent === null) return;\n const isGuard =\n consequent.type === \"ReturnStatement\" ||\n consequent.type === \"ThrowStatement\" ||\n (consequent.type === \"BlockStatement\" && isGuardBlock(consequent));\n\n if (!isGuard) return;\n\n const isOptionalParam = params.some(\n (p: Node) => p.type === \"Identifier\" && prop<string>(p, \"name\") === guardedName && prop<boolean>(p, \"optional\") === true,\n );\n if (isOptionalParam) {\n ctx.report(firstStmt);\n }\n },\n};\n\nfunction isGuardBlock(block: Node): boolean {\n const body = children(block, \"body\");\n if (body.length !== 1) return false;\n const stmt = body[0];\n return stmt.type === \"ReturnStatement\" || stmt.type === \"ThrowStatement\";\n}\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateTypeDeclaration: CrossFileRule = {\n id: \"duplicate-type-declaration\",\n severity: \"warning\",\n message: \"Identical type shape declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.types.getDuplicateGroups()) {\n // Only flag if types are in different files\n const files = new Set(group.map((e) => e.file));\n if (files.size < 2) continue;\n\n for (const entry of group) {\n const others = group\n .filter((e) => e !== entry)\n .map((e) => `${e.name} (${e.file}:${e.line})`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Type \"${entry.name}\" has identical shape to: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateFunctionDeclaration: CrossFileRule = {\n id: \"duplicate-function-declaration\",\n severity: \"warning\",\n message: \"Identical function body declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.functions.getDuplicateGroups()) {\n const files = new Set(group.map((e) => e.file));\n if (files.size < 2) continue;\n\n for (const entry of group) {\n const others = group\n .filter((e) => e !== entry)\n .map((e) => `${e.name} (${e.file}:${e.line})`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Function \"${entry.name}\" has identical body to: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const optionalArgAlwaysUsed: CrossFileRule = {\n id: \"optional-arg-always-used\",\n severity: \"warning\",\n message: \"Optional parameter is always provided at every call site; make it required\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n for (const fn of project.functions.getAll()) {\n // Find optional params (by index)\n for (let i = 0; i < fn.params.length; i++) {\n const param = fn.params[i];\n if (!param.optional && !param.hasDefault) continue;\n\n // Find all call sites matching this function name\n const callSites = project.callSites.filter((c) => c.calleeName === fn.name);\n\n // Need at least 2 call sites to be meaningful\n if (callSites.length < 2) continue;\n\n // Check if every call site provides this positional argument\n const allProvide = callSites.every((c) => c.argCount > i);\n if (allProvide) {\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Optional parameter \"${param.name}\" is always provided at all ${callSites.length} call sites; make it required`,\n file: fn.file,\n line: fn.line,\n column: 1,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { child, prop } from \"../../utils/narrow.ts\";\n\nexport const noCatchReturn: SingleFileRule = {\n id: \"no-catch-return\",\n severity: \"warning\",\n message:\n \"Catch block returns a fallback value, forcing callers to handle two data shapes; rethrow or let the error propagate\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CatchClause\") return;\n const body = child(node, \"body\");\n if (body === null) return;\n if (hasReturn(body) && !hasThrow(body)) {\n ctx.report(node);\n }\n },\n};\n\nfunction hasReturn(block: Node): boolean {\n return walkForType(block, \"ReturnStatement\");\n}\n\nfunction hasThrow(block: Node): boolean {\n return walkForType(block, \"ThrowStatement\");\n}\n\nfunction walkForType(root: Node, targetType: string): boolean {\n if (root.type === targetType) return true;\n const keys = Object.keys(root);\n for (const key of keys) {\n if (key === \"start\" || key === \"end\" || key === \"type\") continue;\n const val = prop<unknown>(root, key);\n if (val === null || val === undefined || typeof val !== \"object\") continue;\n // Skip nested function scopes — their returns/throws are their own\n if (isFunction(val as Node)) continue;\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item !== null && typeof item === \"object\" && \"type\" in item) {\n if (isFunction(item as Node)) continue;\n if (walkForType(item as Node, targetType)) return true;\n }\n }\n } else if (\"type\" in val) {\n if (walkForType(val as Node, targetType)) return true;\n }\n }\n return false;\n}\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === \"FunctionDeclaration\" ||\n node.type === \"FunctionExpression\" ||\n node.type === \"ArrowFunctionExpression\"\n );\n}\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\nimport { prop, child, children } from \"../../utils/narrow.ts\";\n\nexport const noErrorRewrap: SingleFileRule = {\n id: \"no-error-rewrap\",\n severity: \"error\",\n message:\n \"Re-wrapped error loses the original stack trace and type; use { cause: originalError } to preserve the error chain\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"CatchClause\") return;\n const param = child(node, \"param\");\n if (param === null || param.type !== \"Identifier\") return;\n const catchName = prop<string>(param, \"name\");\n const body = child(node, \"body\");\n if (body === null) return;\n findRewraps(body, catchName, ctx);\n },\n};\n\nfunction findRewraps(root: Node, catchName: string, ctx: VisitContext): void {\n if (root.type === \"ThrowStatement\") {\n const arg = child(root, \"argument\");\n if (arg !== null && arg.type === \"NewExpression\") {\n const args = children(arg, \"arguments\");\n if (args.length > 0 && referencesName(args, catchName) && !hasCauseArg(args)) {\n ctx.report(root);\n }\n }\n return;\n }\n // Skip nested function scopes\n if (\n root.type === \"FunctionDeclaration\" ||\n root.type === \"FunctionExpression\" ||\n root.type === \"ArrowFunctionExpression\"\n ) {\n return;\n }\n const keys = Object.keys(root);\n for (const key of keys) {\n if (key === \"start\" || key === \"end\" || key === \"type\") continue;\n const val = prop<unknown>(root, key);\n if (val === null || val === undefined || typeof val !== \"object\") continue;\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item !== null && typeof item === \"object\" && \"type\" in item) {\n findRewraps(item as Node, catchName, ctx);\n }\n }\n } else if (\"type\" in val) {\n findRewraps(val as Node, catchName, ctx);\n }\n }\n}\n\nfunction referencesName(nodes: Node[], name: string): boolean {\n for (const node of nodes) {\n if (containsIdentifier(node, name)) return true;\n }\n return false;\n}\n\nfunction containsIdentifier(root: Node, name: string): boolean {\n if (root.type === \"Identifier\" && prop<string>(root, \"name\") === name) return true;\n const keys = Object.keys(root);\n for (const key of keys) {\n if (key === \"start\" || key === \"end\" || key === \"type\") continue;\n const val = prop<unknown>(root, key);\n if (val === null || val === undefined || typeof val !== \"object\") continue;\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item !== null && typeof item === \"object\" && \"type\" in item) {\n if (containsIdentifier(item as Node, name)) return true;\n }\n }\n } else if (\"type\" in val) {\n if (containsIdentifier(val as Node, name)) return true;\n }\n }\n return false;\n}\n\nfunction hasCauseArg(args: Node[]): boolean {\n for (const arg of args) {\n if (arg.type === \"ObjectExpression\") {\n const props = children(arg, \"properties\");\n for (const p of props) {\n const key = child(p, \"key\");\n if (key !== null && key.type === \"Identifier\" && prop<string>(key, \"name\") === \"cause\") {\n return true;\n }\n }\n }\n }\n return false;\n}\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\nimport { children } from \"../../utils/narrow.ts\";\nimport { isNullish } from \"../../utils/ast.ts\";\n\nexport const explicitNullArg: CrossFileRule = {\n id: \"explicit-null-arg\",\n severity: \"warning\",\n message: \"Explicit null/undefined passed to a project function; consider redesigning the interface to not accept nullish values\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n // Build a set of known project function names for fast lookup\n const projectFnNames = new Set<string>();\n for (const fn of project.functions.getAll()) {\n projectFnNames.add(fn.name);\n }\n\n for (const site of project.callSites) {\n // Only flag calls to functions defined in the project\n if (!projectFnNames.has(site.calleeName)) continue;\n\n const args = children(site.node, \"arguments\");\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n if (isNullish(arg)) {\n const val = arg.type === \"Literal\" ? \"null\" : \"undefined\";\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Passing explicit ${val} to \"${site.calleeName}\" at argument ${i + 1}; consider redesigning the interface to not accept nullish values`,\n file: site.file,\n line: site.line,\n column: 1,\n });\n break; // one diagnostic per call site\n }\n }\n }\n\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateFunctionName: CrossFileRule = {\n id: \"duplicate-function-name\",\n severity: \"warning\",\n message: \"Same function name exported from multiple files; consolidate or rename to avoid ambiguity\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.functions.getNameCollisionGroups()) {\n // Skip groups already caught by duplicate-function-declaration (identical bodies)\n const hashes = new Set(group.map((e) => e.hash));\n if (hashes.size === 1) continue;\n\n for (const entry of group) {\n const others = group\n .filter((e) => e !== entry)\n .map((e) => `${e.file}:${e.line}`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Exported function \"${entry.name}\" also defined in: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateTypeName: CrossFileRule = {\n id: \"duplicate-type-name\",\n severity: \"warning\",\n message: \"Same type name exported from multiple files; consolidate or rename to avoid ambiguity\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.types.getNameCollisionGroups()) {\n // Skip groups already caught by duplicate-type-declaration (identical shapes)\n const hashes = new Set(group.map((e) => e.hash));\n if (hashes.size === 1) continue;\n\n for (const entry of group) {\n const others = group\n .filter((e) => e !== entry)\n .map((e) => `${e.file}:${e.line}`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Exported type \"${entry.name}\" also defined in: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import type { Node } from \"oxc-parser\";\nimport type { SingleFileRule, VisitContext } from \"../types.ts\";\n\nexport const noDynamicImport: SingleFileRule = {\n id: \"no-dynamic-import\",\n severity: \"error\",\n message: \"Dynamic import() breaks static analysis and hides dependencies; use a static import instead\",\n\n visit(node: Node, _parent: Node | null, ctx: VisitContext) {\n if (node.type !== \"ImportExpression\") return;\n ctx.report(node);\n },\n};\n","import type { Rule } from \"./types.ts\";\n\nimport { noEmptyCatch } from \"./single-file/no-empty-catch.ts\";\nimport { noNonNullAssertion } from \"./single-file/no-non-null-assertion.ts\";\nimport { noDoubleNegationCoercion } from \"./single-file/no-double-negation-coercion.ts\";\nimport { noTsIgnore } from \"./single-file/no-ts-ignore.ts\";\nimport { noNullishCoalescing } from \"./single-file/no-nullish-coalescing.ts\";\nimport { noOptionalCall } from \"./single-file/no-optional-call.ts\";\nimport { noOptionalPropertyAccess } from \"./single-file/no-optional-property-access.ts\";\nimport { noOptionalElementAccess } from \"./single-file/no-optional-element-access.ts\";\nimport { noLogicalOrFallback } from \"./single-file/no-logical-or-fallback.ts\";\nimport { noNullTernaryNormalization } from \"./single-file/no-null-ternary-normalization.ts\";\nimport { noAnyCast } from \"./single-file/no-any-cast.ts\";\nimport { noExplicitAnyAnnotation } from \"./single-file/no-explicit-any-annotation.ts\";\nimport { noInlineTypeInParams } from \"./single-file/no-inline-type-in-params.ts\";\nimport { noTypeAssertion } from \"./single-file/no-type-assertion.ts\";\nimport { noRedundantExistenceGuard } from \"./single-file/no-redundant-existence-guard.ts\";\nimport { preferDefaultParamValue } from \"./single-file/prefer-default-param-value.ts\";\nimport { preferRequiredParamWithGuard } from \"./single-file/prefer-required-param-with-guard.ts\";\nimport { duplicateTypeDeclaration } from \"./cross-file/duplicate-type-declaration.ts\";\nimport { duplicateFunctionDeclaration } from \"./cross-file/duplicate-function-declaration.ts\";\nimport { optionalArgAlwaysUsed } from \"./cross-file/optional-arg-always-used.ts\";\nimport { noCatchReturn } from \"./single-file/no-catch-return.ts\";\nimport { noErrorRewrap } from \"./single-file/no-error-rewrap.ts\";\nimport { explicitNullArg } from \"./cross-file/explicit-null-arg.ts\";\nimport { duplicateFunctionName } from \"./cross-file/duplicate-function-name.ts\";\nimport { duplicateTypeName } from \"./cross-file/duplicate-type-name.ts\";\nimport { noDynamicImport } from \"./single-file/no-dynamic-import.ts\";\n\nexport const allRules: Rule[] = [\n noEmptyCatch,\n noNonNullAssertion,\n noDoubleNegationCoercion,\n noTsIgnore,\n noNullishCoalescing,\n noOptionalCall,\n noOptionalPropertyAccess,\n noOptionalElementAccess,\n noLogicalOrFallback,\n noNullTernaryNormalization,\n noAnyCast,\n noExplicitAnyAnnotation,\n noInlineTypeInParams,\n noTypeAssertion,\n noRedundantExistenceGuard,\n preferDefaultParamValue,\n preferRequiredParamWithGuard,\n duplicateTypeDeclaration,\n duplicateFunctionDeclaration,\n optionalArgAlwaysUsed,\n noCatchReturn,\n noErrorRewrap,\n explicitNullArg,\n duplicateFunctionName,\n duplicateTypeName,\n noDynamicImport,\n];\n","import { parseSync, type Comment } from \"oxc-parser\";\nimport { walk } from \"oxc-walker\";\nimport fg from \"fast-glob\";\nimport { readFileSync } from \"node:fs\";\nimport type { Node } from \"oxc-parser\";\nimport type { Diagnostic, SingleFileRule, CrossFileRule, Span, VisitContext } from \"./rules/types.ts\";\nimport { allRules } from \"./rules/index.ts\";\nimport { isSingleFileRule } from \"./rules/types.ts\";\nimport { collectProject } from \"./collect/index.ts\";\n\nexport interface ScanOptions {\n paths: string[];\n strict?: boolean;\n rules?: string[];\n}\n\nexport interface ScanResult {\n diagnostics: Diagnostic[];\n fileCount: number;\n}\n\nexport async function scan(options: ScanOptions): Promise<ScanResult> {\n const patterns = options.paths.length > 0 ? options.paths : [\".\"];\n const globs = patterns.map((p) => {\n if (p === \".\") return `./**/*.{ts,cts,mts,tsx}`;\n if (p.endsWith(\"/\")) return `${p}**/*.{ts,cts,mts,tsx}`;\n if (!p.includes(\"*\") && !p.endsWith(\".ts\") && !p.endsWith(\".tsx\") && !p.endsWith(\".cts\") && !p.endsWith(\".mts\")) {\n return `${p}/**/*.{ts,cts,mts,tsx}`;\n }\n return p;\n });\n\n const files = await fg(globs, {\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\", \"**/*.d.ts\", \"**/*.d.cts\", \"**/*.d.mts\"],\n absolute: true,\n });\n\n const activeRules = allRules.filter((r) => {\n if (options.rules && !options.rules.includes(r.id)) return false;\n return true;\n });\n\n const singleFileRules = activeRules.filter(isSingleFileRule);\n const crossFileRules = activeRules.filter((r): r is CrossFileRule => !isSingleFileRule(r));\n const diagnostics: Diagnostic[] = [];\n\n // Single-file pass: parse each file and run visitor rules\n for (const file of files) {\n const source = readFileSync(file, \"utf8\");\n const result = parseSync(file, source);\n const fileDiags = runSingleFileRules(singleFileRules, result.program, result.comments, source, file);\n annotate(fileDiags, result.comments, source);\n diagnostics.push(...fileDiags);\n }\n\n // Cross-file pass: collect project index and run analysis rules\n if (crossFileRules.length > 0 && files.length > 0) {\n const projectIndex = collectProject(files);\n for (const rule of crossFileRules) {\n const crossDiags = rule.analyze(projectIndex);\n for (const d of crossDiags) {\n const fileData = projectIndex.files.get(d.file);\n if (fileData !== undefined) annotate([d], fileData.comments, fileData.source);\n }\n diagnostics.push(...crossDiags);\n }\n }\n\n const seen = new Set<string>();\n const deduped: Diagnostic[] = [];\n for (const d of diagnostics) {\n const key = `${d.file}:${d.line}:${d.ruleId}`;\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(d);\n }\n\n if (options.strict) {\n for (const d of deduped) {\n d.severity = \"error\";\n }\n }\n\n return { diagnostics: deduped, fileCount: files.length };\n}\n\nexport function runSingleFileRules(\n rules: SingleFileRule[],\n program: Node,\n comments: Comment[],\n source: string,\n filename: string,\n): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n const makeCtx = (rule: SingleFileRule): VisitContext => ({\n filename,\n source,\n comments,\n report(span: Span, message?: string) {\n const pos = lineCol(source, span.start);\n diagnostics.push({\n ruleId: rule.id,\n severity: rule.severity,\n message: message === undefined ? rule.message : message,\n file: filename,\n ...pos,\n });\n },\n });\n\n const contexts = rules.map((r) => ({ rule: r, ctx: makeCtx(r) }));\n\n walk(program, {\n enter(node: Node, parent: Node | null) {\n for (const { rule, ctx } of contexts) {\n rule.visit(node, parent, ctx);\n }\n },\n });\n\n for (const { rule, ctx } of contexts) {\n if (rule.visitComment) {\n for (const comment of comments) {\n rule.visitComment(comment, ctx);\n }\n }\n }\n\n return diagnostics;\n}\n\ninterface Position {\n line: number;\n column: number;\n}\n\n/**\n * Attach annotations from comments to diagnostics.\n * A comment annotates a diagnostic if it ends on the line immediately above.\n * Consecutive line comments are joined into a single annotation.\n */\nfunction annotate(diagnostics: Diagnostic[], comments: Comment[], source: string): void {\n if (comments.length === 0 || diagnostics.length === 0) return;\n\n // Build a map: endLine -> comment\n const byEndLine = new Map<number, Comment[]>();\n for (const c of comments) {\n const endLine = lineAt(source, c.end);\n let list = byEndLine.get(endLine);\n if (list === undefined) {\n list = [];\n byEndLine.set(endLine, list);\n }\n list.push(c);\n }\n\n for (const d of diagnostics) {\n // Check inline comment on the same line first\n const inline = findInlineComment(d.line, byEndLine);\n if (inline !== null) {\n d.annotation = inline;\n continue;\n }\n // Then check comment(s) on the line above\n const above = collectAnnotation(d.line - 1, byEndLine, source);\n if (above !== null) d.annotation = above;\n }\n}\n\nfunction findInlineComment(diagLine: number, byEndLine: Map<number, Comment[]>): string | null {\n const commentsOnLine = byEndLine.get(diagLine);\n if (commentsOnLine === undefined || commentsOnLine.length === 0) return null;\n const comment = commentsOnLine.at(-1);\n if (comment === undefined) return null;\n // Only line comments (// ...) count as inline annotations, not block comments\n if (comment.type !== \"Line\") return null;\n const text = comment.value.trim();\n // Skip @expect annotations — those are for the test harness, not user annotations\n if (text.startsWith(\"@expect\")) return null;\n return text;\n}\n\nfunction collectAnnotation(\n commentEndLine: number,\n byEndLine: Map<number, Comment[]>,\n source: string,\n): string | null {\n const commentsOnLine = byEndLine.get(commentEndLine);\n if (commentsOnLine === undefined || commentsOnLine.length === 0) return null;\n const comment = commentsOnLine.at(-1);\n if (comment === undefined) return null;\n\n // Block comment: use its value directly\n if (comment.type === \"Block\") {\n return cleanBlockComment(comment.value);\n }\n\n // Line comment: walk upward to collect consecutive line comments\n const lines: string[] = [comment.value.trim()];\n let prevLine = commentEndLine - 1;\n for (;;) {\n const prev = byEndLine.get(prevLine);\n if (prev === undefined || prev.length === 0) break;\n const prevComment = prev.at(-1);\n if (prevComment === undefined || prevComment.type !== \"Line\") break;\n if (lineAt(source, prevComment.start) !== prevLine) break;\n lines.unshift(prevComment.value.trim());\n prevLine--;\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction cleanBlockComment(value: string): string {\n return value\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*\\*\\s?/, \"\").trim())\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n}\n\nfunction lineAt(source: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset && i < source.length; i++) {\n if (source[i] === \"\\n\") line++;\n }\n return line;\n}\n\nfunction lineCol(source: string, offset: number): Position {\n let line = 1;\n let col = 1;\n for (let i = 0; i < offset && i < source.length; i++) {\n if (source[i] === \"\\n\") {\n line++;\n col = 1;\n } else {\n col++;\n }\n }\n return { line, column: col };\n}\n","import type { Node, Comment } from \"oxc-parser\";\n\nexport interface Diagnostic {\n ruleId: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n file: string;\n line: number;\n column: number;\n annotation?: string;\n}\n\nexport interface Span {\n start: number;\n end: number;\n}\n\nexport interface VisitContext {\n report(span: Span, message?: string): void;\n filename: string;\n source: string;\n comments: Comment[];\n}\n\nexport interface SingleFileRule {\n id: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n visit(node: Node, parent: Node | null, ctx: VisitContext): void;\n visitComment?(comment: Comment, ctx: VisitContext): void;\n}\n\nimport type { ProjectIndex } from \"../collect/index.ts\";\nexport type { ProjectIndex };\n\nexport interface CrossFileRule {\n id: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n analyze(project: ProjectIndex): Diagnostic[];\n}\n\nexport type Rule = SingleFileRule | CrossFileRule;\n\nexport function isSingleFileRule(r: Rule): r is SingleFileRule {\n return \"visit\" in r;\n}\n","import { parseSync, type Comment } from \"oxc-parser\";\nimport { walk } from \"oxc-walker\";\nimport { readFileSync } from \"node:fs\";\nimport type { Node } from \"oxc-parser\";\nimport { TypeRegistry } from \"./type-registry.ts\";\nimport { FunctionRegistry, type FunctionEntry, type ParamInfo } from \"./function-registry.ts\";\nimport { hashFunctionBody } from \"../utils/hash.ts\";\nimport { prop, child, children } from \"../utils/narrow.ts\";\n\nexport interface ProjectIndex {\n types: TypeRegistry;\n functions: FunctionRegistry;\n callSites: CallSite[];\n files: Map<string, { source: string; program: Node; comments: Comment[] }>;\n}\n\nexport interface CallSite {\n calleeName: string;\n file: string;\n line: number;\n argCount: number;\n node: Node;\n}\n\nexport function collectProject(files: string[]): ProjectIndex {\n const types = new TypeRegistry();\n const functions = new FunctionRegistry();\n const callSites: CallSite[] = [];\n const fileMap = new Map<string, { source: string; program: Node; comments: Comment[] }>();\n\n for (const file of files) {\n const source = readFileSync(file, \"utf8\");\n const result = parseSync(file, source);\n fileMap.set(file, { source, program: result.program, comments: result.comments });\n\n walk(result.program, {\n enter(node: Node, parent: Node | null) {\n collectTypes(node, parent, file, source, types);\n collectFunctions(node, parent, file, source, functions);\n collectCallSites(node, file, source, callSites);\n },\n });\n }\n\n return { types, functions, callSites, files: fileMap };\n}\n\nfunction lineAt(source: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset; i++) {\n if (source[i] === \"\\n\") line++;\n }\n return line;\n}\n\nfunction collectTypes(node: Node, parent: Node | null, file: string, source: string, registry: TypeRegistry): void {\n if (node.type === \"TSTypeAliasDeclaration\") {\n const id = child(node, \"id\");\n const typeAnno = child(node, \"typeAnnotation\");\n if (id && typeAnno) {\n registry.add(prop<string>(id, \"name\"), file, lineAt(source, node.start), typeAnno, source, isExported(parent));\n }\n }\n if (node.type === \"TSInterfaceDeclaration\") {\n const id = child(node, \"id\");\n const body = child(node, \"body\");\n if (id && body) {\n registry.add(prop<string>(id, \"name\"), file, lineAt(source, node.start), body, source, isExported(parent));\n }\n }\n}\n\nfunction isExported(parent: Node | null): boolean {\n if (parent === null) return false;\n return parent.type === \"ExportNamedDeclaration\" || parent.type === \"ExportDefaultDeclaration\";\n}\n\nfunction collectFunctions(node: Node, parent: Node | null, file: string, source: string, registry: FunctionRegistry): void {\n if (node.type === \"FunctionDeclaration\" || node.type === \"FunctionExpression\") {\n const id = child(node, \"id\");\n const body = child(node, \"body\");\n if (!id || !body) return;\n const name = prop<string>(id, \"name\");\n const params = extractParams(children(node, \"params\"), source);\n const hash = hashFunctionBody(body, source);\n const exported = isExported(parent);\n registry.add({ name, file, line: lineAt(source, node.start), hash, params, node, exported });\n }\n // Arrow functions assigned to const\n if (node.type === \"VariableDeclarator\") {\n const init = child(node, \"init\");\n const id = child(node, \"id\");\n if (init !== null && init.type === \"ArrowFunctionExpression\" && id !== null && id.type === \"Identifier\") {\n const body = child(init, \"body\");\n if (!body) return;\n const name = prop<string>(id, \"name\");\n const params = extractParams(children(init, \"params\"), source);\n const hash = hashFunctionBody(body, source);\n // Parent is VariableDeclaration; check if \"export\" precedes the declaration on the same line\n const lineStart = source.lastIndexOf(\"\\n\", node.start) + 1;\n const linePrefix = source.slice(lineStart, node.start);\n const exported = linePrefix.includes(\"export\");\n registry.add({ name, file, line: lineAt(source, node.start), hash, params, node, exported });\n }\n }\n}\n\nfunction paramName(node: Node, source: string): string {\n const name = prop<string>(node, \"name\");\n if (name !== undefined) return name;\n return source.slice(node.start, node.end);\n}\n\nfunction typeText(node: Node | null, source: string): string | null {\n if (node === null) return null;\n return source.slice(node.start, node.end);\n}\n\nfunction extractParams(params: Node[], source: string): ParamInfo[] {\n return params.map((p) => {\n if (p.type === \"AssignmentPattern\") {\n const left = child(p, \"left\");\n if (left === null) {\n return { name: \"?\", optional: false, hasDefault: true, typeText: null };\n }\n return {\n name: paramName(left, source),\n optional: prop<boolean>(left, \"optional\") === true,\n hasDefault: true,\n typeText: typeText(child(left, \"typeAnnotation\"), source),\n };\n }\n const typeAnno = child(p, \"typeAnnotation\");\n return {\n name: paramName(p, source),\n optional: prop<boolean>(p, \"optional\") === true,\n hasDefault: false,\n typeText: typeText(typeAnno, source),\n };\n });\n}\n\nfunction collectCallSites(node: Node, file: string, source: string, sites: CallSite[]): void {\n if (node.type !== \"CallExpression\") return;\n const callee = child(node, \"callee\");\n let calleeName: string | null = null;\n if (callee !== null && callee.type === \"Identifier\") {\n calleeName = prop<string>(callee, \"name\");\n } else if (callee !== null && callee.type === \"MemberExpression\" && prop<boolean>(callee, \"computed\") !== true) {\n const property = child(callee, \"property\");\n if (property) calleeName = prop<string>(property, \"name\");\n }\n if (calleeName) {\n sites.push({\n calleeName,\n file,\n line: lineAt(source, node.start),\n argCount: children(node, \"arguments\").length,\n node,\n });\n }\n}\n","import { createHash } from \"node:crypto\";\nimport type { Node } from \"oxc-parser\";\nimport { prop, child, children } from \"./narrow.ts\";\n\n/**\n * Create a structural hash of a type node.\n * Normalizes by sorting property names and stripping locations.\n */\nexport function hashTypeShape(node: Node, source: string): string {\n const normalized = normalizeTypeNode(node, source);\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeTypeNode(node: Node, source: string): string {\n if (node.type === \"TSTypeLiteral\") {\n const members = children(node, \"members\");\n const normalized = members.map((m) => normalizeTypeNode(m, source)).sort().join(\";\");\n return `{${normalized}}`;\n }\n if (node.type === \"TSInterfaceBody\") {\n const members = children(node, \"body\");\n const normalized = members.map((m) => normalizeTypeNode(m, source)).sort().join(\";\");\n return `{${normalized}}`;\n }\n if (node.type === \"TSPropertySignature\") {\n const key = child(node, \"key\");\n const rawName = key ? prop<string>(key, \"name\") : undefined;\n const keyName = rawName !== undefined ? rawName : key ? source.slice(key.start, key.end) : \"?\";\n const typeAnno = child(node, \"typeAnnotation\");\n const innerType = typeAnno ? child(typeAnno, \"typeAnnotation\") : null;\n const type = innerType ? normalizeTypeNode(innerType, source) : \"any\";\n const optional = prop<boolean>(node, \"optional\") ? \"?\" : \"\";\n return `${keyName}${optional}:${type}`;\n }\n if (node.type === \"TSTypeAnnotation\") {\n const inner = child(node, \"typeAnnotation\");\n return inner ? normalizeTypeNode(inner, source) : \"any\";\n }\n // Fallback: use source text with whitespace normalized\n return source.slice(node.start, node.end).replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Hash a function body for duplicate detection.\n * Normalizes whitespace.\n */\nexport function hashFunctionBody(node: Node, source: string): string {\n const bodyText = source.slice(node.start, node.end);\n const normalized = bodyText.replace(/\\s+/g, \" \").trim();\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n","import type { Node } from \"oxc-parser\";\nimport { hashTypeShape } from \"../utils/hash.ts\";\n\nexport interface TypeEntry {\n name: string;\n file: string;\n line: number;\n hash: string;\n node: Node;\n exported: boolean;\n}\n\nexport class TypeRegistry {\n private entries: TypeEntry[] = [];\n private byHash = new Map<string, TypeEntry[]>();\n\n add(name: string, file: string, line: number, typeNode: Node, source: string, exported: boolean): void {\n const hash = hashTypeShape(typeNode, source);\n const entry: TypeEntry = { name, file, line, hash, node: typeNode, exported };\n this.entries.push(entry);\n let list = this.byHash.get(hash);\n if (list === undefined) {\n list = [];\n this.byHash.set(hash, list);\n }\n list.push(entry);\n }\n\n getDuplicateGroups(): TypeEntry[][] {\n return [...this.byHash.values()].filter((group) => group.length > 1);\n }\n\n getAll(): TypeEntry[] {\n return this.entries;\n }\n\n getNameCollisionGroups(): TypeEntry[][] {\n const byName = new Map<string, TypeEntry[]>();\n for (const entry of this.entries) {\n if (!entry.exported) continue;\n let list = byName.get(entry.name);\n if (list === undefined) {\n list = [];\n byName.set(entry.name, list);\n }\n list.push(entry);\n }\n return [...byName.values()].filter((group) => {\n if (group.length < 2) return false;\n const files = new Set(group.map((e) => e.file));\n return files.size > 1;\n });\n }\n}\n","import type { Node } from \"oxc-parser\";\n\nexport interface ParamInfo {\n name: string;\n optional: boolean;\n hasDefault: boolean;\n typeText: string | null;\n}\n\nexport interface FunctionEntry {\n name: string;\n file: string;\n line: number;\n hash: string;\n params: ParamInfo[];\n node: Node;\n exported: boolean;\n}\n\nexport class FunctionRegistry {\n private entries: FunctionEntry[] = [];\n private byHash = new Map<string, FunctionEntry[]>();\n\n add(entry: FunctionEntry): void {\n this.entries.push(entry);\n let list = this.byHash.get(entry.hash);\n if (list === undefined) {\n list = [];\n this.byHash.set(entry.hash, list);\n }\n list.push(entry);\n }\n\n getDuplicateGroups(): FunctionEntry[][] {\n return [...this.byHash.values()].filter((group) => group.length > 1);\n }\n\n getAll(): FunctionEntry[] {\n return this.entries;\n }\n\n getByName(name: string): FunctionEntry[] {\n return this.entries.filter((e) => e.name === name);\n }\n\n getNameCollisionGroups(): FunctionEntry[][] {\n const byName = new Map<string, FunctionEntry[]>();\n for (const entry of this.entries) {\n if (!entry.exported) continue;\n let list = byName.get(entry.name);\n if (list === undefined) {\n list = [];\n byName.set(entry.name, list);\n }\n list.push(entry);\n }\n return [...byName.values()].filter((group) => {\n if (group.length < 2) return false;\n const files = new Set(group.map((e) => e.file));\n return files.size > 1;\n });\n }\n}\n"],"mappings":"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","names":["parseSync","walk","readFileSync","readFileSync","parseSync","walk","lineAt"]}
|