AumCoreAI commited on
Commit
def6015
Β·
verified Β·
1 Parent(s): b26909a

Create modules/code_reviewer.py

Browse files
Files changed (1) hide show
  1. modules/code_reviewer.py +743 -0
modules/code_reviewer.py ADDED
@@ -0,0 +1,743 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ AumCore AI - Professional Code Reviewer Module
3
+ Version: 1.0.0
4
+ Author: AumCore AI
5
+ Location: modules/pro_code_reviewer.py
6
+ """
7
+
8
+ import ast
9
+ import re
10
+ import json
11
+ from typing import Dict, List, Tuple, Any, Optional
12
+ from enum import Enum
13
+ from dataclasses import dataclass, asdict
14
+ from datetime import datetime
15
+
16
+ # ==================== COLOR CODING ====================
17
+ class TerminalColors:
18
+ """ANSI color codes for terminal output"""
19
+ RED = '\033[91m'
20
+ GREEN = '\033[92m'
21
+ YELLOW = '\033[93m'
22
+ BLUE = '\033[94m'
23
+ MAGENTA = '\033[95m'
24
+ CYAN = '\033[96m'
25
+ BOLD = '\033[1m'
26
+ UNDERLINE = '\033[4m'
27
+ RESET = '\033[0m'
28
+
29
+ @staticmethod
30
+ def colorize(text: str, color_code: str) -> str:
31
+ """Add color to text for terminal output"""
32
+ return f"{color_code}{text}{TerminalColors.RESET}"
33
+
34
+ @staticmethod
35
+ def html_colorize(text: str, color: str, is_html: bool = True) -> str:
36
+ """Colorize text for HTML or terminal"""
37
+ if is_html:
38
+ return f'<span style="color: {color}; font-weight: bold;">{text}</span>'
39
+ return TerminalColors.colorize(text, getattr(TerminalColors, color.upper()))
40
+
41
+ # ==================== ENUMS & DATA CLASSES ====================
42
+ class IssueCategory(Enum):
43
+ """Categories of code issues"""
44
+ SECURITY = "Security"
45
+ PERFORMANCE = "Performance"
46
+ QUALITY = "Code Quality"
47
+ BEST_PRACTICE = "Best Practice"
48
+ BUG_RISK = "Bug Risk"
49
+ STYLE = "Style Guide"
50
+
51
+ class IssueSeverity(Enum):
52
+ """Severity levels with color coding"""
53
+ CRITICAL = {"level": "CRITICAL", "color": "#ff4444", "emoji": "πŸ”΄", "score_impact": -20}
54
+ HIGH = {"level": "HIGH", "color": "#ff8800", "emoji": "🟠", "score_impact": -15}
55
+ MEDIUM = {"level": "MEDIUM", "color": "#ffbb33", "emoji": "🟑", "score_impact": -10}
56
+ LOW = {"level": "LOW", "color": "#00C851", "emoji": "🟒", "score_impact": -5}
57
+ INFO = {"level": "INFO", "color": "#33b5e5", "emoji": "πŸ”΅", "score_impact": -2}
58
+ POSITIVE = {"level": "POSITIVE", "color": "#2E7D32", "emoji": "βœ…", "score_impact": +5}
59
+
60
+ class CodeLanguage(Enum):
61
+ """Supported programming languages"""
62
+ PYTHON = "Python"
63
+ JAVASCRIPT = "JavaScript"
64
+ TYPESCRIPT = "TypeScript"
65
+ JAVA = "Java"
66
+ CPP = "C++"
67
+ GO = "Go"
68
+ RUST = "Rust"
69
+ SQL = "SQL"
70
+ HTML = "HTML"
71
+ CSS = "CSS"
72
+
73
+ @dataclass
74
+ class CodeIssue:
75
+ """Detailed code issue"""
76
+ id: str
77
+ line: int
78
+ column: int
79
+ category: IssueCategory
80
+ severity: IssueSeverity
81
+ title: str
82
+ description: str
83
+ suggestion: str
84
+ code_snippet: str
85
+ rule_id: str
86
+ confidence: float # 0.0 to 1.0
87
+
88
+ def to_dict(self) -> Dict:
89
+ """Convert to dictionary for JSON serialization"""
90
+ data = asdict(self)
91
+ data["category"] = self.category.value
92
+ data["severity"] = {
93
+ "level": self.severity.value["level"],
94
+ "color": self.severity.value["color"],
95
+ "emoji": self.severity.value["emoji"],
96
+ "score_impact": self.severity.value["score_impact"]
97
+ }
98
+ return data
99
+
100
+ @dataclass
101
+ class CodeReviewReport:
102
+ """Complete code review report"""
103
+ review_id: str
104
+ timestamp: str
105
+ language: CodeLanguage
106
+ overall_score: int # 0-100
107
+ grade: str # A, B, C, D, F
108
+ issues: List[CodeIssue]
109
+ metrics: Dict[str, Any]
110
+ summary: Dict[str, Any]
111
+ html_report: str
112
+ terminal_report: str
113
+
114
+ def to_dict(self) -> Dict:
115
+ """Convert to dictionary"""
116
+ return {
117
+ "review_id": self.review_id,
118
+ "timestamp": self.timestamp,
119
+ "language": self.language.value,
120
+ "overall_score": self.overall_score,
121
+ "grade": self.grade,
122
+ "issues": [issue.to_dict() for issue in self.issues],
123
+ "metrics": self.metrics,
124
+ "summary": self.summary,
125
+ "html_report": self.html_report,
126
+ "terminal_report": self.terminal_report
127
+ }
128
+
129
+ # ==================== MAIN REVIEWER CLASS ====================
130
+ class AumCoreProCodeReviewer:
131
+ """
132
+ Professional Code Review System with Color-Coded Output
133
+ Features: Security scanning, performance analysis, quality metrics
134
+ """
135
+
136
+ def __init__(self):
137
+ self._rules = self._load_rules()
138
+ self._patterns = self._load_patterns()
139
+ self.review_count = 0
140
+
141
+ def _load_rules(self) -> Dict:
142
+ """Load comprehensive review rules"""
143
+ return {
144
+ "PY001": {
145
+ "title": "Avoid exec() function",
146
+ "description": "The exec() function can execute arbitrary code and is a security risk.",
147
+ "category": IssueCategory.SECURITY,
148
+ "severity": IssueSeverity.CRITICAL,
149
+ "pattern": r"exec\(",
150
+ "suggestion": "Use safer alternatives like ast.literal_eval() or restructure code.",
151
+ "languages": [CodeLanguage.PYTHON]
152
+ },
153
+ "PY002": {
154
+ "title": "Bare except clause",
155
+ "description": "Catching all exceptions can hide bugs and make debugging difficult.",
156
+ "category": IssueCategory.BUG_RISK,
157
+ "severity": IssueSeverity.MEDIUM,
158
+ "pattern": r"except:",
159
+ "suggestion": "Specify exception types: except ValueError:, except Exception:",
160
+ "languages": [CodeLanguage.PYTHON]
161
+ },
162
+ "PY003": {
163
+ "title": "Use enumerate() for iteration",
164
+ "description": "Using range(len()) is less readable and efficient than enumerate().",
165
+ "category": IssueCategory.PERFORMANCE,
166
+ "severity": IssueSeverity.LOW,
167
+ "pattern": r"for.*in.*range\(len\(",
168
+ "suggestion": "Replace with: for index, item in enumerate(collection):",
169
+ "languages": [CodeLanguage.PYTHON]
170
+ },
171
+ "PY004": {
172
+ "title": "Type hints missing",
173
+ "description": "Function lacks type hints, reducing code clarity and IDE support.",
174
+ "category": IssueCategory.QUALITY,
175
+ "severity": IssueSeverity.INFO,
176
+ "pattern": r"def \w+\([^)]*\):",
177
+ "suggestion": "Add type hints: def function(param: type) -> return_type:",
178
+ "languages": [CodeLanguage.PYTHON]
179
+ },
180
+ "PY005": {
181
+ "title": "Docstring missing",
182
+ "description": "Function or class lacks documentation.",
183
+ "category": IssueCategory.BEST_PRACTICE,
184
+ "severity": IssueSeverity.LOW,
185
+ "pattern": r"(def|class) \w+",
186
+ "suggestion": "Add Google-style or Numpy-style docstring.",
187
+ "languages": [CodeLanguage.PYTHON]
188
+ },
189
+ "JS001": {
190
+ "title": "eval() usage",
191
+ "description": "eval() executes arbitrary code and is a major security risk.",
192
+ "category": IssueCategory.SECURITY,
193
+ "severity": IssueSeverity.CRITICAL,
194
+ "pattern": r"eval\(",
195
+ "suggestion": "Use JSON.parse() for JSON or Function constructor with caution.",
196
+ "languages": [CodeLanguage.JAVASCRIPT]
197
+ },
198
+ "JS002": {
199
+ "title": "Use const/let instead of var",
200
+ "description": "var has function scope and can cause unexpected behavior.",
201
+ "category": IssueCategory.BEST_PRACTICE,
202
+ "severity": IssueSeverity.MEDIUM,
203
+ "pattern": r"var ",
204
+ "suggestion": "Use const for constants, let for variables that change.",
205
+ "languages": [CodeLanguage.JAVASCRIPT]
206
+ },
207
+ "SQL001": {
208
+ "title": "SQL Injection risk",
209
+ "description": "String concatenation in SQL queries can lead to injection attacks.",
210
+ "category": IssueCategory.SECURITY,
211
+ "severity": IssueSeverity.CRITICAL,
212
+ "pattern": r"'.*\+.*SELECT",
213
+ "suggestion": "Use parameterized queries or ORM with built-in protection.",
214
+ "languages": [CodeLanguage.SQL]
215
+ }
216
+ }
217
+
218
+ def _load_patterns(self) -> Dict:
219
+ """Load regex patterns for quick scanning"""
220
+ patterns = {}
221
+ for rule_id, rule in self._rules.items():
222
+ patterns[rule_id] = re.compile(rule["pattern"], re.IGNORECASE | re.MULTILINE)
223
+ return patterns
224
+
225
+ def review_code(self, code: str, language: CodeLanguage = CodeLanguage.PYTHON) -> CodeReviewReport:
226
+ """
227
+ Perform comprehensive code review
228
+
229
+ Args:
230
+ code: Source code to review
231
+ language: Programming language
232
+
233
+ Returns:
234
+ Complete review report with color-coded output
235
+ """
236
+ self.review_count += 1
237
+ review_id = f"REV-{self.review_count:04d}-{datetime.now().strftime('%Y%m%d')}"
238
+
239
+ # Parse code and find issues
240
+ issues = self._analyze_code(code, language)
241
+
242
+ # Calculate metrics
243
+ metrics = self._calculate_metrics(code, issues, language)
244
+
245
+ # Generate score and grade
246
+ overall_score = self._calculate_score(issues)
247
+ grade = self._get_grade(overall_score)
248
+
249
+ # Generate reports
250
+ html_report = self._generate_html_report(review_id, code, issues, metrics, overall_score, grade, language)
251
+ terminal_report = self._generate_terminal_report(review_id, issues, metrics, overall_score, grade)
252
+
253
+ # Create summary
254
+ summary = {
255
+ "total_lines": len(code.split('\n')),
256
+ "total_issues": len(issues),
257
+ "critical_issues": len([i for i in issues if i.severity == IssueSeverity.CRITICAL]),
258
+ "security_issues": len([i for i in issues if i.category == IssueCategory.SECURITY]),
259
+ "performance_issues": len([i for i in issues if i.category == IssueCategory.PERFORMANCE]),
260
+ }
261
+
262
+ return CodeReviewReport(
263
+ review_id=review_id,
264
+ timestamp=datetime.now().isoformat(),
265
+ language=language,
266
+ overall_score=overall_score,
267
+ grade=grade,
268
+ issues=issues,
269
+ metrics=metrics,
270
+ summary=summary,
271
+ html_report=html_report,
272
+ terminal_report=terminal_report
273
+ )
274
+
275
+ def _analyze_code(self, code: str, language: CodeLanguage) -> List[CodeIssue]:
276
+ """Analyze code and return issues"""
277
+ issues = []
278
+ lines = code.split('\n')
279
+
280
+ # Apply language-specific rules
281
+ for rule_id, rule in self._rules.items():
282
+ if language not in rule["languages"]:
283
+ continue
284
+
285
+ pattern = self._patterns[rule_id]
286
+ for line_num, line in enumerate(lines, 1):
287
+ if pattern.search(line):
288
+ # Find column position
289
+ match = pattern.search(line)
290
+ column = match.start() + 1 if match else 1
291
+
292
+ issue = CodeIssue(
293
+ id=f"{rule_id}-{line_num:03d}",
294
+ line=line_num,
295
+ column=column,
296
+ category=rule["category"],
297
+ severity=rule["severity"],
298
+ title=rule["title"],
299
+ description=rule["description"],
300
+ suggestion=rule["suggestion"],
301
+ code_snippet=line.strip(),
302
+ rule_id=rule_id,
303
+ confidence=0.9
304
+ )
305
+ issues.append(issue)
306
+
307
+ # AST-based analysis for Python
308
+ if language == CodeLanguage.PYTHON:
309
+ issues.extend(self._analyze_python_ast(code))
310
+
311
+ return sorted(issues, key=lambda x: (x.severity.value["score_impact"], x.line))
312
+
313
+ def _analyze_python_ast(self, code: str) -> List[CodeIssue]:
314
+ """Python-specific AST analysis"""
315
+ issues = []
316
+
317
+ try:
318
+ tree = ast.parse(code)
319
+
320
+ for node in ast.walk(tree):
321
+ # Check for complex functions
322
+ if isinstance(node, ast.FunctionDef):
323
+ complexity = self._calculate_cyclomatic_complexity(node)
324
+ if complexity > 10:
325
+ issues.append(CodeIssue(
326
+ id=f"COMPLEX-{node.lineno:03d}",
327
+ line=node.lineno,
328
+ column=node.col_offset,
329
+ category=IssueCategory.PERFORMANCE,
330
+ severity=IssueSeverity.MEDIUM,
331
+ title="High cyclomatic complexity",
332
+ description=f"Function '{node.name}' has complexity score of {complexity}",
333
+ suggestion="Break into smaller functions with single responsibility",
334
+ code_snippet=node.name,
335
+ rule_id="AST001",
336
+ confidence=0.8
337
+ ))
338
+
339
+ # Check for magic numbers
340
+ if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
341
+ if abs(node.value) > 1000 or (0 < abs(node.value) < 0.001):
342
+ issues.append(CodeIssue(
343
+ id=f"MAGIC-{node.lineno:03d}",
344
+ line=node.lineno,
345
+ column=node.col_offset,
346
+ category=IssueCategory.BEST_PRACTICE,
347
+ severity=IssueSeverity.LOW,
348
+ title="Magic number detected",
349
+ description=f"Consider replacing {node.value} with named constant",
350
+ suggestion="Define constant with descriptive name",
351
+ code_snippet=str(node.value),
352
+ rule_id="AST002",
353
+ confidence=0.7
354
+ ))
355
+
356
+ except SyntaxError:
357
+ # Syntax errors caught by pattern matching
358
+ pass
359
+
360
+ return issues
361
+
362
+ def _calculate_cyclomatic_complexity(self, node: ast.AST) -> int:
363
+ """Calculate McCabe cyclomatic complexity"""
364
+ complexity = 1
365
+
366
+ for child in ast.walk(node):
367
+ if isinstance(child, (ast.If, ast.While, ast.For, ast.Try, ast.ExceptHandler)):
368
+ complexity += 1
369
+ elif isinstance(child, ast.BoolOp):
370
+ complexity += len(child.values) - 1
371
+
372
+ return complexity
373
+
374
+ def _calculate_metrics(self, code: str, issues: List[CodeIssue], language: CodeLanguage) -> Dict:
375
+ """Calculate code metrics"""
376
+ lines = code.split('\n')
377
+
378
+ return {
379
+ "lines_of_code": len(lines),
380
+ "non_empty_lines": len([l for l in lines if l.strip()]),
381
+ "comment_lines": len([l for l in lines if l.strip().startswith('#')]),
382
+ "functions_count": code.count('def '),
383
+ "classes_count": code.count('class '),
384
+ "imports_count": code.count('import '),
385
+ "average_line_length": sum(len(l) for l in lines) / len(lines) if lines else 0,
386
+ "issue_density": len(issues) / len(lines) if lines else 0,
387
+ }
388
+
389
+ def _calculate_score(self, issues: List[CodeIssue]) -> int:
390
+ """Calculate overall code quality score (0-100)"""
391
+ score = 100
392
+
393
+ for issue in issues:
394
+ score += issue.severity.value["score_impact"]
395
+
396
+ return max(0, min(100, score))
397
+
398
+ def _get_grade(self, score: int) -> str:
399
+ """Convert score to letter grade"""
400
+ if score >= 90: return "A"
401
+ if score >= 80: return "B"
402
+ if score >= 70: return "C"
403
+ if score >= 60: return "D"
404
+ return "F"
405
+
406
+ def _generate_html_report(self, review_id: str, code: str, issues: List[CodeIssue],
407
+ metrics: Dict, score: int, grade: str, language: CodeLanguage) -> str:
408
+ """Generate HTML color-coded report"""
409
+
410
+ # Color-coded severity badges
411
+ severity_html = ""
412
+ for severity in IssueSeverity:
413
+ count = len([i for i in issues if i.severity == severity])
414
+ if count > 0:
415
+ severity_html += f'''
416
+ <span style="background-color: {severity.value['color']};
417
+ color: white; padding: 4px 8px; border-radius: 4px;
418
+ margin: 0 5px;">
419
+ {severity.value['emoji']} {severity.value['level']}: {count}
420
+ </span>
421
+ '''
422
+
423
+ # Issues table
424
+ issues_html = ""
425
+ for issue in issues:
426
+ issues_html += f'''
427
+ <tr style="border-bottom: 1px solid #eee;">
428
+ <td style="padding: 8px;">
429
+ <span style="color: {issue.severity.value['color']}; font-weight: bold;">
430
+ {issue.severity.value['emoji']} {issue.severity.value['level']}
431
+ </span>
432
+ </td>
433
+ <td style="padding: 8px;">{issue.category.value}</td>
434
+ <td style="padding: 8px;">Line {issue.line}</td>
435
+ <td style="padding: 8px;"><strong>{issue.title}</strong></td>
436
+ <td style="padding: 8px;">{issue.suggestion}</td>
437
+ </tr>
438
+ '''
439
+
440
+ # Score with color
441
+ score_color = "#4CAF50" if score >= 80 else "#FF9800" if score >= 60 else "#F44336"
442
+
443
+ html = f'''
444
+ <!DOCTYPE html>
445
+ <html>
446
+ <head>
447
+ <title>AumCore AI Code Review - {review_id}</title>
448
+ <style>
449
+ body {{ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
450
+ margin: 20px; background: #f5f5f5; }}
451
+ .container {{ max-width: 1200px; margin: 0 auto; background: white;
452
+ padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
453
+ .header {{ text-align: center; margin-bottom: 30px; padding-bottom: 20px;
454
+ border-bottom: 2px solid #e0e0e0; }}
455
+ .score-circle {{
456
+ display: inline-block; width: 100px; height: 100px;
457
+ border-radius: 50%; background: {score_color};
458
+ color: white; line-height: 100px; font-size: 36px;
459
+ font-weight: bold; margin: 10px;
460
+ }}
461
+ .metrics-grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
462
+ gap: 15px; margin: 20px 0; }}
463
+ .metric-card {{ background: #f8f9fa; padding: 15px; border-radius: 8px;
464
+ border-left: 4px solid #2196F3; }}
465
+ table {{ width: 100%; border-collapse: collapse; margin: 20px 0; }}
466
+ th {{ background: #2c3e50; color: white; padding: 12px; text-align: left; }}
467
+ .highlight {{ background: #fffde7; padding: 2px 4px; border-radius: 3px;
468
+ font-family: 'Courier New', monospace; }}
469
+ </style>
470
+ </head>
471
+ <body>
472
+ <div class="container">
473
+ <div class="header">
474
+ <h1 style="color: #2c3e50;">πŸ§‘β€πŸ’» AumCore AI Code Review</h1>
475
+ <p style="color: #7f8c8d;">Review ID: {review_id} | Language: {language.value} | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
476
+
477
+ <div style="margin: 20px 0;">
478
+ <div class="score-circle">{score}</div>
479
+ <div style="display: inline-block; vertical-align: top; margin-left: 20px;">
480
+ <h2 style="margin: 0; color: {score_color};">Grade: {grade}</h2>
481
+ <p style="color: #666;">Overall Code Quality Score</p>
482
+ </div>
483
+ </div>
484
+
485
+ <div style="margin: 20px 0;">
486
+ {severity_html}
487
+ </div>
488
+ </div>
489
+
490
+ <h3>πŸ“Š Code Metrics</h3>
491
+ <div class="metrics-grid">
492
+ <div class="metric-card">
493
+ <div style="font-size: 24px; font-weight: bold; color: #2196F3;">
494
+ {metrics['lines_of_code']}
495
+ </div>
496
+ <div style="color: #666;">Lines of Code</div>
497
+ </div>
498
+ <div class="metric-card">
499
+ <div style="font-size: 24px; font-weight: bold; color: #4CAF50;">
500
+ {metrics['functions_count']}
501
+ </div>
502
+ <div style="color: #666;">Functions</div>
503
+ </div>
504
+ <div class="metric-card">
505
+ <div style="font-size: 24px; font-weight: bold; color: #9C27B0;">
506
+ {len(issues)}
507
+ </div>
508
+ <div style="color: #666;">Issues Found</div>
509
+ </div>
510
+ <div class="metric-card">
511
+ <div style="font-size: 24px; font-weight: bold; color: #FF9800;">
512
+ {len([i for i in issues if i.category == IssueCategory.SECURITY])}
513
+ </div>
514
+ <div style="color: #666;">Security Issues</div>
515
+ </div>
516
+ </div>
517
+
518
+ <h3>πŸ” Issues Found ({len(issues)})</h3>
519
+ <table>
520
+ <thead>
521
+ <tr>
522
+ <th>Severity</th>
523
+ <th>Category</th>
524
+ <th>Location</th>
525
+ <th>Issue</th>
526
+ <th>Suggestion</th>
527
+ </tr>
528
+ </thead>
529
+ <tbody>
530
+ {issues_html}
531
+ </tbody>
532
+ </table>
533
+
534
+ <div style="margin-top: 30px; padding: 20px; background: #e8f5e8; border-radius: 8px;">
535
+ <h3 style="color: #2E7D32;">πŸ’‘ Recommendations</h3>
536
+ <ul>
537
+ <li>Fix all <strong>Critical</strong> and <strong>High</strong> severity issues first</li>
538
+ <li>Review security issues carefully before deployment</li>
539
+ <li>Consider adding tests for complex functions</li>
540
+ <li>Add documentation for public APIs</li>
541
+ </ul>
542
+ </div>
543
+
544
+ <div style="margin-top: 30px; text-align: center; color: #7f8c8d; font-size: 14px;">
545
+ <p>Generated by AumCore AI Professional Code Reviewer β€’ {datetime.now().strftime('%Y-%m-%d')}</p>
546
+ </div>
547
+ </div>
548
+ </body>
549
+ </html>
550
+ '''
551
+
552
+ return html
553
+
554
+ def _generate_terminal_report(self, review_id: str, issues: List[CodeIssue],
555
+ metrics: Dict, score: int, grade: str) -> str:
556
+ """Generate terminal color-coded report"""
557
+
558
+ report = []
559
+ report.append(TerminalColors.BOLD + "=" * 70 + TerminalColors.RESET)
560
+ report.append(TerminalColors.CYAN + TerminalColors.BOLD +
561
+ f"πŸ§‘β€πŸ’» AUMCORE AI CODE REVIEW - {review_id}" + TerminalColors.RESET)
562
+ report.append(TerminalColors.BOLD + "=" * 70 + TerminalColors.RESET)
563
+
564
+ # Score section
565
+ score_color = TerminalColors.GREEN if score >= 80 else TerminalColors.YELLOW if score >= 60 else TerminalColors.RED
566
+ report.append(f"\n{TerminalColors.BOLD}Overall Score:{TerminalColors.RESET}")
567
+ report.append(f" {score_color}{score}/100 {TerminalColors.RESET}(Grade: {grade})")
568
+
569
+ # Metrics
570
+ report.append(f"\n{TerminalColors.BOLD}Code Metrics:{TerminalColors.RESET}")
571
+ report.append(f" πŸ“ Lines of Code: {metrics['lines_of_code']}")
572
+ report.append(f" πŸ“Š Issue Density: {metrics['issue_density']:.2f} issues/line")
573
+ report.append(f" πŸ”§ Functions: {metrics['functions_count']}")
574
+
575
+ # Issues by severity
576
+ report.append(f"\n{TerminalColors.BOLD}Issues by Severity:{TerminalColors.RESET}")
577
+ for severity in IssueSeverity:
578
+ count = len([i for i in issues if i.severity == severity])
579
+ if count > 0:
580
+ color = TerminalColors.RED if severity == IssueSeverity.CRITICAL else \
581
+ TerminalColors.YELLOW if severity in [IssueSeverity.HIGH, IssueSeverity.MEDIUM] else \
582
+ TerminalColors.GREEN
583
+ report.append(f" {severity.value['emoji']} {color}{severity.value['level']}: {count}{TerminalColors.RESET}")
584
+
585
+ # Detailed issues
586
+ if issues:
587
+ report.append(f"\n{TerminalColors.BOLD}Detailed Issues:{TerminalColors.RESET}")
588
+ for issue in issues[:10]: # Show first 10 issues
589
+ color = TerminalColors.RED if issue.severity == IssueSeverity.CRITICAL else \
590
+ TerminalColors.YELLOW if issue.severity in [IssueSeverity.HIGH, IssueSeverity.MEDIUM] else \
591
+ TerminalColors.GREEN
592
+ report.append(f"\n {color}{issue.severity.value['emoji']} Line {issue.line}: {issue.title}{TerminalColors.RESET}")
593
+ report.append(f" {TerminalColors.BLUE}Category:{TerminalColors.RESET} {issue.category.value}")
594
+ report.append(f" {TerminalColors.MAGENTA}Suggestion:{TerminalColors.RESET} {issue.suggestion}")
595
+
596
+ report.append(f"\n{TerminalColors.BOLD}=" * 70 + TerminalColors.RESET)
597
+ report.append(f"{TerminalColors.GREEN}βœ… Review complete. {len(issues)} issues found.{TerminalColors.RESET}")
598
+
599
+ return "\n".join(report)
600
+
601
+ # ==================== FASTAPI MODULE REGISTRATION ====================
602
+ def register_module(app, client, username):
603
+ """Register code reviewer module with FastAPI app"""
604
+ from fastapi import APIRouter, HTTPException
605
+
606
+ router = APIRouter(prefix="/system")
607
+ reviewer = AumCoreProCodeReviewer()
608
+
609
+ @router.post("/code/review/advanced")
610
+ async def review_code_advanced(
611
+ code: str = "",
612
+ language: str = "python",
613
+ format: str = "html" # html, terminal, json
614
+ ):
615
+ """
616
+ Advanced code review with color-coded output
617
+
618
+ Args:
619
+ code: Source code to review
620
+ language: Programming language
621
+ format: Output format (html, terminal, json)
622
+ """
623
+ try:
624
+ if not code.strip():
625
+ return {"success": False, "error": "No code provided"}
626
+
627
+ # Map language string to enum
628
+ lang_map = {
629
+ "python": CodeLanguage.PYTHON,
630
+ "javascript": CodeLanguage.JAVASCRIPT,
631
+ "typescript": CodeLanguage.TYPESCRIPT,
632
+ "java": CodeLanguage.JAVA,
633
+ "cpp": CodeLanguage.CPP,
634
+ "go": CodeLanguage.GO,
635
+ "rust": CodeLanguage.RUST,
636
+ "sql": CodeLanguage.SQL,
637
+ "html": CodeLanguage.HTML,
638
+ "css": CodeLanguage.CSS,
639
+ }
640
+
641
+ lang_enum = lang_map.get(language.lower(), CodeLanguage.PYTHON)
642
+
643
+ # Perform review
644
+ report = reviewer.review_code(code, lang_enum)
645
+
646
+ # Return requested format
647
+ if format == "json":
648
+ return {
649
+ "success": True,
650
+ "review_id": report.review_id,
651
+ "data": report.to_dict()
652
+ }
653
+ elif format == "terminal":
654
+ return {
655
+ "success": True,
656
+ "review_id": report.review_id,
657
+ "report": report.terminal_report
658
+ }
659
+ else: # html
660
+ return {
661
+ "success": True,
662
+ "review_id": report.review_id,
663
+ "report": report.html_report
664
+ }
665
+
666
+ except Exception as e:
667
+ raise HTTPException(status_code=500, detail=f"Review failed: {str(e)}")
668
+
669
+ @router.get("/code/review/simple")
670
+ async def review_code_simple(code: str = "", lang: str = "python"):
671
+ """Simple code review endpoint"""
672
+ try:
673
+ if not code.strip():
674
+ return {"success": False, "error": "No code provided"}
675
+
676
+ reviewer = AumCoreProCodeReviewer()
677
+ lang_enum = CodeLanguage.PYTHON if lang == "python" else CodeLanguage.JAVASCRIPT
678
+ report = reviewer.review_code(code, lang_enum)
679
+
680
+ return {
681
+ "success": True,
682
+ "score": report.overall_score,
683
+ "grade": report.grade,
684
+ "total_issues": len(report.issues),
685
+ "critical_issues": len([i for i in report.issues if i.severity == IssueSeverity.CRITICAL]),
686
+ "issues": [issue.to_dict() for issue in report.issues[:5]] # First 5 issues
687
+ }
688
+
689
+ except Exception as e:
690
+ return {"success": False, "error": str(e)}
691
+
692
+ app.include_router(router)
693
+
694
+ print(f"{TerminalColors.GREEN}βœ… Professional Code Reviewer module registered with FastAPI{TerminalColors.RESET}")
695
+ print(f"{TerminalColors.CYAN} Endpoints:{TerminalColors.RESET}")
696
+ print(f"{TerminalColors.BLUE} β€’ POST /system/code/review/advanced{TerminalColors.RESET}")
697
+ print(f"{TerminalColors.BLUE} β€’ GET /system/code/review/simple{TerminalColors.RESET}")
698
+
699
+ return {
700
+ "module": "pro_code_reviewer",
701
+ "version": "1.0.0",
702
+ "status": "registered",
703
+ "description": "Professional color-coded code review system"
704
+ }
705
+
706
+ # ==================== TEST FUNCTION ====================
707
+ def test_reviewer():
708
+ """Test the code reviewer"""
709
+ test_code = """
710
+ import os
711
+
712
+ def process_data(data):
713
+ for i in range(len(data)):
714
+ print(data[i])
715
+
716
+ password = "secret123"
717
+
718
+ try:
719
+ result = eval("2 + 2")
720
+ except:
721
+ print("Error")
722
+
723
+ return result
724
+
725
+ class User:
726
+ def __init__(self, name):
727
+ self.name = name
728
+ """
729
+
730
+ reviewer = AumCoreProCodeReviewer()
731
+ report = reviewer.review_code(test_code, CodeLanguage.PYTHON)
732
+
733
+ print(report.terminal_report)
734
+ print("\n" + "="*70)
735
+ print(f"HTML Report length: {len(report.html_report)} characters")
736
+ print(f"Total issues found: {len(report.issues)}")
737
+
738
+ return report
739
+
740
+ # Run test if executed directly
741
+ if __name__ == "__main__":
742
+ print("Testing AumCore Pro Code Reviewer...\n")
743
+ test_reviewer()