feat(extraction): add GDScript language support - #1579
Open
Plumvery wants to merge 1 commit into
Open
Conversation
Adds GDScript (.gd) as a supported language on the wasm extraction path: - Extractor (src/extraction/languages/gdscript.ts): functions and typed signatures, `_init` constructors (no name field in the grammar — resolveName supplies the conventional name), inner classes with methods, enums with members (`enumerator` names via `left`), `static func` detection (static_keyword child scan), and call edges through `call`, `attribute_call`, and `base_call`. - The var/const family (`variable_statement`, `export_variable_statement`, `onready_variable_statement`, `const_statement`) names its target via a `name`-typed child, not `identifier`, so the core's generic variable fallback can't read them — a visitNode hook creates variable/constant nodes itself and walks initializers so calls inside them (`preload(...)`, `Foo.new()`) are captured. - Signals extract as properties carrying their parameter list, so connect()-heavy scripts expose their signal surface in the graph. - Grammar: PrestonKnopp/tree-sitter-gdscript v6.1.0 (MIT), vendored as an ABI-15 wasm rebuilt from upstream source (tree-sitter-cli 0.25.10 generate + build --wasm, emscripten/emsdk:4.0.4); external scanner (indentation) included. check-grammar.mjs: ABI 15, 20/20 clean parses, heap-safe under multi-grammar reuse. Validated with the add-lang verification gate on two corpora: - godotengine/godot-demo-projects (public): 461 .gd files -> 5,216 nodes / 6,783 edges in 3.7s (classes 45, methods 184, signals 141, enums 39+130). - A private Godot 4 game (138 .gd files): 2,996 nodes / 11,484 edges; all critical and soft checks pass (2,858 structural symbols, density 20.7/file). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds GDScript (
.gd, Godot Engine) as a supported language on the wasm extraction path, following the shape of previous language additions (Nix #1190, ArkTS #648).src/extraction/languages/gdscript.ts, ~100 lines): functions with typed signatures,_initconstructors, inner classes with methods, the fullvar/const/@export/@onreadyvariable family, signals, enums with members,static funcdetection, and call edges throughcall/attribute_call/base_call.tree-sitter-cli 0.25.10 generate+build --wasm, emscripten/emsdk:4.0.4), external scanner (indentation) included — the same approach as the Nix wasm.Grammar shapes that needed care
name-typed child, notidentifier, so the core's generic variable fallback can't read them. AvisitNodehook creates variable/constant nodes itself, then walks initializers so calls inside them (preload(...),Foo.new()) are captured.func _init(...)(constructor_definition) has no name field —resolveNamesupplies the conventional_init.enumeratornames its identifier vialeft.staticon functions is a namedstatic_keywordchild with no field (the var statements carry it via a field) — a child scan covers both.signal foo(a, b)extracts as a property carrying the parameter list, so connect()-heavy scripts expose their signal surface in the graph.obj.method(args)parses asattribute(identifier, attribute_call(...))—attribute_calljoins callTypes and the core'snamedChild(0)callee fallback yields the bare method name (name-match resolution, same as self/this receivers elsewhere).Validation
scripts/add-lang/check-grammar.mjs: ABI 15, 20/20 clean parses, heap-safe under multi-grammar reuse (the Lua ABI-13 corruption scenario this script exists for does not occur).scripts/add-lang/verify-extraction.mjscriteria on two corpora (all critical and soft checks pass):Kind spread on the public corpus: 2,027 functions / 184 methods / 45 classes / 141 signals→properties / 39 enums + 130 members / 1,570 variables / 422 constants — symbol density well above the 1-per-file soft bar.
Tests: 4 new extraction describe-blocks + detection/support assertions in
__tests__/extraction.test.ts; full vitest suite passes locally (all pre-existing tests unaffected).Not included (deliberately small)
preload/loadimport-edge resolution tores://paths (calls are captured; resolving them to file nodes would follow the Luau instance-pathrequirepattern and can come as a follow-up).🤖 Generated with Claude Code