Files
index/index1c/parse_modules.py
T

90 lines
2.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Индексация BSL-модулей конфигурации."""
from __future__ import annotations
import re
from dataclasses import dataclass
from pathlib import Path
from .config import OBJECT_TYPE_FOLDERS
# Процедура/Функция Имя(...)
RE_SYMBOL = re.compile(
r"(?im)^\s*(?:&[А-Яа-яA-Za-z_]+)*\s*"
r"(?:Процедура|Функция|Procedure|Function)\s+"
r"([А-Яа-яA-Za-z_][А-Яа-яA-Za-z0-9_]*)"
)
# Лимит тела для FTS (символы) — полные гигантские модули не кладём целиком.
MAX_BODY_CHARS = 200_000
@dataclass
class ModuleRec:
config: str
rel_path: str
abs_path: str
owner: str
module_kind: str
symbols: list[str]
body: str
line_count: int
size: int
mtime_ns: int
def _module_kind(rel: Path) -> str:
name = rel.name
if name == "Module.bsl":
parent = rel.parent.name
if parent == "Form":
return "FormModule"
if parent == "Ext":
# CommonModules/.../Ext/Module.bsl или HTTPServices/.../Ext/Module.bsl
return "Module"
return "Module"
if name.endswith("Module.bsl"):
return name[: -len(".bsl")] # ObjectModule, ManagerModule, ...
return name
def _owner_from_rel(rel: Path) -> str:
"""Documents/ЗаказКлиента/Ext/ObjectModule.bsl → Document.ЗаказКлиента."""
parts = rel.parts
if not parts:
return ""
folder = parts[0]
otype = OBJECT_TYPE_FOLDERS.get(folder)
if otype and len(parts) >= 2:
return f"{otype}.{parts[1]}"
return folder
def parse_bsl_file(path: Path, *, config: str, src_root: Path) -> ModuleRec | None:
try:
st = path.stat()
text = path.read_text(encoding="utf-8-sig", errors="replace")
except OSError:
return None
rel = path.relative_to(src_root).as_posix()
symbols = sorted(set(RE_SYMBOL.findall(text)))
body = text if len(text) <= MAX_BODY_CHARS else text[:MAX_BODY_CHARS]
return ModuleRec(
config=config,
rel_path=rel,
abs_path=str(path),
owner=_owner_from_rel(Path(rel)),
module_kind=_module_kind(Path(rel)),
symbols=symbols,
body=body,
line_count=text.count("\n") + (1 if text and not text.endswith("\n") else 0),
size=st.st_size,
mtime_ns=getattr(st, "st_mtime_ns", int(st.st_mtime * 1e9)),
)
def iter_bsl_files(src: Path) -> list[Path]:
if not src.is_dir():
return []
return sorted(src.rglob("*.bsl"))