Skip to content

fix(typescript): recognize bodyless constructor declarations - #2283

Merged
squid-protocol merged 7 commits into
mainfrom
fix/typescript-2279-bodyless-notype
Aug 26, 2026
Merged

fix(typescript): recognize bodyless constructor declarations#2283
squid-protocol merged 7 commits into
mainfrom
fix/typescript-2279-bodyless-notype

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Summary

Fixes #2279 (dominant TypeScript gap: 113 of 131 corpus-wide missing occurrences). 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) structurally unmatchable.

Fix

Split the zero-prefix branch: constructor gets 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 like next();. 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

  • Isolated regex tests: constructor(x: number); (bodyless) and constructor(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.
  • Full 23-file typescript corpus diff against tree-sitter: vscode/vscode.d.ts recovers essentially all ~113 previously-missed constructors (struct_func_start/function_count now 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.
  • ReDoS pathological-input timing probe -- no slowdown.

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

  • Regex-level positive/negative tests (bodyless + body-bearing constructors, bare-call false-positive guard)
  • test_typescript.py / test_typescript_strict.py / test_detector.py
  • Full-corpus tri-comparison diff (before/after)
  • ruff/mypy baseline audits
  • ReDoS sanity check

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>
@github-actions

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab



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
squid-protocol enabled auto-merge (squash) August 26, 2026 20:07
squid-protocol and others added 5 commits August 26, 2026 16:20
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.
…2277+#2279)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
@squid-protocol
squid-protocol merged commit b671f66 into main Aug 26, 2026
28 checks passed
@squid-protocol
squid-protocol deleted the fix/typescript-2279-bodyless-notype branch August 26, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TypeScript] func_start's bodyless-declaration branch requires a return-type annotation that constructors (and many methods) never have

1 participant