@gulu9527/code-trust 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/engine.ts","../src/parsers/diff.ts","../src/i18n/index.ts","../src/rules/builtin/unnecessary-try-catch.ts","../src/rules/builtin/over-defensive.ts","../src/rules/builtin/dead-logic.ts","../src/parsers/ast.ts","../src/parsers/walk.ts","../src/rules/builtin/unused-variables.ts","../src/rules/builtin/duplicate-condition.ts","../src/rules/builtin/security.ts","../src/rules/builtin/empty-catch.ts","../src/rules/builtin/identical-branches.ts","../src/rules/builtin/redundant-else.ts","../src/rules/builtin/console-in-code.ts","../src/rules/builtin/phantom-import.ts","../src/rules/builtin/unused-import.ts","../src/rules/builtin/missing-await.ts","../src/rules/builtin/any-type-abuse.ts","../src/rules/builtin/type-coercion.ts","../src/rules/builtin/magic-number.ts","../src/rules/builtin/nested-ternary.ts","../src/rules/builtin/duplicate-string.ts","../src/rules/builtin/no-debugger.ts","../src/rules/builtin/no-non-null-assertion.ts","../src/rules/builtin/no-self-compare.ts","../src/rules/builtin/no-return-assign.ts","../src/rules/builtin/promise-void.ts","../src/rules/builtin/no-reassign-param.ts","../src/rules/builtin/no-async-without-await.ts","../src/rules/builtin/no-useless-constructor.ts","../src/rules/engine.ts","../src/core/scorer.ts","../src/analyzers/structure.ts","../src/analyzers/style.ts","../src/analyzers/coverage.ts","../src/core/config.ts","../src/types/config.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Issue, TrustReport, DimensionScore, RuleCategory, ScanOptions } from '../types/index.js';\nimport { CodeTrustConfig } from '../types/config.js';\nimport { DiffParser } from '../parsers/diff.js';\nimport { RuleEngine } from '../rules/engine.js';\nimport { calculateDimensionScore, calculateOverallScore, getGrade } from './scorer.js';\nimport { analyzeStructure } from '../analyzers/structure.js';\nimport { analyzeStyle } from '../analyzers/style.js';\nimport { analyzeCoverage } from '../analyzers/coverage.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst PKG_VERSION: string = (() => {\n try {\n const pkg = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf-8'));\n return pkg.version;\n } catch {\n return '0.1.0';\n }\n})();\n\nexport class ScanEngine {\n private config: CodeTrustConfig;\n private diffParser: DiffParser;\n private ruleEngine: RuleEngine;\n\n constructor(config: CodeTrustConfig, workDir?: string) {\n this.config = config;\n this.diffParser = new DiffParser(workDir);\n this.ruleEngine = new RuleEngine(config);\n }\n\n async scan(options: ScanOptions): Promise<TrustReport> {\n const diffFiles = await this.getDiffFiles(options);\n const allIssues: Issue[] = [];\n\n for (const diffFile of diffFiles) {\n if (diffFile.status === 'deleted') continue;\n\n const filePath = resolve(diffFile.filePath);\n let fileContent: string;\n\n try {\n if (existsSync(filePath)) {\n fileContent = await readFile(filePath, 'utf-8');\n } else {\n const content = await this.diffParser.getFileContent(diffFile.filePath);\n if (!content) continue;\n fileContent = content;\n }\n } catch {\n // Intentionally skip unreadable files\n continue;\n }\n\n const addedLines = diffFile.hunks.flatMap((hunk) => {\n const lines = hunk.content.split('\\n');\n const result: Array<{ lineNumber: number; content: string }> = [];\n let currentLine = hunk.newStart;\n\n for (const line of lines) {\n if (line.startsWith('+')) {\n result.push({ lineNumber: currentLine, content: line.slice(1) });\n currentLine++;\n } else if (line.startsWith('-')) {\n // deleted line, don't increment\n } else {\n currentLine++;\n }\n }\n\n return result;\n });\n\n const issues = this.ruleEngine.run({\n filePath: diffFile.filePath,\n fileContent,\n addedLines,\n });\n\n allIssues.push(...issues);\n\n // AST-based analyzers (structure, style, coverage)\n if (this.isTsJsFile(diffFile.filePath)) {\n const structureResult = analyzeStructure(fileContent, diffFile.filePath, {\n maxCyclomaticComplexity: this.config.thresholds['max-cyclomatic-complexity'],\n maxCognitiveComplexity: this.config.thresholds['max-cognitive-complexity'],\n maxFunctionLength: this.config.thresholds['max-function-length'],\n maxNestingDepth: this.config.thresholds['max-nesting-depth'],\n maxParamCount: this.config.thresholds['max-params'],\n });\n allIssues.push(...structureResult.issues);\n\n const styleResult = analyzeStyle(fileContent, diffFile.filePath);\n allIssues.push(...styleResult.issues);\n\n const coverageResult = analyzeCoverage(fileContent, diffFile.filePath);\n allIssues.push(...coverageResult.issues);\n }\n }\n\n const dimensions = this.groupByDimension(allIssues);\n const overallScore = calculateOverallScore(dimensions, this.config.weights);\n const grade = getGrade(overallScore);\n const commitHash = await this.diffParser.getCurrentCommitHash();\n\n return {\n version: PKG_VERSION,\n timestamp: new Date().toISOString(),\n commit: commitHash,\n overall: {\n score: overallScore,\n grade,\n filesScanned: diffFiles.filter((f) => f.status !== 'deleted').length,\n issuesFound: allIssues.length,\n },\n dimensions,\n issues: allIssues.sort((a, b) => {\n const severityOrder = { high: 0, medium: 1, low: 2, info: 3 };\n return severityOrder[a.severity] - severityOrder[b.severity];\n }),\n };\n }\n\n private async getDiffFiles(options: ScanOptions) {\n if (options.staged) {\n return this.diffParser.getStagedFiles();\n }\n\n if (options.diff) {\n return this.diffParser.getDiffFromRef(options.diff);\n }\n\n if (options.files && options.files.length > 0) {\n // For specific files, create synthetic diff entries\n return Promise.all(\n options.files.map(async (filePath) => {\n let content = '';\n try {\n content = await readFile(resolve(filePath), 'utf-8');\n } catch {\n // file not readable\n }\n return {\n filePath,\n status: 'modified' as const,\n additions: content.split('\\n').length,\n deletions: 0,\n content,\n hunks: [\n {\n oldStart: 1,\n oldLines: 0,\n newStart: 1,\n newLines: content.split('\\n').length,\n content: content\n .split('\\n')\n .map((l) => '+' + l)\n .join('\\n'),\n },\n ],\n };\n }),\n );\n }\n\n // Default: get all uncommitted changes\n return this.diffParser.getChangedFiles();\n }\n\n private isTsJsFile(filePath: string): boolean {\n return /\\.(ts|tsx|js|jsx|mts|mjs|cts|cjs)$/.test(filePath);\n }\n\n private groupByDimension(\n issues: Issue[],\n ): Record<RuleCategory, DimensionScore> {\n const categories: RuleCategory[] = [\n 'security',\n 'logic',\n 'structure',\n 'style',\n 'coverage',\n ];\n\n const grouped: Record<RuleCategory, DimensionScore> = {} as Record<\n RuleCategory,\n DimensionScore\n >;\n\n for (const cat of categories) {\n const catIssues = issues.filter((i) => i.category === cat);\n grouped[cat] = calculateDimensionScore(catIssues);\n }\n\n return grouped;\n }\n}\n","import simpleGit, { SimpleGit } from 'simple-git';\nimport { DiffFile, DiffHunk } from '../types/index.js';\n\nexport class DiffParser {\n private git: SimpleGit;\n\n constructor(workDir?: string) {\n this.git = simpleGit(workDir);\n }\n\n async getStagedFiles(): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff(['--cached', '--unified=3']);\n return this.parseDiffOutput(diffDetail);\n }\n\n async getDiffFromRef(ref: string): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff([ref, '--unified=3']);\n return this.parseDiffOutput(diffDetail);\n }\n\n async getChangedFiles(): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff(['--unified=3']);\n const stagedDetail = await this.git.diff(['--cached', '--unified=3']);\n const allDiff = diffDetail + '\\n' + stagedDetail;\n return this.parseDiffOutput(allDiff);\n }\n\n async getLastCommitDiff(): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff(['HEAD~1', 'HEAD', '--unified=3']);\n return this.parseDiffOutput(diffDetail);\n }\n\n async getCurrentCommitHash(): Promise<string | undefined> {\n try {\n const hash = await this.git.revparse(['HEAD']);\n return hash.trim().slice(0, 7);\n } catch {\n return undefined;\n }\n }\n\n async getFileContent(filePath: string): Promise<string | undefined> {\n try {\n const content = await this.git.show([`HEAD:${filePath}`]);\n return content;\n } catch {\n return undefined;\n }\n }\n\n private parseDiffOutput(diffOutput: string): DiffFile[] {\n const files: DiffFile[] = [];\n const fileDiffs = diffOutput.split(/^diff --git /m).filter(Boolean);\n\n for (const fileDiff of fileDiffs) {\n const file = this.parseFileDiff(fileDiff);\n if (file) {\n files.push(file);\n }\n }\n\n return files;\n }\n\n private parseFileDiff(fileDiff: string): DiffFile | null {\n const lines = fileDiff.split('\\n');\n\n const headerMatch = lines[0]?.match(/a\\/(.+?) b\\/(.+)/);\n if (!headerMatch) return null;\n\n const filePath = headerMatch[2];\n let status: DiffFile['status'] = 'modified';\n let additions = 0;\n let deletions = 0;\n\n if (fileDiff.includes('new file mode')) {\n status = 'added';\n } else if (fileDiff.includes('deleted file mode')) {\n status = 'deleted';\n } else if (fileDiff.includes('rename from')) {\n status = 'renamed';\n }\n\n const hunks = this.parseHunks(fileDiff);\n\n for (const line of fileDiff.split('\\n')) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n additions++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n deletions++;\n }\n }\n\n return {\n filePath,\n status,\n additions,\n deletions,\n hunks,\n };\n }\n\n private parseHunks(fileDiff: string): DiffHunk[] {\n const hunks: DiffHunk[] = [];\n const hunkRegex = /^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@(.*)$/gm;\n let match: RegExpExecArray | null;\n\n const lines = fileDiff.split('\\n');\n\n while ((match = hunkRegex.exec(fileDiff)) !== null) {\n const oldStart = parseInt(match[1], 10);\n const oldLines = parseInt(match[2] || '1', 10);\n const newStart = parseInt(match[3], 10);\n const newLines = parseInt(match[4] || '1', 10);\n\n const hunkStartIndex = lines.findIndex((l) => l.includes(match![0]));\n const hunkContent: string[] = [];\n\n if (hunkStartIndex >= 0) {\n for (let i = hunkStartIndex + 1; i < lines.length; i++) {\n if (lines[i].startsWith('@@ ') || lines[i].startsWith('diff --git ')) {\n break;\n }\n hunkContent.push(lines[i]);\n }\n }\n\n hunks.push({\n oldStart,\n oldLines,\n newStart,\n newLines,\n content: hunkContent.join('\\n'),\n });\n }\n\n return hunks;\n }\n}\n","import { execSync } from 'node:child_process';\n\nlet _cachedLocale: boolean | null = null;\n\n/** @internal 仅用于测试 */\nexport function resetLocaleCache(): void {\n _cachedLocale = null;\n}\n\nexport function isZhLocale(): boolean {\n if (_cachedLocale !== null) return _cachedLocale;\n\n // 1. 用户显式设置 CODETRUST_LANG=zh 优先级最高\n if (process.env.CODETRUST_LANG?.startsWith('zh')) {\n _cachedLocale = true;\n return true;\n }\n if (process.env.CODETRUST_LANG && !process.env.CODETRUST_LANG.startsWith('zh')) {\n _cachedLocale = false;\n return false;\n }\n\n // 2. 标准环境变量\n const envVars = [\n process.env.LANG,\n process.env.LC_ALL,\n process.env.LC_MESSAGES,\n process.env.LANGUAGE,\n ];\n for (const v of envVars) {\n if (v?.startsWith('zh')) {\n _cachedLocale = true;\n return true;\n }\n }\n\n // 3. macOS: 读取 AppleLocale(LANG 可能是 C.UTF-8 但系统实际是中文)\n if (process.platform === 'darwin') {\n try {\n const appleLocale = execSync('defaults read -g AppleLocale 2>/dev/null', {\n encoding: 'utf-8',\n timeout: 1000,\n }).trim();\n if (appleLocale.startsWith('zh')) {\n _cachedLocale = true;\n return true;\n }\n } catch {\n // ignore\n }\n }\n\n _cachedLocale = false;\n return false;\n}\n\nexport function t(en: string, zh: string): string {\n return isZhLocale() ? zh : en;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects unnecessary try-catch blocks that wrap simple statements\n * with generic error handling — a common AI hallucination pattern.\n *\n * Pattern: try { single statement } catch (e) { console.log/error }\n */\nexport const unnecessaryTryCatchRule: Rule = {\n id: 'logic/unnecessary-try-catch',\n category: 'logic',\n severity: 'medium',\n title: 'Unnecessary try-catch wrapping simple statement',\n description:\n 'AI often wraps simple, non-throwing statements in try-catch blocks with generic console.log/error in the catch. This is hallucinated error handling.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n const trimmed = line.trim();\n\n if (trimmed.startsWith('try') && trimmed.includes('{')) {\n const tryBlock = extractBlock(lines, i);\n if (tryBlock) {\n const { bodyLines, catchBodyLines, endLine } = tryBlock;\n\n const nonEmptyBody = bodyLines.filter((l) => l.trim().length > 0);\n const nonEmptyCatch = catchBodyLines.filter((l) => l.trim().length > 0);\n\n const isSimpleBody = nonEmptyBody.length <= 2;\n const isGenericCatch =\n nonEmptyCatch.length <= 2 &&\n nonEmptyCatch.some(\n (l) =>\n /console\\.(log|error|warn)/.test(l) ||\n /throw\\s+(new\\s+)?Error/.test(l) ||\n l.trim() === '',\n );\n\n const bodyHasOnlyAssignments = nonEmptyBody.every(\n (l) =>\n /^\\s*(const|let|var)\\s+/.test(l) ||\n /^\\s*\\w+(\\.\\w+)*\\s*=\\s*/.test(l) ||\n /^\\s*return\\s+/.test(l),\n );\n\n if (isSimpleBody && isGenericCatch && bodyHasOnlyAssignments) {\n issues.push({\n ruleId: 'logic/unnecessary-try-catch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: endLine + 1,\n message: t(\n 'Unnecessary try-catch wrapping a simple statement with generic error handling. This is likely AI-hallucinated error handling.',\n '不必要的 try-catch 包裹了简单语句,catch 中只有通用的错误日志。这很可能是 AI 幻觉生成的错误处理。',\n ),\n suggestion: t(\n 'Remove the try-catch block or add meaningful error recovery logic.',\n '移除 try-catch 块,或添加有意义的错误恢复逻辑。',\n ),\n });\n }\n\n i = endLine + 1;\n continue;\n }\n }\n\n i++;\n }\n\n return issues;\n },\n};\n\ninterface TryCatchBlock {\n bodyLines: string[];\n catchStart: number;\n catchBodyLines: string[];\n endLine: number;\n}\n\nfunction extractBlock(lines: string[], tryLineIndex: number): TryCatchBlock | null {\n let braceCount = 0;\n let foundTryOpen = false;\n let tryBodyStart = -1;\n let tryBodyEnd = -1;\n let catchStart = -1;\n let catchBodyStart = -1;\n let catchBodyEnd = -1;\n\n for (let i = tryLineIndex; i < lines.length; i++) {\n const line = lines[i];\n for (const ch of line) {\n if (ch === '{') {\n braceCount++;\n if (!foundTryOpen) {\n foundTryOpen = true;\n tryBodyStart = i;\n }\n } else if (ch === '}') {\n braceCount--;\n if (braceCount === 0 && tryBodyEnd === -1) {\n tryBodyEnd = i;\n } else if (braceCount === 0 && catchBodyEnd === -1 && catchBodyStart !== -1) {\n catchBodyEnd = i;\n break;\n }\n }\n }\n\n if (tryBodyEnd !== -1 && catchStart === -1) {\n if (line.includes('catch')) {\n catchStart = i;\n }\n }\n\n if (catchStart !== -1 && catchBodyStart === -1 && line.includes('{')) {\n catchBodyStart = i;\n }\n\n if (catchBodyEnd !== -1) break;\n }\n\n if (tryBodyStart === -1 || tryBodyEnd === -1 || catchBodyStart === -1 || catchBodyEnd === -1) {\n return null;\n }\n\n const bodyLines = lines.slice(tryBodyStart + 1, tryBodyEnd);\n const catchBodyLines = lines.slice(catchBodyStart + 1, catchBodyEnd);\n\n return {\n bodyLines,\n catchStart,\n catchBodyLines,\n endLine: catchBodyEnd,\n };\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects over-defensive coding patterns typical of AI-generated code.\n *\n * Pattern: 3+ consecutive null/undefined/empty-string checks at function start,\n * or excessive type guards that the type system already guarantees.\n */\nexport const overDefensiveRule: Rule = {\n id: 'logic/over-defensive',\n category: 'logic',\n severity: 'low',\n title: 'Over-defensive coding pattern',\n description:\n 'AI-generated code often includes excessive null/undefined checks, redundant type guards, and unnecessary validations that the type system already handles.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n let consecutiveChecks = 0;\n let checkStartLine = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n if (isDefensiveCheck(trimmed)) {\n if (consecutiveChecks === 0) {\n checkStartLine = i;\n }\n consecutiveChecks++;\n } else if (trimmed.length > 0) {\n if (consecutiveChecks >= 3) {\n issues.push({\n ruleId: 'logic/over-defensive',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: checkStartLine + 1,\n endLine: i,\n message: t(\n `${consecutiveChecks} consecutive defensive checks detected. AI tends to add excessive null/undefined guards.`,\n `检测到 ${consecutiveChecks} 个连续的防御性检查。AI 倾向于添加过多的 null/undefined 守卫。`,\n ),\n suggestion: t(\n 'Consider if these checks are necessary — TypeScript types may already prevent these cases. Remove redundant guards.',\n '考虑这些检查是否必要 — TypeScript 类型可能已经防止了这些情况。移除冗余的守卫。',\n ),\n });\n }\n consecutiveChecks = 0;\n }\n }\n\n if (consecutiveChecks >= 3) {\n issues.push({\n ruleId: 'logic/over-defensive',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: checkStartLine + 1,\n endLine: lines.length,\n message: t(\n `${consecutiveChecks} consecutive defensive checks detected at end of block.`,\n `在代码块末尾检测到 ${consecutiveChecks} 个连续的防御性检查。`,\n ),\n suggestion: t(\n 'Review if these defensive checks are truly necessary.',\n '检查这些防御性检查是否真正必要。',\n ),\n });\n }\n\n detectRedundantTypeofChecks(context, lines, issues);\n\n return issues;\n },\n};\n\nfunction isDefensiveCheck(line: string): boolean {\n const patterns = [\n /^if\\s*\\(\\s*!?\\w+(\\.\\w+)*\\s*(===?|!==?)\\s*(null|undefined|''|\"\")\\s*\\)/,\n /^if\\s*\\(\\s*!?\\w+(\\.\\w+)*\\s*\\)\\s*\\{?\\s*(return|throw)/,\n /^if\\s*\\(\\s*typeof\\s+\\w+\\s*(===?|!==?)\\s*['\"]undefined['\"]\\s*\\)/,\n /^if\\s*\\(\\s*\\w+(\\.\\w+)*\\s*==\\s*null\\s*\\)/,\n /^if\\s*\\(\\s*!\\w+(\\.\\w+)*\\s*\\)\\s*\\{?\\s*$/,\n /^\\w+(\\.\\w+)*\\s*\\?\\?=/,\n /^if\\s*\\(\\s*Array\\.isArray\\(\\w+\\)\\s*&&\\s*\\w+\\.length\\s*(>|>=|===?)\\s*0\\s*\\)/,\n ];\n\n return patterns.some((p) => p.test(line));\n}\n\nfunction detectRedundantTypeofChecks(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n const typeofMatch = trimmed.match(\n /if\\s*\\(\\s*typeof\\s+(\\w+)\\s*(!==?|===?)\\s*['\"]undefined['\"]\\s*\\)/,\n );\n if (typeofMatch) {\n const varName = typeofMatch[1];\n const prevLines = lines.slice(Math.max(0, i - 5), i);\n const hasDeclaration = prevLines.some((l) =>\n new RegExp(`(const|let|var)\\\\s+${varName}\\\\s*[:=]`).test(l),\n );\n\n if (hasDeclaration) {\n issues.push({\n ruleId: 'logic/over-defensive',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Redundant typeof check for \"${varName}\" — variable is declared within ${prevLines.length} line(s) above and cannot be undefined.`,\n `对 \"${varName}\" 的 typeof 检查是冗余的 — 变量已在上方 ${prevLines.length} 行内声明,不可能为 undefined。`,\n ),\n suggestion: t(\n `Remove the typeof check for \"${varName}\".`,\n `移除对 \"${varName}\" 的 typeof 检查。`,\n ),\n });\n }\n }\n }\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects dead logic patterns — code that can never execute or\n * conditions that are always true/false.\n */\nexport const deadLogicRule: Rule = {\n id: 'logic/dead-branch',\n category: 'logic',\n severity: 'medium',\n title: 'Dead logic branch detected',\n description:\n 'AI-generated code sometimes contains conditions that are always true or false, unreachable code after return/throw, or assign-then-immediately-reassign patterns.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n detectAlwaysTrueFalse(context, lines, issues);\n detectCodeAfterReturn(context, lines, issues);\n detectImmediateReassign(context, lines, issues);\n\n return issues;\n },\n};\n\nfunction detectAlwaysTrueFalse(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n const alwaysTruePatterns = [\n /if\\s*\\(\\s*true\\s*\\)/,\n /if\\s*\\(\\s*1\\s*\\)/,\n /if\\s*\\(\\s*['\"].+['\"]\\s*\\)/,\n ];\n\n const alwaysFalsePatterns = [\n /if\\s*\\(\\s*false\\s*\\)/,\n /if\\s*\\(\\s*0\\s*\\)/,\n /if\\s*\\(\\s*null\\s*\\)/,\n /if\\s*\\(\\s*undefined\\s*\\)/,\n /if\\s*\\(\\s*''\\s*\\)/,\n /if\\s*\\(\\s*\"\"\\s*\\)/,\n ];\n\n for (const pattern of alwaysTruePatterns) {\n if (pattern.test(trimmed)) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Condition is always true — this branch always executes.',\n '条件始终为 true — 此分支始终会执行。',\n ),\n suggestion: t(\n 'Remove the condition and keep only the body, or fix the logic.',\n '移除条件判断只保留主体,或修复逻辑。',\n ),\n });\n }\n }\n\n for (const pattern of alwaysFalsePatterns) {\n if (pattern.test(trimmed)) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Condition is always false — this branch never executes.',\n '条件始终为 false — 此分支永远不会执行。',\n ),\n suggestion: t(\n 'Remove the dead branch entirely.',\n '完全移除该死代码分支。',\n ),\n });\n }\n }\n }\n}\n\nfunction detectCodeAfterReturn(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n let braceDepth = 0;\n let lastReturnDepth = -1;\n let lastReturnLine = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n for (const ch of trimmed) {\n if (ch === '{') braceDepth++;\n if (ch === '}') {\n if (braceDepth === lastReturnDepth) {\n lastReturnDepth = -1;\n lastReturnLine = -1;\n }\n braceDepth--;\n }\n }\n\n if (/^(return|throw)\\b/.test(trimmed) && !trimmed.includes('=>')) {\n // 如果 return/throw 行以开括号结尾(多行返回值),跳过\n const endsOpen = /[{(\\[,]$/.test(trimmed) || /^(return|throw)\\s*$/.test(trimmed);\n if (endsOpen) continue;\n lastReturnDepth = braceDepth;\n lastReturnLine = i;\n } else if (\n lastReturnLine !== -1 &&\n braceDepth === lastReturnDepth &&\n trimmed.length > 0 &&\n trimmed !== '}' &&\n trimmed !== '};' &&\n !trimmed.startsWith('//') &&\n !trimmed.startsWith('case ') &&\n !trimmed.startsWith('default:') &&\n !trimmed.startsWith('default :')\n ) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Unreachable code after return/throw at line ${lastReturnLine + 1}.`,\n `第 ${lastReturnLine + 1} 行的 return/throw 之后存在不可达代码。`,\n ),\n suggestion: t(\n 'Remove unreachable code or restructure the logic.',\n '移除不可达代码或重构逻辑。',\n ),\n });\n lastReturnDepth = -1;\n lastReturnLine = -1;\n }\n }\n}\n\nfunction detectImmediateReassign(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n for (let i = 0; i < lines.length - 1; i++) {\n const current = lines[i].trim();\n const next = lines[i + 1].trim();\n\n const assignMatch = current.match(/^(let|var)\\s+(\\w+)\\s*=\\s*.+;?\\s*$/);\n if (assignMatch) {\n const varName = assignMatch[2];\n const reassignPattern = new RegExp(`^${varName}\\\\s*=\\\\s*.+;?\\\\s*$`);\n if (reassignPattern.test(next)) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 2,\n message: t(\n `Variable \"${varName}\" is assigned and immediately reassigned on the next line.`,\n `变量 \"${varName}\" 赋值后立即在下一行被重新赋值。`,\n ),\n suggestion: t(\n `Remove the first assignment or combine into a single declaration.`,\n `移除第一次赋值,或合并为一次声明。`,\n ),\n });\n }\n }\n }\n}\n","import { parse, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';\nimport type { TSESTree } from '@typescript-eslint/typescript-estree';\nimport { walkAST } from './walk.js';\n\nexport interface ParsedAST {\n ast: TSESTree.Program;\n filePath: string;\n}\n\nconst _astCache = new Map<string, ParsedAST>();\n\nexport function parseCode(code: string, filePath: string): ParsedAST {\n const cacheKey = `${filePath}:${code.length}:${simpleHash(code)}`;\n const cached = _astCache.get(cacheKey);\n if (cached) return cached;\n\n const ast = parse(code, {\n loc: true,\n range: true,\n comment: true,\n jsx: filePath.endsWith('.tsx') || filePath.endsWith('.jsx'),\n filePath,\n });\n\n const result = { ast, filePath };\n _astCache.set(cacheKey, result);\n\n // 限制缓存大小\n if (_astCache.size > 50) {\n const firstKey = _astCache.keys().next().value;\n if (firstKey) _astCache.delete(firstKey);\n }\n\n return result;\n}\n\nfunction simpleHash(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0;\n }\n return hash;\n}\n\nexport interface FunctionInfo {\n name: string;\n startLine: number;\n endLine: number;\n lineCount: number;\n paramCount: number;\n cyclomaticComplexity: number;\n cognitiveComplexity: number;\n maxNestingDepth: number;\n}\n\nexport function extractFunctions(parsed: ParsedAST): FunctionInfo[] {\n const functions: FunctionInfo[] = [];\n visitNode(parsed.ast, functions);\n return functions;\n}\n\nfunction visitNode(root: TSESTree.Node, functions: FunctionInfo[]): void {\n const methodBodies = new WeakSet<TSESTree.Node>();\n\n walkAST(root, (node) => {\n // 跳过 MethodDefinition 内部的 FunctionExpression(避免双重计数)\n if (node.type === AST_NODE_TYPES.FunctionExpression && methodBodies.has(node)) {\n return false;\n }\n\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.MethodDefinition\n ) {\n const info = analyzeFunctionNode(node);\n if (info) functions.push(info);\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n methodBodies.add(node.value);\n }\n }\n return;\n });\n}\n\nfunction analyzeFunctionNode(node: TSESTree.Node): FunctionInfo | null {\n let name = '<anonymous>';\n let params: TSESTree.Parameter[] = [];\n let body: TSESTree.Node | null = null;\n\n if (node.type === AST_NODE_TYPES.FunctionDeclaration) {\n name = node.id?.name ?? '<anonymous>';\n params = node.params;\n body = node.body;\n } else if (node.type === AST_NODE_TYPES.FunctionExpression) {\n name = node.id?.name ?? '<anonymous>';\n params = node.params;\n body = node.body;\n } else if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n name = '<arrow>';\n params = node.params;\n body = node.body;\n } else if (node.type === AST_NODE_TYPES.MethodDefinition) {\n if (node.key.type === AST_NODE_TYPES.Identifier) {\n name = node.key.name;\n }\n const value = node.value;\n params = value.params;\n body = value.body;\n }\n\n if (!body || !node.loc) return null;\n\n const startLine = node.loc.start.line;\n const endLine = node.loc.end.line;\n\n return {\n name,\n startLine,\n endLine,\n lineCount: endLine - startLine + 1,\n paramCount: params.length,\n cyclomaticComplexity: body ? calculateCyclomaticComplexity(body) : 1,\n cognitiveComplexity: body ? calculateCognitiveComplexity(body) : 0,\n maxNestingDepth: body ? calculateMaxNestingDepth(body) : 0,\n };\n}\n\n// 圈复杂度:每个分支点 +1\nfunction calculateCyclomaticComplexity(root: TSESTree.Node): number {\n let complexity = 1;\n\n walkAST(root, (n) => {\n switch (n.type) {\n case AST_NODE_TYPES.IfStatement:\n case AST_NODE_TYPES.ConditionalExpression:\n case AST_NODE_TYPES.ForStatement:\n case AST_NODE_TYPES.ForInStatement:\n case AST_NODE_TYPES.ForOfStatement:\n case AST_NODE_TYPES.WhileStatement:\n case AST_NODE_TYPES.DoWhileStatement:\n case AST_NODE_TYPES.CatchClause:\n complexity++;\n break;\n case AST_NODE_TYPES.SwitchCase:\n if (n.test) complexity++;\n break;\n case AST_NODE_TYPES.LogicalExpression:\n if (n.operator === '&&' || n.operator === '||' || n.operator === '??') {\n complexity++;\n }\n break;\n }\n });\n\n return complexity;\n}\n\n// 认知复杂度:嵌套越深越难理解\nfunction calculateCognitiveComplexity(root: TSESTree.Node): number {\n let complexity = 0;\n const depthMap = new WeakMap<TSESTree.Node, number>();\n depthMap.set(root, 0);\n\n walkAST(root, (n, parent) => {\n const parentDepth = parent ? (depthMap.get(parent) ?? 0) : 0;\n const isNesting = isNestingNode(n);\n const depth = isNesting ? parentDepth + 1 : parentDepth;\n depthMap.set(n, depth);\n\n if (isNesting) {\n complexity += 1 + parentDepth;\n }\n\n if (\n n.type === AST_NODE_TYPES.LogicalExpression &&\n (n.operator === '&&' || n.operator === '||' || n.operator === '??')\n ) {\n complexity += 1;\n }\n });\n\n return complexity;\n}\n\n// 最大嵌套深度\nfunction calculateMaxNestingDepth(root: TSESTree.Node): number {\n let maxDepth = 0;\n const depthMap = new WeakMap<TSESTree.Node, number>();\n depthMap.set(root, 0);\n\n walkAST(root, (n, parent) => {\n const parentDepth = parent ? (depthMap.get(parent) ?? 0) : 0;\n const isNesting =\n n.type === AST_NODE_TYPES.IfStatement ||\n n.type === AST_NODE_TYPES.ForStatement ||\n n.type === AST_NODE_TYPES.ForInStatement ||\n n.type === AST_NODE_TYPES.ForOfStatement ||\n n.type === AST_NODE_TYPES.WhileStatement ||\n n.type === AST_NODE_TYPES.DoWhileStatement ||\n n.type === AST_NODE_TYPES.SwitchStatement ||\n n.type === AST_NODE_TYPES.TryStatement;\n\n const currentDepth = isNesting ? parentDepth + 1 : parentDepth;\n depthMap.set(n, currentDepth);\n if (currentDepth > maxDepth) maxDepth = currentDepth;\n });\n\n return maxDepth;\n}\n\nfunction isNestingNode(n: TSESTree.Node): boolean {\n return (\n n.type === AST_NODE_TYPES.IfStatement ||\n n.type === AST_NODE_TYPES.ForStatement ||\n n.type === AST_NODE_TYPES.ForInStatement ||\n n.type === AST_NODE_TYPES.ForOfStatement ||\n n.type === AST_NODE_TYPES.WhileStatement ||\n n.type === AST_NODE_TYPES.DoWhileStatement ||\n n.type === AST_NODE_TYPES.SwitchStatement ||\n n.type === AST_NODE_TYPES.CatchClause ||\n n.type === AST_NODE_TYPES.ConditionalExpression\n );\n}\n\nexport { AST_NODE_TYPES };\nexport type { TSESTree };\n","import type { TSESTree } from '@typescript-eslint/typescript-estree';\n\n/**\n * Generic AST walker — eliminates the repeated Object.keys + cast pattern\n * used across multiple files.\n *\n * @param node The root AST node to walk\n * @param visitor Called for every node; return `false` to skip children\n */\nexport type ASTVisitor = (node: TSESTree.Node, parent: TSESTree.Node | null) => boolean | void;\n\nexport function walkAST(\n node: TSESTree.Node,\n visitor: ASTVisitor,\n parent: TSESTree.Node | null = null,\n): void {\n const result = visitor(node, parent);\n if (result === false) return; // skip children\n\n for (const key of Object.keys(node)) {\n if (key === 'parent') continue;\n const child = (node as unknown as Record<string, unknown>)[key];\n if (child && typeof child === 'object') {\n if (Array.isArray(child)) {\n for (const item of child) {\n if (isASTNode(item)) {\n walkAST(item, visitor, node);\n }\n }\n } else if (isASTNode(child)) {\n walkAST(child as TSESTree.Node, visitor, node);\n }\n }\n }\n}\n\n\nfunction isASTNode(value: unknown): value is TSESTree.Node {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'type' in (value as Record<string, unknown>)\n );\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects variables that are declared but never used.\n * AI-generated code often introduces variables that are assigned\n * but never referenced elsewhere.\n */\nexport const unusedVariablesRule: Rule = {\n id: 'logic/unused-variables',\n category: 'logic',\n severity: 'low',\n title: 'Unused variable detected',\n description:\n 'AI-generated code sometimes declares variables that are never used, indicating incomplete or hallucinated logic.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const declarations = new Map<string, { line: number; kind: string }>();\n const references = new Set<string>();\n\n collectDeclarationsAndReferences(ast, declarations, references);\n\n for (const [name, info] of declarations) {\n // 跳过以 _ 开头的变量(约定为有意忽略)\n if (name.startsWith('_')) continue;\n // 跳过导出的变量\n if (info.kind === 'export') continue;\n\n if (!references.has(name)) {\n issues.push({\n ruleId: 'logic/unused-variables',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: info.line,\n endLine: info.line,\n message: t(\n `Variable \"${name}\" is declared but never used.`,\n `变量 \"${name}\" 已声明但从未使用。`,\n ),\n suggestion: t(\n `Remove the unused variable \"${name}\" or prefix it with _ if intentionally unused.`,\n `移除未使用的变量 \"${name}\",或用 _ 前缀标记为有意忽略。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n\nfunction collectDeclarationsAndReferences(\n root: TSESTree.Node,\n declarations: Map<string, { line: number; kind: string }>,\n references: Set<string>,\n): void {\n // 先收集所有 export 声明的变量名\n // AST 结构: ExportNamedDeclaration → VariableDeclaration → VariableDeclarator\n const exportedNames = new Set<string>();\n walkAST(root, (node) => {\n if (node.type === AST_NODE_TYPES.ExportNamedDeclaration) {\n walkAST(node, (inner) => {\n if (inner.type === AST_NODE_TYPES.VariableDeclarator && inner.id.type === AST_NODE_TYPES.Identifier) {\n exportedNames.add(inner.id.name);\n }\n if (inner.type === AST_NODE_TYPES.FunctionDeclaration && inner.id) {\n exportedNames.add(inner.id.name);\n }\n });\n }\n });\n\n walkAST(root, (node, parent) => {\n const parentType = parent?.type;\n\n if (node.type === AST_NODE_TYPES.VariableDeclarator) {\n if (node.id.type === AST_NODE_TYPES.Identifier) {\n declarations.set(node.id.name, {\n line: node.loc?.start.line ?? 0,\n kind: exportedNames.has(node.id.name) ? 'export' : 'local',\n });\n }\n // 遍历 init 中的引用(但不遍历 id)\n if (node.init) {\n walkAST(node.init, (n) => {\n if (n.type === AST_NODE_TYPES.Identifier) {\n references.add(n.name);\n }\n });\n }\n return false;\n }\n\n if (node.type === AST_NODE_TYPES.FunctionDeclaration && node.id) {\n declarations.set(node.id.name, {\n line: node.loc?.start.line ?? 0,\n kind: exportedNames.has(node.id.name) ? 'export' : 'local',\n });\n }\n\n // 收集引用(非声明位置的 Identifier)\n if (\n node.type === AST_NODE_TYPES.Identifier &&\n parentType !== 'VariableDeclarator' &&\n parentType !== 'FunctionDeclaration'\n ) {\n references.add(node.name);\n }\n return;\n });\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects duplicate conditions in if-else chains.\n * AI often generates if-else chains where the same condition\n * appears multiple times, making some branches unreachable.\n */\nexport const duplicateConditionRule: Rule = {\n id: 'logic/duplicate-condition',\n category: 'logic',\n severity: 'medium',\n title: 'Duplicate condition in if-else chain',\n description:\n 'AI-generated code sometimes contains duplicate conditions in if-else chains, making later branches unreachable.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const visited = new WeakSet<TSESTree.Node>();\n\n walkAST(ast, (node) => {\n if (node.type === AST_NODE_TYPES.IfStatement && !visited.has(node)) {\n const conditions: Array<{ text: string; line: number }> = [];\n collectIfElseChainConditions(node, conditions, visited);\n\n if (conditions.length >= 2) {\n const seen = new Map<string, number>();\n for (const cond of conditions) {\n if (seen.has(cond.text)) {\n const firstLine = seen.get(cond.text)!;\n issues.push({\n ruleId: 'logic/duplicate-condition',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: cond.line,\n endLine: cond.line,\n message: t(\n `Duplicate condition \"${truncate(cond.text, 40)}\" — same condition already checked at line ${firstLine}.`,\n `重复条件 \"${truncate(cond.text, 40)}\" — 相同条件已在第 ${firstLine} 行检查过。`,\n ),\n suggestion: t(\n 'Remove the duplicate branch or change the condition.',\n '移除重复的分支或修改条件。',\n ),\n });\n } else {\n seen.set(cond.text, cond.line);\n }\n }\n }\n }\n });\n\n return issues;\n },\n};\n\nfunction collectIfElseChainConditions(\n node: TSESTree.IfStatement,\n conditions: Array<{ text: string; line: number }>,\n visited: WeakSet<TSESTree.Node>,\n): void {\n visited.add(node);\n const condText = stringifyCondition(node.test);\n conditions.push({ text: condText, line: node.loc?.start.line ?? 0 });\n\n if (node.alternate?.type === AST_NODE_TYPES.IfStatement) {\n collectIfElseChainConditions(node.alternate, conditions, visited);\n }\n}\n\nfunction stringifyCondition(node: TSESTree.Node): string {\n switch (node.type) {\n case AST_NODE_TYPES.Identifier:\n return node.name;\n case AST_NODE_TYPES.Literal:\n return String(node.value);\n case AST_NODE_TYPES.BinaryExpression:\n case AST_NODE_TYPES.LogicalExpression:\n return `${stringifyCondition(node.left)} ${node.operator} ${stringifyCondition(node.right)}`;\n case AST_NODE_TYPES.UnaryExpression:\n return `${node.operator}${stringifyCondition(node.argument)}`;\n case AST_NODE_TYPES.MemberExpression:\n return `${stringifyCondition(node.object)}.${stringifyCondition(node.property)}`;\n case AST_NODE_TYPES.CallExpression:\n return `${stringifyCondition(node.callee)}(...)`;\n default:\n return `[${node.type}]`;\n }\n}\n\nfunction truncate(s: string, maxLen: number): string {\n return s.length > maxLen ? s.slice(0, maxLen) + '...' : s;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects common security issues in code:\n * - Hardcoded secrets/API keys\n * - eval() usage\n * - SQL injection patterns\n * - Insecure crypto usage\n * - Dangerous innerHTML/outerHTML\n */\nexport const securityRules: Rule[] = [\n {\n id: 'security/hardcoded-secret',\n category: 'security',\n severity: 'high',\n title: 'Hardcoded secret or API key',\n description: 'Hardcoded secrets, API keys, passwords, or tokens in source code.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n const secretPatterns = [\n // API keys / tokens\n { pattern: /(?:api[_-]?key|apikey)\\s*[:=]\\s*['\"`][A-Za-z0-9_\\-]{16,}['\"`]/i, label: 'API key' },\n { pattern: /(?:secret|token|password|passwd|pwd)\\s*[:=]\\s*['\"`][^'\"`]{8,}['\"`]/i, label: 'secret/password' },\n // AWS\n { pattern: /AKIA[0-9A-Z]{16}/, label: 'AWS Access Key' },\n // GitHub\n { pattern: /gh[ps]_[A-Za-z0-9_]{36,}/i, label: 'GitHub Token' },\n // Generic long hex/base64 strings assigned to key-like variables\n { pattern: /(?:key|secret|token|auth)\\s*[:=]\\s*['\"`][A-Fa-f0-9]{32,}['\"`]/i, label: 'hex secret' },\n // Private key\n { pattern: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, label: 'private key' },\n // JWT\n { pattern: /eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/, label: 'JWT token' },\n ];\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Skip comments and imports\n if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('import ')) continue;\n // Skip env variable references\n if (/process\\.env\\b/.test(line)) continue;\n\n for (const { pattern, label } of secretPatterns) {\n if (pattern.test(line)) {\n issues.push({\n ruleId: 'security/hardcoded-secret',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Possible hardcoded ${label} detected. Never commit secrets to source code.`,\n `检测到可能的硬编码${label}。永远不要将密钥提交到源代码中。`,\n ),\n suggestion: t(\n 'Use environment variables or a secrets manager instead.',\n '请改用环境变量或密钥管理服务。',\n ),\n });\n break; // one issue per line\n }\n }\n }\n\n return issues;\n },\n },\n\n {\n id: 'security/eval-usage',\n category: 'security',\n severity: 'high',\n title: 'Dangerous eval() usage',\n description: 'eval() can execute arbitrary code and is a major security risk.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n // eval(), new Function(), setTimeout/setInterval with string\n const evalPatterns = [\n { pattern: /\\beval\\s*\\(/, label: 'eval()' },\n { pattern: /new\\s+Function\\s*\\(/, label: 'new Function()' },\n { pattern: /\\b(setTimeout|setInterval)\\s*\\(\\s*['\"`]/, label: 'setTimeout/setInterval with string' },\n ];\n\n for (const { pattern, label } of evalPatterns) {\n if (pattern.test(lines[i])) {\n issues.push({\n ruleId: 'security/eval-usage',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Dangerous ${label} detected — can execute arbitrary code.`,\n `检测到危险的 ${label} — 可执行任意代码。`,\n ),\n suggestion: t(\n `Avoid ${label}. Use safer alternatives like JSON.parse() or proper function references.`,\n `避免使用 ${label}。使用更安全的替代方案,如 JSON.parse() 或函数引用。`,\n ),\n });\n break;\n }\n }\n }\n\n return issues;\n },\n },\n\n {\n id: 'security/sql-injection',\n category: 'security',\n severity: 'high',\n title: 'Potential SQL injection',\n description: 'String concatenation or template literals in SQL queries can lead to SQL injection.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n // SQL query with string concatenation or template literal with variable\n const sqlKeywords = /\\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER)\\b/i;\n if (sqlKeywords.test(lines[i])) {\n // Check for string concat or template with variables\n if (/\\$\\{[^}]+\\}/.test(lines[i]) || /['\"]\\s*\\+\\s*\\w+/.test(lines[i])) {\n issues.push({\n ruleId: 'security/sql-injection',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Potential SQL injection — string interpolation in SQL query.',\n '潜在的 SQL 注入 — SQL 查询中使用了字符串插值。',\n ),\n suggestion: t(\n 'Use parameterized queries or prepared statements instead.',\n '请改用参数化查询或预编译语句。',\n ),\n });\n }\n }\n }\n\n return issues;\n },\n },\n\n {\n id: 'security/dangerous-html',\n category: 'security',\n severity: 'medium',\n title: 'Dangerous HTML manipulation',\n description: 'Direct innerHTML/outerHTML assignment can lead to XSS attacks.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n if (/\\.(innerHTML|outerHTML)\\s*=/.test(lines[i]) || /dangerouslySetInnerHTML/.test(lines[i])) {\n issues.push({\n ruleId: 'security/dangerous-html',\n severity: 'medium',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Direct HTML assignment detected — potential XSS vulnerability.',\n '检测到直接 HTML 赋值 — 可能存在 XSS 漏洞。',\n ),\n suggestion: t(\n 'Use safe DOM APIs like textContent, or sanitize HTML before insertion.',\n '使用安全的 DOM API(如 textContent),或在插入前对 HTML 进行清洗。',\n ),\n });\n }\n }\n\n return issues;\n },\n },\n];\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects empty or useless catch blocks that silently swallow errors.\n *\n * Patterns:\n * - catch (e) {} — completely empty\n * - catch (e) { // ignored } — only comments\n * - catch (e) { throw e; } — re-throws without modification\n */\nexport const emptyCatchRule: Rule = {\n id: 'logic/empty-catch',\n category: 'logic',\n severity: 'medium',\n title: 'Empty or useless catch block',\n description:\n 'AI-generated code often includes catch blocks that silently swallow errors (empty body) or pointlessly re-throw the same error without modification.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n let inBlockComment = false;\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n // Match catch block opening\n const catchMatch = trimmed.match(/\\bcatch\\s*\\(\\s*(\\w+)?\\s*\\)\\s*\\{/);\n if (!catchMatch) continue;\n\n const catchVarName = catchMatch[1] || '';\n const blockContent = extractCatchBody(lines, i);\n if (!blockContent) continue;\n\n const { bodyLines, endLine } = blockContent;\n const meaningful = bodyLines.filter(\n (l) => l.trim().length > 0 && !l.trim().startsWith('//') && !l.trim().startsWith('*'),\n );\n\n // Pattern 1: Completely empty or only comments\n if (meaningful.length === 0) {\n issues.push({\n ruleId: 'logic/empty-catch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: endLine + 1,\n message: t(\n 'Empty catch block silently swallows errors. This is a common AI hallucination pattern.',\n '空的 catch 块静默吞掉了错误。这是常见的 AI 幻觉模式。',\n ),\n suggestion: t(\n 'Add error handling logic, or remove the try-catch if the operation cannot fail.',\n '添加错误处理逻辑,或在操作不会抛错时移除 try-catch。',\n ),\n });\n continue;\n }\n\n // Pattern 2: Just re-throws the same error without modification\n if (catchVarName && meaningful.length === 1) {\n const onlyLine = meaningful[0].trim();\n if (\n onlyLine === `throw ${catchVarName};` ||\n onlyLine === `throw ${catchVarName}`\n ) {\n issues.push({\n ruleId: 'logic/empty-catch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: endLine + 1,\n message: t(\n `Catch block only re-throws the original error \"${catchVarName}\" without modification. The try-catch is pointless.`,\n `catch 块仅原样重新抛出错误 \"${catchVarName}\",没有任何修改。try-catch 毫无意义。`,\n ),\n suggestion: t(\n 'Remove the try-catch block entirely, or wrap the error with additional context.',\n '完全移除 try-catch 块,或在重新抛出时添加额外的上下文信息。',\n ),\n });\n }\n }\n }\n\n return issues;\n },\n};\n\ninterface CatchBody {\n bodyLines: string[];\n endLine: number;\n}\n\nfunction extractCatchBody(lines: string[], catchLineIndex: number): CatchBody | null {\n // Find the 'catch' keyword position to skip the preceding '}' from the try block\n const catchLine = lines[catchLineIndex];\n const catchIdx = catchLine.indexOf('catch');\n if (catchIdx === -1) return null;\n\n let braceCount = 0;\n let started = false;\n let bodyStart = -1;\n\n for (let i = catchLineIndex; i < lines.length; i++) {\n const line = lines[i];\n const startJ = i === catchLineIndex ? catchIdx : 0;\n\n for (let j = startJ; j < line.length; j++) {\n const ch = line[j];\n if (ch === '{') {\n braceCount++;\n if (!started) {\n started = true;\n bodyStart = i;\n }\n } else if (ch === '}') {\n braceCount--;\n if (started && braceCount === 0) {\n return {\n bodyLines: lines.slice(bodyStart + 1, i),\n endLine: i,\n };\n }\n }\n }\n }\n\n return null;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects if-else blocks where both branches contain identical code.\n *\n * AI often generates if/else with the same logic in both branches,\n * making the condition meaningless.\n */\nexport const identicalBranchesRule: Rule = {\n id: 'logic/identical-branches',\n category: 'logic',\n severity: 'medium',\n title: 'Identical if/else branches',\n description:\n 'AI-generated code sometimes contains if/else blocks where both branches have identical code, making the condition meaningless.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const parsed = parseCode(context.fileContent, context.filePath);\n if (!parsed) return issues;\n\n const source = context.fileContent;\n\n walkAST(parsed.ast, (node) => {\n if (\n node.type === AST_NODE_TYPES.IfStatement &&\n node.consequent &&\n node.alternate\n ) {\n // Skip else-if chains — only check simple if/else\n if (node.alternate.type === AST_NODE_TYPES.IfStatement) return;\n\n const thenCode = extractBlockText(source, node.consequent);\n const elseCode = extractBlockText(source, node.alternate);\n\n if (thenCode && elseCode && thenCode === elseCode && thenCode.length > 0) {\n issues.push({\n ruleId: 'logic/identical-branches',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n 'The if and else branches contain identical code. The condition is meaningless.',\n 'if 和 else 分支包含完全相同的代码,条件判断毫无意义。',\n ),\n suggestion: t(\n 'Remove the if/else and keep only one copy of the code, or fix the branching logic.',\n '移除 if/else,只保留一份代码;或修复分支逻辑。',\n ),\n });\n }\n }\n });\n\n return issues;\n },\n};\n\nfunction extractBlockText(\n source: string,\n node: { type: string; range?: [number, number] },\n): string {\n if (!node.range) return '';\n\n let text = source.slice(node.range[0], node.range[1]);\n\n // If it's a block statement, strip the outer { }\n if (text.startsWith('{')) text = text.slice(1);\n if (text.endsWith('}')) text = text.slice(0, -1);\n\n // Normalize whitespace for comparison\n return text.trim().replace(/\\s+/g, ' ');\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects redundant else blocks after return/throw/continue/break.\n *\n * Pattern:\n * if (condition) { return x; } else { doSomething(); }\n * →\n * if (condition) { return x; }\n * doSomething();\n *\n * AI often generates this pattern instead of using early returns.\n */\nexport const redundantElseRule: Rule = {\n id: 'logic/redundant-else',\n category: 'logic',\n severity: 'low',\n title: 'Redundant else after return/throw',\n description:\n 'AI-generated code often uses else blocks after if blocks that already return/throw. The else is unnecessary and adds nesting.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const parsed = parseCode(context.fileContent, context.filePath);\n if (!parsed) return issues;\n\n walkAST(parsed.ast, (node) => {\n if (\n node.type === AST_NODE_TYPES.IfStatement &&\n node.consequent &&\n node.alternate &&\n node.alternate.type !== AST_NODE_TYPES.IfStatement // Skip else-if\n ) {\n if (blockEndsWithExit(node.consequent)) {\n issues.push({\n ruleId: 'logic/redundant-else',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n 'Unnecessary else — the if block already returns/throws. The else adds pointless nesting.',\n '不必要的 else — if 块已经 return/throw 了,else 增加了无意义的嵌套。',\n ),\n suggestion: t(\n 'Remove the else wrapper and place its code after the if block (early return pattern).',\n '移除 else 包裹,将其代码放在 if 块之后(提前返回模式)。',\n ),\n });\n }\n }\n return;\n });\n\n return issues;\n },\n};\n\nfunction blockEndsWithExit(node: { type: string; body?: unknown }): boolean {\n // BlockStatement with last statement being return/throw\n if (node.type === AST_NODE_TYPES.BlockStatement) {\n if (!Array.isArray(node.body)) return false;\n const body = node.body as Array<{ type: string }>;\n if (body.length === 0) return false;\n const last = body[body.length - 1];\n return (\n last.type === AST_NODE_TYPES.ReturnStatement ||\n last.type === AST_NODE_TYPES.ThrowStatement\n );\n }\n // Single statement (no block)\n return (\n node.type === AST_NODE_TYPES.ReturnStatement ||\n node.type === AST_NODE_TYPES.ThrowStatement\n );\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects console.log/warn/error statements left in code.\n *\n * AI-generated code frequently includes console.log for debugging\n * that should be removed before production.\n * Severity is 'info' since some projects legitimately use console.\n */\nexport const consoleInCodeRule: Rule = {\n id: 'logic/console-in-code',\n category: 'logic',\n severity: 'info',\n title: 'Console statement left in code',\n description:\n 'AI-generated code often includes console.log/warn/error statements intended for debugging that should be removed or replaced with a proper logger.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n // Skip files that are likely CLI/logger utilities\n const lowerPath = context.filePath.toLowerCase();\n if (\n lowerPath.includes('/cli/') ||\n lowerPath.includes('logger') ||\n lowerPath.includes('log.') ||\n lowerPath.endsWith('.test.ts') ||\n lowerPath.endsWith('.test.js') ||\n lowerPath.endsWith('.spec.ts') ||\n lowerPath.endsWith('.spec.js')\n ) {\n return issues;\n }\n\n let count = 0;\n const locations: number[] = [];\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n if (trimmed.startsWith('//')) continue;\n\n if (/\\bconsole\\.(log|warn|error|info|debug|trace)\\s*\\(/.test(trimmed)) {\n count++;\n locations.push(i + 1);\n }\n }\n\n // Only report if there are 3+ console statements (to reduce noise)\n if (count >= 3) {\n issues.push({\n ruleId: 'logic/console-in-code',\n severity: 'info',\n category: 'logic',\n file: context.filePath,\n startLine: locations[0],\n endLine: locations[locations.length - 1],\n message: t(\n `${count} console statements found. AI-generated code often leaves debug logging that should be removed or replaced with a proper logger.`,\n `发现 ${count} 个 console 语句。AI 生成的代码经常留下调试日志,应该移除或替换为正式的日志工具。`,\n ),\n suggestion: t(\n 'Remove console statements or replace with a structured logger (e.g. winston, pino).',\n '移除 console 语句或替换为结构化日志工具(如 winston、pino)。',\n ),\n });\n }\n\n return issues;\n },\n};\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects imports that reference non-existent relative modules.\n * AI often hallucinates import paths — referencing files, functions,\n * or modules that don't actually exist in the project.\n */\nexport const phantomImportRule: Rule = {\n id: 'logic/phantom-import',\n category: 'logic',\n severity: 'high',\n title: 'Phantom import — module does not exist',\n description:\n 'AI-generated code frequently imports from non-existent relative paths, indicating hallucinated modules or functions.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n // Only check files with an actual file path on disk\n if (!context.filePath || context.filePath === '<unknown>') {\n return issues;\n }\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const fileDir = dirname(resolve(context.filePath));\n\n walkAST(ast, (node) => {\n // ImportDeclaration: import { foo } from './bar'\n if (node.type === AST_NODE_TYPES.ImportDeclaration) {\n const source = node.source.value;\n if (typeof source === 'string' && isRelativePath(source)) {\n if (!resolveModulePath(fileDir, source)) {\n issues.push({\n ruleId: 'logic/phantom-import',\n severity: 'high',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n `Import from \"${source}\" — module does not exist.`,\n `导入 \"${source}\" — 模块不存在。`,\n ),\n suggestion: t(\n 'Verify the import path. The AI may have hallucinated this module.',\n '检查导入路径,AI 可能编造了这个模块。',\n ),\n });\n }\n }\n }\n\n // Dynamic import: import('./bar') or require('./bar')\n if (\n node.type === AST_NODE_TYPES.ImportExpression &&\n node.source.type === AST_NODE_TYPES.Literal &&\n typeof node.source.value === 'string'\n ) {\n const source = node.source.value;\n if (isRelativePath(source) && !resolveModulePath(fileDir, source)) {\n issues.push({\n ruleId: 'logic/phantom-import',\n severity: 'high',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n `Dynamic import \"${source}\" — module does not exist.`,\n `动态导入 \"${source}\" — 模块不存在。`,\n ),\n suggestion: t(\n 'Verify the import path. The AI may have hallucinated this module.',\n '检查导入路径,AI 可能编造了这个模块。',\n ),\n });\n }\n }\n\n // require('./bar')\n if (\n node.type === AST_NODE_TYPES.CallExpression &&\n node.callee.type === AST_NODE_TYPES.Identifier &&\n node.callee.name === 'require' &&\n node.arguments.length >= 1 &&\n node.arguments[0].type === AST_NODE_TYPES.Literal &&\n typeof node.arguments[0].value === 'string'\n ) {\n const source = node.arguments[0].value;\n if (isRelativePath(source) && !resolveModulePath(fileDir, source)) {\n issues.push({\n ruleId: 'logic/phantom-import',\n severity: 'high',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n `Require \"${source}\" — module does not exist.`,\n `Require \"${source}\" — 模块不存在。`,\n ),\n suggestion: t(\n 'Verify the require path. The AI may have hallucinated this module.',\n '检查 require 路径,AI 可能编造了这个模块。',\n ),\n });\n }\n }\n });\n\n return issues;\n },\n};\n\nfunction isRelativePath(source: string): boolean {\n return source.startsWith('./') || source.startsWith('../');\n}\n\n/**\n * Try to resolve a relative import to an actual file.\n * Checks common extensions: .ts, .tsx, .js, .jsx, .mts, .mjs, .json\n * Also checks for index files in directories.\n */\nfunction resolveModulePath(dir: string, importPath: string): boolean {\n const resolved = resolve(dir, importPath);\n\n // Exact match (e.g., import './data.json')\n if (existsSync(resolved)) return true;\n\n // TypeScript ESM convention: import './foo.js' → actually ./foo.ts\n // Map .js → .ts/.tsx, .mjs → .mts, .cjs → .cts\n const extMap: Record<string, string[]> = {\n '.js': ['.ts', '.tsx'],\n '.jsx': ['.tsx'],\n '.mjs': ['.mts'],\n '.cjs': ['.cts'],\n };\n for (const [fromExt, toExts] of Object.entries(extMap)) {\n if (importPath.endsWith(fromExt)) {\n const base = resolved.slice(0, -fromExt.length);\n for (const toExt of toExts) {\n if (existsSync(base + toExt)) return true;\n }\n }\n }\n\n // Try common extensions (for extensionless imports)\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs', '.cts', '.cjs', '.json'];\n for (const ext of extensions) {\n if (existsSync(resolved + ext)) return true;\n }\n\n // Directory with index file\n for (const ext of extensions) {\n if (existsSync(resolve(resolved, `index${ext}`))) return true;\n }\n\n return false;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects imported identifiers that are never referenced in the code.\n * AI frequently imports modules or functions it never actually uses,\n * indicating incomplete or hallucinated logic.\n */\nexport const unusedImportRule: Rule = {\n id: 'logic/unused-import',\n category: 'logic',\n severity: 'low',\n title: 'Unused import',\n description:\n 'AI-generated code often imports modules or identifiers that are never used in the file.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // Collect all import specifiers with their names and locations\n const imports: Array<{\n name: string;\n local: string;\n line: number;\n isTypeOnly: boolean;\n source: string;\n }> = [];\n\n // Collect namespace imports (import * as foo) — harder to track usage\n const namespaceImports = new Set<string>();\n\n for (const node of ast.body) {\n if (node.type !== AST_NODE_TYPES.ImportDeclaration) continue;\n\n const source = String(node.source.value);\n const isTypeOnlyImport = (node as { importKind?: string }).importKind === 'type';\n\n for (const spec of node.specifiers) {\n if (spec.type === AST_NODE_TYPES.ImportNamespaceSpecifier) {\n // import * as foo — skip, too complex to reliably check\n namespaceImports.add(spec.local.name);\n continue;\n }\n\n const isTypeOnlySpec =\n isTypeOnlyImport ||\n (spec.type === AST_NODE_TYPES.ImportSpecifier &&\n (spec as { importKind?: string }).importKind === 'type');\n\n imports.push({\n name: spec.type === AST_NODE_TYPES.ImportSpecifier\n ? (spec.imported as { name: string }).name\n : 'default',\n local: spec.local.name,\n line: spec.loc?.start.line ?? 0,\n isTypeOnly: isTypeOnlySpec,\n source,\n });\n }\n }\n\n if (imports.length === 0) return issues;\n\n // Collect all identifier references outside of import declarations\n const references = new Set<string>();\n const importNodes = new WeakSet<TSESTree.Node>();\n\n for (const node of ast.body) {\n if (node.type === AST_NODE_TYPES.ImportDeclaration) {\n importNodes.add(node);\n }\n }\n\n walkAST(ast, (node) => {\n // Skip import declaration subtrees\n if (importNodes.has(node)) return false;\n\n if (node.type === AST_NODE_TYPES.Identifier) {\n references.add(node.name);\n }\n\n // JSX element names: <MyComponent />\n if (node.type === AST_NODE_TYPES.JSXIdentifier) {\n references.add((node as { name: string }).name);\n }\n return;\n });\n\n // Also check for references in type annotations via string matching\n // This catches cases where type-only imports are used in type positions\n // that the AST walker might miss\n const typeRefPattern = /\\b([A-Z][A-Za-z0-9]*)\\b/g;\n let match;\n while ((match = typeRefPattern.exec(context.fileContent)) !== null) {\n references.add(match[1]);\n }\n\n // Report unused imports\n for (const imp of imports) {\n if (!references.has(imp.local)) {\n issues.push({\n ruleId: 'logic/unused-import',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: imp.line,\n endLine: imp.line,\n message: t(\n `Imported \"${imp.local}\" from \"${imp.source}\" is never used.`,\n `从 \"${imp.source}\" 导入的 \"${imp.local}\" 从未使用。`,\n ),\n suggestion: t(\n `Remove the unused import \"${imp.local}\".`,\n `移除未使用的导入 \"${imp.local}\"。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects calls to async functions or Promise-returning functions\n * inside async functions where the `await` keyword is missing.\n * AI often forgets to add `await`, leading to unhandled promises\n * and subtle race-condition bugs.\n */\nexport const missingAwaitRule: Rule = {\n id: 'logic/missing-await',\n category: 'logic',\n severity: 'medium',\n title: 'Missing await on async call',\n description:\n 'AI-generated code often omits `await` when calling async functions, leading to unhandled promises and race conditions.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // Step 1: Collect names of async functions declared in this file\n const asyncFuncNames = new Set<string>();\n collectAsyncFunctionNames(ast, asyncFuncNames);\n\n // Step 2: Walk async functions and find un-awaited calls to known async functions\n walkAST(ast, (node) => {\n if (!isAsyncFunction(node)) return;\n\n const body = getFunctionBody(node);\n if (!body) return;\n\n walkAST(body, (inner, parent) => {\n // Skip nested async functions — they have their own scope\n if (inner !== body && isAsyncFunction(inner)) return false;\n\n // Look for call expressions that are NOT awaited\n if (inner.type !== AST_NODE_TYPES.CallExpression) return;\n\n // If the parent is an AwaitExpression, it's already awaited\n if (parent?.type === AST_NODE_TYPES.AwaitExpression) return;\n\n // If it's part of a return statement, it's okay (returning a promise)\n if (parent?.type === AST_NODE_TYPES.ReturnStatement) return;\n\n // If it's inside .then()/.catch(), skip\n if (isInsidePromiseChain(inner, parent ?? null)) return;\n\n // If assigned to a variable, skip (might be awaited later)\n if (parent?.type === AST_NODE_TYPES.VariableDeclarator) return;\n if (parent?.type === AST_NODE_TYPES.AssignmentExpression) return;\n\n // If passed as argument, skip (e.g., Promise.all([...]))\n if (parent?.type === AST_NODE_TYPES.ArrayExpression) return;\n if (parent?.type === AST_NODE_TYPES.CallExpression && parent !== inner) return;\n\n const callName = getCallName(inner);\n if (!callName) return;\n\n // Only report if we know the function is async\n if (!asyncFuncNames.has(callName)) return;\n\n issues.push({\n ruleId: 'logic/missing-await',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: inner.loc?.start.line ?? 0,\n endLine: inner.loc?.end.line ?? 0,\n message: t(\n `Call to async function \"${callName}\" is missing \"await\".`,\n `调用异步函数 \"${callName}\" 时缺少 \"await\"。`,\n ),\n suggestion: t(\n `Add \"await\" before the call: await ${callName}(...)`,\n `在调用前添加 \"await\":await ${callName}(...)`,\n ),\n });\n });\n });\n\n return issues;\n },\n};\n\nfunction collectAsyncFunctionNames(\n ast: TSESTree.Program,\n names: Set<string>,\n): void {\n walkAST(ast, (node) => {\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration &&\n node.async &&\n node.id\n ) {\n names.add(node.id.name);\n }\n\n // const foo = async () => { ... }\n // const foo = async function() { ... }\n if (\n node.type === AST_NODE_TYPES.VariableDeclarator &&\n node.id.type === AST_NODE_TYPES.Identifier &&\n node.init &&\n (node.init.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.init.type === AST_NODE_TYPES.FunctionExpression) &&\n node.init.async\n ) {\n names.add(node.id.name);\n }\n\n // Method definitions: async foo() { ... }\n if (\n node.type === AST_NODE_TYPES.MethodDefinition &&\n node.key.type === AST_NODE_TYPES.Identifier &&\n node.value.async\n ) {\n names.add(node.key.name);\n }\n });\n}\n\nfunction isAsyncFunction(node: TSESTree.Node): boolean {\n return (\n (node.type === AST_NODE_TYPES.FunctionDeclaration && node.async) ||\n (node.type === AST_NODE_TYPES.FunctionExpression && node.async) ||\n (node.type === AST_NODE_TYPES.ArrowFunctionExpression && node.async) ||\n (node.type === AST_NODE_TYPES.MethodDefinition && node.value.async)\n );\n}\n\nfunction getFunctionBody(node: TSESTree.Node): TSESTree.Node | null {\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return node.body;\n }\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n return node.value.body;\n }\n return null;\n}\n\nfunction getCallName(node: TSESTree.CallExpression): string | null {\n const callee = node.callee;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n // this.foo() or obj.foo()\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return callee.property.name;\n }\n return null;\n}\n\nfunction isInsidePromiseChain(\n _node: TSESTree.Node,\n parent: TSESTree.Node | null,\n): boolean {\n if (!parent) return false;\n if (\n parent.type === AST_NODE_TYPES.MemberExpression &&\n parent.property.type === AST_NODE_TYPES.Identifier &&\n (parent.property.name === 'then' ||\n parent.property.name === 'catch' ||\n parent.property.name === 'finally')\n ) {\n return true;\n }\n return false;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects excessive use of TypeScript `any` type.\n * AI-generated code tends to use `any` to bypass type checking,\n * which defeats the purpose of using TypeScript.\n */\nexport const anyTypeAbuseRule: Rule = {\n id: 'logic/any-type-abuse',\n category: 'logic',\n severity: 'medium',\n title: 'Excessive any type usage',\n description:\n 'AI-generated code often uses `any` type to bypass TypeScript type checking, reducing type safety.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n // Only check TypeScript files\n if (!context.filePath.match(/\\.tsx?$/)) return issues;\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const lines = context.fileContent.split('\\n');\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.TSAnyKeyword) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n // Skip if inside a comment\n const lineContent = lines[line - 1] ?? '';\n const trimmed = lineContent.trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) return;\n\n // Skip type assertion expressions like `as any` in catch clauses\n // e.g., catch (e) { (e as any).message } — sometimes necessary\n const parent = (node as TSESTree.Node & { parent?: TSESTree.Node }).parent;\n if (parent?.type === AST_NODE_TYPES.TSTypeAssertion || parent?.type === AST_NODE_TYPES.TSAsExpression) {\n // Check if it's in a catch clause — allow `as any` in catch\n let ancestor: TSESTree.Node | undefined = parent;\n while (ancestor) {\n if ((ancestor as TSESTree.Node).type === AST_NODE_TYPES.CatchClause) return;\n ancestor = (ancestor as TSESTree.Node & { parent?: TSESTree.Node }).parent;\n }\n }\n\n issues.push({\n ruleId: 'logic/any-type-abuse',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Usage of \"any\" type reduces type safety.`,\n `使用 \"any\" 类型降低了类型安全性。`,\n ),\n suggestion: t(\n `Replace \"any\" with a specific type or \"unknown\" for safer type narrowing.`,\n `将 \"any\" 替换为具体类型或使用 \"unknown\" 进行更安全的类型收窄。`,\n ),\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects loose equality operators (== and !=) that cause implicit type coercion.\n * AI-generated code frequently uses == instead of ===, which can lead to\n * subtle bugs due to JavaScript's type coercion rules.\n */\nexport const typeCoercionRule: Rule = {\n id: 'logic/type-coercion',\n category: 'logic',\n severity: 'medium',\n title: 'Loose equality with type coercion',\n description:\n 'AI-generated code often uses == instead of ===, leading to implicit type coercion bugs.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip single-line comments\n if (trimmed.startsWith('//')) continue;\n\n // Remove string literals and comments from the line before checking\n const cleaned = line\n .replace(/(['\"`])(?:(?!\\1|\\\\).|\\\\.)*\\1/g, '\"\"') // remove string contents\n .replace(/\\/\\/.*$/, ''); // remove inline comments\n\n // Match == or != but not === or !==\n const looseEqRegex = /[^!=<>]==[^=]|[^!]==[^=]|!=[^=]/g;\n let match;\n\n while ((match = looseEqRegex.exec(cleaned)) !== null) {\n // Double-check: extract the actual operator\n const pos = match.index;\n const snippet = cleaned.substring(Math.max(0, pos), pos + match[0].length);\n\n // Skip if it's actually === or !==\n if (snippet.includes('===') || snippet.includes('!==')) continue;\n\n const isNotEqual = snippet.includes('!=');\n const operator = isNotEqual ? '!=' : '==';\n const strict = isNotEqual ? '!==' : '===';\n\n // Allow == null / != null pattern (common intentional pattern)\n const afterOp = cleaned.substring(pos + match[0].length - 1).trim();\n if (afterOp.startsWith('null') || afterOp.startsWith('undefined')) continue;\n const beforeOp = cleaned.substring(0, pos + 1).trim();\n if (beforeOp.endsWith('null') || beforeOp.endsWith('undefined')) continue;\n\n issues.push({\n ruleId: 'logic/type-coercion',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Loose equality \"${operator}\" can cause implicit type coercion.`,\n `宽松等于 \"${operator}\" 会导致隐式类型转换。`,\n ),\n suggestion: t(\n `Use strict equality \"${strict}\" instead of \"${operator}\".`,\n `使用严格等于 \"${strict}\" 代替 \"${operator}\"。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects magic numbers — numeric literals used directly in logic\n * without being assigned to a named constant.\n * AI-generated code frequently hard-codes numbers like timeout values,\n * array indices, HTTP status codes, etc. without meaningful names.\n */\n\n// Numbers that are commonly used and generally acceptable\nconst ALLOWED_NUMBERS = new Set([\n -1, 0, 1, 2, 10, 100,\n]);\n\nexport const magicNumberRule: Rule = {\n id: 'logic/magic-number',\n category: 'logic',\n severity: 'low',\n title: 'Magic number',\n description:\n 'AI-generated code often uses unexplained numeric literals instead of named constants.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip comments\n if (trimmed.startsWith('//')) continue;\n\n // Skip const/let/var declarations with direct assignment (defining constants is fine)\n if (/^\\s*(export\\s+)?(const|let|var|readonly)\\s+[A-Z_][A-Z0-9_]*\\s*[=:]/.test(line)) continue;\n\n // Skip enum declarations\n if (/^\\s*(export\\s+)?enum\\s/.test(line)) continue;\n\n // Skip array index access [0], [1], etc.\n // Skip import statements\n if (trimmed.startsWith('import ')) continue;\n\n // Skip lines that are purely return statements with simple numbers\n if (/^\\s*return\\s+[0-9]+\\s*;?\\s*$/.test(line)) continue;\n\n // Remove string contents and comments\n const cleaned = line\n .replace(/(['\"`])(?:(?!\\1|\\\\).|\\\\.)*\\1/g, '\"\"')\n .replace(/\\/\\/.*$/, '');\n\n // Find numeric literals (integers and floats, but not in simple assignments to UPPER_CASE)\n const numRegex = /(?<![.\\w])(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)\\b/gi;\n let match;\n\n while ((match = numRegex.exec(cleaned)) !== null) {\n const value = parseFloat(match[1]);\n\n // Skip commonly acceptable numbers\n if (ALLOWED_NUMBERS.has(value)) continue;\n\n // Skip if it's NaN (parsing failed)\n if (isNaN(value)) continue;\n\n // Skip array index patterns like [3] or .slice(0, 5)\n const beforeChar = cleaned[match.index - 1] || '';\n if (beforeChar === '[') continue;\n\n // Skip if part of a type annotation (e.g., tuple types)\n if (beforeChar === '<' || beforeChar === ',') continue;\n\n issues.push({\n ruleId: 'logic/magic-number',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Magic number ${match[1]} should be extracted to a named constant.`,\n `魔术数字 ${match[1]} 应提取为命名常量。`,\n ),\n suggestion: t(\n `Define a descriptive constant, e.g., const MAX_RETRIES = ${match[1]};`,\n `定义一个描述性常量,例如 const MAX_RETRIES = ${match[1]};`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects nested ternary expressions.\n * AI-generated code frequently produces deeply nested ternary operators\n * that are very hard to read and maintain.\n */\nexport const nestedTernaryRule: Rule = {\n id: 'logic/no-nested-ternary',\n category: 'logic',\n severity: 'medium',\n title: 'Nested ternary expression',\n description:\n 'AI-generated code often produces nested ternary expressions that are hard to read.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // Track reported lines to avoid duplicate reports\n const reportedLines = new Set<number>();\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ConditionalExpression) return;\n\n // Check if any child (consequent or alternate) is also a ternary\n const conditional = node as TSESTree.ConditionalExpression;\n const hasNestedTernary =\n conditional.consequent.type === AST_NODE_TYPES.ConditionalExpression ||\n conditional.alternate.type === AST_NODE_TYPES.ConditionalExpression;\n\n if (!hasNestedTernary) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0 || reportedLines.has(line)) return;\n reportedLines.add(line);\n\n // Count nesting depth\n let depth = 1;\n let current: TSESTree.Node = node;\n while (current.type === AST_NODE_TYPES.ConditionalExpression) {\n const cond = current as TSESTree.ConditionalExpression;\n if (cond.consequent.type === AST_NODE_TYPES.ConditionalExpression) {\n depth++;\n current = cond.consequent;\n } else if (cond.alternate.type === AST_NODE_TYPES.ConditionalExpression) {\n depth++;\n current = cond.alternate;\n } else {\n break;\n }\n }\n\n const endLine = node.loc?.end.line ?? line;\n\n issues.push({\n ruleId: 'logic/no-nested-ternary',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine,\n message: t(\n `Nested ternary expression (depth: ${depth}) reduces readability.`,\n `嵌套三元表达式(深度: ${depth})降低了可读性。`,\n ),\n suggestion: t(\n `Refactor into if-else statements or use a lookup object/map.`,\n `重构为 if-else 语句或使用查找对象/映射。`,\n ),\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects string literals that appear multiple times in the same file.\n * AI-generated code often repeats the same string literal instead of\n * extracting it into a named constant.\n */\n\nconst MIN_STRING_LENGTH = 6;\nconst MIN_OCCURRENCES = 3;\n\nexport const duplicateStringRule: Rule = {\n id: 'logic/duplicate-string',\n category: 'logic',\n severity: 'low',\n title: 'Duplicate string literal',\n description:\n 'AI-generated code often repeats the same string literal instead of extracting it into a constant.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n // Collect all string literals with their locations\n const stringMap = new Map<string, number[]>();\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip comments and import lines\n if (trimmed.startsWith('//')) continue;\n if (trimmed.startsWith('import ')) continue;\n\n // Remove inline comments\n const cleaned = line.replace(/\\/\\/.*$/, '');\n\n // Match string literals (single and double quotes)\n const stringRegex = /(['\"])([^'\"\\\\](?:(?!\\1|\\\\).|\\\\.)*)\\1/g;\n let match;\n\n while ((match = stringRegex.exec(cleaned)) !== null) {\n const value = match[2];\n\n // Skip short strings\n if (value.length < MIN_STRING_LENGTH) continue;\n\n // Skip template-like strings with interpolation markers\n if (value.includes('${')) continue;\n\n // Skip URL-like strings and paths\n if (value.startsWith('http') || value.startsWith('/')) continue;\n\n // Skip common test strings\n if (value.startsWith('test') || value.startsWith('mock')) continue;\n\n if (!stringMap.has(value)) {\n stringMap.set(value, []);\n }\n stringMap.get(value)!.push(i + 1);\n }\n }\n\n // Report strings that appear too many times\n for (const [value, locations] of stringMap) {\n if (locations.length < MIN_OCCURRENCES) continue;\n\n // Report only on the first occurrence\n const firstLine = locations[0];\n const displayValue = value.length > 30 ? value.substring(0, 30) + '...' : value;\n\n issues.push({\n ruleId: 'logic/duplicate-string',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: firstLine,\n endLine: firstLine,\n message: t(\n `String \"${displayValue}\" is repeated ${locations.length} times.`,\n `字符串 \"${displayValue}\" 重复出现了 ${locations.length} 次。`,\n ),\n suggestion: t(\n `Extract to a named constant to improve maintainability.`,\n `提取为命名常量以提高可维护性。`,\n ),\n });\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects `debugger` statements left in code.\n * AI-generated code or debugging sessions may leave debugger statements\n * that should never reach production.\n */\nexport const noDebuggerRule: Rule = {\n id: 'security/no-debugger',\n category: 'security',\n severity: 'high',\n title: 'Debugger statement',\n description:\n 'Debugger statements should never be committed to production code.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip single-line comments\n if (trimmed.startsWith('//')) continue;\n\n // Remove string contents and inline comments\n const cleaned = line\n .replace(/(['\"`])(?:(?!\\1|\\\\).|\\\\.)*\\1/g, '\"\"')\n .replace(/\\/\\/.*$/, '');\n\n // Match standalone `debugger` keyword\n if (/\\bdebugger\\b/.test(cleaned)) {\n issues.push({\n ruleId: 'security/no-debugger',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Debugger statement found. Remove before committing.`,\n `发现 debugger 语句。提交前请移除。`,\n ),\n suggestion: t(\n `Remove the debugger statement.`,\n `移除 debugger 语句。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects non-null assertion operator (!) usage.\n * AI-generated code frequently uses the ! operator to silence TypeScript\n * null-check errors instead of properly handling nullable values.\n * This can lead to runtime crashes when the value is actually null/undefined.\n */\nexport const noNonNullAssertionRule: Rule = {\n id: 'logic/no-non-null-assertion',\n category: 'logic',\n severity: 'medium',\n title: 'Non-null assertion operator',\n description:\n 'AI-generated code often uses the ! operator to bypass TypeScript null checks, risking runtime crashes.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n // Only check TypeScript files\n if (!context.filePath.match(/\\.tsx?$/)) return issues;\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.TSNonNullExpression) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-non-null-assertion',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Non-null assertion (!) used — value could be null/undefined at runtime.`,\n `使用了非空断言 (!) — 值在运行时可能为 null/undefined。`,\n ),\n suggestion: t(\n `Use optional chaining (?.), nullish coalescing (??), or add a proper null check.`,\n `使用可选链 (?.)、空值合并 (??) 或添加适当的空值检查。`,\n ),\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects self-comparison expressions like `x === x` or `x !== x`.\n * AI-generated code sometimes produces self-comparisons that are always\n * true (===) or always false (!==). The only valid use case is NaN checking,\n * which should use Number.isNaN() instead.\n */\nexport const noSelfCompareRule: Rule = {\n id: 'logic/no-self-compare',\n category: 'logic',\n severity: 'medium',\n title: 'Self-comparison',\n description:\n 'Self-comparison (x === x) is always true (or always false for !==). Use Number.isNaN() for NaN checks.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.BinaryExpression) return;\n\n const binExpr = node as TSESTree.BinaryExpression;\n const op = binExpr.operator;\n\n // Only check equality/inequality operators\n if (!['===', '!==', '==', '!='].includes(op)) return;\n\n // Compare the source text of left and right operands\n const left = serializeNode(binExpr.left);\n const right = serializeNode(binExpr.right);\n\n if (left === null || right === null || left !== right) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-self-compare',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Self-comparison \"${left} ${op} ${right}\" is always ${op.includes('!') ? 'false' : 'true'}.`,\n `自比较 \"${left} ${op} ${right}\" 始终为 ${op.includes('!') ? 'false' : 'true'}。`,\n ),\n suggestion: t(\n `If checking for NaN, use Number.isNaN(${left}) instead.`,\n `如需检查 NaN,请使用 Number.isNaN(${left})。`,\n ),\n });\n });\n\n return issues;\n },\n};\n\n/**\n * Serialize a simple AST node to a string for comparison.\n * Returns null for complex expressions to avoid false positives.\n */\nfunction serializeNode(node: TSESTree.Node): string | null {\n if (node.type === AST_NODE_TYPES.Identifier) {\n return node.name;\n }\n if (node.type === AST_NODE_TYPES.MemberExpression && !node.computed) {\n const obj = serializeNode(node.object);\n const prop = (node.property as TSESTree.Identifier).name;\n if (obj && prop) return `${obj}.${prop}`;\n }\n return null;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects assignment expressions inside return statements.\n * AI-generated code sometimes confuses `=` with `===` in return statements,\n * e.g., `return x = 5` instead of `return x === 5`.\n */\nexport const noReturnAssignRule: Rule = {\n id: 'logic/no-return-assign',\n category: 'logic',\n severity: 'medium',\n title: 'Assignment in return statement',\n description:\n 'AI-generated code sometimes uses assignment (=) instead of comparison (===) in return statements.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ReturnStatement) return;\n\n const returnStmt = node as TSESTree.ReturnStatement;\n if (!returnStmt.argument) return;\n\n // Check if the return argument is an assignment expression\n if (returnStmt.argument.type === AST_NODE_TYPES.AssignmentExpression) {\n const assignExpr = returnStmt.argument as TSESTree.AssignmentExpression;\n // Only flag simple = assignments, not +=, -=, etc.\n if (assignExpr.operator !== '=') return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-return-assign',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Assignment in return statement — did you mean to use === instead of =?`,\n `return 语句中使用了赋值 — 是否应该使用 === 而非 =?`,\n ),\n suggestion: t(\n `If comparison was intended, use === instead of =. If assignment is intentional, extract it to a separate line.`,\n `如果意图是比较,请使用 === 代替 =。如果确实需要赋值,请提取到单独的行。`,\n ),\n });\n }\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects floating promises — async function calls whose return value\n * is neither awaited, returned, nor assigned.\n * AI-generated code frequently calls async functions without await,\n * leading to unhandled promise rejections and race conditions.\n *\n * This is different from missing-await which checks function-level patterns.\n * This rule catches standalone expression statements that are promise-producing calls.\n */\nexport const promiseVoidRule: Rule = {\n id: 'logic/promise-void',\n category: 'logic',\n severity: 'medium',\n title: 'Floating promise (not awaited or returned)',\n description:\n 'AI-generated code often calls async functions without await, causing unhandled rejections.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // First pass: collect all async function/method names defined in this file\n const asyncFnNames = new Set<string>();\n walkAST(ast, (node): void => {\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration &&\n (node as TSESTree.FunctionDeclaration).async &&\n (node as TSESTree.FunctionDeclaration).id\n ) {\n asyncFnNames.add((node as TSESTree.FunctionDeclaration).id!.name);\n }\n\n if (\n node.type === AST_NODE_TYPES.VariableDeclarator &&\n (node as TSESTree.VariableDeclarator).id.type === AST_NODE_TYPES.Identifier\n ) {\n const init = (node as TSESTree.VariableDeclarator).init;\n if (\n init &&\n (init.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n init.type === AST_NODE_TYPES.FunctionExpression) &&\n (init as TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression).async\n ) {\n asyncFnNames.add(\n ((node as TSESTree.VariableDeclarator).id as TSESTree.Identifier).name,\n );\n }\n }\n });\n\n // Also detect common async API names\n const commonAsyncPatterns = [\n /^fetch$/,\n /^save/,\n /^load/,\n /^send/,\n /^delete/,\n /^update/,\n /^create/,\n /^connect/,\n /^disconnect/,\n /^init/,\n ];\n\n // Second pass: find expression statements that call async functions\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ExpressionStatement) return;\n\n const expr = (node as TSESTree.ExpressionStatement).expression;\n if (expr.type !== AST_NODE_TYPES.CallExpression) return;\n\n const callExpr = expr as TSESTree.CallExpression;\n const fnName = getCallName(callExpr);\n if (!fnName) return;\n\n // Check if this is a known async function or matches async patterns\n const isKnownAsync = asyncFnNames.has(fnName);\n const matchesPattern = commonAsyncPatterns.some((p) => p.test(fnName));\n\n // Also check for .then() chains — these are definitely promises\n // Method calls ending in common promise-producing names\n const endsWithAsync = fnName.endsWith('Async') || fnName.endsWith('async');\n\n if (!isKnownAsync && !matchesPattern && !endsWithAsync) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n // Skip if inside a non-async function (might be intentional fire-and-forget)\n // We still report but the suggestion is gentler\n issues.push({\n ruleId: 'logic/promise-void',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: node.loc?.end.line ?? line,\n message: t(\n `Call to \"${fnName}()\" appears to be a floating promise (not awaited or returned).`,\n `调用 \"${fnName}()\" 疑似浮动 Promise(未 await 或 return)。`,\n ),\n suggestion: t(\n `Add \"await\" before the call, assign the result, or use \"void ${fnName}()\" to explicitly discard.`,\n `在调用前添加 \"await\",赋值给变量,或使用 \"void ${fnName}()\" 显式丢弃。`,\n ),\n });\n });\n\n return issues;\n },\n};\n\nfunction getCallName(callExpr: TSESTree.CallExpression): string | null {\n const callee = callExpr.callee;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return callee.property.name;\n }\n return null;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects reassignment of function parameters.\n * AI-generated code often reassigns parameters directly instead of\n * using local variables, which creates confusing side-effect patterns\n * and makes the original argument value unrecoverable.\n */\nexport const noReassignParamRule: Rule = {\n id: 'logic/no-reassign-param',\n category: 'logic',\n severity: 'low',\n title: 'Parameter reassignment',\n description:\n 'AI-generated code often reassigns function parameters, creating confusing side-effect patterns.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n // Find function-like nodes\n const isFn =\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.MethodDefinition;\n\n if (!isFn) return;\n\n // Get parameters\n let params: TSESTree.Parameter[] = [];\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n const method = node as TSESTree.MethodDefinition;\n if (method.value && 'params' in method.value) {\n params = (method.value as TSESTree.FunctionExpression).params;\n }\n } else {\n params = (node as TSESTree.FunctionDeclaration).params;\n }\n\n // Collect parameter names (only simple identifiers)\n const paramNames = new Set<string>();\n for (const param of params) {\n if (param.type === AST_NODE_TYPES.Identifier) {\n paramNames.add(param.name);\n }\n // Handle destructured params with defaults: (x = 5)\n if (param.type === AST_NODE_TYPES.AssignmentPattern) {\n const left = param.left;\n if (left.type === AST_NODE_TYPES.Identifier) {\n paramNames.add(left.name);\n }\n }\n }\n\n if (paramNames.size === 0) return;\n\n // Get function body\n let body: TSESTree.Node | null = null;\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n body = (node as TSESTree.MethodDefinition).value;\n } else {\n body = node;\n }\n if (!body || !('body' in body)) return;\n\n // Walk the function body to find assignments to parameters\n const fnBody = (body as { body: TSESTree.Node }).body;\n if (!fnBody) return;\n\n const reportedParams = new Set<string>();\n\n walkAST(fnBody as TSESTree.Node, (innerNode): void => {\n if (innerNode.type !== AST_NODE_TYPES.AssignmentExpression) return;\n\n const assignExpr = innerNode as TSESTree.AssignmentExpression;\n if (assignExpr.left.type !== AST_NODE_TYPES.Identifier) return;\n\n const name = assignExpr.left.name;\n if (!paramNames.has(name) || reportedParams.has(name)) return;\n\n reportedParams.add(name);\n const line = innerNode.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-reassign-param',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Parameter \"${name}\" is reassigned. This can cause confusion and lose the original value.`,\n `参数 \"${name}\" 被重新赋值。这可能造成混淆并丢失原始值。`,\n ),\n suggestion: t(\n `Use a local variable instead: const local${name.charAt(0).toUpperCase() + name.slice(1)} = ...`,\n `使用局部变量代替:const local${name.charAt(0).toUpperCase() + name.slice(1)} = ...`,\n ),\n });\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects async functions that never use `await` inside their body.\n * AI-generated code frequently marks functions as `async` without\n * actually needing asynchronous behavior, adding unnecessary Promise\n * wrapping overhead and confusion.\n */\nexport const noAsyncWithoutAwaitRule: Rule = {\n id: 'logic/no-async-without-await',\n category: 'logic',\n severity: 'low',\n title: 'Async function without await',\n description:\n 'AI-generated code often marks functions as async without using await, adding unnecessary Promise wrapping.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): boolean | void => {\n const isAsyncFn =\n (node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression) &&\n (node as TSESTree.FunctionDeclaration).async;\n\n if (!isAsyncFn) return;\n\n // Check if the function body contains any await expression\n const fnNode = node as TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression;\n const body = fnNode.body;\n if (!body) return;\n\n let hasAwait = false;\n\n walkAST(body as TSESTree.Node, (innerNode): boolean | void => {\n // Stop searching into nested async functions — their awaits don't count\n if (\n innerNode !== body &&\n (innerNode.type === AST_NODE_TYPES.FunctionDeclaration ||\n innerNode.type === AST_NODE_TYPES.FunctionExpression ||\n innerNode.type === AST_NODE_TYPES.ArrowFunctionExpression) &&\n (innerNode as TSESTree.FunctionDeclaration).async\n ) {\n return false; // skip children\n }\n\n if (innerNode.type === AST_NODE_TYPES.AwaitExpression) {\n hasAwait = true;\n return false; // stop searching\n }\n\n // Also check for `for await` loops\n if (\n innerNode.type === AST_NODE_TYPES.ForOfStatement &&\n (innerNode as TSESTree.ForOfStatement).await\n ) {\n hasAwait = true;\n return false;\n }\n\n return;\n });\n\n if (hasAwait) return false; // skip children of this function\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n // Get function name for better error message\n let fnName = '<anonymous>';\n if (fnNode.type === AST_NODE_TYPES.FunctionDeclaration && fnNode.id) {\n fnName = fnNode.id.name;\n }\n\n issues.push({\n ruleId: 'logic/no-async-without-await',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: node.loc?.end.line ?? line,\n message: t(\n `Async function \"${fnName}\" does not use await.`,\n `异步函数 \"${fnName}\" 内部没有使用 await。`,\n ),\n suggestion: t(\n `Remove the async keyword if this function doesn't need to be asynchronous.`,\n `如果此函数不需要异步行为,请移除 async 关键字。`,\n ),\n });\n\n return false; // skip children\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects constructors that only call super() with the same parameters,\n * or empty constructors in classes that extend another class.\n * AI-generated code frequently produces these unnecessary constructors.\n */\nexport const noUselessConstructorRule: Rule = {\n id: 'logic/no-useless-constructor',\n category: 'logic',\n severity: 'low',\n title: 'Useless constructor',\n description:\n 'AI-generated code often produces constructors that only call super() or are completely empty.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ClassDeclaration && node.type !== AST_NODE_TYPES.ClassExpression) return;\n\n const classNode = node as TSESTree.ClassDeclaration | TSESTree.ClassExpression;\n const hasSuper = classNode.superClass !== null && classNode.superClass !== undefined;\n\n // Find constructor\n const constructor = classNode.body.body.find(\n (member) =>\n member.type === AST_NODE_TYPES.MethodDefinition &&\n member.kind === 'constructor',\n ) as TSESTree.MethodDefinition | undefined;\n\n if (!constructor) return;\n\n const ctorValue = constructor.value as TSESTree.FunctionExpression;\n if (!ctorValue.body) return;\n\n const bodyStatements = ctorValue.body.body;\n\n // Case 1: Empty constructor\n if (bodyStatements.length === 0) {\n const line = constructor.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-useless-constructor',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: constructor.loc?.end.line ?? line,\n message: t(\n `Empty constructor is unnecessary.`,\n `空构造函数是不必要的。`,\n ),\n suggestion: t(\n `Remove the empty constructor — JavaScript provides a default one.`,\n `移除空构造函数 — JavaScript 会自动提供默认构造函数。`,\n ),\n });\n return;\n }\n\n // Case 2: Constructor with only super() call, passing same params\n if (hasSuper && bodyStatements.length === 1) {\n const stmt = bodyStatements[0];\n if (stmt.type !== AST_NODE_TYPES.ExpressionStatement) return;\n\n const expr = stmt.expression;\n if (expr.type !== AST_NODE_TYPES.CallExpression) return;\n if (expr.callee.type !== AST_NODE_TYPES.Super) return;\n\n // Check if super() args match constructor params\n const ctorParams = ctorValue.params;\n const superArgs = expr.arguments;\n\n if (ctorParams.length === superArgs.length) {\n let allMatch = true;\n for (let i = 0; i < ctorParams.length; i++) {\n const param = ctorParams[i];\n const arg = superArgs[i];\n\n // Simple identifier match\n if (\n param.type === AST_NODE_TYPES.Identifier &&\n arg.type === AST_NODE_TYPES.Identifier &&\n param.name === arg.name\n ) {\n continue;\n }\n\n // Handle TypeScript parameter properties (public x: number)\n if (\n param.type === AST_NODE_TYPES.TSParameterProperty &&\n (param as TSESTree.TSParameterProperty).parameter.type === AST_NODE_TYPES.Identifier\n ) {\n // Parameter properties DO something (create class fields), so this constructor is NOT useless\n allMatch = false;\n break;\n }\n\n allMatch = false;\n break;\n }\n\n if (allMatch) {\n const line = constructor.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-useless-constructor',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: constructor.loc?.end.line ?? line,\n message: t(\n `Constructor only calls super() with the same arguments — it is unnecessary.`,\n `构造函数仅调用 super() 并传递相同参数 — 这是不必要的。`,\n ),\n suggestion: t(\n `Remove the constructor — JavaScript automatically calls super() with the same arguments.`,\n `移除构造函数 — JavaScript 会自动用相同参数调用 super()。`,\n ),\n });\n }\n }\n }\n });\n\n return issues;\n },\n};\n","import { Issue } from '../types/index.js';\nimport { CodeTrustConfig } from '../types/config.js';\nimport { Rule, RuleContext } from './types.js';\nimport { unnecessaryTryCatchRule } from './builtin/unnecessary-try-catch.js';\nimport { overDefensiveRule } from './builtin/over-defensive.js';\nimport { deadLogicRule } from './builtin/dead-logic.js';\nimport { unusedVariablesRule } from './builtin/unused-variables.js';\nimport { duplicateConditionRule } from './builtin/duplicate-condition.js';\nimport { securityRules } from './builtin/security.js';\nimport { emptyCatchRule } from './builtin/empty-catch.js';\nimport { identicalBranchesRule } from './builtin/identical-branches.js';\nimport { redundantElseRule } from './builtin/redundant-else.js';\nimport { consoleInCodeRule } from './builtin/console-in-code.js';\nimport { phantomImportRule } from './builtin/phantom-import.js';\nimport { unusedImportRule } from './builtin/unused-import.js';\nimport { missingAwaitRule } from './builtin/missing-await.js';\nimport { anyTypeAbuseRule } from './builtin/any-type-abuse.js';\nimport { typeCoercionRule } from './builtin/type-coercion.js';\nimport { magicNumberRule } from './builtin/magic-number.js';\nimport { nestedTernaryRule } from './builtin/nested-ternary.js';\nimport { duplicateStringRule } from './builtin/duplicate-string.js';\nimport { noDebuggerRule } from './builtin/no-debugger.js';\nimport { noNonNullAssertionRule } from './builtin/no-non-null-assertion.js';\nimport { noSelfCompareRule } from './builtin/no-self-compare.js';\nimport { noReturnAssignRule } from './builtin/no-return-assign.js';\nimport { promiseVoidRule } from './builtin/promise-void.js';\nimport { noReassignParamRule } from './builtin/no-reassign-param.js';\nimport { noAsyncWithoutAwaitRule } from './builtin/no-async-without-await.js';\nimport { noUselessConstructorRule } from './builtin/no-useless-constructor.js';\n\nconst BUILTIN_RULES: Rule[] = [\n unnecessaryTryCatchRule,\n overDefensiveRule,\n deadLogicRule,\n unusedVariablesRule,\n duplicateConditionRule,\n ...securityRules,\n emptyCatchRule,\n identicalBranchesRule,\n redundantElseRule,\n consoleInCodeRule,\n phantomImportRule,\n unusedImportRule,\n missingAwaitRule,\n anyTypeAbuseRule,\n typeCoercionRule,\n magicNumberRule,\n nestedTernaryRule,\n duplicateStringRule,\n noDebuggerRule,\n noNonNullAssertionRule,\n noSelfCompareRule,\n noReturnAssignRule,\n promiseVoidRule,\n noReassignParamRule,\n noAsyncWithoutAwaitRule,\n noUselessConstructorRule,\n];\n\nexport class RuleEngine {\n private rules: Rule[];\n\n constructor(config: CodeTrustConfig) {\n this.rules = BUILTIN_RULES.filter(\n (rule) => !config.rules.disabled.includes(rule.id),\n );\n }\n\n run(context: RuleContext): Issue[] {\n const allIssues: Issue[] = [];\n\n for (const rule of this.rules) {\n try {\n const issues = rule.check(context);\n allIssues.push(...issues);\n } catch (_err) {\n // Rule execution failed — skip silently for now\n }\n }\n\n return allIssues;\n }\n\n getRules(): Rule[] {\n return [...this.rules];\n }\n\n listRules(): Array<{ id: string; category: string; severity: string; title: string }> {\n return BUILTIN_RULES.map((r) => ({\n id: r.id,\n category: r.category,\n severity: r.severity,\n title: r.title,\n }));\n }\n}\n","import { Issue, DimensionScore, TrustGrade, RuleCategory } from '../types/index.js';\nimport { DimensionWeights } from '../types/config.js';\nimport { isZhLocale } from '../i18n/index.js';\n\n// Info-level issues (e.g. console-in-code) have 0 penalty — they are\n// advisory only and do not affect the trust score.\nconst SEVERITY_PENALTY: Record<string, number> = {\n high: 15,\n medium: 8,\n low: 3,\n info: 0,\n};\n\nexport function calculateDimensionScore(issues: Issue[]): DimensionScore {\n let score = 100;\n\n for (const issue of issues) {\n score -= SEVERITY_PENALTY[issue.severity] ?? 0;\n }\n\n return {\n score: Math.max(0, Math.min(100, score)),\n issues,\n };\n}\n\nexport function calculateOverallScore(\n dimensions: Record<RuleCategory, DimensionScore>,\n weights: DimensionWeights,\n): number {\n const score =\n dimensions.security.score * weights.security +\n dimensions.logic.score * weights.logic +\n dimensions.structure.score * weights.structure +\n dimensions.style.score * weights.style +\n dimensions.coverage.score * weights.coverage;\n\n return Math.round(Math.max(0, Math.min(100, score)));\n}\n\nexport function getGrade(score: number): TrustGrade {\n if (score >= 90) return 'HIGH_TRUST';\n if (score >= 70) return 'REVIEW';\n if (score >= 50) return 'LOW_TRUST';\n return 'UNTRUSTED';\n}\n\nexport function getGradeEmoji(grade: TrustGrade): string {\n switch (grade) {\n case 'HIGH_TRUST':\n return '✅';\n case 'REVIEW':\n return '⚠️';\n case 'LOW_TRUST':\n return '⚠️';\n case 'UNTRUSTED':\n return '❌';\n }\n}\n\nexport function getGradeLabel(grade: TrustGrade): string {\n const isZh = isZhLocale();\n if (isZh) {\n switch (grade) {\n case 'HIGH_TRUST':\n return '高信任 — 可安全合并';\n case 'REVIEW':\n return '建议审查';\n case 'LOW_TRUST':\n return '低信任 — 需仔细审查';\n case 'UNTRUSTED':\n return '不可信 — 不应合并';\n }\n }\n switch (grade) {\n case 'HIGH_TRUST':\n return 'HIGH TRUST — Safe to merge';\n case 'REVIEW':\n return 'REVIEW RECOMMENDED';\n case 'LOW_TRUST':\n return 'LOW TRUST — Careful review needed';\n case 'UNTRUSTED':\n return 'UNTRUSTED — Do not merge without changes';\n }\n}\n","import { Issue } from '../types/index.js';\nimport { parseCode, extractFunctions, FunctionInfo } from '../parsers/ast.js';\nimport { t } from '../i18n/index.js';\n\nexport interface StructureThresholds {\n maxCyclomaticComplexity: number;\n maxCognitiveComplexity: number;\n maxFunctionLength: number;\n maxNestingDepth: number;\n maxParamCount: number;\n}\n\nconst DEFAULT_THRESHOLDS: StructureThresholds = {\n maxCyclomaticComplexity: 10,\n maxCognitiveComplexity: 20,\n maxFunctionLength: 40,\n maxNestingDepth: 4,\n maxParamCount: 5,\n};\n\nexport interface StructureAnalysisResult {\n functions: FunctionInfo[];\n issues: Issue[];\n}\n\nexport function analyzeStructure(\n code: string,\n filePath: string,\n thresholds: Partial<StructureThresholds> = {},\n): StructureAnalysisResult {\n const t_ = { ...DEFAULT_THRESHOLDS, ...thresholds };\n const issues: Issue[] = [];\n\n let parsed;\n try {\n parsed = parseCode(code, filePath);\n } catch {\n return { functions: [], issues: [] };\n }\n\n const functions = extractFunctions(parsed);\n\n for (const fn of functions) {\n if (fn.cyclomaticComplexity > t_.maxCyclomaticComplexity) {\n issues.push({\n ruleId: 'structure/high-cyclomatic-complexity',\n severity: fn.cyclomaticComplexity > t_.maxCyclomaticComplexity * 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has cyclomatic complexity of ${fn.cyclomaticComplexity} (threshold: ${t_.maxCyclomaticComplexity}).`,\n `函数 \"${fn.name}\" 的圈复杂度为 ${fn.cyclomaticComplexity}(阈值:${t_.maxCyclomaticComplexity})。`,\n ),\n suggestion: t(\n 'Break the function into smaller, simpler functions.',\n '将函数拆分为更小、更简单的函数。',\n ),\n });\n }\n\n if (fn.cognitiveComplexity > t_.maxCognitiveComplexity) {\n issues.push({\n ruleId: 'structure/high-cognitive-complexity',\n severity: fn.cognitiveComplexity > t_.maxCognitiveComplexity * 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has cognitive complexity of ${fn.cognitiveComplexity} (threshold: ${t_.maxCognitiveComplexity}).`,\n `函数 \"${fn.name}\" 的认知复杂度为 ${fn.cognitiveComplexity}(阈值:${t_.maxCognitiveComplexity})。`,\n ),\n suggestion: t(\n 'Simplify the function by reducing nesting and breaking out helper functions.',\n '通过减少嵌套和提取辅助函数来简化该函数。',\n ),\n });\n }\n\n if (fn.lineCount > t_.maxFunctionLength) {\n issues.push({\n ruleId: 'structure/long-function',\n severity: fn.lineCount > t_.maxFunctionLength * 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" is ${fn.lineCount} lines long (threshold: ${t_.maxFunctionLength}).`,\n `函数 \"${fn.name}\" 长达 ${fn.lineCount} 行(阈值:${t_.maxFunctionLength})。`,\n ),\n suggestion: t(\n 'Break the function into smaller units with clear responsibilities.',\n '将函数拆分为职责清晰的更小单元。',\n ),\n });\n }\n\n if (fn.maxNestingDepth > t_.maxNestingDepth) {\n issues.push({\n ruleId: 'structure/deep-nesting',\n severity: fn.maxNestingDepth > t_.maxNestingDepth + 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has nesting depth of ${fn.maxNestingDepth} (threshold: ${t_.maxNestingDepth}).`,\n `函数 \"${fn.name}\" 的嵌套深度为 ${fn.maxNestingDepth}(阈值:${t_.maxNestingDepth})。`,\n ),\n suggestion: t(\n 'Use early returns, guard clauses, or extract nested logic into separate functions.',\n '使用提前返回、守卫语句,或将嵌套逻辑提取到单独的函数中。',\n ),\n });\n }\n\n if (fn.paramCount > t_.maxParamCount) {\n issues.push({\n ruleId: 'structure/too-many-params',\n severity: 'low',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has ${fn.paramCount} parameters (threshold: ${t_.maxParamCount}).`,\n `函数 \"${fn.name}\" 有 ${fn.paramCount} 个参数(阈值:${t_.maxParamCount})。`,\n ),\n suggestion: t(\n 'Consider using an options object to group related parameters.',\n '考虑使用选项对象来组合相关参数。',\n ),\n });\n }\n }\n\n return { functions, issues };\n}\n","import { Issue } from '../types/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../parsers/ast.js';\nimport type { TSESTree } from '../parsers/ast.js';\nimport { walkAST } from '../parsers/walk.js';\nimport { t } from '../i18n/index.js';\n\nexport interface StyleAnalysisResult {\n issues: Issue[];\n stats: {\n camelCaseCount: number;\n snakeCaseCount: number;\n pascalCaseCount: number;\n totalIdentifiers: number;\n commentLineCount: number;\n codeLineCount: number;\n commentDensity: number;\n };\n}\n\nexport function analyzeStyle(code: string, filePath: string): StyleAnalysisResult {\n const issues: Issue[] = [];\n const lines = code.split('\\n');\n\n // 注释密度\n let commentLines = 0;\n let codeLines = 0;\n let inBlockComment = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n\n if (inBlockComment) {\n commentLines++;\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n\n if (trimmed.startsWith('/*')) {\n commentLines++;\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n if (trimmed.startsWith('//')) {\n commentLines++;\n continue;\n }\n\n codeLines++;\n }\n\n const commentDensity = codeLines > 0 ? commentLines / codeLines : 0;\n\n // 命名风格分析\n let camelCase = 0;\n let snakeCase = 0;\n let pascalCase = 0;\n let totalIdents = 0;\n\n try {\n const parsed = parseCode(code, filePath);\n collectNamingStyles(parsed.ast, (style) => {\n totalIdents++;\n if (style === 'camel') camelCase++;\n else if (style === 'snake') snakeCase++;\n else if (style === 'pascal') pascalCase++;\n });\n } catch {\n // AST parse failed, skip naming analysis\n }\n\n // 命名风格不一致检测\n const styles = [\n { name: 'camelCase', count: camelCase },\n { name: 'snake_case', count: snakeCase },\n ].filter((s) => s.count > 0);\n\n if (styles.length > 1 && totalIdents >= 5) {\n const dominant = styles.reduce((a, b) => (a.count > b.count ? a : b));\n const minority = styles.reduce((a, b) => (a.count < b.count ? a : b));\n const ratio = minority.count / totalIdents;\n\n if (ratio > 0.15) {\n issues.push({\n ruleId: 'style/inconsistent-naming',\n severity: 'low',\n category: 'style',\n file: filePath,\n startLine: 1,\n endLine: lines.length,\n message: t(\n `Mixed naming styles: ${dominant.count} ${dominant.name} vs ${minority.count} ${minority.name} identifiers.`,\n `命名风格混用:${dominant.count} 个 ${dominant.name} 与 ${minority.count} 个 ${minority.name} 标识符。`,\n ),\n suggestion: t(\n `Standardize on ${dominant.name} for consistency.`,\n `统一使用 ${dominant.name} 以保持一致性。`,\n ),\n });\n }\n }\n\n return {\n issues,\n stats: {\n camelCaseCount: camelCase,\n snakeCaseCount: snakeCase,\n pascalCaseCount: pascalCase,\n totalIdentifiers: totalIdents,\n commentLineCount: commentLines,\n codeLineCount: codeLines,\n commentDensity,\n },\n };\n}\n\ntype NamingStyle = 'camel' | 'snake' | 'pascal' | 'other';\n\nfunction detectNamingStyle(name: string): NamingStyle {\n if (name.length <= 1) return 'other';\n if (name.startsWith('_') || name === name.toUpperCase()) return 'other';\n if (name.includes('_')) return 'snake';\n if (/^[A-Z]/.test(name)) return 'pascal';\n if (/^[a-z]/.test(name)) return 'camel';\n return 'other';\n}\n\nfunction collectNamingStyles(\n root: TSESTree.Node,\n callback: (style: NamingStyle) => void,\n): void {\n walkAST(root, (node) => {\n if (node.type === AST_NODE_TYPES.VariableDeclarator && node.id.type === AST_NODE_TYPES.Identifier) {\n const style = detectNamingStyle(node.id.name);\n if (style !== 'other') callback(style);\n }\n\n if (node.type === AST_NODE_TYPES.FunctionDeclaration && node.id) {\n const style = detectNamingStyle(node.id.name);\n if (style !== 'other') callback(style);\n }\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Issue } from '../types/index.js';\nimport { parseCode, extractFunctions } from '../parsers/ast.js';\nimport { t } from '../i18n/index.js';\n\nexport interface CoverageAnalysisResult {\n issues: Issue[];\n exportedFunctions: string[];\n hasTestFile: boolean;\n}\n\nexport function analyzeCoverage(\n code: string,\n filePath: string,\n): CoverageAnalysisResult {\n const issues: Issue[] = [];\n const exportedFunctions: string[] = [];\n\n // 检查是否有对应的测试文件\n const testFile = findTestFile(filePath);\n const hasTestFile = testFile !== null;\n\n try {\n const parsed = parseCode(code, filePath);\n const functions = extractFunctions(parsed);\n\n // 收集 exported 函数名\n for (const fn of functions) {\n if (fn.name !== '<anonymous>' && fn.name !== '<arrow>') {\n exportedFunctions.push(fn.name);\n }\n }\n\n // 如果文件有超过 2 个导出函数且没有测试文件,报告\n if (exportedFunctions.length >= 2 && !hasTestFile) {\n // 跳过测试文件本身\n const basename = path.basename(filePath);\n if (!basename.includes('.test.') && !basename.includes('.spec.') && !basename.startsWith('test')) {\n issues.push({\n ruleId: 'coverage/missing-test-file',\n severity: 'low',\n category: 'coverage',\n file: filePath,\n startLine: 1,\n endLine: 1,\n message: t(\n `File has ${exportedFunctions.length} functions but no corresponding test file found.`,\n `文件有 ${exportedFunctions.length} 个函数,但未找到对应的测试文件。`,\n ),\n suggestion: t(\n `Create a test file (e.g., ${suggestTestFileName(filePath)}).`,\n `创建测试文件(如:${suggestTestFileName(filePath)})。`,\n ),\n });\n }\n }\n } catch {\n // AST parse failed\n }\n\n return { issues, exportedFunctions, hasTestFile };\n}\n\nfunction findTestFile(filePath: string): string | null {\n const dir = path.dirname(filePath);\n const ext = path.extname(filePath);\n const base = path.basename(filePath, ext);\n\n const candidates = [\n // 同目录\n path.join(dir, `${base}.test${ext}`),\n path.join(dir, `${base}.spec${ext}`),\n // tests/ 目录(复数)\n path.join(dir, '..', 'tests', `${base}.test${ext}`),\n path.join(dir, '..', 'tests', `${base}.spec${ext}`),\n path.join(dir, '..', '..', 'tests', `${base}.test${ext}`),\n path.join(dir, '..', '..', 'tests', `${base}.spec${ext}`),\n // test/ 目录(单数)\n path.join(dir, '..', 'test', `${base}.test${ext}`),\n path.join(dir, '..', 'test', `${base}.spec${ext}`),\n // __tests__/ 目录\n path.join(dir, '__tests__', `${base}.test${ext}`),\n path.join(dir, '__tests__', `${base}.spec${ext}`),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction suggestTestFileName(filePath: string): string {\n const ext = path.extname(filePath);\n const base = path.basename(filePath, ext);\n return `${base}.test${ext}`;\n}\n","import { cosmiconfig } from 'cosmiconfig';\nimport { CodeTrustConfig, DEFAULT_CONFIG } from '../types/config.js';\n\nconst MODULE_NAME = 'codetrust';\n\nexport async function loadConfig(searchFrom?: string): Promise<CodeTrustConfig> {\n const explorer = cosmiconfig(MODULE_NAME, {\n searchPlaces: [\n `.${MODULE_NAME}.yml`,\n `.${MODULE_NAME}.yaml`,\n `.${MODULE_NAME}.json`,\n `.${MODULE_NAME}rc`,\n `${MODULE_NAME}.config.js`,\n `${MODULE_NAME}.config.ts`,\n ],\n });\n\n const result = await explorer.search(searchFrom);\n\n if (!result || result.isEmpty) {\n return DEFAULT_CONFIG;\n }\n\n return mergeConfig(DEFAULT_CONFIG, result.config);\n}\n\nfunction mergeConfig(\n defaults: CodeTrustConfig,\n overrides: Partial<CodeTrustConfig>,\n): CodeTrustConfig {\n return {\n ...defaults,\n ...overrides,\n weights: { ...defaults.weights, ...overrides.weights },\n thresholds: { ...defaults.thresholds, ...overrides.thresholds },\n rules: {\n disabled: overrides.rules?.disabled ?? defaults.rules.disabled,\n overrides: { ...defaults.rules.overrides, ...overrides.rules?.overrides },\n },\n detection: { ...defaults.detection, ...overrides.detection },\n };\n}\n\nexport function generateDefaultConfig(): string {\n return `# .codetrust.yml\nversion: 1\n\n# Scan scope\ninclude:\n - \"src/**/*.ts\"\n - \"src/**/*.js\"\nexclude:\n - \"**/*.test.ts\"\n - \"**/*.spec.ts\"\n - \"**/node_modules/**\"\n - \"**/dist/**\"\n\n# Dimension weights (must sum to 1.0)\nweights:\n security: 0.30\n logic: 0.25\n structure: 0.20\n style: 0.10\n coverage: 0.15\n\n# Thresholds\nthresholds:\n min-score: 70\n max-function-length: 40\n max-cyclomatic-complexity: 10\n max-nesting-depth: 4\n max-params: 5\n\n# Rules\nrules:\n disabled: []\n overrides: {}\n\n# AI code detection\ndetection:\n enabled: true\n show-probability: true\n`;\n}\n","export interface CodeTrustConfig {\n version: number;\n include: string[];\n exclude: string[];\n weights: DimensionWeights;\n thresholds: Thresholds;\n rules: RulesConfig;\n detection: DetectionConfig;\n}\n\nexport interface DimensionWeights {\n security: number;\n logic: number;\n structure: number;\n style: number;\n coverage: number;\n}\n\nexport interface Thresholds {\n 'min-score': number;\n 'max-function-length': number;\n 'max-cyclomatic-complexity': number;\n 'max-cognitive-complexity': number;\n 'max-nesting-depth': number;\n 'max-params': number;\n}\n\nexport interface RulesConfig {\n disabled: string[];\n overrides: Record<string, string>;\n}\n\n// Reserved for Phase 3: AI-generated code probability detection\nexport interface DetectionConfig {\n enabled: boolean;\n 'show-probability': boolean;\n}\n\nexport const DEFAULT_CONFIG: CodeTrustConfig = {\n version: 1,\n include: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],\n exclude: [\n '**/*.test.ts',\n '**/*.spec.ts',\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n ],\n weights: {\n security: 0.30,\n logic: 0.25,\n structure: 0.20,\n style: 0.10,\n coverage: 0.15,\n },\n thresholds: {\n 'min-score': 70,\n 'max-function-length': 40,\n 'max-cyclomatic-complexity': 10,\n 'max-cognitive-complexity': 20,\n 'max-nesting-depth': 4,\n 'max-params': 5,\n },\n rules: {\n disabled: [],\n overrides: {},\n },\n detection: {\n enabled: true,\n 'show-probability': true,\n },\n};\n"],"mappings":"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","names":["existsSync","resolve","dirname","getCallName","basename","dirname","resolve","existsSync"]}
1
+ {"version":3,"sources":["../src/core/engine.ts","../src/parsers/diff.ts","../src/i18n/index.ts","../src/rules/builtin/unnecessary-try-catch.ts","../src/rules/builtin/over-defensive.ts","../src/rules/builtin/dead-logic.ts","../src/rules/fix-utils.ts","../src/parsers/ast.ts","../src/parsers/walk.ts","../src/rules/builtin/unused-variables.ts","../src/rules/builtin/duplicate-condition.ts","../src/rules/builtin/security.ts","../src/rules/builtin/empty-catch.ts","../src/rules/builtin/identical-branches.ts","../src/rules/builtin/redundant-else.ts","../src/rules/builtin/console-in-code.ts","../src/rules/builtin/phantom-import.ts","../src/rules/builtin/unused-import.ts","../src/rules/builtin/missing-await.ts","../src/rules/builtin/any-type-abuse.ts","../src/rules/builtin/type-coercion.ts","../src/rules/builtin/magic-number.ts","../src/rules/builtin/nested-ternary.ts","../src/rules/builtin/duplicate-string.ts","../src/rules/builtin/no-debugger.ts","../src/rules/builtin/no-non-null-assertion.ts","../src/rules/builtin/no-self-compare.ts","../src/rules/builtin/no-return-assign.ts","../src/rules/builtin/promise-void.ts","../src/rules/builtin/no-reassign-param.ts","../src/rules/builtin/no-async-without-await.ts","../src/rules/builtin/no-useless-constructor.ts","../src/rules/engine.ts","../src/core/scorer.ts","../src/analyzers/structure.ts","../src/analyzers/style.ts","../src/analyzers/coverage.ts","../src/core/config.ts","../src/types/config.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Issue, TrustReport, DimensionScore, RuleCategory, ScanOptions } from '../types/index.js';\nimport { CodeTrustConfig } from '../types/config.js';\nimport { DiffParser } from '../parsers/diff.js';\nimport { RuleEngine } from '../rules/engine.js';\nimport { calculateDimensionScore, calculateOverallScore, getGrade } from './scorer.js';\nimport { analyzeStructure } from '../analyzers/structure.js';\nimport { analyzeStyle } from '../analyzers/style.js';\nimport { analyzeCoverage } from '../analyzers/coverage.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst PKG_VERSION: string = (() => {\n try {\n const pkg = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf-8'));\n return pkg.version;\n } catch {\n return '0.1.0';\n }\n})();\n\nexport class ScanEngine {\n private config: CodeTrustConfig;\n private diffParser: DiffParser;\n private ruleEngine: RuleEngine;\n\n constructor(config: CodeTrustConfig, workDir?: string) {\n this.config = config;\n this.diffParser = new DiffParser(workDir);\n this.ruleEngine = new RuleEngine(config);\n }\n\n async scan(options: ScanOptions): Promise<TrustReport> {\n const diffFiles = await this.getDiffFiles(options);\n const allIssues: Issue[] = [];\n\n for (const diffFile of diffFiles) {\n if (diffFile.status === 'deleted') continue;\n\n const filePath = resolve(diffFile.filePath);\n let fileContent: string;\n\n try {\n if (existsSync(filePath)) {\n fileContent = await readFile(filePath, 'utf-8');\n } else {\n const content = await this.diffParser.getFileContent(diffFile.filePath);\n if (!content) continue;\n fileContent = content;\n }\n } catch {\n // Intentionally skip unreadable files\n continue;\n }\n\n const addedLines = diffFile.hunks.flatMap((hunk) => {\n const lines = hunk.content.split('\\n');\n const result: Array<{ lineNumber: number; content: string }> = [];\n let currentLine = hunk.newStart;\n\n for (const line of lines) {\n if (line.startsWith('+')) {\n result.push({ lineNumber: currentLine, content: line.slice(1) });\n currentLine++;\n } else if (line.startsWith('-')) {\n // deleted line, don't increment\n } else {\n currentLine++;\n }\n }\n\n return result;\n });\n\n const issues = this.ruleEngine.run({\n filePath: diffFile.filePath,\n fileContent,\n addedLines,\n });\n\n allIssues.push(...issues);\n\n // AST-based analyzers (structure, style, coverage)\n if (this.isTsJsFile(diffFile.filePath)) {\n const structureResult = analyzeStructure(fileContent, diffFile.filePath, {\n maxCyclomaticComplexity: this.config.thresholds['max-cyclomatic-complexity'],\n maxCognitiveComplexity: this.config.thresholds['max-cognitive-complexity'],\n maxFunctionLength: this.config.thresholds['max-function-length'],\n maxNestingDepth: this.config.thresholds['max-nesting-depth'],\n maxParamCount: this.config.thresholds['max-params'],\n });\n allIssues.push(...structureResult.issues);\n\n const styleResult = analyzeStyle(fileContent, diffFile.filePath);\n allIssues.push(...styleResult.issues);\n\n const coverageResult = analyzeCoverage(fileContent, diffFile.filePath);\n allIssues.push(...coverageResult.issues);\n }\n }\n\n const dimensions = this.groupByDimension(allIssues);\n const overallScore = calculateOverallScore(dimensions, this.config.weights);\n const grade = getGrade(overallScore);\n const commitHash = await this.diffParser.getCurrentCommitHash();\n\n return {\n version: PKG_VERSION,\n timestamp: new Date().toISOString(),\n commit: commitHash,\n overall: {\n score: overallScore,\n grade,\n filesScanned: diffFiles.filter((f) => f.status !== 'deleted').length,\n issuesFound: allIssues.length,\n },\n dimensions,\n issues: allIssues.sort((a, b) => {\n const severityOrder = { high: 0, medium: 1, low: 2, info: 3 };\n return severityOrder[a.severity] - severityOrder[b.severity];\n }),\n };\n }\n\n private async getDiffFiles(options: ScanOptions) {\n if (options.staged) {\n return this.diffParser.getStagedFiles();\n }\n\n if (options.diff) {\n return this.diffParser.getDiffFromRef(options.diff);\n }\n\n if (options.files && options.files.length > 0) {\n // For specific files, create synthetic diff entries\n return Promise.all(\n options.files.map(async (filePath) => {\n let content = '';\n try {\n content = await readFile(resolve(filePath), 'utf-8');\n } catch {\n // file not readable\n }\n return {\n filePath,\n status: 'modified' as const,\n additions: content.split('\\n').length,\n deletions: 0,\n content,\n hunks: [\n {\n oldStart: 1,\n oldLines: 0,\n newStart: 1,\n newLines: content.split('\\n').length,\n content: content\n .split('\\n')\n .map((l) => '+' + l)\n .join('\\n'),\n },\n ],\n };\n }),\n );\n }\n\n // Default: get all uncommitted changes\n return this.diffParser.getChangedFiles();\n }\n\n private isTsJsFile(filePath: string): boolean {\n return /\\.(ts|tsx|js|jsx|mts|mjs|cts|cjs)$/.test(filePath);\n }\n\n private groupByDimension(\n issues: Issue[],\n ): Record<RuleCategory, DimensionScore> {\n const categories: RuleCategory[] = [\n 'security',\n 'logic',\n 'structure',\n 'style',\n 'coverage',\n ];\n\n const grouped: Record<RuleCategory, DimensionScore> = {} as Record<\n RuleCategory,\n DimensionScore\n >;\n\n for (const cat of categories) {\n const catIssues = issues.filter((i) => i.category === cat);\n grouped[cat] = calculateDimensionScore(catIssues);\n }\n\n return grouped;\n }\n}\n","import simpleGit, { SimpleGit } from 'simple-git';\nimport { DiffFile, DiffHunk } from '../types/index.js';\n\nexport class DiffParser {\n private git: SimpleGit;\n\n constructor(workDir?: string) {\n this.git = simpleGit(workDir);\n }\n\n async getStagedFiles(): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff(['--cached', '--unified=3']);\n return this.parseDiffOutput(diffDetail);\n }\n\n async getDiffFromRef(ref: string): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff([ref, '--unified=3']);\n return this.parseDiffOutput(diffDetail);\n }\n\n async getChangedFiles(): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff(['--unified=3']);\n const stagedDetail = await this.git.diff(['--cached', '--unified=3']);\n const allDiff = diffDetail + '\\n' + stagedDetail;\n return this.parseDiffOutput(allDiff);\n }\n\n async getLastCommitDiff(): Promise<DiffFile[]> {\n const diffDetail = await this.git.diff(['HEAD~1', 'HEAD', '--unified=3']);\n return this.parseDiffOutput(diffDetail);\n }\n\n async getCurrentCommitHash(): Promise<string | undefined> {\n try {\n const hash = await this.git.revparse(['HEAD']);\n return hash.trim().slice(0, 7);\n } catch {\n return undefined;\n }\n }\n\n async getFileContent(filePath: string): Promise<string | undefined> {\n try {\n const content = await this.git.show([`HEAD:${filePath}`]);\n return content;\n } catch {\n return undefined;\n }\n }\n\n private parseDiffOutput(diffOutput: string): DiffFile[] {\n const files: DiffFile[] = [];\n const fileDiffs = diffOutput.split(/^diff --git /m).filter(Boolean);\n\n for (const fileDiff of fileDiffs) {\n const file = this.parseFileDiff(fileDiff);\n if (file) {\n files.push(file);\n }\n }\n\n return files;\n }\n\n private parseFileDiff(fileDiff: string): DiffFile | null {\n const lines = fileDiff.split('\\n');\n\n const headerMatch = lines[0]?.match(/a\\/(.+?) b\\/(.+)/);\n if (!headerMatch) return null;\n\n const filePath = headerMatch[2];\n let status: DiffFile['status'] = 'modified';\n let additions = 0;\n let deletions = 0;\n\n if (fileDiff.includes('new file mode')) {\n status = 'added';\n } else if (fileDiff.includes('deleted file mode')) {\n status = 'deleted';\n } else if (fileDiff.includes('rename from')) {\n status = 'renamed';\n }\n\n const hunks = this.parseHunks(fileDiff);\n\n for (const line of fileDiff.split('\\n')) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n additions++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n deletions++;\n }\n }\n\n return {\n filePath,\n status,\n additions,\n deletions,\n hunks,\n };\n }\n\n private parseHunks(fileDiff: string): DiffHunk[] {\n const hunks: DiffHunk[] = [];\n const hunkRegex = /^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@(.*)$/gm;\n let match: RegExpExecArray | null;\n\n const lines = fileDiff.split('\\n');\n\n while ((match = hunkRegex.exec(fileDiff)) !== null) {\n const oldStart = parseInt(match[1], 10);\n const oldLines = parseInt(match[2] || '1', 10);\n const newStart = parseInt(match[3], 10);\n const newLines = parseInt(match[4] || '1', 10);\n\n const hunkStartIndex = lines.findIndex((l) => l.includes(match![0]));\n const hunkContent: string[] = [];\n\n if (hunkStartIndex >= 0) {\n for (let i = hunkStartIndex + 1; i < lines.length; i++) {\n if (lines[i].startsWith('@@ ') || lines[i].startsWith('diff --git ')) {\n break;\n }\n hunkContent.push(lines[i]);\n }\n }\n\n hunks.push({\n oldStart,\n oldLines,\n newStart,\n newLines,\n content: hunkContent.join('\\n'),\n });\n }\n\n return hunks;\n }\n}\n","import { execSync } from 'node:child_process';\n\nlet _cachedLocale: boolean | null = null;\n\n/** @internal 仅用于测试 */\nexport function resetLocaleCache(): void {\n _cachedLocale = null;\n}\n\nexport function isZhLocale(): boolean {\n if (_cachedLocale !== null) return _cachedLocale;\n\n // 1. 用户显式设置 CODETRUST_LANG=zh 优先级最高\n if (process.env.CODETRUST_LANG?.startsWith('zh')) {\n _cachedLocale = true;\n return true;\n }\n if (process.env.CODETRUST_LANG && !process.env.CODETRUST_LANG.startsWith('zh')) {\n _cachedLocale = false;\n return false;\n }\n\n // 2. 标准环境变量\n const envVars = [\n process.env.LANG,\n process.env.LC_ALL,\n process.env.LC_MESSAGES,\n process.env.LANGUAGE,\n ];\n for (const v of envVars) {\n if (v?.startsWith('zh')) {\n _cachedLocale = true;\n return true;\n }\n }\n\n // 3. macOS: 读取 AppleLocale(LANG 可能是 C.UTF-8 但系统实际是中文)\n if (process.platform === 'darwin') {\n try {\n const appleLocale = execSync('defaults read -g AppleLocale 2>/dev/null', {\n encoding: 'utf-8',\n timeout: 1000,\n }).trim();\n if (appleLocale.startsWith('zh')) {\n _cachedLocale = true;\n return true;\n }\n } catch {\n // ignore\n }\n }\n\n _cachedLocale = false;\n return false;\n}\n\nexport function t(en: string, zh: string): string {\n return isZhLocale() ? zh : en;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects unnecessary try-catch blocks that wrap simple statements\n * with generic error handling — a common AI hallucination pattern.\n *\n * Pattern: try { single statement } catch (e) { console.log/error }\n */\nexport const unnecessaryTryCatchRule: Rule = {\n id: 'logic/unnecessary-try-catch',\n category: 'logic',\n severity: 'medium',\n title: 'Unnecessary try-catch wrapping simple statement',\n description:\n 'AI often wraps simple, non-throwing statements in try-catch blocks with generic console.log/error in the catch. This is hallucinated error handling.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n const trimmed = line.trim();\n\n if (trimmed.startsWith('try') && trimmed.includes('{')) {\n const tryBlock = extractBlock(lines, i);\n if (tryBlock) {\n const { bodyLines, catchBodyLines, endLine } = tryBlock;\n\n const nonEmptyBody = bodyLines.filter((l) => l.trim().length > 0);\n const nonEmptyCatch = catchBodyLines.filter((l) => l.trim().length > 0);\n\n const isSimpleBody = nonEmptyBody.length <= 2;\n const isGenericCatch =\n nonEmptyCatch.length <= 2 &&\n nonEmptyCatch.some(\n (l) =>\n /console\\.(log|error|warn)/.test(l) ||\n /throw\\s+(new\\s+)?Error/.test(l) ||\n l.trim() === '',\n );\n\n const bodyHasOnlyAssignments = nonEmptyBody.every(\n (l) =>\n /^\\s*(const|let|var)\\s+/.test(l) ||\n /^\\s*\\w+(\\.\\w+)*\\s*=\\s*/.test(l) ||\n /^\\s*return\\s+/.test(l),\n );\n\n if (isSimpleBody && isGenericCatch && bodyHasOnlyAssignments) {\n issues.push({\n ruleId: 'logic/unnecessary-try-catch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: endLine + 1,\n message: t(\n 'Unnecessary try-catch wrapping a simple statement with generic error handling. This is likely AI-hallucinated error handling.',\n '不必要的 try-catch 包裹了简单语句,catch 中只有通用的错误日志。这很可能是 AI 幻觉生成的错误处理。',\n ),\n suggestion: t(\n 'Remove the try-catch block or add meaningful error recovery logic.',\n '移除 try-catch 块,或添加有意义的错误恢复逻辑。',\n ),\n });\n }\n\n i = endLine + 1;\n continue;\n }\n }\n\n i++;\n }\n\n return issues;\n },\n};\n\ninterface TryCatchBlock {\n bodyLines: string[];\n catchStart: number;\n catchBodyLines: string[];\n endLine: number;\n}\n\nfunction extractBlock(lines: string[], tryLineIndex: number): TryCatchBlock | null {\n let braceCount = 0;\n let foundTryOpen = false;\n let tryBodyStart = -1;\n let tryBodyEnd = -1;\n let catchStart = -1;\n let catchBodyStart = -1;\n let catchBodyEnd = -1;\n\n for (let i = tryLineIndex; i < lines.length; i++) {\n const line = lines[i];\n for (const ch of line) {\n if (ch === '{') {\n braceCount++;\n if (!foundTryOpen) {\n foundTryOpen = true;\n tryBodyStart = i;\n }\n } else if (ch === '}') {\n braceCount--;\n if (braceCount === 0 && tryBodyEnd === -1) {\n tryBodyEnd = i;\n } else if (braceCount === 0 && catchBodyEnd === -1 && catchBodyStart !== -1) {\n catchBodyEnd = i;\n break;\n }\n }\n }\n\n if (tryBodyEnd !== -1 && catchStart === -1) {\n if (line.includes('catch')) {\n catchStart = i;\n }\n }\n\n if (catchStart !== -1 && catchBodyStart === -1 && line.includes('{')) {\n catchBodyStart = i;\n }\n\n if (catchBodyEnd !== -1) break;\n }\n\n if (tryBodyStart === -1 || tryBodyEnd === -1 || catchBodyStart === -1 || catchBodyEnd === -1) {\n return null;\n }\n\n const bodyLines = lines.slice(tryBodyStart + 1, tryBodyEnd);\n const catchBodyLines = lines.slice(catchBodyStart + 1, catchBodyEnd);\n\n return {\n bodyLines,\n catchStart,\n catchBodyLines,\n endLine: catchBodyEnd,\n };\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects over-defensive coding patterns typical of AI-generated code.\n *\n * Pattern: 3+ consecutive null/undefined/empty-string checks at function start,\n * or excessive type guards that the type system already guarantees.\n */\nexport const overDefensiveRule: Rule = {\n id: 'logic/over-defensive',\n category: 'logic',\n severity: 'low',\n title: 'Over-defensive coding pattern',\n description:\n 'AI-generated code often includes excessive null/undefined checks, redundant type guards, and unnecessary validations that the type system already handles.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n let consecutiveChecks = 0;\n let checkStartLine = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n if (isDefensiveCheck(trimmed)) {\n if (consecutiveChecks === 0) {\n checkStartLine = i;\n }\n consecutiveChecks++;\n } else if (trimmed.length > 0) {\n if (consecutiveChecks >= 3) {\n issues.push({\n ruleId: 'logic/over-defensive',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: checkStartLine + 1,\n endLine: i,\n message: t(\n `${consecutiveChecks} consecutive defensive checks detected. AI tends to add excessive null/undefined guards.`,\n `检测到 ${consecutiveChecks} 个连续的防御性检查。AI 倾向于添加过多的 null/undefined 守卫。`,\n ),\n suggestion: t(\n 'Consider if these checks are necessary — TypeScript types may already prevent these cases. Remove redundant guards.',\n '考虑这些检查是否必要 — TypeScript 类型可能已经防止了这些情况。移除冗余的守卫。',\n ),\n });\n }\n consecutiveChecks = 0;\n }\n }\n\n if (consecutiveChecks >= 3) {\n issues.push({\n ruleId: 'logic/over-defensive',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: checkStartLine + 1,\n endLine: lines.length,\n message: t(\n `${consecutiveChecks} consecutive defensive checks detected at end of block.`,\n `在代码块末尾检测到 ${consecutiveChecks} 个连续的防御性检查。`,\n ),\n suggestion: t(\n 'Review if these defensive checks are truly necessary.',\n '检查这些防御性检查是否真正必要。',\n ),\n });\n }\n\n detectRedundantTypeofChecks(context, lines, issues);\n\n return issues;\n },\n};\n\nfunction isDefensiveCheck(line: string): boolean {\n const patterns = [\n /^if\\s*\\(\\s*!?\\w+(\\.\\w+)*\\s*(===?|!==?)\\s*(null|undefined|''|\"\")\\s*\\)/,\n /^if\\s*\\(\\s*!?\\w+(\\.\\w+)*\\s*\\)\\s*\\{?\\s*(return|throw)/,\n /^if\\s*\\(\\s*typeof\\s+\\w+\\s*(===?|!==?)\\s*['\"]undefined['\"]\\s*\\)/,\n /^if\\s*\\(\\s*\\w+(\\.\\w+)*\\s*==\\s*null\\s*\\)/,\n /^if\\s*\\(\\s*!\\w+(\\.\\w+)*\\s*\\)\\s*\\{?\\s*$/,\n /^\\w+(\\.\\w+)*\\s*\\?\\?=/,\n /^if\\s*\\(\\s*Array\\.isArray\\(\\w+\\)\\s*&&\\s*\\w+\\.length\\s*(>|>=|===?)\\s*0\\s*\\)/,\n ];\n\n return patterns.some((p) => p.test(line));\n}\n\nfunction detectRedundantTypeofChecks(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n const typeofMatch = trimmed.match(\n /if\\s*\\(\\s*typeof\\s+(\\w+)\\s*(!==?|===?)\\s*['\"]undefined['\"]\\s*\\)/,\n );\n if (typeofMatch) {\n const varName = typeofMatch[1];\n const prevLines = lines.slice(Math.max(0, i - 5), i);\n const hasDeclaration = prevLines.some((l) =>\n new RegExp(`(const|let|var)\\\\s+${varName}\\\\s*[:=]`).test(l),\n );\n\n if (hasDeclaration) {\n issues.push({\n ruleId: 'logic/over-defensive',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Redundant typeof check for \"${varName}\" — variable is declared within ${prevLines.length} line(s) above and cannot be undefined.`,\n `对 \"${varName}\" 的 typeof 检查是冗余的 — 变量已在上方 ${prevLines.length} 行内声明,不可能为 undefined。`,\n ),\n suggestion: t(\n `Remove the typeof check for \"${varName}\".`,\n `移除对 \"${varName}\" 的 typeof 检查。`,\n ),\n });\n }\n }\n }\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects dead logic patterns — code that can never execute or\n * conditions that are always true/false.\n */\nexport const deadLogicRule: Rule = {\n id: 'logic/dead-branch',\n category: 'logic',\n severity: 'medium',\n title: 'Dead logic branch detected',\n description:\n 'AI-generated code sometimes contains conditions that are always true or false, unreachable code after return/throw, or assign-then-immediately-reassign patterns.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n detectAlwaysTrueFalse(context, lines, issues);\n detectCodeAfterReturn(context, lines, issues);\n detectImmediateReassign(context, lines, issues);\n\n return issues;\n },\n};\n\nfunction detectAlwaysTrueFalse(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n const alwaysTruePatterns = [\n /if\\s*\\(\\s*true\\s*\\)/,\n /if\\s*\\(\\s*1\\s*\\)/,\n /if\\s*\\(\\s*['\"].+['\"]\\s*\\)/,\n ];\n\n const alwaysFalsePatterns = [\n /if\\s*\\(\\s*false\\s*\\)/,\n /if\\s*\\(\\s*0\\s*\\)/,\n /if\\s*\\(\\s*null\\s*\\)/,\n /if\\s*\\(\\s*undefined\\s*\\)/,\n /if\\s*\\(\\s*''\\s*\\)/,\n /if\\s*\\(\\s*\"\"\\s*\\)/,\n ];\n\n for (const pattern of alwaysTruePatterns) {\n if (pattern.test(trimmed)) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Condition is always true — this branch always executes.',\n '条件始终为 true — 此分支始终会执行。',\n ),\n suggestion: t(\n 'Remove the condition and keep only the body, or fix the logic.',\n '移除条件判断只保留主体,或修复逻辑。',\n ),\n });\n }\n }\n\n for (const pattern of alwaysFalsePatterns) {\n if (pattern.test(trimmed)) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Condition is always false — this branch never executes.',\n '条件始终为 false — 此分支永远不会执行。',\n ),\n suggestion: t(\n 'Remove the dead branch entirely.',\n '完全移除该死代码分支。',\n ),\n });\n }\n }\n }\n}\n\nfunction detectCodeAfterReturn(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n let braceDepth = 0;\n let lastReturnDepth = -1;\n let lastReturnLine = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n for (const ch of trimmed) {\n if (ch === '{') braceDepth++;\n if (ch === '}') {\n if (braceDepth === lastReturnDepth) {\n lastReturnDepth = -1;\n lastReturnLine = -1;\n }\n braceDepth--;\n }\n }\n\n if (/^(return|throw)\\b/.test(trimmed) && !trimmed.includes('=>')) {\n // 如果 return/throw 行以开括号结尾(多行返回值),跳过\n const endsOpen = /[{(\\[,]$/.test(trimmed) || /^(return|throw)\\s*$/.test(trimmed);\n if (endsOpen) continue;\n lastReturnDepth = braceDepth;\n lastReturnLine = i;\n } else if (\n lastReturnLine !== -1 &&\n braceDepth === lastReturnDepth &&\n trimmed.length > 0 &&\n trimmed !== '}' &&\n trimmed !== '};' &&\n !trimmed.startsWith('//') &&\n !trimmed.startsWith('case ') &&\n !trimmed.startsWith('default:') &&\n !trimmed.startsWith('default :')\n ) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Unreachable code after return/throw at line ${lastReturnLine + 1}.`,\n `第 ${lastReturnLine + 1} 行的 return/throw 之后存在不可达代码。`,\n ),\n suggestion: t(\n 'Remove unreachable code or restructure the logic.',\n '移除不可达代码或重构逻辑。',\n ),\n });\n lastReturnDepth = -1;\n lastReturnLine = -1;\n }\n }\n}\n\nfunction detectImmediateReassign(\n context: RuleContext,\n lines: string[],\n issues: Issue[],\n): void {\n for (let i = 0; i < lines.length - 1; i++) {\n const current = lines[i].trim();\n const next = lines[i + 1].trim();\n\n const assignMatch = current.match(/^(let|var)\\s+(\\w+)\\s*=\\s*.+;?\\s*$/);\n if (assignMatch) {\n const varName = assignMatch[2];\n const reassignPattern = new RegExp(`^${varName}\\\\s*=\\\\s*.+;?\\\\s*$`);\n if (reassignPattern.test(next)) {\n issues.push({\n ruleId: 'logic/dead-branch',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 2,\n message: t(\n `Variable \"${varName}\" is assigned and immediately reassigned on the next line.`,\n `变量 \"${varName}\" 赋值后立即在下一行被重新赋值。`,\n ),\n suggestion: t(\n `Remove the first assignment or combine into a single declaration.`,\n `移除第一次赋值,或合并为一次声明。`,\n ),\n });\n }\n }\n }\n}\n","/**\n * Utility functions for rule fix implementations.\n */\n\n/**\n * Get the byte offset of a specific line start (1-indexed).\n */\nexport function lineStartOffset(content: string, lineNumber: number): number {\n let offset = 0;\n const lines = content.split('\\n');\n for (let i = 0; i < lineNumber - 1 && i < lines.length; i++) {\n offset += lines[i].length + 1; // +1 for \\n\n }\n return offset;\n}\n\n/**\n * Get the byte offset range for an entire line (1-indexed),\n * including the trailing newline if present.\n */\nexport function lineRange(content: string, lineNumber: number): [number, number] {\n const lines = content.split('\\n');\n const lineIndex = lineNumber - 1;\n if (lineIndex < 0 || lineIndex >= lines.length) return [0, 0];\n\n const start = lineStartOffset(content, lineNumber);\n const end = start + lines[lineIndex].length + (lineIndex < lines.length - 1 ? 1 : 0);\n return [start, end];\n}\n","import { parse, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';\nimport type { TSESTree } from '@typescript-eslint/typescript-estree';\nimport { walkAST } from './walk.js';\n\nexport interface ParsedAST {\n ast: TSESTree.Program;\n filePath: string;\n}\n\nconst _astCache = new Map<string, ParsedAST>();\n\nexport function parseCode(code: string, filePath: string): ParsedAST {\n const cacheKey = `${filePath}:${code.length}:${simpleHash(code)}`;\n const cached = _astCache.get(cacheKey);\n if (cached) return cached;\n\n const ast = parse(code, {\n loc: true,\n range: true,\n comment: true,\n jsx: filePath.endsWith('.tsx') || filePath.endsWith('.jsx'),\n filePath,\n });\n\n const result = { ast, filePath };\n _astCache.set(cacheKey, result);\n\n // 限制缓存大小\n if (_astCache.size > 50) {\n const firstKey = _astCache.keys().next().value;\n if (firstKey) _astCache.delete(firstKey);\n }\n\n return result;\n}\n\nfunction simpleHash(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0;\n }\n return hash;\n}\n\nexport interface FunctionInfo {\n name: string;\n startLine: number;\n endLine: number;\n lineCount: number;\n paramCount: number;\n cyclomaticComplexity: number;\n cognitiveComplexity: number;\n maxNestingDepth: number;\n}\n\nexport function extractFunctions(parsed: ParsedAST): FunctionInfo[] {\n const functions: FunctionInfo[] = [];\n visitNode(parsed.ast, functions);\n return functions;\n}\n\nfunction visitNode(root: TSESTree.Node, functions: FunctionInfo[]): void {\n const methodBodies = new WeakSet<TSESTree.Node>();\n\n walkAST(root, (node) => {\n // 跳过 MethodDefinition 内部的 FunctionExpression(避免双重计数)\n if (node.type === AST_NODE_TYPES.FunctionExpression && methodBodies.has(node)) {\n return false;\n }\n\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.MethodDefinition\n ) {\n const info = analyzeFunctionNode(node);\n if (info) functions.push(info);\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n methodBodies.add(node.value);\n }\n }\n return;\n });\n}\n\nfunction analyzeFunctionNode(node: TSESTree.Node): FunctionInfo | null {\n let name = '<anonymous>';\n let params: TSESTree.Parameter[] = [];\n let body: TSESTree.Node | null = null;\n\n if (node.type === AST_NODE_TYPES.FunctionDeclaration) {\n name = node.id?.name ?? '<anonymous>';\n params = node.params;\n body = node.body;\n } else if (node.type === AST_NODE_TYPES.FunctionExpression) {\n name = node.id?.name ?? '<anonymous>';\n params = node.params;\n body = node.body;\n } else if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n name = '<arrow>';\n params = node.params;\n body = node.body;\n } else if (node.type === AST_NODE_TYPES.MethodDefinition) {\n if (node.key.type === AST_NODE_TYPES.Identifier) {\n name = node.key.name;\n }\n const value = node.value;\n params = value.params;\n body = value.body;\n }\n\n if (!body || !node.loc) return null;\n\n const startLine = node.loc.start.line;\n const endLine = node.loc.end.line;\n\n return {\n name,\n startLine,\n endLine,\n lineCount: endLine - startLine + 1,\n paramCount: params.length,\n cyclomaticComplexity: body ? calculateCyclomaticComplexity(body) : 1,\n cognitiveComplexity: body ? calculateCognitiveComplexity(body) : 0,\n maxNestingDepth: body ? calculateMaxNestingDepth(body) : 0,\n };\n}\n\n// 圈复杂度:每个分支点 +1\nfunction calculateCyclomaticComplexity(root: TSESTree.Node): number {\n let complexity = 1;\n\n walkAST(root, (n) => {\n switch (n.type) {\n case AST_NODE_TYPES.IfStatement:\n case AST_NODE_TYPES.ConditionalExpression:\n case AST_NODE_TYPES.ForStatement:\n case AST_NODE_TYPES.ForInStatement:\n case AST_NODE_TYPES.ForOfStatement:\n case AST_NODE_TYPES.WhileStatement:\n case AST_NODE_TYPES.DoWhileStatement:\n case AST_NODE_TYPES.CatchClause:\n complexity++;\n break;\n case AST_NODE_TYPES.SwitchCase:\n if (n.test) complexity++;\n break;\n case AST_NODE_TYPES.LogicalExpression:\n if (n.operator === '&&' || n.operator === '||' || n.operator === '??') {\n complexity++;\n }\n break;\n }\n });\n\n return complexity;\n}\n\n// 认知复杂度:嵌套越深越难理解\nfunction calculateCognitiveComplexity(root: TSESTree.Node): number {\n let complexity = 0;\n const depthMap = new WeakMap<TSESTree.Node, number>();\n depthMap.set(root, 0);\n\n walkAST(root, (n, parent) => {\n const parentDepth = parent ? (depthMap.get(parent) ?? 0) : 0;\n const isNesting = isNestingNode(n);\n const depth = isNesting ? parentDepth + 1 : parentDepth;\n depthMap.set(n, depth);\n\n if (isNesting) {\n complexity += 1 + parentDepth;\n }\n\n if (\n n.type === AST_NODE_TYPES.LogicalExpression &&\n (n.operator === '&&' || n.operator === '||' || n.operator === '??')\n ) {\n complexity += 1;\n }\n });\n\n return complexity;\n}\n\n// 最大嵌套深度\nfunction calculateMaxNestingDepth(root: TSESTree.Node): number {\n let maxDepth = 0;\n const depthMap = new WeakMap<TSESTree.Node, number>();\n depthMap.set(root, 0);\n\n walkAST(root, (n, parent) => {\n const parentDepth = parent ? (depthMap.get(parent) ?? 0) : 0;\n const isNesting =\n n.type === AST_NODE_TYPES.IfStatement ||\n n.type === AST_NODE_TYPES.ForStatement ||\n n.type === AST_NODE_TYPES.ForInStatement ||\n n.type === AST_NODE_TYPES.ForOfStatement ||\n n.type === AST_NODE_TYPES.WhileStatement ||\n n.type === AST_NODE_TYPES.DoWhileStatement ||\n n.type === AST_NODE_TYPES.SwitchStatement ||\n n.type === AST_NODE_TYPES.TryStatement;\n\n const currentDepth = isNesting ? parentDepth + 1 : parentDepth;\n depthMap.set(n, currentDepth);\n if (currentDepth > maxDepth) maxDepth = currentDepth;\n });\n\n return maxDepth;\n}\n\nfunction isNestingNode(n: TSESTree.Node): boolean {\n return (\n n.type === AST_NODE_TYPES.IfStatement ||\n n.type === AST_NODE_TYPES.ForStatement ||\n n.type === AST_NODE_TYPES.ForInStatement ||\n n.type === AST_NODE_TYPES.ForOfStatement ||\n n.type === AST_NODE_TYPES.WhileStatement ||\n n.type === AST_NODE_TYPES.DoWhileStatement ||\n n.type === AST_NODE_TYPES.SwitchStatement ||\n n.type === AST_NODE_TYPES.CatchClause ||\n n.type === AST_NODE_TYPES.ConditionalExpression\n );\n}\n\nexport { AST_NODE_TYPES };\nexport type { TSESTree };\n","import type { TSESTree } from '@typescript-eslint/typescript-estree';\n\n/**\n * Generic AST walker — eliminates the repeated Object.keys + cast pattern\n * used across multiple files.\n *\n * @param node The root AST node to walk\n * @param visitor Called for every node; return `false` to skip children\n */\nexport type ASTVisitor = (node: TSESTree.Node, parent: TSESTree.Node | null) => boolean | void;\n\nexport function walkAST(\n node: TSESTree.Node,\n visitor: ASTVisitor,\n parent: TSESTree.Node | null = null,\n): void {\n const result = visitor(node, parent);\n if (result === false) return; // skip children\n\n for (const key of Object.keys(node)) {\n if (key === 'parent') continue;\n const child = (node as unknown as Record<string, unknown>)[key];\n if (child && typeof child === 'object') {\n if (Array.isArray(child)) {\n for (const item of child) {\n if (isASTNode(item)) {\n walkAST(item, visitor, node);\n }\n }\n } else if (isASTNode(child)) {\n walkAST(child as TSESTree.Node, visitor, node);\n }\n }\n }\n}\n\n\nfunction isASTNode(value: unknown): value is TSESTree.Node {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'type' in (value as Record<string, unknown>)\n );\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext, Fix } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { lineRange } from '../fix-utils.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects variables that are declared but never used.\n * AI-generated code often introduces variables that are assigned\n * but never referenced elsewhere.\n */\nexport const unusedVariablesRule: Rule = {\n id: 'logic/unused-variables',\n category: 'logic',\n severity: 'low',\n title: 'Unused variable detected',\n description:\n 'AI-generated code sometimes declares variables that are never used, indicating incomplete or hallucinated logic.',\n\n fixable: true,\n\n fix(context: RuleContext, issue: Issue): Fix | null {\n // Only fix simple single-variable declarations on one line\n const lines = context.fileContent.split('\\n');\n const lineIndex = issue.startLine - 1;\n if (lineIndex < 0 || lineIndex >= lines.length) return null;\n\n const line = lines[lineIndex].trim();\n // Match: const/let/var varName = ...; (single declaration)\n if (/^(const|let|var)\\s+\\w+\\s*[=:;]/.test(line) && !line.includes(',')) {\n const [start, end] = lineRange(context.fileContent, issue.startLine);\n if (start === end) return null;\n return { range: [start, end], text: '' };\n }\n\n return null;\n },\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const declarations = new Map<string, { line: number; kind: string }>();\n const references = new Set<string>();\n\n collectDeclarationsAndReferences(ast, declarations, references);\n\n for (const [name, info] of declarations) {\n // 跳过以 _ 开头的变量(约定为有意忽略)\n if (name.startsWith('_')) continue;\n // 跳过导出的变量\n if (info.kind === 'export') continue;\n\n if (!references.has(name)) {\n issues.push({\n ruleId: 'logic/unused-variables',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: info.line,\n endLine: info.line,\n message: t(\n `Variable \"${name}\" is declared but never used.`,\n `变量 \"${name}\" 已声明但从未使用。`,\n ),\n suggestion: t(\n `Remove the unused variable \"${name}\" or prefix it with _ if intentionally unused.`,\n `移除未使用的变量 \"${name}\",或用 _ 前缀标记为有意忽略。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n\nfunction collectDeclarationsAndReferences(\n root: TSESTree.Node,\n declarations: Map<string, { line: number; kind: string }>,\n references: Set<string>,\n): void {\n // 先收集所有 export 声明的变量名\n // AST 结构: ExportNamedDeclaration → VariableDeclaration → VariableDeclarator\n const exportedNames = new Set<string>();\n walkAST(root, (node) => {\n if (node.type === AST_NODE_TYPES.ExportNamedDeclaration) {\n walkAST(node, (inner) => {\n if (inner.type === AST_NODE_TYPES.VariableDeclarator && inner.id.type === AST_NODE_TYPES.Identifier) {\n exportedNames.add(inner.id.name);\n }\n if (inner.type === AST_NODE_TYPES.FunctionDeclaration && inner.id) {\n exportedNames.add(inner.id.name);\n }\n });\n }\n });\n\n walkAST(root, (node, parent) => {\n const parentType = parent?.type;\n\n if (node.type === AST_NODE_TYPES.VariableDeclarator) {\n if (node.id.type === AST_NODE_TYPES.Identifier) {\n declarations.set(node.id.name, {\n line: node.loc?.start.line ?? 0,\n kind: exportedNames.has(node.id.name) ? 'export' : 'local',\n });\n }\n // 遍历 init 中的引用(但不遍历 id)\n if (node.init) {\n walkAST(node.init, (n) => {\n if (n.type === AST_NODE_TYPES.Identifier) {\n references.add(n.name);\n }\n });\n }\n return false;\n }\n\n if (node.type === AST_NODE_TYPES.FunctionDeclaration && node.id) {\n declarations.set(node.id.name, {\n line: node.loc?.start.line ?? 0,\n kind: exportedNames.has(node.id.name) ? 'export' : 'local',\n });\n }\n\n // 收集引用(非声明位置的 Identifier)\n if (\n node.type === AST_NODE_TYPES.Identifier &&\n parentType !== 'VariableDeclarator' &&\n parentType !== 'FunctionDeclaration'\n ) {\n references.add(node.name);\n }\n return;\n });\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects duplicate conditions in if-else chains.\n * AI often generates if-else chains where the same condition\n * appears multiple times, making some branches unreachable.\n */\nexport const duplicateConditionRule: Rule = {\n id: 'logic/duplicate-condition',\n category: 'logic',\n severity: 'medium',\n title: 'Duplicate condition in if-else chain',\n description:\n 'AI-generated code sometimes contains duplicate conditions in if-else chains, making later branches unreachable.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const visited = new WeakSet<TSESTree.Node>();\n\n walkAST(ast, (node) => {\n if (node.type === AST_NODE_TYPES.IfStatement && !visited.has(node)) {\n const conditions: Array<{ text: string; line: number }> = [];\n collectIfElseChainConditions(node, conditions, visited);\n\n if (conditions.length >= 2) {\n const seen = new Map<string, number>();\n for (const cond of conditions) {\n if (seen.has(cond.text)) {\n const firstLine = seen.get(cond.text)!;\n issues.push({\n ruleId: 'logic/duplicate-condition',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: cond.line,\n endLine: cond.line,\n message: t(\n `Duplicate condition \"${truncate(cond.text, 40)}\" — same condition already checked at line ${firstLine}.`,\n `重复条件 \"${truncate(cond.text, 40)}\" — 相同条件已在第 ${firstLine} 行检查过。`,\n ),\n suggestion: t(\n 'Remove the duplicate branch or change the condition.',\n '移除重复的分支或修改条件。',\n ),\n });\n } else {\n seen.set(cond.text, cond.line);\n }\n }\n }\n }\n });\n\n return issues;\n },\n};\n\nfunction collectIfElseChainConditions(\n node: TSESTree.IfStatement,\n conditions: Array<{ text: string; line: number }>,\n visited: WeakSet<TSESTree.Node>,\n): void {\n visited.add(node);\n const condText = stringifyCondition(node.test);\n conditions.push({ text: condText, line: node.loc?.start.line ?? 0 });\n\n if (node.alternate?.type === AST_NODE_TYPES.IfStatement) {\n collectIfElseChainConditions(node.alternate, conditions, visited);\n }\n}\n\nfunction stringifyCondition(node: TSESTree.Node): string {\n switch (node.type) {\n case AST_NODE_TYPES.Identifier:\n return node.name;\n case AST_NODE_TYPES.Literal:\n return String(node.value);\n case AST_NODE_TYPES.BinaryExpression:\n case AST_NODE_TYPES.LogicalExpression:\n return `${stringifyCondition(node.left)} ${node.operator} ${stringifyCondition(node.right)}`;\n case AST_NODE_TYPES.UnaryExpression:\n return `${node.operator}${stringifyCondition(node.argument)}`;\n case AST_NODE_TYPES.MemberExpression:\n return `${stringifyCondition(node.object)}.${stringifyCondition(node.property)}`;\n case AST_NODE_TYPES.CallExpression:\n return `${stringifyCondition(node.callee)}(...)`;\n default:\n return `[${node.type}]`;\n }\n}\n\nfunction truncate(s: string, maxLen: number): string {\n return s.length > maxLen ? s.slice(0, maxLen) + '...' : s;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects common security issues in code:\n * - Hardcoded secrets/API keys\n * - eval() usage\n * - SQL injection patterns\n * - Insecure crypto usage\n * - Dangerous innerHTML/outerHTML\n */\nexport const securityRules: Rule[] = [\n {\n id: 'security/hardcoded-secret',\n category: 'security',\n severity: 'high',\n title: 'Hardcoded secret or API key',\n description: 'Hardcoded secrets, API keys, passwords, or tokens in source code.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n const secretPatterns = [\n // API keys / tokens\n { pattern: /(?:api[_-]?key|apikey)\\s*[:=]\\s*['\"`][A-Za-z0-9_\\-]{16,}['\"`]/i, label: 'API key' },\n { pattern: /(?:secret|token|password|passwd|pwd)\\s*[:=]\\s*['\"`][^'\"`]{8,}['\"`]/i, label: 'secret/password' },\n // AWS\n { pattern: /AKIA[0-9A-Z]{16}/, label: 'AWS Access Key' },\n // GitHub\n { pattern: /gh[ps]_[A-Za-z0-9_]{36,}/i, label: 'GitHub Token' },\n // Generic long hex/base64 strings assigned to key-like variables\n { pattern: /(?:key|secret|token|auth)\\s*[:=]\\s*['\"`][A-Fa-f0-9]{32,}['\"`]/i, label: 'hex secret' },\n // Private key\n { pattern: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, label: 'private key' },\n // JWT\n { pattern: /eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/, label: 'JWT token' },\n ];\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Skip comments and imports\n if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('import ')) continue;\n // Skip env variable references\n if (/process\\.env\\b/.test(line)) continue;\n\n for (const { pattern, label } of secretPatterns) {\n if (pattern.test(line)) {\n issues.push({\n ruleId: 'security/hardcoded-secret',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Possible hardcoded ${label} detected. Never commit secrets to source code.`,\n `检测到可能的硬编码${label}。永远不要将密钥提交到源代码中。`,\n ),\n suggestion: t(\n 'Use environment variables or a secrets manager instead.',\n '请改用环境变量或密钥管理服务。',\n ),\n });\n break; // one issue per line\n }\n }\n }\n\n return issues;\n },\n },\n\n {\n id: 'security/eval-usage',\n category: 'security',\n severity: 'high',\n title: 'Dangerous eval() usage',\n description: 'eval() can execute arbitrary code and is a major security risk.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n // eval(), new Function(), setTimeout/setInterval with string\n const evalPatterns = [\n { pattern: /\\beval\\s*\\(/, label: 'eval()' },\n { pattern: /new\\s+Function\\s*\\(/, label: 'new Function()' },\n { pattern: /\\b(setTimeout|setInterval)\\s*\\(\\s*['\"`]/, label: 'setTimeout/setInterval with string' },\n ];\n\n for (const { pattern, label } of evalPatterns) {\n if (pattern.test(lines[i])) {\n issues.push({\n ruleId: 'security/eval-usage',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Dangerous ${label} detected — can execute arbitrary code.`,\n `检测到危险的 ${label} — 可执行任意代码。`,\n ),\n suggestion: t(\n `Avoid ${label}. Use safer alternatives like JSON.parse() or proper function references.`,\n `避免使用 ${label}。使用更安全的替代方案,如 JSON.parse() 或函数引用。`,\n ),\n });\n break;\n }\n }\n }\n\n return issues;\n },\n },\n\n {\n id: 'security/sql-injection',\n category: 'security',\n severity: 'high',\n title: 'Potential SQL injection',\n description: 'String concatenation or template literals in SQL queries can lead to SQL injection.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n // SQL query with string concatenation or template literal with variable\n const sqlKeywords = /\\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER)\\b/i;\n if (sqlKeywords.test(lines[i])) {\n // Check for string concat or template with variables\n if (/\\$\\{[^}]+\\}/.test(lines[i]) || /['\"]\\s*\\+\\s*\\w+/.test(lines[i])) {\n issues.push({\n ruleId: 'security/sql-injection',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Potential SQL injection — string interpolation in SQL query.',\n '潜在的 SQL 注入 — SQL 查询中使用了字符串插值。',\n ),\n suggestion: t(\n 'Use parameterized queries or prepared statements instead.',\n '请改用参数化查询或预编译语句。',\n ),\n });\n }\n }\n }\n\n return issues;\n },\n },\n\n {\n id: 'security/dangerous-html',\n category: 'security',\n severity: 'medium',\n title: 'Dangerous HTML manipulation',\n description: 'Direct innerHTML/outerHTML assignment can lead to XSS attacks.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n if (/\\.(innerHTML|outerHTML)\\s*=/.test(lines[i]) || /dangerouslySetInnerHTML/.test(lines[i])) {\n issues.push({\n ruleId: 'security/dangerous-html',\n severity: 'medium',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n 'Direct HTML assignment detected — potential XSS vulnerability.',\n '检测到直接 HTML 赋值 — 可能存在 XSS 漏洞。',\n ),\n suggestion: t(\n 'Use safe DOM APIs like textContent, or sanitize HTML before insertion.',\n '使用安全的 DOM API(如 textContent),或在插入前对 HTML 进行清洗。',\n ),\n });\n }\n }\n\n return issues;\n },\n },\n];\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects empty or useless catch blocks that silently swallow errors.\n *\n * Patterns:\n * - catch (e) {} — completely empty\n * - catch (e) { // ignored } — only comments\n * - catch (e) { throw e; } — re-throws without modification\n */\nexport const emptyCatchRule: Rule = {\n id: 'logic/empty-catch',\n category: 'logic',\n severity: 'medium',\n title: 'Empty or useless catch block',\n description:\n 'AI-generated code often includes catch blocks that silently swallow errors (empty body) or pointlessly re-throw the same error without modification.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n let inBlockComment = false;\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n if (trimmed.startsWith('//') || trimmed.startsWith('*')) continue;\n\n // Match catch block opening\n const catchMatch = trimmed.match(/\\bcatch\\s*\\(\\s*(\\w+)?\\s*\\)\\s*\\{/);\n if (!catchMatch) continue;\n\n const catchVarName = catchMatch[1] || '';\n const blockContent = extractCatchBody(lines, i);\n if (!blockContent) continue;\n\n const { bodyLines, endLine } = blockContent;\n const meaningful = bodyLines.filter(\n (l) => l.trim().length > 0 && !l.trim().startsWith('//') && !l.trim().startsWith('*'),\n );\n\n // Pattern 1: Completely empty or only comments\n if (meaningful.length === 0) {\n issues.push({\n ruleId: 'logic/empty-catch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: endLine + 1,\n message: t(\n 'Empty catch block silently swallows errors. This is a common AI hallucination pattern.',\n '空的 catch 块静默吞掉了错误。这是常见的 AI 幻觉模式。',\n ),\n suggestion: t(\n 'Add error handling logic, or remove the try-catch if the operation cannot fail.',\n '添加错误处理逻辑,或在操作不会抛错时移除 try-catch。',\n ),\n });\n continue;\n }\n\n // Pattern 2: Just re-throws the same error without modification\n if (catchVarName && meaningful.length === 1) {\n const onlyLine = meaningful[0].trim();\n if (\n onlyLine === `throw ${catchVarName};` ||\n onlyLine === `throw ${catchVarName}`\n ) {\n issues.push({\n ruleId: 'logic/empty-catch',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: endLine + 1,\n message: t(\n `Catch block only re-throws the original error \"${catchVarName}\" without modification. The try-catch is pointless.`,\n `catch 块仅原样重新抛出错误 \"${catchVarName}\",没有任何修改。try-catch 毫无意义。`,\n ),\n suggestion: t(\n 'Remove the try-catch block entirely, or wrap the error with additional context.',\n '完全移除 try-catch 块,或在重新抛出时添加额外的上下文信息。',\n ),\n });\n }\n }\n }\n\n return issues;\n },\n};\n\ninterface CatchBody {\n bodyLines: string[];\n endLine: number;\n}\n\nfunction extractCatchBody(lines: string[], catchLineIndex: number): CatchBody | null {\n // Find the 'catch' keyword position to skip the preceding '}' from the try block\n const catchLine = lines[catchLineIndex];\n const catchIdx = catchLine.indexOf('catch');\n if (catchIdx === -1) return null;\n\n let braceCount = 0;\n let started = false;\n let bodyStart = -1;\n\n for (let i = catchLineIndex; i < lines.length; i++) {\n const line = lines[i];\n const startJ = i === catchLineIndex ? catchIdx : 0;\n\n for (let j = startJ; j < line.length; j++) {\n const ch = line[j];\n if (ch === '{') {\n braceCount++;\n if (!started) {\n started = true;\n bodyStart = i;\n }\n } else if (ch === '}') {\n braceCount--;\n if (started && braceCount === 0) {\n return {\n bodyLines: lines.slice(bodyStart + 1, i),\n endLine: i,\n };\n }\n }\n }\n }\n\n return null;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects if-else blocks where both branches contain identical code.\n *\n * AI often generates if/else with the same logic in both branches,\n * making the condition meaningless.\n */\nexport const identicalBranchesRule: Rule = {\n id: 'logic/identical-branches',\n category: 'logic',\n severity: 'medium',\n title: 'Identical if/else branches',\n description:\n 'AI-generated code sometimes contains if/else blocks where both branches have identical code, making the condition meaningless.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const parsed = parseCode(context.fileContent, context.filePath);\n if (!parsed) return issues;\n\n const source = context.fileContent;\n\n walkAST(parsed.ast, (node) => {\n if (\n node.type === AST_NODE_TYPES.IfStatement &&\n node.consequent &&\n node.alternate\n ) {\n // Skip else-if chains — only check simple if/else\n if (node.alternate.type === AST_NODE_TYPES.IfStatement) return;\n\n const thenCode = extractBlockText(source, node.consequent);\n const elseCode = extractBlockText(source, node.alternate);\n\n if (thenCode && elseCode && thenCode === elseCode && thenCode.length > 0) {\n issues.push({\n ruleId: 'logic/identical-branches',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n 'The if and else branches contain identical code. The condition is meaningless.',\n 'if 和 else 分支包含完全相同的代码,条件判断毫无意义。',\n ),\n suggestion: t(\n 'Remove the if/else and keep only one copy of the code, or fix the branching logic.',\n '移除 if/else,只保留一份代码;或修复分支逻辑。',\n ),\n });\n }\n }\n });\n\n return issues;\n },\n};\n\nfunction extractBlockText(\n source: string,\n node: { type: string; range?: [number, number] },\n): string {\n if (!node.range) return '';\n\n let text = source.slice(node.range[0], node.range[1]);\n\n // If it's a block statement, strip the outer { }\n if (text.startsWith('{')) text = text.slice(1);\n if (text.endsWith('}')) text = text.slice(0, -1);\n\n // Normalize whitespace for comparison\n return text.trim().replace(/\\s+/g, ' ');\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects redundant else blocks after return/throw/continue/break.\n *\n * Pattern:\n * if (condition) { return x; } else { doSomething(); }\n * →\n * if (condition) { return x; }\n * doSomething();\n *\n * AI often generates this pattern instead of using early returns.\n */\nexport const redundantElseRule: Rule = {\n id: 'logic/redundant-else',\n category: 'logic',\n severity: 'low',\n title: 'Redundant else after return/throw',\n description:\n 'AI-generated code often uses else blocks after if blocks that already return/throw. The else is unnecessary and adds nesting.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const parsed = parseCode(context.fileContent, context.filePath);\n if (!parsed) return issues;\n\n walkAST(parsed.ast, (node) => {\n if (\n node.type === AST_NODE_TYPES.IfStatement &&\n node.consequent &&\n node.alternate &&\n node.alternate.type !== AST_NODE_TYPES.IfStatement // Skip else-if\n ) {\n if (blockEndsWithExit(node.consequent)) {\n issues.push({\n ruleId: 'logic/redundant-else',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n 'Unnecessary else — the if block already returns/throws. The else adds pointless nesting.',\n '不必要的 else — if 块已经 return/throw 了,else 增加了无意义的嵌套。',\n ),\n suggestion: t(\n 'Remove the else wrapper and place its code after the if block (early return pattern).',\n '移除 else 包裹,将其代码放在 if 块之后(提前返回模式)。',\n ),\n });\n }\n }\n return;\n });\n\n return issues;\n },\n};\n\nfunction blockEndsWithExit(node: { type: string; body?: unknown }): boolean {\n // BlockStatement with last statement being return/throw\n if (node.type === AST_NODE_TYPES.BlockStatement) {\n if (!Array.isArray(node.body)) return false;\n const body = node.body as Array<{ type: string }>;\n if (body.length === 0) return false;\n const last = body[body.length - 1];\n return (\n last.type === AST_NODE_TYPES.ReturnStatement ||\n last.type === AST_NODE_TYPES.ThrowStatement\n );\n }\n // Single statement (no block)\n return (\n node.type === AST_NODE_TYPES.ReturnStatement ||\n node.type === AST_NODE_TYPES.ThrowStatement\n );\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects console.log/warn/error statements left in code.\n *\n * AI-generated code frequently includes console.log for debugging\n * that should be removed before production.\n * Severity is 'info' since some projects legitimately use console.\n */\nexport const consoleInCodeRule: Rule = {\n id: 'logic/console-in-code',\n category: 'logic',\n severity: 'info',\n title: 'Console statement left in code',\n description:\n 'AI-generated code often includes console.log/warn/error statements intended for debugging that should be removed or replaced with a proper logger.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n // Skip files that are likely CLI/logger utilities\n const lowerPath = context.filePath.toLowerCase();\n if (\n lowerPath.includes('/cli/') ||\n lowerPath.includes('logger') ||\n lowerPath.includes('log.') ||\n lowerPath.endsWith('.test.ts') ||\n lowerPath.endsWith('.test.js') ||\n lowerPath.endsWith('.spec.ts') ||\n lowerPath.endsWith('.spec.js')\n ) {\n return issues;\n }\n\n let count = 0;\n const locations: number[] = [];\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n if (trimmed.startsWith('//')) continue;\n\n if (/\\bconsole\\.(log|warn|error|info|debug|trace)\\s*\\(/.test(trimmed)) {\n count++;\n locations.push(i + 1);\n }\n }\n\n // Only report if there are 3+ console statements (to reduce noise)\n if (count >= 3) {\n issues.push({\n ruleId: 'logic/console-in-code',\n severity: 'info',\n category: 'logic',\n file: context.filePath,\n startLine: locations[0],\n endLine: locations[locations.length - 1],\n message: t(\n `${count} console statements found. AI-generated code often leaves debug logging that should be removed or replaced with a proper logger.`,\n `发现 ${count} 个 console 语句。AI 生成的代码经常留下调试日志,应该移除或替换为正式的日志工具。`,\n ),\n suggestion: t(\n 'Remove console statements or replace with a structured logger (e.g. winston, pino).',\n '移除 console 语句或替换为结构化日志工具(如 winston、pino)。',\n ),\n });\n }\n\n return issues;\n },\n};\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects imports that reference non-existent relative modules.\n * AI often hallucinates import paths — referencing files, functions,\n * or modules that don't actually exist in the project.\n */\nexport const phantomImportRule: Rule = {\n id: 'logic/phantom-import',\n category: 'logic',\n severity: 'high',\n title: 'Phantom import — module does not exist',\n description:\n 'AI-generated code frequently imports from non-existent relative paths, indicating hallucinated modules or functions.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n // Only check files with an actual file path on disk\n if (!context.filePath || context.filePath === '<unknown>') {\n return issues;\n }\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const fileDir = dirname(resolve(context.filePath));\n\n walkAST(ast, (node) => {\n // ImportDeclaration: import { foo } from './bar'\n if (node.type === AST_NODE_TYPES.ImportDeclaration) {\n const source = node.source.value;\n if (typeof source === 'string' && isRelativePath(source)) {\n if (!resolveModulePath(fileDir, source)) {\n issues.push({\n ruleId: 'logic/phantom-import',\n severity: 'high',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n `Import from \"${source}\" — module does not exist.`,\n `导入 \"${source}\" — 模块不存在。`,\n ),\n suggestion: t(\n 'Verify the import path. The AI may have hallucinated this module.',\n '检查导入路径,AI 可能编造了这个模块。',\n ),\n });\n }\n }\n }\n\n // Dynamic import: import('./bar') or require('./bar')\n if (\n node.type === AST_NODE_TYPES.ImportExpression &&\n node.source.type === AST_NODE_TYPES.Literal &&\n typeof node.source.value === 'string'\n ) {\n const source = node.source.value;\n if (isRelativePath(source) && !resolveModulePath(fileDir, source)) {\n issues.push({\n ruleId: 'logic/phantom-import',\n severity: 'high',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n `Dynamic import \"${source}\" — module does not exist.`,\n `动态导入 \"${source}\" — 模块不存在。`,\n ),\n suggestion: t(\n 'Verify the import path. The AI may have hallucinated this module.',\n '检查导入路径,AI 可能编造了这个模块。',\n ),\n });\n }\n }\n\n // require('./bar')\n if (\n node.type === AST_NODE_TYPES.CallExpression &&\n node.callee.type === AST_NODE_TYPES.Identifier &&\n node.callee.name === 'require' &&\n node.arguments.length >= 1 &&\n node.arguments[0].type === AST_NODE_TYPES.Literal &&\n typeof node.arguments[0].value === 'string'\n ) {\n const source = node.arguments[0].value;\n if (isRelativePath(source) && !resolveModulePath(fileDir, source)) {\n issues.push({\n ruleId: 'logic/phantom-import',\n severity: 'high',\n category: 'logic',\n file: context.filePath,\n startLine: node.loc?.start.line ?? 0,\n endLine: node.loc?.end.line ?? 0,\n message: t(\n `Require \"${source}\" — module does not exist.`,\n `Require \"${source}\" — 模块不存在。`,\n ),\n suggestion: t(\n 'Verify the require path. The AI may have hallucinated this module.',\n '检查 require 路径,AI 可能编造了这个模块。',\n ),\n });\n }\n }\n });\n\n return issues;\n },\n};\n\nfunction isRelativePath(source: string): boolean {\n return source.startsWith('./') || source.startsWith('../');\n}\n\n/**\n * Try to resolve a relative import to an actual file.\n * Checks common extensions: .ts, .tsx, .js, .jsx, .mts, .mjs, .json\n * Also checks for index files in directories.\n */\nfunction resolveModulePath(dir: string, importPath: string): boolean {\n const resolved = resolve(dir, importPath);\n\n // Exact match (e.g., import './data.json')\n if (existsSync(resolved)) return true;\n\n // TypeScript ESM convention: import './foo.js' → actually ./foo.ts\n // Map .js → .ts/.tsx, .mjs → .mts, .cjs → .cts\n const extMap: Record<string, string[]> = {\n '.js': ['.ts', '.tsx'],\n '.jsx': ['.tsx'],\n '.mjs': ['.mts'],\n '.cjs': ['.cts'],\n };\n for (const [fromExt, toExts] of Object.entries(extMap)) {\n if (importPath.endsWith(fromExt)) {\n const base = resolved.slice(0, -fromExt.length);\n for (const toExt of toExts) {\n if (existsSync(base + toExt)) return true;\n }\n }\n }\n\n // Try common extensions (for extensionless imports)\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs', '.cts', '.cjs', '.json'];\n for (const ext of extensions) {\n if (existsSync(resolved + ext)) return true;\n }\n\n // Directory with index file\n for (const ext of extensions) {\n if (existsSync(resolve(resolved, `index${ext}`))) return true;\n }\n\n return false;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext, Fix } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { lineRange } from '../fix-utils.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects imported identifiers that are never referenced in the code.\n * AI frequently imports modules or functions it never actually uses,\n * indicating incomplete or hallucinated logic.\n */\nexport const unusedImportRule: Rule = {\n id: 'logic/unused-import',\n category: 'logic',\n severity: 'low',\n title: 'Unused import',\n description:\n 'AI-generated code often imports modules or identifiers that are never used in the file.',\n\n fixable: true,\n\n fix(context: RuleContext, issue: Issue): Fix | null {\n // Only fix when the entire import line contains a single specifier.\n // For multi-specifier imports, return null (too risky to auto-fix).\n const lines = context.fileContent.split('\\n');\n const lineIndex = issue.startLine - 1;\n if (lineIndex < 0 || lineIndex >= lines.length) return null;\n\n const line = lines[lineIndex].trim();\n // Check if this is a simple single-specifier import line\n const isSingleDefault = /^import\\s+\\w+\\s+from\\s+/.test(line);\n const isSingleNamed = /^import\\s*\\{\\s*\\w+\\s*\\}\\s*from\\s+/.test(line);\n const isSingleTypeNamed = /^import\\s+type\\s*\\{\\s*\\w+\\s*\\}\\s*from\\s+/.test(line);\n const isSingleTypeDefault = /^import\\s+type\\s+\\w+\\s+from\\s+/.test(line);\n\n if (!isSingleDefault && !isSingleNamed && !isSingleTypeNamed && !isSingleTypeDefault) {\n return null;\n }\n\n const [start, end] = lineRange(context.fileContent, issue.startLine);\n if (start === end) return null;\n return { range: [start, end], text: '' };\n },\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // Collect all import specifiers with their names and locations\n const imports: Array<{\n name: string;\n local: string;\n line: number;\n isTypeOnly: boolean;\n source: string;\n }> = [];\n\n // Collect namespace imports (import * as foo) — harder to track usage\n const namespaceImports = new Set<string>();\n\n for (const node of ast.body) {\n if (node.type !== AST_NODE_TYPES.ImportDeclaration) continue;\n\n const source = String(node.source.value);\n const isTypeOnlyImport = (node as { importKind?: string }).importKind === 'type';\n\n for (const spec of node.specifiers) {\n if (spec.type === AST_NODE_TYPES.ImportNamespaceSpecifier) {\n // import * as foo — skip, too complex to reliably check\n namespaceImports.add(spec.local.name);\n continue;\n }\n\n const isTypeOnlySpec =\n isTypeOnlyImport ||\n (spec.type === AST_NODE_TYPES.ImportSpecifier &&\n (spec as { importKind?: string }).importKind === 'type');\n\n imports.push({\n name: spec.type === AST_NODE_TYPES.ImportSpecifier\n ? (spec.imported as { name: string }).name\n : 'default',\n local: spec.local.name,\n line: spec.loc?.start.line ?? 0,\n isTypeOnly: isTypeOnlySpec,\n source,\n });\n }\n }\n\n if (imports.length === 0) return issues;\n\n // Collect all identifier references outside of import declarations\n const references = new Set<string>();\n const importNodes = new WeakSet<TSESTree.Node>();\n\n for (const node of ast.body) {\n if (node.type === AST_NODE_TYPES.ImportDeclaration) {\n importNodes.add(node);\n }\n }\n\n walkAST(ast, (node) => {\n // Skip import declaration subtrees\n if (importNodes.has(node)) return false;\n\n if (node.type === AST_NODE_TYPES.Identifier) {\n references.add(node.name);\n }\n\n // JSX element names: <MyComponent />\n if (node.type === AST_NODE_TYPES.JSXIdentifier) {\n references.add((node as { name: string }).name);\n }\n return;\n });\n\n // Also check for references in type annotations via string matching\n // This catches cases where type-only imports are used in type positions\n // that the AST walker might miss\n const typeRefPattern = /\\b([A-Z][A-Za-z0-9]*)\\b/g;\n let match;\n while ((match = typeRefPattern.exec(context.fileContent)) !== null) {\n references.add(match[1]);\n }\n\n // Report unused imports\n for (const imp of imports) {\n if (!references.has(imp.local)) {\n issues.push({\n ruleId: 'logic/unused-import',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: imp.line,\n endLine: imp.line,\n message: t(\n `Imported \"${imp.local}\" from \"${imp.source}\" is never used.`,\n `从 \"${imp.source}\" 导入的 \"${imp.local}\" 从未使用。`,\n ),\n suggestion: t(\n `Remove the unused import \"${imp.local}\".`,\n `移除未使用的导入 \"${imp.local}\"。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects calls to async functions or Promise-returning functions\n * inside async functions where the `await` keyword is missing.\n * AI often forgets to add `await`, leading to unhandled promises\n * and subtle race-condition bugs.\n */\nexport const missingAwaitRule: Rule = {\n id: 'logic/missing-await',\n category: 'logic',\n severity: 'medium',\n title: 'Missing await on async call',\n description:\n 'AI-generated code often omits `await` when calling async functions, leading to unhandled promises and race conditions.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // Step 1: Collect names of async functions declared in this file\n const asyncFuncNames = new Set<string>();\n collectAsyncFunctionNames(ast, asyncFuncNames);\n\n // Step 2: Walk async functions and find un-awaited calls to known async functions\n walkAST(ast, (node) => {\n if (!isAsyncFunction(node)) return;\n\n const body = getFunctionBody(node);\n if (!body) return;\n\n walkAST(body, (inner, parent) => {\n // Skip nested async functions — they have their own scope\n if (inner !== body && isAsyncFunction(inner)) return false;\n\n // Look for call expressions that are NOT awaited\n if (inner.type !== AST_NODE_TYPES.CallExpression) return;\n\n // If the parent is an AwaitExpression, it's already awaited\n if (parent?.type === AST_NODE_TYPES.AwaitExpression) return;\n\n // If it's part of a return statement, it's okay (returning a promise)\n if (parent?.type === AST_NODE_TYPES.ReturnStatement) return;\n\n // If it's inside .then()/.catch(), skip\n if (isInsidePromiseChain(inner, parent ?? null)) return;\n\n // If assigned to a variable, skip (might be awaited later)\n if (parent?.type === AST_NODE_TYPES.VariableDeclarator) return;\n if (parent?.type === AST_NODE_TYPES.AssignmentExpression) return;\n\n // If passed as argument, skip (e.g., Promise.all([...]))\n if (parent?.type === AST_NODE_TYPES.ArrayExpression) return;\n if (parent?.type === AST_NODE_TYPES.CallExpression && parent !== inner) return;\n\n const callName = getCallName(inner);\n if (!callName) return;\n\n // Only report if we know the function is async\n if (!asyncFuncNames.has(callName)) return;\n\n issues.push({\n ruleId: 'logic/missing-await',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: inner.loc?.start.line ?? 0,\n endLine: inner.loc?.end.line ?? 0,\n message: t(\n `Call to async function \"${callName}\" is missing \"await\".`,\n `调用异步函数 \"${callName}\" 时缺少 \"await\"。`,\n ),\n suggestion: t(\n `Add \"await\" before the call: await ${callName}(...)`,\n `在调用前添加 \"await\":await ${callName}(...)`,\n ),\n });\n });\n });\n\n return issues;\n },\n};\n\nfunction collectAsyncFunctionNames(\n ast: TSESTree.Program,\n names: Set<string>,\n): void {\n walkAST(ast, (node) => {\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration &&\n node.async &&\n node.id\n ) {\n names.add(node.id.name);\n }\n\n // const foo = async () => { ... }\n // const foo = async function() { ... }\n if (\n node.type === AST_NODE_TYPES.VariableDeclarator &&\n node.id.type === AST_NODE_TYPES.Identifier &&\n node.init &&\n (node.init.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.init.type === AST_NODE_TYPES.FunctionExpression) &&\n node.init.async\n ) {\n names.add(node.id.name);\n }\n\n // Method definitions: async foo() { ... }\n if (\n node.type === AST_NODE_TYPES.MethodDefinition &&\n node.key.type === AST_NODE_TYPES.Identifier &&\n node.value.async\n ) {\n names.add(node.key.name);\n }\n });\n}\n\nfunction isAsyncFunction(node: TSESTree.Node): boolean {\n return (\n (node.type === AST_NODE_TYPES.FunctionDeclaration && node.async) ||\n (node.type === AST_NODE_TYPES.FunctionExpression && node.async) ||\n (node.type === AST_NODE_TYPES.ArrowFunctionExpression && node.async) ||\n (node.type === AST_NODE_TYPES.MethodDefinition && node.value.async)\n );\n}\n\nfunction getFunctionBody(node: TSESTree.Node): TSESTree.Node | null {\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression\n ) {\n return node.body;\n }\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n return node.value.body;\n }\n return null;\n}\n\nfunction getCallName(node: TSESTree.CallExpression): string | null {\n const callee = node.callee;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n // this.foo() or obj.foo()\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return callee.property.name;\n }\n return null;\n}\n\nfunction isInsidePromiseChain(\n _node: TSESTree.Node,\n parent: TSESTree.Node | null,\n): boolean {\n if (!parent) return false;\n if (\n parent.type === AST_NODE_TYPES.MemberExpression &&\n parent.property.type === AST_NODE_TYPES.Identifier &&\n (parent.property.name === 'then' ||\n parent.property.name === 'catch' ||\n parent.property.name === 'finally')\n ) {\n return true;\n }\n return false;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects excessive use of TypeScript `any` type.\n * AI-generated code tends to use `any` to bypass type checking,\n * which defeats the purpose of using TypeScript.\n */\nexport const anyTypeAbuseRule: Rule = {\n id: 'logic/any-type-abuse',\n category: 'logic',\n severity: 'medium',\n title: 'Excessive any type usage',\n description:\n 'AI-generated code often uses `any` type to bypass TypeScript type checking, reducing type safety.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n // Only check TypeScript files\n if (!context.filePath.match(/\\.tsx?$/)) return issues;\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n const lines = context.fileContent.split('\\n');\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.TSAnyKeyword) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n // Skip if inside a comment\n const lineContent = lines[line - 1] ?? '';\n const trimmed = lineContent.trim();\n if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) return;\n\n // Skip type assertion expressions like `as any` in catch clauses\n // e.g., catch (e) { (e as any).message } — sometimes necessary\n const parent = (node as TSESTree.Node & { parent?: TSESTree.Node }).parent;\n if (parent?.type === AST_NODE_TYPES.TSTypeAssertion || parent?.type === AST_NODE_TYPES.TSAsExpression) {\n // Check if it's in a catch clause — allow `as any` in catch\n let ancestor: TSESTree.Node | undefined = parent;\n while (ancestor) {\n if ((ancestor as TSESTree.Node).type === AST_NODE_TYPES.CatchClause) return;\n ancestor = (ancestor as TSESTree.Node & { parent?: TSESTree.Node }).parent;\n }\n }\n\n issues.push({\n ruleId: 'logic/any-type-abuse',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Usage of \"any\" type reduces type safety.`,\n `使用 \"any\" 类型降低了类型安全性。`,\n ),\n suggestion: t(\n `Replace \"any\" with a specific type or \"unknown\" for safer type narrowing.`,\n `将 \"any\" 替换为具体类型或使用 \"unknown\" 进行更安全的类型收窄。`,\n ),\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext, Fix } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { lineStartOffset } from '../fix-utils.js';\n\n/**\n * Detects loose equality operators (== and !=) that cause implicit type coercion.\n * AI-generated code frequently uses == instead of ===, which can lead to\n * subtle bugs due to JavaScript's type coercion rules.\n */\nexport const typeCoercionRule: Rule = {\n id: 'logic/type-coercion',\n category: 'logic',\n severity: 'medium',\n title: 'Loose equality with type coercion',\n description:\n 'AI-generated code often uses == instead of ===, leading to implicit type coercion bugs.',\n\n fixable: true,\n\n fix(context: RuleContext, issue: Issue): Fix | null {\n const lines = context.fileContent.split('\\n');\n const lineIndex = issue.startLine - 1;\n if (lineIndex < 0 || lineIndex >= lines.length) return null;\n\n const line = lines[lineIndex];\n const base = lineStartOffset(context.fileContent, issue.startLine);\n\n // Determine operator from issue message\n const isNotEqual = issue.message.includes('!=');\n const searchOp = isNotEqual ? '!=' : '==';\n const replaceOp = isNotEqual ? '!==' : '===';\n\n // Find the operator position on this line (skip ===, !==)\n let pos = -1;\n for (let j = 0; j < line.length - 1; j++) {\n if (line[j] === searchOp[0] && line[j + 1] === '=') {\n // Make sure it's not already === or !==\n if (line[j + 2] === '=') { j += 2; continue; }\n // For !=, also check it's not just a single =\n if (!isNotEqual && j > 0 && (line[j - 1] === '!' || line[j - 1] === '<' || line[j - 1] === '>')) { continue; }\n pos = j;\n break;\n }\n }\n\n if (pos === -1) return null;\n return { range: [base + pos, base + pos + searchOp.length], text: replaceOp };\n },\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip single-line comments\n if (trimmed.startsWith('//')) continue;\n\n // Remove string literals and comments from the line before checking\n const cleaned = line\n .replace(/(['\"`])(?:(?!\\1|\\\\).|\\\\.)*\\1/g, '\"\"') // remove string contents\n .replace(/\\/\\/.*$/, ''); // remove inline comments\n\n // Match == or != but not === or !==\n const looseEqRegex = /[^!=<>]==[^=]|[^!]==[^=]|!=[^=]/g;\n let match;\n\n while ((match = looseEqRegex.exec(cleaned)) !== null) {\n // Double-check: extract the actual operator\n const pos = match.index;\n const snippet = cleaned.substring(Math.max(0, pos), pos + match[0].length);\n\n // Skip if it's actually === or !==\n if (snippet.includes('===') || snippet.includes('!==')) continue;\n\n const isNotEqual = snippet.includes('!=');\n const operator = isNotEqual ? '!=' : '==';\n const strict = isNotEqual ? '!==' : '===';\n\n // Allow == null / != null pattern (common intentional pattern)\n const afterOp = cleaned.substring(pos + match[0].length - 1).trim();\n if (afterOp.startsWith('null') || afterOp.startsWith('undefined')) continue;\n const beforeOp = cleaned.substring(0, pos + 1).trim();\n if (beforeOp.endsWith('null') || beforeOp.endsWith('undefined')) continue;\n\n issues.push({\n ruleId: 'logic/type-coercion',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Loose equality \"${operator}\" can cause implicit type coercion.`,\n `宽松等于 \"${operator}\" 会导致隐式类型转换。`,\n ),\n suggestion: t(\n `Use strict equality \"${strict}\" instead of \"${operator}\".`,\n `使用严格等于 \"${strict}\" 代替 \"${operator}\"。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects magic numbers — numeric literals used directly in logic\n * without being assigned to a named constant.\n * AI-generated code frequently hard-codes numbers like timeout values,\n * array indices, HTTP status codes, etc. without meaningful names.\n */\n\n// Numbers that are commonly used and generally acceptable\nconst ALLOWED_NUMBERS = new Set([\n -1, 0, 1, 2, 10, 100,\n]);\n\nexport const magicNumberRule: Rule = {\n id: 'logic/magic-number',\n category: 'logic',\n severity: 'low',\n title: 'Magic number',\n description:\n 'AI-generated code often uses unexplained numeric literals instead of named constants.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip comments\n if (trimmed.startsWith('//')) continue;\n\n // Skip const/let/var declarations with direct assignment (defining constants is fine)\n if (/^\\s*(export\\s+)?(const|let|var|readonly)\\s+[A-Z_][A-Z0-9_]*\\s*[=:]/.test(line)) continue;\n\n // Skip enum declarations\n if (/^\\s*(export\\s+)?enum\\s/.test(line)) continue;\n\n // Skip array index access [0], [1], etc.\n // Skip import statements\n if (trimmed.startsWith('import ')) continue;\n\n // Skip lines that are purely return statements with simple numbers\n if (/^\\s*return\\s+[0-9]+\\s*;?\\s*$/.test(line)) continue;\n\n // Remove string contents and comments\n const cleaned = line\n .replace(/(['\"`])(?:(?!\\1|\\\\).|\\\\.)*\\1/g, '\"\"')\n .replace(/\\/\\/.*$/, '');\n\n // Find numeric literals (integers and floats, but not in simple assignments to UPPER_CASE)\n const numRegex = /(?<![.\\w])(-?\\d+\\.?\\d*(?:e[+-]?\\d+)?)\\b/gi;\n let match;\n\n while ((match = numRegex.exec(cleaned)) !== null) {\n const value = parseFloat(match[1]);\n\n // Skip commonly acceptable numbers\n if (ALLOWED_NUMBERS.has(value)) continue;\n\n // Skip if it's NaN (parsing failed)\n if (isNaN(value)) continue;\n\n // Skip array index patterns like [3] or .slice(0, 5)\n const beforeChar = cleaned[match.index - 1] || '';\n if (beforeChar === '[') continue;\n\n // Skip if part of a type annotation (e.g., tuple types)\n if (beforeChar === '<' || beforeChar === ',') continue;\n\n issues.push({\n ruleId: 'logic/magic-number',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Magic number ${match[1]} should be extracted to a named constant.`,\n `魔术数字 ${match[1]} 应提取为命名常量。`,\n ),\n suggestion: t(\n `Define a descriptive constant, e.g., const MAX_RETRIES = ${match[1]};`,\n `定义一个描述性常量,例如 const MAX_RETRIES = ${match[1]};`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects nested ternary expressions.\n * AI-generated code frequently produces deeply nested ternary operators\n * that are very hard to read and maintain.\n */\nexport const nestedTernaryRule: Rule = {\n id: 'logic/no-nested-ternary',\n category: 'logic',\n severity: 'medium',\n title: 'Nested ternary expression',\n description:\n 'AI-generated code often produces nested ternary expressions that are hard to read.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // Track reported lines to avoid duplicate reports\n const reportedLines = new Set<number>();\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ConditionalExpression) return;\n\n // Check if any child (consequent or alternate) is also a ternary\n const conditional = node as TSESTree.ConditionalExpression;\n const hasNestedTernary =\n conditional.consequent.type === AST_NODE_TYPES.ConditionalExpression ||\n conditional.alternate.type === AST_NODE_TYPES.ConditionalExpression;\n\n if (!hasNestedTernary) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0 || reportedLines.has(line)) return;\n reportedLines.add(line);\n\n // Count nesting depth\n let depth = 1;\n let current: TSESTree.Node = node;\n while (current.type === AST_NODE_TYPES.ConditionalExpression) {\n const cond = current as TSESTree.ConditionalExpression;\n if (cond.consequent.type === AST_NODE_TYPES.ConditionalExpression) {\n depth++;\n current = cond.consequent;\n } else if (cond.alternate.type === AST_NODE_TYPES.ConditionalExpression) {\n depth++;\n current = cond.alternate;\n } else {\n break;\n }\n }\n\n const endLine = node.loc?.end.line ?? line;\n\n issues.push({\n ruleId: 'logic/no-nested-ternary',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine,\n message: t(\n `Nested ternary expression (depth: ${depth}) reduces readability.`,\n `嵌套三元表达式(深度: ${depth})降低了可读性。`,\n ),\n suggestion: t(\n `Refactor into if-else statements or use a lookup object/map.`,\n `重构为 if-else 语句或使用查找对象/映射。`,\n ),\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\n\n/**\n * Detects string literals that appear multiple times in the same file.\n * AI-generated code often repeats the same string literal instead of\n * extracting it into a named constant.\n */\n\nconst MIN_STRING_LENGTH = 6;\nconst MIN_OCCURRENCES = 3;\n\nexport const duplicateStringRule: Rule = {\n id: 'logic/duplicate-string',\n category: 'logic',\n severity: 'low',\n title: 'Duplicate string literal',\n description:\n 'AI-generated code often repeats the same string literal instead of extracting it into a constant.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n\n // Collect all string literals with their locations\n const stringMap = new Map<string, number[]>();\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip comments and import lines\n if (trimmed.startsWith('//')) continue;\n if (trimmed.startsWith('import ')) continue;\n\n // Remove inline comments\n const cleaned = line.replace(/\\/\\/.*$/, '');\n\n // Match string literals (single and double quotes)\n const stringRegex = /(['\"])([^'\"\\\\](?:(?!\\1|\\\\).|\\\\.)*)\\1/g;\n let match;\n\n while ((match = stringRegex.exec(cleaned)) !== null) {\n const value = match[2];\n\n // Skip short strings\n if (value.length < MIN_STRING_LENGTH) continue;\n\n // Skip template-like strings with interpolation markers\n if (value.includes('${')) continue;\n\n // Skip URL-like strings and paths\n if (value.startsWith('http') || value.startsWith('/')) continue;\n\n // Skip common test strings\n if (value.startsWith('test') || value.startsWith('mock')) continue;\n\n if (!stringMap.has(value)) {\n stringMap.set(value, []);\n }\n stringMap.get(value)!.push(i + 1);\n }\n }\n\n // Report strings that appear too many times\n for (const [value, locations] of stringMap) {\n if (locations.length < MIN_OCCURRENCES) continue;\n\n // Report only on the first occurrence\n const firstLine = locations[0];\n const displayValue = value.length > 30 ? value.substring(0, 30) + '...' : value;\n\n issues.push({\n ruleId: 'logic/duplicate-string',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: firstLine,\n endLine: firstLine,\n message: t(\n `String \"${displayValue}\" is repeated ${locations.length} times.`,\n `字符串 \"${displayValue}\" 重复出现了 ${locations.length} 次。`,\n ),\n suggestion: t(\n `Extract to a named constant to improve maintainability.`,\n `提取为命名常量以提高可维护性。`,\n ),\n });\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext, Fix } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { lineRange } from '../fix-utils.js';\n\n/**\n * Detects `debugger` statements left in code.\n * AI-generated code or debugging sessions may leave debugger statements\n * that should never reach production.\n */\nexport const noDebuggerRule: Rule = {\n id: 'security/no-debugger',\n category: 'security',\n severity: 'high',\n title: 'Debugger statement',\n description:\n 'Debugger statements should never be committed to production code.',\n\n fixable: true,\n\n fix(context: RuleContext, issue: Issue): Fix | null {\n const [start, end] = lineRange(context.fileContent, issue.startLine);\n if (start === end) return null;\n return { range: [start, end], text: '' };\n },\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n const lines = context.fileContent.split('\\n');\n let inBlockComment = false;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const trimmed = line.trim();\n\n // Track block comments\n if (inBlockComment) {\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n if (trimmed.startsWith('/*')) {\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n // Skip single-line comments\n if (trimmed.startsWith('//')) continue;\n\n // Remove string contents and inline comments\n const cleaned = line\n .replace(/(['\"`])(?:(?!\\1|\\\\).|\\\\.)*\\1/g, '\"\"')\n .replace(/\\/\\/.*$/, '');\n\n // Match standalone `debugger` keyword\n if (/\\bdebugger\\b/.test(cleaned)) {\n issues.push({\n ruleId: 'security/no-debugger',\n severity: 'high',\n category: 'security',\n file: context.filePath,\n startLine: i + 1,\n endLine: i + 1,\n message: t(\n `Debugger statement found. Remove before committing.`,\n `发现 debugger 语句。提交前请移除。`,\n ),\n suggestion: t(\n `Remove the debugger statement.`,\n `移除 debugger 语句。`,\n ),\n });\n }\n }\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects non-null assertion operator (!) usage.\n * AI-generated code frequently uses the ! operator to silence TypeScript\n * null-check errors instead of properly handling nullable values.\n * This can lead to runtime crashes when the value is actually null/undefined.\n */\nexport const noNonNullAssertionRule: Rule = {\n id: 'logic/no-non-null-assertion',\n category: 'logic',\n severity: 'medium',\n title: 'Non-null assertion operator',\n description:\n 'AI-generated code often uses the ! operator to bypass TypeScript null checks, risking runtime crashes.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n // Only check TypeScript files\n if (!context.filePath.match(/\\.tsx?$/)) return issues;\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.TSNonNullExpression) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-non-null-assertion',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Non-null assertion (!) used — value could be null/undefined at runtime.`,\n `使用了非空断言 (!) — 值在运行时可能为 null/undefined。`,\n ),\n suggestion: t(\n `Use optional chaining (?.), nullish coalescing (??), or add a proper null check.`,\n `使用可选链 (?.)、空值合并 (??) 或添加适当的空值检查。`,\n ),\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects self-comparison expressions like `x === x` or `x !== x`.\n * AI-generated code sometimes produces self-comparisons that are always\n * true (===) or always false (!==). The only valid use case is NaN checking,\n * which should use Number.isNaN() instead.\n */\nexport const noSelfCompareRule: Rule = {\n id: 'logic/no-self-compare',\n category: 'logic',\n severity: 'medium',\n title: 'Self-comparison',\n description:\n 'Self-comparison (x === x) is always true (or always false for !==). Use Number.isNaN() for NaN checks.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.BinaryExpression) return;\n\n const binExpr = node as TSESTree.BinaryExpression;\n const op = binExpr.operator;\n\n // Only check equality/inequality operators\n if (!['===', '!==', '==', '!='].includes(op)) return;\n\n // Compare the source text of left and right operands\n const left = serializeNode(binExpr.left);\n const right = serializeNode(binExpr.right);\n\n if (left === null || right === null || left !== right) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-self-compare',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Self-comparison \"${left} ${op} ${right}\" is always ${op.includes('!') ? 'false' : 'true'}.`,\n `自比较 \"${left} ${op} ${right}\" 始终为 ${op.includes('!') ? 'false' : 'true'}。`,\n ),\n suggestion: t(\n `If checking for NaN, use Number.isNaN(${left}) instead.`,\n `如需检查 NaN,请使用 Number.isNaN(${left})。`,\n ),\n });\n });\n\n return issues;\n },\n};\n\n/**\n * Serialize a simple AST node to a string for comparison.\n * Returns null for complex expressions to avoid false positives.\n */\nfunction serializeNode(node: TSESTree.Node): string | null {\n if (node.type === AST_NODE_TYPES.Identifier) {\n return node.name;\n }\n if (node.type === AST_NODE_TYPES.MemberExpression && !node.computed) {\n const obj = serializeNode(node.object);\n const prop = (node.property as TSESTree.Identifier).name;\n if (obj && prop) return `${obj}.${prop}`;\n }\n return null;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects assignment expressions inside return statements.\n * AI-generated code sometimes confuses `=` with `===` in return statements,\n * e.g., `return x = 5` instead of `return x === 5`.\n */\nexport const noReturnAssignRule: Rule = {\n id: 'logic/no-return-assign',\n category: 'logic',\n severity: 'medium',\n title: 'Assignment in return statement',\n description:\n 'AI-generated code sometimes uses assignment (=) instead of comparison (===) in return statements.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ReturnStatement) return;\n\n const returnStmt = node as TSESTree.ReturnStatement;\n if (!returnStmt.argument) return;\n\n // Check if the return argument is an assignment expression\n if (returnStmt.argument.type === AST_NODE_TYPES.AssignmentExpression) {\n const assignExpr = returnStmt.argument as TSESTree.AssignmentExpression;\n // Only flag simple = assignments, not +=, -=, etc.\n if (assignExpr.operator !== '=') return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-return-assign',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Assignment in return statement — did you mean to use === instead of =?`,\n `return 语句中使用了赋值 — 是否应该使用 === 而非 =?`,\n ),\n suggestion: t(\n `If comparison was intended, use === instead of =. If assignment is intentional, extract it to a separate line.`,\n `如果意图是比较,请使用 === 代替 =。如果确实需要赋值,请提取到单独的行。`,\n ),\n });\n }\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects floating promises — async function calls whose return value\n * is neither awaited, returned, nor assigned.\n * AI-generated code frequently calls async functions without await,\n * leading to unhandled promise rejections and race conditions.\n *\n * This is different from missing-await which checks function-level patterns.\n * This rule catches standalone expression statements that are promise-producing calls.\n */\nexport const promiseVoidRule: Rule = {\n id: 'logic/promise-void',\n category: 'logic',\n severity: 'medium',\n title: 'Floating promise (not awaited or returned)',\n description:\n 'AI-generated code often calls async functions without await, causing unhandled rejections.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n // First pass: collect all async function/method names defined in this file\n const asyncFnNames = new Set<string>();\n walkAST(ast, (node): void => {\n if (\n node.type === AST_NODE_TYPES.FunctionDeclaration &&\n (node as TSESTree.FunctionDeclaration).async &&\n (node as TSESTree.FunctionDeclaration).id\n ) {\n asyncFnNames.add((node as TSESTree.FunctionDeclaration).id!.name);\n }\n\n if (\n node.type === AST_NODE_TYPES.VariableDeclarator &&\n (node as TSESTree.VariableDeclarator).id.type === AST_NODE_TYPES.Identifier\n ) {\n const init = (node as TSESTree.VariableDeclarator).init;\n if (\n init &&\n (init.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n init.type === AST_NODE_TYPES.FunctionExpression) &&\n (init as TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression).async\n ) {\n asyncFnNames.add(\n ((node as TSESTree.VariableDeclarator).id as TSESTree.Identifier).name,\n );\n }\n }\n });\n\n // Also detect common async API names\n const commonAsyncPatterns = [\n /^fetch$/,\n /^save/,\n /^load/,\n /^send/,\n /^delete/,\n /^update/,\n /^create/,\n /^connect/,\n /^disconnect/,\n /^init/,\n ];\n\n // Second pass: find expression statements that call async functions\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ExpressionStatement) return;\n\n const expr = (node as TSESTree.ExpressionStatement).expression;\n if (expr.type !== AST_NODE_TYPES.CallExpression) return;\n\n const callExpr = expr as TSESTree.CallExpression;\n const fnName = getCallName(callExpr);\n if (!fnName) return;\n\n // Check if this is a known async function or matches async patterns\n const isKnownAsync = asyncFnNames.has(fnName);\n const matchesPattern = commonAsyncPatterns.some((p) => p.test(fnName));\n\n // Also check for .then() chains — these are definitely promises\n // Method calls ending in common promise-producing names\n const endsWithAsync = fnName.endsWith('Async') || fnName.endsWith('async');\n\n if (!isKnownAsync && !matchesPattern && !endsWithAsync) return;\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n // Skip if inside a non-async function (might be intentional fire-and-forget)\n // We still report but the suggestion is gentler\n issues.push({\n ruleId: 'logic/promise-void',\n severity: 'medium',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: node.loc?.end.line ?? line,\n message: t(\n `Call to \"${fnName}()\" appears to be a floating promise (not awaited or returned).`,\n `调用 \"${fnName}()\" 疑似浮动 Promise(未 await 或 return)。`,\n ),\n suggestion: t(\n `Add \"await\" before the call, assign the result, or use \"void ${fnName}()\" to explicitly discard.`,\n `在调用前添加 \"await\",赋值给变量,或使用 \"void ${fnName}()\" 显式丢弃。`,\n ),\n });\n });\n\n return issues;\n },\n};\n\nfunction getCallName(callExpr: TSESTree.CallExpression): string | null {\n const callee = callExpr.callee;\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n if (\n callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ) {\n return callee.property.name;\n }\n return null;\n}\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects reassignment of function parameters.\n * AI-generated code often reassigns parameters directly instead of\n * using local variables, which creates confusing side-effect patterns\n * and makes the original argument value unrecoverable.\n */\nexport const noReassignParamRule: Rule = {\n id: 'logic/no-reassign-param',\n category: 'logic',\n severity: 'low',\n title: 'Parameter reassignment',\n description:\n 'AI-generated code often reassigns function parameters, creating confusing side-effect patterns.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n // Find function-like nodes\n const isFn =\n node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n node.type === AST_NODE_TYPES.MethodDefinition;\n\n if (!isFn) return;\n\n // Get parameters\n let params: TSESTree.Parameter[] = [];\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n const method = node as TSESTree.MethodDefinition;\n if (method.value && 'params' in method.value) {\n params = (method.value as TSESTree.FunctionExpression).params;\n }\n } else {\n params = (node as TSESTree.FunctionDeclaration).params;\n }\n\n // Collect parameter names (only simple identifiers)\n const paramNames = new Set<string>();\n for (const param of params) {\n if (param.type === AST_NODE_TYPES.Identifier) {\n paramNames.add(param.name);\n }\n // Handle destructured params with defaults: (x = 5)\n if (param.type === AST_NODE_TYPES.AssignmentPattern) {\n const left = param.left;\n if (left.type === AST_NODE_TYPES.Identifier) {\n paramNames.add(left.name);\n }\n }\n }\n\n if (paramNames.size === 0) return;\n\n // Get function body\n let body: TSESTree.Node | null = null;\n if (node.type === AST_NODE_TYPES.MethodDefinition) {\n body = (node as TSESTree.MethodDefinition).value;\n } else {\n body = node;\n }\n if (!body || !('body' in body)) return;\n\n // Walk the function body to find assignments to parameters\n const fnBody = (body as { body: TSESTree.Node }).body;\n if (!fnBody) return;\n\n const reportedParams = new Set<string>();\n\n walkAST(fnBody as TSESTree.Node, (innerNode): void => {\n if (innerNode.type !== AST_NODE_TYPES.AssignmentExpression) return;\n\n const assignExpr = innerNode as TSESTree.AssignmentExpression;\n if (assignExpr.left.type !== AST_NODE_TYPES.Identifier) return;\n\n const name = assignExpr.left.name;\n if (!paramNames.has(name) || reportedParams.has(name)) return;\n\n reportedParams.add(name);\n const line = innerNode.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-reassign-param',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: line,\n message: t(\n `Parameter \"${name}\" is reassigned. This can cause confusion and lose the original value.`,\n `参数 \"${name}\" 被重新赋值。这可能造成混淆并丢失原始值。`,\n ),\n suggestion: t(\n `Use a local variable instead: const local${name.charAt(0).toUpperCase() + name.slice(1)} = ...`,\n `使用局部变量代替:const local${name.charAt(0).toUpperCase() + name.slice(1)} = ...`,\n ),\n });\n });\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects async functions that never use `await` inside their body.\n * AI-generated code frequently marks functions as `async` without\n * actually needing asynchronous behavior, adding unnecessary Promise\n * wrapping overhead and confusion.\n */\nexport const noAsyncWithoutAwaitRule: Rule = {\n id: 'logic/no-async-without-await',\n category: 'logic',\n severity: 'low',\n title: 'Async function without await',\n description:\n 'AI-generated code often marks functions as async without using await, adding unnecessary Promise wrapping.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): boolean | void => {\n const isAsyncFn =\n (node.type === AST_NODE_TYPES.FunctionDeclaration ||\n node.type === AST_NODE_TYPES.FunctionExpression ||\n node.type === AST_NODE_TYPES.ArrowFunctionExpression) &&\n (node as TSESTree.FunctionDeclaration).async;\n\n if (!isAsyncFn) return;\n\n // Check if the function body contains any await expression\n const fnNode = node as TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression;\n const body = fnNode.body;\n if (!body) return;\n\n let hasAwait = false;\n\n walkAST(body as TSESTree.Node, (innerNode): boolean | void => {\n // Stop searching into nested async functions — their awaits don't count\n if (\n innerNode !== body &&\n (innerNode.type === AST_NODE_TYPES.FunctionDeclaration ||\n innerNode.type === AST_NODE_TYPES.FunctionExpression ||\n innerNode.type === AST_NODE_TYPES.ArrowFunctionExpression) &&\n (innerNode as TSESTree.FunctionDeclaration).async\n ) {\n return false; // skip children\n }\n\n if (innerNode.type === AST_NODE_TYPES.AwaitExpression) {\n hasAwait = true;\n return false; // stop searching\n }\n\n // Also check for `for await` loops\n if (\n innerNode.type === AST_NODE_TYPES.ForOfStatement &&\n (innerNode as TSESTree.ForOfStatement).await\n ) {\n hasAwait = true;\n return false;\n }\n\n return;\n });\n\n if (hasAwait) return false; // skip children of this function\n\n const line = node.loc?.start.line ?? 0;\n if (line === 0) return;\n\n // Get function name for better error message\n let fnName = '<anonymous>';\n if (fnNode.type === AST_NODE_TYPES.FunctionDeclaration && fnNode.id) {\n fnName = fnNode.id.name;\n }\n\n issues.push({\n ruleId: 'logic/no-async-without-await',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: node.loc?.end.line ?? line,\n message: t(\n `Async function \"${fnName}\" does not use await.`,\n `异步函数 \"${fnName}\" 内部没有使用 await。`,\n ),\n suggestion: t(\n `Remove the async keyword if this function doesn't need to be asynchronous.`,\n `如果此函数不需要异步行为,请移除 async 关键字。`,\n ),\n });\n\n return false; // skip children\n });\n\n return issues;\n },\n};\n","import { Issue } from '../../types/index.js';\nimport { Rule, RuleContext } from '../types.js';\nimport { t } from '../../i18n/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../../parsers/ast.js';\nimport type { TSESTree } from '../../parsers/ast.js';\nimport { walkAST } from '../../parsers/walk.js';\n\n/**\n * Detects constructors that only call super() with the same parameters,\n * or empty constructors in classes that extend another class.\n * AI-generated code frequently produces these unnecessary constructors.\n */\nexport const noUselessConstructorRule: Rule = {\n id: 'logic/no-useless-constructor',\n category: 'logic',\n severity: 'low',\n title: 'Useless constructor',\n description:\n 'AI-generated code often produces constructors that only call super() or are completely empty.',\n\n check(context: RuleContext): Issue[] {\n const issues: Issue[] = [];\n\n let ast: TSESTree.Program;\n try {\n const parsed = parseCode(context.fileContent, context.filePath);\n ast = parsed.ast;\n } catch {\n return issues;\n }\n\n walkAST(ast, (node): void => {\n if (node.type !== AST_NODE_TYPES.ClassDeclaration && node.type !== AST_NODE_TYPES.ClassExpression) return;\n\n const classNode = node as TSESTree.ClassDeclaration | TSESTree.ClassExpression;\n const hasSuper = classNode.superClass !== null && classNode.superClass !== undefined;\n\n // Find constructor\n const constructor = classNode.body.body.find(\n (member) =>\n member.type === AST_NODE_TYPES.MethodDefinition &&\n member.kind === 'constructor',\n ) as TSESTree.MethodDefinition | undefined;\n\n if (!constructor) return;\n\n const ctorValue = constructor.value as TSESTree.FunctionExpression;\n if (!ctorValue.body) return;\n\n const bodyStatements = ctorValue.body.body;\n\n // Case 1: Empty constructor\n if (bodyStatements.length === 0) {\n const line = constructor.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-useless-constructor',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: constructor.loc?.end.line ?? line,\n message: t(\n `Empty constructor is unnecessary.`,\n `空构造函数是不必要的。`,\n ),\n suggestion: t(\n `Remove the empty constructor — JavaScript provides a default one.`,\n `移除空构造函数 — JavaScript 会自动提供默认构造函数。`,\n ),\n });\n return;\n }\n\n // Case 2: Constructor with only super() call, passing same params\n if (hasSuper && bodyStatements.length === 1) {\n const stmt = bodyStatements[0];\n if (stmt.type !== AST_NODE_TYPES.ExpressionStatement) return;\n\n const expr = stmt.expression;\n if (expr.type !== AST_NODE_TYPES.CallExpression) return;\n if (expr.callee.type !== AST_NODE_TYPES.Super) return;\n\n // Check if super() args match constructor params\n const ctorParams = ctorValue.params;\n const superArgs = expr.arguments;\n\n if (ctorParams.length === superArgs.length) {\n let allMatch = true;\n for (let i = 0; i < ctorParams.length; i++) {\n const param = ctorParams[i];\n const arg = superArgs[i];\n\n // Simple identifier match\n if (\n param.type === AST_NODE_TYPES.Identifier &&\n arg.type === AST_NODE_TYPES.Identifier &&\n param.name === arg.name\n ) {\n continue;\n }\n\n // Handle TypeScript parameter properties (public x: number)\n if (\n param.type === AST_NODE_TYPES.TSParameterProperty &&\n (param as TSESTree.TSParameterProperty).parameter.type === AST_NODE_TYPES.Identifier\n ) {\n // Parameter properties DO something (create class fields), so this constructor is NOT useless\n allMatch = false;\n break;\n }\n\n allMatch = false;\n break;\n }\n\n if (allMatch) {\n const line = constructor.loc?.start.line ?? 0;\n if (line === 0) return;\n\n issues.push({\n ruleId: 'logic/no-useless-constructor',\n severity: 'low',\n category: 'logic',\n file: context.filePath,\n startLine: line,\n endLine: constructor.loc?.end.line ?? line,\n message: t(\n `Constructor only calls super() with the same arguments — it is unnecessary.`,\n `构造函数仅调用 super() 并传递相同参数 — 这是不必要的。`,\n ),\n suggestion: t(\n `Remove the constructor — JavaScript automatically calls super() with the same arguments.`,\n `移除构造函数 — JavaScript 会自动用相同参数调用 super()。`,\n ),\n });\n }\n }\n }\n });\n\n return issues;\n },\n};\n","import { Issue } from '../types/index.js';\nimport { CodeTrustConfig } from '../types/config.js';\nimport { Rule, RuleContext } from './types.js';\nimport { unnecessaryTryCatchRule } from './builtin/unnecessary-try-catch.js';\nimport { overDefensiveRule } from './builtin/over-defensive.js';\nimport { deadLogicRule } from './builtin/dead-logic.js';\nimport { unusedVariablesRule } from './builtin/unused-variables.js';\nimport { duplicateConditionRule } from './builtin/duplicate-condition.js';\nimport { securityRules } from './builtin/security.js';\nimport { emptyCatchRule } from './builtin/empty-catch.js';\nimport { identicalBranchesRule } from './builtin/identical-branches.js';\nimport { redundantElseRule } from './builtin/redundant-else.js';\nimport { consoleInCodeRule } from './builtin/console-in-code.js';\nimport { phantomImportRule } from './builtin/phantom-import.js';\nimport { unusedImportRule } from './builtin/unused-import.js';\nimport { missingAwaitRule } from './builtin/missing-await.js';\nimport { anyTypeAbuseRule } from './builtin/any-type-abuse.js';\nimport { typeCoercionRule } from './builtin/type-coercion.js';\nimport { magicNumberRule } from './builtin/magic-number.js';\nimport { nestedTernaryRule } from './builtin/nested-ternary.js';\nimport { duplicateStringRule } from './builtin/duplicate-string.js';\nimport { noDebuggerRule } from './builtin/no-debugger.js';\nimport { noNonNullAssertionRule } from './builtin/no-non-null-assertion.js';\nimport { noSelfCompareRule } from './builtin/no-self-compare.js';\nimport { noReturnAssignRule } from './builtin/no-return-assign.js';\nimport { promiseVoidRule } from './builtin/promise-void.js';\nimport { noReassignParamRule } from './builtin/no-reassign-param.js';\nimport { noAsyncWithoutAwaitRule } from './builtin/no-async-without-await.js';\nimport { noUselessConstructorRule } from './builtin/no-useless-constructor.js';\n\nconst BUILTIN_RULES: Rule[] = [\n unnecessaryTryCatchRule,\n overDefensiveRule,\n deadLogicRule,\n unusedVariablesRule,\n duplicateConditionRule,\n ...securityRules,\n emptyCatchRule,\n identicalBranchesRule,\n redundantElseRule,\n consoleInCodeRule,\n phantomImportRule,\n unusedImportRule,\n missingAwaitRule,\n anyTypeAbuseRule,\n typeCoercionRule,\n magicNumberRule,\n nestedTernaryRule,\n duplicateStringRule,\n noDebuggerRule,\n noNonNullAssertionRule,\n noSelfCompareRule,\n noReturnAssignRule,\n promiseVoidRule,\n noReassignParamRule,\n noAsyncWithoutAwaitRule,\n noUselessConstructorRule,\n];\n\nexport class RuleEngine {\n private rules: Rule[];\n\n constructor(config: CodeTrustConfig) {\n this.rules = BUILTIN_RULES.filter(\n (rule) => !config.rules.disabled.includes(rule.id),\n );\n }\n\n run(context: RuleContext): Issue[] {\n const allIssues: Issue[] = [];\n\n for (const rule of this.rules) {\n try {\n const issues = rule.check(context);\n allIssues.push(...issues);\n } catch (_err) {\n // Rule execution failed — skip silently for now\n }\n }\n\n return allIssues;\n }\n\n getRules(): Rule[] {\n return [...this.rules];\n }\n\n listRules(): Array<{ id: string; category: string; severity: string; title: string }> {\n return BUILTIN_RULES.map((r) => ({\n id: r.id,\n category: r.category,\n severity: r.severity,\n title: r.title,\n }));\n }\n}\n","import { Issue, DimensionScore, TrustGrade, RuleCategory } from '../types/index.js';\nimport { DimensionWeights } from '../types/config.js';\nimport { isZhLocale } from '../i18n/index.js';\n\n// Info-level issues (e.g. console-in-code) have 0 penalty — they are\n// advisory only and do not affect the trust score.\nconst SEVERITY_PENALTY: Record<string, number> = {\n high: 15,\n medium: 8,\n low: 3,\n info: 0,\n};\n\nexport function calculateDimensionScore(issues: Issue[]): DimensionScore {\n let score = 100;\n\n for (const issue of issues) {\n score -= SEVERITY_PENALTY[issue.severity] ?? 0;\n }\n\n return {\n score: Math.max(0, Math.min(100, score)),\n issues,\n };\n}\n\nexport function calculateOverallScore(\n dimensions: Record<RuleCategory, DimensionScore>,\n weights: DimensionWeights,\n): number {\n const score =\n dimensions.security.score * weights.security +\n dimensions.logic.score * weights.logic +\n dimensions.structure.score * weights.structure +\n dimensions.style.score * weights.style +\n dimensions.coverage.score * weights.coverage;\n\n return Math.round(Math.max(0, Math.min(100, score)));\n}\n\nexport function getGrade(score: number): TrustGrade {\n if (score >= 90) return 'HIGH_TRUST';\n if (score >= 70) return 'REVIEW';\n if (score >= 50) return 'LOW_TRUST';\n return 'UNTRUSTED';\n}\n\nexport function getGradeEmoji(grade: TrustGrade): string {\n switch (grade) {\n case 'HIGH_TRUST':\n return '✅';\n case 'REVIEW':\n return '⚠️';\n case 'LOW_TRUST':\n return '⚠️';\n case 'UNTRUSTED':\n return '❌';\n }\n}\n\nexport function getGradeLabel(grade: TrustGrade): string {\n const isZh = isZhLocale();\n if (isZh) {\n switch (grade) {\n case 'HIGH_TRUST':\n return '高信任 — 可安全合并';\n case 'REVIEW':\n return '建议审查';\n case 'LOW_TRUST':\n return '低信任 — 需仔细审查';\n case 'UNTRUSTED':\n return '不可信 — 不应合并';\n }\n }\n switch (grade) {\n case 'HIGH_TRUST':\n return 'HIGH TRUST — Safe to merge';\n case 'REVIEW':\n return 'REVIEW RECOMMENDED';\n case 'LOW_TRUST':\n return 'LOW TRUST — Careful review needed';\n case 'UNTRUSTED':\n return 'UNTRUSTED — Do not merge without changes';\n }\n}\n","import { Issue } from '../types/index.js';\nimport { parseCode, extractFunctions, FunctionInfo } from '../parsers/ast.js';\nimport { t } from '../i18n/index.js';\n\nexport interface StructureThresholds {\n maxCyclomaticComplexity: number;\n maxCognitiveComplexity: number;\n maxFunctionLength: number;\n maxNestingDepth: number;\n maxParamCount: number;\n}\n\nconst DEFAULT_THRESHOLDS: StructureThresholds = {\n maxCyclomaticComplexity: 10,\n maxCognitiveComplexity: 20,\n maxFunctionLength: 40,\n maxNestingDepth: 4,\n maxParamCount: 5,\n};\n\nexport interface StructureAnalysisResult {\n functions: FunctionInfo[];\n issues: Issue[];\n}\n\nexport function analyzeStructure(\n code: string,\n filePath: string,\n thresholds: Partial<StructureThresholds> = {},\n): StructureAnalysisResult {\n const t_ = { ...DEFAULT_THRESHOLDS, ...thresholds };\n const issues: Issue[] = [];\n\n let parsed;\n try {\n parsed = parseCode(code, filePath);\n } catch {\n return { functions: [], issues: [] };\n }\n\n const functions = extractFunctions(parsed);\n\n for (const fn of functions) {\n if (fn.cyclomaticComplexity > t_.maxCyclomaticComplexity) {\n issues.push({\n ruleId: 'structure/high-cyclomatic-complexity',\n severity: fn.cyclomaticComplexity > t_.maxCyclomaticComplexity * 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has cyclomatic complexity of ${fn.cyclomaticComplexity} (threshold: ${t_.maxCyclomaticComplexity}).`,\n `函数 \"${fn.name}\" 的圈复杂度为 ${fn.cyclomaticComplexity}(阈值:${t_.maxCyclomaticComplexity})。`,\n ),\n suggestion: t(\n 'Break the function into smaller, simpler functions.',\n '将函数拆分为更小、更简单的函数。',\n ),\n });\n }\n\n if (fn.cognitiveComplexity > t_.maxCognitiveComplexity) {\n issues.push({\n ruleId: 'structure/high-cognitive-complexity',\n severity: fn.cognitiveComplexity > t_.maxCognitiveComplexity * 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has cognitive complexity of ${fn.cognitiveComplexity} (threshold: ${t_.maxCognitiveComplexity}).`,\n `函数 \"${fn.name}\" 的认知复杂度为 ${fn.cognitiveComplexity}(阈值:${t_.maxCognitiveComplexity})。`,\n ),\n suggestion: t(\n 'Simplify the function by reducing nesting and breaking out helper functions.',\n '通过减少嵌套和提取辅助函数来简化该函数。',\n ),\n });\n }\n\n if (fn.lineCount > t_.maxFunctionLength) {\n issues.push({\n ruleId: 'structure/long-function',\n severity: fn.lineCount > t_.maxFunctionLength * 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" is ${fn.lineCount} lines long (threshold: ${t_.maxFunctionLength}).`,\n `函数 \"${fn.name}\" 长达 ${fn.lineCount} 行(阈值:${t_.maxFunctionLength})。`,\n ),\n suggestion: t(\n 'Break the function into smaller units with clear responsibilities.',\n '将函数拆分为职责清晰的更小单元。',\n ),\n });\n }\n\n if (fn.maxNestingDepth > t_.maxNestingDepth) {\n issues.push({\n ruleId: 'structure/deep-nesting',\n severity: fn.maxNestingDepth > t_.maxNestingDepth + 2 ? 'high' : 'medium',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has nesting depth of ${fn.maxNestingDepth} (threshold: ${t_.maxNestingDepth}).`,\n `函数 \"${fn.name}\" 的嵌套深度为 ${fn.maxNestingDepth}(阈值:${t_.maxNestingDepth})。`,\n ),\n suggestion: t(\n 'Use early returns, guard clauses, or extract nested logic into separate functions.',\n '使用提前返回、守卫语句,或将嵌套逻辑提取到单独的函数中。',\n ),\n });\n }\n\n if (fn.paramCount > t_.maxParamCount) {\n issues.push({\n ruleId: 'structure/too-many-params',\n severity: 'low',\n category: 'structure',\n file: filePath,\n startLine: fn.startLine,\n endLine: fn.endLine,\n message: t(\n `Function \"${fn.name}\" has ${fn.paramCount} parameters (threshold: ${t_.maxParamCount}).`,\n `函数 \"${fn.name}\" 有 ${fn.paramCount} 个参数(阈值:${t_.maxParamCount})。`,\n ),\n suggestion: t(\n 'Consider using an options object to group related parameters.',\n '考虑使用选项对象来组合相关参数。',\n ),\n });\n }\n }\n\n return { functions, issues };\n}\n","import { Issue } from '../types/index.js';\nimport { parseCode, AST_NODE_TYPES } from '../parsers/ast.js';\nimport type { TSESTree } from '../parsers/ast.js';\nimport { walkAST } from '../parsers/walk.js';\nimport { t } from '../i18n/index.js';\n\nexport interface StyleAnalysisResult {\n issues: Issue[];\n stats: {\n camelCaseCount: number;\n snakeCaseCount: number;\n pascalCaseCount: number;\n totalIdentifiers: number;\n commentLineCount: number;\n codeLineCount: number;\n commentDensity: number;\n };\n}\n\nexport function analyzeStyle(code: string, filePath: string): StyleAnalysisResult {\n const issues: Issue[] = [];\n const lines = code.split('\\n');\n\n // 注释密度\n let commentLines = 0;\n let codeLines = 0;\n let inBlockComment = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n\n if (inBlockComment) {\n commentLines++;\n if (trimmed.includes('*/')) inBlockComment = false;\n continue;\n }\n\n if (trimmed.startsWith('/*')) {\n commentLines++;\n if (!trimmed.includes('*/')) inBlockComment = true;\n continue;\n }\n\n if (trimmed.startsWith('//')) {\n commentLines++;\n continue;\n }\n\n codeLines++;\n }\n\n const commentDensity = codeLines > 0 ? commentLines / codeLines : 0;\n\n // 命名风格分析\n let camelCase = 0;\n let snakeCase = 0;\n let pascalCase = 0;\n let totalIdents = 0;\n\n try {\n const parsed = parseCode(code, filePath);\n collectNamingStyles(parsed.ast, (style) => {\n totalIdents++;\n if (style === 'camel') camelCase++;\n else if (style === 'snake') snakeCase++;\n else if (style === 'pascal') pascalCase++;\n });\n } catch {\n // AST parse failed, skip naming analysis\n }\n\n // 命名风格不一致检测\n const styles = [\n { name: 'camelCase', count: camelCase },\n { name: 'snake_case', count: snakeCase },\n ].filter((s) => s.count > 0);\n\n if (styles.length > 1 && totalIdents >= 5) {\n const dominant = styles.reduce((a, b) => (a.count > b.count ? a : b));\n const minority = styles.reduce((a, b) => (a.count < b.count ? a : b));\n const ratio = minority.count / totalIdents;\n\n if (ratio > 0.15) {\n issues.push({\n ruleId: 'style/inconsistent-naming',\n severity: 'low',\n category: 'style',\n file: filePath,\n startLine: 1,\n endLine: lines.length,\n message: t(\n `Mixed naming styles: ${dominant.count} ${dominant.name} vs ${minority.count} ${minority.name} identifiers.`,\n `命名风格混用:${dominant.count} 个 ${dominant.name} 与 ${minority.count} 个 ${minority.name} 标识符。`,\n ),\n suggestion: t(\n `Standardize on ${dominant.name} for consistency.`,\n `统一使用 ${dominant.name} 以保持一致性。`,\n ),\n });\n }\n }\n\n return {\n issues,\n stats: {\n camelCaseCount: camelCase,\n snakeCaseCount: snakeCase,\n pascalCaseCount: pascalCase,\n totalIdentifiers: totalIdents,\n commentLineCount: commentLines,\n codeLineCount: codeLines,\n commentDensity,\n },\n };\n}\n\ntype NamingStyle = 'camel' | 'snake' | 'pascal' | 'other';\n\nfunction detectNamingStyle(name: string): NamingStyle {\n if (name.length <= 1) return 'other';\n if (name.startsWith('_') || name === name.toUpperCase()) return 'other';\n if (name.includes('_')) return 'snake';\n if (/^[A-Z]/.test(name)) return 'pascal';\n if (/^[a-z]/.test(name)) return 'camel';\n return 'other';\n}\n\nfunction collectNamingStyles(\n root: TSESTree.Node,\n callback: (style: NamingStyle) => void,\n): void {\n walkAST(root, (node) => {\n if (node.type === AST_NODE_TYPES.VariableDeclarator && node.id.type === AST_NODE_TYPES.Identifier) {\n const style = detectNamingStyle(node.id.name);\n if (style !== 'other') callback(style);\n }\n\n if (node.type === AST_NODE_TYPES.FunctionDeclaration && node.id) {\n const style = detectNamingStyle(node.id.name);\n if (style !== 'other') callback(style);\n }\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Issue } from '../types/index.js';\nimport { parseCode, extractFunctions } from '../parsers/ast.js';\nimport { t } from '../i18n/index.js';\n\nexport interface CoverageAnalysisResult {\n issues: Issue[];\n exportedFunctions: string[];\n hasTestFile: boolean;\n}\n\nexport function analyzeCoverage(\n code: string,\n filePath: string,\n): CoverageAnalysisResult {\n const issues: Issue[] = [];\n const exportedFunctions: string[] = [];\n\n // 检查是否有对应的测试文件\n const testFile = findTestFile(filePath);\n const hasTestFile = testFile !== null;\n\n try {\n const parsed = parseCode(code, filePath);\n const functions = extractFunctions(parsed);\n\n // 收集 exported 函数名\n for (const fn of functions) {\n if (fn.name !== '<anonymous>' && fn.name !== '<arrow>') {\n exportedFunctions.push(fn.name);\n }\n }\n\n // 如果文件有超过 2 个导出函数且没有测试文件,报告\n if (exportedFunctions.length >= 2 && !hasTestFile) {\n // 跳过测试文件本身\n const basename = path.basename(filePath);\n if (!basename.includes('.test.') && !basename.includes('.spec.') && !basename.startsWith('test')) {\n issues.push({\n ruleId: 'coverage/missing-test-file',\n severity: 'low',\n category: 'coverage',\n file: filePath,\n startLine: 1,\n endLine: 1,\n message: t(\n `File has ${exportedFunctions.length} functions but no corresponding test file found.`,\n `文件有 ${exportedFunctions.length} 个函数,但未找到对应的测试文件。`,\n ),\n suggestion: t(\n `Create a test file (e.g., ${suggestTestFileName(filePath)}).`,\n `创建测试文件(如:${suggestTestFileName(filePath)})。`,\n ),\n });\n }\n }\n } catch {\n // AST parse failed\n }\n\n return { issues, exportedFunctions, hasTestFile };\n}\n\nfunction findTestFile(filePath: string): string | null {\n const dir = path.dirname(filePath);\n const ext = path.extname(filePath);\n const base = path.basename(filePath, ext);\n\n const candidates = [\n // 同目录\n path.join(dir, `${base}.test${ext}`),\n path.join(dir, `${base}.spec${ext}`),\n // tests/ 目录(复数)\n path.join(dir, '..', 'tests', `${base}.test${ext}`),\n path.join(dir, '..', 'tests', `${base}.spec${ext}`),\n path.join(dir, '..', '..', 'tests', `${base}.test${ext}`),\n path.join(dir, '..', '..', 'tests', `${base}.spec${ext}`),\n // test/ 目录(单数)\n path.join(dir, '..', 'test', `${base}.test${ext}`),\n path.join(dir, '..', 'test', `${base}.spec${ext}`),\n // __tests__/ 目录\n path.join(dir, '__tests__', `${base}.test${ext}`),\n path.join(dir, '__tests__', `${base}.spec${ext}`),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction suggestTestFileName(filePath: string): string {\n const ext = path.extname(filePath);\n const base = path.basename(filePath, ext);\n return `${base}.test${ext}`;\n}\n","import { cosmiconfig } from 'cosmiconfig';\nimport { CodeTrustConfig, DEFAULT_CONFIG } from '../types/config.js';\n\nconst MODULE_NAME = 'codetrust';\n\nexport async function loadConfig(searchFrom?: string): Promise<CodeTrustConfig> {\n const explorer = cosmiconfig(MODULE_NAME, {\n searchPlaces: [\n `.${MODULE_NAME}.yml`,\n `.${MODULE_NAME}.yaml`,\n `.${MODULE_NAME}.json`,\n `.${MODULE_NAME}rc`,\n `${MODULE_NAME}.config.js`,\n `${MODULE_NAME}.config.ts`,\n ],\n });\n\n const result = await explorer.search(searchFrom);\n\n if (!result || result.isEmpty) {\n return DEFAULT_CONFIG;\n }\n\n return mergeConfig(DEFAULT_CONFIG, result.config);\n}\n\nfunction mergeConfig(\n defaults: CodeTrustConfig,\n overrides: Partial<CodeTrustConfig>,\n): CodeTrustConfig {\n return {\n ...defaults,\n ...overrides,\n weights: { ...defaults.weights, ...overrides.weights },\n thresholds: { ...defaults.thresholds, ...overrides.thresholds },\n rules: {\n disabled: overrides.rules?.disabled ?? defaults.rules.disabled,\n overrides: { ...defaults.rules.overrides, ...overrides.rules?.overrides },\n },\n detection: { ...defaults.detection, ...overrides.detection },\n };\n}\n\nexport function generateDefaultConfig(): string {\n return `# .codetrust.yml\nversion: 1\n\n# Scan scope\ninclude:\n - \"src/**/*.ts\"\n - \"src/**/*.js\"\nexclude:\n - \"**/*.test.ts\"\n - \"**/*.spec.ts\"\n - \"**/node_modules/**\"\n - \"**/dist/**\"\n\n# Dimension weights (must sum to 1.0)\nweights:\n security: 0.30\n logic: 0.25\n structure: 0.20\n style: 0.10\n coverage: 0.15\n\n# Thresholds\nthresholds:\n min-score: 70\n max-function-length: 40\n max-cyclomatic-complexity: 10\n max-nesting-depth: 4\n max-params: 5\n\n# Rules\nrules:\n disabled: []\n overrides: {}\n\n# AI code detection\ndetection:\n enabled: true\n show-probability: true\n`;\n}\n","export interface CodeTrustConfig {\n version: number;\n include: string[];\n exclude: string[];\n weights: DimensionWeights;\n thresholds: Thresholds;\n rules: RulesConfig;\n detection: DetectionConfig;\n}\n\nexport interface DimensionWeights {\n security: number;\n logic: number;\n structure: number;\n style: number;\n coverage: number;\n}\n\nexport interface Thresholds {\n 'min-score': number;\n 'max-function-length': number;\n 'max-cyclomatic-complexity': number;\n 'max-cognitive-complexity': number;\n 'max-nesting-depth': number;\n 'max-params': number;\n}\n\nexport interface RulesConfig {\n disabled: string[];\n overrides: Record<string, string>;\n}\n\n// Reserved for Phase 3: AI-generated code probability detection\nexport interface DetectionConfig {\n enabled: boolean;\n 'show-probability': boolean;\n}\n\nexport const DEFAULT_CONFIG: CodeTrustConfig = {\n version: 1,\n include: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],\n exclude: [\n '**/*.test.ts',\n '**/*.spec.ts',\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n ],\n weights: {\n security: 0.30,\n logic: 0.25,\n structure: 0.20,\n style: 0.10,\n coverage: 0.15,\n },\n thresholds: {\n 'min-score': 70,\n 'max-function-length': 40,\n 'max-cyclomatic-complexity': 10,\n 'max-cognitive-complexity': 20,\n 'max-nesting-depth': 4,\n 'max-params': 5,\n },\n rules: {\n disabled: [],\n overrides: {},\n },\n detection: {\n enabled: true,\n 'show-probability': true,\n },\n};\n"],"mappings":"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","names":["existsSync","resolve","dirname","getCallName","basename","dirname","resolve","existsSync"]}