Skip to content

Commit 37497b5

Browse files
committed
test(go): pin both directions of per-function receiver scoping
test_the_first_binding_of_a_name_wins asserted the flat table's cross-function shadowing as intended behaviour, which the scoping fix removed; its fixture now pins that each function's parameter answers only its own calls.
1 parent d375863 commit 37497b5

1 file changed

Lines changed: 13 additions & 27 deletions

File tree

‎tests/test_go_receiver_member_calls.py‎

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -130,25 +130,6 @@ def test_two_packages_declaring_the_same_type_resolve_to_neither(tmp_path):
130130
assert _greet_edge(calls) is None, calls
131131

132132

133-
def test_the_first_binding_of_a_name_wins(tmp_path):
134-
# The table is flat per file, so a parameter named like an earlier one has to lose:
135-
# otherwise `other`'s signature would redirect the first function's calls.
136-
calls, result = _calls(tmp_path, {
137-
"svc/greeter.go": GREETER,
138-
"svc/other.go": "package svc\n\ntype Other struct{}\n\nfunc (o *Other) Greet() {}\n",
139-
"svc/app.go": "package svc\n\nfunc Run(g *Greeter) { g.Greet() }\n\n"
140-
"func Also(g *Other) { g.Greet() }\n",
141-
})
142-
source_of = {n["id"]: str(n.get("source_file") or "") for n in result["nodes"]}
143-
label_of = {n["id"]: n["label"] for n in result["nodes"]}
144-
run_targets = {source_of[e["target"]] for e in result["edges"]
145-
if e["relation"] == "calls"
146-
and label_of.get(e["source"]) == "Run()"
147-
and label_of.get(e["target"]) == ".Greet()"}
148-
assert len(run_targets) == 1, run_targets
149-
assert run_targets.pop().endswith("greeter.go")
150-
151-
152133
def test_a_same_file_method_call_keeps_its_extracted_edge(tmp_path):
153134
# In-file resolution still happens by bare label before this pass, so the edge must
154135
# stay EXTRACTED and must not be doubled.
@@ -189,12 +170,17 @@ def test_the_methods_own_receiver_outranks_an_earlier_binding_of_the_name(tmp_pa
189170
def test_a_parameter_binds_only_inside_its_own_function(tmp_path):
190171
# `s`, `c`, `w`, `r` get reused as parameter names by every function in a Go file, so a
191172
# table flat over the file answers one function's receiver with another's type.
192-
calls, _ = _calls(tmp_path, {
193-
"greeter.go": GREETER,
194-
"shouter.go": "package svc\n\ntype Shouter struct{}\n\nfunc (s *Shouter) Greet() {}\n",
195-
"use.go": ("package svc\n\nfunc First(g *Greeter) {}\n\n"
196-
"func Second(g *Shouter) {\n\tg.Greet()\n}\n"),
173+
calls, result = _calls(tmp_path, {
174+
"svc/greeter.go": GREETER,
175+
"svc/other.go": "package svc\n\ntype Other struct{}\n\nfunc (o *Other) Greet() {}\n",
176+
"svc/app.go": "package svc\n\nfunc Run(g *Greeter) { g.Greet() }\n\n"
177+
"func Also(g *Other) { g.Greet() }\n",
197178
})
198-
hits = [e for (src, tgt), e in calls.items() if src == "Second()" and tgt == ".Greet()"]
199-
assert len(hits) == 1, calls
200-
assert "shouter" in hits[0]["target"].lower(), hits[0]["target"]
179+
source_of = {n["id"]: str(n.get("source_file") or "") for n in result["nodes"]}
180+
label_of = {n["id"]: n["label"] for n in result["nodes"]}
181+
targets = {}
182+
for e in result["edges"]:
183+
if e["relation"] == "calls" and label_of.get(e["target"]) == ".Greet()":
184+
targets.setdefault(label_of.get(e["source"]), set()).add(source_of[e["target"]])
185+
assert len(targets["Run()"]) == 1 and targets["Run()"].pop().endswith("greeter.go"), targets
186+
assert len(targets["Also()"]) == 1 and targets["Also()"].pop().endswith("other.go"), targets

0 commit comments

Comments
 (0)