()
| 472 | } |
| 473 | |
| 474 | export function ensureDynamicLanguages(): void { |
| 475 | if (dynamicLangsRegistered) return; |
| 476 | dynamicLangsRegistered = true; |
| 477 | |
| 478 | try { |
| 479 | const survivors: Record<string, AstGrepLangModule> = {}; |
| 480 | |
| 481 | const langPackages: Array<[string, string]> = [ |
| 482 | ["python", "@ast-grep/lang-python"], |
| 483 | ["go", "@ast-grep/lang-go"], |
| 484 | ["java", "@ast-grep/lang-java"], |
| 485 | ["rust", "@ast-grep/lang-rust"], |
| 486 | ["c", "@ast-grep/lang-c"], |
| 487 | ["cpp", "@ast-grep/lang-cpp"], |
| 488 | ["csharp", "@ast-grep/lang-csharp"], |
| 489 | ["ruby", "@ast-grep/lang-ruby"], |
| 490 | ["kotlin", "@ast-grep/lang-kotlin"], |
| 491 | ["swift", "@ast-grep/lang-swift"], |
| 492 | ["scala", "@ast-grep/lang-scala"], |
| 493 | ["bash", "@ast-grep/lang-bash"], |
| 494 | ["php", "@ast-grep/lang-php"], |
| 495 | ["lua", "@ast-grep/lang-lua"], |
| 496 | ["dart", "@ast-grep/lang-dart"], |
| 497 | ]; |
| 498 | |
| 499 | for (const [name, pkg] of langPackages) { |
| 500 | try { |
| 501 | const mod = esmRequire(pkg) as AstGrepLangModule; |
| 502 | // Pre-validate the lazy `libraryPath` getter. `registerDynamicLanguage` |
| 503 | // accesses this property for every entry it receives, and a single |
| 504 | // throwing getter aborts the entire batch atomically (issue #43). |
| 505 | // Touching the getter here, inside the per-grammar try/catch, isolates |
| 506 | // a missing-prebuild failure to that one grammar so the rest can still |
| 507 | // be registered. The getter caches its result inside the package, so |
| 508 | // this is not duplicated work. |
| 509 | void mod.libraryPath; |
| 510 | survivors[name] = mod; |
| 511 | loadedDynamicLanguages.add(name); |
| 512 | } catch (err) { |
| 513 | const message = err instanceof Error ? err.message : String(err); |
| 514 | failedDynamicLanguages.set(name, message); |
| 515 | logger.warn("ast-grep grammar failed to load", { name, error: message }); |
| 516 | } |
| 517 | } |
| 518 | |
| 519 | if (Object.keys(survivors).length > 0) { |
| 520 | registerDynamicLanguage(survivors); |
| 521 | logger.info("Registered dynamic ast-grep languages", { |
| 522 | languages: [...loadedDynamicLanguages].sort(), |
| 523 | }); |
| 524 | } else { |
| 525 | logger.warn( |
| 526 | "No dynamic ast-grep grammars loaded; PHP, Python, JVM and other dynamic languages will fall through to <module>-only extraction", |
| 527 | ); |
| 528 | } |
| 529 | if (failedDynamicLanguages.size > 0) { |
| 530 | logger.warn( |
| 531 | "Some dynamic ast-grep grammars failed to load; affected languages will produce only <module>-level symbols", |
no test coverage detected