Skip to content

Commit 09b7adc

Browse files
committed
Add path support for marking test modules
1 parent 95b0c4c commit 09b7adc

File tree

4 files changed

+105
-9
lines changed

4 files changed

+105
-9
lines changed

crates/ra_analysis/src/imp.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,23 @@ impl AnalysisImpl {
201201
let source_root = self.db.file_source_root(file_id);
202202
self.db.module_tree(source_root)
203203
}
204+
pub(crate) fn module_path(&self, file_id: FileId) -> Cancelable<String> {
205+
let mut current_file_id = file_id;
206+
let mut path = "".to_string();
207+
loop {
208+
if let Some((file_id, file_symbol)) = self.parent_module(current_file_id)?.first() {
209+
path = format!("{}::{}", file_symbol.name, path);
210+
current_file_id = *file_id;
211+
} else {
212+
break;
213+
}
214+
}
215+
216+
Ok(path.to_string())
217+
}
204218
pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
205219
let module_tree = self.module_tree(file_id)?;
220+
println!("{:?}", module_tree);
206221

207222
let res = module_tree.modules_for_file(file_id)
208223
.into_iter()

crates/ra_analysis/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ impl Analysis {
263263
pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
264264
self.imp.parent_module(file_id)
265265
}
266+
pub fn module_path(&self, file_id: FileId) -> Cancelable<String> {
267+
self.imp.module_path(file_id)
268+
}
266269
pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
267270
self.imp.crate_for(file_id)
268271
}
@@ -271,7 +274,8 @@ impl Analysis {
271274
}
272275
pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
273276
let file = self.imp.file_syntax(file_id);
274-
Ok(runnables::runnables(&file))
277+
let path = self.imp.module_path(file_id)?;
278+
Ok(runnables::runnables(&file, &path))
275279
}
276280
pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
277281
let file = self.imp.file_syntax(file_id);

crates/ra_analysis/src/runnables.rs

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ pub enum RunnableKind {
1818
Bin,
1919
}
2020

21-
pub fn runnables(file: &File) -> Vec<Runnable> {
21+
pub fn runnables(file: &File, module_path: &str) -> Vec<Runnable> {
2222
file.syntax()
2323
.descendants()
24-
.filter_map(runnable)
24+
.filter_map(|i| runnable(i, module_path))
2525
.collect()
2626
}
2727

28-
fn runnable<'a>(item: SyntaxNodeRef<'a>) -> Option<Runnable> {
28+
fn runnable<'a>(item: SyntaxNodeRef<'a>, module_path: &str) -> Option<Runnable> {
2929
if let Some(f) = ast::FnDef::cast(item) {
3030
let name = f.name()?.text();
3131
let kind = if name == "main" {
@@ -48,10 +48,25 @@ fn runnable<'a>(item: SyntaxNodeRef<'a>) -> Option<Runnable> {
4848
.map(ast::ModuleItem::syntax)
4949
.filter_map(ast::FnDef::cast)
5050
.any(|f| f.has_atom_attr("test")) {
51+
let mut current_module = m;
52+
let mut path = String::new();
53+
loop {
54+
if let Some(item_list) = current_module.syntax().parent().and_then(ast::ItemList::cast) {
55+
if let Some(m) = item_list.syntax().parent().and_then(ast::Module::cast){
56+
path = format!("{}::{}", m.name().unwrap().text(), path);
57+
current_module = m;
58+
} else {
59+
break;
60+
}
61+
} else {
62+
break;
63+
}
64+
}
65+
5166
Some(Runnable {
5267
range: m.syntax().range(),
5368
kind: RunnableKind::TestMod {
54-
path: name.to_string()
69+
path: format!("{}::{}{}", module_path, path, name),
5570
}
5671
})
5772
}else {
@@ -81,7 +96,7 @@ fn test_foo() {}
8196
fn test_foo() {}
8297
"#,
8398
);
84-
let runnables = runnables(&file);
99+
let runnables = runnables(&file, "");
85100
assert_eq_dbg(
86101
r#"[Runnable { range: [1; 13), kind: Bin },
87102
Runnable { range: [15; 39), kind: Test { name: "test_foo" } },
@@ -100,14 +115,56 @@ mod test_mod {
100115
}
101116
"#,
102117
);
103-
let runnables = runnables(&file);
118+
let runnables = runnables(&file, "parent");
104119
assert_eq_dbg(
105-
r#"[Runnable { range: [1; 51), kind: TestMod { path: "test_mod" } },
120+
r#"[Runnable { range: [1; 51), kind: TestMod { path: "parent::test_mod" } },
106121
Runnable { range: [20; 49), kind: Test { name: "test_foo1" } }]"#,
107122
&runnables,
108123
)
109124
}
110125

126+
#[test]
127+
fn test_runnables_one_depth_layer_module() {
128+
let file = File::parse(
129+
r#"
130+
mod foo {
131+
mod test_mod {
132+
#[test]
133+
fn test_foo1() {}
134+
}
135+
}
136+
"#,
137+
);
138+
let runnables = runnables(&file, "parent");
139+
assert_eq_dbg(
140+
r#"[Runnable { range: [15; 77), kind: TestMod { path: "parent::foo::test_mod" } },
141+
Runnable { range: [38; 71), kind: Test { name: "test_foo1" } }]"#,
142+
&runnables,
143+
)
144+
}
145+
146+
#[test]
147+
fn test_runnables_multiple_depth_module() {
148+
let file = File::parse(
149+
r#"
150+
mod foo {
151+
mod bar {
152+
mod test_mod {
153+
#[test]
154+
fn test_foo1() {}
155+
}
156+
}
157+
}
158+
"#,
159+
);
160+
let runnables = runnables(&file, "parent");
161+
assert_eq_dbg(
162+
r#"[Runnable { range: [33; 107), kind: TestMod { path: "parent::foo::bar::test_mod" } },
163+
Runnable { range: [60; 97), kind: Test { name: "test_foo1" } }]"#,
164+
&runnables,
165+
)
166+
}
167+
111168
#[test]
112169
fn test_runnables_no_test_function_in_module() {
113170
let file = File::parse(
@@ -117,7 +174,7 @@ mod test_mod {
117174
}
118175
"#,
119176
);
120-
let runnables = runnables(&file);
177+
let runnables = runnables(&file, "");
121178
assert_eq_dbg(
122179
r#"[]"#,
123180
&runnables,

crates/ra_analysis/tests/tests.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,26 @@ fn test_resolve_parent_module() {
123123
);
124124
}
125125

126+
#[test]
127+
fn test_path_one_layer() {
128+
let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo/mod.rs", "mod bla;"), ("/foo/bla.rs", "")]);
129+
let symbols = snap.module_path(FileId(3)).unwrap();
130+
assert_eq!(
131+
"foo::bla::",
132+
&symbols,
133+
);
134+
}
135+
136+
#[test]
137+
fn test_path_two_layer() {
138+
let snap = analysis(&[("/lib.rs", "mod foo;"), ("/foo/mod.rs", "mod bla;"), ("/foo/bla/mod.rs", "mod more;"), ("/foo/bla/more.rs", "")]);
139+
let symbols = snap.module_path(FileId(4)).unwrap();
140+
assert_eq!(
141+
"foo::bla::more::",
142+
&symbols,
143+
);
144+
}
145+
126146
#[test]
127147
fn test_resolve_crate_root() {
128148
let mut host = analysis_host(&[("/lib.rs", "mod foo;"), ("/foo.rs", "")]);

0 commit comments

Comments
 (0)