(filePath, relativePath)
| 621 | }); |
| 622 | return 0; |
| 623 | } catch (err) { |
| 624 | const output = (err.stdout || '') + (err.stderr || ''); |
| 625 | const errors = output.split('\n').filter(l => l.includes('error')); |
| 626 | if (errors.length > 0) { |
| 627 | hookOutput('post-edit', 'error', `[typecheck] cargo check errors:\n${errors.slice(0, 10).join('\n')}`, { file: '', errors: errors.slice(0, 10), exit_code: 2 }); |
| 628 | return 2; |
| 629 | } |
| 630 | return 0; |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | // ── Performance Lint ───────────────────────────────────────────────────────── |
| 635 | |
| 636 | function performanceLint(filePath, relativePath) { |
| 637 | // Only lint source files |
| 638 | if (!/\.(ts|tsx|js|jsx|py|go|rs)$/.test(filePath)) return; |
| 639 | |
| 640 | let content; |
| 641 | try { |
| 642 | content = fs.readFileSync(filePath, 'utf8'); |
| 643 | } catch { |
| 644 | return; |
| 645 | } |
| 646 | |
| 647 | const warnings = []; |
| 648 | |
| 649 | // Check for confirm/alert/prompt (cross-language web anti-pattern) |
| 650 | if (/\.(ts|tsx|js|jsx)$/.test(filePath)) { |
| 651 | if (/\bconfirm\s*\(/.test(content)) warnings.push('Uses confirm() — use an in-app modal instead'); |
| 652 | if (/\balert\s*\(/.test(content)) warnings.push('Uses alert() — use an in-app notification instead'); |
| 653 | if (/\bprompt\s*\(/.test(content)) warnings.push('Uses prompt() — use an in-app input instead'); |
| 654 | } |
no test coverage detected