aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_proc_macro_srv
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_proc_macro_srv')
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs20
-rw-r--r--crates/ra_proc_macro_srv/src/lib.rs8
2 files changed, 12 insertions, 16 deletions
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs
index 99c83481a..209f61493 100644
--- a/crates/ra_proc_macro_srv/src/dylib.rs
+++ b/crates/ra_proc_macro_srv/src/dylib.rs
@@ -109,24 +109,19 @@ impl ProcMacroLibraryLibloading {
109 } 109 }
110} 110}
111 111
112type ProcMacroLibraryImpl = ProcMacroLibraryLibloading;
113
114pub struct Expander { 112pub struct Expander {
115 inner: ProcMacroLibraryImpl, 113 inner: ProcMacroLibraryLibloading,
116} 114}
117 115
118impl Expander { 116impl Expander {
119 pub fn new(lib: &Path) -> Result<Expander, String> { 117 pub fn new(lib: &Path) -> io::Result<Expander> {
120 // Some libraries for dynamic loading require canonicalized path even when it is 118 // Some libraries for dynamic loading require canonicalized path even when it is
121 // already absolute 119 // already absolute
122 let lib = lib 120 let lib = lib.canonicalize()?;
123 .canonicalize()
124 .unwrap_or_else(|err| panic!("Cannot canonicalize {}: {:?}", lib.display(), err));
125 121
126 // Copy the dylib to temp directory to prevent locking in Windows 122 let lib = ensure_file_with_lock_free_access(&lib)?;
127 let lib = copy_to_temp_dir(&lib).map_err(|e| e.to_string())?;
128 123
129 let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?; 124 let library = ProcMacroLibraryLibloading::open(&lib)?;
130 125
131 Ok(Expander { inner: library }) 126 Ok(Expander { inner: library })
132 } 127 }
@@ -199,8 +194,9 @@ impl Expander {
199 } 194 }
200} 195}
201 196
197/// Copy the dylib to temp directory to prevent locking in Windows
202#[cfg(windows)] 198#[cfg(windows)]
203fn copy_to_temp_dir(path: &Path) -> io::Result<PathBuf> { 199fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
204 let mut to = std::env::temp_dir(); 200 let mut to = std::env::temp_dir();
205 let file_name = path.file_name().ok_or_else(|| { 201 let file_name = path.file_name().ok_or_else(|| {
206 io::Error::new( 202 io::Error::new(
@@ -215,6 +211,6 @@ fn copy_to_temp_dir(path: &Path) -> io::Result<PathBuf> {
215} 211}
216 212
217#[cfg(unix)] 213#[cfg(unix)]
218fn copy_to_temp_dir(path: &Path) -> io::Result<PathBuf> { 214fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
219 Ok(path.to_path_buf()) 215 Ok(path.to_path_buf())
220} 216}
diff --git a/crates/ra_proc_macro_srv/src/lib.rs b/crates/ra_proc_macro_srv/src/lib.rs
index 121f531fd..922bb84bb 100644
--- a/crates/ra_proc_macro_srv/src/lib.rs
+++ b/crates/ra_proc_macro_srv/src/lib.rs
@@ -23,7 +23,7 @@ use proc_macro::bridge::client::TokenStream;
23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; 23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
24use std::{ 24use std::{
25 collections::{hash_map::Entry, HashMap}, 25 collections::{hash_map::Entry, HashMap},
26 fs::metadata, 26 fs,
27 path::{Path, PathBuf}, 27 path::{Path, PathBuf},
28 time::SystemTime, 28 time::SystemTime,
29}; 29};
@@ -50,9 +50,9 @@ impl ProcMacroSrv {
50 } 50 }
51 51
52 fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> { 52 fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
53 let time = metadata(path) 53 let time = fs::metadata(path).and_then(|it| it.modified()).map_err(|err| {
54 .and_then(|it| it.modified()) 54 format!("Failed to get file metadata for {}: {:?}", path.display(), err)
55 .map_err(|err| format!("Failed to file metadata for {}: {:?}", path.display(), err))?; 55 })?;
56 56
57 Ok(match self.expanders.entry((path.to_path_buf(), time)) { 57 Ok(match self.expanders.entry((path.to_path_buf(), time)) {
58 Entry::Vacant(v) => v.insert(dylib::Expander::new(path).map_err(|err| { 58 Entry::Vacant(v) => v.insert(dylib::Expander::new(path).map_err(|err| {