Skip to content

fix(scanner): detect same-scope method values, closing #6#25

Merged
flaglint merged 1 commit into
mainfrom
fix/same-scope-method-values
Jul 7, 2026
Merged

fix(scanner): detect same-scope method values, closing #6#25
flaglint merged 1 commit into
mainfrom
fix/same-scope-method-values

Conversation

@flaglint

@flaglint flaglint commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #6 (the issue's own literal repro). f := client.BoolVariation; f("flag", nil, false) was not detected — detection required the method to be called directly through a selector expression at the call site itself, not via an intermediate variable holding just the method value.

What changed

  • New binding kind, methodValueBinding (identifier → SDK version + method name), tracked by walkScoped with the exact same block-scoped lexical-shadowing semantics as regular client bindings (scanner: block-scoped variable shadowing within a single function can cause a false positive #5's fix) — scopeBindings now bundles both kinds together so a single push/pop always moves them in lockstep, since they share the same scoping rules.
  • bindLocalValue recognizes f := client.BoolVariation (bare selector, no call parens, receiver already a proven client, method name a recognized SDK method) and binds f as a method value; anything else continues to unbind both kinds for that name, exactly as before.
  • fileDetector.detect now resolves a call's version+method name via either path: the existing selector-expression receiver resolution, or (new) a bare-identifier call resolving through methodValues.

Scope boundary (important)

Deliberately narrow, matching the issue's own repro: only a plain identifier receiver is recognized (client.BoolVariation), not a struct-field chain. A method value passed across a function boundary — captured in one function, called from inside a different one it was passed into, which is the shape a real e2b-dev/infra field-testing repro actually needed (see the comment on #6) — is not resolved by this fix. That's a meaningfully larger interprocedural-propagation problem; I'll file it as a separate, precisely-scoped issue after this merges rather than leave it silently unaddressed under #6's now-closed title.

Verification

  • New fixtures prove the same-scope repro is detected, a false-positive guard proves an unrelated same-named method value isn't, and a combined fixture proves method-value bindings correctly follow the same block-scoped shadowing rules as client bindings (issue scanner: block-scoped variable shadowing within a single function can cause a false positive #5).
  • Full test suite green.
  • Re-verified against weaviate (unchanged, 4 real usages, no regression) and e2b-dev/infra (still correctly 0 — its cross-function case remains open, as scoped above).

f := client.BoolVariation; f("flag", nil, false) was not detected —
detection required the method to be called directly through a selector
expression at the call site itself, not via an intermediate variable
holding just the method value.

Added a new binding kind, methodValueBinding (identifier -> SDK version +
method name), tracked by walkScoped with the exact same block-scoped
lexical-shadowing semantics as regular client bindings (issue #5's fix) —
scopeBindings now bundles both kinds together in one struct so a single
push/pop always moves them in lockstep, since they share the same scoping
rules. bindLocalValue recognizes `f := client.BoolVariation` (a bare
selector, no call parens, receiver already a proven client, method name a
recognized SDK method) and binds f as a method value; anything else
continues to unbind both kinds for that name, exactly as before for plain
client bindings.

fileDetector.detect now resolves a call's version+method name via either
path: the existing selector-expression receiver resolution, or (new) a
bare-identifier call resolving through methodValues.

Deliberately narrow, matching the issue's own repro: only a plain
identifier receiver is recognized (`client.BoolVariation`), not a
struct-field chain (`obj.field.BoolVariation`). A method value passed
*across a function boundary* — captured in one function, called from
inside a different one it was passed into, which is the shape a real
e2b-dev/infra field-testing repro actually needed (see the comment on
#6) — is NOT resolved by this fix; that's a meaningfully larger
interprocedural-propagation problem, filed separately rather than
silently left unaddressed.

Verified: new fixtures prove the same-scope repro is detected, a
false-positive guard proves an unrelated same-named method value isn't,
and a combined fixture proves method-value bindings correctly follow the
same block-scoped shadowing rules as client bindings. Full test suite
green. Re-verified against weaviate (unchanged, 4 real usages, no
regression) and e2b-dev/infra (still correctly 0 — its cross-function
case remains open, as scoped above).

Fixes #6

Signed-off-by: Krishan Kant Sharma <krishansharma0327@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@flaglint, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f0fa4b62-61f4-42d6-be49-44fda80f53a4

📥 Commits

Reviewing files that changed from the base of the PR and between 8e4373b and e8fb9ea.

📒 Files selected for processing (6)
  • internal/scanner/identity.go
  • internal/scanner/scanner.go
  • internal/scanner/scanner_test.go
  • internal/scanner/testdata/fixtures/false_positive_method_value_unrelated.go
  • internal/scanner/testdata/fixtures/positive_method_value.go
  • internal/scanner/testdata/fixtures/positive_method_value_block_scoped.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/same-scope-method-values

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@flaglint flaglint merged commit 4af5a95 into main Jul 7, 2026
13 checks passed
@flaglint flaglint deleted the fix/same-scope-method-values branch July 7, 2026 16:18
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.

scanner: method-value indirection (f := client.BoolVariation) is not detected

2 participants