diff options
author | Edwin Cheng <[email protected]> | 2020-03-18 12:56:46 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2020-03-25 19:29:45 +0000 |
commit | d0b6ed4441469acfb6bc6555d78abf12637b6cf4 (patch) | |
tree | a4b39b33590c472a68fd76ceae96732e9cb54ebb /crates | |
parent | a617f24eae6c02f087759312e9aa08507fbecdf0 (diff) |
Add ProcMacroClient
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_db/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_db/src/fixture.rs | 4 | ||||
-rw-r--r-- | crates/ra_db/src/input.rs | 15 | ||||
-rw-r--r-- | crates/ra_db/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/proc_macro.rs | 30 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/mock_analysis.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/parent_module.rs | 1 | ||||
-rw-r--r-- | crates/ra_proc_macro/src/lib.rs | 81 | ||||
-rw-r--r-- | crates/ra_project_model/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 31 | ||||
-rw-r--r-- | crates/ra_project_model/src/json_project.rs | 1 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 41 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 19 | ||||
-rw-r--r-- | crates/rust-analyzer/src/world.rs | 14 |
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" | |||
15 | ra_syntax = { path = "../ra_syntax" } | 15 | ra_syntax = { path = "../ra_syntax" } |
16 | ra_cfg = { path = "../ra_cfg" } | 16 | ra_cfg = { path = "../ra_cfg" } |
17 | ra_prof = { path = "../ra_prof" } | 17 | ra_prof = { path = "../ra_prof" } |
18 | ra_proc_macro = { path = "../ra_proc_macro" } | ||
18 | test_utils = { path = "../test_utils" } | 19 | test_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 | ||
20 | use crate::{RelativePath, RelativePathBuf}; | 20 | use crate::{RelativePath, RelativePathBuf}; |
21 | use fmt::Display; | 21 | use fmt::Display; |
22 | use 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)] | ||
120 | pub struct ProcMacroId(pub usize); | ||
121 | |||
118 | #[derive(Debug, Clone, PartialEq, Eq)] | 122 | #[derive(Debug, Clone, PartialEq, Eq)] |
119 | pub struct CrateData { | 123 | pub 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 | }; |
18 | pub use ra_proc_macro::ProcMacro; | ||
18 | pub use relative_path::{RelativePath, RelativePathBuf}; | 19 | pub use relative_path::{RelativePath, RelativePathBuf}; |
19 | pub use salsa; | 20 | pub 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 | }; |
13 | use ra_cfg::CfgOptions; | 13 | use ra_cfg::CfgOptions; |
14 | use ra_db::{CrateId, FileId}; | 14 | use ra_db::{CrateId, FileId, ProcMacroId}; |
15 | use ra_syntax::ast; | 15 | use ra_syntax::{ast, SmolStr}; |
16 | use rustc_hash::FxHashMap; | 16 | use rustc_hash::FxHashMap; |
17 | use test_utils::tested_by; | 17 | use 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 | ||
3 | use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc}; | 3 | use crate::{db::AstDatabase, LazyMacroId}; |
4 | use ra_db::CrateId; | 4 | use ra_db::{CrateId, ProcMacroId}; |
5 | 5 | ||
6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] | 6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
7 | pub struct ProcMacroExpander { | 7 | pub struct ProcMacroExpander { |
8 | krate: CrateId, | 8 | krate: CrateId, |
9 | proc_macro_id: ProcMacroId, | ||
9 | } | 10 | } |
10 | 11 | ||
11 | impl ProcMacroExpander { | 12 | impl 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 |
2 | mod 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 | |||
8 | use ra_mbe::ExpandError; | ||
9 | use ra_tt::Subtree; | ||
10 | use std::{ | ||
11 | path::{Path, PathBuf}, | ||
12 | sync::Arc, | ||
13 | }; | ||
14 | |||
15 | trait 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)] | ||
20 | pub struct ProcMacroProcessExpander { | ||
21 | process_path: PathBuf, | ||
22 | } | ||
23 | |||
24 | impl 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)] | ||
36 | pub struct ProcMacro { | ||
37 | expander: Arc<Box<dyn ProcMacroExpander>>, | ||
38 | name: String, | ||
39 | } | ||
40 | |||
41 | impl Eq for ProcMacro {} | ||
42 | impl 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 | |||
48 | impl 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)] | ||
59 | pub enum ProcMacroClient { | ||
60 | Process { expander: Arc<ProcMacroProcessExpander> }, | ||
61 | Dummy, | ||
62 | } | ||
63 | |||
64 | impl 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" } | |||
17 | ra_db = { path = "../ra_db" } | 17 | ra_db = { path = "../ra_db" } |
18 | ra_cfg = { path = "../ra_cfg" } | 18 | ra_cfg = { path = "../ra_cfg" } |
19 | ra_cargo_watch = { path = "../ra_cargo_watch" } | 19 | ra_cargo_watch = { path = "../ra_cargo_watch" } |
20 | ra_proc_macro = { path = "../ra_proc_macro" } | ||
20 | 21 | ||
21 | serde = { version = "1.0.104", features = ["derive"] } | 22 | serde = { version = "1.0.104", features = ["derive"] } |
22 | serde_json = "1.0.48" | 23 | serde_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 | ||
249 | pub fn load_out_dirs( | 254 | #[derive(Debug, Clone, Default)] |
250 | cargo_toml: &Path, | 255 | pub 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 | |||
260 | pub 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 | }; |
26 | pub use ra_proc_macro::ProcMacroClient; | ||
26 | 27 | ||
27 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 28 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
28 | pub struct CargoTomlNotFoundError { | 29 | pub 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; | |||
7 | use crossbeam_channel::{unbounded, Receiver}; | 7 | use crossbeam_channel::{unbounded, Receiver}; |
8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; | 8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; |
9 | use ra_ide::{AnalysisChange, AnalysisHost}; | 9 | use ra_ide::{AnalysisChange, AnalysisHost}; |
10 | use ra_project_model::{get_rustc_cfg_options, CargoFeatures, PackageRoot, ProjectWorkspace}; | 10 | use ra_project_model::{ |
11 | get_rustc_cfg_options, CargoFeatures, PackageRoot, ProcMacroClient, ProjectWorkspace, | ||
12 | }; | ||
11 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; | 13 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; |
12 | use rustc_hash::{FxHashMap, FxHashSet}; | 14 | use 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 | }; |
19 | use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; | 19 | use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace}; |
20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; | 20 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; |
21 | use relative_path::RelativePathBuf; | 21 | use 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 | }); |