Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/runnables.rs')
| -rw-r--r-- | crates/ide/src/runnables.rs | 78 |
1 files changed, 42 insertions, 36 deletions
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index ec13ba0fde..9e17ab2bab 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -3,20 +3,18 @@ use std::{fmt, sync::OnceLock}; use arrayvec::ArrayVec; use ast::HasName; use cfg::{CfgAtom, CfgExpr}; -use hir::{ - AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, HasSource, Semantics, Symbol, db::HirDatabase, - sym, -}; +use hir::{AsAssocItem, HasAttrs, HasCrate, HasSource, Semantics, Symbol, db::HirDatabase, sym}; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; +use ide_db::impl_empty_upmap_from_ra_fixture; use ide_db::{ FilePosition, FxHashMap, FxIndexMap, FxIndexSet, RootDatabase, SymbolKind, - base_db::{RootQueryDb, salsa}, + base_db::RootQueryDb, defs::Definition, - documentation::docs_from_attrs, helpers::visit_file_defs, search::{FileReferenceNode, SearchScope}, }; use itertools::Itertools; +use macros::UpmapFromRaFixture; use smallvec::SmallVec; use span::{Edition, TextSize}; use stdx::format_to; @@ -28,7 +26,7 @@ use syntax::{ use crate::{FileId, NavigationTarget, ToNav, TryToNav, references}; -#[derive(Debug, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)] pub struct Runnable { pub use_name_in_title: bool, pub nav: NavigationTarget, @@ -37,6 +35,8 @@ pub struct Runnable { pub update_test: UpdateTest, } +impl_empty_upmap_from_ra_fixture!(RunnableKind, UpdateTest); + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum TestId { Name(SmolStr), @@ -227,7 +227,7 @@ fn cmp_runnables( .cmp(&nav_b.focus_range.map_or_else(t_0, |it| it.start())) }) .then_with(|| kind.disc().cmp(&kind_b.disc())) - .then_with(|| nav.name.cmp(&nav_b.name)) + .then_with(|| nav.name.as_str().cmp(nav_b.name.as_str())) } fn find_related_tests( @@ -319,7 +319,7 @@ pub(crate) fn runnable_fn( def: hir::Function, ) -> Option<Runnable> { let edition = def.krate(sema.db).edition(sema.db); - let under_cfg_test = has_cfg_test(def.module(sema.db).attrs(sema.db)); + let under_cfg_test = has_cfg_test(def.module(sema.db).attrs(sema.db).cfgs(sema.db)); let kind = if !under_cfg_test && def.is_main(sema.db) { RunnableKind::Bin } else { @@ -354,7 +354,7 @@ pub(crate) fn runnable_fn( let file_range = fn_source.syntax().original_file_range_with_macro_call_input(sema.db); let update_test = UpdateTest::find_snapshot_macro(sema, file_range); - let cfg = def.attrs(sema.db).cfg(); + let cfg = def.attrs(sema.db).cfgs(sema.db).cloned(); Some(Runnable { use_name_in_title: false, nav, kind, cfg, update_test }) } @@ -362,8 +362,8 @@ pub(crate) fn runnable_mod( sema: &Semantics<'_, RootDatabase>, def: hir::Module, ) -> Option<Runnable> { - if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(def.attrs(sema.db))) - { + let cfg = def.attrs(sema.db).cfgs(sema.db); + if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(cfg)) { return None; } let path = def @@ -377,8 +377,7 @@ pub(crate) fn runnable_mod( }) .join("::"); - let attrs = def.attrs(sema.db); - let cfg = attrs.cfg(); + let cfg = cfg.cloned(); let nav = NavigationTarget::from_module_to_decl(sema.db, def).call_site(); let module_source = sema.module_definition_node(def); @@ -405,15 +404,15 @@ pub(crate) fn runnable_impl( let display_target = def.module(sema.db).krate().to_display_target(sema.db); let edition = display_target.edition; let attrs = def.attrs(sema.db); - if !has_runnable_doc_test(&attrs) { + if !has_runnable_doc_test(sema.db, &attrs) { return None; } - let cfg = attrs.cfg(); + let cfg = attrs.cfgs(sema.db).cloned(); let nav = def.try_to_nav(sema)?.call_site(); let ty = def.self_ty(sema.db); let adt_name = ty.as_adt()?.name(sema.db); let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable(); - let params = salsa::attach(sema.db, || { + let params = hir::attach_db(sema.db, || { if ty_args.peek().is_some() { format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))) } else { @@ -438,8 +437,16 @@ pub(crate) fn runnable_impl( }) } -fn has_cfg_test(attrs: AttrsWithOwner) -> bool { - attrs.cfgs().any(|cfg| matches!(&cfg, CfgExpr::Atom(CfgAtom::Flag(s)) if *s == sym::test)) +fn has_cfg_test(cfg: Option<&CfgExpr>) -> bool { + return cfg.is_some_and(has_cfg_test_impl); + + fn has_cfg_test_impl(cfg: &CfgExpr) -> bool { + match cfg { + CfgExpr::Atom(CfgAtom::Flag(s)) => *s == sym::test, + CfgExpr::Any(cfgs) | CfgExpr::All(cfgs) => cfgs.iter().any(has_cfg_test_impl), + _ => false, + } + } } /// Creates a test mod runnable for outline modules at the top of their definition. @@ -449,8 +456,8 @@ fn runnable_mod_outline_definition( ) -> Option<Runnable> { def.as_source_file_id(sema.db)?; - if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(def.attrs(sema.db))) - { + let cfg = def.attrs(sema.db).cfgs(sema.db); + if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(cfg)) { return None; } let path = def @@ -464,8 +471,7 @@ fn runnable_mod_outline_definition( }) .join("::"); - let attrs = def.attrs(sema.db); - let cfg = attrs.cfg(); + let cfg = cfg.cloned(); let mod_source = sema.module_definition_node(def); let mod_syntax = mod_source.file_syntax(sema.db); @@ -504,7 +510,7 @@ 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); - if !has_runnable_doc_test(&attrs) { + if !has_runnable_doc_test(db, &attrs) { return None; } let def_name = def.name(db)?; @@ -522,7 +528,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op let mut ty_args = ty.generic_parameters(db, display_target).peekable(); format_to!(path, "{}", name.display(db, edition)); if ty_args.peek().is_some() { - salsa::attach(db, || { + hir::attach_db(db, || { format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))); }); } @@ -550,7 +556,7 @@ fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Op use_name_in_title: false, nav, kind: RunnableKind::DocTest { test_id }, - cfg: attrs.cfg(), + cfg: attrs.cfgs(db).cloned(), update_test: UpdateTest::default(), }; Some(res) @@ -567,15 +573,15 @@ impl TestAttr { } } -fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool { +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"]; - docs_from_attrs(attrs).is_some_and(|doc| { + attrs.hir_docs(db).is_some_and(|doc| { let mut in_code_block = false; - for line in doc.lines() { + for line in doc.docs().lines() { if let Some(header) = RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence)) { @@ -813,7 +819,7 @@ mod not_a_root { "#, expect![[r#" [ - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..331, name: \"\", kind: Module })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..331, name: \"_\", kind: Module })", "(Bin, NavigationTarget { file_id: FileId(0), full_range: 1..13, focus_range: 4..8, name: \"main\", kind: Function })", "(Bin, NavigationTarget { file_id: FileId(0), full_range: 15..76, focus_range: 42..71, name: \"__cortex_m_rt_main_trampoline\", kind: Function })", "(Bin, NavigationTarget { file_id: FileId(0), full_range: 78..154, focus_range: 113..149, name: \"__cortex_m_rt_main_trampoline_unsafe\", kind: Function })", @@ -1134,7 +1140,7 @@ fn test_foo1() {} "#, expect![[r#" [ - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..51, name: \"\", kind: Module })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..51, name: \"_\", kind: Module })", "(Test, NavigationTarget { file_id: FileId(0), full_range: 1..50, focus_range: 36..45, name: \"test_foo1\", kind: Function }, Atom(KeyValue { key: \"feature\", value: \"foo\" }))", ] "#]], @@ -1153,7 +1159,7 @@ fn test_foo1() {} "#, expect![[r#" [ - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..73, name: \"\", kind: Module })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..73, name: \"_\", kind: Module })", "(Test, NavigationTarget { file_id: FileId(0), full_range: 1..72, focus_range: 58..67, name: \"test_foo1\", kind: Function }, All([Atom(KeyValue { key: \"feature\", value: \"foo\" }), Atom(KeyValue { key: \"feature\", value: \"bar\" })]))", ] "#]], @@ -1232,7 +1238,7 @@ generate_main!(); "#, expect![[r#" [ - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..345, name: \"\", kind: Module })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..345, name: \"_\", kind: Module })", "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 282..312, focus_range: 286..291, name: \"tests\", kind: Module, description: \"mod tests\" })", "(Test, NavigationTarget { file_id: FileId(0), full_range: 298..307, name: \"foo_test\", kind: Function })", "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 313..323, name: \"tests2\", kind: Module, description: \"mod tests2\" }, true)", @@ -1675,10 +1681,10 @@ mod r#mod { "#, expect![[r#" [ - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 1..461, focus_range: 5..10, name: \"r#mod\", kind: Module, description: \"mod r#mod\" })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 1..461, focus_range: 5..10, name: \"mod\", kind: Module, description: \"mod r#mod\" })", "(Test, NavigationTarget { file_id: FileId(0), full_range: 17..41, focus_range: 32..36, name: \"r#fn\", kind: Function })", - "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 47..84, name: \"r#for\", container_name: \"r#mod\" })", - "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 90..146, name: \"r#struct\", container_name: \"r#mod\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 47..84, name: \"r#for\", container_name: \"mod\" })", + "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 90..146, name: \"r#struct\", container_name: \"mod\" })", "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 152..266, focus_range: 189..205, name: \"impl\", kind: Impl })", "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 216..260, name: \"r#fn\" })", "(DocTest, NavigationTarget { file_id: FileId(0), full_range: 323..367, name: \"r#fn\" })", |