analyze_code
Analyze frontend source code to identify accessibility issues, CSS problems, component complexity, design inconsistencies, and performance concerns for quality improvement.
Instructions
Analyze frontend source code for quality issues: accessibility anti-patterns, CSS problems, component complexity, design inconsistencies, and performance concerns.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| directory | Yes | Absolute path to the frontend source directory (e.g., /Users/me/project/src) |
Implementation Reference
- src/tools/code-analysis.ts:448-582 (handler)The primary handler function `analyzeCode` that executes code analysis on a given directory. It scans files for various patterns, applies rules, and aggregates findings.
export async function analyzeCode( directory: string ): Promise<CodeAnalysisResult> { const { config, loaded, path: configPath } = await loadConfig(directory); const framework = await detectFramework(directory); // Convert config ignore patterns to glob-compatible patterns const configIgnoreGlobs = config.ignore.map((pattern) => { // If pattern has no glob chars and no extension, treat as a directory if (!pattern.includes("*") && !pattern.includes(".")) { return `${pattern}/**`; } // If it's a glob pattern like "*.test.*", ensure it matches in all directories if (pattern.startsWith("*.")) { return `**/${pattern}`; } return pattern; }); const files = await collectFrontendFiles(directory, 200, configIgnoreGlobs); // Filter RULES based on config (immutable — create a new filtered array) const activeRules = RULES.filter((rule) => config.rules[rule.id] !== "off"); // Build a list of disabled rule IDs for reporting const rulesDisabled = Object.entries(config.rules) .filter(([, status]) => status === "off") .map(([id]) => id); // Build a list of severity-overridden rule IDs for reporting const severityOverrides = Object.keys(config.severity); const findings: CodeFinding[] = []; let totalLines = 0; let componentCount = 0; let stylesheetCount = 0; for (const file of files) { totalLines += file.lineCount; // Count components and stylesheets if ([".tsx", ".jsx", ".vue", ".svelte"].includes(file.extension)) { componentCount++; } if ([".css", ".scss", ".sass", ".less"].includes(file.extension)) { stylesheetCount++; } // Run pattern-based rules (using filtered activeRules) for (const rule of activeRules) { if (!rule.fileTypes.includes(file.extension)) continue; const matches = file.content.matchAll(rule.pattern); let matchCount = 0; // Determine the effective severity: config override takes precedence const effectiveSeverity = config.severity[rule.id] ?? rule.severity; for (const match of matches) { matchCount++; if (matchCount > 5) break; // Limit findings per rule per file // Find line number const beforeMatch = file.content.slice(0, match.index); const lineNumber = beforeMatch.split("\n").length; findings.push({ file: file.relativePath, line: lineNumber, severity: effectiveSeverity, category: rule.category, rule: rule.id, message: rule.message, suggestion: rule.suggestion, }); } } // Run file-level checks const sizeCheck = checkFileSize(file); if (sizeCheck) findings.push(sizeCheck); const nestingCheck = checkDeepNesting(file); if (nestingCheck) findings.push(nestingCheck); } // Run project-level checks const errorBoundaryCheck = checkMissingErrorBoundary(files); if (errorBoundaryCheck) findings.push(errorBoundaryCheck); // Sort findings by severity const severityOrder: Record<Severity, number> = { critical: 0, high: 1, medium: 2, low: 3, }; const sortedFindings = [...findings].sort( (a, b) => severityOrder[a.severity] - severityOrder[b.severity] ); // Find largest files const sortedFiles = [...files].sort((a, b) => b.lineCount - a.lineCount); const largestFiles = sortedFiles.slice(0, 5).map((f) => ({ file: f.relativePath, lines: f.lineCount, })); const avgFileSize = files.length > 0 ? Math.round(totalLines / files.length) : 0; return { directory, timestamp: new Date().toISOString(), framework, totalFiles: files.length, totalLines, findings: sortedFindings, summary: { components: componentCount, stylesheets: stylesheetCount, avgFileSize, largestFiles, }, configStatus: { loaded, path: configPath, rulesDisabled, severityOverrides, }, }; }