fix: nested call context misattribution and multi-line import capture#1292
Open
MorningStar0709 wants to merge 1 commit into
Open
fix: nested call context misattribution and multi-line import capture#1292MorningStar0709 wants to merge 1 commit into
MorningStar0709 wants to merge 1 commit into
Conversation
… capture
Two related bugs in the Python parser that cause dead-code false
positives and missing cross-file CALLS edges:
1. Nested call context misattribution (Type A)
When a function call is nested inside a method's arguments
(e.g. results.append(_helper(data))), the inner call's context
was incorrectly set to the method name ("append") instead of the
enclosing function ("process"). Since method names are not
Function nodes in the graph, this creates orphan CALLS edges and
causes dead-code analysis to report false positives.
Fix: Pass local_names (set of locally defined function/class
names) through _walk_call_tree. In _record_call, only use
enclosing_caller as context when it is in local_names; otherwise
fall back to _get_parent_context. In _walk_call_tree, only
propagate called_name as next enclosing_caller for direct calls
(identifier type); attribute calls (obj.method()) should not act
as nested callers.
2. Multi-line from...import capture (Type B1)
_find_imports used child_by_field_name('name') which only returns
the first import name. For multi-line imports like
from pkg import (a, b, c, d, e), only 'a' was captured and the
remaining 4 names were silently dropped, breaking cross-file
CALLS edge resolution.
Fix: Use children_by_field_name('name') to capture ALL imported
names from from...import statements.
3. Stale test assertion fix
test_parse_simple_function expected len(funcs) == 1 but
_attach_module_context injects a synthetic <module> frame.
Updated to filter out <module> before asserting.
Tests:
- test_nested_call_inside_method_uses_enclosing_function_context
- test_method_name_collision_uses_enclosing_function_context
- test_multiline_from_import_captures_all_names
- test_multiline_from_import_with_alias
All 9 Python parser tests pass.
|
@MorningStar0709 is attempting to deploy a commit to the shashankss1205's projects Team on Vercel. A member of the Team first needs to authorize it. |
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 two related bugs in the Python parser that cause dead-code false positives and missing cross-file CALLS edges.
Root Cause
Bug 1: Nested call context misattribution
When a function call is nested inside a method call's arguments, e.g.:
The
_walk_call_treemethod propagatedcalled_name(the method nameappend) as theenclosing_callerfor nested calls. Sinceappendis not a Function node in the graph, this creates orphan CALLS edges (pointing to nothing), causing the dead-code analysis to incorrectly report_helperas unused.Bug 2: Multi-line
from...importonly captures first name_find_importsusedchild_by_field_name('name')(singular) which only returns the first import name from a tree-sitter node. For multi-line imports like:Only
VERSIONwas captured; the remaining 4 names were silently dropped. This breaks cross-file CALLS edge resolution for all subsequent imports in the same statement.Changes
src/codegraphcontext/tools/languages/python.pyNested call context fix:
local_names(set of all locally defined function/class names) before calling_find_callslocal_namesthrough_find_calls→_walk_call_tree→_record_call_record_call: only useenclosing_calleras context when it is inlocal_names; otherwise fall back to_get_parent_context(which returns the actual enclosing function)_walk_call_tree: only propagatecalled_nameas nextenclosing_callerfor direct calls (identifiertype); attribute calls (obj.method()) should not act as nested callers since they are method invocations, not local function definitionsMulti-line import fix:
child_by_field_name('name')withchildren_by_field_name('name')in_find_importsto capture ALL imported names fromfrom...importstatementstests/unit/parsers/test_python_parser.pyNew tests:
test_nested_call_inside_method_uses_enclosing_function_context— verifiesresults.append(_helper(data))attributes_helper's context to the enclosing function, notappendtest_method_name_collision_uses_enclosing_function_context— verifies that when a local function shares a name with a method (e.g.def append(...)+results.append(append(data))), the inner call still attributes to the enclosing functiontest_multiline_from_import_captures_all_names— verifies all 5 names in a parenthesized import are capturedtest_multiline_from_import_with_alias— verifiesfrom X import Y as Zcaptures both name and alias correctlyFixed stale test:
test_parse_simple_function— updated to filter out synthetic<module>frame injected by_attach_module_contextbefore asserting function countTesting
All 9 Python parser tests pass, including:
Full parser test suite (165 tests) also passes with no regressions.
Impact
list.append(helper()),all(check(x) for x in ...)) are now correctly attributed to their enclosing function, preventing orphan CALLS edgesfrom...importstatements now correctly capture all imported names, enabling proper cross-file call resolutionNonedefaults; existing behavior is preserved whenlocal_namesis not provided