Skip to content

Commit ff6c12b

Browse files
fix
clippy
1 parent 31d2019 commit ff6c12b

File tree

2 files changed

+91
-26
lines changed

2 files changed

+91
-26
lines changed

crates/ide/src/runnables.rs

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub enum RunnableKind {
5757
TestMod { path: String },
5858
Test { test_id: TestId, attr: TestAttr },
5959
Bench { test_id: TestId },
60-
DocTest { test_id: TestId },
60+
DocTest { test_id: TestId, has_compile_fail: bool },
6161
Bin,
6262
}
6363

@@ -404,9 +404,7 @@ pub(crate) fn runnable_impl(
404404
let display_target = def.module(sema.db).krate(sema.db).to_display_target(sema.db);
405405
let edition = display_target.edition;
406406
let attrs = def.attrs(sema.db);
407-
if !has_runnable_doc_test(sema.db, &attrs) {
408-
return None;
409-
}
407+
let doc_test_info = runnable_doc_test_info(sema.db, &attrs)?;
410408
let cfg = attrs.cfgs(sema.db).cloned();
411409
let nav = def.try_to_nav(sema)?.call_site();
412410
let ty = def.self_ty(sema.db);
@@ -429,7 +427,7 @@ pub(crate) fn runnable_impl(
429427
Some(Runnable {
430428
use_name_in_title: false,
431429
nav,
432-
kind: RunnableKind::DocTest { test_id },
430+
kind: RunnableKind::DocTest { test_id, has_compile_fail: doc_test_info.has_compile_fail },
433431
cfg,
434432
update_test,
435433
})
@@ -508,9 +506,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op
508506
let display_target = krate
509507
.unwrap_or_else(|| (*db.all_crates().last().expect("no crate graph present")).into())
510508
.to_display_target(db);
511-
if !has_runnable_doc_test(db, &attrs) {
512-
return None;
513-
}
509+
let doc_test_info = runnable_doc_test_info(db, &attrs)?;
514510
let def_name = def.name(db)?;
515511
let path = (|| {
516512
let mut path = String::new();
@@ -551,7 +547,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op
551547
let res = Runnable {
552548
use_name_in_title: false,
553549
nav,
554-
kind: RunnableKind::DocTest { test_id },
550+
kind: RunnableKind::DocTest { test_id, has_compile_fail: doc_test_info.has_compile_fail },
555551
cfg: attrs.cfgs(db).cloned(),
556552
update_test: UpdateTest::default(),
557553
};
@@ -569,32 +565,64 @@ impl TestAttr {
569565
}
570566
}
571567

572-
fn has_runnable_doc_test(db: &RootDatabase, attrs: &hir::AttrsWithOwner) -> bool {
568+
#[derive(Default, Clone, Copy)]
569+
struct RunnableDocTestInfo {
570+
has_compile_fail: bool,
571+
}
572+
573+
fn runnable_doc_test_info(
574+
db: &RootDatabase,
575+
attrs: &hir::AttrsWithOwner,
576+
) -> Option<RunnableDocTestInfo> {
573577
const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
574578
const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
575-
&["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
579+
&["", "rust", "should_panic", "edition2015", "edition2018", "edition2021", "edition2024"];
580+
581+
let doc = attrs.hir_docs(db)?;
582+
let mut info = RunnableDocTestInfo::default();
583+
let mut in_code_block = false;
584+
let mut runnable_found = false;
585+
586+
for line in doc.docs().lines() {
587+
let trimmed_line = line.trim_start();
588+
if let Some(header) =
589+
RUSTDOC_FENCES.into_iter().find_map(|fence| trimmed_line.strip_prefix(fence))
590+
{
591+
if in_code_block {
592+
in_code_block = false;
593+
continue;
594+
}
576595

577-
attrs.hir_docs(db).is_some_and(|doc| {
578-
let mut in_code_block = false;
596+
in_code_block = true;
597+
let mut block_has_compile_fail = false;
598+
let mut block_runnable = true;
579599

580-
for line in doc.docs().lines() {
581-
if let Some(header) =
582-
RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence))
600+
for attr in header
601+
.split(',')
602+
.flat_map(|segment| segment.split_ascii_whitespace())
603+
.map(str::trim)
604+
.filter(|attr| !attr.is_empty())
583605
{
584-
in_code_block = !in_code_block;
606+
if attr.eq_ignore_ascii_case("compile_fail") {
607+
block_has_compile_fail = true;
608+
block_runnable = false;
609+
continue;
610+
}
585611

586-
if in_code_block
587-
&& header
588-
.split(',')
589-
.all(|sub| RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE.contains(&sub.trim()))
612+
if !RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE
613+
.iter()
614+
.any(|allowed| allowed.eq_ignore_ascii_case(attr))
590615
{
591-
return true;
616+
block_runnable = false;
592617
}
593618
}
619+
620+
info.has_compile_fail |= block_has_compile_fail;
621+
runnable_found |= block_runnable;
594622
}
623+
}
595624

596-
false
597-
})
625+
runnable_found.then_some(info)
598626
}
599627

600628
// We could create runnables for modules with number_of_test_submodules > 0,
@@ -752,6 +780,7 @@ impl UpdateTest {
752780
mod tests {
753781
use expect_test::{Expect, expect};
754782

783+
use super::RunnableKind;
755784
use crate::fixture;
756785

757786
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
@@ -940,6 +969,39 @@ impl Test for StructWithRunnable {}
940969
);
941970
}
942971

972+
#[test]
973+
fn doc_test_runnable_tracks_compile_fail_blocks() {
974+
let (analysis, position) = fixture::position(
975+
r#"
976+
//- /lib.rs
977+
$0
978+
/// ```compile_fail
979+
/// let x = 5;
980+
/// x += 1;
981+
/// ```
982+
///
983+
/// ```
984+
/// let x = 5;
985+
/// x + 1;
986+
/// ```
987+
fn add(left: u64, right: u64) -> u64 {
988+
left + right
989+
}
990+
"#,
991+
);
992+
993+
let runnables = analysis.runnables(position.file_id).unwrap();
994+
let doc_test = runnables
995+
.into_iter()
996+
.find(|runnable| matches!(runnable.kind, RunnableKind::DocTest { .. }))
997+
.expect("expected doctest runnable");
998+
999+
match doc_test.kind {
1000+
RunnableKind::DocTest { has_compile_fail, .. } => assert!(has_compile_fail),
1001+
_ => panic!("expected doctest runnable"),
1002+
}
1003+
}
1004+
9431005
#[test]
9441006
fn test_runnables_doc_test_in_impl() {
9451007
check(

crates/rust-analyzer/src/target_spec.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl CargoTargetSpec {
116116
cfg: &Option<CfgExpr>,
117117
) -> (Vec<String>, Vec<String>) {
118118
let config = snap.config.runnables(None);
119-
let extra_test_binary_args = config.extra_test_binary_args;
119+
let mut extra_test_binary_args = config.extra_test_binary_args;
120120

121121
let mut cargo_args = Vec::new();
122122
let mut executable_args = Vec::new();
@@ -146,10 +146,13 @@ impl CargoTargetSpec {
146146
}
147147
executable_args.extend(extra_test_binary_args);
148148
}
149-
RunnableKind::DocTest { test_id } => {
149+
RunnableKind::DocTest { test_id, has_compile_fail } => {
150150
cargo_args.push("test".to_owned());
151151
cargo_args.push("--doc".to_owned());
152152
executable_args.push(test_id.to_string());
153+
if *has_compile_fail {
154+
extra_test_binary_args.retain(|arg| arg != "--nocapture");
155+
}
153156
executable_args.extend(extra_test_binary_args);
154157
}
155158
RunnableKind::Bin => {

0 commit comments

Comments
 (0)