Coverage for agentos/marketplace/skills/code-review/code-review.py: 54%
63 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-06 08:01 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-06 08:01 +0800
1"""
2code-review — Static code analysis and review.
4Actions: complexity, functions, imports, todo_fixme, lines
5"""
7import re
8from typing import Any
9from pathlib import Path
12def run(action: str = "overview", file_path: str = "", code: str = "", **kwargs: Any) -> str:
13 content = code
14 if file_path:
15 try:
16 content = Path(file_path).read_text(encoding="utf-8")
17 except FileNotFoundError:
18 return f"[code-review] File not found: {file_path}"
19 except Exception as e:
20 return f"[code-review] Error: {e}"
22 if not content.strip():
23 return "[code-review] No code provided."
25 lines = content.split("\n")
27 if action == "lines":
28 total = len(lines)
29 code_lines = len([l for l in lines if l.strip() and not l.strip().startswith("#")])
30 comment_lines = len([l for l in lines if l.strip().startswith("#")])
31 blank_lines = len([l for l in lines if not l.strip()])
32 return f"Total: {total}, Code: {code_lines}, Comments: {comment_lines}, Blank: {blank_lines}"
34 if action == "functions":
35 funcs = re.findall(r'^\s*(?:def|async def)\s+(\w+)', content, re.MULTILINE)
36 classes = re.findall(r'^\s*class\s+(\w+)', content, re.MULTILINE)
37 result = f"Functions ({len(funcs)}): {', '.join(funcs[:20])}\n"
38 result += f"Classes ({len(classes)}): {', '.join(classes[:10])}"
39 return result
41 if action == "imports":
42 imports = re.findall(r'^(?:import\s+(\S+)|from\s+(\S+)\s+import)', content, re.MULTILINE)
43 deps = set()
44 for m in imports:
45 deps.add(m[0] or m[1])
46 return f"Imports ({len(deps)}): {', '.join(sorted(deps))}"
48 if action == "todo_fixme":
49 todos = re.findall(r'.*?(TODO|FIXME|HACK|XXX)[: ]*(.*)', content)
50 if not todos:
51 return "[code-review] No TODOs found."
52 return "TODOs/FIXMEs:\n" + "\n".join(f" L{content[:content.index(t[1])].count(chr(10))+1}: {t[0]}: {t[1].strip()}" for t in todos)
54 if action == "complexity":
55 func_pattern = re.compile(r'^\s*(?:def|async def)\s+(\w+)', re.MULTILINE)
56 funcs = {}
57 current_func = None
58 for i, line in enumerate(lines):
59 m = func_pattern.match(line)
60 if m:
61 current_func = m.group(1)
62 funcs[current_func] = {"start": i, "lines": 0, "branches": 0}
63 elif current_func:
64 funcs[current_func]["lines"] += 1
65 if re.search(r'\b(if|elif|for|while|except|and|or)\b', line):
66 funcs[current_func]["branches"] += 1
67 result = []
68 for name, f in sorted(funcs.items(), key=lambda x: -x[1]["branches"]):
69 score = f["branches"] + 1
70 flag = "HIGH" if score > 10 else ("MED" if score > 5 else "LOW")
71 result.append(f" {name}: {f['lines']} lines, complexity ~{score} ({flag})")
72 return "Function Complexity:\n" + "\n".join(result[:15])
74 # Default: overview
75 total = len(lines)
76 func_count = len(re.findall(r'^\s*(?:def|async def)\s+', content, re.MULTILINE))
77 class_count = len(re.findall(r'^\s*class\s+', content, re.MULTILINE))
78 import_count = len(re.findall(r'^(?:import|from\s+\S+\s+import)', content, re.MULTILINE))
79 return f"[code-review] {total} lines, {func_count} functions, {class_count} classes, {import_count} imports"
82__all__ = ["run"]