This commit is contained in:
110
.code_doc_cli/parsers/base.py
Normal file
110
.code_doc_cli/parsers/base.py
Normal file
@@ -0,0 +1,110 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user