fix(analysis): assign AstNode to the scope a node introduces - #235
Open
keshav9926 wants to merge 1 commit into
Open
fix(analysis): assign AstNode to the scope a node introduces#235keshav9926 wants to merge 1 commit into
keshav9926 wants to merge 1 commit into
Conversation
Scope.AstNode is documented as "the AST node that introduces this scope
into the scope tree", but buildScopeTree assigned it on the *parent*
scope instead of the newly created one.
Two consequences:
- a new scope's own AstNode was never set, so every scope in the tree
reported nil except the synthetic root
- a parent's AstNode was overwritten by each scope-creating child in
turn, so it ended up holding whichever child was visited last
Concretely, for:
let x = 1
function f() { let y = 2 }
{ let z = 3 }
the program scope pointed at the trailing statement_block, the function
scope pointed at its own body, and both block scopes were nil.
Assign nextScope.AstNode instead. ScopeOfNode already mapped each node
to the correct scope, so GetScope was unaffected and nothing that
relied on it changes.
Adds Test_ScopeAstNode, which walks ScopeOfNode and asserts every scope
points at its own introducing node, plus explicit cases for the
parent-overwrite and function-vs-body confusions.
Signed-off-by: keshav9926 <kkakani160@gmail.com>
|
@keshav9926 is attempting to deploy a commit to the DeepSource Team on Vercel. A member of the Team first needs to authorize it. |
keshav9926
added a commit
to keshav9926/wright
that referenced
this pull request
Aug 7, 2026
docs/wright-index-readout.html shows what the index actually extracts: the three passes, the proof ladder over all 2,933 of globstar's call sites, four real queries with real answers, and the scope bug the recon surfaced. Every number comes from indexing DeepSourceCorp/globstar cold (105 files, 359 symbols, 137 co-change pairs). Self-contained: no network, no build step, works offline, follows the viewer light/dark theme. That recon produced an upstream contribution: DeepSourceCorp/globstar#235 fixes Scope.AstNode being assigned to the parent scope instead of the scope the node introduces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Description
Scope.AstNodeis documented as "the AST node that introduces this scope into the scope tree", butbuildScopeTreeassigned it on the parent scope rather than on the scope the node actually introduces:Two things follow from that:
AstNodewas never assigned, so every scope in the tree reportednilexcept the synthetic rootAstNodewas reassigned by each scope-creating child in turn, so it ended up holding whichever child was visited lastReproduction
For this source:
walking
ScopeOfNodeonmastergives:AstNodereportedprogramstatement_blockprogramfunction_declarationstatement_block(its own body)function_declarationstatement_blocknilstatement_blockstatement_blocknilstatement_blockFix
Assign
nextScope.AstNode = node.ScopeOfNodealready mapped each node to the correct scope, soGetScopewas never affected and nothing that relies on it changes behaviour — this only makes the field match its documented meaning.I found this while reading
ScopeBuilderto understand how scope resolution works before writing a checker. The field is exported on an exported type, so checker authors reaching forscope.AstNodecurrently getnilor the wrong node; that seemed worth fixing even though nothing in-tree reads it today.Type of change
Checklist
checkersdirectorymake testall)Test_ScopeAstNodewalksScopeOfNodeand asserts every scope points at its own introducing node, with explicit subtests for the parent-overwrite and function-vs-body cases. It fails onmasterwith:and passes with the fix.
On my machine (Windows)
TestFindYamlTestFilesfails both before and after this change, so it looks unrelated and pre-existing rather than something this PR introduces — happy to look into it separately if that's useful.Related Issues
None.
Additional Notes
This PR was developed with AI assistance (Claude); the bug was found by reading the scope builder, and the fix and tests were reviewed and verified locally before submission.