unguard 0.13.2 → 0.13.4

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rules/cross-file/dead-overload.ts","../src/rules/types.ts","../src/rules/cross-file/duplicate-constant-declaration.ts","../src/rules/cross-file/duplicate-file.ts","../src/rules/cross-file/duplicate-function-declaration.ts","../src/rules/cross-file/duplicate-function-name.ts","../src/rules/cross-file/duplicate-inline-type-in-params.ts","../src/rules/cross-file/duplicate-statement-sequence.ts","../src/rules/cross-file/duplicate-type-declaration.ts","../src/rules/cross-file/duplicate-type-name.ts","../src/rules/cross-file/explicit-null-arg.ts","../src/typecheck/utils.ts","../src/rules/cross-file/near-duplicate-function.ts","../src/rules/cross-file/optional-arg-always-used.ts","../src/rules/cross-file/repeated-literal-property.ts","../src/rules/cross-file/repeated-return-shape.ts","../src/rules/cross-file/object-shape.ts","../src/rules/cross-file/trivial-wrapper.ts","../src/rules/cross-file/unused-export.ts","../src/rules/ts/no-any-cast.ts","../src/rules/ts/no-catch-return.ts","../src/rules/ts/no-double-negation-coercion.ts","../src/rules/ts/no-dynamic-import.ts","../src/rules/ts/no-empty-catch.ts","../src/rules/ts/no-error-rewrap.ts","../src/rules/ts/no-explicit-any-annotation.ts","../src/rules/ts/no-inline-param-type.ts","../src/rules/ts/no-inline-type-assertion.ts","../src/rules/ts/no-logical-or-fallback.ts","../src/rules/ts/no-non-null-assertion.ts","../src/rules/ts/no-null-ternary-normalization.ts","../src/rules/ts/no-nullish-coalescing.ts","../src/rules/ts/no-optional-call.ts","../src/rules/ts/no-optional-element-access.ts","../src/rules/ts/no-optional-property-access.ts","../src/rules/ts/no-redundant-existence-guard.ts","../src/rules/ts/no-ts-ignore.ts","../src/rules/ts/no-type-assertion.ts","../src/rules/ts/prefer-default-param-value.ts","../src/rules/ts/prefer-required-param-with-guard.ts","../src/rules/index.ts","../src/scan/config.ts","../src/collect/index.ts","../src/collect/type-registry.ts","../src/utils/hash.ts","../src/collect/base-registry.ts","../src/collect/function-registry.ts","../src/collect/constant-registry.ts","../src/collect/statement-sequence-registry.ts","../src/collect/inline-type-registry.ts","../src/typecheck/walk.ts","../src/typecheck/program.ts","../src/scan/analyze.ts","../src/scan/discover.ts","../src/scan/policy.ts","../src/engine.ts"],"sourcesContent":["import * as ts from \"typescript\";\nimport type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\ntype OverloadDeclaration = ts.FunctionDeclaration | ts.MethodDeclaration;\n\ninterface OverloadFamily {\n name: string;\n file: string;\n sourceFile: ts.SourceFile;\n overloads: OverloadDeclaration[];\n implementation: OverloadDeclaration;\n}\n\nexport const deadOverload: CrossFileRule = {\n id: \"dead-overload\",\n severity: \"warning\",\n message: \"Overload signature has no matching call sites in the project\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n for (const [file, { sourceFile }] of project.files) {\n for (const family of collectOverloadFamilies(sourceFile, file)) {\n const matchedOverloads = new Set<OverloadDeclaration>();\n\n for (const site of project.callSites) {\n const declaration = site.resolvedDeclaration;\n if (declaration === undefined) continue;\n if (family.overloads.includes(declaration as OverloadDeclaration)) {\n matchedOverloads.add(declaration as OverloadDeclaration);\n }\n }\n\n if (matchedOverloads.size === 0) continue;\n\n const deadOverloads = family.overloads.filter((overload) => !matchedOverloads.has(overload));\n const liveOverloads = family.overloads.filter((overload) => matchedOverloads.has(overload));\n\n for (const overload of deadOverloads) {\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: buildMessage(family, overload, deadOverloads, liveOverloads),\n file,\n line: lineOf(sourceFile, overload),\n column: 1,\n });\n }\n }\n }\n\n return diagnostics;\n },\n};\n\nfunction buildMessage(\n family: OverloadFamily,\n overload: OverloadDeclaration,\n deadOverloads: OverloadDeclaration[],\n liveOverloads: OverloadDeclaration[],\n): string {\n const base = `Overload signature for \"${family.name}\" has no matching call sites in the project`;\n if (!shouldMentionCascade(family, overload, deadOverloads, liveOverloads)) {\n return base;\n }\n return `${base}; removing it may let you collapse to the remaining constrained signature and drop implementation casts`;\n}\n\nfunction shouldMentionCascade(\n family: OverloadFamily,\n overload: OverloadDeclaration,\n deadOverloads: OverloadDeclaration[],\n liveOverloads: OverloadDeclaration[],\n): boolean {\n if (deadOverloads.length !== 1 || liveOverloads.length !== 1) return false;\n if (deadOverloads[0] !== overload) return false;\n const liveOverload = liveOverloads[0];\n if (liveOverload === undefined) return false;\n if (family.implementation.typeParameters === undefined || liveOverload.typeParameters === undefined) return false;\n const body = family.implementation.body;\n if (body === undefined) return false;\n\n const implementationTypeParams = family.implementation.typeParameters;\n const liveTypeParams = liveOverload.typeParameters;\n if (implementationTypeParams.length === 0 || implementationTypeParams.length !== liveTypeParams.length) return false;\n\n const constrainedParams = implementationTypeParams.flatMap((typeParam, index) => {\n const liveTypeParam = liveTypeParams[index];\n if (liveTypeParam === undefined) return [];\n if (typeParam.constraint !== undefined) return [];\n if (liveTypeParam.constraint === undefined) return [];\n return [{\n paramName: typeParam.name.text,\n constraintText: normalizeText(liveTypeParam.constraint.getText(family.sourceFile)),\n }];\n });\n\n if (constrainedParams.length === 0) return false;\n\n return constrainedParams.some(({ paramName, constraintText }) =>\n hasIntersectionCast(body, family.sourceFile, paramName, constraintText)\n );\n}\n\nfunction hasIntersectionCast(\n body: ts.Block,\n sourceFile: ts.SourceFile,\n paramName: string,\n constraintText: string,\n): boolean {\n let found = false;\n\n function visit(node: ts.Node): void {\n if (found) return;\n\n if (ts.isAsExpression(node) || ts.isTypeAssertionExpression(node)) {\n if (isConstraintIntersection(node.type, sourceFile, paramName, constraintText)) {\n found = true;\n return;\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(body);\n return found;\n}\n\nfunction isConstraintIntersection(\n typeNode: ts.TypeNode,\n sourceFile: ts.SourceFile,\n paramName: string,\n constraintText: string,\n): boolean {\n const target = unwrapParenthesizedType(typeNode);\n if (!ts.isIntersectionTypeNode(target)) return false;\n\n let hasParam = false;\n let hasConstraint = false;\n\n for (const part of target.types) {\n const text = normalizeText(unwrapParenthesizedType(part).getText(sourceFile));\n if (text === paramName) hasParam = true;\n if (text === constraintText) hasConstraint = true;\n }\n\n return hasParam && hasConstraint;\n}\n\nfunction unwrapParenthesizedType(typeNode: ts.TypeNode): ts.TypeNode {\n let current = typeNode;\n while (ts.isParenthesizedTypeNode(current)) {\n current = current.type;\n }\n return current;\n}\n\nfunction collectOverloadFamilies(sourceFile: ts.SourceFile, file: string): OverloadFamily[] {\n const families: OverloadFamily[] = [];\n\n collectFromList(sourceFile.statements, sourceFile, file, families);\n\n function visit(node: ts.Node): void {\n if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {\n collectFromList(node.members, sourceFile, file, families);\n }\n ts.forEachChild(node, visit);\n }\n\n ts.forEachChild(sourceFile, visit);\n return families;\n}\n\nfunction collectFromList(\n nodes: ts.NodeArray<ts.Node>,\n sourceFile: ts.SourceFile,\n file: string,\n families: OverloadFamily[],\n): void {\n for (let index = 0; index < nodes.length; index++) {\n const current = asOverloadDeclaration(nodes[index]);\n const name = current ? getDeclarationName(current) : null;\n if (current === null || name === null) continue;\n\n const run: OverloadDeclaration[] = [current];\n let nextIndex = index + 1;\n while (nextIndex < nodes.length) {\n const next = asOverloadDeclaration(nodes[nextIndex]);\n if (next === null) break;\n if (getDeclarationName(next) !== name) break;\n run.push(next);\n nextIndex++;\n }\n\n const family = toOverloadFamily(run, name, file, sourceFile);\n if (family !== null) {\n families.push(family);\n }\n\n index = nextIndex - 1;\n }\n}\n\nfunction toOverloadFamily(\n run: OverloadDeclaration[],\n name: string,\n file: string,\n sourceFile: ts.SourceFile,\n): OverloadFamily | null {\n if (run.length < 2) return null;\n\n const implementation = run.at(-1);\n if (implementation === undefined || implementation.body === undefined) return null;\n if (run.slice(0, -1).some((declaration) => declaration.body !== undefined)) return null;\n\n return {\n name,\n file,\n sourceFile,\n overloads: run.slice(0, -1),\n implementation,\n };\n}\n\nfunction asOverloadDeclaration(node: ts.Node | undefined): OverloadDeclaration | null {\n if (node === undefined) return null;\n if (ts.isFunctionDeclaration(node)) return node;\n if (ts.isMethodDeclaration(node)) return node;\n return null;\n}\n\nfunction getDeclarationName(node: OverloadDeclaration): string | null {\n if (ts.isFunctionDeclaration(node)) {\n return node.name?.text ?? null;\n }\n\n if (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name) || ts.isNumericLiteral(node.name)) {\n return node.name.text;\n }\n\n return null;\n}\n\nfunction lineOf(sourceFile: ts.SourceFile, node: ts.Node): number {\n return ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n}\n\nfunction normalizeText(text: string): string {\n return text.replace(/\\s+/g, \"\");\n}\n","import type * as ts from \"typescript\";\n\nexport interface Diagnostic {\n ruleId: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n file: string;\n line: number;\n column: number;\n annotation?: string;\n}\n\nexport interface TSVisitContext {\n report(node: ts.Node, message?: string): void;\n reportAtOffset(offset: number, message?: string): void;\n filename: string;\n source: string;\n sourceFile: ts.SourceFile;\n checker: ts.TypeChecker;\n isNullable(node: ts.Node): boolean;\n isExternal(node: ts.Node): boolean;\n}\n\nexport interface TSRule {\n kind: \"ts\";\n id: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n visit(node: ts.Node, ctx: TSVisitContext): void;\n}\n\nimport type { ProjectIndex } from \"../collect/index.ts\";\nexport type { ProjectIndex };\n\nexport interface CrossFileRule {\n id: string;\n severity: \"info\" | \"warning\" | \"error\";\n message: string;\n analyze(project: ProjectIndex): Diagnostic[];\n}\n\nexport type Rule = CrossFileRule | TSRule;\n\nexport function isTSRule(r: Rule): r is TSRule {\n return \"kind\" in r && r.kind === \"ts\";\n}\n\nexport function reportDuplicateGroup<T extends { file: string; line: number }>(\n group: T[],\n ruleId: string,\n severity: Diagnostic[\"severity\"],\n formatOther: (entry: T) => string,\n formatMessage: (entry: T, others: string) => string,\n diagnostics: Diagnostic[],\n): void {\n const sorted = [...group].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n for (const entry of sorted.slice(1)) {\n const others = sorted\n .filter((e) => e !== entry)\n .map(formatOther)\n .join(\", \");\n diagnostics.push({\n ruleId,\n severity,\n message: formatMessage(entry, others),\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n}\n","import { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } from \"../types.ts\";\n\nexport const duplicateConstantDeclaration: CrossFileRule = {\n id: \"duplicate-constant-declaration\",\n severity: \"warning\",\n message: \"Identical constant value declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.constants.getDuplicateGroups()) {\n const files = new Set(group.map((e) => e.file));\n if (files.size < 2) continue;\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.name} (${e.file}:${e.line})`,\n (e, others) => `Constant \"${e.name}\" has identical value \\`${e.valueText}\\` to: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateFile: CrossFileRule = {\n id: \"duplicate-file\",\n severity: \"warning\",\n message: \"File has identical content to another file; one is likely dead code\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const files of project.fileHashes.values()) {\n if (files.length < 2) continue;\n const sorted = [...files].sort();\n for (const file of sorted.slice(1)) {\n const others = sorted.filter((f) => f !== file).join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `File is identical to: ${others}`,\n file,\n line: 1,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import * as ts from \"typescript\";\nimport { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } from \"../types.ts\";\n\nexport const duplicateFunctionDeclaration: CrossFileRule = {\n id: \"duplicate-function-declaration\",\n severity: \"warning\",\n message: \"Identical function body declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.functions.getDuplicateGroups()) {\n const first = group[0];\n if (first === undefined) continue;\n if (isSingleStatement(first.node)) continue;\n if (isSetter(first.node)) continue;\n\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.name} (${e.file}:${e.line})`,\n (e, others) => `Function \"${e.name}\" has identical body to: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n\nfunction getBodyBlock(node: ts.Node): ts.Block | undefined {\n if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) return node.body;\n if (ts.isArrowFunction(node)) return ts.isBlock(node.body) ? node.body : undefined;\n if (ts.isMethodDeclaration(node)) return node.body;\n return undefined;\n}\n\nfunction isSingleStatement(node: ts.Node): boolean {\n if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) return true;\n const body = getBodyBlock(node);\n return body !== undefined && body.statements.length <= 1;\n}\n\nfunction isSetter(node: ts.Node): boolean {\n const body = getBodyBlock(node);\n if (!body || body.statements.length !== 1) return false;\n const stmt = body.statements[0];\n if (stmt === undefined || !ts.isExpressionStatement(stmt)) return false;\n return ts.isBinaryExpression(stmt.expression) &&\n stmt.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken;\n}\n","import { dirname, resolve } from \"node:path\";\nimport { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } from \"../types.ts\";\n\nconst EXTENSIONS = [\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".jsx\", \".mjs\", \".cjs\"];\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 const hashes = new Set(group.map((e) => e.hash));\n if (hashes.size === 1) continue;\n\n const groupFiles = new Set(group.map((e) => e.file));\n const first = group[0];\n if (first === undefined) continue;\n const funcName = first.name;\n const hasImportLink = project.imports.some((imp) => {\n if (!groupFiles.has(imp.file)) return false;\n if (imp.importedName !== funcName && imp.localName !== funcName) return false;\n if (!imp.source.startsWith(\".\")) return false;\n const candidates = resolveCandidates(imp.file, imp.source);\n if (candidates.some((c) => groupFiles.has(c))) return true;\n return candidates.some((c) =>\n project.imports.some((reExp) => {\n if (reExp.file !== c) return false;\n if (reExp.importedName !== funcName && reExp.localName !== funcName) return false;\n if (!reExp.source.startsWith(\".\")) return false;\n const innerCandidates = resolveCandidates(reExp.file, reExp.source);\n return innerCandidates.some((ic) => groupFiles.has(ic));\n }),\n );\n });\n if (hasImportLink) continue;\n\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.file}:${e.line}`,\n (e, others) => `Exported function \"${e.name}\" also defined in: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n\nfunction resolveCandidates(fromFile: string, specifier: string): string[] {\n const base = resolve(dirname(fromFile), specifier);\n const candidates = [base];\n for (const ext of EXTENSIONS) {\n candidates.push(base + ext);\n candidates.push(resolve(base, `index${ext}`));\n }\n return candidates;\n}\n","import { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } from \"../types.ts\";\n\nexport const duplicateInlineTypeInParams: CrossFileRule = {\n id: \"duplicate-inline-type-in-params\",\n severity: \"warning\",\n message: \"Same inline param type shape appears in multiple places; extract to a shared named type\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.inlineParamTypes.getDuplicateGroups()) {\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.typeText} (${e.file}:${e.line})`,\n (e, others) => `Inline param type \\`${e.typeText}\\` also appears at: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n","import type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const duplicateStatementSequence: CrossFileRule = {\n id: \"duplicate-statement-sequence\",\n severity: \"info\",\n message: \"Repeated statement sequence; consider extracting to a shared helper\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const MIN_NORMALIZED_BODY = 128;\n\n for (const group of project.statementSequences.getNormalizedDuplicateGroups()) {\n if (group.every((e) => e.normalizedBodyLength < MIN_NORMALIZED_BODY)) continue;\n\n // Deduplicate overlapping windows: keep only the largest per location\n const byLocation = new Map<string, (typeof group)[number]>();\n for (const entry of group) {\n const key = `${entry.file}:${entry.line}`;\n const existing = byLocation.get(key);\n if (existing === undefined || entry.statementCount > existing.statementCount) {\n byLocation.set(key, entry);\n }\n }\n const deduped = [...byLocation.values()];\n if (deduped.length < 2) continue;\n\n const sorted = deduped.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n for (const entry of sorted.slice(1)) {\n const others = sorted\n .filter((e) => e !== entry)\n .map((e) => `${e.file}:${e.line}`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Statement sequence (${entry.statementCount} statements) duplicated at: ${others}`,\n file: entry.file,\n line: entry.line,\n column: 1,\n });\n }\n }\n return diagnostics;\n },\n};\n","import * as ts from \"typescript\";\nimport { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } from \"../types.ts\";\n\nexport const duplicateTypeDeclaration: CrossFileRule = {\n id: \"duplicate-type-declaration\",\n severity: \"warning\",\n message: \"Identical type shape declared in multiple files; consolidate to a single definition\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.types.getDuplicateGroups()) {\n const files = new Set(group.map((e) => e.file));\n if (files.size < 2) continue;\n if (group.every((e) => isTrivialObjectShape(e.node))) continue;\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.name} (${e.file}:${e.line})`,\n (e, others) => `Type \"${e.name}\" has identical shape to: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n\nfunction isTrivialObjectShape(node: ts.Node): boolean {\n if (ts.isTypeLiteralNode(node)) return node.members.length <= 1;\n if (ts.isInterfaceDeclaration(node)) return node.members.length <= 1;\n return false;\n}\n","import * as ts from \"typescript\";\nimport { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } 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 const hashes = new Set(group.map((e) => e.hash));\n if (hashes.size === 1) continue;\n\n const hasInferredType = group.some(\n (e) => !ts.isTypeLiteralNode(e.node) && !ts.isInterfaceDeclaration(e.node),\n );\n if (hasInferredType) continue;\n\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.file}:${e.line}`,\n (e, others) => `Exported type \"${e.name}\" also defined in: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n","import * as ts from \"typescript\";\nimport type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\nimport { isNullishLiteral } from \"../../typecheck/utils.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 lookup structures for known project functions\n const projectFnNames = new Set<string>();\n const projectFnSymbols = new Set<ts.Symbol>();\n for (const fn of project.functions.getAll()) {\n projectFnNames.add(fn.name);\n if (fn.symbol) projectFnSymbols.add(fn.symbol);\n }\n\n for (const site of project.callSites) {\n // Only flag calls to functions defined in the project — prefer symbol matching\n const isProjectFn = site.symbol\n ? projectFnSymbols.has(site.symbol)\n : projectFnNames.has(site.calleeName);\n if (!isProjectFn) continue;\n\n for (let i = 0; i < site.node.arguments.length; i++) {\n const arg = site.node.arguments[i];\n if (arg === undefined) continue;\n if (isNullishLiteral(arg)) {\n const val = arg.kind === ts.SyntaxKind.NullKeyword ? \"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\n","import * as ts from \"typescript\";\n\nfunction hasFlags(flags: number, mask: number): boolean {\n return (flags & mask) !== 0;\n}\n\nconst NULLISH_FLAGS = ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Void;\n\nexport function isNullableType(checker: ts.TypeChecker, type: ts.Type): boolean {\n if (type.isUnion()) {\n return type.types.some((t) => hasFlags(t.flags, NULLISH_FLAGS));\n }\n return hasFlags(type.flags, NULLISH_FLAGS);\n}\n\nexport function isFromNodeModules(node: ts.Node): boolean {\n const sourceFile = node.getSourceFile();\n return sourceFile.fileName.includes(\"/node_modules/\");\n}\n\nexport function includesNumberType(type: ts.Type): boolean {\n if (type.isUnion()) {\n return type.types.some((t) => hasFlags(t.flags, ts.TypeFlags.NumberLike));\n }\n return hasFlags(type.flags, ts.TypeFlags.NumberLike);\n}\n\nexport function includesBooleanType(type: ts.Type): boolean {\n if (type.isUnion()) {\n return type.types.some((t) => hasFlags(t.flags, ts.TypeFlags.BooleanLike));\n }\n return hasFlags(type.flags, ts.TypeFlags.BooleanLike);\n}\n\nexport function isNullishLiteral(node: ts.Node): boolean {\n if (node.kind === ts.SyntaxKind.NullKeyword) return true;\n if (ts.isIdentifier(node) && node.text === \"undefined\") return true;\n return false;\n}\n\ntype FunctionLike = ts.FunctionDeclaration | ts.ArrowFunction;\n\nexport function getFunctionBodyStatements(node: ts.Node): { statements: ts.NodeArray<ts.Statement>; fn: FunctionLike } | null {\n if (!ts.isFunctionDeclaration(node) && !ts.isArrowFunction(node)) return null;\n if (!node.body || !ts.isBlock(node.body)) return null;\n if (node.body.statements.length === 0) return null;\n return { statements: node.body.statements, fn: node };\n}\n\nexport function getFirstFunctionStatement(node: ts.Node): { firstStmt: ts.Statement; fn: FunctionLike } | null {\n const result = getFunctionBodyStatements(node);\n if (result === null) return null;\n const firstStmt = result.statements[0];\n if (firstStmt === undefined) return null;\n return { firstStmt, fn: result.fn };\n}\n\nexport function isInlineParamType(node: ts.Node): boolean {\n if (!ts.isTypeLiteralNode(node)) return false;\n const parent = node.parent;\n if (!parent || !ts.isParameter(parent)) return false;\n return parent.type === node;\n}\n","import * as ts from \"typescript\";\nimport type { FunctionEntry } from \"../../collect/function-registry.ts\";\nimport { type CrossFileRule, type Diagnostic, type ProjectIndex, reportDuplicateGroup } from \"../types.ts\";\n\nexport const nearDuplicateFunction: CrossFileRule = {\n id: \"near-duplicate-function\",\n severity: \"warning\",\n message: \"Near-duplicate function bodies across files; consider parameterizing\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n for (const group of project.functions.getNearDuplicateGroups()) {\n const MIN_NORMALIZED_BODY = 32;\n if (group.every((e) => e.normalizedBodyLength < MIN_NORMALIZED_BODY)) continue;\n // Precision-first: tiny wrappers/callbacks are often intentionally repeated.\n if (group.every(isSimpleStructure)) continue;\n reportDuplicateGroup(group, this.id, this.severity,\n (e) => `${e.name} (${e.file}:${e.line})`,\n (e, others) => `Function \"${e.name}\" is near-duplicate of: ${others}`,\n diagnostics);\n }\n return diagnostics;\n },\n};\n\nfunction getFunctionBody(node: ts.Node): ts.Block | ts.Expression | undefined {\n if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) return node.body;\n if (ts.isArrowFunction(node)) return node.body;\n if (ts.isMethodDeclaration(node)) return node.body;\n return undefined;\n}\n\nfunction getTopLevelStatementCount(body: ts.Block | ts.Expression): number {\n if (ts.isBlock(body)) return body.statements.length;\n return 1;\n}\n\nfunction hasControlFlow(node: ts.Node): boolean {\n let found = false;\n function visit(current: ts.Node): void {\n if (found) return;\n if (\n ts.isIfStatement(current) ||\n ts.isSwitchStatement(current) ||\n ts.isTryStatement(current) ||\n ts.isForStatement(current) ||\n ts.isForInStatement(current) ||\n ts.isForOfStatement(current) ||\n ts.isWhileStatement(current) ||\n ts.isDoStatement(current)\n ) {\n found = true;\n return;\n }\n ts.forEachChild(current, visit);\n }\n visit(node);\n return found;\n}\n\nfunction isSimpleStructure(entry: FunctionEntry): boolean {\n const body = getFunctionBody(entry.node);\n if (!body) return false;\n if (hasControlFlow(body)) return false;\n return getTopLevelStatementCount(body) <= 2;\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 === undefined) continue;\n if (!param.optional && !param.hasDefault) continue;\n\n // Find call sites for this function — use symbol matching when available\n const callSites = fn.symbol\n ? project.callSites.filter((c) => c.symbol === fn.symbol)\n : 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 * as ts from \"typescript\";\nimport type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nconst MODULE_SCOPE = -1;\n\ninterface LiteralOccurrence {\n line: number;\n isAsConst: boolean;\n scopeId: number;\n key: string;\n}\n\nexport const repeatedLiteralProperty: CrossFileRule = {\n id: \"repeated-literal-property\",\n severity: \"warning\",\n message: \"Repeated literal value in object properties; consider extracting a constant or factory\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n for (const [file, { sourceFile }] of project.files) {\n const valueMap = new Map<string, LiteralOccurrence[]>();\n\n function visit(node: ts.Node): void {\n if (ts.isObjectLiteralExpression(node)) {\n for (const prop of node.properties) {\n if (!ts.isPropertyAssignment(prop)) continue;\n const result = extractLiteral(prop.initializer, sourceFile);\n if (result.literalText === null) continue;\n let list = valueMap.get(result.literalText);\n if (!list) {\n list = [];\n valueMap.set(result.literalText, list);\n }\n const line = ts.getLineAndCharacterOfPosition(sourceFile, prop.getStart(sourceFile)).line + 1;\n const scopeId = findEnclosingFunctionStart(prop, sourceFile);\n const key = ts.isIdentifier(prop.name) ? prop.name.text\n : ts.isStringLiteral(prop.name) ? prop.name.text\n : \"\";\n list.push({ line, isAsConst: result.isAsConst, scopeId, key });\n }\n }\n ts.forEachChild(node, visit);\n }\n ts.forEachChild(sourceFile, visit);\n\n for (const [value, occurrences] of valueMap) {\n // All occurrences on the same property key = discriminant pattern, not a DRY violation\n const uniqueKeys = new Set(occurrences.map((o) => o.key).filter((k) => k !== \"\"));\n if (uniqueKeys.size === 1) continue;\n\n const hasAsConst = occurrences.some((o) => o.isAsConst);\n // Deduplicate by scope — count distinct functions, not raw occurrences\n const uniqueScopes = new Set(occurrences.map((o) => o.scopeId));\n const threshold = hasAsConst ? 3 : 5;\n if (uniqueScopes.size < threshold) continue;\n\n const sorted = [...occurrences].sort((a, b) => a.line - b.line);\n const first = sorted[0];\n if (first === undefined) continue;\n const otherLines = sorted.slice(1).map((o) => o.line).join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `${JSON.stringify(value)}${hasAsConst ? \" as const\" : \"\"} repeated across ${uniqueScopes.size} scopes as property value (also at lines ${otherLines})`,\n file,\n line: first.line,\n column: 1,\n });\n }\n }\n\n return diagnostics;\n },\n};\n\nfunction findEnclosingFunctionStart(node: ts.Node, sourceFile: ts.SourceFile): number {\n let current = node.parent;\n while (current) {\n if (\n ts.isFunctionDeclaration(current) ||\n ts.isFunctionExpression(current) ||\n ts.isArrowFunction(current) ||\n ts.isMethodDeclaration(current)\n ) {\n return current.getStart(sourceFile);\n }\n current = current.parent;\n }\n return MODULE_SCOPE;\n}\n\nfunction extractLiteral(\n node: ts.Node,\n sourceFile: ts.SourceFile,\n): { literalText: string | null; isAsConst: boolean } {\n if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {\n return { literalText: node.text, isAsConst: false };\n }\n\n if (ts.isAsExpression(node) && node.type.getText(sourceFile).trim() === \"const\") {\n const inner = extractLiteral(node.expression, sourceFile);\n if (inner.literalText !== null) {\n return { literalText: inner.literalText, isAsConst: true };\n }\n }\n\n return { literalText: null, isAsConst: false };\n}\n","import * as ts from \"typescript\";\nimport type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\nimport { extractPropertyNames, getShapeGroup } from \"./object-shape.ts\";\nimport type { TypeEntry } from \"../../collect/type-registry.ts\";\n\ninterface ReturnShapeEntry {\n file: string;\n line: number;\n functionName: string;\n props: string[];\n}\n\nexport const repeatedReturnShape: CrossFileRule = {\n id: \"repeated-return-shape\",\n severity: \"warning\",\n message: \"Multiple functions return the same object shape; consider a shared return type\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const THRESHOLD = 3;\n const shapeMap = new Map<string, ReturnShapeEntry[]>();\n\n for (const [file, { sourceFile }] of project.files) {\n function visit(node: ts.Node): void {\n if (isFunctionLike(node) && !isCallbackArgument(node)) {\n const functionName = deriveFunctionName(node, sourceFile);\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n collectReturnShapes(node, file, line, functionName, sourceFile, shapeMap);\n }\n ts.forEachChild(node, visit);\n }\n ts.forEachChild(sourceFile, visit);\n }\n\n const knownTypeShapes = buildKnownTypeShapes(project.types.getAll());\n\n for (const [shapeKey, entries] of shapeMap) {\n if (knownTypeShapes.has(shapeKey)) continue;\n // Deduplicate: one entry per function (same file + line)\n const byFunction = new Map<string, ReturnShapeEntry>();\n for (const entry of entries) {\n const key = `${entry.file}:${entry.line}`;\n if (!byFunction.has(key)) {\n byFunction.set(key, entry);\n }\n }\n const unique = [...byFunction.values()];\n if (unique.length < THRESHOLD) continue;\n\n // Same-file repetition is visible and likely intentional (protocol/framework pattern).\n // Only flag shapes that span multiple files — that's where the developer can't see the duplication.\n const uniqueFiles = new Set(unique.map((e) => e.file));\n if (uniqueFiles.size < 2) continue;\n\n const sorted = unique.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);\n const first = sorted[0];\n if (first === undefined) continue;\n const others = sorted\n .slice(1)\n .map((e) => `${e.functionName} (${e.file}:${e.line})`)\n .join(\", \");\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `${unique.length} functions return shape {${first.props.join(\", \")}}; consider a shared return type (${others})`,\n file: first.file,\n line: first.line,\n column: 1,\n });\n }\n\n return diagnostics;\n },\n};\n\nfunction isFunctionLike(node: ts.Node): boolean {\n return (\n ts.isFunctionDeclaration(node) ||\n ts.isFunctionExpression(node) ||\n ts.isArrowFunction(node) ||\n ts.isMethodDeclaration(node)\n );\n}\n\nfunction unwrapExpression(node: ts.Expression): ts.Expression {\n if (ts.isParenthesizedExpression(node)) return unwrapExpression(node.expression);\n if (ts.isAsExpression(node)) return unwrapExpression(node.expression);\n return node;\n}\n\nfunction getBody(node: ts.Node): ts.Block | undefined {\n if (ts.isFunctionDeclaration(node) && node.body) return node.body;\n if (ts.isFunctionExpression(node) && node.body) return node.body;\n if (ts.isArrowFunction(node) && ts.isBlock(node.body)) return node.body;\n if (ts.isMethodDeclaration(node) && node.body) return node.body;\n return undefined;\n}\n\nfunction collectReturnShapes(\n funcNode: ts.Node,\n file: string,\n funcLine: number,\n functionName: string,\n sourceFile: ts.SourceFile,\n shapeMap: Map<string, ReturnShapeEntry[]>,\n): void {\n // Arrow function with expression body\n if (ts.isArrowFunction(funcNode) && !ts.isBlock(funcNode.body)) {\n const expr = unwrapExpression(funcNode.body);\n if (ts.isObjectLiteralExpression(expr)) {\n addShape(expr, file, funcLine, functionName, sourceFile, shapeMap);\n }\n return;\n }\n\n const body = getBody(funcNode);\n if (!body) return;\n\n function walkForReturns(node: ts.Node): void {\n if (ts.isReturnStatement(node) && node.expression) {\n const expr = unwrapExpression(node.expression);\n if (ts.isObjectLiteralExpression(expr)) {\n addShape(expr, file, funcLine, functionName, sourceFile, shapeMap);\n }\n }\n // Don't recurse into nested function-like nodes\n if (isFunctionLike(node)) return;\n ts.forEachChild(node, walkForReturns);\n }\n ts.forEachChild(body, walkForReturns);\n}\n\nfunction addShape(\n objLiteral: ts.ObjectLiteralExpression,\n file: string,\n funcLine: number,\n functionName: string,\n sourceFile: ts.SourceFile,\n shapeMap: Map<string, ReturnShapeEntry[]>,\n): void {\n const props = extractPropertyNames(objLiteral);\n if (props === null || props.length < 2) return;\n const { sorted, list } = getShapeGroup(shapeMap, props);\n list.push({ file, line: funcLine, functionName, props: sorted });\n}\n\nfunction isCallbackArgument(node: ts.Node): boolean {\n let current: ts.Node = node;\n if (ts.isParenthesizedExpression(current.parent)) {\n current = current.parent;\n }\n const parent = current.parent;\n if (!ts.isCallExpression(parent)) return false;\n return parent.arguments.some((arg) => arg === current);\n}\n\nfunction buildKnownTypeShapes(typeEntries: TypeEntry[]): Set<string> {\n const shapes = new Set<string>();\n for (const entry of typeEntries) {\n const props = extractTypePropertyNames(entry.node);\n if (props && props.length >= 2) {\n shapes.add([...props].sort().join(\"\\0\"));\n }\n }\n return shapes;\n}\n\nfunction extractTypePropertyNames(node: ts.Node): string[] | null {\n let members: ts.NodeArray<ts.TypeElement> | undefined;\n if (ts.isTypeLiteralNode(node)) {\n members = node.members;\n } else if (ts.isInterfaceDeclaration(node)) {\n members = node.members;\n }\n if (!members) return null;\n\n const names: string[] = [];\n for (const member of members) {\n if (ts.isPropertySignature(member) && member.name) {\n if (ts.isIdentifier(member.name)) names.push(member.name.text);\n else if (ts.isStringLiteral(member.name)) names.push(member.name.text);\n else return null;\n }\n }\n return names.length > 0 ? names : null;\n}\n\nfunction deriveFunctionName(node: ts.Node, sourceFile: ts.SourceFile): string {\n if (ts.isFunctionDeclaration(node) && node.name) {\n return node.name.text;\n }\n if (ts.isMethodDeclaration(node) && ts.isIdentifier(node.name)) {\n const parent = node.parent;\n if (ts.isClassDeclaration(parent) && parent.name) {\n return `${parent.name.text}.${node.name.text}`;\n }\n return node.name.text;\n }\n const parent = node.parent;\n if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {\n return parent.name.text;\n }\n if (ts.isPropertyAssignment(parent) && ts.isIdentifier(parent.name)) {\n return parent.name.text;\n }\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n return `<anonymous>:${line}`;\n}\n","import * as ts from \"typescript\";\n\n/** Extract static property names from an object literal. Returns null if any property is dynamic (spread, computed). */\nexport function extractPropertyNames(node: ts.ObjectLiteralExpression): string[] | null {\n const names: string[] = [];\n for (const prop of node.properties) {\n if (ts.isSpreadAssignment(prop)) return null;\n if (ts.isPropertyAssignment(prop)) {\n if (ts.isIdentifier(prop.name)) names.push(prop.name.text);\n else if (ts.isStringLiteral(prop.name)) names.push(prop.name.text);\n else return null;\n } else if (ts.isShorthandPropertyAssignment(prop)) {\n names.push(prop.name.text);\n } else if (ts.isMethodDeclaration(prop)) {\n if (ts.isIdentifier(prop.name)) names.push(prop.name.text);\n else return null;\n } else if (ts.isGetAccessorDeclaration(prop) || ts.isSetAccessorDeclaration(prop)) {\n if (ts.isIdentifier(prop.name)) names.push(prop.name.text);\n else return null;\n }\n }\n return names;\n}\n\n/** Sort property names, compute a canonical key, and get-or-create the group list in the map. */\nexport function getShapeGroup<T>(map: Map<string, T[]>, props: string[]): { sorted: string[]; list: T[] } {\n const sorted = [...props].sort();\n const key = sorted.join(\"\\0\");\n let list = map.get(key);\n if (!list) {\n list = [];\n map.set(key, list);\n }\n return { sorted, list };\n}\n","import * as ts from \"typescript\";\nimport type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\nimport type { FunctionEntry } from \"../../collect/function-registry.ts\";\n\ninterface TrivialCallTarget {\n calleeName: string;\n}\n\nfunction getFunctionBody(node: ts.Node): ts.Block | ts.Expression | undefined {\n if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) {\n return node.body;\n }\n if (ts.isArrowFunction(node)) {\n return node.body;\n }\n if (ts.isMethodDeclaration(node)) {\n return node.body;\n }\n return undefined;\n}\n\nfunction getCalleeName(expr: ts.Expression): string | undefined {\n if (ts.isIdentifier(expr)) return expr.text;\n if (ts.isPropertyAccessExpression(expr)) return expr.name.text;\n return undefined;\n}\n\nfunction getTrivialCallTarget(fn: FunctionEntry): TrivialCallTarget | null {\n const body = getFunctionBody(fn.node);\n if (!body) return null;\n\n let callExpr: ts.CallExpression | undefined;\n\n if (ts.isBlock(body)) {\n // Block body: exactly one statement that is `return callee(args)`\n if (body.statements.length !== 1) return null;\n const stmt = body.statements[0];\n if (!stmt || !ts.isReturnStatement(stmt) || !stmt.expression) return null;\n if (!ts.isCallExpression(stmt.expression)) return null;\n callExpr = stmt.expression;\n } else {\n // Expression body arrow: `=> callee(args)`\n if (!ts.isCallExpression(body)) return null;\n callExpr = body;\n }\n\n const calleeName = getCalleeName(callExpr.expression);\n if (!calleeName) return null;\n\n // All arguments must be plain identifiers matching the function's own param names\n const paramNames = fn.params.map((p) => p.name);\n const args = callExpr.arguments;\n\n // Args must be a subset of params (in order or not), but every arg must be a plain param reference\n for (const arg of args) {\n if (!ts.isIdentifier(arg)) return null;\n if (!paramNames.includes(arg.text)) return null;\n }\n\n return { calleeName };\n}\n\nexport const trivialWrapper: CrossFileRule = {\n id: \"trivial-wrapper\",\n severity: \"info\",\n message:\n \"Function is a trivial wrapper that delegates without transformation; consider using the target directly\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const knownFunctions = new Set(\n project.functions.getAll().map((f) => f.name),\n );\n\n for (const fn of project.functions.getAll()) {\n const target = getTrivialCallTarget(fn);\n if (!target) continue;\n // Don't flag if the callee isn't a known project function\n if (!knownFunctions.has(target.calleeName)) continue;\n // Don't flag if wrapper and target have the same name (re-export pattern)\n if (fn.name === target.calleeName) continue;\n\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Function \"${fn.name}\" trivially wraps \"${target.calleeName}\" without transformation`,\n file: fn.file,\n line: fn.line,\n column: 1,\n });\n }\n return diagnostics;\n },\n};\n","import type * as ts from \"typescript\";\nimport type { CrossFileRule, Diagnostic, ProjectIndex } from \"../types.ts\";\n\nexport const unusedExport: CrossFileRule = {\n id: \"unused-export\",\n severity: \"info\",\n message: \"Exported function has no usages within the project\",\n\n analyze(project: ProjectIndex): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n // Build set of declaration nodes referenced by call sites.\n // Using valueDeclaration (the AST node) instead of symbol identity\n // so that inherited class methods are correctly matched — a call to\n // `subclass.method()` resolves through the prototype chain to the\n // same declaration node as the base class method entry.\n const usedDeclarations = new Set<ts.Node>();\n const usedNamesByFile = new Map<string, Set<string>>();\n\n for (const site of project.callSites) {\n if (site.symbol?.valueDeclaration) {\n usedDeclarations.add(site.symbol.valueDeclaration);\n }\n let files = usedNamesByFile.get(site.calleeName);\n if (!files) {\n files = new Set();\n usedNamesByFile.set(site.calleeName, files);\n }\n files.add(site.file);\n }\n\n // Also count imports as usage\n for (const imp of project.imports) {\n let files = usedNamesByFile.get(imp.importedName);\n if (!files) {\n files = new Set();\n usedNamesByFile.set(imp.importedName, files);\n }\n files.add(imp.file);\n }\n\n // Build set of class names that are imported from other files.\n // When a class is imported, its public methods are reachable — callers\n // may interact through an interface type (DI, Effect layers) where the\n // call-site symbol resolves to the interface method, not the class method.\n const importedClassNames = buildImportedClassNames(project);\n\n for (const fn of project.functions.getAll()) {\n if (!fn.exported) continue;\n if (isEntryPoint(fn.file)) continue;\n\n // Class methods on classes that implement an interface are contract\n // obligations — they exist to fulfill the interface, not as independent API\n if (fn.implementsInterface) continue;\n\n // Class methods on classes imported from other files are reachable\n // through the class instance, even when calls go through an interface type\n if (fn.className && isClassImported(fn.className, fn.file, importedClassNames)) continue;\n\n // Check declaration-based usage (handles inheritance)\n if (fn.symbol?.valueDeclaration && usedDeclarations.has(fn.symbol.valueDeclaration)) continue;\n\n // Fallback: check name-based usage from OTHER files\n const nameUsers = usedNamesByFile.get(fn.name);\n if (nameUsers) {\n const hasExternalUser = [...nameUsers].some((f) => f !== fn.file);\n if (hasExternalUser) continue;\n }\n\n diagnostics.push({\n ruleId: this.id,\n severity: this.severity,\n message: `Exported function \"${fn.name}\" has no usages in the project`,\n file: fn.file,\n line: fn.line,\n column: 1,\n });\n }\n return diagnostics;\n },\n};\n\nfunction isEntryPoint(file: string): boolean {\n if (/\\/index\\.[cm]?[jt]sx?$/.test(file)) return true;\n if (/\\/bin\\//.test(file)) return true;\n return false;\n}\n\n/** Map each class name to the set of files that import it. */\nfunction buildImportedClassNames(project: ProjectIndex): Map<string, Set<string>> {\n const map = new Map<string, Set<string>>();\n for (const imp of project.imports) {\n let files = map.get(imp.importedName);\n if (!files) {\n files = new Set();\n map.set(imp.importedName, files);\n }\n files.add(imp.file);\n }\n return map;\n}\n\n/** Check if a class is imported from a file other than where it's declared. */\nfunction isClassImported(className: string, declFile: string, importedNames: Map<string, Set<string>>): boolean {\n const importers = importedNames.get(className);\n if (!importers) return false;\n return [...importers].some((f) => f !== declFile);\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noAnyCast: TSRule = {\n kind: \"ts\",\n id: \"no-any-cast\",\n severity: \"error\",\n message: \"Casting to `any` erases type safety; use a specific type or generic instead\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isAsExpression(node)) return;\n if (node.type.kind !== ts.SyntaxKind.AnyKeyword) return;\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noCatchReturn: TSRule = {\n kind: \"ts\",\n id: \"no-catch-return\",\n severity: \"warning\",\n message:\n \"Catch block silently returns a fallback value with no logging; rethrow, log the error, or let it propagate\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isCatchClause(node)) return;\n const block = node.block;\n if (hasReturn(block) && !hasThrow(block) && !hasLogging(block)) {\n ctx.report(node);\n }\n },\n};\n\nfunction walkBlock(block: ts.Block, predicate: (node: ts.Node) => boolean): boolean {\n function visit(node: ts.Node): boolean {\n if (predicate(node)) return true;\n if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) return false;\n return ts.forEachChild(node, visit) ?? false;\n }\n return ts.forEachChild(block, visit) ?? false;\n}\n\nfunction hasReturn(block: ts.Block): boolean {\n return walkBlock(block, (n) => ts.isReturnStatement(n));\n}\n\nfunction hasThrow(block: ts.Block): boolean {\n return walkBlock(block, (n) => ts.isThrowStatement(n));\n}\n\nconst LOG_OBJECTS = new Set([\"console\", \"logger\", \"log\"]);\n\nfunction hasLogging(block: ts.Block): boolean {\n return walkBlock(block, (n) => {\n if (!ts.isCallExpression(n)) return false;\n const callee = n.expression;\n if (!ts.isPropertyAccessExpression(callee)) return false;\n if (!ts.isIdentifier(callee.expression)) return false;\n return LOG_OBJECTS.has(callee.expression.text);\n });\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\nimport { includesBooleanType } from \"../../typecheck/utils.ts\";\n\nexport const noDoubleNegationCoercion: TSRule = {\n kind: \"ts\",\n id: \"no-double-negation-coercion\",\n severity: \"info\",\n message: \"!! coercion hides intent; use an explicit check (!== null, !== undefined, .length > 0) so the condition documents what it tests\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isPrefixUnaryExpression(node)) return;\n if (node.operator !== ts.SyntaxKind.ExclamationToken) return;\n const inner = node.operand;\n if (!ts.isPrefixUnaryExpression(inner)) return;\n if (inner.operator !== ts.SyntaxKind.ExclamationToken) return;\n\n const operand = inner.operand;\n\n // Already boolean -> !! is a no-op, promote severity\n const innerType = ctx.checker.getTypeAtLocation(operand);\n if (includesBooleanType(innerType) && !(innerType.flags & ts.TypeFlags.Union)) {\n ctx.report(node, \"!! on an already-boolean type is a no-op; remove the double negation\");\n return;\n }\n\n // Bitwise expression: !!(flags & MASK) is the standard idiom for flag testing\n if (isBitwiseExpression(operand)) return;\n\n ctx.report(node);\n },\n};\n\nconst BITWISE_OPS = new Set([\n ts.SyntaxKind.AmpersandToken,\n ts.SyntaxKind.BarToken,\n ts.SyntaxKind.CaretToken,\n ts.SyntaxKind.LessThanLessThanToken,\n ts.SyntaxKind.GreaterThanGreaterThanToken,\n ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken,\n]);\n\nfunction isBitwiseExpression(node: ts.Node): boolean {\n // Direct: !!(a & b)\n if (ts.isBinaryExpression(node) && BITWISE_OPS.has(node.operatorToken.kind)) return true;\n // Parenthesized: !!((a & b) | c)\n if (ts.isParenthesizedExpression(node)) return isBitwiseExpression(node.expression);\n return false;\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noDynamicImport: TSRule = {\n kind: \"ts\",\n id: \"no-dynamic-import\",\n severity: \"error\",\n message: \"Dynamic import() breaks static analysis and hides dependencies; use a static import instead\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isCallExpression(node)) return;\n if (node.expression.kind !== ts.SyntaxKind.ImportKeyword) return;\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noEmptyCatch: TSRule = {\n kind: \"ts\",\n id: \"no-empty-catch\",\n severity: \"error\",\n message: \"Empty catch blocks hide failures; handle, annotate, or rethrow explicitly\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isCatchClause(node)) return;\n const block = node.block;\n if (block.statements.length > 0) return;\n\n // Check for comments inside the block braces\n const blockStart = block.getStart(ctx.sourceFile);\n const blockEnd = block.getEnd();\n const inner = ctx.source.slice(blockStart + 1, blockEnd - 1);\n if (inner.includes(\"//\") || inner.includes(\"/*\")) return;\n\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noErrorRewrap: TSRule = {\n kind: \"ts\",\n id: \"no-error-rewrap\",\n severity: \"error\",\n message:\n \"Re-wrapped error loses the original stack trace and type; use { cause: originalError } to preserve the error chain\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isCatchClause(node)) return;\n if (!node.variableDeclaration) return;\n const param = node.variableDeclaration.name;\n if (!ts.isIdentifier(param)) return;\n const catchName = param.text;\n findRewraps(node.block, catchName, ctx);\n },\n};\n\nfunction findRewraps(block: ts.Block, catchName: string, ctx: TSVisitContext): void {\n function visit(node: ts.Node): void {\n if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) return;\n if (ts.isThrowStatement(node) && node.expression && ts.isNewExpression(node.expression)) {\n const args = node.expression.arguments;\n if (args && args.length > 0 && referencesName(args, catchName) && !hasCauseArg(args)) {\n ctx.report(node);\n }\n return;\n }\n ts.forEachChild(node, visit);\n }\n ts.forEachChild(block, visit);\n}\n\nfunction referencesName(args: readonly ts.Expression[], name: string): boolean {\n for (const arg of args) {\n if (containsIdentifier(arg, name)) return true;\n }\n return false;\n}\n\nfunction containsIdentifier(node: ts.Node, name: string): boolean {\n if (ts.isIdentifier(node) && node.text === name) return true;\n return ts.forEachChild(node, (child) => containsIdentifier(child, name) || undefined) ?? false;\n}\n\nfunction hasCauseArg(args: readonly ts.Expression[]): boolean {\n for (const arg of args) {\n if (ts.isObjectLiteralExpression(arg)) {\n for (const prop of arg.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === \"cause\") return true;\n if (ts.isShorthandPropertyAssignment(prop) && prop.name.text === \"cause\") return true;\n }\n }\n }\n return false;\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noExplicitAnyAnnotation: TSRule = {\n kind: \"ts\",\n id: \"no-explicit-any-annotation\",\n severity: \"error\",\n message: \"Explicit `any` annotation erases type safety; use a specific type, `unknown`, or a generic\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (node.kind !== ts.SyntaxKind.AnyKeyword) return;\n if (node.parent && ts.isAsExpression(node.parent)) return;\n ctx.report(node);\n },\n};\n","import type * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\nimport { isInlineParamType } from \"../../typecheck/utils.ts\";\n\nexport const noInlineParamType: TSRule = {\n kind: \"ts\",\n id: \"no-inline-param-type\",\n severity: \"warning\",\n message:\n \"Inline object type on parameter; extract to a named type\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (isInlineParamType(node)) ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noInlineTypeAssertion: TSRule = {\n kind: \"ts\",\n id: \"no-inline-type-assertion\",\n severity: \"error\",\n message: \"Inline object type assertions (`x as { ... }`) hide missing named types; extract a named type or fix the upstream type\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (ts.isAsExpression(node) && ts.isTypeLiteralNode(node.type)) {\n ctx.report(node);\n return;\n }\n\n if (ts.isTypeAssertionExpression(node) && ts.isTypeLiteralNode(node.type)) {\n ctx.report(node);\n }\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\nimport { includesNumberType, isNullableType } from \"../../typecheck/utils.ts\";\n\nexport const noLogicalOrFallback: TSRule = {\n kind: \"ts\",\n id: \"no-logical-or-fallback\",\n severity: \"warning\",\n message:\n '|| fallback on a data-structure lookup swallows valid falsy values (0, \"\"); use ?? to only catch null/undefined',\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isBinaryExpression(node)) return;\n if (node.operatorToken.kind !== ts.SyntaxKind.BarBarToken) return;\n\n const right = node.right;\n if (!isLiteral(right)) return;\n\n const left = node.left;\n const lhsType = ctx.checker.getTypeAtLocation(left);\n\n // Number() / parseInt() — || catches NaN/0 intentionally, ?? would not help\n if (isNumericCoercionCall(left)) return;\n\n // String type without undefined: || catches \"\" intentionally — suppress\n // String | undefined: || swallows \"\" AND catches undefined — should use ??\n if (isStringNotNullable(lhsType, ctx.checker)) return;\n\n // LHS includes number and RHS is not 0 -> catches bugs like `seed || undefined`\n if (includesNumberType(lhsType) && !isZeroLiteral(right)) {\n ctx.report(node, '|| on a numeric type swallows 0; use ?? to only catch null/undefined');\n return;\n }\n\n // Data-structure lookups: .get(), .find(), x[key], optional chaining\n if (isDataStructureLookup(left)) {\n ctx.report(node);\n }\n },\n};\n\n/** LHS is string (or string-like) without null/undefined in the union. */\nfunction isStringNotNullable(type: ts.Type, checker: ts.TypeChecker): boolean {\n if (isNullableType(checker, type)) return false;\n if (type.isUnion()) {\n return type.types.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0);\n }\n return (type.flags & ts.TypeFlags.StringLike) !== 0;\n}\n\nfunction isLiteral(node: ts.Node): boolean {\n if (ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return true;\n if (ts.isTemplateExpression(node)) return true;\n if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) return true;\n if (ts.isIdentifier(node) && node.text === \"undefined\") return true;\n if (node.kind === ts.SyntaxKind.NullKeyword) return true;\n if (node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword) return true;\n return false;\n}\n\n/** Number(...) or parseInt(...) — returns number, || catches NaN/0, ?? wouldn't help */\nfunction isNumericCoercionCall(node: ts.Node): boolean {\n if (!ts.isCallExpression(node)) return false;\n if (!ts.isIdentifier(node.expression)) return false;\n const name = node.expression.text;\n return name === \"Number\" || name === \"parseInt\" || name === \"parseFloat\";\n}\n\nfunction isZeroLiteral(node: ts.Node): boolean {\n return ts.isNumericLiteral(node) && node.text === \"0\";\n}\n\nfunction isDataStructureLookup(left: ts.Node): boolean {\n // Flag: LHS is .get(), .find(), .getStore() call\n if (ts.isCallExpression(left)) {\n const callee = left.expression;\n if (ts.isPropertyAccessExpression(callee)) {\n const methodName = callee.name.text;\n if (methodName === \"find\" || methodName === \"getStore\" || methodName === \"get\") return true;\n }\n }\n\n // Flag: LHS is computed member expression x[key]\n if (ts.isElementAccessExpression(left)) return true;\n\n // Flag: LHS contains optional chaining (?.)\n if (hasOptionalChaining(left)) return true;\n\n return false;\n}\n\nfunction hasOptionalChaining(node: ts.Node): boolean {\n if (ts.isPropertyAccessExpression(node) && node.questionDotToken) return true;\n if (ts.isElementAccessExpression(node) && node.questionDotToken) return true;\n if (ts.isCallExpression(node) && node.questionDotToken) return true;\n if (ts.isPropertyAccessExpression(node)) return hasOptionalChaining(node.expression);\n if (ts.isCallExpression(node)) return hasOptionalChaining(node.expression);\n if (ts.isElementAccessExpression(node)) return hasOptionalChaining(node.expression);\n return false;\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noNonNullAssertion: TSRule = {\n kind: \"ts\",\n id: \"no-non-null-assertion\",\n severity: \"warning\",\n message: \"Non-null assertion (!) overrides the type checker; narrow with a type guard or fix the type so it's not nullable\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isNonNullExpression(node)) return;\n\n const inner = node.expression;\n\n // Type already non-nullable -> ! is redundant noise, not worth flagging\n if (!ctx.isNullable(inner)) return;\n\n // External library type gap -> suppress\n if (ctx.isExternal(inner)) return;\n\n // split(...)[n]! — always safe\n if (isSplitElementAccess(inner)) return;\n\n // filter(...)[n]! — safe pattern (narrowed array)\n if (isFilterElementAccess(inner)) return;\n\n // arr[n]! after a length guard — provably safe\n if (isLengthGuardedAccess(inner)) return;\n\n ctx.report(node);\n },\n};\n\nfunction isSplitElementAccess(node: ts.Node): boolean {\n if (!ts.isElementAccessExpression(node)) return false;\n const obj = node.expression;\n if (!ts.isCallExpression(obj)) return false;\n const callee = obj.expression;\n if (!ts.isPropertyAccessExpression(callee)) return false;\n return callee.name.text === \"split\";\n}\n\nfunction isFilterElementAccess(node: ts.Node): boolean {\n // Direct: items.filter(...)[n]!\n if (ts.isElementAccessExpression(node)) {\n const obj = node.expression;\n if (ts.isCallExpression(obj)) {\n const callee = obj.expression;\n if (ts.isPropertyAccessExpression(callee) && callee.name.text === \"filter\") return true;\n }\n // Indirect: const filtered = items.filter(...); filtered[n]!\n if (ts.isIdentifier(obj)) {\n const init = findVariableInit(obj);\n if (init && ts.isCallExpression(init)) {\n const callee = init.expression;\n if (ts.isPropertyAccessExpression(callee) && callee.name.text === \"filter\") return true;\n }\n }\n }\n return false;\n}\n\n/** Detect arr[n]! where arr.length is checked in a preceding guard or enclosing for-loop. */\nfunction isLengthGuardedAccess(node: ts.Node): boolean {\n if (!ts.isElementAccessExpression(node)) return false;\n const arr = node.expression;\n\n const arrName = getIdentifierName(arr);\n if (!arrName) return false;\n\n // Check for enclosing for-loop: for (let i = 0; i < arr.length; i++)\n if (isInsideForLoopBoundedBy(node, arrName)) return true;\n\n // Check for preceding length guard in same block\n return hasPrecedingLengthGuard(node, arrName);\n}\n\n/** Walk ancestors to find a for-loop whose condition bounds against arrName.length. */\nfunction isInsideForLoopBoundedBy(node: ts.Node, arrName: string): boolean {\n let current: ts.Node = node;\n while (current.parent) {\n current = current.parent;\n if (ts.isForStatement(current) && current.condition) {\n if (isLengthBoundCondition(current.condition, arrName)) return true;\n }\n }\n return false;\n}\n\n/** Check if a condition is `i < arr.length` or similar. */\nfunction isLengthBoundCondition(cond: ts.Expression, arrName: string): boolean {\n if (!ts.isBinaryExpression(cond)) return false;\n const op = cond.operatorToken.kind;\n // i < arr.length or i <= arr.length - 1\n if (op === ts.SyntaxKind.LessThanToken || op === ts.SyntaxKind.LessThanEqualsToken) {\n return isLengthAccess(cond.right, arrName);\n }\n // arr.length > i\n if (op === ts.SyntaxKind.GreaterThanToken || op === ts.SyntaxKind.GreaterThanEqualsToken) {\n return isLengthAccess(cond.left, arrName);\n }\n return false;\n}\n\n/** Check if node is `arrName.length`. */\nfunction isLengthAccess(node: ts.Node, arrName: string): boolean {\n if (!ts.isPropertyAccessExpression(node)) return false;\n if (node.name.text !== \"length\") return false;\n return getIdentifierName(node.expression) === arrName;\n}\n\n/**\n * Check if there's a preceding statement in the same block (or a parent block)\n * that guards on arrName.length, implying the array is non-empty.\n *\n * Patterns:\n * - if (arr.length === 0) return;\n * - if (arr.length < N) return; (where N >= 1)\n * - if (arr.length > 0) { ... arr[0]! ... }\n * - if (arr.length !== 0) { ... arr[0]! ... }\n * - if (arr.length >= 1) { ... arr[0]! ... }\n * - if (arr.length !== N) return; (where N >= 1)\n */\nfunction hasPrecedingLengthGuard(node: ts.Node, arrName: string): boolean {\n // Walk up to find the containing block/if-statement\n let current: ts.Node = node;\n while (current.parent) {\n const parent = current.parent;\n\n // Case 1: we're in a block and a preceding if-statement guards length with early return\n if (ts.isBlock(parent)) {\n for (const stmt of parent.statements) {\n if (stmt === current || stmt.pos >= current.pos) break;\n if (ts.isIfStatement(stmt) && isLengthGuardWithEarlyExit(stmt, arrName)) return true;\n }\n }\n\n // Case 2: we're inside the then-branch of an if that checks length > 0\n if (ts.isIfStatement(parent) && parent.thenStatement === current) {\n if (isPositiveLengthCheck(parent.expression, arrName)) return true;\n }\n // Also handle: if (...) { <block containing current> }\n if (ts.isBlock(current) && ts.isIfStatement(parent) && parent.thenStatement === current) {\n if (isPositiveLengthCheck(parent.expression, arrName)) return true;\n }\n\n current = parent;\n }\n return false;\n}\n\n/** if (arr.length === 0) return/throw; or if (arr.length < 1) return/throw; etc. */\nfunction isLengthGuardWithEarlyExit(stmt: ts.IfStatement, arrName: string): boolean {\n if (!isEarlyExit(stmt.thenStatement)) return false;\n return isZeroLengthCheck(stmt.expression, arrName);\n}\n\n/** Checks if condition means \"arr is empty\": arr.length === 0, arr.length < 1, arr.length !== N (N>=1) */\nfunction isZeroLengthCheck(expr: ts.Expression, arrName: string): boolean {\n if (!ts.isBinaryExpression(expr)) return false;\n const op = expr.operatorToken.kind;\n\n // arr.length === 0\n if ((op === ts.SyntaxKind.EqualsEqualsEqualsToken || op === ts.SyntaxKind.EqualsEqualsToken)) {\n if (isLengthAccess(expr.left, arrName) && isNumericLiteralValue(expr.right, 0)) return true;\n if (isLengthAccess(expr.right, arrName) && isNumericLiteralValue(expr.left, 0)) return true;\n }\n\n // arr.length < 1 (or any N >= 1)\n if (op === ts.SyntaxKind.LessThanToken) {\n if (isLengthAccess(expr.left, arrName) && isNumericLiteralGte(expr.right, 1)) return true;\n }\n\n // arr.length !== N where N >= 1 (e.g., if (arr.length !== 1) return; arr[0]!)\n if ((op === ts.SyntaxKind.ExclamationEqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken)) {\n if (isLengthAccess(expr.left, arrName) && isNumericLiteralGte(expr.right, 1)) return true;\n }\n\n return false;\n}\n\n/** Checks if condition means \"arr is non-empty\": arr.length > 0, arr.length !== 0, arr.length >= 1 */\nfunction isPositiveLengthCheck(expr: ts.Expression, arrName: string): boolean {\n if (!ts.isBinaryExpression(expr)) return false;\n const op = expr.operatorToken.kind;\n\n // arr.length > 0\n if (op === ts.SyntaxKind.GreaterThanToken) {\n if (isLengthAccess(expr.left, arrName) && isNumericLiteralValue(expr.right, 0)) return true;\n }\n\n // arr.length >= 1\n if (op === ts.SyntaxKind.GreaterThanEqualsToken) {\n if (isLengthAccess(expr.left, arrName) && isNumericLiteralGte(expr.right, 1)) return true;\n }\n\n // arr.length !== 0\n if ((op === ts.SyntaxKind.ExclamationEqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken)) {\n if (isLengthAccess(expr.left, arrName) && isNumericLiteralValue(expr.right, 0)) return true;\n }\n\n return false;\n}\n\nfunction isEarlyExit(stmt: ts.Statement): boolean {\n if (ts.isReturnStatement(stmt) || ts.isThrowStatement(stmt)) return true;\n if (ts.isBlock(stmt) && stmt.statements.length === 1) {\n const inner = stmt.statements[0];\n if (inner === undefined) return false;\n return ts.isReturnStatement(inner) || ts.isThrowStatement(inner);\n }\n return false;\n}\n\nfunction isNumericLiteralValue(node: ts.Node, value: number): boolean {\n return ts.isNumericLiteral(node) && node.text === String(value);\n}\n\nfunction isNumericLiteralGte(node: ts.Node, min: number): boolean {\n return ts.isNumericLiteral(node) && Number(node.text) >= min;\n}\n\nfunction getIdentifierName(node: ts.Node): string | null {\n if (ts.isIdentifier(node)) return node.text;\n return null;\n}\n\nfunction findVariableInit(id: ts.Identifier): ts.Expression | undefined {\n const sourceFile = id.getSourceFile();\n let result: ts.Expression | undefined;\n function visit(node: ts.Node): void {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === id.text && node.initializer) {\n result = node.initializer;\n }\n if (!result) ts.forEachChild(node, visit);\n }\n visit(sourceFile);\n return result;\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noNullTernaryNormalization: TSRule = {\n kind: \"ts\",\n id: \"no-null-ternary-normalization\",\n severity: \"warning\",\n message: \"Ternary null-normalization (x == null ? fallback : x); if the type guarantees non-null, remove the ternary; if not, fix the type upstream\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isConditionalExpression(node)) return;\n const test = node.condition;\n if (!ts.isBinaryExpression(test)) return;\n\n const op = test.operatorToken.kind;\n if (\n op !== ts.SyntaxKind.EqualsEqualsEqualsToken &&\n op !== ts.SyntaxKind.ExclamationEqualsEqualsToken &&\n op !== ts.SyntaxKind.EqualsEqualsToken &&\n op !== ts.SyntaxKind.ExclamationEqualsToken\n ) return;\n\n const hasNullishComparand = isNullish(test.left) || isNullish(test.right);\n if (!hasNullishComparand) return;\n\n if (isNullish(node.whenTrue) || isNullish(node.whenFalse)) {\n // Non-nullable tested value -> this is dead code\n const tested = isNullish(test.left) ? test.right : test.left;\n if (!ctx.isNullable(tested)) {\n ctx.report(node, \"Ternary null-normalization on a non-nullable type is dead code; remove the ternary\");\n return;\n }\n ctx.report(node);\n }\n },\n};\n\nfunction isNullish(node: ts.Node): boolean {\n if (node.kind === ts.SyntaxKind.NullKeyword) return true;\n if (ts.isIdentifier(node) && node.text === \"undefined\") return true;\n // void 0\n if (ts.isVoidExpression(node)) return true;\n return false;\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noNullishCoalescing: TSRule = {\n kind: \"ts\",\n id: \"no-nullish-coalescing\",\n severity: \"warning\",\n message: \"Nullish coalescing (??) on a non-nullable type is unreachable; remove the fallback or fix the type upstream\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isBinaryExpression(node)) return;\n if (node.operatorToken.kind !== ts.SyntaxKind.QuestionQuestionToken) return;\n if (isPossiblyMissingArrayBindingValue(node.left, ctx)) return;\n if (ctx.isNullable(node.left)) return;\n ctx.report(node);\n },\n};\n\nfunction isPossiblyMissingArrayBindingValue(node: ts.Node, ctx: TSVisitContext): boolean {\n if (!ts.isIdentifier(node)) return false;\n\n const symbol = ctx.checker.getSymbolAtLocation(node);\n if (!symbol) return false;\n\n for (const declaration of symbol.declarations ?? []) {\n if (!ts.isBindingElement(declaration)) continue;\n if (declaration.initializer || declaration.dotDotDotToken) continue;\n if (!ts.isArrayBindingPattern(declaration.parent)) continue;\n\n const pattern = declaration.parent;\n const index = pattern.elements.indexOf(declaration);\n if (index < 0) continue;\n\n if (!isTupleSlotDefinitelyPresent(ctx.checker.getTypeAtLocation(pattern), index, ctx.checker)) {\n // Without noUncheckedIndexedAccess, TS treats `[x] = T[]` as `x: T`, even though runtime can produce undefined.\n return true;\n }\n }\n\n return false;\n}\n\nfunction isTupleSlotDefinitelyPresent(type: ts.Type, index: number, checker: ts.TypeChecker): boolean {\n if (type.isUnion()) {\n return type.types.every((member) => isTupleSlotDefinitelyPresent(member, index, checker));\n }\n\n const apparent = checker.getApparentType(type);\n if (!isTupleTypeReference(apparent, checker)) return false;\n return index < apparent.target.minLength;\n}\n\nfunction isTupleTypeReference(type: ts.Type, checker: ts.TypeChecker): type is ts.TupleTypeReference {\n if (!checker.isTupleType(type)) return false;\n if (!(\"target\" in type)) return false;\n\n const target = type.target;\n if (typeof target !== \"object\" || target === null) return false;\n if (!(\"minLength\" in target)) return false;\n\n return typeof target.minLength === \"number\";\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noOptionalCall: TSRule = {\n kind: \"ts\",\n id: \"no-optional-call\",\n severity: \"warning\",\n message: \"Optional call (?.) on a non-nullable function is redundant; call directly or fix the type upstream\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isCallExpression(node)) return;\n if (!node.questionDotToken) return;\n if (ctx.isNullable(node.expression)) return;\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noOptionalElementAccess: TSRule = {\n kind: \"ts\",\n id: \"no-optional-element-access\",\n severity: \"warning\",\n message: \"Optional element access (?.[]) on a non-nullable type is redundant; use direct access or fix the type upstream\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isElementAccessExpression(node)) return;\n if (!node.questionDotToken) return;\n if (ctx.isNullable(node.expression)) return;\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noOptionalPropertyAccess: TSRule = {\n kind: \"ts\",\n id: \"no-optional-property-access\",\n severity: \"warning\",\n message: \"Optional chaining (?.) on a non-nullable type is redundant; use direct access or fix the type upstream\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isPropertyAccessExpression(node)) return;\n if (!node.questionDotToken) return;\n if (ctx.isNullable(node.expression)) return;\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\nimport { isNullishLiteral } from \"../../typecheck/utils.ts\";\n\nexport const noRedundantExistenceGuard: TSRule = {\n kind: \"ts\",\n id: \"no-redundant-existence-guard\",\n severity: \"warning\",\n message: \"Redundant existence guard (obj && obj.prop) on a non-nullable type; remove the guard or fix the type upstream\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isBinaryExpression(node)) return;\n if (node.operatorToken.kind !== ts.SyntaxKind.AmpersandAmpersandToken) return;\n\n const left = node.left;\n const right = node.right;\n\n // Pattern 1: obj && obj.prop / obj.method() / obj[key]\n if (ts.isIdentifier(left) && accessesIdentifier(right, left.text)) {\n if (ctx.isNullable(left)) return;\n ctx.report(node);\n return;\n }\n\n // Pattern 2: obj != null && obj.prop (or !== null, !== undefined)\n if (ts.isBinaryExpression(left) && isNullCheck(left)) {\n const checked = getNullCheckedIdentifier(left);\n if (checked && accessesIdentifier(right, checked)) {\n // The null-check LHS is the identifier — check its type before the comparison\n // If the type is non-nullable, the entire guard is redundant\n const identNode = ts.isIdentifier(left.left) ? left.left : left.right;\n if (ts.isIdentifier(identNode) && identNode.text === checked && !ctx.isNullable(identNode)) {\n ctx.report(node);\n }\n }\n }\n },\n};\n\n/** Check if the root object of `expr` is identifier `name`. */\nfunction accessesIdentifier(expr: ts.Node, name: string): boolean {\n const root = getExpressionRoot(expr);\n return ts.isIdentifier(root) && root.text === name;\n}\n\n/** Walk through property access, element access, and call chains to find the root expression. */\nfunction getExpressionRoot(node: ts.Node): ts.Node {\n if (ts.isPropertyAccessExpression(node)) return getExpressionRoot(node.expression);\n if (ts.isElementAccessExpression(node)) return getExpressionRoot(node.expression);\n if (ts.isCallExpression(node)) return getExpressionRoot(node.expression);\n return node;\n}\n\n/** Check if expr is a null/undefined comparison: x != null, x !== null, x !== undefined */\nfunction isNullCheck(expr: ts.BinaryExpression): boolean {\n const op = expr.operatorToken.kind;\n if (op !== ts.SyntaxKind.ExclamationEqualsToken && op !== ts.SyntaxKind.ExclamationEqualsEqualsToken) return false;\n return isNullishLiteral(expr.right) || isNullishLiteral(expr.left);\n}\n\n/** Get the identifier name being null-checked. */\nfunction getNullCheckedIdentifier(expr: ts.BinaryExpression): string | null {\n if (ts.isIdentifier(expr.left) && isNullishLiteral(expr.right)) return expr.left.text;\n if (ts.isIdentifier(expr.right) && isNullishLiteral(expr.left)) return expr.right.text;\n return null;\n}\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noTsIgnore: TSRule = {\n kind: \"ts\",\n id: \"no-ts-ignore\",\n severity: \"error\",\n message: \"@ts-ignore / @ts-expect-error suppresses type checking; fix the underlying type issue\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n const ranges = ts.getLeadingCommentRanges(ctx.source, node.getFullStart());\n if (!ranges) return;\n for (const range of ranges) {\n const text = ctx.source.slice(range.pos, range.end);\n if (text.includes(\"@ts-ignore\") || text.includes(\"@ts-expect-error\")) {\n ctx.reportAtOffset(range.pos);\n }\n }\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\n\nexport const noTypeAssertion: TSRule = {\n kind: \"ts\",\n id: \"no-type-assertion\",\n severity: \"error\",\n message: \"Double type assertion (`as unknown as T`) circumvents the type system; fix the upstream type or use a type guard\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n if (!ts.isAsExpression(node)) return;\n if (!ts.isAsExpression(node.expression)) return;\n if (node.expression.type.kind !== ts.SyntaxKind.UnknownKeyword) return;\n ctx.report(node);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\nimport { getFirstFunctionStatement } from \"../../typecheck/utils.ts\";\n\nexport const preferDefaultParamValue: TSRule = {\n kind: \"ts\",\n id: \"prefer-default-param-value\",\n severity: \"info\",\n message: \"Use a default parameter value instead of reassigning from nullish coalescing inside the body\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n const result = getFirstFunctionStatement(node);\n if (result === null) return;\n const { firstStmt, fn } = result;\n\n if (!ts.isExpressionStatement(firstStmt)) return;\n const expr = firstStmt.expression;\n if (!ts.isBinaryExpression(expr) || expr.operatorToken.kind !== ts.SyntaxKind.EqualsToken) return;\n\n const right = expr.right;\n if (!ts.isBinaryExpression(right) || right.operatorToken.kind !== ts.SyntaxKind.QuestionQuestionToken) return;\n\n if (!ts.isIdentifier(expr.left) || !ts.isIdentifier(right.left)) return;\n if (expr.left.text !== right.left.text) return;\n\n const paramName = expr.left.text;\n const isParam = fn.parameters.some((p) => ts.isIdentifier(p.name) && p.name.text === paramName);\n if (isParam) ctx.report(firstStmt);\n },\n};\n","import * as ts from \"typescript\";\nimport type { TSRule, TSVisitContext } from \"../types.ts\";\nimport { getFirstFunctionStatement } from \"../../typecheck/utils.ts\";\n\nexport const preferRequiredParamWithGuard: TSRule = {\n kind: \"ts\",\n id: \"prefer-required-param-with-guard\",\n severity: \"info\",\n message: \"Optional param with immediate guard (if (!param) return/throw); make it required instead\",\n\n visit(node: ts.Node, ctx: TSVisitContext) {\n const result = getFirstFunctionStatement(node);\n if (result === null) return;\n const { firstStmt, fn } = result;\n\n if (!ts.isIfStatement(firstStmt)) return;\n\n const test = firstStmt.expression;\n let guardedName: string | null = null;\n\n // Pattern 1: if (!param)\n if (ts.isPrefixUnaryExpression(test) && test.operator === ts.SyntaxKind.ExclamationToken) {\n if (ts.isIdentifier(test.operand)) guardedName = test.operand.text;\n }\n // Pattern 2: if (param === undefined)\n if (ts.isBinaryExpression(test)) {\n const op = test.operatorToken.kind;\n if (op === ts.SyntaxKind.EqualsEqualsEqualsToken || op === ts.SyntaxKind.EqualsEqualsToken) {\n if (ts.isIdentifier(test.left) && ts.isIdentifier(test.right) && test.right.text === \"undefined\") {\n guardedName = test.left.text;\n }\n }\n }\n\n if (!guardedName) return;\n\n const consequent = firstStmt.thenStatement;\n const isGuard =\n ts.isReturnStatement(consequent) ||\n ts.isThrowStatement(consequent) ||\n (ts.isBlock(consequent) &&\n consequent.statements.length === 1 &&\n consequent.statements[0] !== undefined &&\n (ts.isReturnStatement(consequent.statements[0]) || ts.isThrowStatement(consequent.statements[0])));\n\n if (!isGuard) return;\n\n const isOptional = fn.parameters.some(\n (p) => ts.isIdentifier(p.name) && p.name.text === guardedName && p.questionToken !== undefined,\n );\n if (isOptional) ctx.report(firstStmt);\n },\n};\n","import type { Rule } from \"./types.ts\";\n\nimport { deadOverload } from \"./cross-file/dead-overload.ts\";\nimport { duplicateConstantDeclaration } from \"./cross-file/duplicate-constant-declaration.ts\";\nimport { duplicateFile } from \"./cross-file/duplicate-file.ts\";\nimport { duplicateFunctionDeclaration } from \"./cross-file/duplicate-function-declaration.ts\";\nimport { duplicateFunctionName } from \"./cross-file/duplicate-function-name.ts\";\nimport { duplicateInlineTypeInParams } from \"./cross-file/duplicate-inline-type-in-params.ts\";\nimport { duplicateStatementSequence } from \"./cross-file/duplicate-statement-sequence.ts\";\nimport { duplicateTypeDeclaration } from \"./cross-file/duplicate-type-declaration.ts\";\nimport { duplicateTypeName } from \"./cross-file/duplicate-type-name.ts\";\nimport { explicitNullArg } from \"./cross-file/explicit-null-arg.ts\";\nimport { nearDuplicateFunction } from \"./cross-file/near-duplicate-function.ts\";\nimport { optionalArgAlwaysUsed } from \"./cross-file/optional-arg-always-used.ts\";\nimport { repeatedLiteralProperty } from \"./cross-file/repeated-literal-property.ts\";\n// import { repeatedObjectShape } from \"./cross-file/repeated-object-shape.ts\";\nimport { repeatedReturnShape } from \"./cross-file/repeated-return-shape.ts\";\nimport { trivialWrapper } from \"./cross-file/trivial-wrapper.ts\";\nimport { unusedExport } from \"./cross-file/unused-export.ts\";\nimport { noAnyCast } from \"./ts/no-any-cast.ts\";\nimport { noCatchReturn } from \"./ts/no-catch-return.ts\";\nimport { noDoubleNegationCoercion } from \"./ts/no-double-negation-coercion.ts\";\nimport { noDynamicImport } from \"./ts/no-dynamic-import.ts\";\nimport { noEmptyCatch } from \"./ts/no-empty-catch.ts\";\nimport { noErrorRewrap } from \"./ts/no-error-rewrap.ts\";\nimport { noExplicitAnyAnnotation } from \"./ts/no-explicit-any-annotation.ts\";\nimport { noInlineParamType } from \"./ts/no-inline-param-type.ts\";\nimport { noInlineTypeAssertion } from \"./ts/no-inline-type-assertion.ts\";\nimport { noLogicalOrFallback } from \"./ts/no-logical-or-fallback.ts\";\nimport { noNonNullAssertion } from \"./ts/no-non-null-assertion.ts\";\nimport { noNullTernaryNormalization } from \"./ts/no-null-ternary-normalization.ts\";\nimport { noNullishCoalescing } from \"./ts/no-nullish-coalescing.ts\";\nimport { noOptionalCall } from \"./ts/no-optional-call.ts\";\nimport { noOptionalElementAccess } from \"./ts/no-optional-element-access.ts\";\nimport { noOptionalPropertyAccess } from \"./ts/no-optional-property-access.ts\";\nimport { noRedundantExistenceGuard } from \"./ts/no-redundant-existence-guard.ts\";\nimport { noTsIgnore } from \"./ts/no-ts-ignore.ts\";\nimport { noTypeAssertion } from \"./ts/no-type-assertion.ts\";\nimport { preferDefaultParamValue } from \"./ts/prefer-default-param-value.ts\";\nimport { preferRequiredParamWithGuard } from \"./ts/prefer-required-param-with-guard.ts\";\n\nexport type RuleCategory =\n | \"type-evasion\"\n | \"defensive-code\"\n | \"error-handling\"\n | \"interface-design\"\n | \"cross-file\"\n | \"imports\";\n\nexport interface RuleMetadata {\n category: RuleCategory;\n tags: string[];\n}\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 duplicateInlineTypeInParams,\n noInlineTypeAssertion,\n noTypeAssertion,\n noRedundantExistenceGuard,\n preferDefaultParamValue,\n preferRequiredParamWithGuard,\n noInlineParamType,\n duplicateTypeDeclaration,\n duplicateFunctionDeclaration,\n optionalArgAlwaysUsed,\n noCatchReturn,\n noErrorRewrap,\n explicitNullArg,\n duplicateFunctionName,\n duplicateTypeName,\n duplicateConstantDeclaration,\n noDynamicImport,\n nearDuplicateFunction,\n trivialWrapper,\n unusedExport,\n duplicateFile,\n duplicateStatementSequence,\n deadOverload,\n repeatedLiteralProperty,\n // repeatedObjectShape — disabled: too noisy on single-property shapes, needs rethinking\n repeatedReturnShape,\n];\n\nconst ruleMetadata: Record<string, RuleMetadata> = {\n \"no-any-cast\": { category: \"type-evasion\", tags: [\"safety\"] },\n \"no-explicit-any-annotation\": { category: \"type-evasion\", tags: [\"safety\"] },\n \"no-inline-type-assertion\": { category: \"type-evasion\", tags: [\"safety\"] },\n \"no-type-assertion\": { category: \"type-evasion\", tags: [\"safety\"] },\n \"no-ts-ignore\": { category: \"type-evasion\", tags: [\"safety\"] },\n\n \"no-optional-property-access\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-optional-element-access\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-optional-call\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-nullish-coalescing\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-logical-or-fallback\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-null-ternary-normalization\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-non-null-assertion\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n \"no-double-negation-coercion\": { category: \"defensive-code\", tags: [\"readability\"] },\n \"no-redundant-existence-guard\": { category: \"defensive-code\", tags: [\"type-aware\"] },\n\n \"no-empty-catch\": { category: \"error-handling\", tags: [\"safety\"] },\n \"no-catch-return\": { category: \"error-handling\", tags: [\"safety\"] },\n \"no-error-rewrap\": { category: \"error-handling\", tags: [\"safety\"] },\n\n \"duplicate-inline-type-in-params\": { category: \"cross-file\", tags: [\"duplicate\", \"api\"] },\n \"prefer-default-param-value\": { category: \"interface-design\", tags: [\"api\"] },\n \"prefer-required-param-with-guard\": { category: \"interface-design\", tags: [\"api\"] },\n \"no-inline-param-type\": { category: \"interface-design\", tags: [\"api\"] },\n \"duplicate-type-declaration\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"duplicate-type-name\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"duplicate-function-declaration\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"duplicate-function-name\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"duplicate-constant-declaration\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"optional-arg-always-used\": { category: \"cross-file\", tags: [\"api\"] },\n \"explicit-null-arg\": { category: \"cross-file\", tags: [\"api\"] },\n\n \"no-dynamic-import\": { category: \"imports\", tags: [\"safety\"] },\n\n \"near-duplicate-function\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"trivial-wrapper\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"unused-export\": { category: \"cross-file\", tags: [\"api\"] },\n \"duplicate-file\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"duplicate-statement-sequence\": { category: \"cross-file\", tags: [\"duplicate\"] },\n \"dead-overload\": { category: \"cross-file\", tags: [\"api\", \"type-evasion\"] },\n\n \"repeated-literal-property\": { category: \"interface-design\", tags: [\"duplicate\", \"readability\"] },\n \"repeated-object-shape\": { category: \"interface-design\", tags: [\"duplicate\", \"readability\"] },\n \"repeated-return-shape\": { category: \"interface-design\", tags: [\"duplicate\", \"readability\"] },\n};\n\nexport function getRuleMetadata(ruleId: string): RuleMetadata {\n const metadata = ruleMetadata[ruleId];\n if (metadata !== undefined) return metadata;\n return { category: \"cross-file\", tags: [] };\n}\n","import type {\n FailOn,\n ResolvedScanConfig,\n RulePolicy,\n RulePolicyEntry,\n RulePolicySeverity,\n ScanOptions,\n Severity,\n} from \"./types.ts\";\n\nconst BUILTIN_IGNORE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.git/**\",\n \"**/*.d.ts\",\n \"**/*.d.cts\",\n \"**/*.d.mts\",\n];\n\nconst GENERATED_IGNORE = [\n \"**/*.gen.*\",\n \"**/*.generated.*\",\n];\n\nconst DEFAULT_FAIL_ON: FailOn = \"info\";\n\nexport function resolveScanConfig(options: ScanOptions): ResolvedScanConfig {\n const paths = options.paths.length > 0 ? options.paths : [\".\"];\n const ignore = [...BUILTIN_IGNORE, ...GENERATED_IGNORE, ...(options.ignore ?? [])];\n return {\n paths,\n strict: options.strict ?? false,\n rules: options.rules ? [...options.rules] : null,\n ignore,\n rulePolicy: toRulePolicyEntries(options.rulePolicy),\n showSeverities: normalizeSeveritySet(options.showSeverities),\n failOn: options.failOn ?? DEFAULT_FAIL_ON,\n useGitIgnore: options.useGitIgnore ?? true,\n };\n}\n\nexport function toRulePolicyEntries(policy: RulePolicy | undefined): RulePolicyEntry[] {\n if (policy === undefined) return [];\n if (Array.isArray(policy)) return [...policy];\n\n const entries: RulePolicyEntry[] = [];\n for (const [selector, severity] of Object.entries(policy)) {\n entries.push({ selector, severity });\n }\n return entries;\n}\n\nfunction normalizeSeveritySet(levels: Severity[] | undefined): Set<Severity> | null {\n if (levels === undefined || levels.length === 0) return null;\n return new Set(levels);\n}\n\nexport function isRulePolicySeverity(value: string): value is RulePolicySeverity {\n return value === \"off\" || value === \"info\" || value === \"warning\" || value === \"error\";\n}\n\nexport function isSeverity(value: string): value is Severity {\n return value === \"info\" || value === \"warning\" || value === \"error\";\n}\n\nexport function isFailOn(value: string): value is FailOn {\n return value === \"none\" || isSeverity(value);\n}\n","import * as ts from \"typescript\";\nimport { createHash } from \"node:crypto\";\nimport { TypeRegistry } from \"./type-registry.ts\";\nimport { FunctionRegistry, type FunctionEntry, type ParamInfo } from \"./function-registry.ts\";\nimport { ConstantRegistry } from \"./constant-registry.ts\";\nimport { hashFunctionBody, hashFunctionBodyNormalized, bodyTextLength, normalizedBodyTextLength, normalizeText, hashText } from \"../utils/hash.ts\";\nimport { StatementSequenceRegistry, type StatementSequenceEntry } from \"./statement-sequence-registry.ts\";\nimport { InlineParamTypeRegistry } from \"./inline-type-registry.ts\";\nimport type { Diagnostic, TSRule } from \"../rules/types.ts\";\nimport { buildContext } from \"../typecheck/walk.ts\";\nimport { isInlineParamType } from \"../typecheck/utils.ts\";\n\nexport interface CommentInfo {\n type: \"Line\" | \"Block\";\n value: string;\n start: number;\n end: number;\n}\n\nexport interface ProjectIndex {\n types: TypeRegistry;\n functions: FunctionRegistry;\n constants: ConstantRegistry;\n callSites: CallSite[];\n imports: ImportEntry[];\n files: Map<string, { source: string; sourceFile: ts.SourceFile; comments: CommentInfo[] }>;\n /** Whitespace-normalized file content hash → list of file paths */\n fileHashes: Map<string, string[]>;\n statementSequences: StatementSequenceRegistry;\n inlineParamTypes: InlineParamTypeRegistry;\n}\n\nexport interface CallSite {\n calleeName: string;\n file: string;\n line: number;\n argCount: number;\n node: ts.CallExpression;\n symbol?: ts.Symbol;\n resolvedDeclaration?: ts.SignatureDeclaration | ts.JSDocSignature;\n}\n\nexport interface ImportEntry {\n file: string;\n localName: string;\n importedName: string;\n source: string;\n}\n\nexport function collectProject(\n program: ts.Program,\n tsRules?: TSRule[],\n allowedFiles?: Set<string>,\n): { index: ProjectIndex; diagnostics: Diagnostic[] } {\n const checker = program.getTypeChecker();\n const types = new TypeRegistry();\n const functions = new FunctionRegistry();\n const constants = new ConstantRegistry();\n const callSites: CallSite[] = [];\n const imports: ImportEntry[] = [];\n const statementSequences = new StatementSequenceRegistry();\n const inlineParamTypes = new InlineParamTypeRegistry();\n const fileMap = new Map<string, { source: string; sourceFile: ts.SourceFile; comments: CommentInfo[] }>();\n const diagnostics: Diagnostic[] = [];\n\n for (const sourceFile of program.getSourceFiles()) {\n const file = sourceFile.fileName;\n if (sourceFile.isDeclarationFile) continue;\n if (file.includes(\"node_modules\")) continue;\n\n const isReportable = !allowedFiles || allowedFiles.has(file);\n const source = sourceFile.getFullText();\n\n // Always collect cross-file data (types, functions, call sites, imports)\n // from all program files for complete analysis context.\n // Only run TS rules and include in fileMap for reportable (scanned) files.\n if (isReportable) {\n const comments = collectAllComments(sourceFile);\n fileMap.set(file, { source, sourceFile, comments });\n }\n\n const ruleContexts = isReportable\n ? tsRules?.map((rule) => ({\n rule,\n ctx: buildContext(rule, sourceFile, checker, source, file, diagnostics),\n }))\n : undefined;\n\n function visit(node: ts.Node): void {\n collectTypes(node, file, sourceFile, types);\n collectFunctions(node, file, sourceFile, checker, functions);\n collectConstants(node, file, sourceFile, constants);\n collectCallSites(node, file, sourceFile, checker, callSites);\n collectStatementSequences(node, file, sourceFile, statementSequences);\n collectInlineParamTypes(node, file, sourceFile, inlineParamTypes);\n collectImports(node, file, imports);\n if (ruleContexts) {\n for (const { rule, ctx } of ruleContexts) {\n rule.visit(node, ctx);\n }\n }\n ts.forEachChild(node, visit);\n }\n ts.forEachChild(sourceFile, visit);\n }\n\n // Compute whole-file content hashes for duplicate-file detection\n const fileHashes = new Map<string, string[]>();\n for (const [file, { source }] of fileMap) {\n const normalized = source.replace(/\\s+/g, \" \").trim();\n const hash = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n let list = fileHashes.get(hash);\n if (list === undefined) {\n list = [];\n fileHashes.set(hash, list);\n }\n list.push(file);\n }\n\n return { index: { types, functions, constants, callSites, imports, files: fileMap, fileHashes, statementSequences, inlineParamTypes }, diagnostics };\n}\n\nfunction hasNonPublicModifier(node: ts.Node): boolean {\n if (!ts.canHaveModifiers(node)) return false;\n const mods = ts.getModifiers(node);\n if (mods === undefined) return false;\n return mods.some(\n (m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword,\n );\n}\n\nfunction isExported(node: ts.Node): boolean {\n if (!ts.canHaveModifiers(node)) return false;\n const mods = ts.getModifiers(node);\n if (mods === undefined) return false;\n return mods.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);\n}\n\nfunction collectTypes(node: ts.Node, file: string, sourceFile: ts.SourceFile, registry: TypeRegistry): void {\n if (ts.isTypeAliasDeclaration(node)) {\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n registry.add(node.name.text, file, line, node.type, sourceFile, isExported(node));\n }\n if (ts.isInterfaceDeclaration(node)) {\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n registry.add(node.name.text, file, line, node, sourceFile, isExported(node));\n }\n}\n\nfunction isConstantValue(node: ts.Node): boolean {\n if (ts.isStringLiteral(node)) return true;\n if (ts.isNumericLiteral(node)) return true;\n if (ts.isNoSubstitutionTemplateLiteral(node)) return true;\n if (ts.isPrefixUnaryExpression(node)) return isConstantValue(node.operand);\n if (ts.isBinaryExpression(node)) return isConstantValue(node.left) && isConstantValue(node.right);\n return false;\n}\n\nfunction collectConstants(node: ts.Node, file: string, sourceFile: ts.SourceFile, registry: ConstantRegistry): void {\n if (!ts.isVariableStatement(node)) return;\n if (!(node.declarationList.flags & ts.NodeFlags.Const)) return;\n const exported = isExported(node);\n for (const decl of node.declarationList.declarations) {\n if (!decl.initializer || !ts.isIdentifier(decl.name)) continue;\n if (!isConstantValue(decl.initializer)) continue;\n const valueText = decl.initializer.getText(sourceFile).replace(/\\s+/g, \" \").trim();\n const valueHash = createHash(\"sha256\").update(valueText).digest(\"hex\").slice(0, 16);\n const line = ts.getLineAndCharacterOfPosition(sourceFile, decl.getStart(sourceFile)).line + 1;\n registry.add({ name: decl.name.text, file, line, valueHash, valueText, exported });\n }\n}\n\nfunction buildFunctionEntry(\n body: ts.Node,\n parameters: ts.NodeArray<ts.ParameterDeclaration>,\n sourceFile: ts.SourceFile,\n file: string,\n lineNode: ts.Node,\n name: string,\n extra: Partial<Pick<FunctionEntry, \"exported\" | \"symbol\" | \"className\" | \"implementsInterface\" | \"node\">>,\n): FunctionEntry {\n const line = ts.getLineAndCharacterOfPosition(sourceFile, lineNode.getStart(sourceFile)).line + 1;\n const params = extractParams(parameters, sourceFile);\n const paramNames = params.map((p) => p.name);\n const hash = hashFunctionBody(body, sourceFile);\n const normalizedHash = hashFunctionBodyNormalized(body, sourceFile, paramNames);\n const bodyLength = bodyTextLength(body, sourceFile);\n const normalizedBodyLength = normalizedBodyTextLength(body, sourceFile, paramNames);\n return {\n name,\n file,\n line,\n hash,\n normalizedHash,\n params,\n node: extra.node ?? body,\n exported: extra.exported ?? false,\n bodyLength,\n normalizedBodyLength,\n ...extra,\n };\n}\n\nfunction collectFunctions(node: ts.Node, file: string, sourceFile: ts.SourceFile, checker: ts.TypeChecker, registry: FunctionRegistry): void {\n if (ts.isFunctionDeclaration(node) && node.name && node.body) {\n registry.add(buildFunctionEntry(node.body, node.parameters, sourceFile, file, node, node.name.text, {\n exported: isExported(node), symbol: checker.getSymbolAtLocation(node.name), node,\n }));\n }\n\n // Arrow functions and function expressions assigned to const: const foo = (...) => { ... } / const foo = function() { ... }\n if (ts.isVariableStatement(node)) {\n const exported = isExported(node);\n for (const decl of node.declarationList.declarations) {\n if (decl.initializer && ts.isArrowFunction(decl.initializer) && ts.isIdentifier(decl.name)) {\n const arrow = decl.initializer;\n registry.add(buildFunctionEntry(arrow.body, arrow.parameters, sourceFile, file, decl, decl.name.text, {\n exported, symbol: checker.getSymbolAtLocation(decl.name), node: arrow,\n }));\n }\n if (decl.initializer && ts.isFunctionExpression(decl.initializer) && ts.isIdentifier(decl.name)) {\n const fn = decl.initializer;\n if (fn.body) {\n registry.add(buildFunctionEntry(fn.body, fn.parameters, sourceFile, file, decl, decl.name.text, {\n exported, symbol: checker.getSymbolAtLocation(decl.name), node: fn,\n }));\n }\n }\n }\n }\n\n // Object property functions: { key: (...) => { ... } } or { key: function(...) { ... } }\n if (ts.isPropertyAssignment(node) && (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name))) {\n const init = node.initializer;\n const propName = node.name.text;\n if (ts.isArrowFunction(init)) {\n registry.add(buildFunctionEntry(init.body, init.parameters, sourceFile, file, node, propName, { node: init }));\n }\n if (ts.isFunctionExpression(init) && init.body) {\n registry.add(buildFunctionEntry(init.body, init.parameters, sourceFile, file, node, propName, { node: init }));\n }\n }\n\n // Anonymous/nested functions (catch-all for ArrowFunction/FunctionExpression not already collected)\n if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {\n const parent = node.parent;\n // Skip if already collected by VariableStatement path\n if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {\n // Already collected above\n }\n // Skip if already collected by PropertyAssignment path\n else if (ts.isPropertyAssignment(parent)) {\n // Already collected above\n }\n else {\n const body = ts.isArrowFunction(node) ? node.body : (node as ts.FunctionExpression).body;\n if (body) {\n const MIN_ANON_BODY = 64;\n if (bodyTextLength(body, sourceFile) >= MIN_ANON_BODY) {\n const name = deriveAnonymousName(node, sourceFile);\n registry.add(buildFunctionEntry(body, node.parameters, sourceFile, file, node, name, { node }));\n }\n }\n }\n }\n\n // Class methods\n if (ts.isMethodDeclaration(node) && node.body && ts.isIdentifier(node.name)) {\n const parent = node.parent;\n if (ts.isClassDeclaration(parent)) {\n if (hasNonPublicModifier(node)) return;\n const className = parent.name ? parent.name.text : \"<anonymous>\";\n const name = `${className}.${node.name.text}`;\n const implementsInterface = parent.heritageClauses?.some(\n (c) => c.token === ts.SyntaxKind.ImplementsKeyword,\n ) ?? false;\n registry.add(buildFunctionEntry(node.body, node.parameters, sourceFile, file, node, name, {\n exported: isExported(parent), symbol: checker.getSymbolAtLocation(node.name), node, className, implementsInterface,\n }));\n }\n }\n}\n\nfunction extractParams(parameters: ts.NodeArray<ts.ParameterDeclaration>, sourceFile: ts.SourceFile): ParamInfo[] {\n return parameters.map((p) => {\n const name = p.name.getText(sourceFile);\n const optional = p.questionToken !== undefined;\n const hasDefault = p.initializer !== undefined;\n const typeText = p.type ? p.type.getText(sourceFile) : null;\n return { name, optional, hasDefault, typeText };\n });\n}\n\nfunction deriveAnonymousName(node: ts.ArrowFunction | ts.FunctionExpression, sourceFile: ts.SourceFile): string {\n const parent = node.parent;\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n\n // Parent is CallExpression — check if grandparent is a PropertyAssignment with a name\n if (ts.isCallExpression(parent)) {\n const grandparent = parent.parent;\n if (ts.isPropertyAssignment(grandparent) && ts.isIdentifier(grandparent.name)) {\n return grandparent.name.text;\n }\n // Callee name + arg index\n let calleeName: string | null = null;\n if (ts.isIdentifier(parent.expression)) {\n calleeName = parent.expression.text;\n } else if (ts.isPropertyAccessExpression(parent.expression)) {\n calleeName = parent.expression.name.text;\n }\n if (calleeName) {\n const argIndex = parent.arguments.indexOf(node as ts.Expression);\n if (argIndex >= 0) return `${calleeName}.$arg${argIndex}`;\n }\n }\n\n return `<anonymous>:${line}`;\n}\n\nfunction collectImports(node: ts.Node, file: string, imports: ImportEntry[]): void {\n if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {\n const moduleSource = node.moduleSpecifier.text;\n const clause = node.importClause;\n if (!clause) return;\n\n // Default import\n if (clause.name) {\n imports.push({\n file,\n localName: clause.name.text,\n importedName: \"default\",\n source: moduleSource,\n });\n }\n\n // Named imports\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements) {\n imports.push({\n file,\n localName: el.name.text,\n importedName: el.propertyName ? el.propertyName.text : el.name.text,\n source: moduleSource,\n });\n }\n }\n }\n\n // Re-exports: export { x } from \"./mod\"\n if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {\n const moduleSource = node.moduleSpecifier.text;\n if (node.exportClause && ts.isNamedExports(node.exportClause)) {\n for (const el of node.exportClause.elements) {\n imports.push({\n file,\n localName: el.name.text,\n importedName: el.propertyName ? el.propertyName.text : el.name.text,\n source: moduleSource,\n });\n }\n }\n }\n}\n\nfunction collectStatementSequences(\n node: ts.Node,\n file: string,\n sourceFile: ts.SourceFile,\n registry: StatementSequenceRegistry,\n): void {\n if (!ts.isBlock(node)) return;\n const stmts = node.statements;\n const n = stmts.length;\n if (n < 3) return;\n const MAX_WINDOW = Math.min(n, 5);\n for (let size = 3; size <= MAX_WINDOW; size++) {\n for (let start = 0; start + size <= n; start++) {\n const window = stmts.slice(start, start + size);\n const texts = window.map((s) => s.getText(sourceFile));\n const joined = texts.join(\"\\n\");\n const normalized = normalizeText(joined);\n if (normalized.length < 128) continue;\n const hash = hashText(joined.replace(/\\s+/g, \" \").trim());\n const normalizedHash = hashText(normalized);\n const firstStmt = window[0];\n const lastStmt = window[window.length - 1];\n if (firstStmt === undefined || lastStmt === undefined) continue;\n const line = ts.getLineAndCharacterOfPosition(sourceFile, firstStmt.getStart(sourceFile)).line + 1;\n const endLine = ts.getLineAndCharacterOfPosition(sourceFile, lastStmt.getEnd()).line + 1;\n registry.add({ file, line, endLine, hash, normalizedHash, statementCount: size, normalizedBodyLength: normalized.length });\n }\n }\n}\n\nfunction collectInlineParamTypes(\n node: ts.Node,\n file: string,\n sourceFile: ts.SourceFile,\n registry: InlineParamTypeRegistry,\n): void {\n if (!isInlineParamType(node)) return;\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n registry.add(file, line, node as ts.TypeLiteralNode, sourceFile);\n}\n\nfunction collectCallSites(node: ts.Node, file: string, sourceFile: ts.SourceFile, checker: ts.TypeChecker, sites: CallSite[]): void {\n if (!ts.isCallExpression(node)) return;\n let calleeName: string | null = null;\n if (ts.isIdentifier(node.expression)) {\n calleeName = node.expression.text;\n } else if (ts.isPropertyAccessExpression(node.expression)) {\n calleeName = node.expression.name.text;\n }\n if (calleeName) {\n const line = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;\n // Resolve the symbol the call refers to (follows imports to the declaration)\n let symbol: ts.Symbol | undefined;\n let resolvedDeclaration: ts.SignatureDeclaration | ts.JSDocSignature | undefined;\n try {\n symbol = checker.getSymbolAtLocation(node.expression);\n if (symbol && (symbol.flags & ts.SymbolFlags.Alias)) {\n symbol = checker.getAliasedSymbol(symbol);\n }\n const signature = checker.getResolvedSignature(node);\n resolvedDeclaration = signature?.declaration;\n } catch {\n // Symbol resolution can fail on synthetic nodes\n }\n sites.push({\n calleeName,\n file,\n line,\n argCount: node.arguments.length,\n node,\n symbol,\n resolvedDeclaration,\n });\n }\n}\n\n/** Collect all comments from a source file. */\nexport function collectAllComments(sourceFile: ts.SourceFile): CommentInfo[] {\n const comments: CommentInfo[] = [];\n const source = sourceFile.getFullText();\n const seen = new Set<number>();\n\n function addRanges(ranges: ts.CommentRange[] | undefined): void {\n if (!ranges) return;\n for (const r of ranges) {\n if (seen.has(r.pos)) continue;\n seen.add(r.pos);\n const isLine = r.kind === ts.SyntaxKind.SingleLineCommentTrivia;\n comments.push({\n type: isLine ? \"Line\" : \"Block\",\n value: source.slice(r.pos + 2, isLine ? r.end : r.end - 2),\n start: r.pos,\n end: r.end,\n });\n }\n }\n\n function visit(node: ts.Node): void {\n addRanges(ts.getLeadingCommentRanges(source, node.getFullStart()));\n addRanges(ts.getTrailingCommentRanges(source, node.getEnd()));\n ts.forEachChild(node, visit);\n }\n visit(sourceFile);\n\n return comments;\n}\n","import type * as ts from \"typescript\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { hashTypeShape } from \"../utils/hash.ts\";\nimport { BaseRegistry } from \"./base-registry.ts\";\n\nexport interface TypeEntry {\n name: string;\n file: string;\n line: number;\n hash: string;\n node: ts.Node;\n exported: boolean;\n}\n\nexport class TypeRegistry extends BaseRegistry<TypeEntry> {\n add(name: string, file: string, line: number, typeNode: ts.Node, sourceFile: ts.SourceFile, exported: boolean): void {\n const hash = hashTypeShape(typeNode, sourceFile);\n const entry: TypeEntry = { name, file, line, hash, node: typeNode, exported };\n this.addEntry(entry, hash);\n }\n\n getNameCollisionGroups(): TypeEntry[][] {\n return getExportedNameCollisions(this.entries);\n }\n}\n\nexport function getExportedNameCollisions<T extends { name: string; file: string; exported: boolean }>(entries: T[]): T[][] {\n const byNameAndPackage = new Map<string, T[]>();\n for (const entry of entries) {\n if (!entry.exported) continue;\n const pkg = findPackageRoot(entry.file);\n const key = `${pkg}\\0${entry.name}`;\n let list = byNameAndPackage.get(key);\n if (list === undefined) {\n list = [];\n byNameAndPackage.set(key, list);\n }\n list.push(entry);\n }\n return [...byNameAndPackage.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\nconst packageRootCache = new Map<string, string>();\n\nfunction findPackageRoot(filePath: string): string {\n let dir = dirname(filePath);\n const cached = packageRootCache.get(dir);\n if (cached !== undefined) return cached;\n\n const startDir = dir;\n const visited: string[] = [dir];\n while (dir !== dirname(dir)) {\n if (existsSync(join(dir, \"package.json\"))) {\n for (const d of visited) packageRootCache.set(d, dir);\n return dir;\n }\n dir = dirname(dir);\n visited.push(dir);\n }\n for (const d of visited) packageRootCache.set(d, dir);\n return dir;\n}\n","import { createHash } from \"node:crypto\";\nimport * as ts from \"typescript\";\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: ts.Node, sourceFile: ts.SourceFile): string {\n const normalized = normalizeTypeNode(node, sourceFile);\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeTypeNode(node: ts.Node, sourceFile: ts.SourceFile): string {\n if (ts.isTypeLiteralNode(node)) {\n const normalized = node.members.map((m) => normalizeTypeNode(m, sourceFile)).sort().join(\";\");\n return `{${normalized}}`;\n }\n if (ts.isInterfaceDeclaration(node)) {\n const normalized = node.members.map((m) => normalizeTypeNode(m, sourceFile)).sort().join(\";\");\n return `{${normalized}}`;\n }\n if (ts.isPropertySignature(node)) {\n const keyName = node.name.getText(sourceFile);\n const optional = node.questionToken ? \"?\" : \"\";\n const type = node.type ? normalizeTypeNode(node.type, sourceFile) : \"any\";\n return `${keyName}${optional}:${type}`;\n }\n if (ts.isTypeAliasDeclaration(node)) {\n return normalizeTypeNode(node.type, sourceFile);\n }\n // Fallback: use source text with whitespace normalized\n return node.getText(sourceFile).replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Hash a function body for duplicate detection.\n * Normalizes whitespace.\n */\nexport function hashFunctionBody(node: ts.Node, sourceFile: ts.SourceFile): string {\n const normalized = stripComments(node.getText(sourceFile));\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\n/**\n * Whitespace-normalized body text length.\n * Used to filter trivially small function bodies from duplicate detection.\n */\nexport function bodyTextLength(node: ts.Node, sourceFile: ts.SourceFile): number {\n return stripComments(node.getText(sourceFile)).length;\n}\n\nfunction stripComments(text: string): string {\n return text.replace(/\\/\\/[^\\n]*/g, \"\").replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/\\s+/g, \" \").trim();\n}\n\nfunction normalizeBody(node: ts.Node, sourceFile: ts.SourceFile, paramNames: string[]): string {\n let text = node.getText(sourceFile);\n // Strip line comments\n text = text.replace(/\\/\\/[^\\n]*/g, \"\");\n // Strip block comments\n text = text.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n // Normalize string literals (double-quoted, single-quoted, template)\n text = text.replace(/\"(?:[^\"\\\\]|\\\\.)*\"/g, '\"__STR__\"');\n text = text.replace(/'(?:[^'\\\\]|\\\\.)*'/g, '\"__STR__\"');\n text = text.replace(/`(?:[^`\\\\]|\\\\.)*`/g, '\"__STR__\"');\n // Normalize numeric literals (standalone numbers, not inside identifiers)\n text = text.replace(/\\b\\d+(?:\\.\\d+)?\\b/g, \"__NUM__\");\n // Normalize parameter names to positional placeholders\n for (let i = 0; i < paramNames.length; i++) {\n const name = paramNames[i] as string;\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n text = text.replace(new RegExp(`\\\\b${escaped}\\\\b`, \"g\"), `$${i}`);\n }\n // Normalize member-access objects: this.x and $N.x both become $_.x\n text = text.replace(/\\bthis\\./g, \"$_.\");\n text = text.replace(/\\$\\d+\\./g, \"$_.\");\n // Normalize whitespace\n text = text.replace(/\\s+/g, \" \").trim();\n return text;\n}\n\n/**\n * Normalize raw text (not from an AST node) using the same normalization pipeline.\n * Used for statement-sequence hashing.\n */\nexport function normalizeText(text: string): string {\n // Strip line comments\n let t = text.replace(/\\/\\/[^\\n]*/g, \"\");\n // Strip block comments\n t = t.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n // Normalize string literals\n t = t.replace(/\"(?:[^\"\\\\]|\\\\.)*\"/g, '\"__STR__\"');\n t = t.replace(/'(?:[^'\\\\]|\\\\.)*'/g, '\"__STR__\"');\n t = t.replace(/`(?:[^`\\\\]|\\\\.)*`/g, '\"__STR__\"');\n // Normalize numeric literals\n t = t.replace(/\\b\\d+(?:\\.\\d+)?\\b/g, \"__NUM__\");\n // Normalize member-access objects\n t = t.replace(/\\bthis\\./g, \"$_.\");\n // Normalize whitespace\n t = t.replace(/\\s+/g, \" \").trim();\n return t;\n}\n\nexport function hashText(text: string): string {\n return createHash(\"sha256\").update(text).digest(\"hex\").slice(0, 16);\n}\n\nexport function hashFunctionBodyNormalized(\n node: ts.Node,\n sourceFile: ts.SourceFile,\n paramNames: string[],\n): string {\n const text = normalizeBody(node, sourceFile, paramNames);\n return createHash(\"sha256\").update(text).digest(\"hex\").slice(0, 16);\n}\n\n/**\n * Length of fully-normalized body text (strings/numbers/params replaced).\n * Used to filter near-duplicate groups with trivial collapsed bodies.\n */\nexport function normalizedBodyTextLength(\n node: ts.Node,\n sourceFile: ts.SourceFile,\n paramNames: string[],\n): number {\n return normalizeBody(node, sourceFile, paramNames).length;\n}\n","export class BaseRegistry<T> {\n protected entries: T[] = [];\n protected byHash = new Map<string, T[]>();\n\n protected addEntry(entry: T, hash: string): void {\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(): T[][] {\n return [...this.byHash.values()].filter((group) => group.length > 1);\n }\n\n getAll(): T[] {\n return this.entries;\n }\n}\n\nexport class DualHashRegistry<T> extends BaseRegistry<T> {\n private bySecondaryHash = new Map<string, T[]>();\n\n protected addWithSecondary(entry: T, primaryHash: string, secondaryHash: string): void {\n this.addEntry(entry, primaryHash);\n let list = this.bySecondaryHash.get(secondaryHash);\n if (list === undefined) {\n list = [];\n this.bySecondaryHash.set(secondaryHash, list);\n }\n list.push(entry);\n }\n\n getSecondaryDuplicateGroups(): T[][] {\n return [...this.bySecondaryHash.values()].filter((group) => group.length > 1);\n }\n}\n","import type * as ts from \"typescript\";\nimport { DualHashRegistry } from \"./base-registry.ts\";\nimport { getExportedNameCollisions } from \"./type-registry.ts\";\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 normalizedHash: string;\n params: ParamInfo[];\n node: ts.Node;\n exported: boolean;\n symbol?: ts.Symbol;\n /** Whitespace-normalized body text length (for trivial-body filtering) */\n bodyLength: number;\n /** Fully-normalized body text length (strings/numbers/params replaced) */\n normalizedBodyLength: number;\n /** Class name for class methods (e.g. \"Foo\" for \"Foo.bar\"), undefined for standalone functions */\n className?: string;\n /** True if the declaring class has an `implements` clause */\n implementsInterface?: boolean;\n}\n\nexport class FunctionRegistry extends DualHashRegistry<FunctionEntry> {\n add(entry: FunctionEntry): void {\n this.addWithSecondary(entry, entry.hash, entry.normalizedHash);\n }\n\n getNearDuplicateGroups(): FunctionEntry[][] {\n return this.getSecondaryDuplicateGroups().filter((group) => {\n // Exclude groups where all entries share the same exact hash\n // (those are already caught by duplicate-function-declaration)\n const hashes = new Set(group.map((e) => e.hash));\n return hashes.size > 1;\n });\n }\n\n getByName(name: string): FunctionEntry[] {\n return this.entries.filter((e) => e.name === name);\n }\n\n getNameCollisionGroups(): FunctionEntry[][] {\n return getExportedNameCollisions(this.entries);\n }\n}\n","import { BaseRegistry } from \"./base-registry.ts\";\n\nexport interface ConstantEntry {\n name: string;\n file: string;\n line: number;\n valueHash: string;\n valueText: string;\n exported: boolean;\n}\n\nexport class ConstantRegistry extends BaseRegistry<ConstantEntry> {\n add(entry: ConstantEntry): void {\n this.addEntry(entry, entry.valueHash);\n }\n}\n","import { DualHashRegistry } from \"./base-registry.ts\";\n\nexport interface StatementSequenceEntry {\n file: string;\n line: number;\n endLine: number;\n hash: string;\n normalizedHash: string;\n statementCount: number;\n normalizedBodyLength: number;\n}\n\nexport class StatementSequenceRegistry extends DualHashRegistry<StatementSequenceEntry> {\n add(entry: StatementSequenceEntry): void {\n this.addWithSecondary(entry, entry.hash, entry.normalizedHash);\n }\n\n getNormalizedDuplicateGroups(): StatementSequenceEntry[][] {\n return this.getSecondaryDuplicateGroups();\n }\n}\n","import type * as ts from \"typescript\";\nimport { hashTypeShape } from \"../utils/hash.ts\";\nimport { BaseRegistry } from \"./base-registry.ts\";\n\nexport interface InlineParamTypeEntry {\n file: string;\n line: number;\n hash: string;\n typeText: string;\n node: ts.Node;\n}\n\nexport class InlineParamTypeRegistry extends BaseRegistry<InlineParamTypeEntry> {\n add(file: string, line: number, typeNode: ts.TypeLiteralNode, sourceFile: ts.SourceFile): void {\n const hash = hashTypeShape(typeNode, sourceFile);\n const typeText = typeNode.getText(sourceFile).replace(/\\s+/g, \" \").trim();\n this.addEntry({ file, line, hash, typeText, node: typeNode }, hash);\n }\n}\n","import * as ts from \"typescript\";\nimport type { Diagnostic, TSRule, TSVisitContext } from \"../rules/types.ts\";\nimport { isNullableType, isFromNodeModules } from \"./utils.ts\";\n\nexport function buildContext(\n rule: TSRule,\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n source: string,\n filename: string,\n diagnostics: Diagnostic[],\n): TSVisitContext {\n return {\n filename,\n source,\n sourceFile,\n checker,\n\n report(node: ts.Node, message?: string) {\n const { line, character } = ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile));\n diagnostics.push({\n ruleId: rule.id,\n severity: rule.severity,\n message: message ?? rule.message,\n file: filename,\n line: line + 1,\n column: character + 1,\n });\n },\n\n reportAtOffset(offset: number, message?: string) {\n const { line, character } = ts.getLineAndCharacterOfPosition(sourceFile, offset);\n diagnostics.push({\n ruleId: rule.id,\n severity: rule.severity,\n message: message ?? rule.message,\n file: filename,\n line: line + 1,\n column: character + 1,\n });\n },\n\n isNullable(node: ts.Node): boolean {\n const type = checker.getTypeAtLocation(node);\n return isNullableType(checker, type);\n },\n\n isExternal(node: ts.Node): boolean {\n const type = checker.getTypeAtLocation(node);\n const symbol = type.getSymbol();\n if (!symbol) return false;\n const declarations = symbol.getDeclarations();\n if (!declarations || declarations.length === 0) return false;\n return declarations.some((d) => isFromNodeModules(d));\n },\n };\n}\n","import * as ts from \"typescript\";\nimport { dirname } from \"node:path\";\n\nexport function createProgramFromFiles(files: string[]): ts.Program {\n let configPath: string | undefined;\n if (files.length > 0) {\n configPath = ts.findConfigFile(dirname(files[0] as string), ts.sys.fileExists, \"tsconfig.json\");\n }\n\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, dirname(configPath));\n return ts.createProgram({\n rootNames: files,\n options: { ...parsed.options, skipLibCheck: true },\n });\n }\n\n return ts.createProgram({\n rootNames: files,\n options: {\n target: ts.ScriptTarget.ESNext,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n strict: true,\n skipLibCheck: true,\n noEmit: true,\n },\n });\n}\n\n/** Resolve the full set of project files from a tsconfig, merged with the scan set. */\nexport function resolveProjectFiles(scanFiles: string[]): string[] {\n if (scanFiles.length === 0) return [];\n const configPath = ts.findConfigFile(dirname(scanFiles[0] as string), ts.sys.fileExists, \"tsconfig.json\");\n if (!configPath) return scanFiles;\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, dirname(configPath));\n return [...new Set([...scanFiles, ...parsed.fileNames])];\n}\n","import { collectProject, type CommentInfo } from \"../collect/index.ts\";\nimport { isTSRule } from \"../rules/types.ts\";\nimport type { CrossFileRule, Diagnostic, Rule } from \"../rules/types.ts\";\nimport { createProgramFromFiles, resolveProjectFiles } from \"../typecheck/program.ts\";\n\nexport function analyzeFiles(files: string[], rules: Rule[]): Diagnostic[] {\n const tsRules = rules.filter(isTSRule);\n const crossFileRules = rules.filter((r): r is CrossFileRule => !isTSRule(r));\n\n const projectFiles = resolveProjectFiles(files);\n const program = projectFiles.length > 0 ? createProgramFromFiles(projectFiles) : null;\n if (!program) return [];\n\n const allowedFiles = new Set(files);\n const { index, diagnostics } = collectProject(program, tsRules, allowedFiles);\n\n for (const rule of crossFileRules) {\n const ruleDiagnostics = rule.analyze(index);\n // Cross-file rules may see the full project but only report for scanned files\n diagnostics.push(...ruleDiagnostics.filter((d) => allowedFiles.has(d.file)));\n }\n\n return finalizeDiagnostics(diagnostics, index.files);\n}\n\nfunction dedupeDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] {\n const seen = new Set<string>();\n const deduped: Diagnostic[] = [];\n for (const diagnostic of diagnostics) {\n const key = `${diagnostic.file}:${diagnostic.line}:${diagnostic.ruleId}`;\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(diagnostic);\n }\n return deduped;\n}\n\nfunction finalizeDiagnostics(\n diagnostics: Diagnostic[],\n files: Map<string, { source: string; comments: CommentInfo[] }>,\n): Diagnostic[] {\n const diagnosticsByFile = new Map<string, Diagnostic[]>();\n for (const diagnostic of diagnostics) {\n let list = diagnosticsByFile.get(diagnostic.file);\n if (list === undefined) {\n list = [];\n diagnosticsByFile.set(diagnostic.file, list);\n }\n list.push(diagnostic);\n }\n\n const finalized: Diagnostic[] = [];\n for (const [file, fileDiagnostics] of diagnosticsByFile) {\n const fileData = files.get(file);\n if (fileData === undefined) {\n finalized.push(...fileDiagnostics);\n continue;\n }\n finalized.push(...annotateAndFilter(fileDiagnostics, fileData.comments, fileData.source));\n }\n\n return dedupeDiagnostics(finalized);\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 annotateAndFilter(diagnostics: Diagnostic[], comments: CommentInfo[], source: string): Diagnostic[] {\n if (diagnostics.length === 0) return diagnostics;\n if (comments.length === 0) return diagnostics;\n\n const byEndLine = new Map<number, CommentInfo[]>();\n for (const comment of comments) {\n const endLine = lineAt(source, comment.end);\n let list = byEndLine.get(endLine);\n if (list === undefined) {\n list = [];\n byEndLine.set(endLine, list);\n }\n list.push(comment);\n }\n\n const kept: Diagnostic[] = [];\n for (const diagnostic of diagnostics) {\n if (isSatisfiedByComment(diagnostic, byEndLine, source)) continue;\n\n const inline = findInlineComment(diagnostic.line, byEndLine);\n if (inline !== null) {\n diagnostic.annotation = inline;\n kept.push(diagnostic);\n continue;\n }\n const above = collectAnnotation(diagnostic.line - 1, byEndLine, source);\n if (above !== null) diagnostic.annotation = above;\n kept.push(diagnostic);\n }\n\n return kept;\n}\n\nfunction lastCommentOnLine(line: number, byEndLine: Map<number, CommentInfo[]>): CommentInfo | null {\n const commentsOnLine = byEndLine.get(line);\n if (commentsOnLine === undefined || commentsOnLine.length === 0) return null;\n return commentsOnLine.at(-1) ?? null;\n}\n\nfunction findInlineComment(diagLine: number, byEndLine: Map<number, CommentInfo[]>): string | null {\n const comment = lastCommentOnLine(diagLine, byEndLine);\n if (comment === null || comment.type !== \"Line\") return null;\n const text = comment.value.trim();\n if (isDirectiveComment(text)) return null;\n return text;\n}\n\nfunction collectAnnotation(\n commentEndLine: number,\n byEndLine: Map<number, CommentInfo[]>,\n source: string,\n): string | null {\n const comments = collectCommentsAbove(commentEndLine, byEndLine, source);\n if (comments.length === 0) return null;\n const first = comments[0];\n if (comments.length === 1 && first !== undefined && first.type === \"Block\") {\n return cleanBlockComment(first.value);\n }\n return comments.map((c) => c.value.trim()).join(\"\\n\");\n}\n\nfunction isSatisfiedByComment(\n diagnostic: Diagnostic,\n byEndLine: Map<number, CommentInfo[]>,\n source: string,\n): boolean {\n if (diagnostic.severity === \"error\") return false;\n\n const candidates = getCommentCandidates(diagnostic.line, byEndLine, source);\n return candidates.some((comment) => commentSatisfiesRule(comment, diagnostic.ruleId));\n}\n\nfunction getCommentCandidates(\n diagLine: number,\n byEndLine: Map<number, CommentInfo[]>,\n source: string,\n): CommentInfo[] {\n const inline = byEndLine.get(diagLine) ?? [];\n const above = collectCommentsAbove(diagLine - 1, byEndLine, source);\n // Also check the line immediately below (inside a block body).\n // Formatters like Biome/Prettier enforce `} catch {` on one line,\n // forcing suppression comments into the block where they end up on diagLine + 1.\n const below = byEndLine.get(diagLine + 1) ?? [];\n return [...inline, ...above, ...below];\n}\n\nfunction collectCommentsAbove(\n commentEndLine: number,\n byEndLine: Map<number, CommentInfo[]>,\n source: string,\n): CommentInfo[] {\n const comment = lastCommentOnLine(commentEndLine, byEndLine);\n if (comment === null) return [];\n if (comment.type === \"Block\") return [comment];\n\n const lines: CommentInfo[] = [comment];\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);\n prevLine--;\n }\n\n return lines;\n}\n\nfunction commentSatisfiesRule(comment: CommentInfo, ruleId: string): boolean {\n for (const line of commentLines(comment)) {\n const match = line.match(/^@unguard\\s+([^\\s]+)\\b/);\n if (match?.[1] === ruleId) return true;\n }\n return false;\n}\n\nfunction commentLines(comment: CommentInfo): string[] {\n if (comment.type === \"Block\") {\n const cleaned = cleanBlockComment(comment.value);\n if (cleaned.length === 0) return [];\n return cleaned.split(\"\\n\");\n }\n return [comment.value.trim()];\n}\n\nfunction isDirectiveComment(text: string): boolean {\n return text.startsWith(\"@expect\") || text.startsWith(\"@unguard\");\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","import fg from \"fast-glob\";\nimport ignore from \"ignore\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { relative, resolve, sep } from \"node:path\";\nimport type { ResolvedScanConfig } from \"./types.ts\";\n\nexport async function discoverFiles(config: ResolvedScanConfig): Promise<string[]> {\n const globs = expandGlobs(config.paths);\n const discoveredFiles = await fg(globs, {\n ignore: config.ignore,\n absolute: true,\n });\n if (!config.useGitIgnore) return discoveredFiles;\n return applyGitIgnore(discoveredFiles);\n}\n\nfunction expandGlobs(paths: string[]): string[] {\n return paths.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\nfunction applyGitIgnore(files: string[]): string[] {\n const gitIgnorePath = resolve(process.cwd(), \".gitignore\");\n if (!existsSync(gitIgnorePath)) return files;\n\n const matcher = ignore().add(readFileSync(gitIgnorePath, \"utf8\"));\n return files.filter((file) => {\n const rel = relative(process.cwd(), file);\n if (rel.startsWith(\"..\")) return true;\n const normalized = rel.split(sep).join(\"/\");\n return !matcher.ignores(normalized);\n });\n}\n","import type { Diagnostic, Rule } from \"../rules/types.ts\";\nimport { getRuleMetadata } from \"../rules/index.ts\";\nimport type {\n ResolvedScanConfig,\n RuleDescriptor,\n RulePolicySeverity,\n ScanExecutionResult,\n ScanResult,\n Severity,\n} from \"./types.ts\";\n\nexport function buildRuleDescriptors(rules: Rule[]): RuleDescriptor[] {\n return rules.map((rule) => {\n const metadata = getRuleMetadata(rule.id);\n return {\n rule,\n category: metadata.category,\n tags: metadata.tags,\n };\n });\n}\n\nexport function resolveActiveRules(\n descriptors: RuleDescriptor[],\n config: ResolvedScanConfig,\n): Rule[] {\n const selectedRules = config.rules ? new Set(config.rules) : null;\n const active: Rule[] = [];\n\n for (const descriptor of descriptors) {\n if (selectedRules && !selectedRules.has(descriptor.rule.id)) continue;\n const resolvedSeverity = resolveRuleSeverity(descriptor, config);\n if (resolvedSeverity === \"off\") continue;\n if (descriptor.rule.severity === resolvedSeverity) {\n active.push(descriptor.rule);\n continue;\n }\n active.push({ ...descriptor.rule, severity: resolvedSeverity });\n }\n\n return active;\n}\n\nfunction resolveRuleSeverity(descriptor: RuleDescriptor, config: ResolvedScanConfig): RulePolicySeverity {\n let severity: RulePolicySeverity = descriptor.rule.severity;\n for (const entry of config.rulePolicy) {\n if (!matchesSelector(descriptor, entry.selector)) continue;\n severity = entry.severity;\n }\n\n if (severity === \"off\") return \"off\";\n if (config.strict) return \"error\";\n return severity;\n}\n\nfunction matchesSelector(descriptor: RuleDescriptor, selector: string): boolean {\n if (selector.startsWith(\"category:\")) {\n return descriptor.category === selector.slice(\"category:\".length);\n }\n if (selector.startsWith(\"tag:\")) {\n return descriptor.tags.includes(selector.slice(\"tag:\".length));\n }\n if (selector === descriptor.rule.id) return true;\n if (!selector.includes(\"*\")) return false;\n const regex = new RegExp(`^${escapeRegex(selector).replaceAll(\"\\\\*\", \".*\")}$`);\n return regex.test(descriptor.rule.id);\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport function finalizeScanResult(\n diagnostics: Diagnostic[],\n fileCount: number,\n config: ResolvedScanConfig,\n): ScanExecutionResult {\n const visibleDiagnostics = config.showSeverities\n ? diagnostics.filter((d) => config.showSeverities?.has(d.severity))\n : diagnostics;\n\n return {\n diagnostics,\n visibleDiagnostics,\n fileCount,\n exitCode: computeExitCode(diagnostics, config.failOn),\n };\n}\n\nexport function toScanResult(execution: ScanExecutionResult): ScanResult {\n return {\n diagnostics: execution.diagnostics,\n fileCount: execution.fileCount,\n };\n}\n\nfunction computeExitCode(diagnostics: Diagnostic[], failOn: \"none\" | Severity): number {\n if (failOn === \"none\") return 0;\n\n const hasError = diagnostics.some((d) => d.severity === \"error\");\n const hasWarning = diagnostics.some((d) => d.severity === \"warning\");\n const hasInfo = diagnostics.some((d) => d.severity === \"info\");\n\n if (failOn === \"error\") return hasError ? 2 : 0;\n if (failOn === \"warning\") {\n if (hasError) return 2;\n return hasWarning ? 1 : 0;\n }\n\n if (hasError) return 2;\n if (hasWarning || hasInfo) return 1;\n return 0;\n}\n","import { allRules } from \"./rules/index.ts\";\nimport { analyzeFiles } from \"./scan/analyze.ts\";\nimport { resolveScanConfig } from \"./scan/config.ts\";\nimport { discoverFiles } from \"./scan/discover.ts\";\nimport { buildRuleDescriptors, finalizeScanResult, resolveActiveRules, toScanResult } from \"./scan/policy.ts\";\nimport type { ScanExecutionResult, ScanOptions, ScanResult } from \"./scan/types.ts\";\n\nexport type {\n FailOn,\n RulePolicy,\n RulePolicyEntry,\n RulePolicySeverity,\n ScanExecutionResult,\n ScanOptions,\n ScanResult,\n Severity,\n} from \"./scan/types.ts\";\n\nexport async function executeScan(options: ScanOptions): Promise<ScanExecutionResult> {\n const config = resolveScanConfig(options);\n const files = await discoverFiles(config);\n const descriptors = buildRuleDescriptors(allRules);\n const activeRules = resolveActiveRules(descriptors, config);\n const diagnostics = analyzeFiles(files, activeRules);\n return finalizeScanResult(diagnostics, files.length, config);\n}\n\nexport async function scan(options: ScanOptions): Promise<ScanResult> {\n const execution = await executeScan(options);\n return toScanResult(execution);\n}\n"],"mappings":"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","names":["ts","ts","ts","ts","ts","ts","ts","visit","ts","ts","visit","parent","ts","getFunctionBody","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ts","ignore","ts","createHash","dirname","ts","normalizeText","dirname","ts","visit","createHash","normalizeText","ts","dirname","existsSync","resolve"]}
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  isRulePolicySeverity,
5
5
  isSeverity,
6
6
  toRulePolicyEntries
7
- } from "./chunk-2QER6GG7.js";
7
+ } from "./chunk-O5DINU36.js";
8
8
 
9
9
  // src/cli.ts
10
10
  import { existsSync, readFileSync } from "fs";