"""Markdown formatter for code structure output."""
from typing import List
from ..models import AnalysisResult, CodeElement, CodeStructure, ParseError
class MarkdownFormatter:
"""Formats code structure as markdown for LLM consumption."""
def format_structure(self, structure: CodeStructure) -> str:
"""Format code structure as markdown."""
lines: List[str] = []
# Header
lines.append(f"# Code Structure: `{structure.file_path}`")
lines.append("")
# Metadata
lines.append(f"**Language**: {structure.language.capitalize()}")
lines.append(f"**Total Classes**: {structure.total_classes}")
lines.append(f"**Total Functions**: {structure.total_functions}")
lines.append(f"**Max Nesting Depth**: {structure.max_nesting_depth}")
lines.append("")
# Classes section
if structure.classes:
lines.append("## Classes")
lines.append("")
for cls in structure.classes:
lines.extend(self._format_class(cls))
lines.append("")
# Functions section
if structure.functions:
lines.append("## Functions")
lines.append("")
for func in structure.functions:
lines.extend(self._format_function(func))
lines.append("")
# Errors section
if structure.errors:
lines.append("## Parse Errors")
lines.append("")
for error in structure.errors:
lines.extend(self._format_error(error))
lines.append("")
return "\n".join(lines)
def _format_class(self, class_element: CodeElement, indent: int = 0) -> List[str]:
"""Format a class element."""
lines: List[str] = []
prefix = " " * indent
# Class header
lines.append(
f"{prefix}### `{class_element.name}` (Lines {class_element.start_line}-{class_element.end_line}, Nesting: {class_element.nesting_level})"
)
lines.append(f"{prefix}- **Type**: Class")
# Docstring
if class_element.docstring:
lines.append(f"{prefix}- **Docstring**: {class_element.docstring}")
# Methods (nested functions)
methods = class_element.get_nested_functions()
if methods:
lines.append(f"{prefix}- **Methods**:")
for method in methods:
lines.extend(self._format_function(method, indent + 1))
# Nested classes
nested_classes = class_element.get_nested_classes()
if nested_classes:
lines.append(f"{prefix}- **Nested Classes**:")
for nested_cls in nested_classes:
lines.extend(self._format_class(nested_cls, indent + 1))
return lines
def _format_function(
self, function_element: CodeElement, indent: int = 0
) -> List[str]:
"""Format a function element."""
lines: List[str] = []
prefix = " " * indent
# Function header
parent_info = ""
if function_element.parent:
parent_info = f", Parent: `{function_element.parent.name}`"
lines.append(
f"{prefix}### `{function_element.name}` (Lines {function_element.start_line}-{function_element.end_line}, Nesting: {function_element.nesting_level}{parent_info})"
)
lines.append(f"{prefix}- **Type**: Function")
# Parameters
if function_element.parameters:
params_str = ", ".join(str(p) for p in function_element.parameters)
lines.append(f"{prefix}- **Parameters**: `{params_str}`")
# Return type
if function_element.return_type:
lines.append(f"{prefix}- **Return Type**: `{function_element.return_type}`")
# Docstring
if function_element.docstring:
lines.append(f"{prefix}- **Docstring**: {function_element.docstring}")
# Nested functions
nested_functions = function_element.get_nested_functions()
if nested_functions:
lines.append(f"{prefix}- **Nested Functions**:")
for nested_func in nested_functions:
lines.extend(self._format_function(nested_func, indent + 1))
# Nested classes
nested_classes = function_element.get_nested_classes()
if nested_classes:
lines.append(f"{prefix}- **Nested Classes**:")
for nested_cls in nested_classes:
lines.extend(self._format_class(nested_cls, indent + 1))
return lines
def format_multi_file_structure(self, results: List[AnalysisResult]) -> str:
"""Format multiple code structure results as markdown."""
lines: List[str] = []
# Summary header
success_count = sum(1 for r in results if r.success)
error_count = len(results) - success_count
lines.append("# Code Structure Analysis")
lines.append("")
lines.append(f"**Files Analyzed**: {len(results)}")
lines.append(f"**Successful**: {success_count}")
lines.append(f"**Failed**: {error_count}")
lines.append("")
# Each file's output
for i, result in enumerate(results):
if i > 0:
lines.append("") # Blank line before separator
lines.append("---") # Horizontal rule
lines.append("")
lines.append(result.markdown)
return "\n".join(lines)
def _format_error(self, error: ParseError) -> List[str]:
"""Format a parsing error."""
lines: List[str] = []
lines.append(
f"⚠️ **{error.severity.capitalize()} at Line {error.line}**: {error.message}"
)
lines.append("```")
lines.append(error.context)
lines.append("```")
return lines