Skip to content

fix(typescript): recognize arrow/method-shorthand defs not at line start - #2285

Merged
squid-protocol merged 4 commits into
mainfrom
fix/typescript-2277-line-start-anchor
Aug 26, 2026
Merged

fix(typescript): recognize arrow/method-shorthand defs not at line start#2285
squid-protocol merged 4 commits into
mainfrom
fix/typescript-2277-line-start-anchor

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Summary

Fixes #2277. func_start's object-literal-property and method-shorthand branches were anchored to ^[ \t]* (true line start only), so a real function value that wasn't the first thing on its line was invisible -- a comma-preceded sibling property (return { result, abort: () => aborted = true };) or a method shorthand nested inside a one-line call/return argument (foo(bar, { report(n: number) { } });).

Fix

Widened the anchor on both branches to (?:^[ \t]*|(?<=[,{])[ \t\n]*) -- true line start, OR immediately after a comma or opening brace. Bounded (fixed-width lookbehind, no new unbounded quantifiers).

Real side effect, caught during this PR's own verification (not shipped): two pre-existing gates in detector.py's _slice_by_braces (#1631/#1632) assumed match.start() - 1/- 2 was always the newline immediately preceding true line-start -- an assumption this widened anchor breaks, since a match can now start right after a ,/{ mid-line. A first draft regressed 6 real functions elsewhere in the corpus this way (caught by a full corpus diff, not by narrow unit tests). Fixed by having both gates independently resolve the true start of the line containing the captured name (match.start(match.lastindex)) rather than trusting the match's own start position.

Verification

Implemented by a dispatched Gemini/agy subagent per this repo's tree-sitter-accuracy-sweep-style workflow, across two rounds (round 1's regression was root-caused in the main session and the precise fix specified for round 2's implementation); independently re-verified before this push.

Test plan

  • Regex-level positive/negative tests (3 targeted cases + regression-guard cases)
  • test_typescript.py / test_typescript_strict.py / test_javascript.py / test_javascript_strict.py / test_detector.py
  • Full-corpus tri-comparison diff, confirming both the fix and the absence of the round-1 regression
  • Cross-language sanity spot-check
  • ruff/mypy baseline audits
  • ReDoS sanity check

func_start's object-literal-property and method-shorthand branches
were anchored to `^[ \t]*` (true line start only), so a real function
value that wasn't the first thing on its line was invisible -- a
comma-preceded sibling property (`return { result, abort: () =>
aborted = true };`) or a method shorthand nested inside a one-line
call/return argument (`foo(bar, { report(n: number) { } });`).

Widened the anchor on both branches to
`(?:^[ \t]*|(?<=[,{])[ \t\n]*)` -- true line start, OR immediately
after a comma or opening brace. Bounded (fixed-width lookbehind, no
new unbounded quantifiers), confirmed via a pathological-input timing
probe.

That widening has a real side effect worth calling out: two
pre-existing gates in detector.py's _slice_by_braces (#1631/#1632,
guarding against a phantom parameter-type annotation and a ternary
false-positive) assumed `match.start() - 1`/`match.start() - 2` was
always the newline immediately preceding true line-start -- an
assumption this widened anchor breaks, since a match can now start
right after a `,`/`{` mid-line. A first draft of this fix (caught and
reverted during verification, not shipped) regressed 6 real functions
elsewhere in the corpus this way. Fixed by having both gates
independently resolve the true start of the line containing the
CAPTURED NAME (`match.start(match.lastindex)`, falling back to
`match.start()` when lastindex is None) rather than trusting the
match's own start position.

Verified via the full 23-file typescript corpus diff against
tree-sitter: all 3 originally-targeted examples fixed (abort, report,
dispose), zero new regressions (the 6 introduced by the first draft
are all gone), missing-function count 131 -> 127 (a `firstParallel`
overload-collapse case newly surfaced by this widening is the same
pre-existing #2278-class bug, not a new one -- resolves once combined
with #2278's fix on main).

Fixes #2277.

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 fully attributable to the fix: abort/report/dispose
(and the confirmed downstream ripple into topological coordinates,
structural-magnitude aggregates, and Function Analysis top-N
reordering for the affected files/directory groups) now correctly
extracted. Independently re-verified against tree_sitter_accuracy_
audit.py's own tree-sitter walker before blessing, given #2278's own
verification pass on this same day caught a real discrepancy between
that tool and the corpus-diff approach used elsewhere in this sweep --
both tools agree here: extra_functions unchanged at the 12-baseline
for both typescript and javascript, found_functions genuinely
improved (2773 -> 2777), zero regressions.

tree_sitter_accuracy_audit --all --ci: all 31 languages OK.
audit_check --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 2 commits August 26, 2026 16:12
Resolves conflict with #2276 (now on main): both PRs touch the same
func_start branch (modifier-prefixed method shorthand) -- combined
#2276's catch/return/throw conditional exclusion with #2277's widened
line-start anchor into one regex, since both changes are independent
and compose cleanly. Golden masters taken from origin/main wholesale
and will be regenerated fresh against the merged code before pushing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@squid-protocol
squid-protocol merged commit 34faa33 into main Aug 26, 2026
27 of 28 checks passed
@squid-protocol
squid-protocol deleted the fix/typescript-2277-line-start-anchor branch August 26, 2026 20:19
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 misses arrow/method-shorthand definitions not at line start (comma-sibling properties, nested one-line call arguments)

1 participant