From c1db5d26a0bd491f13b12d85ee43faf6f35fb1a6 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 10 Mar 2020 21:58:15 +0800 Subject: Add additional_outdirs in config --- crates/rust-analyzer/src/config.rs | 4 ++++ crates/rust-analyzer/src/main_loop.rs | 1 + crates/rust-analyzer/src/world.rs | 1 + 3 files changed, 6 insertions(+) (limited to 'crates') diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3314269ec..a8bf29ddf 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -44,6 +44,9 @@ pub struct ServerConfig { /// Fine grained feature flags to disable specific features. pub feature_flags: FxHashMap, + /// Fine grained controls for additional `OUT_DIR` env variables + pub additional_out_dirs: FxHashMap, + pub rustfmt_args: Vec, /// Cargo feature configurations. @@ -64,6 +67,7 @@ impl Default for ServerConfig { cargo_watch_all_targets: true, with_sysroot: true, feature_flags: FxHashMap::default(), + additional_out_dirs: FxHashMap::default(), cargo_features: Default::default(), rustfmt_args: Vec::new(), } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 221f464b6..6d123f629 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -195,6 +195,7 @@ pub fn main_loop( Watch(!config.use_client_watching), options, feature_flags, + config.additional_out_dirs, ) }; diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 6f394055a..ac4395617 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs @@ -76,6 +76,7 @@ impl WorldState { watch: Watch, options: Options, feature_flags: FeatureFlags, + additional_out_dirs: FxHashMap, ) -> WorldState { let mut change = AnalysisChange::new(); -- cgit v1.2.3 From 8153a0b3ef84b8ad2f26bba14a094752797a5ada Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 10 Mar 2020 21:59:12 +0800 Subject: Add ExternSourceId and env functions --- crates/ra_db/src/input.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'crates') diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 1a1c64202..18d8e2a53 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -122,9 +122,16 @@ pub enum Edition { Edition2015, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ExternSourceId(pub u32); + #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct Env { entries: FxHashMap, + + // Note: Some env variables (e.g. OUT_DIR) are located outside of the + // crate. We store a map to allow remap it to ExternSourceId + extern_paths: FxHashMap, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -269,6 +276,26 @@ impl Env { pub fn get(&self, env: &str) -> Option { self.entries.get(env).cloned() } + + pub fn extern_path(&self, path: &str) -> Option<(ExternSourceId, RelativePathBuf)> { + self.extern_paths.iter().find_map(|(root_path, id)| { + if path.starts_with(root_path) { + let mut rel_path = &path[root_path.len()..]; + if rel_path.starts_with("/") { + rel_path = &rel_path[1..]; + } + let rel_path = RelativePathBuf::from_path(rel_path).ok()?; + Some((id.clone(), rel_path)) + } else { + None + } + }) + } + + pub fn set_extern_path(&mut self, env: &str, root_path: &str, root: ExternSourceId) { + self.entries.insert(env.to_owned(), root_path.to_owned()); + self.extern_paths.insert(root_path.to_owned(), root); + } } #[derive(Debug)] -- cgit v1.2.3 From 22f064cca7651eaf2980fcfa27618d99c633a589 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 10 Mar 2020 22:00:31 +0800 Subject: Add resolve_extern_path in DB --- crates/ra_db/src/lib.rs | 18 +++++++++++++++++- crates/ra_hir_def/src/test_db.rs | 10 +++++++++- crates/ra_hir_expand/src/test_db.rs | 9 ++++++++- crates/ra_hir_ty/src/test_db.rs | 7 +++++++ crates/ra_ide_db/src/lib.rs | 7 +++++++ 5 files changed, 48 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index fb002d717..9bf3fe248 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs @@ -11,7 +11,8 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit}; pub use crate::{ cancellation::Canceled, input::{ - CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, SourceRoot, SourceRootId, + CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSourceId, FileId, + SourceRoot, SourceRootId, }, }; pub use relative_path::{RelativePath, RelativePathBuf}; @@ -87,6 +88,12 @@ pub trait FileLoader { fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath) -> Option; fn relevant_crates(&self, file_id: FileId) -> Arc>; + + fn resolve_extern_path( + &self, + extern_id: ExternSourceId, + relative_path: &RelativePath, + ) -> Option; } /// Database which stores all significant input facts: source code and project @@ -164,4 +171,13 @@ impl FileLoader for FileLoaderDelegate<&'_ T> { let source_root = self.0.file_source_root(file_id); self.0.source_root_crates(source_root) } + + fn resolve_extern_path( + &self, + extern_id: ExternSourceId, + relative_path: &RelativePath, + ) -> Option { + let source_root = self.0.source_root(SourceRootId(extern_id.0)); + source_root.file_by_relative_path(&relative_path) + } } diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs index 1568820e9..0756916a8 100644 --- a/crates/ra_hir_def/src/test_db.rs +++ b/crates/ra_hir_def/src/test_db.rs @@ -6,7 +6,7 @@ use std::{ }; use crate::db::DefDatabase; -use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath}; +use ra_db::{salsa, CrateId, ExternSourceId, FileId, FileLoader, FileLoaderDelegate, RelativePath}; #[salsa::database( ra_db::SourceDatabaseExtStorage, @@ -52,6 +52,14 @@ impl FileLoader for TestDB { fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) } + + fn resolve_extern_path( + &self, + extern_id: ExternSourceId, + relative_path: &RelativePath, + ) -> Option { + FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path) + } } impl TestDB { diff --git a/crates/ra_hir_expand/src/test_db.rs b/crates/ra_hir_expand/src/test_db.rs index 918736e2a..c1fb762de 100644 --- a/crates/ra_hir_expand/src/test_db.rs +++ b/crates/ra_hir_expand/src/test_db.rs @@ -5,7 +5,7 @@ use std::{ sync::{Arc, Mutex}, }; -use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath}; +use ra_db::{salsa, CrateId, ExternSourceId, FileId, FileLoader, FileLoaderDelegate, RelativePath}; #[salsa::database( ra_db::SourceDatabaseExtStorage, @@ -51,4 +51,11 @@ impl FileLoader for TestDB { fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) } + fn resolve_extern_path( + &self, + anchor: ExternSourceId, + relative_path: &RelativePath, + ) -> Option { + FileLoaderDelegate(self).resolve_extern_path(anchor, relative_path) + } } diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index c794f7b84..0be2fea4b 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -67,6 +67,13 @@ impl FileLoader for TestDB { fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) } + fn resolve_extern_path( + &self, + extern_id: ra_db::ExternSourceId, + relative_path: &RelativePath, + ) -> Option { + FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path) + } } impl TestDB { diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs index a105c7556..74408d3d7 100644 --- a/crates/ra_ide_db/src/lib.rs +++ b/crates/ra_ide_db/src/lib.rs @@ -57,6 +57,13 @@ impl FileLoader for RootDatabase { fn relevant_crates(&self, file_id: FileId) -> Arc> { FileLoaderDelegate(self).relevant_crates(file_id) } + fn resolve_extern_path( + &self, + extern_id: ra_db::ExternSourceId, + relative_path: &RelativePath, + ) -> Option { + FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path) + } } impl salsa::Database for RootDatabase { -- cgit v1.2.3 From e00a1e0b79e2b2c0c20a96e5341e3a35f46f99b7 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 10 Mar 2020 22:00:58 +0800 Subject: Setup Env in world --- crates/ra_project_model/src/lib.rs | 18 ++++++++++++--- crates/rust-analyzer/src/cli/load_cargo.rs | 5 +++- crates/rust-analyzer/src/world.rs | 37 ++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 8 deletions(-) (limited to 'crates') diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 37845ca56..b46320304 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -14,7 +14,7 @@ use std::{ use anyhow::{bail, Context, Result}; use ra_cfg::CfgOptions; -use ra_db::{CrateGraph, CrateName, Edition, Env, FileId}; +use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSourceId, FileId}; use rustc_hash::FxHashMap; use serde_json::from_reader; @@ -162,6 +162,7 @@ impl ProjectWorkspace { pub fn to_crate_graph( &self, default_cfg_options: &CfgOptions, + outdirs: &FxHashMap, load: &mut dyn FnMut(&Path) -> Option, ) -> CrateGraph { let mut crate_graph = CrateGraph::default(); @@ -185,6 +186,8 @@ impl ProjectWorkspace { } opts }; + + // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env crates.insert( crate_id, crate_graph.add_crate_root( @@ -231,12 +234,17 @@ impl ProjectWorkspace { opts }; + let mut env = Env::default(); + if let Some((id, path)) = outdirs.get(krate.name(&sysroot)) { + env.set_extern_path("OUT_DIR", &path, *id); + } + let crate_id = crate_graph.add_crate_root( file_id, Edition::Edition2018, Some(krate.name(&sysroot).to_string()), cfg_options, - Env::default(), + env, ); sysroot_crates.insert(krate, crate_id); } @@ -275,12 +283,16 @@ impl ProjectWorkspace { opts.insert_features(pkg.features(&cargo).iter().map(Into::into)); opts }; + let mut env = Env::default(); + if let Some((id, path)) = outdirs.get(pkg.name(&cargo)) { + env.set_extern_path("OUT_DIR", &path, *id); + } let crate_id = crate_graph.add_crate_root( file_id, edition, Some(pkg.name(&cargo).to_string()), cfg_options, - Env::default(), + env, ); if tgt.kind(&cargo) == TargetKind::Lib { lib_tgt = Some(crate_id); diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 4be987860..403f353f1 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs @@ -52,7 +52,10 @@ pub(crate) fn load_cargo( opts }; - let crate_graph = ws.to_crate_graph(&default_cfg_options, &mut |path: &Path| { + // FIXME: outdirs? + let outdirs = FxHashMap::default(); + + let crate_graph = ws.to_crate_graph(&default_cfg_options, &outdirs, &mut |path: &Path| { let vfs_file = vfs.load(path); log::debug!("vfs file {:?} -> {:?}", path, vfs_file); vfs_file.map(vfs_file_to_id) diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index ac4395617..b64140b74 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs @@ -26,6 +26,8 @@ use crate::{ vfs_glob::{Glob, RustPackageFilterBuilder}, LspError, Result, }; +use ra_db::ExternSourceId; +use rustc_hash::{FxHashMap, FxHashSet}; #[derive(Debug, Clone)] pub struct Options { @@ -98,6 +100,19 @@ impl WorldState { RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) })); } + + let extern_dirs: FxHashSet<_> = + additional_out_dirs.iter().map(|(_, path)| (PathBuf::from(path))).collect(); + let mut extern_source_roots = FxHashMap::default(); + + roots.extend(additional_out_dirs.iter().map(|(_, path)| { + let mut filter = RustPackageFilterBuilder::default().set_member(false); + for glob in exclude_globs.iter() { + filter = filter.exclude(glob.clone()); + } + RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter()) + })); + let (task_sender, task_receiver) = unbounded(); let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); @@ -107,6 +122,11 @@ impl WorldState { let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); change.add_root(SourceRootId(r.0), is_local); change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string()); + + // FIXME: add path2root in vfs to simpily this logic + if extern_dirs.contains(&vfs_root_path) { + extern_source_roots.insert(vfs_root_path, ExternSourceId(r.0)); + } } // FIXME: Read default cfgs from config @@ -124,11 +144,20 @@ impl WorldState { vfs_file.map(|f| FileId(f.0)) }; - workspaces.iter().map(|ws| ws.to_crate_graph(&default_cfg_options, &mut load)).for_each( - |graph| { + let mut outdirs = FxHashMap::default(); + for (name, path) in additional_out_dirs { + let path = PathBuf::from(&path); + if let Some(id) = extern_source_roots.get(&path) { + outdirs.insert(name, (id.clone(), path.to_string_lossy().replace("\\", "/"))); + } + } + + workspaces + .iter() + .map(|ws| ws.to_crate_graph(&default_cfg_options, &outdirs, &mut load)) + .for_each(|graph| { crate_graph.extend(graph); - }, - ); + }); change.set_crate_graph(crate_graph); // FIXME: Figure out the multi-workspace situation -- cgit v1.2.3 From 5a292309c55639a12d10b3c37b9f800d8b802b6d Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 10 Mar 2020 22:01:08 +0800 Subject: Add and fix tests --- crates/ra_hir_expand/src/builtin_macro.rs | 181 ++++++++++++++++++++---------- crates/ra_hir_ty/src/tests/macros.rs | 20 ++++ 2 files changed, 141 insertions(+), 60 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 3f60b1cca..298ec22ff 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -90,15 +90,15 @@ register_builtin! { (line, Line) => line_expand, (stringify, Stringify) => stringify_expand, (format_args, FormatArgs) => format_args_expand, - (env, Env) => env_expand, - (option_env, OptionEnv) => option_env_expand, // format_args_nl only differs in that it adds a newline in the end, // so we use the same stub expansion for now (format_args_nl, FormatArgsNl) => format_args_expand, EAGER: (concat, Concat) => concat_expand, - (include, Include) => include_expand + (include, Include) => include_expand, + (env, Env) => env_expand, + (option_env, OptionEnv) => option_env_expand } fn line_expand( @@ -137,31 +137,6 @@ fn stringify_expand( Ok(expanded) } -fn env_expand( - _db: &dyn AstDatabase, - _id: LazyMacroId, - _tt: &tt::Subtree, -) -> Result { - // dummy implementation for type-checking purposes - // we cannot use an empty string here, because for - // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become - // `include!("foo.rs"), which maybe infinite loop - let expanded = quote! { "__RA_UNIMPLEMENTATED__" }; - - Ok(expanded) -} - -fn option_env_expand( - _db: &dyn AstDatabase, - _id: LazyMacroId, - _tt: &tt::Subtree, -) -> Result { - // dummy implementation for type-checking purposes - let expanded = quote! { std::option::Option::None::<&str> }; - - Ok(expanded) -} - fn column_expand( _db: &dyn AstDatabase, _id: LazyMacroId, @@ -278,30 +253,36 @@ fn concat_expand( fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option { let call_site = call_id.as_file().original_file(db); - let path = RelativePath::new(&path); - let res = db.resolve_relative_path(call_site, &path)?; - // Prevent include itself - if res == call_site { - return None; + // Handle trivial case + if let Some(res) = db.resolve_relative_path(call_site, &RelativePath::new(&path)) { + // Prevent include itself + return if res == call_site { None } else { Some(res) }; } - Some(res) + + // Extern paths ? + let krate = db.relevant_crates(call_site).get(0)?.clone(); + let (extern_source_id, relative_file) = db.crate_graph()[krate].env.extern_path(path)?; + + db.resolve_extern_path(extern_source_id, &relative_file) } -fn include_expand( - db: &dyn AstDatabase, - arg_id: EagerMacroId, - tt: &tt::Subtree, -) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { - let path = tt - .token_trees +fn parse_string(tt: &tt::Subtree) -> Result { + tt.token_trees .get(0) .and_then(|tt| match tt { tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(&it), _ => None, }) - .ok_or_else(|| mbe::ExpandError::ConversionError)?; + .ok_or_else(|| mbe::ExpandError::ConversionError) +} +fn include_expand( + db: &dyn AstDatabase, + arg_id: EagerMacroId, + tt: &tt::Subtree, +) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { + let path = parse_string(tt)?; let file_id = relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?; @@ -314,12 +295,58 @@ fn include_expand( Ok((res, FragmentKind::Items)) } +fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option { + let call_id: MacroCallId = arg_id.into(); + let original_file = call_id.as_file().original_file(db); + + let krate = db.relevant_crates(original_file).get(0)?.clone(); + db.crate_graph()[krate].env.get(key) +} + +fn env_expand( + db: &dyn AstDatabase, + arg_id: EagerMacroId, + tt: &tt::Subtree, +) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { + let key = parse_string(tt)?; + + // FIXME: + // If the environment variable is not defined int rustc, then a compilation error will be emitted. + // We might do the same if we fully support all other stuffs. + // But for now on, we should return some dummy string for better type infer purpose. + // However, we cannot use an empty string here, because for + // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become + // `include!("foo.rs"), which might go to infinite loop + let s = get_env_inner(db, arg_id, &key).unwrap_or("__RA_UNIMPLEMENTATED__".to_string()); + let expanded = quote! { #s }; + + Ok((expanded, FragmentKind::Expr)) +} + +fn option_env_expand( + db: &dyn AstDatabase, + arg_id: EagerMacroId, + tt: &tt::Subtree, +) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { + let key = parse_string(tt)?; + let expanded = match get_env_inner(db, arg_id, &key) { + None => quote! { std::option::Option::None::<&str> }, + Some(s) => quote! { std::option::Some(#s) }, + }; + + Ok((expanded, FragmentKind::Expr)) +} + #[cfg(test)] mod tests { use super::*; - use crate::{name::AsName, test_db::TestDB, AstNode, MacroCallId, MacroCallKind, MacroCallLoc}; + use crate::{ + name::AsName, test_db::TestDB, AstNode, EagerCallLoc, MacroCallId, MacroCallKind, + MacroCallLoc, + }; use ra_db::{fixture::WithFixture, SourceDatabase}; use ra_syntax::ast::NameOwner; + use std::sync::Arc; fn expand_builtin_macro(ra_fixture: &str) -> String { let (db, file_id) = TestDB::with_single_file(&ra_fixture); @@ -330,27 +357,61 @@ mod tests { let ast_id_map = db.ast_id_map(file_id.into()); let expander = find_by_name(¯o_calls[0].name().unwrap().as_name()).unwrap(); - let expander = expander.left().unwrap(); - // the first one should be a macro_rules - let def = MacroDefId { - krate: Some(CrateId(0)), - ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), - kind: MacroDefKind::BuiltIn(expander), - }; + let file_id = match expander { + Either::Left(expander) => { + // the first one should be a macro_rules + let def = MacroDefId { + krate: Some(CrateId(0)), + ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), + kind: MacroDefKind::BuiltIn(expander), + }; - let loc = MacroCallLoc { - def, - kind: MacroCallKind::FnLike(AstId::new( - file_id.into(), - ast_id_map.ast_id(¯o_calls[1]), - )), - }; + let loc = MacroCallLoc { + def, + kind: MacroCallKind::FnLike(AstId::new( + file_id.into(), + ast_id_map.ast_id(¯o_calls[1]), + )), + }; + + let id: MacroCallId = db.intern_macro(loc).into(); + id.as_file() + } + Either::Right(expander) => { + // the first one should be a macro_rules + let def = MacroDefId { + krate: Some(CrateId(0)), + ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), + kind: MacroDefKind::BuiltInEager(expander), + }; - let id: MacroCallId = db.intern_macro(loc).into(); - let parsed = db.parse_or_expand(id.as_file()).unwrap(); + let args = macro_calls[1].token_tree().unwrap(); + let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; + + let arg_id = db.intern_eager_expansion({ + EagerCallLoc { + def, + fragment: FragmentKind::Expr, + subtree: Arc::new(parsed_args.clone()), + file_id: file_id.into(), + } + }); + + let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).unwrap(); + let eager = EagerCallLoc { + def, + fragment, + subtree: Arc::new(subtree), + file_id: file_id.into(), + }; + + let id: MacroCallId = db.intern_eager_expansion(eager.into()).into(); + id.as_file() + } + }; - parsed.text().to_string() + db.parse_or_expand(file_id).unwrap().to_string() } #[test] diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index ffa78b046..32457bbf7 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -549,6 +549,26 @@ fn main() { ); } +#[test] +fn infer_builtin_macros_env() { + assert_snapshot!( + infer(r#" +//- /main.rs env:foo=bar +#[rustc_builtin_macro] +macro_rules! env {() => {}} + +fn main() { + let x = env!("foo"); +} +"#), + @r###" + ![0; 5) '"bar"': &str + [88; 116) '{ ...o"); }': () + [98; 99) 'x': &str + "### + ); +} + #[test] fn infer_derive_clone_simple() { let (db, pos) = TestDB::with_position( -- cgit v1.2.3 From 6ea7c319154f9ec10721f4041afc9d07d6b2476b Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 11 Mar 2020 11:04:02 +0800 Subject: Add extern source --- crates/ra_db/src/fixture.rs | 12 +++++++++++- crates/ra_db/src/input.rs | 24 ++++++++++++++++++++---- crates/ra_db/src/lib.rs | 4 ++-- crates/ra_hir_expand/src/builtin_macro.rs | 3 ++- crates/ra_ide/src/lib.rs | 1 + crates/ra_ide/src/mock_analysis.rs | 2 ++ crates/ra_ide/src/parent_module.rs | 1 + crates/ra_project_model/src/lib.rs | 13 ++++++++++--- 8 files changed, 49 insertions(+), 11 deletions(-) (limited to 'crates') diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index 7f43c2971..3dc86ca2d 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs @@ -61,7 +61,14 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId }; let mut crate_graph = CrateGraph::default(); - crate_graph.add_crate_root(file_id, meta.edition, meta.krate, meta.cfg, meta.env); + crate_graph.add_crate_root( + file_id, + meta.edition, + meta.krate, + meta.cfg, + meta.env, + Default::default(), + ); crate_graph } else { let mut crate_graph = CrateGraph::default(); @@ -71,6 +78,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId None, CfgOptions::default(), Env::default(), + Default::default(), ); crate_graph }; @@ -119,6 +127,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option Option, pub cfg_options: CfgOptions, pub env: Env, + pub extern_source: ExternSource, pub dependencies: Vec, } @@ -128,9 +129,13 @@ pub struct ExternSourceId(pub u32); #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct Env { entries: FxHashMap, +} - // Note: Some env variables (e.g. OUT_DIR) are located outside of the - // crate. We store a map to allow remap it to ExternSourceId +// FIXME: Redesign vfs for solve the following limitation ? +// Note: Some env variables (e.g. OUT_DIR) are located outside of the +// crate. We store a map to allow remap it to ExternSourceId +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct ExternSource { extern_paths: FxHashMap, } @@ -148,6 +153,7 @@ impl CrateGraph { display_name: Option, cfg_options: CfgOptions, env: Env, + extern_source: ExternSource, ) -> CrateId { let data = CrateData { root_file_id: file_id, @@ -155,6 +161,7 @@ impl CrateGraph { display_name, cfg_options, env, + extern_source, dependencies: Vec::new(), }; let crate_id = CrateId(self.arena.len() as u32); @@ -276,7 +283,9 @@ impl Env { pub fn get(&self, env: &str) -> Option { self.entries.get(env).cloned() } +} +impl ExternSource { pub fn extern_path(&self, path: &str) -> Option<(ExternSourceId, RelativePathBuf)> { self.extern_paths.iter().find_map(|(root_path, id)| { if path.starts_with(root_path) { @@ -292,8 +301,7 @@ impl Env { }) } - pub fn set_extern_path(&mut self, env: &str, root_path: &str, root: ExternSourceId) { - self.entries.insert(env.to_owned(), root_path.to_owned()); + pub fn set_extern_path(&mut self, root_path: &str, root: ExternSourceId) { self.extern_paths.insert(root_path.to_owned(), root); } } @@ -327,6 +335,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -334,6 +343,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); let crate3 = graph.add_crate_root( FileId(3u32), @@ -341,6 +351,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); @@ -356,6 +367,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -363,6 +375,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); let crate3 = graph.add_crate_root( FileId(3u32), @@ -370,6 +383,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); @@ -384,6 +398,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -391,6 +406,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); assert!(graph .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 9bf3fe248..d500d5e85 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs @@ -11,8 +11,8 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit}; pub use crate::{ cancellation::Canceled, input::{ - CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSourceId, FileId, - SourceRoot, SourceRootId, + CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, + FileId, SourceRoot, SourceRootId, }, }; pub use relative_path::{RelativePath, RelativePathBuf}; diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 298ec22ff..a90007f26 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -262,7 +262,8 @@ fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Opti // Extern paths ? let krate = db.relevant_crates(call_site).get(0)?.clone(); - let (extern_source_id, relative_file) = db.crate_graph()[krate].env.extern_path(path)?; + let (extern_source_id, relative_file) = + db.crate_graph()[krate].extern_source.extern_path(path)?; db.resolve_extern_path(extern_source_id, &relative_file) } diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index c60e86aea..39981ed3b 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -217,6 +217,7 @@ impl Analysis { None, cfg_options, Env::default(), + Default::default(), ); change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); change.set_crate_graph(crate_graph); diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index 90f84b052..25816cf6f 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs @@ -102,6 +102,7 @@ impl MockAnalysis { None, cfg_options, Env::default(), + Default::default(), )); } else if path.ends_with("/lib.rs") { let crate_name = path.parent().unwrap().file_name().unwrap(); @@ -111,6 +112,7 @@ impl MockAnalysis { Some(crate_name.to_owned()), cfg_options, Env::default(), + Default::default(), ); if let Some(root_crate) = root_crate { crate_graph diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index b73cefd97..76d130b9b 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs @@ -136,6 +136,7 @@ mod tests { None, CfgOptions::default(), Env::default(), + Default::default(), ); let mut change = AnalysisChange::new(); change.set_crate_graph(crate_graph); diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index b46320304..a6274709d 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -14,7 +14,7 @@ use std::{ use anyhow::{bail, Context, Result}; use ra_cfg::CfgOptions; -use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSourceId, FileId}; +use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSource, ExternSourceId, FileId}; use rustc_hash::FxHashMap; use serde_json::from_reader; @@ -197,6 +197,7 @@ impl ProjectWorkspace { None, cfg_options, Env::default(), + Default::default(), ), ); } @@ -235,8 +236,10 @@ impl ProjectWorkspace { }; let mut env = Env::default(); + let mut extern_source = ExternSource::default(); if let Some((id, path)) = outdirs.get(krate.name(&sysroot)) { - env.set_extern_path("OUT_DIR", &path, *id); + env.set("OUT_DIR", path.clone()); + extern_source.set_extern_path(&path, *id); } let crate_id = crate_graph.add_crate_root( @@ -245,6 +248,7 @@ impl ProjectWorkspace { Some(krate.name(&sysroot).to_string()), cfg_options, env, + extern_source, ); sysroot_crates.insert(krate, crate_id); } @@ -284,8 +288,10 @@ impl ProjectWorkspace { opts }; let mut env = Env::default(); + let mut extern_source = ExternSource::default(); if let Some((id, path)) = outdirs.get(pkg.name(&cargo)) { - env.set_extern_path("OUT_DIR", &path, *id); + env.set("OUT_DIR", path.clone()); + extern_source.set_extern_path(&path, *id); } let crate_id = crate_graph.add_crate_root( file_id, @@ -293,6 +299,7 @@ impl ProjectWorkspace { Some(pkg.name(&cargo).to_string()), cfg_options, env, + extern_source, ); if tgt.kind(&cargo) == TargetKind::Lib { lib_tgt = Some(crate_id); -- cgit v1.2.3