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-04 16:40 +0800

1""" 

2code-review — Static code analysis and review. 

3 

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

5""" 

6 

7import re 

8from typing import Any 

9from pathlib import Path 

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

33 

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 

40 

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

47 

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) 

53 

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

73 

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" 

80 

81 

82__all__ = ["run"]