unguard 0.4.2 → 0.4.3

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.
@@ -208,11 +208,26 @@ var noInlineTypeInParams = {
208
208
  message: "Inline type literal in annotation; extract to a named type for reuse and clarity",
209
209
  visit(node, parent, ctx) {
210
210
  if (node.type !== "TSTypeLiteral") return;
211
- if (parent !== null && parent.type === "TSTypeAnnotation") {
212
- ctx.report(node);
213
- }
211
+ if (parent === null || parent.type !== "TSTypeAnnotation") return;
212
+ if (isInsideMethodOrInterface(ctx.source, node.start)) return;
213
+ ctx.report(node);
214
214
  }
215
215
  };
216
+ function isInsideMethodOrInterface(source, offset) {
217
+ let depth = 0;
218
+ for (let i = offset - 1; i >= 0; i--) {
219
+ if (source[i] === "}") depth++;
220
+ if (source[i] === "{") {
221
+ if (depth === 0) {
222
+ const before = source.slice(Math.max(0, i - 100), i).trimEnd();
223
+ if (/\b(interface|class)\s+\w+/.test(before)) return true;
224
+ return false;
225
+ }
226
+ depth--;
227
+ }
228
+ }
229
+ return false;
230
+ }
216
231
 
217
232
  // src/rules/single-file/no-type-assertion.ts
218
233
  var noTypeAssertion = {
@@ -1110,4 +1125,4 @@ export {
1110
1125
  allRules,
1111
1126
  scan
1112
1127
  };
1113
- //# sourceMappingURL=chunk-AAUSR4FA.js.map
1128
+ //# sourceMappingURL=chunk-ZPHC5BEF.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: \"warning\",\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 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 (!) bypasses type safety; prove the value exists instead\",\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: \"warning\",\n message: \"!! coercion hides data-shape intent; use an explicit boolean comparison\",\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: \"warning\",\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 (??) implies the value could be null/undefined; prove the shape instead\",\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: \"warning\",\n message: \"Optional call (?.) implies the function could be undefined; prove it exists\",\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: \"warning\",\n message: \"Optional chaining (?.) implies the object could be nullish; prove the shape instead\",\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: \"warning\",\n message: \"Optional element access (?.[]) implies the object could be nullish; prove the shape instead\",\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 implies the left side could be falsy; prove the shape instead\",\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) implies the value could be nullish; prove the shape\",\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: \"warning\",\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 (isInsideMethodOrInterface(ctx.source, node.start)) return;\n\n ctx.report(node);\n },\n};\n\nfunction isInsideMethodOrInterface(source: string, offset: number): boolean {\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 const before = source.slice(Math.max(0, i - 100), i).trimEnd();\n if (/\\b(interface|class)\\s+\\w+/.test(before)) return true;\n return false;\n }\n depth--;\n }\n }\n return false;\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: \"warning\",\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 obj is typed, the guard is unnecessary\",\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: \"warning\",\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: \"warning\",\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; extract to a shared module\",\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; extract to a shared module\",\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 value instead of throwing; this converts errors into fallback data that callers must defensively handle\",\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: \"warning\",\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: \"warning\",\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\nfunction 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 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: \"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}\n\nexport interface SingleFileRule {\n id: string;\n severity: \"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: \"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,6 +1,6 @@
1
1
  import {
2
2
  scan
3
- } from "./chunk-AAUSR4FA.js";
3
+ } from "./chunk-ZPHC5BEF.js";
4
4
 
5
5
  // src/cli.ts
6
6
  import { relative } from "path";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  allRules,
3
3
  scan
4
- } from "./chunk-AAUSR4FA.js";
4
+ } from "./chunk-ZPHC5BEF.js";
5
5
  export {
6
6
  allRules,
7
7
  scan
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unguard",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Unslop",
5
5
  "author": "TwoAbove",
6
6
  "license": "MIT",
@@ -12,6 +12,13 @@
12
12
  "bugs": {
13
13
  "url": "https://github.com/TwoAbove/unguard/issues"
14
14
  },
15
+ "keywords": [
16
+ "typescript",
17
+ "linter",
18
+ "static-analysis",
19
+ "code-quality",
20
+ "type-safety"
21
+ ],
15
22
  "type": "module",
16
23
  "bin": {
17
24
  "unguard": "./bin/unguard.mjs"
@@ -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: \"warning\",\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 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 (!) bypasses type safety; prove the value exists instead\",\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: \"warning\",\n message: \"!! coercion hides data-shape intent; use an explicit boolean comparison\",\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: \"warning\",\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 (??) implies the value could be null/undefined; prove the shape instead\",\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: \"warning\",\n message: \"Optional call (?.) implies the function could be undefined; prove it exists\",\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: \"warning\",\n message: \"Optional chaining (?.) implies the object could be nullish; prove the shape instead\",\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: \"warning\",\n message: \"Optional element access (?.[]) implies the object could be nullish; prove the shape instead\",\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 implies the left side could be falsy; prove the shape instead\",\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) implies the value could be nullish; prove the shape\",\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: \"warning\",\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\") {\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 noTypeAssertion: SingleFileRule = {\n id: \"no-type-assertion\",\n severity: \"warning\",\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 obj is typed, the guard is unnecessary\",\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: \"warning\",\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: \"warning\",\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; extract to a shared module\",\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; extract to a shared module\",\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 value instead of throwing; this converts errors into fallback data that callers must defensively handle\",\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: \"warning\",\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: \"warning\",\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\nfunction 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 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: \"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}\n\nexport interface SingleFileRule {\n id: string;\n severity: \"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: \"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"]}