"""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)))