aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2020-03-18 12:56:46 +0000
committerEdwin Cheng <[email protected]>2020-03-25 19:29:45 +0000
commitd0b6ed4441469acfb6bc6555d78abf12637b6cf4 (patch)
treea4b39b33590c472a68fd76ceae96732e9cb54ebb /crates
parenta617f24eae6c02f087759312e9aa08507fbecdf0 (diff)
Add ProcMacroClient
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_db/Cargo.toml1
-rw-r--r--crates/ra_db/src/fixture.rs4
-rw-r--r--crates/ra_db/src/input.rs15
-rw-r--r--crates/ra_db/src/lib.rs3
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs18
-rw-r--r--crates/ra_hir_expand/src/proc_macro.rs30
-rw-r--r--crates/ra_ide/src/lib.rs1
-rw-r--r--crates/ra_ide/src/mock_analysis.rs2
-rw-r--r--crates/ra_ide/src/parent_module.rs1
-rw-r--r--crates/ra_proc_macro/src/lib.rs81
-rw-r--r--crates/ra_project_model/Cargo.toml1
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs31
-rw-r--r--crates/ra_project_model/src/json_project.rs1
-rw-r--r--crates/ra_project_model/src/lib.rs41
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs19
-rw-r--r--crates/rust-analyzer/src/world.rs14
16 files changed, 220 insertions, 43 deletions
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 878c22ba9..82fd842a6 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -15,4 +15,5 @@ rustc-hash = "1.1.0"
15ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
16ra_cfg = { path = "../ra_cfg" } 16ra_cfg = { path = "../ra_cfg" }
17ra_prof = { path = "../ra_prof" } 17ra_prof = { path = "../ra_prof" }
18ra_proc_macro = { path = "../ra_proc_macro" }
18test_utils = { path = "../test_utils" } 19test_utils = { path = "../test_utils" }
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
index 3464f43df..9d992886e 100644
--- a/crates/ra_db/src/fixture.rs
+++ b/crates/ra_db/src/fixture.rs
@@ -70,6 +70,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
70 meta.cfg, 70 meta.cfg,
71 meta.env, 71 meta.env,
72 Default::default(), 72 Default::default(),
73 Default::default(),
73 ); 74 );
74 crate_graph 75 crate_graph
75 } else { 76 } else {
@@ -81,6 +82,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
81 CfgOptions::default(), 82 CfgOptions::default(),
82 Env::default(), 83 Env::default(),
83 Default::default(), 84 Default::default(),
85 Default::default(),
84 ); 86 );
85 crate_graph 87 crate_graph
86 }; 88 };
@@ -130,6 +132,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
130 meta.cfg, 132 meta.cfg,
131 meta.env, 133 meta.env,
132 Default::default(), 134 Default::default(),
135 Default::default(),
133 ); 136 );
134 let prev = crates.insert(krate.clone(), crate_id); 137 let prev = crates.insert(krate.clone(), crate_id);
135 assert!(prev.is_none()); 138 assert!(prev.is_none());
@@ -167,6 +170,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
167 CfgOptions::default(), 170 CfgOptions::default(),
168 Env::default(), 171 Env::default(),
169 Default::default(), 172 Default::default(),
173 Default::default(),
170 ); 174 );
171 } else { 175 } else {
172 for (from, to) in crate_deps { 176 for (from, to) in crate_deps {
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index e371f849d..65b553a9f 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -19,6 +19,7 @@ use rustc_hash::FxHashSet;
19 19
20use crate::{RelativePath, RelativePathBuf}; 20use crate::{RelativePath, RelativePathBuf};
21use fmt::Display; 21use fmt::Display;
22use ra_proc_macro::ProcMacro;
22 23
23/// `FileId` is an integer which uniquely identifies a file. File paths are 24/// `FileId` is an integer which uniquely identifies a file. File paths are
24/// messy and system-dependent, so most of the code should work directly with 25/// messy and system-dependent, so most of the code should work directly with
@@ -115,6 +116,9 @@ impl Display for CrateName {
115 } 116 }
116} 117}
117 118
119#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
120pub struct ProcMacroId(pub usize);
121
118#[derive(Debug, Clone, PartialEq, Eq)] 122#[derive(Debug, Clone, PartialEq, Eq)]
119pub struct CrateData { 123pub struct CrateData {
120 pub root_file_id: FileId, 124 pub root_file_id: FileId,
@@ -127,6 +131,7 @@ pub struct CrateData {
127 pub env: Env, 131 pub env: Env,
128 pub extern_source: ExternSource, 132 pub extern_source: ExternSource,
129 pub dependencies: Vec<Dependency>, 133 pub dependencies: Vec<Dependency>,
134 pub proc_macro: Vec<ProcMacro>,
130} 135}
131 136
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 137#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -166,6 +171,7 @@ impl CrateGraph {
166 cfg_options: CfgOptions, 171 cfg_options: CfgOptions,
167 env: Env, 172 env: Env,
168 extern_source: ExternSource, 173 extern_source: ExternSource,
174 proc_macro: Vec<ProcMacro>,
169 ) -> CrateId { 175 ) -> CrateId {
170 let data = CrateData { 176 let data = CrateData {
171 root_file_id: file_id, 177 root_file_id: file_id,
@@ -174,6 +180,7 @@ impl CrateGraph {
174 cfg_options, 180 cfg_options,
175 env, 181 env,
176 extern_source, 182 extern_source,
183 proc_macro,
177 dependencies: Vec::new(), 184 dependencies: Vec::new(),
178 }; 185 };
179 let crate_id = CrateId(self.arena.len() as u32); 186 let crate_id = CrateId(self.arena.len() as u32);
@@ -345,6 +352,7 @@ mod tests {
345 CfgOptions::default(), 352 CfgOptions::default(),
346 Env::default(), 353 Env::default(),
347 Default::default(), 354 Default::default(),
355 Default::default(),
348 ); 356 );
349 let crate2 = graph.add_crate_root( 357 let crate2 = graph.add_crate_root(
350 FileId(2u32), 358 FileId(2u32),
@@ -353,6 +361,7 @@ mod tests {
353 CfgOptions::default(), 361 CfgOptions::default(),
354 Env::default(), 362 Env::default(),
355 Default::default(), 363 Default::default(),
364 Default::default(),
356 ); 365 );
357 let crate3 = graph.add_crate_root( 366 let crate3 = graph.add_crate_root(
358 FileId(3u32), 367 FileId(3u32),
@@ -361,6 +370,7 @@ mod tests {
361 CfgOptions::default(), 370 CfgOptions::default(),
362 Env::default(), 371 Env::default(),
363 Default::default(), 372 Default::default(),
373 Default::default(),
364 ); 374 );
365 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 375 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
366 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); 376 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@@ -377,6 +387,7 @@ mod tests {
377 CfgOptions::default(), 387 CfgOptions::default(),
378 Env::default(), 388 Env::default(),
379 Default::default(), 389 Default::default(),
390 Default::default(),
380 ); 391 );
381 let crate2 = graph.add_crate_root( 392 let crate2 = graph.add_crate_root(
382 FileId(2u32), 393 FileId(2u32),
@@ -385,6 +396,7 @@ mod tests {
385 CfgOptions::default(), 396 CfgOptions::default(),
386 Env::default(), 397 Env::default(),
387 Default::default(), 398 Default::default(),
399 Default::default(),
388 ); 400 );
389 let crate3 = graph.add_crate_root( 401 let crate3 = graph.add_crate_root(
390 FileId(3u32), 402 FileId(3u32),
@@ -393,6 +405,7 @@ mod tests {
393 CfgOptions::default(), 405 CfgOptions::default(),
394 Env::default(), 406 Env::default(),
395 Default::default(), 407 Default::default(),
408 Default::default(),
396 ); 409 );
397 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 410 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
398 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); 411 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@@ -408,6 +421,7 @@ mod tests {
408 CfgOptions::default(), 421 CfgOptions::default(),
409 Env::default(), 422 Env::default(),
410 Default::default(), 423 Default::default(),
424 Default::default(),
411 ); 425 );
412 let crate2 = graph.add_crate_root( 426 let crate2 = graph.add_crate_root(
413 FileId(2u32), 427 FileId(2u32),
@@ -416,6 +430,7 @@ mod tests {
416 CfgOptions::default(), 430 CfgOptions::default(),
417 Env::default(), 431 Env::default(),
418 Default::default(), 432 Default::default(),
433 Default::default(),
419 ); 434 );
420 assert!(graph 435 assert!(graph
421 .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) 436 .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 bac24e218..5829ae465 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -12,9 +12,10 @@ pub use crate::{
12 cancellation::Canceled, 12 cancellation::Canceled,
13 input::{ 13 input::{
14 CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, 14 CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId,
15 FileId, SourceRoot, SourceRootId, 15 FileId, ProcMacroId, SourceRoot, SourceRootId,
16 }, 16 },
17}; 17};
18pub use ra_proc_macro::ProcMacro;
18pub use relative_path::{RelativePath, RelativePathBuf}; 19pub use relative_path::{RelativePath, RelativePathBuf};
19pub use salsa; 20pub use salsa;
20 21
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 9c125f32f..9b46431cb 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -11,8 +11,8 @@ use hir_expand::{
11 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 11 HirFileId, MacroCallId, MacroDefId, MacroDefKind,
12}; 12};
13use ra_cfg::CfgOptions; 13use ra_cfg::CfgOptions;
14use ra_db::{CrateId, FileId}; 14use ra_db::{CrateId, FileId, ProcMacroId};
15use ra_syntax::ast; 15use ra_syntax::{ast, SmolStr};
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
@@ -53,6 +53,16 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
53 } 53 }
54 54
55 let cfg_options = &crate_graph[def_map.krate].cfg_options; 55 let cfg_options = &crate_graph[def_map.krate].cfg_options;
56 let proc_macros = &crate_graph[def_map.krate].proc_macro;
57 let proc_macros = proc_macros
58 .iter()
59 .enumerate()
60 .map(|(idx, it)| {
61 // FIXME: a hacky way to create a Name from string.
62 let name = tt::Ident { text: SmolStr::new(&it.name()), id: tt::TokenId::unspecified() };
63 (name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx)))
64 })
65 .collect();
56 66
57 let mut collector = DefCollector { 67 let mut collector = DefCollector {
58 db, 68 db,
@@ -65,9 +75,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
65 unexpanded_attribute_macros: Vec::new(), 75 unexpanded_attribute_macros: Vec::new(),
66 mod_dirs: FxHashMap::default(), 76 mod_dirs: FxHashMap::default(),
67 cfg_options, 77 cfg_options,
68 78 proc_macros,
69 // FIXME: pass proc-macro from crate-graph
70 proc_macros: Default::default(),
71 }; 79 };
72 collector.collect(); 80 collector.collect();
73 collector.finish() 81 collector.finish()
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs
index a8dee2052..296325b05 100644
--- a/crates/ra_hir_expand/src/proc_macro.rs
+++ b/crates/ra_hir_expand/src/proc_macro.rs
@@ -1,33 +1,31 @@
1//! Proc Macro Expander stub 1//! Proc Macro Expander stub
2 2
3use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc}; 3use crate::{db::AstDatabase, LazyMacroId};
4use ra_db::CrateId; 4use ra_db::{CrateId, ProcMacroId};
5 5
6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
7pub struct ProcMacroExpander { 7pub struct ProcMacroExpander {
8 krate: CrateId, 8 krate: CrateId,
9 proc_macro_id: ProcMacroId,
9} 10}
10 11
11impl ProcMacroExpander { 12impl ProcMacroExpander {
12 pub fn new(krate: CrateId) -> ProcMacroExpander { 13 pub fn new(krate: CrateId, proc_macro_id: ProcMacroId) -> ProcMacroExpander {
13 ProcMacroExpander { krate } 14 ProcMacroExpander { krate, proc_macro_id }
14 } 15 }
15 16
16 pub fn expand( 17 pub fn expand(
17 &self, 18 &self,
18 db: &dyn AstDatabase, 19 db: &dyn AstDatabase,
19 id: LazyMacroId, 20 _id: LazyMacroId,
20 _tt: &tt::Subtree, 21 tt: &tt::Subtree,
21 ) -> Result<tt::Subtree, mbe::ExpandError> { 22 ) -> Result<tt::Subtree, mbe::ExpandError> {
22 let loc: MacroCallLoc = db.lookup_intern_macro(id); 23 let krate_graph = db.crate_graph();
23 let name = match loc.kind { 24 let proc_macro = krate_graph[self.krate]
24 MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError), 25 .proc_macro
25 MacroCallKind::Attr(_, name) => name, 26 .get(self.proc_macro_id.0)
26 }; 27 .clone()
27 28 .ok_or_else(|| mbe::ExpandError::ConversionError)?;
28 log::debug!("Proc-macro-expanding name = {}", name); 29 proc_macro.custom_derive(tt)
29
30 // Return nothing for now
31 return Ok(tt::Subtree::default());
32 } 30 }
33} 31}
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 5ab06c6cf..e43414985 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -213,6 +213,7 @@ impl Analysis {
213 cfg_options, 213 cfg_options,
214 Env::default(), 214 Env::default(),
215 Default::default(), 215 Default::default(),
216 Default::default(),
216 ); 217 );
217 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); 218 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
218 change.set_crate_graph(crate_graph); 219 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 2cf77a31f..2c13f206a 100644
--- a/crates/ra_ide/src/mock_analysis.rs
+++ b/crates/ra_ide/src/mock_analysis.rs
@@ -103,6 +103,7 @@ impl MockAnalysis {
103 cfg_options, 103 cfg_options,
104 Env::default(), 104 Env::default(),
105 Default::default(), 105 Default::default(),
106 Default::default(),
106 )); 107 ));
107 } else if path.ends_with("/lib.rs") { 108 } else if path.ends_with("/lib.rs") {
108 let crate_name = path.parent().unwrap().file_name().unwrap(); 109 let crate_name = path.parent().unwrap().file_name().unwrap();
@@ -113,6 +114,7 @@ impl MockAnalysis {
113 cfg_options, 114 cfg_options,
114 Env::default(), 115 Env::default(),
115 Default::default(), 116 Default::default(),
117 Default::default(),
116 ); 118 );
117 if let Some(root_crate) = root_crate { 119 if let Some(root_crate) = root_crate {
118 crate_graph 120 crate_graph
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs
index 76d130b9b..958b92bed 100644
--- a/crates/ra_ide/src/parent_module.rs
+++ b/crates/ra_ide/src/parent_module.rs
@@ -137,6 +137,7 @@ mod tests {
137 CfgOptions::default(), 137 CfgOptions::default(),
138 Env::default(), 138 Env::default(),
139 Default::default(), 139 Default::default(),
140 Default::default(),
140 ); 141 );
141 let mut change = AnalysisChange::new(); 142 let mut change = AnalysisChange::new();
142 change.set_crate_graph(crate_graph); 143 change.set_crate_graph(crate_graph);
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs
index 31e1bb209..a7a84249f 100644
--- a/crates/ra_proc_macro/src/lib.rs
+++ b/crates/ra_proc_macro/src/lib.rs
@@ -1,7 +1,78 @@
1#[cfg(test)] 1//! Client-side Proc-Macro crate
2mod tests { 2//!
3 #[test] 3//! We separate proc-macro expanding logic to an extern program to allow
4 fn it_works() { 4//! different implementations (e.g. wasm or dylib loading). And this crate
5 assert_eq!(2 + 2, 4); 5//! is used for provide basic infra-structure for commnicate between two
6//! process: Client (RA itself), Server (the external program)
7
8use ra_mbe::ExpandError;
9use ra_tt::Subtree;
10use std::{
11 path::{Path, PathBuf},
12 sync::Arc,
13};
14
15trait ProcMacroExpander: std::fmt::Debug + Send + Sync + std::panic::RefUnwindSafe {
16 fn custom_derive(&self, subtree: &Subtree, derive_name: &str) -> Result<Subtree, ExpandError>;
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct ProcMacroProcessExpander {
21 process_path: PathBuf,
22}
23
24impl ProcMacroExpander for ProcMacroProcessExpander {
25 fn custom_derive(
26 &self,
27 _subtree: &Subtree,
28 _derive_name: &str,
29 ) -> Result<Subtree, ExpandError> {
30 // FIXME: do nothing for now
31 Ok(Subtree::default())
32 }
33}
34
35#[derive(Debug, Clone)]
36pub struct ProcMacro {
37 expander: Arc<Box<dyn ProcMacroExpander>>,
38 name: String,
39}
40
41impl Eq for ProcMacro {}
42impl PartialEq for ProcMacro {
43 fn eq(&self, other: &ProcMacro) -> bool {
44 self.name == other.name && Arc::ptr_eq(&self.expander, &other.expander)
45 }
46}
47
48impl ProcMacro {
49 pub fn name(&self) -> String {
50 self.name.clone()
51 }
52
53 pub fn custom_derive(&self, subtree: &Subtree) -> Result<Subtree, ExpandError> {
54 self.expander.custom_derive(subtree, &self.name)
55 }
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum ProcMacroClient {
60 Process { expander: Arc<ProcMacroProcessExpander> },
61 Dummy,
62}
63
64impl ProcMacroClient {
65 pub fn extern_process(process_path: &Path) -> ProcMacroClient {
66 let expander = ProcMacroProcessExpander { process_path: process_path.into() };
67 ProcMacroClient::Process { expander: Arc::new(expander) }
68 }
69
70 pub fn dummy() -> ProcMacroClient {
71 ProcMacroClient::Dummy
72 }
73
74 pub fn by_dylib_path(&self, _dylib_path: &Path) -> Vec<ProcMacro> {
75 // FIXME: return empty for now
76 vec![]
6 } 77 }
7} 78}
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml
index 22300548a..cdcdd63c9 100644
--- a/crates/ra_project_model/Cargo.toml
+++ b/crates/ra_project_model/Cargo.toml
@@ -17,6 +17,7 @@ ra_arena = { path = "../ra_arena" }
17ra_db = { path = "../ra_db" } 17ra_db = { path = "../ra_db" }
18ra_cfg = { path = "../ra_cfg" } 18ra_cfg = { path = "../ra_cfg" }
19ra_cargo_watch = { path = "../ra_cargo_watch" } 19ra_cargo_watch = { path = "../ra_cargo_watch" }
20ra_proc_macro = { path = "../ra_proc_macro" }
20 21
21serde = { version = "1.0.104", features = ["derive"] } 22serde = { version = "1.0.104", features = ["derive"] }
22serde_json = "1.0.48" 23serde_json = "1.0.48"
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index c7f9bd873..291594e2a 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -83,6 +83,7 @@ pub struct PackageData {
83 pub edition: Edition, 83 pub edition: Edition,
84 pub features: Vec<String>, 84 pub features: Vec<String>,
85 pub out_dir: Option<PathBuf>, 85 pub out_dir: Option<PathBuf>,
86 pub proc_macro_dylib_path: Option<PathBuf>,
86} 87}
87 88
88#[derive(Debug, Clone)] 89#[derive(Debug, Clone)]
@@ -158,8 +159,11 @@ impl CargoWorkspace {
158 })?; 159 })?;
159 160
160 let mut out_dir_by_id = FxHashMap::default(); 161 let mut out_dir_by_id = FxHashMap::default();
162 let mut proc_macro_dylib_paths = FxHashMap::default();
161 if cargo_features.load_out_dirs_from_check { 163 if cargo_features.load_out_dirs_from_check {
162 out_dir_by_id = load_out_dirs(cargo_toml, cargo_features); 164 let resources = load_extern_resources(cargo_toml, cargo_features);
165 out_dir_by_id = resources.out_dirs;
166 proc_macro_dylib_paths = resources.proc_dylib_paths;
163 } 167 }
164 168
165 let mut pkg_by_id = FxHashMap::default(); 169 let mut pkg_by_id = FxHashMap::default();
@@ -183,6 +187,7 @@ impl CargoWorkspace {
183 dependencies: Vec::new(), 187 dependencies: Vec::new(),
184 features: Vec::new(), 188 features: Vec::new(),
185 out_dir: out_dir_by_id.get(&id).cloned(), 189 out_dir: out_dir_by_id.get(&id).cloned(),
190 proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(),
186 }); 191 });
187 let pkg_data = &mut packages[pkg]; 192 let pkg_data = &mut packages[pkg];
188 pkg_by_id.insert(id, pkg); 193 pkg_by_id.insert(id, pkg);
@@ -246,10 +251,13 @@ impl CargoWorkspace {
246 } 251 }
247} 252}
248 253
249pub fn load_out_dirs( 254#[derive(Debug, Clone, Default)]
250 cargo_toml: &Path, 255pub struct ExternResources {
251 cargo_features: &CargoFeatures, 256 out_dirs: FxHashMap<PackageId, PathBuf>,
252) -> FxHashMap<PackageId, PathBuf> { 257 proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
258}
259
260pub fn load_extern_resources(cargo_toml: &Path, cargo_features: &CargoFeatures) -> ExternResources {
253 let mut args: Vec<String> = vec![ 261 let mut args: Vec<String> = vec![
254 "check".to_string(), 262 "check".to_string(),
255 "--message-format=json".to_string(), 263 "--message-format=json".to_string(),
@@ -267,14 +275,21 @@ pub fn load_out_dirs(
267 args.extend(cargo_features.features.iter().cloned()); 275 args.extend(cargo_features.features.iter().cloned());
268 } 276 }
269 277
270 let mut acc = FxHashMap::default(); 278 let mut acc = ExternResources::default();
271 let res = run_cargo(&args, cargo_toml.parent(), &mut |message| { 279 let res = run_cargo(&args, cargo_toml.parent(), &mut |message| {
272 match message { 280 match message {
273 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { 281 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => {
274 acc.insert(package_id, out_dir); 282 acc.out_dirs.insert(package_id, out_dir);
275 } 283 }
276 284
277 Message::CompilerArtifact(_) => (), 285 Message::CompilerArtifact(message) => {
286 if message.target.kind.contains(&"proc-macro".to_string()) {
287 let package_id = message.package_id;
288 if let Some(filename) = message.filenames.get(0) {
289 acc.proc_dylib_paths.insert(package_id, filename.clone());
290 }
291 }
292 }
278 Message::CompilerMessage(_) => (), 293 Message::CompilerMessage(_) => (),
279 Message::Unknown => (), 294 Message::Unknown => (),
280 } 295 }
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs
index 336446e58..b030c8a6a 100644
--- a/crates/ra_project_model/src/json_project.rs
+++ b/crates/ra_project_model/src/json_project.rs
@@ -23,6 +23,7 @@ pub struct Crate {
23 pub(crate) atom_cfgs: FxHashSet<String>, 23 pub(crate) atom_cfgs: FxHashSet<String>,
24 pub(crate) key_value_cfgs: FxHashMap<String, String>, 24 pub(crate) key_value_cfgs: FxHashMap<String, String>,
25 pub(crate) out_dir: Option<PathBuf>, 25 pub(crate) out_dir: Option<PathBuf>,
26 pub(crate) proc_macro_dylib_path: Option<PathBuf>,
26} 27}
27 28
28#[derive(Clone, Copy, Debug, Deserialize)] 29#[derive(Clone, Copy, Debug, Deserialize)]
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index a3ef9acdc..444d3bb3f 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -23,6 +23,7 @@ pub use crate::{
23 json_project::JsonProject, 23 json_project::JsonProject,
24 sysroot::Sysroot, 24 sysroot::Sysroot,
25}; 25};
26pub use ra_proc_macro::ProcMacroClient;
26 27
27#[derive(Clone, PartialEq, Eq, Hash, Debug)] 28#[derive(Clone, PartialEq, Eq, Hash, Debug)]
28pub struct CargoTomlNotFoundError { 29pub struct CargoTomlNotFoundError {
@@ -173,6 +174,29 @@ impl ProjectWorkspace {
173 } 174 }
174 } 175 }
175 176
177 pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> {
178 match self {
179 ProjectWorkspace::Json { project } => {
180 let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len());
181 for krate in &project.crates {
182 if let Some(out_dir) = &krate.proc_macro_dylib_path {
183 proc_macro_dylib_paths.push(out_dir.to_path_buf());
184 }
185 }
186 proc_macro_dylib_paths
187 }
188 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => {
189 let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len());
190 for pkg in cargo.packages() {
191 if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path {
192 proc_macro_dylib_paths.push(dylib_path.to_path_buf());
193 }
194 }
195 proc_macro_dylib_paths
196 }
197 }
198 }
199
176 pub fn n_packages(&self) -> usize { 200 pub fn n_packages(&self) -> usize {
177 match self { 201 match self {
178 ProjectWorkspace::Json { project } => project.crates.len(), 202 ProjectWorkspace::Json { project } => project.crates.len(),
@@ -186,6 +210,7 @@ impl ProjectWorkspace {
186 &self, 210 &self,
187 default_cfg_options: &CfgOptions, 211 default_cfg_options: &CfgOptions,
188 extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, 212 extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>,
213 proc_macro_client: &ProcMacroClient,
189 load: &mut dyn FnMut(&Path) -> Option<FileId>, 214 load: &mut dyn FnMut(&Path) -> Option<FileId>,
190 ) -> CrateGraph { 215 ) -> CrateGraph {
191 let mut crate_graph = CrateGraph::default(); 216 let mut crate_graph = CrateGraph::default();
@@ -219,7 +244,10 @@ impl ProjectWorkspace {
219 extern_source.set_extern_path(&out_dir, extern_source_id); 244 extern_source.set_extern_path(&out_dir, extern_source_id);
220 } 245 }
221 } 246 }
222 247 let proc_macro = krate
248 .proc_macro_dylib_path
249 .clone()
250 .map(|it| proc_macro_client.by_dylib_path(&it));
223 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env 251 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
224 crates.insert( 252 crates.insert(
225 crate_id, 253 crate_id,
@@ -231,6 +259,7 @@ impl ProjectWorkspace {
231 cfg_options, 259 cfg_options,
232 env, 260 env,
233 extern_source, 261 extern_source,
262 proc_macro.unwrap_or_default(),
234 ), 263 ),
235 ); 264 );
236 } 265 }
@@ -270,6 +299,8 @@ impl ProjectWorkspace {
270 299
271 let env = Env::default(); 300 let env = Env::default();
272 let extern_source = ExternSource::default(); 301 let extern_source = ExternSource::default();
302 let proc_macro = vec![];
303
273 let crate_id = crate_graph.add_crate_root( 304 let crate_id = crate_graph.add_crate_root(
274 file_id, 305 file_id,
275 Edition::Edition2018, 306 Edition::Edition2018,
@@ -280,6 +311,7 @@ impl ProjectWorkspace {
280 cfg_options, 311 cfg_options,
281 env, 312 env,
282 extern_source, 313 extern_source,
314 proc_macro,
283 ); 315 );
284 sysroot_crates.insert(krate, crate_id); 316 sysroot_crates.insert(krate, crate_id);
285 } 317 }
@@ -327,6 +359,12 @@ impl ProjectWorkspace {
327 extern_source.set_extern_path(&out_dir, extern_source_id); 359 extern_source.set_extern_path(&out_dir, extern_source_id);
328 } 360 }
329 } 361 }
362 let proc_macro = cargo[pkg]
363 .proc_macro_dylib_path
364 .as_ref()
365 .map(|it| proc_macro_client.by_dylib_path(&it))
366 .unwrap_or_default();
367
330 let crate_id = crate_graph.add_crate_root( 368 let crate_id = crate_graph.add_crate_root(
331 file_id, 369 file_id,
332 edition, 370 edition,
@@ -334,6 +372,7 @@ impl ProjectWorkspace {
334 cfg_options, 372 cfg_options,
335 env, 373 env,
336 extern_source, 374 extern_source,
375 proc_macro.clone(),
337 ); 376 );
338 if cargo[tgt].kind == TargetKind::Lib { 377 if cargo[tgt].kind == TargetKind::Lib {
339 lib_tgt = Some((crate_id, cargo[tgt].name.clone())); 378 lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 54e2fa1a7..832f04226 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -7,7 +7,9 @@ use anyhow::Result;
7use crossbeam_channel::{unbounded, Receiver}; 7use crossbeam_channel::{unbounded, Receiver};
8use ra_db::{ExternSourceId, FileId, SourceRootId}; 8use ra_db::{ExternSourceId, FileId, SourceRootId};
9use ra_ide::{AnalysisChange, AnalysisHost}; 9use ra_ide::{AnalysisChange, AnalysisHost};
10use ra_project_model::{get_rustc_cfg_options, CargoFeatures, PackageRoot, ProjectWorkspace}; 10use ra_project_model::{
11 get_rustc_cfg_options, CargoFeatures, PackageRoot, ProcMacroClient, ProjectWorkspace,
12};
11use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; 13use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
12use rustc_hash::{FxHashMap, FxHashSet}; 14use rustc_hash::{FxHashMap, FxHashSet};
13 15
@@ -67,7 +69,9 @@ pub(crate) fn load_cargo(
67 (source_root_id, project_root) 69 (source_root_id, project_root)
68 }) 70 })
69 .collect::<FxHashMap<_, _>>(); 71 .collect::<FxHashMap<_, _>>();
70 let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs); 72
73 let proc_macro_client = ProcMacroClient::dummy();
74 let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client);
71 Ok((host, source_roots)) 75 Ok((host, source_roots))
72} 76}
73 77
@@ -77,6 +81,7 @@ pub(crate) fn load(
77 vfs: &mut Vfs, 81 vfs: &mut Vfs,
78 receiver: Receiver<VfsTask>, 82 receiver: Receiver<VfsTask>,
79 extern_dirs: FxHashSet<PathBuf>, 83 extern_dirs: FxHashSet<PathBuf>,
84 proc_macro_client: &ProcMacroClient,
80) -> AnalysisHost { 85) -> AnalysisHost {
81 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); 86 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
82 let mut host = AnalysisHost::new(lru_cap); 87 let mut host = AnalysisHost::new(lru_cap);
@@ -143,12 +148,16 @@ pub(crate) fn load(
143 opts 148 opts
144 }; 149 };
145 150
146 let crate_graph = 151 let crate_graph = ws.to_crate_graph(
147 ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut |path: &Path| { 152 &default_cfg_options,
153 &extern_source_roots,
154 proc_macro_client,
155 &mut |path: &Path| {
148 let vfs_file = vfs.load(path); 156 let vfs_file = vfs.load(path);
149 log::debug!("vfs file {:?} -> {:?}", path, vfs_file); 157 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
150 vfs_file.map(vfs_file_to_id) 158 vfs_file.map(vfs_file_to_id)
151 }); 159 },
160 );
152 log::debug!("crate graph: {:?}", crate_graph); 161 log::debug!("crate graph: {:?}", crate_graph);
153 analysis_change.set_crate_graph(crate_graph); 162 analysis_change.set_crate_graph(crate_graph);
154 163
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index c4244fee2..de85bb017 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -16,7 +16,7 @@ use ra_ide::{
16 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData, 16 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData,
17 SourceRootId, 17 SourceRootId,
18}; 18};
19use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; 19use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace};
20use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; 20use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
21use relative_path::RelativePathBuf; 21use relative_path::RelativePathBuf;
22 22
@@ -150,9 +150,19 @@ impl WorldState {
150 vfs_file.map(|f| FileId(f.0)) 150 vfs_file.map(|f| FileId(f.0))
151 }; 151 };
152 152
153 let proc_macro_client =
154 ProcMacroClient::extern_process(std::path::Path::new("ra_proc_macro_srv"));
155
153 workspaces 156 workspaces
154 .iter() 157 .iter()
155 .map(|ws| ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut load)) 158 .map(|ws| {
159 ws.to_crate_graph(
160 &default_cfg_options,
161 &extern_source_roots,
162 &proc_macro_client,
163 &mut load,
164 )
165 })
156 .for_each(|graph| { 166 .for_each(|graph| {
157 crate_graph.extend(graph); 167 crate_graph.extend(graph);
158 }); 168 });