""" Review Generation and Formatting System Creates professional code review comments and suggestions """ import json import datetime from typing import Dict, List, Optional, Any from dataclasses import dataclass from enum import Enum from multi_language_parser import CodeIssue, IssueSeverity, ProgrammingLanguage from ai_analysis_engine import AIInsight, AnalysisType, ConfidenceLevel class CommentType(Enum): SUGGESTION = "suggestion" WARNING = "warning" ERROR = "error" INFO = "info" SECURITY = "security" PERFORMANCE = "performance" @dataclass class ReviewComment: """Structure for generated review comments""" file_path: str line_number: int comment_type: CommentType title: str body: str suggestions: List[str] severity: IssueSeverity confidence: Optional[ConfidenceLevel] code_snippet: Optional[str] tags: List[str] @dataclass class ReviewSummary: """Summary of the code review""" total_issues: int critical_issues: int high_issues: int medium_issues: int low_issues: int security_issues: int performance_issues: int quality_score: float # 0.0 to 10.0 recommendations: List[str] class ReviewGenerator: """Generates professional code review comments""" def __init__(self): self.comment_templates = { CommentType.SECURITY: { "title": "🔒 Security Issue Detected", "body": "A potential security vulnerability has been identified that requires immediate attention.", "tags": ["security", "vulnerability", "critical"] }, CommentType.PERFORMANCE: { "title": "⚡ Performance Optimization Opportunity", "body": "This code can be optimized for better performance.", "tags": ["performance", "optimization", "efficiency"] }, CommentType.WARNING: { "title": "âš ī¸ Code Quality Warning", "body": "This code pattern may lead to maintenance issues.", "tags": ["quality", "maintainability", "warning"] }, CommentType.SUGGESTION: { "title": "💡 Improvement Suggestion", "body": "Consider this approach to improve code quality.", "tags": ["suggestion", "improvement", "best-practice"] }, CommentType.ERROR: { "title": "❌ Code Error", "body": "This code contains an error that should be fixed.", "tags": ["error", "bug", "fix-required"] } } self.severity_emoji = { IssueSeverity.CRITICAL: "🚨", IssueSeverity.HIGH: "âš ī¸", IssueSeverity.MEDIUM: "â„šī¸", IssueSeverity.LOW: "💡" } def generate_review(self, file_path: str, code_issues: List[CodeIssue], ai_insights: List[AIInsight]) -> tuple[List[ReviewComment], ReviewSummary]: """Generate comprehensive code review""" comments = [] # Process static analysis issues for issue in code_issues: comment = self._create_comment_from_issue(issue) comments.append(comment) # Process AI insights for insight in ai_insights: comment = self._create_comment_from_insight(insight, file_path) comments.append(comment) # Sort comments by severity and line number comments.sort(key=lambda c: (self._severity_priority(c.severity), c.line_number)) # Generate summary summary = self._generate_summary(comments) return comments, summary def _create_comment_from_issue(self, issue: CodeIssue) -> ReviewComment: """Create review comment from static analysis issue""" comment_type = self._map_severity_to_comment_type(issue.severity) template = self.comment_templates[comment_type] # Format body with issue details body = f"{template['body']}\n\n**Issue:** {issue.message}\n**Rule:** {issue.rule_id}" if issue.suggestion: body += f"\n**Suggestion:** {issue.suggestion}" return ReviewComment( file_path=issue.file_path, line_number=issue.line_number, comment_type=comment_type, title=template["title"], body=body, suggestions=[issue.suggestion] if issue.suggestion else [], severity=issue.severity, confidence=None, code_snippet=None, tags=template["tags"] ) def _create_comment_from_insight(self, insight: AIInsight, file_path: str) -> ReviewComment: """Create review comment from AI insight""" comment_type = self._map_analysis_to_comment_type(insight.category) template = self.comment_templates[comment_type] # Format body with AI insight details body = f"{template['body']}\n\n**AI Analysis:** {insight.message}" if insight.confidence: body += f"\n**Confidence:** {insight.confidence.value}" if insight.impact_score: body += f"\n**Impact Score:** {insight.impact_score:.2f}" # Add code snippet if available snippet = None if insight.code_snippet: snippet = insight.code_snippet body += f"\n\n**Code Context:**\n```{file_path.split('.')[-1]}\n{snippet}\n```" return ReviewComment( file_path=file_path, line_number=insight.line_range[0] if insight.line_range else 1, comment_type=comment_type, title=template["title"], body=body, suggestions=[insight.suggestion], severity=self._map_confidence_to_severity(insight.confidence), confidence=insight.confidence, code_snippet=snippet, tags=template["tags"] + [insight.category.value] ) def _map_severity_to_comment_type(self, severity: IssueSeverity) -> CommentType: """Map issue severity to comment type""" mapping = { IssueSeverity.CRITICAL: CommentType.ERROR, IssueSeverity.HIGH: CommentType.WARNING, IssueSeverity.MEDIUM: CommentType.SUGGESTION, IssueSeverity.LOW: CommentType.INFO } return mapping.get(severity, CommentType.INFO) def _map_analysis_to_comment_type(self, analysis_type: AnalysisType) -> CommentType: """Map analysis type to comment type""" mapping = { AnalysisType.SECURITY: CommentType.SECURITY, AnalysisType.PERFORMANCE: CommentType.PERFORMANCE, AnalysisType.CODE_QUALITY: CommentType.SUGGESTION, AnalysisType.ARCHITECTURE: CommentType.SUGGESTION, AnalysisType.DOCUMENTATION: CommentType.INFO } return mapping.get(analysis_type, CommentType.INFO) def _map_confidence_to_severity(self, confidence: ConfidenceLevel) -> IssueSeverity: """Map AI confidence to issue severity""" mapping = { ConfidenceLevel.VERY_HIGH: IssueSeverity.HIGH, ConfidenceLevel.HIGH: IssueSeverity.MEDIUM, ConfidenceLevel.MEDIUM: IssueSeverity.LOW, ConfidenceLevel.LOW: IssueSeverity.LOW } return mapping.get(confidence, IssueSeverity.LOW) def _severity_priority(self, severity: IssueSeverity) -> int: """Get priority for sorting (lower number = higher priority)""" priorities = { IssueSeverity.CRITICAL: 1, IssueSeverity.HIGH: 2, IssueSeverity.MEDIUM: 3, IssueSeverity.LOW: 4 } return priorities.get(severity, 5) def _generate_summary(self, comments: List[ReviewComment]) -> ReviewSummary: """Generate review summary statistics""" total_issues = len(comments) # Count by severity critical_issues = sum(1 for c in comments if c.severity == IssueSeverity.CRITICAL) high_issues = sum(1 for c in comments if c.severity == IssueSeverity.HIGH) medium_issues = sum(1 for c in comments if c.severity == IssueSeverity.MEDIUM) low_issues = sum(1 for c in comments if c.severity == IssueSeverity.LOW) # Count by type security_issues = sum(1 for c in comments if c.comment_type == CommentType.SECURITY) performance_issues = sum(1 for c in comments if c.comment_type == CommentType.PERFORMANCE) # Calculate quality score quality_score = self._calculate_quality_score(comments) # Generate recommendations recommendations = self._generate_recommendations(comments) return ReviewSummary( total_issues=total_issues, critical_issues=critical_issues, high_issues=high_issues, medium_issues=medium_issues, low_issues=low_issues, security_issues=security_issues, performance_issues=performance_issues, quality_score=quality_score, recommendations=recommendations ) def _calculate_quality_score(self, comments: List[ReviewComment]) -> float: """Calculate code quality score (0.0 to 10.0)""" if not comments: return 10.0 # Start with perfect score score = 10.0 # Deduct points based on issues for comment in comments: if comment.severity == IssueSeverity.CRITICAL: score -= 2.0 elif comment.severity == IssueSeverity.HIGH: score -= 1.0 elif comment.severity == IssueSeverity.MEDIUM: score -= 0.5 elif comment.severity == IssueSeverity.LOW: score -= 0.2 # Security issues have extra penalty security_penalty = sum(1.5 for c in comments if c.comment_type == CommentType.SECURITY) score -= security_penalty return max(0.0, min(10.0, score)) def _generate_recommendations(self, comments: List[ReviewComment]) -> List[str]: """Generate high-level recommendations""" recommendations = [] # Security recommendations security_comments = [c for c in comments if c.comment_type == CommentType.SECURITY] if security_comments: recommendations.append("🔒 Address security vulnerabilities before merging") # Performance recommendations performance_comments = [c for c in comments if c.comment_type == CommentType.PERFORMANCE] if performance_comments: recommendations.append("⚡ Consider performance optimizations for better efficiency") # Quality recommendations critical_comments = [c for c in comments if c.severity in [IssueSeverity.CRITICAL, IssueSeverity.HIGH]] if critical_comments: recommendations.append("🚨 Fix critical and high-severity issues before merging") # General recommendations if len(comments) > 10: recommendations.append("📝 Consider refactoring to reduce complexity and improve maintainability") if not recommendations: recommendations.append("✅ Code looks good! Ready for review.") return recommendations class GitHubCommentFormatter: """Formats comments for GitHub pull requests""" def __init__(self): self.max_body_length = 65536 # GitHub comment limit def format_comment(self, comment: ReviewComment) -> str: """Format comment for GitHub""" # Add emoji and title formatted = f"## {comment.title}\n\n" # Add body formatted += comment.body # Add suggestions if available if comment.suggestions: formatted += "\n\n**Suggestions:**\n" for i, suggestion in enumerate(comment.suggestions, 1): formatted += f"{i}. {suggestion}\n" # Add tags if comment.tags: tag_string = " ".join(f"`{tag}`" for tag in comment.tags) formatted += f"\n\n**Tags:** {tag_string}" # Add footer formatted += f"\n\n---\n*Generated by AI Code Review Assistant at {datetime.datetime.now().isoformat()}*" # Truncate if too long if len(formatted) > self.max_body_length: formatted = formatted[:self.max_body_length - 100] + "\n\n... (truncated)" return formatted def format_summary_comment(self, summary: ReviewSummary, file_path: str) -> str: """Format summary comment for GitHub""" formatted = f"""## 📊 Code Review Summary for `{file_path}` **Quality Score:** {summary.quality_score:.1f}/10.0 ### 📈 Issue Breakdown - **Total Issues:** {summary.total_issues} - **🚨 Critical:** {summary.critical_issues} - **âš ī¸ High:** {summary.high_issues} - **â„šī¸ Medium:** {summary.medium_issues} - **💡 Low:** {summary.low_issues} ### đŸˇī¸ Issue Categories - **🔒 Security:** {summary.security_issues} - **⚡ Performance:** {summary.performance_issues} ### 💡 Recommendations """ for i, rec in enumerate(summary.recommendations, 1): formatted += f"{i}. {rec}\n" formatted += f"\n---\n*Generated by AI Code Review Assistant at {datetime.datetime.now().isoformat()}*" return formatted # Test implementation def test_review_generation(): """Test the review generation system""" generator = ReviewGenerator() formatter = GitHubCommentFormatter() # Create test issues test_issues = [ CodeIssue( file_path="test.py", line_number=10, column=5, severity=IssueSeverity.HIGH, rule_id="hardcoded_secrets", message="Hardcoded secret detected", suggestion="Use environment variables", language=ProgrammingLanguage.PYTHON ) ] # Create test insights from ai_analysis_engine import AnalysisType, ConfidenceLevel test_insights = [ AIInsight( category=AnalysisType.SECURITY, confidence=ConfidenceLevel.HIGH, message="Authentication logic needs improvement", suggestion="Implement proper OAuth2 flow", code_snippet="def authenticate_user():", line_range=(8, 12), impact_score=0.8 ) ] # Generate review comments, summary = generator.generate_review("test.py", test_issues, test_insights) # Verify comments assert len(comments) > 0 assert summary.total_issues > 0 assert 0.0 <= summary.quality_score <= 10.0 # Test formatting for comment in comments: formatted = formatter.format_comment(comment) assert len(formatted) > 0 assert comment.title in formatted # Test summary formatting summary_formatted = formatter.format_summary_comment(summary, "test.py") assert "Code Review Summary" in summary_formatted assert str(summary.quality_score) in summary_formatted print("✅ Review generation tests passed") return True if __name__ == "__main__": test_review_generation()