aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_proc_macro_srv/src/dylib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_proc_macro_srv/src/dylib.rs')
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs113
1 files changed, 69 insertions, 44 deletions
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs
index d202eb0fd..aa84e951c 100644
--- a/crates/ra_proc_macro_srv/src/dylib.rs
+++ b/crates/ra_proc_macro_srv/src/dylib.rs
@@ -2,13 +2,12 @@
2 2
3use crate::{proc_macro::bridge, rustc_server::TokenStream}; 3use crate::{proc_macro::bridge, rustc_server::TokenStream};
4use std::fs::File; 4use std::fs::File;
5use std::path::Path; 5use std::path::{Path, PathBuf};
6 6
7use goblin::{mach::Mach, Object}; 7use goblin::{mach::Mach, Object};
8use libloading::Library; 8use libloading::Library;
9use memmap::Mmap; 9use memmap::Mmap;
10use ra_proc_macro::ProcMacroKind; 10use ra_proc_macro::ProcMacroKind;
11
12use std::io; 11use std::io;
13 12
14const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; 13const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
@@ -109,23 +108,21 @@ impl ProcMacroLibraryLibloading {
109 } 108 }
110} 109}
111 110
112type ProcMacroLibraryImpl = ProcMacroLibraryLibloading;
113
114pub struct Expander { 111pub struct Expander {
115 libs: Vec<ProcMacroLibraryImpl>, 112 inner: ProcMacroLibraryLibloading,
116} 113}
117 114
118impl Expander { 115impl Expander {
119 pub fn new(lib: &Path) -> Result<Expander, String> { 116 pub fn new(lib: &Path) -> io::Result<Expander> {
120 // Some libraries for dynamic loading require canonicalized path even when it is 117 // Some libraries for dynamic loading require canonicalized path even when it is
121 // already absolute 118 // already absolute
122 let lib = lib 119 let lib = lib.canonicalize()?;
123 .canonicalize() 120
124 .unwrap_or_else(|err| panic!("Cannot canonicalize {}: {:?}", lib.display(), err)); 121 let lib = ensure_file_with_lock_free_access(&lib)?;
125 122
126 let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?; 123 let library = ProcMacroLibraryLibloading::open(&lib)?;
127 124
128 Ok(Expander { libs: vec![library] }) 125 Ok(Expander { inner: library })
129 } 126 }
130 127
131 pub fn expand( 128 pub fn expand(
@@ -141,38 +138,36 @@ impl Expander {
141 TokenStream::with_subtree(attr.clone()) 138 TokenStream::with_subtree(attr.clone())
142 }); 139 });
143 140
144 for lib in &self.libs { 141 for proc_macro in &self.inner.exported_macros {
145 for proc_macro in &lib.exported_macros { 142 match proc_macro {
146 match proc_macro { 143 bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
147 bridge::client::ProcMacro::CustomDerive { trait_name, client, .. } 144 if *trait_name == macro_name =>
148 if *trait_name == macro_name => 145 {
149 { 146 let res = client.run(
150 let res = client.run( 147 &crate::proc_macro::bridge::server::SameThread,
151 &crate::proc_macro::bridge::server::SameThread, 148 crate::rustc_server::Rustc::default(),
152 crate::rustc_server::Rustc::default(), 149 parsed_body,
153 parsed_body, 150 );
154 ); 151 return res.map(|it| it.subtree);
155 return res.map(|it| it.subtree); 152 }
156 } 153 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
157 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { 154 let res = client.run(
158 let res = client.run( 155 &crate::proc_macro::bridge::server::SameThread,
159 &crate::proc_macro::bridge::server::SameThread, 156 crate::rustc_server::Rustc::default(),
160 crate::rustc_server::Rustc::default(), 157 parsed_body,
161 parsed_body, 158 );
162 ); 159 return res.map(|it| it.subtree);
163 return res.map(|it| it.subtree); 160 }
164 } 161 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
165 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { 162 let res = client.run(
166 let res = client.run( 163 &crate::proc_macro::bridge::server::SameThread,
167 &crate::proc_macro::bridge::server::SameThread, 164 crate::rustc_server::Rustc::default(),
168 crate::rustc_server::Rustc::default(), 165 parsed_attributes,
169 parsed_attributes, 166 parsed_body,
170 parsed_body, 167 );
171 ); 168 return res.map(|it| it.subtree);
172 return res.map(|it| it.subtree);
173 }
174 _ => continue,
175 } 169 }
170 _ => continue,
176 } 171 }
177 } 172 }
178 173
@@ -180,9 +175,9 @@ impl Expander {
180 } 175 }
181 176
182 pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> { 177 pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
183 self.libs 178 self.inner
179 .exported_macros
184 .iter() 180 .iter()
185 .flat_map(|it| &it.exported_macros)
186 .map(|proc_macro| match proc_macro { 181 .map(|proc_macro| match proc_macro {
187 bridge::client::ProcMacro::CustomDerive { trait_name, .. } => { 182 bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
188 (trait_name.to_string(), ProcMacroKind::CustomDerive) 183 (trait_name.to_string(), ProcMacroKind::CustomDerive)
@@ -197,3 +192,33 @@ impl Expander {
197 .collect() 192 .collect()
198 } 193 }
199} 194}
195
196/// Copy the dylib to temp directory to prevent locking in Windows
197#[cfg(windows)]
198fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
199 use std::{ffi::OsString, time::SystemTime};
200
201 let mut to = std::env::temp_dir();
202
203 let file_name = path.file_name().ok_or_else(|| {
204 io::Error::new(
205 io::ErrorKind::InvalidInput,
206 format!("File path is invalid: {}", path.display()),
207 )
208 })?;
209
210 // generate a time deps unique number
211 let t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("Time went backwards");
212
213 let mut unique_name = OsString::from(t.as_millis().to_string());
214 unique_name.push(file_name);
215
216 to.push(unique_name);
217 std::fs::copy(path, &to).unwrap();
218 Ok(to)
219}
220
221#[cfg(unix)]
222fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
223 Ok(path.to_path_buf())
224}