update based on comment

This commit is contained in:
Asuka Minato 2025-12-22 22:20:33 +09:00
parent ff6c12ba3b
commit 7bfa62e99f
2 changed files with 30 additions and 41 deletions

View file

@ -57,7 +57,7 @@ pub enum RunnableKind {
TestMod { path: String },
Test { test_id: TestId, attr: TestAttr },
Bench { test_id: TestId },
DocTest { test_id: TestId, has_compile_fail: bool },
DocTest { test_id: TestId },
Bin,
}
@ -404,7 +404,9 @@ pub(crate) fn runnable_impl(
let display_target = def.module(sema.db).krate(sema.db).to_display_target(sema.db);
let edition = display_target.edition;
let attrs = def.attrs(sema.db);
let doc_test_info = runnable_doc_test_info(sema.db, &attrs)?;
if !has_runnable_doc_test(sema.db, &attrs) {
return None;
}
let cfg = attrs.cfgs(sema.db).cloned();
let nav = def.try_to_nav(sema)?.call_site();
let ty = def.self_ty(sema.db);
@ -427,7 +429,7 @@ pub(crate) fn runnable_impl(
Some(Runnable {
use_name_in_title: false,
nav,
kind: RunnableKind::DocTest { test_id, has_compile_fail: doc_test_info.has_compile_fail },
kind: RunnableKind::DocTest { test_id },
cfg,
update_test,
})
@ -506,7 +508,9 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op
let display_target = krate
.unwrap_or_else(|| (*db.all_crates().last().expect("no crate graph present")).into())
.to_display_target(db);
let doc_test_info = runnable_doc_test_info(db, &attrs)?;
if !has_runnable_doc_test(db, &attrs) {
return None;
}
let def_name = def.name(db)?;
let path = (|| {
let mut path = String::new();
@ -547,7 +551,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op
let res = Runnable {
use_name_in_title: false,
nav,
kind: RunnableKind::DocTest { test_id, has_compile_fail: doc_test_info.has_compile_fail },
kind: RunnableKind::DocTest { test_id },
cfg: attrs.cfgs(db).cloned(),
update_test: UpdateTest::default(),
};
@ -565,23 +569,18 @@ impl TestAttr {
}
}
#[derive(Default, Clone, Copy)]
struct RunnableDocTestInfo {
has_compile_fail: bool,
}
fn runnable_doc_test_info(
db: &RootDatabase,
attrs: &hir::AttrsWithOwner,
) -> Option<RunnableDocTestInfo> {
fn has_runnable_doc_test(db: &RootDatabase, attrs: &hir::AttrsWithOwner) -> bool {
const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
&["", "rust", "should_panic", "edition2015", "edition2018", "edition2021", "edition2024"];
let doc = attrs.hir_docs(db)?;
let mut info = RunnableDocTestInfo::default();
let doc = match attrs.hir_docs(db) {
Some(doc) => doc,
None => return false,
};
let mut in_code_block = false;
let mut runnable_found = false;
let mut has_compile_fail = false;
for line in doc.docs().lines() {
let trimmed_line = line.trim_start();
@ -606,7 +605,7 @@ fn runnable_doc_test_info(
if attr.eq_ignore_ascii_case("compile_fail") {
block_has_compile_fail = true;
block_runnable = false;
continue;
break;
}
if !RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE
@ -617,12 +616,12 @@ fn runnable_doc_test_info(
}
}
info.has_compile_fail |= block_has_compile_fail;
has_compile_fail |= block_has_compile_fail;
runnable_found |= block_runnable;
}
}
runnable_found.then_some(info)
runnable_found && !has_compile_fail
}
// We could create runnables for modules with number_of_test_submodules > 0,
@ -780,7 +779,6 @@ impl UpdateTest {
mod tests {
use expect_test::{Expect, expect};
use super::RunnableKind;
use crate::fixture;
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
@ -970,11 +968,13 @@ impl Test for StructWithRunnable {}
}
#[test]
fn doc_test_runnable_tracks_compile_fail_blocks() {
let (analysis, position) = fixture::position(
fn doc_test_with_compile_fail_blocks_is_skipped() {
check(
r#"
//- /lib.rs
$0
fn main() {}
/// ```compile_fail
/// let x = 5;
/// x += 1;
@ -984,22 +984,14 @@ $0
/// let x = 5;
/// x + 1;
/// ```
fn add(left: u64, right: u64) -> u64 {
left + right
}
fn add() {}
"#,
expect![[r#"
[
"(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })",
]
"#]],
);
let runnables = analysis.runnables(position.file_id).unwrap();
let doc_test = runnables
.into_iter()
.find(|runnable| matches!(runnable.kind, RunnableKind::DocTest { .. }))
.expect("expected doctest runnable");
match doc_test.kind {
RunnableKind::DocTest { has_compile_fail, .. } => assert!(has_compile_fail),
_ => panic!("expected doctest runnable"),
}
}
#[test]

View file

@ -116,7 +116,7 @@ impl CargoTargetSpec {
cfg: &Option<CfgExpr>,
) -> (Vec<String>, Vec<String>) {
let config = snap.config.runnables(None);
let mut extra_test_binary_args = config.extra_test_binary_args;
let extra_test_binary_args = config.extra_test_binary_args;
let mut cargo_args = Vec::new();
let mut executable_args = Vec::new();
@ -146,13 +146,10 @@ impl CargoTargetSpec {
}
executable_args.extend(extra_test_binary_args);
}
RunnableKind::DocTest { test_id, has_compile_fail } => {
RunnableKind::DocTest { test_id } => {
cargo_args.push("test".to_owned());
cargo_args.push("--doc".to_owned());
executable_args.push(test_id.to_string());
if *has_compile_fail {
extra_test_binary_args.retain(|arg| arg != "--nocapture");
}
executable_args.extend(extra_test_binary_args);
}
RunnableKind::Bin => {