diff options
Diffstat (limited to 'crates/ra_proc_macro_srv/src/dylib.rs')
-rw-r--r-- | crates/ra_proc_macro_srv/src/dylib.rs | 103 |
1 files changed, 45 insertions, 58 deletions
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; | |||
9 | use memmap::Mmap; | 9 | use memmap::Mmap; |
10 | use ra_proc_macro::ProcMacroKind; | 10 | use ra_proc_macro::ProcMacroKind; |
11 | 11 | ||
12 | use std::io::Error as IoError; | 12 | use std::io; |
13 | use std::io::ErrorKind as IoErrorKind; | ||
14 | 13 | ||
15 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; | 14 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; |
16 | 15 | ||
17 | fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError { | 16 | fn 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 | ||
21 | fn is_derive_registrar_symbol(symbol: &str) -> bool { | 20 | fn is_derive_registrar_symbol(symbol: &str) -> bool { |
22 | symbol.contains(NEW_REGISTRAR_SYMBOL) | 21 | symbol.contains(NEW_REGISTRAR_SYMBOL) |
23 | } | 22 | } |
24 | 23 | ||
25 | fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { | 24 | fn 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 | ||
95 | struct ProcMacroLibraryLibloading { | 89 | struct 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 | ||
101 | impl ProcMacroLibraryLibloading { | 95 | impl 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 | ||
123 | impl Expander { | 118 | impl 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 | } |