kyorlin2001/code-analysis-tool
0
1from __future__ import annotations2 3from dataclasses import dataclass4from pathlib import Path5from typing import Any6 7from models.analysis_state import AnalysisState8 9 10@dataclass11class IssueOutput:12 """13 Result of issue / risk analysis.14 """15 16 issues: list[dict[str, Any]]17 notes: list[str]18 19 20class IssueAgent:21 """22 Performs a lightweight issue/risk scan over the repository.23 24 Responsibilities:25 - flag obvious maintenance risks26 - collect simple heuristics-based issues27 - prepare findings for the final report28 """29 30 def run(self, state: AnalysisState) -> IssueOutput:31 issues: list[dict[str, Any]] = []32 notes: list[str] = []33 34 if not state.files:35 issues.append(36 {37 "severity": "medium",38 "message": "Repository contains no supported source files.",39 }40 )41 notes.append("No source files available for deeper analysis.")42 else:43 issues.extend(self._scan_repo_heuristics(state.files))44 45 output = IssueOutput(issues=issues, notes=notes)46 47 state.summaries["issues"] = self._format_summary(output)48 state.agent_outputs["issues"] = output49 state.findings.extend(issues)50 return output51 52 def _scan_repo_heuristics(self, files: list[str]) -> list[dict[str, Any]]:53 issues: list[dict[str, Any]] = []54 55 has_tests = any("test" in f.lower() or "tests" in Path(f).parts for f in files)56 has_readme = any(Path(f).name.lower() == "readme.md" for f in files)57 has_gitignore = any(Path(f).name == ".gitignore" for f in files)58 59 if not has_tests:60 issues.append(61 {62 "severity": "medium",63 "message": "No tests directory or test files were detected.",64 }65 )66 67 if not has_readme:68 issues.append(69 {70 "severity": "low",71 "message": "No README.md file was detected.",72 }73 )74 75 if not has_gitignore:76 issues.append(77 {78 "severity": "low",79 "message": "No .gitignore file was detected.",80 }81 )82 83 return issues84 85 def _format_summary(self, output: IssueOutput) -> str:86 lines = ["Issue analysis:"]87 if output.issues:88 for issue in output.issues:89 lines.append(f"- [{issue.get('severity', 'info')}] {issue.get('message', '')}")90 else:91 lines.append("No obvious issues detected.")92 93 lines.extend(output.notes)94 return "\n".join(lines)