mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-25 19:35:06 +00:00
internal: make sure that proc macro machinery doesn't depend on cwd
This commit is contained in:
parent
9318c643f1
commit
8df38aa797
9 changed files with 52 additions and 22 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1042,6 +1042,9 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paths"
|
name = "paths"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
|
@ -1109,6 +1112,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"object",
|
"object",
|
||||||
|
"paths",
|
||||||
"profile",
|
"profile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -7,3 +7,6 @@ edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = "1"
|
||||||
|
|
|
@ -66,6 +66,27 @@ impl PartialEq<AbsPath> for AbsPathBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl serde::Serialize for AbsPathBuf {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
self.0.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> serde::Deserialize<'de> for AbsPathBuf {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let path = PathBuf::deserialize(deserializer)?;
|
||||||
|
AbsPathBuf::try_from(path).map_err(|path| {
|
||||||
|
serde::de::Error::custom(format!("expected absolute path, got {}", path.display()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AbsPathBuf {
|
impl AbsPathBuf {
|
||||||
/// Wrap the given absolute path in `AbsPathBuf`
|
/// Wrap the given absolute path in `AbsPathBuf`
|
||||||
///
|
///
|
||||||
|
|
|
@ -18,6 +18,7 @@ memmap2 = "0.3.0"
|
||||||
object = { version = "0.25.3", default-features = false, features = ["std", "read_core", "elf", "macho", "pe"] }
|
object = { version = "0.25.3", default-features = false, features = ["std", "read_core", "elf", "macho", "pe"] }
|
||||||
snap = "1.0"
|
snap = "1.0"
|
||||||
|
|
||||||
|
paths = { path = "../paths", version = "0.0.0" }
|
||||||
tt = { path = "../tt", version = "0.0.0" }
|
tt = { path = "../tt", version = "0.0.0" }
|
||||||
base_db = { path = "../base_db", version = "0.0.0" }
|
base_db = { path = "../base_db", version = "0.0.0" }
|
||||||
stdx = { path = "../stdx", version = "0.0.0" }
|
stdx = { path = "../stdx", version = "0.0.0" }
|
||||||
|
|
|
@ -11,10 +11,10 @@ mod rpc;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
use base_db::{Env, ProcMacro};
|
use base_db::{Env, ProcMacro};
|
||||||
|
use paths::{AbsPath, AbsPathBuf};
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
io,
|
io,
|
||||||
path::{Path, PathBuf},
|
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ pub use version::{read_dylib_info, RustCInfo};
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct ProcMacroProcessExpander {
|
struct ProcMacroProcessExpander {
|
||||||
process: Arc<Mutex<ProcMacroProcessSrv>>,
|
process: Arc<Mutex<ProcMacroProcessSrv>>,
|
||||||
dylib_path: PathBuf,
|
dylib_path: AbsPathBuf,
|
||||||
name: SmolStr,
|
name: SmolStr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,26 +79,25 @@ pub struct ProcMacroClient {
|
||||||
impl ProcMacroClient {
|
impl ProcMacroClient {
|
||||||
/// Spawns an external process as the proc macro server and returns a client connected to it.
|
/// Spawns an external process as the proc macro server and returns a client connected to it.
|
||||||
pub fn extern_process(
|
pub fn extern_process(
|
||||||
process_path: PathBuf,
|
process_path: AbsPathBuf,
|
||||||
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
||||||
) -> io::Result<ProcMacroClient> {
|
) -> io::Result<ProcMacroClient> {
|
||||||
let process = ProcMacroProcessSrv::run(process_path, args)?;
|
let process = ProcMacroProcessSrv::run(process_path, args)?;
|
||||||
Ok(ProcMacroClient { process: Arc::new(Mutex::new(process)) })
|
Ok(ProcMacroClient { process: Arc::new(Mutex::new(process)) })
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use paths::AbsPath here
|
pub fn by_dylib_path(&self, dylib_path: &AbsPath) -> Vec<ProcMacro> {
|
||||||
pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> {
|
|
||||||
let _p = profile::span("ProcMacroClient::by_dylib_path");
|
let _p = profile::span("ProcMacroClient::by_dylib_path");
|
||||||
match version::read_dylib_info(dylib_path) {
|
match version::read_dylib_info(dylib_path) {
|
||||||
Ok(info) => {
|
Ok(info) => {
|
||||||
if info.version.0 < 1 || info.version.1 < 47 {
|
if info.version.0 < 1 || info.version.1 < 47 {
|
||||||
eprintln!("proc-macro {} built by {:#?} is not supported by Rust Analyzer, please update your rust version.", dylib_path.to_string_lossy(), info);
|
eprintln!("proc-macro {} built by {:#?} is not supported by Rust Analyzer, please update your rust version.", dylib_path.display(), info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"proc-macro {} failed to find the given version. Reason: {}",
|
"proc-macro {} failed to find the given version. Reason: {}",
|
||||||
dylib_path.to_string_lossy(),
|
dylib_path.display(),
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -129,7 +128,7 @@ impl ProcMacroClient {
|
||||||
let expander = Arc::new(ProcMacroProcessExpander {
|
let expander = Arc::new(ProcMacroProcessExpander {
|
||||||
process: self.process.clone(),
|
process: self.process.clone(),
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
dylib_path: dylib_path.into(),
|
dylib_path: dylib_path.to_path_buf(),
|
||||||
});
|
});
|
||||||
|
|
||||||
ProcMacro { name, kind, expander }
|
ProcMacro { name, kind, expander }
|
||||||
|
|
|
@ -4,10 +4,10 @@ use std::{
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
io::{self, BufRead, BufReader, Write},
|
io::{self, BufRead, BufReader, Write},
|
||||||
path::{Path, PathBuf},
|
|
||||||
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
|
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use paths::{AbsPath, AbsPathBuf};
|
||||||
use stdx::JodChild;
|
use stdx::JodChild;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -24,7 +24,7 @@ pub(crate) struct ProcMacroProcessSrv {
|
||||||
|
|
||||||
impl ProcMacroProcessSrv {
|
impl ProcMacroProcessSrv {
|
||||||
pub(crate) fn run(
|
pub(crate) fn run(
|
||||||
process_path: PathBuf,
|
process_path: AbsPathBuf,
|
||||||
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
||||||
) -> io::Result<ProcMacroProcessSrv> {
|
) -> io::Result<ProcMacroProcessSrv> {
|
||||||
let mut process = Process::run(process_path, args)?;
|
let mut process = Process::run(process_path, args)?;
|
||||||
|
@ -37,7 +37,7 @@ impl ProcMacroProcessSrv {
|
||||||
|
|
||||||
pub(crate) fn find_proc_macros(
|
pub(crate) fn find_proc_macros(
|
||||||
&mut self,
|
&mut self,
|
||||||
dylib_path: &Path,
|
dylib_path: &AbsPath,
|
||||||
) -> Result<Vec<(String, ProcMacroKind)>, tt::ExpansionError> {
|
) -> Result<Vec<(String, ProcMacroKind)>, tt::ExpansionError> {
|
||||||
let task = ListMacrosTask { lib: dylib_path.to_path_buf() };
|
let task = ListMacrosTask { lib: dylib_path.to_path_buf() };
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ struct Process {
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
fn run(
|
fn run(
|
||||||
path: PathBuf,
|
path: AbsPathBuf,
|
||||||
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
||||||
) -> io::Result<Process> {
|
) -> io::Result<Process> {
|
||||||
let args: Vec<OsString> = args.into_iter().map(|s| s.as_ref().into()).collect();
|
let args: Vec<OsString> = args.into_iter().map(|s| s.as_ref().into()).collect();
|
||||||
|
@ -101,8 +101,11 @@ impl Process {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_child(path: &Path, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> io::Result<Child> {
|
fn mk_child(
|
||||||
Command::new(&path)
|
path: &AbsPath,
|
||||||
|
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
|
||||||
|
) -> io::Result<Child> {
|
||||||
|
Command::new(path.as_os_str())
|
||||||
.args(args)
|
.args(args)
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
//! to be much easier, we deliberately duplicate `tt` structs with `#[serde(with = "XXDef")]`
|
//! to be much easier, we deliberately duplicate `tt` structs with `#[serde(with = "XXDef")]`
|
||||||
//! for separation of code responsibility.
|
//! for separation of code responsibility.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use paths::AbsPathBuf;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tt::{
|
use tt::{
|
||||||
Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,
|
Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,
|
||||||
|
@ -16,7 +15,7 @@ use tt::{
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||||
pub struct ListMacrosTask {
|
pub struct ListMacrosTask {
|
||||||
pub lib: PathBuf,
|
pub lib: AbsPathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||||
|
@ -50,7 +49,7 @@ pub struct ExpansionTask {
|
||||||
#[serde(with = "opt_subtree_def")]
|
#[serde(with = "opt_subtree_def")]
|
||||||
pub attributes: Option<Subtree>,
|
pub attributes: Option<Subtree>,
|
||||||
|
|
||||||
pub lib: PathBuf,
|
pub lib: AbsPathBuf,
|
||||||
|
|
||||||
/// Environment variables to set during macro expansion.
|
/// Environment variables to set during macro expansion.
|
||||||
pub env: Vec<(String, String)>,
|
pub env: Vec<(String, String)>,
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, Read},
|
io::{self, Read},
|
||||||
path::Path,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use memmap2::Mmap;
|
use memmap2::Mmap;
|
||||||
use object::read::{File as BinaryFile, Object, ObjectSection};
|
use object::read::{File as BinaryFile, Object, ObjectSection};
|
||||||
|
use paths::AbsPath;
|
||||||
use snap::read::FrameDecoder as SnapDecoder;
|
use snap::read::FrameDecoder as SnapDecoder;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -19,7 +19,7 @@ pub struct RustCInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read rustc dylib information
|
/// Read rustc dylib information
|
||||||
pub fn read_dylib_info(dylib_path: &Path) -> io::Result<RustCInfo> {
|
pub fn read_dylib_info(dylib_path: &AbsPath) -> io::Result<RustCInfo> {
|
||||||
macro_rules! err {
|
macro_rules! err {
|
||||||
($e:literal) => {
|
($e:literal) => {
|
||||||
io::Error::new(io::ErrorKind::InvalidData, $e)
|
io::Error::new(io::ErrorKind::InvalidData, $e)
|
||||||
|
@ -96,7 +96,7 @@ fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'
|
||||||
/// * [some more bytes that we don really care but still there] :-)
|
/// * [some more bytes that we don really care but still there] :-)
|
||||||
/// Check this issue for more about the bytes layout:
|
/// Check this issue for more about the bytes layout:
|
||||||
/// <https://github.com/rust-analyzer/rust-analyzer/issues/6174>
|
/// <https://github.com/rust-analyzer/rust-analyzer/issues/6174>
|
||||||
fn read_version(dylib_path: &Path) -> io::Result<String> {
|
fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
|
||||||
let dylib_file = File::open(dylib_path)?;
|
let dylib_file = File::open(dylib_path)?;
|
||||||
let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?;
|
let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?;
|
||||||
|
|
||||||
|
|
|
@ -312,7 +312,7 @@ impl ProjectWorkspace {
|
||||||
) -> CrateGraph {
|
) -> CrateGraph {
|
||||||
let _p = profile::span("ProjectWorkspace::to_crate_graph");
|
let _p = profile::span("ProjectWorkspace::to_crate_graph");
|
||||||
let proc_macro_loader = |path: &AbsPath| match proc_macro_client {
|
let proc_macro_loader = |path: &AbsPath| match proc_macro_client {
|
||||||
Some(client) => client.by_dylib_path(path.as_ref()), // TODO
|
Some(client) => client.by_dylib_path(path),
|
||||||
None => Vec::new(),
|
None => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue