Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit da499ac

Browse files
author
Hendrik van Antwerpen
committed
Rewrite partial path tests to minimal partial path set
1 parent ac22267 commit da499ac

File tree

2 files changed

+58
-96
lines changed

2 files changed

+58
-96
lines changed

stack-graphs/src/c.rs

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,45 +1576,17 @@ pub extern "C" fn sg_partial_path_arena_find_partial_paths_in_file(
15761576
let partial_path_list = unsafe { &mut *partial_path_list };
15771577
let cancellation_flag: Option<&AtomicUsize> =
15781578
unsafe { std::mem::transmute(cancellation_flag.as_ref()) };
1579-
sg_partial_path_arena_find_partial_paths_in_file_inner(
1580-
graph,
1581-
partials,
1582-
file,
1583-
partial_path_list,
1584-
&AtomicUsizeCancellationFlag(cancellation_flag),
1585-
)
1586-
.into()
1587-
}
1588-
1589-
fn sg_partial_path_arena_find_partial_paths_in_file_inner(
1590-
graph: &StackGraph,
1591-
partials: &mut PartialPaths,
1592-
file: Handle<File>,
1593-
partial_path_list: &mut sg_partial_path_list,
1594-
cancellation_flag: &dyn CancellationFlag,
1595-
) -> Result<(), CancellationError> {
1596-
let mut db = Database::new();
1597-
partials.find_minimal_partial_paths_set_in_file(
1598-
graph,
1599-
file,
1600-
cancellation_flag,
1601-
|graph, partials, path| {
1602-
db.add_partial_path(graph, partials, path);
1603-
},
1604-
)?;
1605-
#[allow(deprecated)]
1606-
ForwardPartialPathStitcher::find_locally_complete_partial_paths(
1607-
graph,
1608-
partials,
1609-
&mut db,
1610-
cancellation_flag,
1611-
|_graph, partials, path| {
1612-
let mut path = path.clone();
1613-
path.ensure_both_directions(partials);
1614-
partial_path_list.partial_paths.push(path);
1615-
},
1616-
)?;
1617-
Ok(())
1579+
partials
1580+
.find_minimal_partial_paths_set_in_file(
1581+
graph,
1582+
file,
1583+
&AtomicUsizeCancellationFlag(cancellation_flag),
1584+
|_graph, partials, mut path| {
1585+
path.ensure_both_directions(partials);
1586+
partial_path_list.partial_paths.push(path);
1587+
},
1588+
)
1589+
.into()
16181590
}
16191591

16201592
/// A handle to a partial path in a partial path database. A zero handle represents a missing

stack-graphs/tests/it/can_find_partial_paths_in_file.rs

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,24 @@ use std::collections::BTreeSet;
1010
use pretty_assertions::assert_eq;
1111
use stack_graphs::graph::StackGraph;
1212
use stack_graphs::partial::PartialPaths;
13-
use stack_graphs::stitching::Database;
14-
use stack_graphs::stitching::ForwardPartialPathStitcher;
1513
use stack_graphs::NoCancellation;
1614

1715
use crate::test_graphs;
1816

1917
fn check_partial_paths_in_file(graph: &StackGraph, file: &str, expected_paths: &[&str]) {
2018
let file = graph.get_file_unchecked(file);
2119
let mut partials = PartialPaths::new();
22-
let mut db = Database::new();
20+
let mut results = BTreeSet::new();
2321
partials
2422
.find_minimal_partial_paths_set_in_file(
2523
graph,
2624
file,
2725
&NoCancellation,
2826
|graph, partials, path| {
29-
db.add_partial_path(graph, partials, path);
27+
results.insert(path.display(graph, partials).to_string());
3028
},
3129
)
3230
.expect("should never be cancelled");
33-
let mut results = BTreeSet::new();
34-
#[allow(deprecated)]
35-
ForwardPartialPathStitcher::find_locally_complete_partial_paths(
36-
graph,
37-
&mut partials,
38-
&mut db,
39-
&NoCancellation,
40-
|g, ps, p| {
41-
results.insert(p.display(g, ps).to_string());
42-
},
43-
)
44-
.expect("should never be cancelled");
4531
let expected_paths = expected_paths
4632
.iter()
4733
.map(|s| s.to_string())
@@ -53,53 +39,48 @@ pub(crate) static CLASS_FIELD_THROUGH_FUNCTION_PARAMETER_MAIN_PATHS: &[&str] = &
5339
// definition of `__main__` module
5440
"<__main__,%1> ($1) [root] -> [main.py(0) definition __main__] <%1> ($1)",
5541
// reference to `a` in import statement
42+
"<%1> ($1) [main.py(15) reference b] -> [root] <b,%1> ($1)",
43+
// reference to `b` in import statement
5644
"<%1> ($1) [main.py(17) reference a] -> [root] <a,%1> ($1)",
5745
// `from a import *` means we can rewrite any lookup of `__main__.*` → `a.*`
58-
"<__main__.,%2> ($1) [root] -> [root] <a.,%2> ($1)",
59-
// reference to `b` in import statement
60-
"<%1> ($1) [main.py(15) reference b] -> [root] <b,%1> ($1)",
46+
"<__main__.,%1> ($1) [main.py(0) definition __main__] -> [main.py(15) reference b] <b.,%1> ($1)",
6147
// `from b import *` means we can rewrite any lookup of `__main__.*` → `b.*`
62-
"<__main__.,%2> ($1) [root] -> [root] <b.,%2> ($1)",
48+
"<__main__.,%1> ($1) [main.py(0) definition __main__] -> [main.py(17) reference a] <a.,%1> ($1)",
6349
// we can look for every reference in either `a` or `b`
64-
"<%1> ($1) [main.py(9) reference A] -> [root] <a.A,%1> ($1)",
65-
"<%1> ($1) [main.py(9) reference A] -> [root] <b.A,%1> ($1)",
66-
"<%1> ($1) [main.py(10) reference bar] -> [root] <a.foo()/([main.py(7)],$1).bar,%1> ($1)",
67-
"<%1> ($1) [main.py(10) reference bar] -> [root] <b.foo()/([main.py(7)],$1).bar,%1> ($1)",
68-
"<%1> ($1) [main.py(13) reference foo] -> [root] <a.foo,%1> ($1)",
69-
"<%1> ($1) [main.py(13) reference foo] -> [root] <b.foo,%1> ($1)",
70-
// parameter 0 of function call is `A`, which we can look up in either `a` or `b`
71-
"<0,%1> ($1) [main.py(7) exported scope] -> [root] <a.A,%1> ($1)",
72-
"<0,%1> ($1) [main.py(7) exported scope] -> [root] <b.A,%1> ($1)",
50+
"<%1> ($1) [main.py(13) reference foo] -> [main.py(15) reference b] <b.foo,%1> ($1)",
51+
"<%1> ($1) [main.py(13) reference foo] -> [main.py(17) reference a] <a.foo,%1> ($1)",
52+
"<%1> ($1) [main.py(9) reference A] -> [main.py(15) reference b] <b.A,%1> ($1)",
53+
"<%1> ($1) [main.py(9) reference A] -> [main.py(17) reference a] <a.A,%1> ($1)",
54+
// we look up the field `bar` in the return type of `foo` applied to ...
55+
"<%1> ($1) [main.py(10) reference bar] -> [main.py(13) reference foo] <foo()/([main.py(7)],$1).bar,%1> ($1)",
56+
// ... `A`, which is parameter 0 of function call
57+
"<0,%1> ($1) [main.py(7) exported scope] -> [main.py(9) reference A] <A,%1> ($1)",
7358
];
7459

7560
pub(crate) static CLASS_FIELD_THROUGH_FUNCTION_PARAMETER_A_PATHS: &[&str] = &[
7661
// definition of `a` module
7762
"<a,%1> ($1) [root] -> [a.py(0) definition a] <%1> ($1)",
7863
// definition of `foo` function
79-
"<a.foo,%2> ($1) [root] -> [a.py(5) definition foo] <%2> ($1)",
64+
"<a.foo,%1> ($1) [a.py(0) definition a] -> [a.py(5) definition foo] <%1> ($1)",
65+
// which, when applied, returns its return expression
66+
"<foo()/($2),%1> ($1) [a.py(5) definition foo] -> [a.py(8) reference x] <x,%1> ($2)",
8067
// reference to `x` in function body can resolve to formal parameter, which might get formal parameters...
8168
"<%1> ($1) [a.py(8) reference x] -> [a.py(14) definition x] <%1> ()",
8269
// ...which we can look up either the 0th actual positional parameter...
8370
"<%1> ($1) [a.py(8) reference x] -> [jump to scope] <0,%1> ($1)",
8471
// ...or the actual named parameter `x`
8572
"<%1> ($1) [a.py(8) reference x] -> [jump to scope] <x,%1> ($1)",
86-
// result of function is `x`, which is passed in as a formal parameter...
87-
"<a.foo()/($3),%3> ($1) [root] -> [a.py(14) definition x] <%3> ()",
88-
// ...which we can look up either the 0th actual positional parameter...
89-
"<a.foo()/($3),%3> ($1) [root] -> [jump to scope] <0,%3> ($3)",
90-
// ...or the actual named parameter `x`
91-
"<a.foo()/($3),%3> ($1) [root] -> [jump to scope] <x,%3> ($3)",
9273
];
9374

9475
pub(crate) static CLASS_FIELD_THROUGH_FUNCTION_PARAMETER_B_PATHS: &[&str] = &[
9576
// definition of `b` module
9677
"<b,%1> ($1) [root] -> [b.py(0) definition b] <%1> ($1)",
9778
// definition of class `A`
98-
"<b.A,%2> ($1) [root] -> [b.py(5) definition A] <%2> ($1)",
79+
"<b.A,%1> ($1) [b.py(0) definition b] -> [b.py(5) definition A] <%1> ($1)",
9980
// definition of class member `A.bar`
100-
"<b.A.bar,%3> ($1) [root] -> [b.py(8) definition bar] <%3> ($1)",
81+
"<A.bar,%1> ($1) [b.py(5) definition A] -> [b.py(8) definition bar] <%1> ($1)",
10182
// `bar` can also be accessed as an instance member
102-
"<b.A()/($3).bar,%3> ($1) [root] -> [b.py(8) definition bar] <%3> ($3)",
83+
"<A()/($2).bar,%1> ($1) [b.py(5) definition A] -> [b.py(8) definition bar] <%1> ($2)",
10384
];
10485

10586
#[test]
@@ -128,9 +109,9 @@ pub(crate) const CYCLIC_IMPORTS_PYTHON_MAIN_PATHS: &[&str] = &[
128109
// reference to `a` in import statement
129110
"<%1> ($1) [main.py(8) reference a] -> [root] <a,%1> ($1)",
130111
// `from a import *` means we can rewrite any lookup of `__main__.*` → `a.*`
131-
"<__main__.,%2> ($1) [root] -> [root] <a.,%2> ($1)",
112+
"<__main__.,%1> ($1) [main.py(0) definition __main__] -> [main.py(8) reference a] <a.,%1> ($1)",
132113
// reference to `foo` becomes `a.foo` because of import statement
133-
"<%1> ($1) [main.py(6) reference foo] -> [root] <a.foo,%1> ($1)",
114+
"<%1> ($1) [main.py(6) reference foo] -> [main.py(8) reference a] <a.foo,%1> ($1)",
134115
];
135116

136117
pub(crate) const CYCLIC_IMPORTS_PYTHON_A_PATHS: &[&str] = &[
@@ -139,7 +120,7 @@ pub(crate) const CYCLIC_IMPORTS_PYTHON_A_PATHS: &[&str] = &[
139120
// reference to `b` in import statement
140121
"<%1> ($1) [a.py(6) reference b] -> [root] <b,%1> ($1)",
141122
// `from b import *` means we can rewrite any lookup of `a.*` → `b.*`
142-
"<a.,%2> ($1) [root] -> [root] <b.,%2> ($1)",
123+
"<a.,%1> ($1) [a.py(0) definition a] -> [a.py(6) reference b] <b.,%1> ($1)",
143124
];
144125

145126
pub(crate) const CYCLIC_IMPORTS_PYTHON_B_PATHS: &[&str] = &[
@@ -148,9 +129,9 @@ pub(crate) const CYCLIC_IMPORTS_PYTHON_B_PATHS: &[&str] = &[
148129
// reference to `a` in import statement
149130
"<%1> ($1) [b.py(8) reference a] -> [root] <a,%1> ($1)",
150131
// `from a import *` means we can rewrite any lookup of `b.*` → `a.*`
151-
"<b.,%2> ($1) [root] -> [root] <a.,%2> ($1)",
132+
"<b.,%1> ($1) [b.py(0) definition b] -> [b.py(8) reference a] <a.,%1> ($1)",
152133
// definition of `foo`
153-
"<b.foo,%2> ($1) [root] -> [b.py(6) definition foo] <%2> ($1)",
134+
"<b.foo,%1> ($1) [b.py(0) definition b] -> [b.py(6) definition foo] <%1> ($1)",
154135
];
155136

156137
#[test]
@@ -164,17 +145,26 @@ fn cyclic_imports_python() {
164145
// NOTE: Because everything in this example is local to one file, there aren't any partial
165146
// paths involving the root node.
166147
pub(crate) const CYCLIC_IMPORTS_RUST_PATHS: &[&str] = &[
148+
// reference to `b` in `a` module
149+
"<%1> ($1) [test.rs(206) reference b] -> [test.rs(301) definition b] <%1> ($1)",
150+
// `pub use crate::b::*` means we can import via `b` from `a`
151+
"<a::,%1> ($1) [test.rs(201) definition a] -> [test.rs(206) reference b] <b::,%1> ($1)",
152+
// definition of `BAR` in `a` module
153+
"<a::BAR,%1> ($1) [test.rs(201) definition a] -> [test.rs(204) definition BAR] <%1> ($1)",
154+
// reference to `a` in `b` module
155+
"<%1> ($1) [test.rs(307) reference a] -> [test.rs(201) definition a] <%1> ($1)",
156+
// `pub use crate::a::*` means we can import via `a` from `b`
157+
"<b::,%1> ($1) [test.rs(301) definition b] -> [test.rs(307) reference a] <a::,%1> ($1)",
158+
// definition of `FOO` in `b` module ...
159+
"<b::FOO,%1> ($1) [test.rs(301) definition b] -> [test.rs(304) definition FOO] <%1> ($1)",
160+
// ... which aliases `BAR` ...
161+
"<FOO,%1> ($1) [test.rs(304) definition FOO] -> [test.rs(305) reference BAR] <BAR,%1> ($1)",
162+
// ... which can be imported via `a`
163+
"<%1> ($1) [test.rs(305) reference BAR] -> [test.rs(307) reference a] <a::BAR,%1> ($1)",
167164
// reference to `a` in `main` function
168165
"<%1> ($1) [test.rs(103) reference a] -> [test.rs(201) definition a] <%1> ($1)",
169-
// reference to `a` in `b` function
170-
"<%1> ($1) [test.rs(307) reference a] -> [test.rs(201) definition a] <%1> ($1)",
171-
// reference to `b` in `a` function
172-
"<%1> ($1) [test.rs(206) reference b] -> [test.rs(301) definition b] <%1> ($1)",
173-
// reference to `FOO` in `main` can resolve either to `a::BAR` or `b::FOO`
174-
"<%1> ($1) [test.rs(101) reference FOO] -> [test.rs(204) definition BAR] <%1> ($1)",
175-
"<%1> ($1) [test.rs(101) reference FOO] -> [test.rs(304) definition FOO] <%1> ($1)",
176-
// reference to `BAR` in `b` resolves _only_ to `a::BAR`
177-
"<%1> ($1) [test.rs(305) reference BAR] -> [test.rs(204) definition BAR] <%1> ($1)",
166+
// reference to `FOO` in `main` can resolve via `a`
167+
"<%1> ($1) [test.rs(101) reference FOO] -> [test.rs(103) reference a] <a::FOO,%1> ($1)",
178168
];
179169

180170
#[test]
@@ -189,9 +179,9 @@ pub(crate) const SEQUENCED_IMPORT_STAR_MAIN_PATHS: &[&str] = &[
189179
// reference to `a` in import statement
190180
"<%1> ($1) [main.py(8) reference a] -> [root] <a,%1> ($1)",
191181
// `from a import *` means we can rewrite any lookup of `__main__.*` → `a.*`
192-
"<__main__.,%2> ($1) [root] -> [root] <a.,%2> ($1)",
182+
"<__main__.,%1> ($1) [main.py(0) definition __main__] -> [main.py(8) reference a] <a.,%1> ($1)",
193183
// reference to `foo` becomes `a.foo` because of import statement
194-
"<%1> ($1) [main.py(6) reference foo] -> [root] <a.foo,%1> ($1)",
184+
"<%1> ($1) [main.py(6) reference foo] -> [main.py(8) reference a] <a.foo,%1> ($1)",
195185
];
196186

197187
pub(crate) const SEQUENCED_IMPORT_STAR_A_PATHS: &[&str] = &[
@@ -200,14 +190,14 @@ pub(crate) const SEQUENCED_IMPORT_STAR_A_PATHS: &[&str] = &[
200190
// reference to `b` in import statement
201191
"<%1> ($1) [a.py(6) reference b] -> [root] <b,%1> ($1)",
202192
// `from b import *` means we can rewrite any lookup of `a.*` → `b.*`
203-
"<a.,%2> ($1) [root] -> [root] <b.,%2> ($1)",
193+
"<a.,%1> ($1) [a.py(0) definition a] -> [a.py(6) reference b] <b.,%1> ($1)",
204194
];
205195

206196
pub(crate) const SEQUENCED_IMPORT_STAR_B_PATHS: &[&str] = &[
207197
// definition of `b` module
208198
"<b,%1> ($1) [root] -> [b.py(0) definition b] <%1> ($1)",
209199
// definition of `foo` inside of `b` module
210-
"<b.foo,%2> ($1) [root] -> [b.py(5) definition foo] <%2> ($1)",
200+
"<b.foo,%1> ($1) [b.py(0) definition b] -> [b.py(5) definition foo] <%1> ($1)",
211201
];
212202

213203
#[test]

0 commit comments

Comments
 (0)