from abc import ABC, abstractmethod from dataclasses import dataclass, field from enum import Enum from pathlib import Path from typing import Optional class EntityType(Enum): FILE = "file" FUNCTION = "function" CLASS = "class" METHOD = "method" IMPORT = "import" VARIABLE = "variable" CONSTANT = "constant" @dataclass class Entity: name: str entity_type: EntityType file_path: Path start_line: int end_line: int code: str = "" attributes: dict = field(default_factory=dict) parent: Optional["Entity"] = None children: list["Entity"] = field(default_factory=list) imports: list[str] = field(default_factory=list) calls: list[str] = field(default_factory=list) @dataclass class ParserResult: file_path: Path entities: list[Entity] = field(default_factory=list) imports: list[str] = field(default_factory=list) errors: list[str] = field(default_factory=list) language: str = "" class BaseParser(ABC): SUPPORTED_EXTENSIONS: list[str] = [] @abstractmethod def parse(self, file_path: Path, content: str) -> ParserResult: pass @abstractmethod def extract_entities(self, tree, file_path: Path) -> list[Entity]: pass @abstractmethod def extract_imports(self, content: str) -> list[str]: pass @abstractmethod def extract_calls(self, content: str) -> list[str]: pass @classmethod def can_parse(cls, file_path: Path) -> bool: return file_path.suffix in cls.SUPPORTED_EXTENSIONS @classmethod def get_parser_for_file(cls, file_path: Path) -> Optional["BaseParser"]: for parser_class in cls.__subclasses__(): if parser_class.can_parse(file_path): return parser_class() return None