"""Data models for code structure analysis."""
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class Parameter:
"""Represents a function parameter."""
name: str
type_annotation: Optional[str] = None
default_value: Optional[str] = None
def __str__(self) -> str:
"""String representation of the parameter."""
parts = [self.name]
if self.type_annotation:
parts.append(f": {self.type_annotation}")
if self.default_value:
parts.append(f" = {self.default_value}")
return "".join(parts)
@dataclass
class CodeElement:
"""Base class for code elements (classes, functions)."""
name: str
element_type: str # "class" or "function"
start_line: int
end_line: int
nesting_level: int
parent: Optional["CodeElement"] = None
docstring: Optional[str] = None
parameters: List[Parameter] = field(default_factory=list)
return_type: Optional[str] = None
children: List["CodeElement"] = field(default_factory=list)
def add_child(self, child: "CodeElement") -> None:
"""Add a child element."""
child.parent = self
self.children.append(child)
def get_nested_functions(self) -> List["CodeElement"]:
"""Get all nested functions."""
return [c for c in self.children if c.element_type == "function"]
def get_nested_classes(self) -> List["CodeElement"]:
"""Get all nested classes."""
return [c for c in self.children if c.element_type == "class"]
@dataclass
class ParseError:
"""Represents a parsing error."""
line: int
message: str
context: str
severity: str = "error" # "error" or "warning"
@dataclass
class CodeStructure:
"""Represents the complete code structure of a file."""
file_path: str
language: str
classes: List[CodeElement] = field(default_factory=list)
functions: List[CodeElement] = field(default_factory=list)
errors: List[ParseError] = field(default_factory=list)
def add_class(self, class_element: CodeElement) -> None:
"""Add a class to the structure."""
self.classes.append(class_element)
def add_function(self, function_element: CodeElement) -> None:
"""Add a function to the structure."""
self.functions.append(function_element)
def add_error(self, error: ParseError) -> None:
"""Add a parsing error."""
self.errors.append(error)
@property
def total_classes(self) -> int:
"""Get total number of classes (including nested)."""
count = len(self.classes)
for cls in self.classes:
count += len(cls.get_nested_classes())
return count
@property
def total_functions(self) -> int:
"""Get total number of functions (including nested)."""
count = len(self.functions)
for func in self.functions:
count += len(func.get_nested_functions())
for cls in self.classes:
count += len(cls.get_nested_functions())
for nested_cls in cls.get_nested_classes():
count += len(nested_cls.get_nested_functions())
return count
@property
def max_nesting_depth(self) -> int:
"""Get maximum nesting depth."""
max_depth = 0
def get_depth(element: CodeElement, current_depth: int) -> int:
nonlocal max_depth
max_depth = max(max_depth, current_depth)
for child in element.children:
get_depth(child, current_depth + 1)
return max_depth
for func in self.functions:
get_depth(func, 0)
for cls in self.classes:
get_depth(cls, 0)
return max_depth
@dataclass
class AnalysisResult:
"""Result of code structure analysis."""
success: bool
language: str
file_path: str
structure: Optional[CodeStructure] = None
markdown: str = ""
errors: List[ParseError] = field(default_factory=list)
stats: dict = field(default_factory=dict)
def to_dict(self) -> dict:
"""Convert to dictionary."""
return {
"success": self.success,
"language": self.language,
"file_path": self.file_path,
"markdown": self.markdown,
"errors": [
{
"line": e.line,
"message": e.message,
"context": e.context,
"severity": e.severity,
}
for e in self.errors
],
"stats": self.stats,
}
@dataclass
class BatchAnalysisResult:
"""Result of analyzing multiple files."""
file_count: int
success_count: int
error_count: int
results: List[AnalysisResult] = field(default_factory=list)