Coverage for agentos/marketplace/skills/code-review/code-review.py: 8%

63 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-06 19:15 +0800

1""" 

2code-review — Static code analysis and review. 

3 

4Actions: complexity, functions, imports, todo_fixme, lines 

5""" 

6 

7import re 

8from pathlib import Path 

9from typing import Any 

10 

11 

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}" 

21 

22 if not content.strip(): 

23 return "[code-review] No code provided." 

24 

25 lines = content.split("\n") 

26 

27 if action == "lines": 

28 total = len(lines) 

29 code_lines = len([ln for ln in lines if ln.strip() and not ln.strip().startswith("#")]) 

30 comment_lines = len([ln for ln in lines if ln.strip().startswith("#")]) 

31 blank_lines = len([ln for ln in lines if not ln.strip()]) 

32 return ( 

33 f"Total: {total}, Code: {code_lines}, Comments: {comment_lines}, Blank: {blank_lines}" 

34 ) 

35 

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 

42 

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))}" 

49 

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 ) 

58 

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]) 

78 

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" 

85 

86 

87__all__ = ["run"]