diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index de07fc95218..7fc4cd76e1a 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -54,6 +54,7 @@ pub struct StructFieldData { impl StructData { pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { let src = id.lookup(db).source(db); + let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); let variant_data = VariantData::new(db, src.map(|s| s.kind())); let variant_data = Arc::new(variant_data); diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 04bd4a3059d..606ec48b084 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -3,15 +3,18 @@ use std::sync::Arc; use hir_expand::{ + hygiene::Hygiene, name::{name, AsName, Name}, AstId, InFile, }; +use ra_cfg::CfgOptions; use ra_prof::profile; use ra_syntax::ast::{ self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, }; use crate::{ + attr::Attrs, db::DefDatabase, path::{path, GenericArgs, Path}, src::HasSource, @@ -26,6 +29,7 @@ pub struct FunctionData { pub name: Name, pub params: Vec, pub ret_type: TypeRef, + pub attrs: Attrs, /// True if the first param is `self`. This is relevant to decide whether this /// can be called as a method. pub has_self_param: bool, @@ -63,6 +67,8 @@ impl FunctionData { params.push(type_ref); } } + let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); + let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { TypeRef::from_ast(type_ref) } else { @@ -81,7 +87,7 @@ impl FunctionData { let visibility = RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); - let sig = FunctionData { name, params, ret_type, has_self_param, visibility }; + let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; Arc::new(sig) } } @@ -211,6 +217,7 @@ impl ImplData { let module_id = impl_loc.container.module(db); let mut items = Vec::new(); + if let Some(item_list) = src.value.item_list() { items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); items.extend(collect_impl_items_in_macros( @@ -311,6 +318,10 @@ fn collect_impl_items_in_macro( } } +fn is_cfg_enabled(cfg_options: &CfgOptions, attrs: &Attrs) -> bool { + attrs.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) +} + fn collect_impl_items( db: &dyn DefDatabase, impl_items: impl Iterator, @@ -318,16 +329,26 @@ fn collect_impl_items( id: ImplId, ) -> Vec { let items = db.ast_id_map(file_id); + let crate_graph = db.crate_graph(); + let module_id = id.lookup(db).container.module(db); impl_items - .map(|item_node| match item_node { + .filter_map(|item_node| match item_node { ast::ImplItem::FnDef(it) => { let def = FunctionLoc { container: AssocContainerId::ImplId(id), ast_id: AstId::new(file_id, items.ast_id(&it)), } .intern(db); - def.into() + + if !is_cfg_enabled( + &crate_graph[module_id.krate].cfg_options, + &db.function_data(def).attrs, + ) { + None + } else { + Some(def.into()) + } } ast::ImplItem::ConstDef(it) => { let def = ConstLoc { @@ -335,7 +356,7 @@ fn collect_impl_items( ast_id: AstId::new(file_id, items.ast_id(&it)), } .intern(db); - def.into() + Some(def.into()) } ast::ImplItem::TypeAliasDef(it) => { let def = TypeAliasLoc { @@ -343,7 +364,7 @@ fn collect_impl_items( ast_id: AstId::new(file_id, items.ast_id(&it)), } .intern(db); - def.into() + Some(def.into()) } }) .collect() diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index b4592fbf56d..e45e9ea14d7 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs @@ -4,8 +4,7 @@ use std::sync::Arc; use hir_def::{path::path, resolver::HasResolver, AdtId, FunctionId}; use hir_expand::diagnostics::DiagnosticSink; -use ra_syntax::ast; -use ra_syntax::AstPtr; +use ra_syntax::{ast, AstPtr}; use rustc_hash::FxHashSet; use crate::{ diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index e4a103d1be1..608408d88c2 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -319,3 +319,33 @@ fn no_such_field_diagnostics() { "### ); } + +#[test] +fn no_such_field_with_feature_flag_diagnostics() { + let diagnostics = TestDB::with_files( + r#" + //- /lib.rs crate:foo cfg:feature=foo + struct MyStruct { + my_val: usize, + #[cfg(feature = "foo")] + bar: bool, + } + + impl MyStruct { + #[cfg(feature = "foo")] + pub(crate) fn new(my_val: usize, bar: bool) -> Self { + Self { my_val, bar } + } + + #[cfg(not(feature = "foo"))] + pub(crate) fn new(my_val: usize, _bar: bool) -> Self { + Self { my_val } + } + } + "#, + ) + .diagnostics() + .0; + + assert_snapshot!(diagnostics, @r###""###); +}