Repository navigation
[TypeScript] func_start's bodyless-declaration branch requires a return-type annotation that constructors (and many methods) never have #2279
Description
The dominant, previously-uncharacterized cause behind the typescript tri-comparison ledger's agree[tree_sitter]_vs[ctags,gitgalaxy] shape (docs/self_scan/tri_comparison_ledger.json, currently 124 occurrences, verdict text "GitGalaxy misses arrow functions" — that verdict undersells it; the real dominant cause is below, not arrow functions).
Real example, vscode/vscode.d.ts (a large, real-world TypeScript ambient-declaration file — 6,551 lines, the kind of file every @types/* package and hand-written .d.ts in the ecosystem looks like): 133 constructor(...) declarations, all bodyless (no {...}, terminated by ;), e.g.:
constructor(line: number, character: number);
constructor(start: Position, end: Position);
private constructor(scheme: string, authority: string, path: string, query: string, fragment: string);tree-sitter correctly finds 123 of them as real constructor signatures. GitGalaxy finds only 10 (confirmed via galaxyscope --db-only + SELECT struct_func_start, function_count FROM file_data: both read exactly 558 for this file — the raw regex signal and the named list agree with each other, meaning nothing is being dropped downstream; the regex itself simply never matches most of these lines in the first place).
Root cause, isolated and reproduced directly against LANGUAGE_DEFINITIONS["typescript"]["rules"]["func_start"]:
>>> pat.finditer('constructor(line: number, character: number);')
[] # MISSES -- no return type before the `;`
>>> pat.finditer('foo(x: number): void;')
['foo'] # matches -- HAS a return type before the `;`
>>> pat.finditer('foo(x: number);')
[] # MISSES -- no return type before the `;`The bodyless-declaration alternative at the tail of the pattern is:
\)[ \t\n]{0,50}(?:(?::[^{;]{0,200})?[ \t\n]{0,50}(?:=>[ \t\n]{0,50})?\{|:[^{;]{0,200}[ \t\n]{0,50};)
Two alternatives after the closing ): a body-bearing case where :ReturnType is genuinely optional ((?::[^{;]{0,200})?...\{), and a bodyless case where it is NOT optional (:[^{;]{0,200}[ \t\n]{0,50}; — the leading :[^{;]{0,200} group has no trailing ?). A TypeScript constructor syntactically can never carry a return-type annotation at all, and any other method/function declaration is free to omit one too — so every bodyless declaration without an explicit : ReturnType is structurally unmatchable by this branch, regardless of language construct (ambient .d.ts class members, interface method signatures, abstract class members, overload signatures with an inferred/omitted return type).
Confirmed scope: 113 of this file's 123 real constructors are lost this way (galaxyscope's own DB confirms 10 survive — those must be the minority that happen to combine with something else the pattern still matches, not investigated further since the mechanism above already fully explains the shape). Across the full 23-file typescript corpus, this single file alone accounts for 113 of the ledger shape's 124 total occurrences — the large majority. A quick manual scan of the remaining ~11 occurrences in other files (vscode/async.ts's cancel/return/catch/constructor duplicates, etc.) suggests at least some share this exact mechanism too, though a couple (like catch) are the separate reserved-keyword issue filed as #2276.
Suggested fix direction (not applied here, needs the full Differential Scan verification chain per CLAUDE.md before shipping): make the bodyless branch's leading :[^{;]{0,200} group optional, mirroring the already-correct body-bearing branch immediately before it in the same alternation — i.e. (?::[^{;]{0,200})?[ \t\n]{0,50}; instead of the current mandatory :[^{;]{0,200}[ \t\n]{0,50};. This is a one-character-level (?) asymmetry fix, but per this repo's .claude/rules/planning-approval.md any change to language_standards.py needs a presented strategy + approval before editing, and per CLAUDE.md's Differential Scan protocol needs the full extraction-gauntlet/golden-master/crucible_check.py verification chain across all 25+ languages sharing this regex-generation convention before it's safe to ship — filing rather than shipping inline.
Activity
Root-cause and file GitHub issues for TypeScript's real func_start re…
chore: bless golden masters + fix stale ground-truth exclusion for #2279
Merge origin/main into fix/typescript-2279-bodyless-notype
chore: re-bless golden masters + baseline against merged main (#2276+#…
Merge origin/main into fix/typescript-2278-overload-collapse
fix(typescript/javascript): stop dropping bodyless overload signatures (