208 lines
No EOL
8.4 KiB
Python
208 lines
No EOL
8.4 KiB
Python
from typing import Dict, Any, Optional
|
|
import logging
|
|
import ast
|
|
import re
|
|
|
|
from modules.methods.methodBase import MethodBase, MethodResult, action
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class MethodCoder(MethodBase):
|
|
"""Coder method implementation for code operations"""
|
|
|
|
def __init__(self, serviceContainer: Any):
|
|
super().__init__(serviceContainer)
|
|
self.name = "coder"
|
|
self.description = "Handle code operations like analysis, generation, and refactoring"
|
|
|
|
@action
|
|
async def analyze(self, parameters: Dict[str, Any], authData: Optional[Dict[str, Any]] = None) -> MethodResult:
|
|
"""Analyze code structure and quality"""
|
|
try:
|
|
code = parameters["code"]
|
|
language = parameters.get("language", "python")
|
|
metrics = parameters.get("metrics", ["complexity", "style", "documentation"])
|
|
|
|
analysis = {}
|
|
|
|
if language.lower() == "python":
|
|
# Parse Python code
|
|
try:
|
|
tree = ast.parse(code)
|
|
|
|
# Calculate basic metrics
|
|
analysis["metrics"] = {
|
|
"lines": len(code.splitlines()),
|
|
"classes": len([node for node in ast.walk(tree) if isinstance(node, ast.ClassDef)]),
|
|
"functions": len([node for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)]),
|
|
"imports": len([node for node in ast.walk(tree) if isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom)])
|
|
}
|
|
|
|
# Check for common issues
|
|
analysis["issues"] = []
|
|
|
|
# Check for missing docstrings
|
|
if "documentation" in metrics:
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, (ast.ClassDef, ast.FunctionDef)) and not ast.get_docstring(node):
|
|
analysis["issues"].append({
|
|
"type": "missing_docstring",
|
|
"line": node.lineno,
|
|
"name": node.name
|
|
})
|
|
|
|
# Check for long functions
|
|
if "complexity" in metrics:
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, ast.FunctionDef):
|
|
bodyLines = len(node.body)
|
|
if bodyLines > 20: # Arbitrary threshold
|
|
analysis["issues"].append({
|
|
"type": "long_function",
|
|
"line": node.lineno,
|
|
"name": node.name,
|
|
"lines": bodyLines
|
|
})
|
|
|
|
# Check for style issues
|
|
if "style" in metrics:
|
|
# Check line length
|
|
for i, line in enumerate(code.splitlines(), 1):
|
|
if len(line) > 100: # PEP 8 recommendation
|
|
analysis["issues"].append({
|
|
"type": "line_too_long",
|
|
"line": i,
|
|
"length": len(line)
|
|
})
|
|
|
|
# Check for mixed tabs and spaces
|
|
if "\t" in code and " " in code:
|
|
analysis["issues"].append({
|
|
"type": "mixed_tabs_spaces",
|
|
"message": "Code mixes tabs and spaces"
|
|
})
|
|
|
|
except SyntaxError as e:
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Syntax error: {str(e)}"}
|
|
)
|
|
else:
|
|
# TODO: Implement analysis for other languages
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Unsupported language: {language}"}
|
|
)
|
|
|
|
return self._createResult(
|
|
success=True,
|
|
data={
|
|
"language": language,
|
|
"analysis": analysis
|
|
}
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Error analyzing code: {e}")
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Analysis failed: {str(e)}"}
|
|
)
|
|
|
|
@action
|
|
async def generate(self, parameters: Dict[str, Any], authData: Optional[Dict[str, Any]] = None) -> MethodResult:
|
|
"""Generate code based on requirements"""
|
|
try:
|
|
requirements = parameters["requirements"]
|
|
language = parameters.get("language", "python")
|
|
style = parameters.get("style", "standard")
|
|
|
|
# TODO: Implement code generation using AI or templates
|
|
# This is a placeholder implementation
|
|
if language.lower() == "python":
|
|
# Generate a simple Python class based on requirements
|
|
className = re.sub(r'[^a-zA-Z0-9]', '', requirements.split()[0].title())
|
|
code = f"""class {className}:
|
|
\"\"\"
|
|
{requirements}
|
|
\"\"\"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
def process(self):
|
|
pass
|
|
"""
|
|
else:
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Unsupported language: {language}"}
|
|
)
|
|
|
|
return self._createResult(
|
|
success=True,
|
|
data={
|
|
"language": language,
|
|
"code": code
|
|
}
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Error generating code: {e}")
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Generation failed: {str(e)}"}
|
|
)
|
|
|
|
@action
|
|
async def refactor(self, parameters: Dict[str, Any], authData: Optional[Dict[str, Any]] = None) -> MethodResult:
|
|
"""Refactor code for better quality"""
|
|
try:
|
|
code = parameters["code"]
|
|
language = parameters.get("language", "python")
|
|
improvements = parameters.get("improvements", ["style", "complexity"])
|
|
|
|
if language.lower() == "python":
|
|
# Parse Python code
|
|
try:
|
|
tree = ast.parse(code)
|
|
|
|
# Apply improvements
|
|
if "style" in improvements:
|
|
# Format code (placeholder)
|
|
code = code.strip()
|
|
|
|
if "complexity" in improvements:
|
|
# TODO: Implement complexity reduction
|
|
pass
|
|
|
|
if "documentation" in improvements:
|
|
# Add missing docstrings
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, (ast.ClassDef, ast.FunctionDef)) and not ast.get_docstring(node):
|
|
# TODO: Generate docstring
|
|
pass
|
|
|
|
except SyntaxError as e:
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Syntax error: {str(e)}"}
|
|
)
|
|
else:
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Unsupported language: {language}"}
|
|
)
|
|
|
|
return self._createResult(
|
|
success=True,
|
|
data={
|
|
"language": language,
|
|
"code": code,
|
|
"improvements": improvements
|
|
}
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Error refactoring code: {e}")
|
|
return self._createResult(
|
|
success=False,
|
|
data={"error": f"Refactoring failed: {str(e)}"}
|
|
) |