Files
code-doc-cli/.code_doc_cli/parsers/base.py
7000pctAUTO 009d285d32
Some checks failed
CI / test (push) Has been cancelled
Add generators and parsers modules
2026-01-29 16:51:53 +00:00

111 lines
3.2 KiB
Python

"""Base parser interface and data structures."""
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Optional
from enum import Enum
class ElementType(Enum):
"""Types of documentation elements."""
FUNCTION = "function"
CLASS = "class"
METHOD = "method"
INTERFACE = "interface"
STRUCT = "struct"
MODULE = "module"
CONSTANT = "constant"
VARIABLE = "variable"
@dataclass
class Parameter:
"""Represents a function/method parameter."""
name: str
type_hint: Optional[str] = None
description: Optional[str] = None
default_value: Optional[str] = None
is_optional: bool = False
def __str__(self) -> str:
parts = [self.name]
if self.type_hint:
parts.append(f": {self.type_hint}")
if self.default_value:
parts.append(f" = {self.default_value}")
return "".join(parts)
@dataclass
class DocElement:
"""Represents a documentation element extracted from source code."""
name: str
element_type: ElementType
description: str = ""
full_docstring: str = ""
parameters: list[Parameter] = field(default_factory=list)
return_type: Optional[str] = None
return_description: Optional[str] = None
raises: list[tuple[str, str]] = field(default_factory=list)
examples: list[str] = field(default_factory=list)
source_file: str = ""
line_number: int = 0
visibility: str = "public"
decorators: list[str] = field(default_factory=list)
attributes: list[tuple[str, Optional[str], Optional[str]]] = field(
default_factory=list
)
imports: list[str] = field(default_factory=list)
class Parser(ABC):
"""Abstract base class for code parsers."""
def __init__(self, file_path: str):
self.file_path = file_path
self.content: str = ""
self.elements: list[DocElement] = []
@abstractmethod
def parse(self) -> list[DocElement]:
"""Parse the file and extract documentation elements."""
pass
@abstractmethod
def get_language_name(self) -> str:
"""Return the name of the language this parser handles."""
pass
@classmethod
@abstractmethod
def supports_file(cls, file_path: str) -> bool:
"""Check if this parser supports the given file."""
pass
def _read_content(self) -> str:
"""Read file content safely."""
with open(self.file_path, "r", encoding="utf-8") as f:
return f.read()
def _strip_docstring_quotes(self, docstring: str) -> str:
"""Remove leading/trailing quotes from docstring."""
if not docstring:
return ""
lines = docstring.split("\n")
if len(lines) == 1:
return docstring.strip('"""').strip("'''").strip()
first_line = lines[0].strip('"""').strip("'''").strip()
last_line = lines[-1].strip('"""').strip("'''").strip()
if len(lines) > 1:
middle_lines = lines[1:-1]
cleaned = []
for line in middle_lines:
stripped = line.strip()
if stripped:
cleaned.append(stripped)
return "\n".join([first_line] + cleaned + [last_line]) if cleaned else first_line
return first_line