fix(typescript): recognize bodyless constructor declarations - #2283
Merged
Conversation
func_start's bodyless-declaration branch required a `:ReturnType` annotation before the terminating `;`, but a TypeScript constructor can never carry a return-type annotation at all -- making every bodyless constructor signature (ambient .d.ts class members, interface-like declarations) structurally unmatchable. Split the zero-prefix branch: `constructor` gets its own alternative with the return-type made fully optional (safe, since it's a reserved identifier that can never collide with a real function call); every other identifier keeps the original branch, still requiring an explicit return type before `;` to avoid false-positiving on bare function calls like `next();`. Verified via the full 23-file typescript corpus diff against tree-sitter: vscode.d.ts alone recovers all ~113 previously-missed constructor signatures (struct_func_start/function_count now match at 671, up from 558/10 constructors found). Corpus-wide missing-function count drops from 131 to 16, zero new regressions, zero new over-detection. Fixes #2279. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
Structural drift in the golden masters is fully attributable to the fix: vscode.d.ts now correctly extracts ~113 previously-missed real constructor signatures, with the expected downstream ripple into topological coordinates and structural-magnitude aggregates for the same file/directory group. tree_sitter_accuracy_audit.py itself needed a real code fix, not just a baseline regeneration: it had a deliberate, pre-existing exclusion (`pass # Intentional drop of bodyless constructors`, from #2245) dropping every bodyless TypeScript `constructor` node from its own ground truth -- written back when GitGalaxy structurally could never find one, so counting it as "real" would have permanently and unfairly penalized recall. #2279 closes that exact gap, so the exclusion is now stale: keeping it would have silently dropped all 123 real constructors in vscode.d.ts from ground truth and counted every one of GitGalaxy's new, correct finds as a false "extra_functions" regression (12 -> 127) instead of the real recall win it is. Removed the exclusion; constructors now flow through the same real_funcs bookkeeping as any other method_signature/ function_signature node. Confirmed via a raw tree-sitter walk of vscode.d.ts independent of this tool's own machinery (123 method_ signature nodes named "constructor", matching exactly) before making the change. Net effect after the fix: found_functions 2773 -> 2898, extra_functions 12 -> 2 (both of the 2 remaining are the already-known-good abstract- method case, unrelated to this PR). tree_sitter_accuracy_audit --all --ci: all 31 baselined languages OK, no regressions anywhere else. tests/tools/audit_check.py --ci: all clear. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
squid-protocol
enabled auto-merge (squash)
August 26, 2026 20:07
Resolves conflict with #2276+#2277 (now on main): all three touch the same func_start branch (modifier-prefixed method shorthand). Combined #2279's constructor-specific split, #2276's catch/return/ throw exclusion, and #2277's widened line-start anchor into one regex -- constructor gets its own alternative (now anchor-widened too), the general-identifier alternative excludes constructor from its own name list (handled by its own branch) alongside the existing catch/return/throw exclusion. Golden masters/baseline taken from origin/main wholesale, will be regenerated fresh against the merged code before pushing.
Resolves trivial summary-table conflict with #2278 (now on main) -- detector.py's overload-collapse fix doesn't touch language_standards.py's regex, only its own bless commit's summary-table refresh. Golden masters taken from origin/main wholesale, will be regenerated fresh.
…mbined) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Trivial summary-table conflict from main's own auto-update companion workflows (docs auto-update commits, no new code PR) advancing since the last merge. No golden-master conflict this round.
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
Fixes #2279 (dominant TypeScript gap: 113 of 131 corpus-wide missing occurrences).
func_start's bodyless-declaration branch required a:ReturnTypeannotation before the terminating;, but a TypeScript constructor can never carry a return-type annotation at all -- making every bodyless constructor signature (ambient.d.tsclass members) structurally unmatchable.Fix
Split the zero-prefix branch:
constructorgets its own alternative with the return-type made fully optional (safe -- it's a reserved identifier that can never collide with a real function call). Every other identifier keeps the original branch, still requiring an explicit return type before;to avoid false-positiving on bare function calls likenext();. This is a narrower, safer scope than the issue's own suggested one-character fix (which the dispatched agent found regressed on bare-call false positives during its own testing) -- deliberate, not an oversight.Verification
constructor(x: number);(bodyless) andconstructor(x: number) { ... }(body-bearing) both match;next();/TargetFunc();/describe('...', () => {(bare calls) still correctly do not.pytest tests/extraction/languages/test_typescript.py tests/extraction/languages/test_typescript_strict.py tests/core_engine/test_detector.py-- 333 passed.vscode/vscode.d.tsrecovers essentially all ~113 previously-missed constructors (struct_func_start/function_countnow match at 671, up from 558/10-found). Corpus-wide missing-function count drops from 131 to 16, zero new regressions, zero new over-detection (extra count unchanged at 2, both pre-existing known-good cases).tests/ruff_audit.py --ci/tests/mypy_audit.py --ci-- no new findings beyond baseline.Implemented by a dispatched Gemini/agy subagent per this repo's
tree-sitter-accuracy-sweep-style workflow; independently re-verified in the main session (diff read, full corpus-wide regression check, ReDoS probe, false-positive probes) before this push.Test plan
test_typescript.py/test_typescript_strict.py/test_detector.py