diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 35c8708955..631ae3cf11 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, MacroCallId, MacroDefKind}; +use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind}; use smallvec::SmallVec; use syntax::ast; @@ -12,7 +12,10 @@ use crate::{ db::DefDatabase, intern::Interned, item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId}, - nameres::{attr_resolution::ResolvedAttr, proc_macro::ProcMacroKind, DefMap}, + nameres::{ + attr_resolution::ResolvedAttr, diagnostics::DefDiagnostic, proc_macro::ProcMacroKind, + DefMap, + }, type_ref::{TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, @@ -210,6 +213,13 @@ pub struct TraitData { impl TraitData { pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc { + db.trait_data_with_diagnostics(tr).0 + } + + pub(crate) fn trait_data_with_diagnostics_query( + db: &dyn DefDatabase, + tr: TraitId, + ) -> (Arc, Arc>) { let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); let item_tree = tree_id.item_tree(db); let tr_def = &item_tree[tree_id.value]; @@ -229,17 +239,20 @@ impl TraitData { let mut collector = AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); - let (items, attribute_calls) = collector.finish(); + let (items, attribute_calls, diagnostics) = collector.finish(); - Arc::new(TraitData { - name, - attribute_calls, - items, - is_auto, - is_unsafe, - visibility, - skip_array_during_method_dispatch, - }) + ( + Arc::new(TraitData { + name, + attribute_calls, + items, + is_auto, + is_unsafe, + visibility, + skip_array_during_method_dispatch, + }), + Arc::new(diagnostics), + ) } pub fn associated_types(&self) -> impl Iterator + '_ { @@ -280,7 +293,14 @@ pub struct ImplData { impl ImplData { pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc { - let _p = profile::span("impl_data_query"); + db.impl_data_with_diagnostics(id).0 + } + + pub(crate) fn impl_data_with_diagnostics_query( + db: &dyn DefDatabase, + id: ImplId, + ) -> (Arc, Arc>) { + let _p = profile::span("impl_data_with_diagnostics_query"); let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); let item_tree = tree_id.item_tree(db); @@ -293,10 +313,13 @@ impl ImplData { AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id)); collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items); - let (items, attribute_calls) = collector.finish(); + let (items, attribute_calls, diagnostics) = collector.finish(); let items = items.into_iter().map(|(_, item)| item).collect(); - Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }) + ( + Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }), + Arc::new(diagnostics), + ) } pub fn attribute_calls(&self) -> impl Iterator, MacroCallId)> + '_ { @@ -437,6 +460,7 @@ struct AssocItemCollector<'a> { db: &'a dyn DefDatabase, module_id: ModuleId, def_map: Arc, + inactive_diagnostics: Vec, container: ItemContainerId, expander: Expander, @@ -459,15 +483,21 @@ impl<'a> AssocItemCollector<'a> { expander: Expander::new(db, file_id, module_id), items: Vec::new(), attr_calls: Vec::new(), + inactive_diagnostics: Vec::new(), } } fn finish( self, - ) -> (Vec<(Name, AssocItemId)>, Option, MacroCallId)>>>) { + ) -> ( + Vec<(Name, AssocItemId)>, + Option, MacroCallId)>>>, + Vec, + ) { ( self.items, if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) }, + self.inactive_diagnostics, ) } @@ -479,6 +509,12 @@ impl<'a> AssocItemCollector<'a> { 'items: for &item in assoc_items { let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); if !attrs.is_cfg_enabled(self.expander.cfg_options()) { + self.inactive_diagnostics.push(DefDiagnostic::unconfigured_code( + self.module_id.local_id, + InFile::new(self.expander.current_file_id(), item.ast_id(&item_tree).upcast()), + attrs.cfg().unwrap(), + self.expander.cfg_options().clone(), + )); continue; } diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index df6dcb024b..40b2f734b7 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -20,7 +20,7 @@ use crate::{ intern::Interned, item_tree::{AttrOwner, ItemTree}, lang_item::{LangItemTarget, LangItems}, - nameres::DefMap, + nameres::{diagnostics::DefDiagnostic, DefMap}, visibility::{self, Visibility}, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, @@ -106,9 +106,16 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::invoke(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; + #[salsa::invoke(ImplData::impl_data_with_diagnostics_query)] + fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc, Arc>); + #[salsa::invoke(TraitData::trait_data_query)] fn trait_data(&self, e: TraitId) -> Arc; + #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)] + fn trait_data_with_diagnostics(&self, tr: TraitId) + -> (Arc, Arc>); + #[salsa::invoke(TypeAliasData::type_alias_data_query)] fn type_alias_data(&self, e: TypeAliasId) -> Arc; diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 0d01f6d0ab..ed7e920fd2 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -73,7 +73,7 @@ impl DefDiagnostic { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } } - pub(super) fn unconfigured_code( + pub fn unconfigured_code( container: LocalModuleId, ast: AstId, cfg: CfgExpr, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index aa019ca483..6dccf2ed20 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -511,6 +511,7 @@ impl Module { .collect() } + /// Fills `acc` with the module's diagnostics. pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { let _p = profile::span("Module::diagnostics").detail(|| { format!("{:?}", self.name(db).map_or("".into(), |name| name.to_string())) @@ -531,11 +532,21 @@ impl Module { m.diagnostics(db, acc) } } + ModuleDef::Trait(t) => { + for diag in db.trait_data_with_diagnostics(t.id).1.iter() { + emit_def_diagnostic(db, acc, diag); + } + acc.extend(decl.diagnostics(db)) + } _ => acc.extend(decl.diagnostics(db)), } } for impl_def in self.impl_defs(db) { + for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() { + emit_def_diagnostic(db, acc, diag); + } + for item in impl_def.items(db) { let def: DefWithBody = match item { AssocItem::Function(it) => it.into(), diff --git a/crates/ide-diagnostics/src/handlers/inactive_code.rs b/crates/ide-diagnostics/src/handlers/inactive_code.rs index 5694f33525..04918891b2 100644 --- a/crates/ide-diagnostics/src/handlers/inactive_code.rs +++ b/crates/ide-diagnostics/src/handlers/inactive_code.rs @@ -106,18 +106,17 @@ fn f() { #[test] fn inactive_assoc_item() { - // FIXME these currently don't work, hence the * check( r#" struct Foo; impl Foo { #[cfg(any())] pub fn f() {} - //*************************** weak: code is inactive due to #[cfg] directives + //^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives } trait Bar { #[cfg(any())] pub fn f() {} - //*************************** weak: code is inactive due to #[cfg] directives + //^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives } "#, );