Skip to content

Commit

Permalink
Consider access information when computing qualified names for nodes (#…
Browse files Browse the repository at this point in the history
…682)

* Write a test case showing qualified names for shadowed assignments

* Consider accesses when looking up names of nodes

* Fix format

* Fix typecheck
  • Loading branch information
lpetre authored May 4, 2022
1 parent c30bbcf commit c655967
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 1 deletion.
16 changes: 16 additions & 0 deletions libcst/metadata/scope_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,22 @@ def f(self) -> "c":
considering it could be a complex type annotation in the string which is hard to
resolve, e.g. ``List[Union[int, str]]``.
"""

# if this node is an access we know the assignment and we can use that name
node_accesses = {
access
for all_accesses in self._accesses.values()
for access in all_accesses
if access.node == node
}
if node_accesses:
return {
qname
for access in node_accesses
for referent in access.referents
for qname in referent.get_qualified_names_for(referent.name)
}

results = set()
full_name = get_full_name_for_node(node)
if full_name is None:
Expand Down
34 changes: 33 additions & 1 deletion libcst/metadata/tests/test_name_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ def g():
cls = ensure_type(m.body[1], cst.ClassDef)
f = ensure_type(cls.body.body[0], cst.FunctionDef)
self.assertEqual(
names[ensure_type(f.returns, cst.Annotation).annotation], set()
names[ensure_type(f.returns, cst.Annotation).annotation],
{QualifiedName("a.b.c", QualifiedNameSource.IMPORT)},
)

c_call = ensure_type(
Expand Down Expand Up @@ -414,6 +415,37 @@ def f(): pass
},
)

def test_shadowed_assignments(self) -> None:
m, names = get_qualified_name_metadata_provider(
"""
from lib import a,b,c
a = a
class Test:
b = b
def func():
c = c
"""
)

# pyre-fixme[53]: Captured variable `names` is not annotated.
def test_name(node: cst.CSTNode, qnames: Set[QualifiedName]) -> None:
name = ensure_type(
ensure_type(node, cst.SimpleStatementLine).body[0], cst.Assign
).value
self.assertEqual(names[name], qnames)

test_name(m.body[1], {QualifiedName("lib.a", QualifiedNameSource.IMPORT)})

cls = ensure_type(m.body[2], cst.ClassDef)
test_name(
cls.body.body[0], {QualifiedName("lib.b", QualifiedNameSource.IMPORT)}
)

func = ensure_type(m.body[3], cst.FunctionDef)
test_name(
func.body.body[0], {QualifiedName("lib.c", QualifiedNameSource.IMPORT)}
)


class FullyQualifiedNameProviderTest(UnitTest):
@data_provider(
Expand Down

0 comments on commit c655967

Please sign in to comment.