Main parse loop. Walks source sequentially, building up ParsedClass/ParsedEnum objects. Strategy: find UCLASS/USTRUCT/UENUM blocks, then scan the body for UPROPERTY/UFUNCTION.
(source: str, result: ParsedFile)
| 311 | |
| 312 | |
| 313 | def _parse_file(source: str, result: ParsedFile): |
| 314 | """ |
| 315 | Main parse loop. Walks source sequentially, building up ParsedClass/ParsedEnum objects. |
| 316 | Strategy: find UCLASS/USTRUCT/UENUM blocks, then scan the body for UPROPERTY/UFUNCTION. |
| 317 | """ |
| 318 | # ── 1. Find all UENUM blocks ────────────────────────────────────────────── |
| 319 | enum_macro_re = re.compile(r'(?:/\*\*((?:(?!\*/).)*?)\*/\s*)?UENUM\s*\((.*?)\)\s*enum\s+class\s+(\w+)[^{]*\{', re.DOTALL) |
| 320 | for m in enum_macro_re.finditer(source): |
| 321 | raw_doc = m.group(1) or '' |
| 322 | spec_str = m.group(2) or '' |
| 323 | enum_name = m.group(3) |
| 324 | brief, desc = _clean_doc_comment(raw_doc) |
| 325 | specs = _parse_specifiers(spec_str) |
| 326 | |
| 327 | # Extract body |
| 328 | body_start = m.end() |
| 329 | body = _extract_to_closing_brace(source, body_start - 1) |
| 330 | |
| 331 | enm = ParsedEnum( |
| 332 | name=enum_name, |
| 333 | specifiers=specs, |
| 334 | brief=brief, |
| 335 | description=desc, |
| 336 | is_blueprint_type=specs.get('BlueprintType', False) is True, |
| 337 | ) |
| 338 | |
| 339 | # Extract enum values |
| 340 | for vm in _ENUM_VALUE_RE.finditer(body): |
| 341 | vname = vm.group(1) |
| 342 | if vname in ('GENERATED_BODY', 'GENERATED_USTRUCT_BODY'): |
| 343 | continue |
| 344 | display = vm.group(2) or vname |
| 345 | enm.values.append(asdict(ParsedEnumValue(name=vname, display_name=display))) |
| 346 | |
| 347 | result.enums.append(asdict(enm)) |
| 348 | |
| 349 | # ── 2. Find all UCLASS / USTRUCT blocks ─────────────────────────────────── |
| 350 | # Match: optional doc, then UCLASS/USTRUCT macro, then class/struct Name |
| 351 | class_block_re = re.compile( |
| 352 | r'(?:/\*\*((?:(?!\*/).)*?)\*/\s*)?' # optional doc comment |
| 353 | r'(UCLASS|USTRUCT)\s*\((.*?)\)\s*' # UCLASS/USTRUCT macro |
| 354 | r'(?:class|struct)\s+(?:\w+_API\s+)?(\w+)' # class/struct Name |
| 355 | r'(?:\s*:\s*(?:public\s+)?(\w+))?' # optional : public Parent |
| 356 | r'\s*\{', # opening brace |
| 357 | re.DOTALL |
| 358 | ) |
| 359 | for m in class_block_re.finditer(source): |
| 360 | raw_doc = m.group(1) or '' |
| 361 | macro = m.group(2) |
| 362 | spec_str = m.group(3) or '' |
| 363 | cls_name = m.group(4) |
| 364 | parent = m.group(5) or '' |
| 365 | brief, desc = _clean_doc_comment(raw_doc) |
| 366 | specs = _parse_specifiers(spec_str) |
| 367 | |
| 368 | # Extract class body |
| 369 | body_start = m.end() |
| 370 | body = _extract_to_closing_brace(source, body_start - 1) |
no test coverage detected