Files

40 lines
2.2 KiB
Python
Raw Permalink Normal View History

2026-09-11 18:18:40 +05:00
"""Lexical dependency hints, explicitly not a substitute for Android compilation."""
from __future__ import annotations
import re
from pathlib import Path
from common import sha256
RISKS={
'desktop_ui':r'\b(?:Forms|Controls|Graphics|Dialogs|LCLIntf|LCLType|Interfaces)\b',
'windows_api':r'\b(?:Windows|Winapi|ShellAPI|MMSystem|Messages)\b',
'legacy_gl':r'\b(?:dglOpenGL|glBegin|glEnd|glMatrixMode|glVertexPointer|glOrtho)\b',
'native_audio':r'\b(?:BASS\w*|OpenAL|DirectSound)\b',
'native_files':r'\b(?:TFileStream|FileExists|FindFirst|FindNext|GetCurrentDir|ParamStr)\b',
'layout_or_assembler':r'\b(?:Extended|NativeUInt|NativeInt|Pointer|assembler|asm|packed\s+record)\b',
'initialization':r'^\s*initialization\b'}
def inventory(source:Path)->dict:
units={};risks=[];edges=[];files=[]
for p in sorted(source.rglob('*')):
if not p.is_file() or p.suffix.lower() not in ('.pas','.pp'):continue
text=p.read_text(encoding='utf-8-sig',errors='replace');rel=p.relative_to(source).as_posix()
m=re.search(r'^\s*unit\s+([\w.]+)\s*;',text,re.I|re.M)
if not m:continue
units.setdefault(m[1].casefold(),[]).append(rel)
files.append({'path':rel,'sha256':sha256(p)})
clean=re.sub(r'\{.*?\}|\(\*.*?\*\)|//[^\n]*',' ',text,flags=re.S)
for use in re.finditer(r'\buses\s+(.+?);',clean,re.I|re.S):
for term in use[1].split(','):
dep=re.match(r'\s*([\w.]+)',term)
if dep:edges.append({'from':m[1],'to':dep[1]})
for kind,pattern in RISKS.items():
for hit in list(re.finditer(pattern,text,re.I|re.M))[:8]:
risks.append({'path':rel,'line':text[:hit.start()].count('\n')+1,'kind':kind,'token':hit[0]})
return {'scope':'Lexical, both conditional branches included; compilation decides active blockers.',
'units':units,'duplicates':{k:v for k,v in units.items() if len(v)>1},'edges':edges,'risks':risks,'files':files}
def search_paths(source:Path)->list[Path]:
dirs={source}
for p in source.rglob('*'):
if p.is_file() and p.suffix.lower() in ('.pas','.pp','.inc','.inl'):dirs.add(p.parent)
return sorted(dirs,key=lambda p:('ext' in p.relative_to(source).parts,len(p.parts),str(p)))