Files
dotfiles/claude/.claude/skills/gdscript-ast-grep/SKILL.md
2026-08-04 11:42:09 +02:00

2.8 KiB

name, description
name description
gdscript-ast-grep Use when running ast-grep against GDScript (.gd) files — pattern-writing quirks specific to the tree-sitter-gdscript grammar (registered as language `gdscript` via the custom-language sgconfig). Covers why `$$$` (multi-metavariable) patterns silently fail to match, how to write working `func` search patterns, and other known-weak GDScript patterns. Pair with the general `ast-grep` skill for retry/fallback mechanics.

ast-grep on GDScript

gdscript is a custom grammar (not built into ast-grep), registered in sgconfig.yml. It's discovered automatically — omit -l and let extension auto-detection pick it up, or pass -l gdscript explicitly (never -l gd, that's the extension, not the language name).

Searching for functions

Don't end a func pattern in a bare : — with or without a $$$ body, it won't match:

func $NAME($$$) -> $RET:        # ✗ never matches (trailing colon, no body)
func $NAME($$$) -> $RET:
	$$$BODY                     # ✗ never matches ($$$ body collides with $)

Instead, match just the header and drop the trailing colon/body entirely — ast-grep still returns the whole function node, body included:

func $NAME($$$)                 # ✓ matches the full function, header through body
func $NAME($$$) -> $RET         # ✓ same, if you need the return type bound

GDScript also has static func — if a plain func $NAME($$$) pattern doesn't hit a function you know exists, retry with static func $NAME($$$) before falling back to rg.

Other known-weak patterns

These don't match even though they look valid — prefer a literal/simpler pattern or fall back to rg per the usual rule:

  • Typed declarations: const $N := $V, var $N := $V
  • Chained/dotted method calls: $O.$M(), $X.connect($Y) — tree-sitter-gdscript parses chains like a().b().c.connect(d) as one flat attribute node, not a nested chain, so these never bind.
  • Bare-colon fragments other than func: if $C:, for $V in $C: — same trailing-colon/body issue as above.

Literal calls (_clear_hover()), bare identifiers, and return $X-style single-metavariable patterns all match reliably.

Why: the $ collision

Root cause behind most of the above: GDScript's $ is a real operator ($Sprite / $"../Path" is shorthand for get_node(...)), and ast-grep also uses $ for metavariables ($X) and $$$ for "match zero-or-more". Single metavariables happen to parse fine, but $$$ immediately followed by an identifier (e.g. $$$BODY) produces a stray ERROR node instead of a clean placeholder, so the whole pattern fails to compile — silently, with no error text. This is an inherent sigil clash, not a bug to chase; see the general ast-grep skill for what to do when a pattern fails (retry simpler, then fall back to rg).