From ffe179a73663b111e4b3ee8a3f525fb3e461c78e Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 02:50:56 +0800 Subject: Pass attributes as token tree to DefCollector --- crates/ra_hir/src/nameres/collector.rs | 19 ++++++------- crates/ra_hir/src/nameres/raw.rs | 52 +++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 20 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index a568fdabd..40e56dfe0 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -523,7 +523,7 @@ where // `#[macro_use] extern crate` is hoisted to imports macros before collecting // any other items. for item in items { - if let raw::RawItem::Import(import_id) = *item { + if let raw::RawItemKind::Import(import_id) = item.kind { let import = self.raw_items[import_id].clone(); if import.is_extern_crate && import.is_macro_use { self.def_collector.import_macros_from_extern_crate(self.module_id, &import); @@ -532,15 +532,14 @@ where } for item in items { - match *item { - raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), - raw::RawItem::Import(import_id) => self.def_collector.unresolved_imports.push(( - self.module_id, - import_id, - self.raw_items[import_id].clone(), - )), - raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), - raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), + match item.kind { + raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), + raw::RawItemKind::Import(import_id) => self + .def_collector + .unresolved_imports + .push((self.module_id, import_id, self.raw_items[import_id].clone())), + raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), + raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), } } } diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index 606bd1a95..cacbcb517 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -2,6 +2,7 @@ use std::{ops::Index, sync::Arc}; +use mbe::ast_to_token_tree; use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, @@ -28,6 +29,8 @@ pub struct RawItems { items: Vec, } +type Attrs = Arc<[tt::Subtree]>; + #[derive(Debug, Default, PartialEq, Eq)] pub struct ImportSourceMap { map: ArenaMap, @@ -119,8 +122,14 @@ impl Index for RawItems { } } +#[derive(Debug, PartialEq, Eq, Clone)] +pub(super) struct RawItem { + pub(super) attrs: Attrs, + pub(super) kind: RawItemKind, +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub(super) enum RawItem { +pub(super) enum RawItemKind { Module(Module), Import(ImportId), Def(Def), @@ -215,6 +224,7 @@ impl RawItemsCollector<&DB> { } fn add_item(&mut self, current_module: Option, item: ast::ModuleItem) { + let attrs = self.parse_attrs(&item); let (kind, name) = match item { ast::ModuleItem::Module(module) => { self.add_module(current_module, module); @@ -263,7 +273,7 @@ impl RawItemsCollector<&DB> { if let Some(name) = name { let name = name.as_name(); let def = self.raw_items.defs.alloc(DefData { name, kind }); - self.push_item(current_module, RawItem::Def(def)) + self.push_item(current_module, attrs, RawItemKind::Def(def)); } } @@ -272,6 +282,7 @@ impl RawItemsCollector<&DB> { Some(it) => it.as_name(), None => return, }; + let attrs = self.parse_attrs(&module); let ast_id = self.source_ast_id_map.ast_id(&module); let is_macro_use = module.has_atom_attr("macro_use"); @@ -283,7 +294,7 @@ impl RawItemsCollector<&DB> { attr_path, is_macro_use, }); - self.push_item(current_module, RawItem::Module(item)); + self.push_item(current_module, attrs, RawItemKind::Module(item)); return; } @@ -297,7 +308,7 @@ impl RawItemsCollector<&DB> { is_macro_use, }); self.process_module(Some(item), item_list); - self.push_item(current_module, RawItem::Module(item)); + self.push_item(current_module, attrs, RawItemKind::Module(item)); return; } tested_by!(name_res_works_for_broken_modules); @@ -305,6 +316,7 @@ impl RawItemsCollector<&DB> { fn add_use_item(&mut self, current_module: Option, use_item: ast::UseItem) { let is_prelude = use_item.has_atom_attr("prelude_import"); + let attrs = self.parse_attrs(&use_item); Path::expand_use_item( Source { ast: use_item, file_id: self.file_id }, @@ -318,7 +330,12 @@ impl RawItemsCollector<&DB> { is_extern_crate: false, is_macro_use: false, }; - self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree))); + self.push_import( + current_module, + attrs.clone(), + import_data, + Either::A(AstPtr::new(use_tree)), + ); }, ) } @@ -331,6 +348,7 @@ impl RawItemsCollector<&DB> { if let Some(name_ref) = extern_crate.name_ref() { let path = Path::from_name_ref(&name_ref); let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); + let attrs = self.parse_attrs(&extern_crate); let is_macro_use = extern_crate.has_atom_attr("macro_use"); let import_data = ImportData { path, @@ -340,7 +358,12 @@ impl RawItemsCollector<&DB> { is_extern_crate: true, is_macro_use, }; - self.push_import(current_module, import_data, Either::B(AstPtr::new(&extern_crate))); + self.push_import( + current_module, + attrs, + import_data, + Either::B(AstPtr::new(&extern_crate)), + ); } } @@ -358,21 +381,22 @@ impl RawItemsCollector<&DB> { let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); - self.push_item(current_module, RawItem::Macro(m)); + self.push_item(current_module, attrs, RawItemKind::Macro(m)); } fn push_import( &mut self, current_module: Option, + attrs: Attrs, data: ImportData, source: ImportSourcePtr, ) { let import = self.raw_items.imports.alloc(data); self.source_map.insert(import, source); - self.push_item(current_module, RawItem::Import(import)) + self.push_item(current_module, attrs, RawItemKind::Import(import)) } - fn push_item(&mut self, current_module: Option, item: RawItem) { + fn push_item(&mut self, current_module: Option, attrs: Attrs, kind: RawItemKind) { match current_module { Some(module) => match &mut self.raw_items.modules[module] { ModuleData::Definition { items, .. } => items, @@ -380,7 +404,15 @@ impl RawItemsCollector<&DB> { }, None => &mut self.raw_items.items, } - .push(item) + .push(RawItem { attrs, kind }) + } + + fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { + item.attrs() + .flat_map(|attr| attr.value()) + .flat_map(|tt| ast_to_token_tree(&tt)) + .map(|(tt, _)| tt) + .collect() } } -- cgit v1.2.3 From b1ed887d813bf5775a16624694939fdf836f97b1 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 06:52:15 +0800 Subject: Introduce ra_cfg to parse and evaluate CfgExpr --- crates/ra_hir/Cargo.toml | 1 + crates/ra_hir/src/attr.rs | 58 ++++++++++++++++++++++++++++++++++ crates/ra_hir/src/lib.rs | 1 + crates/ra_hir/src/nameres/collector.rs | 52 ++++++++++++++++++++---------- crates/ra_hir/src/nameres/raw.rs | 21 ++++++------ 5 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 crates/ra_hir/src/attr.rs (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index d9bed4dda..cc117f84d 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -15,6 +15,7 @@ once_cell = "1.0.1" ra_syntax = { path = "../ra_syntax" } ra_arena = { path = "../ra_arena" } +ra_cfg = { path = "../ra_cfg" } ra_db = { path = "../ra_db" } mbe = { path = "../ra_mbe", package = "ra_mbe" } tt = { path = "../ra_tt", package = "ra_tt" } diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs new file mode 100644 index 000000000..19be6de32 --- /dev/null +++ b/crates/ra_hir/src/attr.rs @@ -0,0 +1,58 @@ +use mbe::ast_to_token_tree; +use ra_syntax::{ + ast::{self, AstNode}, + SmolStr, +}; +use tt::Subtree; + +use crate::{db::AstDatabase, path::Path, Source}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct Attr { + pub(crate) path: Path, + pub(crate) input: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum AttrInput { + Literal(SmolStr), + TokenTree(Subtree), +} + +impl Attr { + pub(crate) fn from_src( + Source { file_id, ast }: Source, + db: &impl AstDatabase, + ) -> Option { + let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?; + let input = match ast.input() { + None => None, + Some(ast::AttrInput::Literal(lit)) => { + // FIXME: escape? raw string? + let value = lit.syntax().first_token()?.text().trim_matches('"').into(); + Some(AttrInput::Literal(value)) + } + Some(ast::AttrInput::TokenTree(tt)) => { + Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) + } + }; + + Some(Attr { path, input }) + } + + pub(crate) fn is_simple_atom(&self, name: &str) -> bool { + // FIXME: Avoid cloning + self.path.as_ident().map_or(false, |s| s.to_string() == name) + } + + pub(crate) fn as_cfg(&self) -> Option<&Subtree> { + if self.is_simple_atom("cfg") { + match &self.input { + Some(AttrInput::TokenTree(subtree)) => Some(subtree), + _ => None, + } + } else { + None + } + } +} diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 00031deba..4340e9d34 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -44,6 +44,7 @@ mod traits; mod type_alias; mod type_ref; mod ty; +mod attr; mod impl_block; mod expr; mod lang_item; diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 40e56dfe0..f0e790e4c 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -1,11 +1,13 @@ //! FIXME: write short doc here +use ra_cfg::CfgOptions; use ra_db::FileId; use ra_syntax::{ast, SmolStr}; use rustc_hash::FxHashMap; use test_utils::tested_by; use crate::{ + attr::Attr, db::DefDatabase, ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, name::MACRO_RULES, @@ -35,6 +37,9 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C } } + let crate_graph = db.crate_graph(); + let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id()); + let mut collector = DefCollector { db, def_map, @@ -42,6 +47,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C unresolved_imports: Vec::new(), unexpanded_macros: Vec::new(), macro_stack_monitor: MacroStackMonitor::default(), + cfg_options, }; collector.collect(); collector.finish() @@ -76,8 +82,8 @@ impl MacroStackMonitor { } /// Walks the tree of module recursively -struct DefCollector { - db: DB, +struct DefCollector<'a, DB> { + db: &'a DB, def_map: CrateDefMap, glob_imports: FxHashMap>, unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, @@ -86,9 +92,11 @@ struct DefCollector { /// Some macro use `$tt:tt which mean we have to handle the macro perfectly /// To prevent stack overflow, we add a deep counter here for prevent that. macro_stack_monitor: MacroStackMonitor, + + cfg_options: &'a CfgOptions, } -impl<'a, DB> DefCollector<&'a DB> +impl DefCollector<'_, DB> where DB: DefDatabase, { @@ -506,7 +514,7 @@ struct ModCollector<'a, D> { parent_module: Option>, } -impl ModCollector<'_, &'_ mut DefCollector<&'_ DB>> +impl ModCollector<'_, &'_ mut DefCollector<'_, DB>> where DB: DefDatabase, { @@ -523,23 +531,27 @@ where // `#[macro_use] extern crate` is hoisted to imports macros before collecting // any other items. for item in items { - if let raw::RawItemKind::Import(import_id) = item.kind { - let import = self.raw_items[import_id].clone(); - if import.is_extern_crate && import.is_macro_use { - self.def_collector.import_macros_from_extern_crate(self.module_id, &import); + if self.is_cfg_enabled(&item.attrs) { + if let raw::RawItemKind::Import(import_id) = item.kind { + let import = self.raw_items[import_id].clone(); + if import.is_extern_crate && import.is_macro_use { + self.def_collector.import_macros_from_extern_crate(self.module_id, &import); + } } } } for item in items { - match item.kind { - raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), - raw::RawItemKind::Import(import_id) => self - .def_collector - .unresolved_imports - .push((self.module_id, import_id, self.raw_items[import_id].clone())), - raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), - raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), + if self.is_cfg_enabled(&item.attrs) { + match item.kind { + raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]), + raw::RawItemKind::Import(import_id) => self + .def_collector + .unresolved_imports + .push((self.module_id, import_id, self.raw_items[import_id].clone())), + raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), + raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), + } } } } @@ -702,6 +714,13 @@ where self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); } } + + fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { + attrs + .iter() + .flat_map(|attr| attr.as_cfg()) + .all(|cfg| self.def_collector.cfg_options.is_cfg_enabled(cfg).unwrap_or(true)) + } } fn is_macro_rules(path: &Path) -> bool { @@ -729,6 +748,7 @@ mod tests { unresolved_imports: Vec::new(), unexpanded_macros: Vec::new(), macro_stack_monitor: monitor, + cfg_options: &CfgOptions::default(), }; collector.collect(); collector.finish() diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index cacbcb517..ff079bcf1 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -2,7 +2,6 @@ use std::{ops::Index, sync::Arc}; -use mbe::ast_to_token_tree; use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, @@ -11,6 +10,7 @@ use ra_syntax::{ use test_utils::tested_by; use crate::{ + attr::Attr, db::{AstDatabase, DefDatabase}, AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source, }; @@ -29,8 +29,6 @@ pub struct RawItems { items: Vec, } -type Attrs = Arc<[tt::Subtree]>; - #[derive(Debug, Default, PartialEq, Eq)] pub struct ImportSourceMap { map: ArenaMap, @@ -124,7 +122,7 @@ impl Index for RawItems { #[derive(Debug, PartialEq, Eq, Clone)] pub(super) struct RawItem { - pub(super) attrs: Attrs, + pub(super) attrs: Arc<[Attr]>, pub(super) kind: RawItemKind, } @@ -285,6 +283,7 @@ impl RawItemsCollector<&DB> { let attrs = self.parse_attrs(&module); let ast_id = self.source_ast_id_map.ast_id(&module); + // FIXME: cfg_attr let is_macro_use = module.has_atom_attr("macro_use"); if module.has_semi() { let attr_path = extract_mod_path_attribute(&module); @@ -315,6 +314,7 @@ impl RawItemsCollector<&DB> { } fn add_use_item(&mut self, current_module: Option, use_item: ast::UseItem) { + // FIXME: cfg_attr let is_prelude = use_item.has_atom_attr("prelude_import"); let attrs = self.parse_attrs(&use_item); @@ -349,6 +349,7 @@ impl RawItemsCollector<&DB> { let path = Path::from_name_ref(&name_ref); let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); let attrs = self.parse_attrs(&extern_crate); + // FIXME: cfg_attr let is_macro_use = extern_crate.has_atom_attr("macro_use"); let import_data = ImportData { path, @@ -368,6 +369,7 @@ impl RawItemsCollector<&DB> { } fn add_macro(&mut self, current_module: Option, m: ast::MacroCall) { + let attrs = self.parse_attrs(&m); let path = match m .path() .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db)) @@ -378,6 +380,7 @@ impl RawItemsCollector<&DB> { let name = m.name().map(|it| it.as_name()); let ast_id = self.source_ast_id_map.ast_id(&m); + // FIXME: cfg_attr let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export"); let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); @@ -387,7 +390,7 @@ impl RawItemsCollector<&DB> { fn push_import( &mut self, current_module: Option, - attrs: Attrs, + attrs: Arc<[Attr]>, data: ImportData, source: ImportSourcePtr, ) { @@ -396,7 +399,7 @@ impl RawItemsCollector<&DB> { self.push_item(current_module, attrs, RawItemKind::Import(import)) } - fn push_item(&mut self, current_module: Option, attrs: Attrs, kind: RawItemKind) { + fn push_item(&mut self, current_module: Option, attrs: Arc<[Attr]>, kind: RawItemKind) { match current_module { Some(module) => match &mut self.raw_items.modules[module] { ModuleData::Definition { items, .. } => items, @@ -407,11 +410,9 @@ impl RawItemsCollector<&DB> { .push(RawItem { attrs, kind }) } - fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { + fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Arc<[Attr]> { item.attrs() - .flat_map(|attr| attr.value()) - .flat_map(|tt| ast_to_token_tree(&tt)) - .map(|(tt, _)| tt) + .flat_map(|ast| Attr::from_src(Source { ast, file_id: self.file_id }, self.db)) .collect() } } -- cgit v1.2.3 From d2ea776b8fbb5286a04dde75a9a8f8b14f12bfe9 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 07:38:16 +0800 Subject: Enable CfgOptions `test` for workspace crates --- crates/ra_hir/src/mock.rs | 23 +++++++++---- crates/ra_hir/src/nameres/tests.rs | 70 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 50feb98fb..f750986b8 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs @@ -3,6 +3,7 @@ use std::{panic, sync::Arc}; use parking_lot::Mutex; +use ra_cfg::CfgOptions; use ra_db::{ salsa, CrateGraph, CrateId, Edition, FileId, FilePosition, SourceDatabase, SourceRoot, SourceRootId, @@ -74,13 +75,13 @@ impl MockDatabase { pub fn set_crate_graph_from_fixture(&mut self, graph: CrateGraphFixture) { let mut ids = FxHashMap::default(); let mut crate_graph = CrateGraph::default(); - for (crate_name, (crate_root, edition, _)) in graph.0.iter() { + for (crate_name, (crate_root, edition, cfg_options, _)) in graph.0.iter() { let crate_root = self.file_id_of(&crate_root); - let crate_id = crate_graph.add_crate_root(crate_root, *edition); + let crate_id = crate_graph.add_crate_root(crate_root, *edition, cfg_options.clone()); Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone()); ids.insert(crate_name, crate_id); } - for (crate_name, (_, _, deps)) in graph.0.iter() { + for (crate_name, (_, _, _, deps)) in graph.0.iter() { let from = ids[crate_name]; for dep in deps { let to = ids[dep]; @@ -184,7 +185,7 @@ impl MockDatabase { if is_crate_root { let mut crate_graph = CrateGraph::default(); - crate_graph.add_crate_root(file_id, Edition::Edition2018); + crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default()); self.set_crate_graph(Arc::new(crate_graph)); } file_id @@ -268,19 +269,27 @@ impl MockDatabase { } #[derive(Default)] -pub struct CrateGraphFixture(pub Vec<(String, (String, Edition, Vec))>); +pub struct CrateGraphFixture(pub Vec<(String, (String, Edition, CfgOptions, Vec))>); #[macro_export] macro_rules! crate_graph { - ($($crate_name:literal: ($crate_path:literal, $($edition:literal,)? [$($dep:literal),*]),)*) => {{ + ($( + $crate_name:literal: ( + $crate_path:literal, + $($edition:literal,)? + [$($dep:literal),*] + $(,$cfg:expr)? + ), + )*) => {{ let mut res = $crate::mock::CrateGraphFixture::default(); $( #[allow(unused_mut, unused_assignments)] let mut edition = ra_db::Edition::Edition2018; $(edition = ra_db::Edition::from_string($edition);)? + let cfg_options = { ::ra_cfg::CfgOptions::default() $(; $cfg)? }; res.0.push(( $crate_name.to_string(), - ($crate_path.to_string(), edition, vec![$($dep.to_string()),*]) + ($crate_path.to_string(), edition, cfg_options, vec![$($dep.to_string()),*]) )); )* res diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index bc4b47b70..f43767e59 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -7,6 +7,7 @@ mod mod_resolution; use std::sync::Arc; use insta::assert_snapshot; +use ra_cfg::CfgOptions; use ra_db::SourceDatabase; use test_utils::covers; @@ -507,3 +508,72 @@ fn values_dont_shadow_extern_crates() { ⋮foo: v "###); } + +#[test] +fn cfg_not_test() { + let map = def_map_with_crate_graph( + r#" + //- /main.rs + use {Foo, Bar, Baz}; + //- /lib.rs + #[prelude_import] + pub use self::prelude::*; + mod prelude { + #[cfg(test)] + pub struct Foo; + #[cfg(not(test))] + pub struct Bar; + #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] + pub struct Baz; + } + "#, + crate_graph! { + "main": ("/main.rs", ["std"]), + "std": ("/lib.rs", []), + }, + ); + + assert_snapshot!(map, @r###" + ⋮crate + ⋮Bar: t v + ⋮Baz: _ + ⋮Foo: _ + "###); +} + +#[test] +fn cfg_test() { + let map = def_map_with_crate_graph( + r#" + //- /main.rs + use {Foo, Bar, Baz}; + //- /lib.rs + #[prelude_import] + pub use self::prelude::*; + mod prelude { + #[cfg(test)] + pub struct Foo; + #[cfg(not(test))] + pub struct Bar; + #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] + pub struct Baz; + } + "#, + crate_graph! { + "main": ("/main.rs", ["std"]), + "std": ("/lib.rs", [], CfgOptions::default() + .atom("test".into()) + .feature("foo".into()) + .feature("bar".into()) + .option("opt".into(), "42".into()) + ), + }, + ); + + assert_snapshot!(map, @r###" + ⋮crate + ⋮Bar: _ + ⋮Baz: t v + ⋮Foo: t v + "###); +} -- cgit v1.2.3 From a49ad47e5afa5950f92b77badc6679295101328a Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Mon, 30 Sep 2019 17:47:17 +0800 Subject: Support cfg attribute on impl blocks --- crates/ra_hir/src/attr.rs | 19 ++++++++++++-- crates/ra_hir/src/impl_block.rs | 30 ++++++++++++++++++++--- crates/ra_hir/src/nameres/collector.rs | 5 +--- crates/ra_hir/src/nameres/raw.rs | 4 +-- crates/ra_hir/src/ty/tests.rs | 45 ++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 13 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs index 19be6de32..84c36b8da 100644 --- a/crates/ra_hir/src/attr.rs +++ b/crates/ra_hir/src/attr.rs @@ -1,11 +1,14 @@ +use std::sync::Arc; + use mbe::ast_to_token_tree; +use ra_cfg::CfgOptions; use ra_syntax::{ - ast::{self, AstNode}, + ast::{self, AstNode, AttrsOwner}, SmolStr, }; use tt::Subtree; -use crate::{db::AstDatabase, path::Path, Source}; +use crate::{db::AstDatabase, path::Path, HirFileId, Source}; #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct Attr { @@ -40,6 +43,14 @@ impl Attr { Some(Attr { path, input }) } + pub(crate) fn from_attrs_owner( + file_id: HirFileId, + owner: &impl AttrsOwner, + db: &impl AstDatabase, + ) -> Arc<[Attr]> { + owner.attrs().flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect() + } + pub(crate) fn is_simple_atom(&self, name: &str) -> bool { // FIXME: Avoid cloning self.path.as_ident().map_or(false, |s| s.to_string() == name) @@ -55,4 +66,8 @@ impl Attr { None } } + + pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option { + cfg_options.is_cfg_enabled(self.as_cfg()?) + } } diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 8cf74ddc7..7877c3171 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -4,12 +4,14 @@ use rustc_hash::FxHashMap; use std::sync::Arc; use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; +use ra_cfg::CfgOptions; use ra_syntax::{ ast::{self, AstNode}, AstPtr, }; use crate::{ + attr::Attr, code_model::{Module, ModuleSource}, db::{AstDatabase, DefDatabase, HirDatabase}, generics::HasGenericParams, @@ -176,6 +178,7 @@ pub struct ModuleImplBlocks { impl ModuleImplBlocks { fn collect( db: &(impl DefDatabase + AstDatabase), + cfg_options: &CfgOptions, module: Module, source_map: &mut ImplSourceMap, ) -> Self { @@ -188,11 +191,11 @@ impl ModuleImplBlocks { let src = m.module.definition_source(db); match &src.ast { ModuleSource::SourceFile(node) => { - m.collect_from_item_owner(db, source_map, node, src.file_id) + m.collect_from_item_owner(db, cfg_options, source_map, node, src.file_id) } ModuleSource::Module(node) => { let item_list = node.item_list().expect("inline module should have item list"); - m.collect_from_item_owner(db, source_map, &item_list, src.file_id) + m.collect_from_item_owner(db, cfg_options, source_map, &item_list, src.file_id) } }; m @@ -201,6 +204,7 @@ impl ModuleImplBlocks { fn collect_from_item_owner( &mut self, db: &(impl DefDatabase + AstDatabase), + cfg_options: &CfgOptions, source_map: &mut ImplSourceMap, owner: &dyn ast::ModuleItemOwner, file_id: HirFileId, @@ -208,6 +212,11 @@ impl ModuleImplBlocks { for item in owner.items_with_macros() { match item { ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { + let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db); + if attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) { + continue; + } + let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast); let id = self.impls.alloc(impl_block); for &impl_item in &self.impls[id].items { @@ -218,6 +227,11 @@ impl ModuleImplBlocks { } ast::ItemOrMacro::Item(_) => (), ast::ItemOrMacro::Macro(macro_call) => { + let attrs = Attr::from_attrs_owner(file_id, ¯o_call, db); + if attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) { + continue; + } + //FIXME: we should really cut down on the boilerplate required to process a macro let ast_id = db.ast_id_map(file_id).ast_id(¯o_call).with_file_id(file_id); if let Some(path) = macro_call @@ -231,7 +245,13 @@ impl ModuleImplBlocks { if let Some(item_list) = db.parse_or_expand(file_id).and_then(ast::MacroItems::cast) { - self.collect_from_item_owner(db, source_map, &item_list, file_id) + self.collect_from_item_owner( + db, + cfg_options, + source_map, + &item_list, + file_id, + ) } } } @@ -246,8 +266,10 @@ pub(crate) fn impls_in_module_with_source_map_query( module: Module, ) -> (Arc, Arc) { let mut source_map = ImplSourceMap::default(); + let crate_graph = db.crate_graph(); + let cfg_options = crate_graph.cfg_options(module.krate.crate_id()); - let result = ModuleImplBlocks::collect(db, module, &mut source_map); + let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map); (Arc::new(result), Arc::new(source_map)) } diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index f0e790e4c..1d79cbd8c 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -716,10 +716,7 @@ where } fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { - attrs - .iter() - .flat_map(|attr| attr.as_cfg()) - .all(|cfg| self.def_collector.cfg_options.is_cfg_enabled(cfg).unwrap_or(true)) + attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) } } diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index ff079bcf1..f02d4eb7a 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -411,9 +411,7 @@ impl RawItemsCollector<&DB> { } fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Arc<[Attr]> { - item.attrs() - .flat_map(|ast| Attr::from_src(Source { ast, file_id: self.file_id }, self.db)) - .collect() + Attr::from_attrs_owner(self.file_id, item, self.db) } } diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 4df39c191..171aead18 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use insta::assert_snapshot; +use ra_cfg::CfgOptions; use ra_db::{salsa::Database, FilePosition, SourceDatabase}; use ra_syntax::{ algo, @@ -23,6 +24,50 @@ use crate::{ mod never_type; mod coercion; +#[test] +fn cfg_impl_block() { + let (mut db, pos) = MockDatabase::with_position( + r#" +//- /main.rs +use foo::S as T; +struct S; + +#[cfg(test)] +impl S { + fn foo1(&self) -> i32 { 0 } +} + +#[cfg(not(test))] +impl S { + fn foo2(&self) -> i32 { 0 } +} + +fn test() { + let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4()); + t<|>; +} + +//- /foo.rs +struct S; + +#[cfg(not(test))] +impl S { + fn foo3(&self) -> i32 { 0 } +} + +#[cfg(test)] +impl S { + fn foo4(&self) -> i32 { 0 } +} +"#, + ); + db.set_crate_graph_from_fixture(crate_graph! { + "main": ("/main.rs", ["foo"], CfgOptions::default().atom("test".into())), + "foo": ("/foo.rs", []), + }); + assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos)); +} + #[test] fn infer_await() { let (mut db, pos) = MockDatabase::with_position( -- cgit v1.2.3 From 43f09ad36ccc1c53c78a66274693e53161c9b2fa Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Thu, 3 Oct 2019 01:20:08 +0800 Subject: Refactor CfgOptions inside --- crates/ra_hir/src/nameres/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index f43767e59..34dd79574 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -563,9 +563,9 @@ fn cfg_test() { "main": ("/main.rs", ["std"]), "std": ("/lib.rs", [], CfgOptions::default() .atom("test".into()) - .feature("foo".into()) - .feature("bar".into()) - .option("opt".into(), "42".into()) + .key_value("feature".into(), "foo".into()) + .key_value("feature".into(), "bar".into()) + .key_value("opt".into(), "42".into()) ), }, ); -- cgit v1.2.3 From e0100e63ae2e873f119b905ac77c3355ffb351b0 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Thu, 3 Oct 2019 01:38:56 +0800 Subject: Optimize --- crates/ra_hir/src/attr.rs | 11 ++++++++--- crates/ra_hir/src/impl_block.rs | 8 ++++++-- crates/ra_hir/src/nameres/collector.rs | 9 ++++++--- crates/ra_hir/src/nameres/raw.rs | 11 +++++++---- 4 files changed, 27 insertions(+), 12 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs index 84c36b8da..a8a7e9006 100644 --- a/crates/ra_hir/src/attr.rs +++ b/crates/ra_hir/src/attr.rs @@ -45,10 +45,15 @@ impl Attr { pub(crate) fn from_attrs_owner( file_id: HirFileId, - owner: &impl AttrsOwner, + owner: &dyn AttrsOwner, db: &impl AstDatabase, - ) -> Arc<[Attr]> { - owner.attrs().flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect() + ) -> Option> { + let mut attrs = owner.attrs().peekable(); + if attrs.peek().is_none() { + // Avoid heap allocation + return None; + } + Some(attrs.flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect()) } pub(crate) fn is_simple_atom(&self, name: &str) -> bool { diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 7877c3171..55dfc393b 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -213,7 +213,9 @@ impl ModuleImplBlocks { match item { ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db); - if attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) { + if attrs.map_or(false, |attrs| { + attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) + }) { continue; } @@ -228,7 +230,9 @@ impl ModuleImplBlocks { ast::ItemOrMacro::Item(_) => (), ast::ItemOrMacro::Macro(macro_call) => { let attrs = Attr::from_attrs_owner(file_id, ¯o_call, db); - if attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) { + if attrs.map_or(false, |attrs| { + attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) + }) { continue; } diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 1d79cbd8c..cef2dc9d2 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -7,7 +7,6 @@ use rustc_hash::FxHashMap; use test_utils::tested_by; use crate::{ - attr::Attr, db::DefDatabase, ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, name::MACRO_RULES, @@ -715,8 +714,12 @@ where } } - fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool { - attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) + fn is_cfg_enabled(&self, attrs: &raw::Attrs) -> bool { + attrs.as_ref().map_or(true, |attrs| { + attrs + .iter() + .all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false)) + }) } } diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index f02d4eb7a..623b343c4 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -120,9 +120,12 @@ impl Index for RawItems { } } +// Avoid heap allocation on items without attributes. +pub(super) type Attrs = Option>; + #[derive(Debug, PartialEq, Eq, Clone)] pub(super) struct RawItem { - pub(super) attrs: Arc<[Attr]>, + pub(super) attrs: Attrs, pub(super) kind: RawItemKind, } @@ -390,7 +393,7 @@ impl RawItemsCollector<&DB> { fn push_import( &mut self, current_module: Option, - attrs: Arc<[Attr]>, + attrs: Attrs, data: ImportData, source: ImportSourcePtr, ) { @@ -399,7 +402,7 @@ impl RawItemsCollector<&DB> { self.push_item(current_module, attrs, RawItemKind::Import(import)) } - fn push_item(&mut self, current_module: Option, attrs: Arc<[Attr]>, kind: RawItemKind) { + fn push_item(&mut self, current_module: Option, attrs: Attrs, kind: RawItemKind) { match current_module { Some(module) => match &mut self.raw_items.modules[module] { ModuleData::Definition { items, .. } => items, @@ -410,7 +413,7 @@ impl RawItemsCollector<&DB> { .push(RawItem { attrs, kind }) } - fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Arc<[Attr]> { + fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { Attr::from_attrs_owner(self.file_id, item, self.db) } } -- cgit v1.2.3 From b271cb18d5ab19624e751867df6705cd1e94edbc Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Thu, 3 Oct 2019 02:50:22 +0800 Subject: Add docs --- crates/ra_hir/src/attr.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs index a8a7e9006..f67e80bfd 100644 --- a/crates/ra_hir/src/attr.rs +++ b/crates/ra_hir/src/attr.rs @@ -1,3 +1,5 @@ +//! A higher level attributes based on TokenTree, with also some shortcuts. + use std::sync::Arc; use mbe::ast_to_token_tree; -- cgit v1.2.3