Skip to content

Commit f0411ff

Browse files
bors[bot]bnjjj
andauthored
Merge #4320
4320: add doctest support r=matklad a=bnjjj close #4317 preview: <img width="253" alt="Capture d’écran 2020-05-05 à 17 39 58" src="https://user-images.githubusercontent.com/5719034/81086040-45110b80-8ef8-11ea-9c05-79c6fe400fc3.png"> Co-authored-by: Benjamin Coenen <[email protected]>
2 parents 58f6431 + fe52f8f commit f0411ff

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

crates/ra_ide/src/runnables.rs

+43
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use ra_syntax::{
99
};
1010

1111
use crate::FileId;
12+
use ast::DocCommentsOwner;
1213
use std::fmt::Display;
1314

1415
#[derive(Debug)]
@@ -37,6 +38,7 @@ pub enum RunnableKind {
3738
Test { test_id: TestId, attr: TestAttr },
3839
TestMod { path: String },
3940
Bench { test_id: TestId },
41+
DocTest { test_id: TestId },
4042
Bin,
4143
}
4244

@@ -81,6 +83,8 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run
8183
RunnableKind::Test { test_id, attr }
8284
} else if fn_def.has_atom_attr("bench") {
8385
RunnableKind::Bench { test_id }
86+
} else if has_doc_test(&fn_def) {
87+
RunnableKind::DocTest { test_id }
8488
} else {
8589
return None;
8690
}
@@ -117,6 +121,10 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
117121
.any(|attribute_text| attribute_text.contains("test"))
118122
}
119123

124+
fn has_doc_test(fn_def: &ast::FnDef) -> bool {
125+
fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```"))
126+
}
127+
120128
fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
121129
let has_test_function = module
122130
.item_list()?
@@ -194,6 +202,41 @@ mod tests {
194202
);
195203
}
196204

205+
#[test]
206+
fn test_runnables_doc_test() {
207+
let (analysis, pos) = analysis_and_position(
208+
r#"
209+
//- /lib.rs
210+
<|> //empty
211+
fn main() {}
212+
213+
/// ```
214+
/// let x = 5;
215+
/// ```
216+
fn foo() {}
217+
"#,
218+
);
219+
let runnables = analysis.runnables(pos.file_id).unwrap();
220+
assert_debug_snapshot!(&runnables,
221+
@r###"
222+
[
223+
Runnable {
224+
range: 1..21,
225+
kind: Bin,
226+
},
227+
Runnable {
228+
range: 22..64,
229+
kind: DocTest {
230+
test_id: Path(
231+
"foo",
232+
),
233+
},
234+
},
235+
]
236+
"###
237+
);
238+
}
239+
197240
#[test]
198241
fn test_runnables_module() {
199242
let (analysis, pos) = analysis_and_position(

crates/rust-analyzer/src/cargo_target_spec.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,49 @@ impl CargoTargetSpec {
2727
RunnableKind::Test { test_id, attr } => {
2828
args.push("test".to_string());
2929
if let Some(spec) = spec {
30-
spec.push_to(&mut args);
30+
spec.push_to(&mut args, kind);
3131
}
3232
extra_args.push(test_id.to_string());
3333
if let TestId::Path(_) = test_id {
3434
extra_args.push("--exact".to_string());
3535
}
3636
extra_args.push("--nocapture".to_string());
3737
if attr.ignore {
38-
extra_args.push("--ignored".to_string())
38+
extra_args.push("--ignored".to_string());
3939
}
4040
}
4141
RunnableKind::TestMod { path } => {
4242
args.push("test".to_string());
4343
if let Some(spec) = spec {
44-
spec.push_to(&mut args);
44+
spec.push_to(&mut args, kind);
4545
}
4646
extra_args.push(path.to_string());
4747
extra_args.push("--nocapture".to_string());
4848
}
4949
RunnableKind::Bench { test_id } => {
5050
args.push("bench".to_string());
5151
if let Some(spec) = spec {
52-
spec.push_to(&mut args);
52+
spec.push_to(&mut args, kind);
5353
}
5454
extra_args.push(test_id.to_string());
5555
if let TestId::Path(_) = test_id {
5656
extra_args.push("--exact".to_string());
5757
}
5858
extra_args.push("--nocapture".to_string());
5959
}
60+
RunnableKind::DocTest { test_id } => {
61+
args.push("test".to_string());
62+
args.push("--doc".to_string());
63+
if let Some(spec) = spec {
64+
spec.push_to(&mut args, kind);
65+
}
66+
extra_args.push(test_id.to_string());
67+
extra_args.push("--nocapture".to_string());
68+
}
6069
RunnableKind::Bin => {
6170
args.push("run".to_string());
6271
if let Some(spec) = spec {
63-
spec.push_to(&mut args);
72+
spec.push_to(&mut args, kind);
6473
}
6574
}
6675
}
@@ -91,9 +100,14 @@ impl CargoTargetSpec {
91100
Ok(res)
92101
}
93102

94-
pub(crate) fn push_to(self, buf: &mut Vec<String>) {
103+
pub(crate) fn push_to(self, buf: &mut Vec<String>, kind: &RunnableKind) {
95104
buf.push("--package".to_string());
96105
buf.push(self.package);
106+
107+
// Can't mix --doc with other target flags
108+
if let RunnableKind::DocTest { .. } = kind {
109+
return;
110+
}
97111
match self.target_kind {
98112
TargetKind::Bin => {
99113
buf.push("--bin".to_string());

crates/rust-analyzer/src/main_loop/handlers.rs

+2
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ pub fn handle_code_lens(
835835
for runnable in world.analysis().runnables(file_id)? {
836836
let title = match &runnable.kind {
837837
RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️\u{fe0e}Run Test",
838+
RunnableKind::DocTest { .. } => "▶️\u{fe0e}Run Doctest",
838839
RunnableKind::Bench { .. } => "Run Bench",
839840
RunnableKind::Bin => "Run",
840841
}
@@ -1018,6 +1019,7 @@ fn to_lsp_runnable(
10181019
RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
10191020
RunnableKind::TestMod { path } => format!("test-mod {}", path),
10201021
RunnableKind::Bench { test_id } => format!("bench {}", test_id),
1022+
RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id),
10211023
RunnableKind::Bin => "run binary".to_string(),
10221024
};
10231025
Ok(req::Runnable {

0 commit comments

Comments
 (0)