Spaces:
Sleeping
Sleeping
File size: 1,835 Bytes
b76a728 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import ast
from typing import List, Dict
class CodeSmellVisitor(ast.NodeVisitor):
def __init__(self):
self.issues = []
def visit_FunctionDef(self, node):
"""Check for functions with too many arguments (Code Smell)"""
if len(node.args.args) > 5:
self.issues.append({
"line": node.lineno,
"type": "Complexity",
"message": f"Function '{node.name}' has too many arguments ({len(node.args.args)}). Max is 5."
})
# Check for mutable default arguments (e.g., def foo(l=[]))
# This is a classic Python 'gotcha' interview question
for default in node.args.defaults:
if isinstance(default, (ast.List, ast.Dict, ast.Set)):
self.issues.append({
"line": node.lineno,
"type": "Bug Risk",
"message": f"Function '{node.name}' uses a mutable default argument. This persists state across calls!"
})
# Continue walking through the children of this node
self.generic_visit(node)
def visit_Call(self, node):
"""Check for dangerous function calls like eval()"""
if isinstance(node.func, ast.Name) and node.func.id == 'eval':
self.issues.append({
"line": node.lineno,
"type": "Security",
"message": "Use of 'eval()' detected. This is a major security risk."
})
self.generic_visit(node)
def analyze_code(code_content: str) -> List[Dict]:
try:
tree = ast.parse(code_content)
visitor = CodeSmellVisitor()
visitor.visit(tree)
return visitor.issues
except SyntaxError as e:
return [{"line": e.lineno, "type": "Syntax Error", "message": str(e)}]
|