aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_proc_macro/src/lib.rs17
-rw-r--r--crates/ra_proc_macro/src/msg.rs37
-rw-r--r--crates/ra_proc_macro/src/process.rs31
-rw-r--r--crates/ra_proc_macro/src/rpc.rs18
-rw-r--r--crates/ra_proc_macro_srv/src/cli.rs58
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs103
-rw-r--r--crates/ra_proc_macro_srv/src/lib.rs36
-rw-r--r--crates/ra_proc_macro_srv/src/rustc_server.rs2
-rw-r--r--crates/ra_proc_macro_srv/src/tests/utils.rs2
-rw-r--r--crates/rust-analyzer/src/bin/main.rs4
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs2
-rw-r--r--crates/rust-analyzer/src/world.rs23
12 files changed, 142 insertions, 191 deletions
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs
index b200fd126..004943b9e 100644
--- a/crates/ra_proc_macro/src/lib.rs
+++ b/crates/ra_proc_macro/src/lib.rs
@@ -2,7 +2,7 @@
2//! 2//!
3//! We separate proc-macro expanding logic to an extern program to allow 3//! We separate proc-macro expanding logic to an extern program to allow
4//! different implementations (e.g. wasm or dylib loading). And this crate 4//! different implementations (e.g. wasm or dylib loading). And this crate
5//! is used to provide basic infrastructure for communication between two 5//! is used to provide basic infrastructure for communication between two
6//! processes: Client (RA itself), Server (the external program) 6//! processes: Client (RA itself), Server (the external program)
7 7
8mod rpc; 8mod rpc;
@@ -13,6 +13,7 @@ use process::{ProcMacroProcessSrv, ProcMacroProcessThread};
13use ra_tt::{SmolStr, Subtree}; 13use ra_tt::{SmolStr, Subtree};
14use std::{ 14use std::{
15 ffi::OsStr, 15 ffi::OsStr,
16 io,
16 path::{Path, PathBuf}, 17 path::{Path, PathBuf},
17 sync::Arc, 18 sync::Arc,
18}; 19};
@@ -57,14 +58,10 @@ pub struct ProcMacroClient {
57} 58}
58 59
59impl ProcMacroClient { 60impl ProcMacroClient {
60 pub fn extern_process<I, S>( 61 pub fn extern_process(
61 process_path: &Path, 62 process_path: PathBuf,
62 args: I, 63 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
63 ) -> Result<ProcMacroClient, std::io::Error> 64 ) -> io::Result<ProcMacroClient> {
64 where
65 I: IntoIterator<Item = S>,
66 S: AsRef<OsStr>,
67 {
68 let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?; 65 let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?;
69 Ok(ProcMacroClient { 66 Ok(ProcMacroClient {
70 kind: ProcMacroClientKind::Process { process: Arc::new(process), thread }, 67 kind: ProcMacroClientKind::Process { process: Arc::new(process), thread },
@@ -84,7 +81,7 @@ impl ProcMacroClient {
84 ProcMacroClientKind::Process { process, .. } => { 81 ProcMacroClientKind::Process { process, .. } => {
85 let macros = match process.find_proc_macros(dylib_path) { 82 let macros = match process.find_proc_macros(dylib_path) {
86 Err(err) => { 83 Err(err) => {
87 eprintln!("Fail to find proc macro. Error: {:#?}", err); 84 eprintln!("Failed to find proc macros. Error: {:#?}", err);
88 return vec![]; 85 return vec![];
89 } 86 }
90 Ok(macros) => macros, 87 Ok(macros) => macros,
diff --git a/crates/ra_proc_macro/src/msg.rs b/crates/ra_proc_macro/src/msg.rs
index aa95bcc8f..95d9b8804 100644
--- a/crates/ra_proc_macro/src/msg.rs
+++ b/crates/ra_proc_macro/src/msg.rs
@@ -1,4 +1,4 @@
1//! Defines messages for cross-process message based on `ndjson` wire protocol 1//! Defines messages for cross-process message passing based on `ndjson` wire protocol
2 2
3use std::{ 3use std::{
4 convert::TryFrom, 4 convert::TryFrom,
@@ -31,7 +31,7 @@ macro_rules! impl_try_from_response {
31 fn try_from(value: Response) -> Result<Self, Self::Error> { 31 fn try_from(value: Response) -> Result<Self, Self::Error> {
32 match value { 32 match value {
33 Response::$tag(res) => Ok(res), 33 Response::$tag(res) => Ok(res),
34 _ => Err("Fail to convert from response"), 34 _ => Err(concat!("Failed to convert response to ", stringify!($tag))),
35 } 35 }
36 } 36 }
37 } 37 }
@@ -53,18 +53,16 @@ pub enum ErrorCode {
53 ExpansionError, 53 ExpansionError,
54} 54}
55 55
56pub trait Message: Sized + Serialize + DeserializeOwned { 56pub trait Message: Serialize + DeserializeOwned {
57 fn read(r: &mut impl BufRead) -> io::Result<Option<Self>> { 57 fn read(inp: &mut impl BufRead) -> io::Result<Option<Self>> {
58 let text = match read_json(r)? { 58 Ok(match read_json(inp)? {
59 None => return Ok(None), 59 None => None,
60 Some(text) => text, 60 Some(text) => Some(serde_json::from_str(&text)?),
61 }; 61 })
62 let msg = serde_json::from_str(&text)?;
63 Ok(Some(msg))
64 } 62 }
65 fn write(self, w: &mut impl Write) -> io::Result<()> { 63 fn write(self, out: &mut impl Write) -> io::Result<()> {
66 let text = serde_json::to_string(&self)?; 64 let text = serde_json::to_string(&self)?;
67 write_json(w, &text) 65 write_json(out, &text)
68 } 66 }
69} 67}
70 68
@@ -73,15 +71,12 @@ impl Message for Response {}
73 71
74fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { 72fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> {
75 let mut buf = String::new(); 73 let mut buf = String::new();
76 if inp.read_line(&mut buf)? == 0 { 74 inp.read_line(&mut buf)?;
77 return Ok(None); 75 buf.pop(); // Remove traling '\n'
78 } 76 Ok(match buf.len() {
79 // Remove ending '\n' 77 0 => None,
80 let buf = &buf[..buf.len() - 1]; 78 _ => Some(buf),
81 if buf.is_empty() { 79 })
82 return Ok(None);
83 }
84 Ok(Some(buf.to_string()))
85} 80}
86 81
87fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { 82fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> {
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs
index f851570bc..e24944af4 100644
--- a/crates/ra_proc_macro/src/process.rs
+++ b/crates/ra_proc_macro/src/process.rs
@@ -45,24 +45,23 @@ impl Drop for Process {
45} 45}
46 46
47impl Process { 47impl Process {
48 fn run<I, S>(process_path: &Path, args: I) -> Result<Process, io::Error> 48 fn run(
49 where 49 process_path: PathBuf,
50 I: IntoIterator<Item = S>, 50 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
51 S: AsRef<OsStr>, 51 ) -> io::Result<Process> {
52 { 52 let child = Command::new(&process_path)
53 let child = Command::new(process_path.clone())
54 .args(args) 53 .args(args)
55 .stdin(Stdio::piped()) 54 .stdin(Stdio::piped())
56 .stdout(Stdio::piped()) 55 .stdout(Stdio::piped())
57 .stderr(Stdio::null()) 56 .stderr(Stdio::null())
58 .spawn()?; 57 .spawn()?;
59 58
60 Ok(Process { path: process_path.into(), child }) 59 Ok(Process { path: process_path, child })
61 } 60 }
62 61
63 fn restart(&mut self) -> Result<(), io::Error> { 62 fn restart(&mut self) -> io::Result<()> {
64 let _ = self.child.kill(); 63 let _ = self.child.kill();
65 self.child = Command::new(self.path.clone()) 64 self.child = Command::new(&self.path)
66 .stdin(Stdio::piped()) 65 .stdin(Stdio::piped())
67 .stdout(Stdio::piped()) 66 .stdout(Stdio::piped())
68 .stderr(Stdio::null()) 67 .stderr(Stdio::null())
@@ -80,14 +79,10 @@ impl Process {
80} 79}
81 80
82impl ProcMacroProcessSrv { 81impl ProcMacroProcessSrv {
83 pub fn run<I, S>( 82 pub fn run(
84 process_path: &Path, 83 process_path: PathBuf,
85 args: I, 84 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
86 ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> 85 ) -> io::Result<(ProcMacroProcessThread, ProcMacroProcessSrv)> {
87 where
88 I: IntoIterator<Item = S>,
89 S: AsRef<OsStr>,
90 {
91 let process = Process::run(process_path, args)?; 86 let process = Process::run(process_path, args)?;
92 87
93 let (task_tx, task_rx) = bounded(0); 88 let (task_tx, task_rx) = bounded(0);
@@ -201,7 +196,7 @@ fn send_request(
201 mut writer: &mut impl Write, 196 mut writer: &mut impl Write,
202 mut reader: &mut impl BufRead, 197 mut reader: &mut impl BufRead,
203 req: Request, 198 req: Request,
204) -> Result<Option<Response>, io::Error> { 199) -> io::Result<Option<Response>> {
205 req.write(&mut writer)?; 200 req.write(&mut writer)?;
206 Ok(Response::read(&mut reader)?) 201 Ok(Response::read(&mut reader)?)
207} 202}
diff --git a/crates/ra_proc_macro/src/rpc.rs b/crates/ra_proc_macro/src/rpc.rs
index 66b3f55db..4ce485926 100644
--- a/crates/ra_proc_macro/src/rpc.rs
+++ b/crates/ra_proc_macro/src/rpc.rs
@@ -1,9 +1,9 @@
1//! Data struture serialization related stuffs for RPC 1//! Data struture serialization related stuff for RPC
2//! 2//!
3//! Define all necessary rpc serialization data structure, 3//! Defines all necessary rpc serialization data structures,
4//! which include ra_tt related data and some task messages. 4//! which includes `ra_tt` related data and some task messages.
5//! Although adding Serialize and Deserialize trait to ra_tt directly seem to be much easier, 5//! Although adding `Serialize` and `Deserialize` traits to `ra_tt` directly seems
6//! we deliberately duplicate the ra_tt struct with #[serde(with = "XXDef")] 6//! to be much easier, we deliberately duplicate `ra_tt` structs with `#[serde(with = "XXDef")]`
7//! for separation of code responsibility. 7//! for separation of code responsibility.
8 8
9use ra_tt::{ 9use ra_tt::{
@@ -34,15 +34,15 @@ pub struct ListMacrosResult {
34pub struct ExpansionTask { 34pub struct ExpansionTask {
35 /// Argument of macro call. 35 /// Argument of macro call.
36 /// 36 ///
37 /// In custom derive that would be a struct or enum; in attribute-like macro - underlying 37 /// In custom derive this will be a struct or enum; in attribute-like macro - underlying
38 /// item; in function-like macro - the macro body. 38 /// item; in function-like macro - the macro body.
39 #[serde(with = "SubtreeDef")] 39 #[serde(with = "SubtreeDef")]
40 pub macro_body: Subtree, 40 pub macro_body: Subtree,
41 41
42 /// Names of macros to expand. 42 /// Name of macro to expand.
43 /// 43 ///
44 /// In custom derive those are names of derived traits (`Serialize`, `Getters`, etc.). In 44 /// In custom derive this is the name of the derived trait (`Serialize`, `Getters`, etc.).
45 /// attribute-like and functiona-like macros - single name of macro itself (`show_streams`). 45 /// In attribute-like and function-like macros - single name of macro itself (`show_streams`).
46 pub macro_name: String, 46 pub macro_name: String,
47 47
48 /// Possible attributes for the attribute-like macros. 48 /// Possible attributes for the attribute-like macros.
diff --git a/crates/ra_proc_macro_srv/src/cli.rs b/crates/ra_proc_macro_srv/src/cli.rs
index c771f2b38..5f1f3ba3c 100644
--- a/crates/ra_proc_macro_srv/src/cli.rs
+++ b/crates/ra_proc_macro_srv/src/cli.rs
@@ -2,55 +2,43 @@
2 2
3use crate::{expand_task, list_macros}; 3use crate::{expand_task, list_macros};
4use ra_proc_macro::msg::{self, Message}; 4use ra_proc_macro::msg::{self, Message};
5
6use std::io; 5use std::io;
7 6
8fn read_request() -> Result<Option<msg::Request>, io::Error> {
9 let stdin = io::stdin();
10 let mut stdin = stdin.lock();
11 msg::Request::read(&mut stdin)
12}
13
14fn write_response(res: Result<msg::Response, String>) -> Result<(), io::Error> {
15 let msg: msg::Response = match res {
16 Ok(res) => res,
17 Err(err) => msg::Response::Error(msg::ResponseError {
18 code: msg::ErrorCode::ExpansionError,
19 message: err,
20 }),
21 };
22
23 let stdout = io::stdout();
24 let mut stdout = stdout.lock();
25 msg.write(&mut stdout)
26}
27
28pub fn run() { 7pub fn run() {
29 loop { 8 loop {
30 let req = match read_request() { 9 let req = match read_request() {
31 Err(err) => { 10 Err(err) => {
32 eprintln!("Read message error on ra_proc_macro_srv: {}", err.to_string()); 11 eprintln!("Read message error on ra_proc_macro_srv: {}", err);
33 continue; 12 continue;
34 } 13 }
35 Ok(None) => continue, 14 Ok(None) => continue,
36 Ok(Some(req)) => req, 15 Ok(Some(req)) => req,
37 }; 16 };
38 17
39 match req { 18 let res = match req {
40 msg::Request::ListMacro(task) => { 19 msg::Request::ListMacro(task) => Ok(msg::Response::ListMacro(list_macros(&task))),
41 if let Err(err) =
42 write_response(list_macros(&task).map(|it| msg::Response::ListMacro(it)))
43 {
44 eprintln!("Write message error on list macro: {}", err);
45 }
46 }
47 msg::Request::ExpansionMacro(task) => { 20 msg::Request::ExpansionMacro(task) => {
48 if let Err(err) = 21 expand_task(&task).map(msg::Response::ExpansionMacro)
49 write_response(expand_task(&task).map(|it| msg::Response::ExpansionMacro(it)))
50 {
51 eprintln!("Write message error on expansion macro: {}", err);
52 }
53 } 22 }
23 };
24
25 let msg = res.unwrap_or_else(|err| {
26 msg::Response::Error(msg::ResponseError {
27 code: msg::ErrorCode::ExpansionError,
28 message: err,
29 })
30 });
31
32 if let Err(err) = write_response(msg) {
33 eprintln!("Write message error: {}", err);
54 } 34 }
55 } 35 }
56} 36}
37
38fn read_request() -> io::Result<Option<msg::Request>> {
39 msg::Request::read(&mut io::stdin().lock())
40}
41
42fn write_response(msg: msg::Response) -> io::Result<()> {
43 msg.write(&mut io::stdout().lock())
44}
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs
index 16bd7466e..d202eb0fd 100644
--- a/crates/ra_proc_macro_srv/src/dylib.rs
+++ b/crates/ra_proc_macro_srv/src/dylib.rs
@@ -9,43 +9,37 @@ use libloading::Library;
9use memmap::Mmap; 9use memmap::Mmap;
10use ra_proc_macro::ProcMacroKind; 10use ra_proc_macro::ProcMacroKind;
11 11
12use std::io::Error as IoError; 12use std::io;
13use std::io::ErrorKind as IoErrorKind;
14 13
15const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; 14const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
16 15
17fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError { 16fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
18 IoError::new(IoErrorKind::InvalidData, e) 17 io::Error::new(io::ErrorKind::InvalidData, e)
19} 18}
20 19
21fn is_derive_registrar_symbol(symbol: &str) -> bool { 20fn is_derive_registrar_symbol(symbol: &str) -> bool {
22 symbol.contains(NEW_REGISTRAR_SYMBOL) 21 symbol.contains(NEW_REGISTRAR_SYMBOL)
23} 22}
24 23
25fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { 24fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
26 let file = File::open(file)?; 25 let file = File::open(file)?;
27 let buffer = unsafe { Mmap::map(&file)? }; 26 let buffer = unsafe { Mmap::map(&file)? };
28 let object = Object::parse(&buffer).map_err(invalid_data_err)?; 27 let object = Object::parse(&buffer).map_err(invalid_data_err)?;
29 28
30 match object { 29 let name = match object {
31 Object::Elf(elf) => { 30 Object::Elf(elf) => {
32 let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; 31 let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?;
33 let name = 32 symbols.into_iter().find(|s| is_derive_registrar_symbol(s)).map(&str::to_owned)
34 symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| s.to_string());
35 Ok(name)
36 }
37 Object::PE(pe) => {
38 let name = pe
39 .exports
40 .iter()
41 .flat_map(|s| s.name)
42 .find(|s| is_derive_registrar_symbol(s))
43 .map(|s| s.to_string());
44 Ok(name)
45 } 33 }
34 Object::PE(pe) => pe
35 .exports
36 .iter()
37 .flat_map(|s| s.name)
38 .find(|s| is_derive_registrar_symbol(s))
39 .map(&str::to_owned),
46 Object::Mach(Mach::Binary(binary)) => { 40 Object::Mach(Mach::Binary(binary)) => {
47 let exports = binary.exports().map_err(invalid_data_err)?; 41 let exports = binary.exports().map_err(invalid_data_err)?;
48 let name = exports 42 exports
49 .iter() 43 .iter()
50 .map(|s| { 44 .map(|s| {
51 // In macos doc: 45 // In macos doc:
@@ -59,11 +53,11 @@ fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> {
59 } 53 }
60 }) 54 })
61 .find(|s| is_derive_registrar_symbol(s)) 55 .find(|s| is_derive_registrar_symbol(s))
62 .map(|s| s.to_string()); 56 .map(&str::to_owned)
63 Ok(name)
64 } 57 }
65 _ => Ok(None), 58 _ => return Ok(None),
66 } 59 };
60 return Ok(name);
67} 61}
68 62
69/// Loads dynamic library in platform dependent manner. 63/// Loads dynamic library in platform dependent manner.
@@ -93,15 +87,16 @@ fn load_library(file: &Path) -> Result<Library, libloading::Error> {
93} 87}
94 88
95struct ProcMacroLibraryLibloading { 89struct ProcMacroLibraryLibloading {
96 // Hold the dylib to prevent it for unloadeding 90 // Hold the dylib to prevent it from unloading
97 _lib: Library, 91 _lib: Library,
98 exported_macros: Vec<bridge::client::ProcMacro>, 92 exported_macros: Vec<bridge::client::ProcMacro>,
99} 93}
100 94
101impl ProcMacroLibraryLibloading { 95impl ProcMacroLibraryLibloading {
102 fn open(file: &Path) -> Result<Self, IoError> { 96 fn open(file: &Path) -> io::Result<Self> {
103 let symbol_name = find_registrar_symbol(file)? 97 let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
104 .ok_or(invalid_data_err(format!("Cannot find registrar symbol in file {:?}", file)))?; 98 invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
99 })?;
105 100
106 let lib = load_library(file).map_err(invalid_data_err)?; 101 let lib = load_library(file).map_err(invalid_data_err)?;
107 let exported_macros = { 102 let exported_macros = {
@@ -121,18 +116,16 @@ pub struct Expander {
121} 116}
122 117
123impl Expander { 118impl Expander {
124 pub fn new<P: AsRef<Path>>(lib: &P) -> Result<Expander, String> { 119 pub fn new(lib: &Path) -> Result<Expander, String> {
125 let mut libs = vec![]; 120 // Some libraries for dynamic loading require canonicalized path even when it is
126 /* Some libraries for dynamic loading require canonicalized path (even when it is 121 // already absolute
127 already absolute 122 let lib = lib
128 */ 123 .canonicalize()
129 let lib = 124 .unwrap_or_else(|err| panic!("Cannot canonicalize {}: {:?}", lib.display(), err));
130 lib.as_ref().canonicalize().expect(&format!("Cannot canonicalize {:?}", lib.as_ref()));
131 125
132 let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?; 126 let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?;
133 libs.push(library);
134 127
135 Ok(Expander { libs }) 128 Ok(Expander { libs: vec![library] })
136 } 129 }
137 130
138 pub fn expand( 131 pub fn expand(
@@ -176,7 +169,6 @@ impl Expander {
176 parsed_attributes, 169 parsed_attributes,
177 parsed_body, 170 parsed_body,
178 ); 171 );
179
180 return res.map(|it| it.subtree); 172 return res.map(|it| it.subtree);
181 } 173 }
182 _ => continue, 174 _ => continue,
@@ -187,26 +179,21 @@ impl Expander {
187 Err(bridge::PanicMessage::String("Nothing to expand".to_string())) 179 Err(bridge::PanicMessage::String("Nothing to expand".to_string()))
188 } 180 }
189 181
190 pub fn list_macros(&self) -> Result<Vec<(String, ProcMacroKind)>, bridge::PanicMessage> { 182 pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
191 let mut result = vec![]; 183 self.libs
192 184 .iter()
193 for lib in &self.libs { 185 .flat_map(|it| &it.exported_macros)
194 for proc_macro in &lib.exported_macros { 186 .map(|proc_macro| match proc_macro {
195 let res = match proc_macro { 187 bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
196 bridge::client::ProcMacro::CustomDerive { trait_name, .. } => { 188 (trait_name.to_string(), ProcMacroKind::CustomDerive)
197 (trait_name.to_string(), ProcMacroKind::CustomDerive) 189 }
198 } 190 bridge::client::ProcMacro::Bang { name, .. } => {
199 bridge::client::ProcMacro::Bang { name, .. } => { 191 (name.to_string(), ProcMacroKind::FuncLike)
200 (name.to_string(), ProcMacroKind::FuncLike) 192 }
201 } 193 bridge::client::ProcMacro::Attr { name, .. } => {
202 bridge::client::ProcMacro::Attr { name, .. } => { 194 (name.to_string(), ProcMacroKind::Attr)
203 (name.to_string(), ProcMacroKind::Attr) 195 }
204 } 196 })
205 }; 197 .collect()
206 result.push(res);
207 }
208 }
209
210 Ok(result)
211 } 198 }
212} 199}
diff --git a/crates/ra_proc_macro_srv/src/lib.rs b/crates/ra_proc_macro_srv/src/lib.rs
index c62b0ed89..3aca859db 100644
--- a/crates/ra_proc_macro_srv/src/lib.rs
+++ b/crates/ra_proc_macro_srv/src/lib.rs
@@ -3,10 +3,10 @@
3//! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code. 3//! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code.
4//! The general idea here is based on https://github.com/fedochet/rust-proc-macro-expander. 4//! The general idea here is based on https://github.com/fedochet/rust-proc-macro-expander.
5//! 5//!
6//! But we change some several design for fitting RA needs: 6//! But we adapt it to better fit RA needs:
7//! 7//!
8//! * We use `ra_tt` for proc-macro `TokenStream` server, it is easy to manipute and interact with 8//! * We use `ra_tt` for proc-macro `TokenStream` server, it is easier to manipulate and interact with
9//! RA then proc-macro2 token stream. 9//! RA than `proc-macro2` token stream.
10//! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable` 10//! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable`
11//! rustc rather than `unstable`. (Although in gerenal ABI compatibility is still an issue) 11//! rustc rather than `unstable`. (Although in gerenal ABI compatibility is still an issue)
12 12
@@ -21,36 +21,28 @@ mod dylib;
21 21
22use proc_macro::bridge::client::TokenStream; 22use proc_macro::bridge::client::TokenStream;
23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; 23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
24use std::path::Path;
24 25
25pub(crate) fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> { 26pub(crate) fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> {
26 let expander = dylib::Expander::new(&task.lib) 27 let expander = create_expander(&task.lib);
27 .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib));
28 28
29 match expander.expand(&task.macro_name, &task.macro_body, task.attributes.as_ref()) { 29 match expander.expand(&task.macro_name, &task.macro_body, task.attributes.as_ref()) {
30 Ok(expansion) => Ok(ExpansionResult { expansion }), 30 Ok(expansion) => Ok(ExpansionResult { expansion }),
31 Err(msg) => { 31 Err(msg) => {
32 let reason = format!( 32 Err(format!("Cannot perform expansion for {}: error {:?}", &task.macro_name, msg))
33 "Cannot perform expansion for {}: error {:?}!",
34 &task.macro_name,
35 msg.as_str()
36 );
37 Err(reason)
38 } 33 }
39 } 34 }
40} 35}
41 36
42pub(crate) fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> { 37pub(crate) fn list_macros(task: &ListMacrosTask) -> ListMacrosResult {
43 let expander = dylib::Expander::new(&task.lib) 38 let expander = create_expander(&task.lib);
44 .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib));
45 39
46 match expander.list_macros() { 40 ListMacrosResult { macros: expander.list_macros() }
47 Ok(macros) => Ok(ListMacrosResult { macros }), 41}
48 Err(msg) => { 42
49 let reason = 43fn create_expander(lib: &Path) -> dylib::Expander {
50 format!("Cannot perform expansion for {:?}: error {:?}!", &task.lib, msg.as_str()); 44 dylib::Expander::new(lib)
51 Err(reason) 45 .unwrap_or_else(|err| panic!("Cannot create expander for {}: {:?}", lib.display(), err))
52 }
53 }
54} 46}
55 47
56pub mod cli; 48pub mod cli;
diff --git a/crates/ra_proc_macro_srv/src/rustc_server.rs b/crates/ra_proc_macro_srv/src/rustc_server.rs
index 9fcfdc450..f481d70b2 100644
--- a/crates/ra_proc_macro_srv/src/rustc_server.rs
+++ b/crates/ra_proc_macro_srv/src/rustc_server.rs
@@ -6,7 +6,7 @@
6//! The original idea from fedochet is using proc-macro2 as backend, 6//! The original idea from fedochet is using proc-macro2 as backend,
7//! we use ra_tt instead for better intergation with RA. 7//! we use ra_tt instead for better intergation with RA.
8//! 8//!
9//! FIXME: No span and source file informatin is implemented yet 9//! FIXME: No span and source file information is implemented yet
10 10
11use crate::proc_macro::bridge::{self, server}; 11use crate::proc_macro::bridge::{self, server};
12use ra_tt as tt; 12use ra_tt as tt;
diff --git a/crates/ra_proc_macro_srv/src/tests/utils.rs b/crates/ra_proc_macro_srv/src/tests/utils.rs
index 1ee409449..2139ec7a4 100644
--- a/crates/ra_proc_macro_srv/src/tests/utils.rs
+++ b/crates/ra_proc_macro_srv/src/tests/utils.rs
@@ -60,6 +60,6 @@ pub fn list(crate_name: &str, version: &str) -> Vec<String> {
60 let path = fixtures::dylib_path(crate_name, version); 60 let path = fixtures::dylib_path(crate_name, version);
61 let task = ListMacrosTask { lib: path }; 61 let task = ListMacrosTask { lib: path };
62 62
63 let res = list_macros(&task).unwrap(); 63 let res = list_macros(&task);
64 res.macros.into_iter().map(|(name, kind)| format!("{} [{:?}]", name, kind)).collect() 64 res.macros.into_iter().map(|(name, kind)| format!("{} [{:?}]", name, kind)).collect()
65} 65}
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 28b67cfe2..e8d5dad65 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -51,7 +51,7 @@ fn main() -> Result<()> {
51 cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)? 51 cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)?
52 } 52 }
53 53
54 args::Command::ProcMacro => run_proc_macro_sv()?, 54 args::Command::ProcMacro => run_proc_macro_srv()?,
55 args::Command::RunServer => run_server()?, 55 args::Command::RunServer => run_server()?,
56 args::Command::Version => println!("rust-analyzer {}", env!("REV")), 56 args::Command::Version => println!("rust-analyzer {}", env!("REV")),
57 } 57 }
@@ -65,7 +65,7 @@ fn setup_logging() -> Result<()> {
65 Ok(()) 65 Ok(())
66} 66}
67 67
68fn run_proc_macro_sv() -> Result<()> { 68fn run_proc_macro_srv() -> Result<()> {
69 ra_proc_macro_srv::cli::run(); 69 ra_proc_macro_srv::cli::run();
70 Ok(()) 70 Ok(())
71} 71}
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 762f776fe..d0a71120a 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -76,7 +76,7 @@ pub(crate) fn load_cargo(
76 ProcMacroClient::dummy() 76 ProcMacroClient::dummy()
77 } else { 77 } else {
78 let path = std::env::current_exe()?; 78 let path = std::env::current_exe()?;
79 ProcMacroClient::extern_process(&path, &["proc-macro"]).unwrap() 79 ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap()
80 }; 80 };
81 let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client); 81 let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client);
82 Ok((host, source_roots)) 82 Ok((host, source_roots))
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 369578fb6..8e1744bf9 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -148,20 +148,17 @@ impl WorldState {
148 148
149 let proc_macro_client = match &config.proc_macro_srv { 149 let proc_macro_client = match &config.proc_macro_srv {
150 None => ProcMacroClient::dummy(), 150 None => ProcMacroClient::dummy(),
151 Some((path, args)) => { 151 Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
152 let path = std::path::Path::new(path); 152 Ok(it) => it,
153 match ProcMacroClient::extern_process(path, args) { 153 Err(err) => {
154 Ok(it) => it, 154 log::error!(
155 Err(err) => { 155 "Fail to run ra_proc_macro_srv from path {}, error: {:?}",
156 log::error!( 156 path,
157 "Fail to run ra_proc_macro_srv from path {}, error : {}", 157 err
158 path.to_string_lossy(), 158 );
159 err 159 ProcMacroClient::dummy()
160 );
161 ProcMacroClient::dummy()
162 }
163 } 160 }
164 } 161 },
165 }; 162 };
166 163
167 workspaces 164 workspaces