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 12:29 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-06 12:29 +0800
1"""
2code-review — Static code analysis and review.
4Actions: complexity, functions, imports, todo_fixme, lines
5"""
7import re
8from pathlib import Path
9from typing import Any
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 (
33 f"Total: {total}, Code: {code_lines}, Comments: {comment_lines}, Blank: {blank_lines}"
34 )
36 if action == "functions":
37 funcs = re.findall(r"^\s*(?:def|async def)\s+(\w+)", content, re.MULTILINE)
38 classes = re.findall(r"^\s*class\s+(\w+)", content, re.MULTILINE)
39 result = f"Functions ({len(funcs)}): {', '.join(funcs[:20])}\n"
40 result += f"Classes ({len(classes)}): {', '.join(classes[:10])}"
41 return result
43 if action == "imports":
44 imports = re.findall(r"^(?:import\s+(\S+)|from\s+(\S+)\s+import)", content, re.MULTILINE)
45 deps = set()
46 for m in imports:
47 deps.add(m[0] or m[1])
48 return f"Imports ({len(deps)}): {', '.join(sorted(deps))}"
50 if action == "todo_fixme":
51 todos = re.findall(r".*?(TODO|FIXME|HACK|XXX)[: ]*(.*)", content)
52 if not todos:
53 return "[code-review] No TODOs found."
54 return "TODOs/FIXMEs:\n" + "\n".join(
55 f" L{content[:content.index(t[1])].count(chr(10))+1}: {t[0]}: {t[1].strip()}"
56 for t in todos
57 )
59 if action == "complexity":
60 func_pattern = re.compile(r"^\s*(?:def|async def)\s+(\w+)", re.MULTILINE)
61 funcs = {}
62 current_func = None
63 for i, line in enumerate(lines):
64 m = func_pattern.match(line)
65 if m:
66 current_func = m.group(1)
67 funcs[current_func] = {"start": i, "lines": 0, "branches": 0}
68 elif current_func:
69 funcs[current_func]["lines"] += 1
70 if re.search(r"\b(if|elif|for|while|except|and|or)\b", line):
71 funcs[current_func]["branches"] += 1
72 result = []
73 for name, f in sorted(funcs.items(), key=lambda x: -x[1]["branches"]):
74 score = f["branches"] + 1
75 flag = "HIGH" if score > 10 else ("MED" if score > 5 else "LOW")
76 result.append(f" {name}: {f['lines']} lines, complexity ~{score} ({flag})")
77 return "Function Complexity:\n" + "\n".join(result[:15])
79 # Default: overview
80 total = len(lines)
81 func_count = len(re.findall(r"^\s*(?:def|async def)\s+", content, re.MULTILINE))
82 class_count = len(re.findall(r"^\s*class\s+", content, re.MULTILINE))
83 import_count = len(re.findall(r"^(?:import|from\s+\S+\s+import)", content, re.MULTILINE))
84 return f"[code-review] {total} lines, {func_count} functions, {class_count} classes, {import_count} imports"
87__all__ = ["run"]