mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Introduce proc_macro_srv::abis, impl 1.47 and 1.55
Rather than a "Stable" and "Nightly" ABI we instead name ABIs based on the version of the rust compiler in which they were introduced. We place these ABIs in a new module - `proc_macro_srv::abis` - where we also add some mchinery to abstract over ABIs. This should make it easy to add new ABIs at a later date as the rust compiler evolves.
This commit is contained in:
parent
14a51d28b5
commit
e240eb67a8
28 changed files with 390 additions and 327 deletions
106
crates/proc_macro_srv/src/abis/abi_1_47/mod.rs
Normal file
106
crates/proc_macro_srv/src/abis/abi_1_47/mod.rs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
//! Macro ABI for version 1.47 of rustc
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod proc_macro;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod rustc_server;
|
||||||
|
use libloading::Library;
|
||||||
|
|
||||||
|
use proc_macro_api::ProcMacroKind;
|
||||||
|
|
||||||
|
use super::PanicMessage;
|
||||||
|
|
||||||
|
pub use rustc_server::TokenStream;
|
||||||
|
|
||||||
|
pub(crate) struct Abi {
|
||||||
|
exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<proc_macro::bridge::PanicMessage> for PanicMessage {
|
||||||
|
fn from(p: proc_macro::bridge::PanicMessage) -> Self {
|
||||||
|
Self { message: p.as_str().map(|s| s.to_string()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Abi {
|
||||||
|
pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> {
|
||||||
|
let macros: libloading::Symbol<&&[proc_macro::bridge::client::ProcMacro]> =
|
||||||
|
lib.get(symbol_name.as_bytes())?;
|
||||||
|
Ok(Self { exported_macros: macros.to_vec() })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand(
|
||||||
|
&self,
|
||||||
|
macro_name: &str,
|
||||||
|
macro_body: &tt::Subtree,
|
||||||
|
attributes: Option<&tt::Subtree>,
|
||||||
|
) -> Result<tt::Subtree, PanicMessage> {
|
||||||
|
let parsed_body = rustc_server::TokenStream::with_subtree(macro_body.clone());
|
||||||
|
|
||||||
|
let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| {
|
||||||
|
rustc_server::TokenStream::with_subtree(attr.clone())
|
||||||
|
});
|
||||||
|
|
||||||
|
for proc_macro in &self.exported_macros {
|
||||||
|
match proc_macro {
|
||||||
|
proc_macro::bridge::client::ProcMacro::CustomDerive {
|
||||||
|
trait_name, client, ..
|
||||||
|
} if *trait_name == macro_name => {
|
||||||
|
let res = client.run(
|
||||||
|
&proc_macro::bridge::server::SameThread,
|
||||||
|
rustc_server::Rustc::default(),
|
||||||
|
parsed_body,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Bang { name, client }
|
||||||
|
if *name == macro_name =>
|
||||||
|
{
|
||||||
|
let res = client.run(
|
||||||
|
&proc_macro::bridge::server::SameThread,
|
||||||
|
rustc_server::Rustc::default(),
|
||||||
|
parsed_body,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Attr { name, client }
|
||||||
|
if *name == macro_name =>
|
||||||
|
{
|
||||||
|
let res = client.run(
|
||||||
|
&proc_macro::bridge::server::SameThread,
|
||||||
|
rustc_server::Rustc::default(),
|
||||||
|
parsed_attributes,
|
||||||
|
parsed_body,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
|
||||||
|
self.exported_macros
|
||||||
|
.iter()
|
||||||
|
.map(|proc_macro| match proc_macro {
|
||||||
|
proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
|
||||||
|
(trait_name.to_string(), ProcMacroKind::CustomDerive)
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
|
||||||
|
(name.to_string(), ProcMacroKind::FuncLike)
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
|
||||||
|
(name.to_string(), ProcMacroKind::Attr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/client.rs>
|
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/client.rs>
|
||||||
//! augmented with removing unstable features
|
//! augmented with removing unstable features
|
||||||
|
|
||||||
|
use super::super::TokenStream as CrateTokenStream;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! define_handles {
|
macro_rules! define_handles {
|
||||||
|
@ -401,26 +402,26 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
||||||
b
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
impl Client<fn(CrateTokenStream) -> CrateTokenStream> {
|
||||||
pub fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
|
pub fn expand1(f: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||||
extern "C" fn run(
|
extern "C" fn run(
|
||||||
bridge: Bridge<'_>,
|
bridge: Bridge<'_>,
|
||||||
f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
|
f: impl FnOnce(CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Buffer<u8> {
|
) -> Buffer<u8> {
|
||||||
run_client(bridge, |input| f(crate::TokenStream(input)).0)
|
run_client(bridge, |input| f(CrateTokenStream(input)).0)
|
||||||
}
|
}
|
||||||
Client { get_handle_counters: HandleCounters::get, run, f }
|
Client { get_handle_counters: HandleCounters::get, run, f }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
|
impl Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream> {
|
||||||
pub fn expand2(f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream) -> Self {
|
pub fn expand2(f: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||||
extern "C" fn run(
|
extern "C" fn run(
|
||||||
bridge: Bridge<'_>,
|
bridge: Bridge<'_>,
|
||||||
f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
f: impl FnOnce(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Buffer<u8> {
|
) -> Buffer<u8> {
|
||||||
run_client(bridge, |(input, input2)| {
|
run_client(bridge, |(input, input2)| {
|
||||||
f(crate::TokenStream(input), crate::TokenStream(input2)).0
|
f(CrateTokenStream(input), CrateTokenStream(input2)).0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Client { get_handle_counters: HandleCounters::get, run, f }
|
Client { get_handle_counters: HandleCounters::get, run, f }
|
||||||
|
@ -433,17 +434,17 @@ pub enum ProcMacro {
|
||||||
CustomDerive {
|
CustomDerive {
|
||||||
trait_name: &'static str,
|
trait_name: &'static str,
|
||||||
attributes: &'static [&'static str],
|
attributes: &'static [&'static str],
|
||||||
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
|
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Attr {
|
Attr {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
client: Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream>,
|
client: Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Bang {
|
Bang {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
|
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,19 +466,19 @@ impl ProcMacro {
|
||||||
pub fn custom_derive(
|
pub fn custom_derive(
|
||||||
trait_name: &'static str,
|
trait_name: &'static str,
|
||||||
attributes: &'static [&'static str],
|
attributes: &'static [&'static str],
|
||||||
expand: fn(crate::TokenStream) -> crate::TokenStream,
|
expand: fn(CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
|
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attr(
|
pub fn attr(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
expand: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ProcMacro::Attr { name, client: Client::expand2(expand) }
|
ProcMacro::Attr { name, client: Client::expand2(expand) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bang(name: &'static str, expand: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
|
pub fn bang(name: &'static str, expand: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||||
ProcMacro::Bang { name, client: Client::expand1(expand) }
|
ProcMacro::Bang { name, client: Client::expand1(expand) }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
pub use crate::proc_macro::{Delimiter, Level, LineColumn, Spacing};
|
pub use super::{Delimiter, Level, LineColumn, Spacing};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::marker;
|
use std::marker;
|
|
@ -3,6 +3,7 @@
|
||||||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
|
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
|
||||||
//! augmented with removing unstable features
|
//! augmented with removing unstable features
|
||||||
|
|
||||||
|
use super::super::TokenStream as ProcMacroTokenStream;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
|
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
|
||||||
|
@ -308,7 +309,7 @@ fn run_server<
|
||||||
Result::decode(&mut &b[..], &mut dispatcher.handle_store)
|
Result::decode(&mut &b[..], &mut dispatcher.handle_store)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
impl client::Client<fn(ProcMacroTokenStream) -> ProcMacroTokenStream> {
|
||||||
pub fn run<S: Server>(
|
pub fn run<S: Server>(
|
||||||
&self,
|
&self,
|
||||||
strategy: &impl ExecutionStrategy,
|
strategy: &impl ExecutionStrategy,
|
||||||
|
@ -330,7 +331,7 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
|
impl client::Client<fn(ProcMacroTokenStream, ProcMacroTokenStream) -> ProcMacroTokenStream> {
|
||||||
pub fn run<S: Server>(
|
pub fn run<S: Server>(
|
||||||
&self,
|
&self,
|
||||||
strategy: &impl ExecutionStrategy,
|
strategy: &impl ExecutionStrategy,
|
|
@ -133,7 +133,7 @@ impl Extend<TokenStream> for TokenStream {
|
||||||
|
|
||||||
/// Public implementation details for the `TokenStream` type, such as iterators.
|
/// Public implementation details for the `TokenStream` type, such as iterators.
|
||||||
pub mod token_stream {
|
pub mod token_stream {
|
||||||
use crate::proc_macro::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree};
|
use super::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree};
|
||||||
|
|
||||||
/// An iterator over `TokenStream`'s `TokenTree`s.
|
/// An iterator over `TokenStream`'s `TokenTree`s.
|
||||||
/// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
|
/// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
|
|
@ -8,7 +8,7 @@
|
||||||
//!
|
//!
|
||||||
//! FIXME: No span and source file information is implemented yet
|
//! FIXME: No span and source file information is implemented yet
|
||||||
|
|
||||||
use crate::proc_macro::bridge::{self, server};
|
use super::proc_macro::bridge::{self, server};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -97,9 +97,9 @@ impl Extend<TokenStream> for TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Level = crate::proc_macro::Level;
|
type Level = super::proc_macro::Level;
|
||||||
type LineColumn = crate::proc_macro::LineColumn;
|
type LineColumn = super::proc_macro::LineColumn;
|
||||||
type SourceFile = crate::proc_macro::SourceFile;
|
type SourceFile = super::proc_macro::SourceFile;
|
||||||
|
|
||||||
/// A structure representing a diagnostic message and associated children
|
/// A structure representing a diagnostic message and associated children
|
||||||
/// messages.
|
/// messages.
|
||||||
|
@ -734,8 +734,8 @@ impl server::MultiSpan for Rustc {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::super::proc_macro::bridge::server::Literal;
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::proc_macro::bridge::server::Literal;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rustc_server_literals() {
|
fn test_rustc_server_literals() {
|
104
crates/proc_macro_srv/src/abis/abi_1_55/mod.rs
Normal file
104
crates/proc_macro_srv/src/abis/abi_1_55/mod.rs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
//! Macro ABI for version 1.55 of rustc
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod proc_macro;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod rustc_server;
|
||||||
|
use libloading::Library;
|
||||||
|
|
||||||
|
use proc_macro_api::ProcMacroKind;
|
||||||
|
|
||||||
|
use super::PanicMessage;
|
||||||
|
|
||||||
|
pub(crate) struct Abi {
|
||||||
|
exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<proc_macro::bridge::PanicMessage> for PanicMessage {
|
||||||
|
fn from(p: proc_macro::bridge::PanicMessage) -> Self {
|
||||||
|
Self { message: p.as_str().map(|s| s.to_string()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Abi {
|
||||||
|
pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> {
|
||||||
|
let macros: libloading::Symbol<&&[proc_macro::bridge::client::ProcMacro]> =
|
||||||
|
lib.get(symbol_name.as_bytes())?;
|
||||||
|
Ok(Self { exported_macros: macros.to_vec() })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand(
|
||||||
|
&self,
|
||||||
|
macro_name: &str,
|
||||||
|
macro_body: &tt::Subtree,
|
||||||
|
attributes: Option<&tt::Subtree>,
|
||||||
|
) -> Result<tt::Subtree, PanicMessage> {
|
||||||
|
let parsed_body = rustc_server::TokenStream::with_subtree(macro_body.clone());
|
||||||
|
|
||||||
|
let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| {
|
||||||
|
rustc_server::TokenStream::with_subtree(attr.clone())
|
||||||
|
});
|
||||||
|
|
||||||
|
for proc_macro in &self.exported_macros {
|
||||||
|
match proc_macro {
|
||||||
|
proc_macro::bridge::client::ProcMacro::CustomDerive {
|
||||||
|
trait_name, client, ..
|
||||||
|
} if *trait_name == macro_name => {
|
||||||
|
let res = client.run(
|
||||||
|
&proc_macro::bridge::server::SameThread,
|
||||||
|
rustc_server::Rustc::default(),
|
||||||
|
parsed_body,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Bang { name, client }
|
||||||
|
if *name == macro_name =>
|
||||||
|
{
|
||||||
|
let res = client.run(
|
||||||
|
&proc_macro::bridge::server::SameThread,
|
||||||
|
rustc_server::Rustc::default(),
|
||||||
|
parsed_body,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Attr { name, client }
|
||||||
|
if *name == macro_name =>
|
||||||
|
{
|
||||||
|
let res = client.run(
|
||||||
|
&proc_macro::bridge::server::SameThread,
|
||||||
|
rustc_server::Rustc::default(),
|
||||||
|
parsed_attributes,
|
||||||
|
parsed_body,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
|
||||||
|
self.exported_macros
|
||||||
|
.iter()
|
||||||
|
.map(|proc_macro| match proc_macro {
|
||||||
|
proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
|
||||||
|
(trait_name.to_string(), ProcMacroKind::CustomDerive)
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
|
||||||
|
(name.to_string(), ProcMacroKind::FuncLike)
|
||||||
|
}
|
||||||
|
proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
|
||||||
|
(name.to_string(), ProcMacroKind::Attr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/client.rs>
|
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/client.rs>
|
||||||
//! augmented with removing unstable features
|
//! augmented with removing unstable features
|
||||||
|
|
||||||
|
use super::super::TokenStream as CrateTokenStream;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! define_handles {
|
macro_rules! define_handles {
|
||||||
|
@ -401,26 +402,26 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
||||||
b
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
impl Client<fn(CrateTokenStream) -> CrateTokenStream> {
|
||||||
pub fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
|
pub fn expand1(f: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||||
extern "C" fn run(
|
extern "C" fn run(
|
||||||
bridge: Bridge<'_>,
|
bridge: Bridge<'_>,
|
||||||
f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
|
f: impl FnOnce(CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Buffer<u8> {
|
) -> Buffer<u8> {
|
||||||
run_client(bridge, |input| f(crate::TokenStream(input)).0)
|
run_client(bridge, |input| f(CrateTokenStream(input)).0)
|
||||||
}
|
}
|
||||||
Client { get_handle_counters: HandleCounters::get, run, f }
|
Client { get_handle_counters: HandleCounters::get, run, f }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
|
impl Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream> {
|
||||||
pub fn expand2(f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream) -> Self {
|
pub fn expand2(f: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||||
extern "C" fn run(
|
extern "C" fn run(
|
||||||
bridge: Bridge<'_>,
|
bridge: Bridge<'_>,
|
||||||
f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
f: impl FnOnce(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Buffer<u8> {
|
) -> Buffer<u8> {
|
||||||
run_client(bridge, |(input, input2)| {
|
run_client(bridge, |(input, input2)| {
|
||||||
f(crate::TokenStream(input), crate::TokenStream(input2)).0
|
f(CrateTokenStream(input), CrateTokenStream(input2)).0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Client { get_handle_counters: HandleCounters::get, run, f }
|
Client { get_handle_counters: HandleCounters::get, run, f }
|
||||||
|
@ -433,17 +434,17 @@ pub enum ProcMacro {
|
||||||
CustomDerive {
|
CustomDerive {
|
||||||
trait_name: &'static str,
|
trait_name: &'static str,
|
||||||
attributes: &'static [&'static str],
|
attributes: &'static [&'static str],
|
||||||
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
|
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Attr {
|
Attr {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
client: Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream>,
|
client: Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Bang {
|
Bang {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
|
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,19 +466,19 @@ impl ProcMacro {
|
||||||
pub fn custom_derive(
|
pub fn custom_derive(
|
||||||
trait_name: &'static str,
|
trait_name: &'static str,
|
||||||
attributes: &'static [&'static str],
|
attributes: &'static [&'static str],
|
||||||
expand: fn(crate::TokenStream) -> crate::TokenStream,
|
expand: fn(CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
|
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attr(
|
pub fn attr(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
expand: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ProcMacro::Attr { name, client: Client::expand2(expand) }
|
ProcMacro::Attr { name, client: Client::expand2(expand) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bang(name: &'static str, expand: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
|
pub fn bang(name: &'static str, expand: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||||
ProcMacro::Bang { name, client: Client::expand1(expand) }
|
ProcMacro::Bang { name, client: Client::expand1(expand) }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
|
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
|
||||||
//! augmented with removing unstable features
|
//! augmented with removing unstable features
|
||||||
|
|
||||||
|
use super::super::TokenStream as CrateTokenStream;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
|
// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
|
||||||
|
@ -302,7 +303,7 @@ fn run_server<
|
||||||
Result::decode(&mut &b[..], &mut dispatcher.handle_store)
|
Result::decode(&mut &b[..], &mut dispatcher.handle_store)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
impl client::Client<fn(CrateTokenStream) -> CrateTokenStream> {
|
||||||
pub fn run<S: Server>(
|
pub fn run<S: Server>(
|
||||||
&self,
|
&self,
|
||||||
strategy: &impl ExecutionStrategy,
|
strategy: &impl ExecutionStrategy,
|
||||||
|
@ -324,7 +325,7 @@ impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl client::Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
|
impl client::Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream> {
|
||||||
pub fn run<S: Server>(
|
pub fn run<S: Server>(
|
||||||
&self,
|
&self,
|
||||||
strategy: &impl ExecutionStrategy,
|
strategy: &impl ExecutionStrategy,
|
|
@ -3,7 +3,7 @@
|
||||||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/diagnostic.rs>
|
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/diagnostic.rs>
|
||||||
//! augmented with removing unstable features
|
//! augmented with removing unstable features
|
||||||
|
|
||||||
use crate::proc_macro::Span;
|
use super::Span;
|
||||||
|
|
||||||
/// An enum representing a diagnostic level.
|
/// An enum representing a diagnostic level.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -146,15 +146,15 @@ impl Diagnostic {
|
||||||
|
|
||||||
/// Emit the diagnostic.
|
/// Emit the diagnostic.
|
||||||
pub fn emit(self) {
|
pub fn emit(self) {
|
||||||
fn to_internal(spans: Vec<Span>) -> crate::proc_macro::bridge::client::MultiSpan {
|
fn to_internal(spans: Vec<Span>) -> super::bridge::client::MultiSpan {
|
||||||
let mut multi_span = crate::proc_macro::bridge::client::MultiSpan::new();
|
let mut multi_span = super::bridge::client::MultiSpan::new();
|
||||||
for span in spans {
|
for span in spans {
|
||||||
multi_span.push(span.0);
|
multi_span.push(span.0);
|
||||||
}
|
}
|
||||||
multi_span
|
multi_span
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diag = crate::proc_macro::bridge::client::Diagnostic::new(
|
let mut diag = super::bridge::client::Diagnostic::new(
|
||||||
self.level,
|
self.level,
|
||||||
&self.message[..],
|
&self.message[..],
|
||||||
to_internal(self.spans),
|
to_internal(self.spans),
|
|
@ -8,7 +8,7 @@
|
||||||
//!
|
//!
|
||||||
//! FIXME: No span and source file information is implemented yet
|
//! FIXME: No span and source file information is implemented yet
|
||||||
|
|
||||||
use crate::proc_macro_nightly::bridge::{self, server};
|
use super::proc_macro::bridge::{self, server};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -97,9 +97,9 @@ impl Extend<TokenStream> for TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Level = crate::proc_macro_nightly::Level;
|
type Level = super::proc_macro::Level;
|
||||||
type LineColumn = crate::proc_macro_nightly::LineColumn;
|
type LineColumn = super::proc_macro::LineColumn;
|
||||||
type SourceFile = crate::proc_macro_nightly::SourceFile;
|
type SourceFile = super::proc_macro::SourceFile;
|
||||||
|
|
||||||
/// A structure representing a diagnostic message and associated children
|
/// A structure representing a diagnostic message and associated children
|
||||||
/// messages.
|
/// messages.
|
||||||
|
@ -737,8 +737,8 @@ impl server::MultiSpan for Rustc {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::super::proc_macro::bridge::server::Literal;
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::proc_macro_nightly::bridge::server::Literal;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rustc_server_literals() {
|
fn test_rustc_server_literals() {
|
97
crates/proc_macro_srv/src/abis/mod.rs
Normal file
97
crates/proc_macro_srv/src/abis/mod.rs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
//! Procedural macros are implemented by compiling the macro providing crate
|
||||||
|
//! to a dynamic library with a particular ABI which the compiler uses to expand
|
||||||
|
//! macros. Unfortunately this ABI is not specified and can change from version
|
||||||
|
//! to version of the compiler. To support this we copy the ABI from the rust
|
||||||
|
//! compiler into submodules of this module (e.g proc_macro_srv::abis::abi_1_47).
|
||||||
|
//!
|
||||||
|
//! All of these ABIs are subsumed in the `Abi` enum, which exposes a simple
|
||||||
|
//! interface the rest of rust analyzer can use to talk to the macro
|
||||||
|
//! provider.
|
||||||
|
//!
|
||||||
|
//! # Adding a new ABI
|
||||||
|
//!
|
||||||
|
//! To add a new ABI you'll need to copy the source of the target proc_macro
|
||||||
|
//! crate from the source tree of the Rust compiler into this directory tree.
|
||||||
|
//! Then you'll need to modify it
|
||||||
|
//! - Remove any feature! or other things which won't compile on stable
|
||||||
|
//! - change any absolute imports to relative imports within the ABI tree
|
||||||
|
//!
|
||||||
|
//! Then you'll need to add a branch to the `Abi` enum and an implementation of
|
||||||
|
//! `Abi::expand`, `Abi::list_macros` and `Abi::from_lib` for the new ABI. See
|
||||||
|
//! `proc_macro_srv/src/abis/abi_1_47/mod.rs` for an example. Finally you'll
|
||||||
|
//! need to update the conditionals in `Abi::from_lib` to return your new ABI
|
||||||
|
//! for the relevant versions of the rust compiler
|
||||||
|
//!
|
||||||
|
|
||||||
|
// pub(crate) so tests can use the TokenStream, more notes in test/utils.rs
|
||||||
|
pub(crate) mod abi_1_47;
|
||||||
|
mod abi_1_55;
|
||||||
|
|
||||||
|
use super::dylib::LoadProcMacroDylibError;
|
||||||
|
pub(crate) use abi_1_47::Abi as Abi_1_47;
|
||||||
|
pub(crate) use abi_1_55::Abi as Abi_1_55;
|
||||||
|
use libloading::Library;
|
||||||
|
use proc_macro_api::{ProcMacroKind, RustCInfo};
|
||||||
|
|
||||||
|
pub struct PanicMessage {
|
||||||
|
message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PanicMessage {
|
||||||
|
pub fn as_str(&self) -> Option<String> {
|
||||||
|
self.message.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) enum Abi {
|
||||||
|
Abi1_47(Abi_1_47),
|
||||||
|
Abi1_55(Abi_1_55),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Abi {
|
||||||
|
/// Load a new ABI.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// *`lib` - The dynamic library containing the macro implementations
|
||||||
|
/// *`symbol_name` - The symbol name the macros can be found attributes
|
||||||
|
/// *`info` - RustCInfo about the compiler that was used to compile the
|
||||||
|
/// macro crate. This is the information we use to figure out
|
||||||
|
/// which ABI to return
|
||||||
|
pub fn from_lib(
|
||||||
|
lib: &Library,
|
||||||
|
symbol_name: String,
|
||||||
|
info: RustCInfo,
|
||||||
|
) -> Result<Abi, LoadProcMacroDylibError> {
|
||||||
|
if info.version.0 != 1 {
|
||||||
|
Err(LoadProcMacroDylibError::UnsupportedABI)
|
||||||
|
} else if info.version.1 < 47 {
|
||||||
|
Err(LoadProcMacroDylibError::UnsupportedABI)
|
||||||
|
} else if info.version.1 < 54 {
|
||||||
|
let inner = unsafe { Abi_1_47::from_lib(lib, symbol_name) }?;
|
||||||
|
Ok(Abi::Abi1_47(inner))
|
||||||
|
} else {
|
||||||
|
let inner = unsafe { Abi_1_55::from_lib(lib, symbol_name) }?;
|
||||||
|
Ok(Abi::Abi1_55(inner))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand(
|
||||||
|
&self,
|
||||||
|
macro_name: &str,
|
||||||
|
macro_body: &tt::Subtree,
|
||||||
|
attributes: Option<&tt::Subtree>,
|
||||||
|
) -> Result<tt::Subtree, PanicMessage> {
|
||||||
|
match self {
|
||||||
|
Self::Abi1_55(abi) => abi.expand(macro_name, macro_body, attributes),
|
||||||
|
Self::Abi1_47(abi) => abi.expand(macro_name, macro_body, attributes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
|
||||||
|
match self {
|
||||||
|
Self::Abi1_47(abi) => abi.list_macros(),
|
||||||
|
Self::Abi1_55(abi) => abi.list_macros(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
//! Handles dynamic library loading for proc macro
|
//! Handles dynamic library loading for proc macro
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::{TryFrom, TryInto},
|
|
||||||
fmt,
|
fmt,
|
||||||
fs::File,
|
fs::File,
|
||||||
io,
|
io,
|
||||||
|
@ -11,16 +10,9 @@ use std::{
|
||||||
use libloading::Library;
|
use libloading::Library;
|
||||||
use memmap2::Mmap;
|
use memmap2::Mmap;
|
||||||
use object::Object;
|
use object::Object;
|
||||||
use proc_macro_api::{read_dylib_info, ProcMacroKind, RustCInfo};
|
use proc_macro_api::{read_dylib_info, ProcMacroKind};
|
||||||
|
|
||||||
use crate::{
|
use super::abis::Abi;
|
||||||
proc_macro::bridge::{self as stable_bridge, client::ProcMacro as StableProcMacro},
|
|
||||||
rustc_server::TokenStream as StableTokenStream,
|
|
||||||
};
|
|
||||||
use crate::{
|
|
||||||
proc_macro_nightly::bridge::{self as nightly_bridge, client::ProcMacro as NightlyProcMacro},
|
|
||||||
rustc_server_nightly::TokenStream as NightlyTokenStream,
|
|
||||||
};
|
|
||||||
|
|
||||||
const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
|
const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
|
||||||
|
|
||||||
|
@ -83,30 +75,10 @@ fn load_library(file: &Path) -> Result<Library, libloading::Error> {
|
||||||
unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) }
|
unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ProcMacroABI {
|
|
||||||
Stable,
|
|
||||||
Nightly,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<RustCInfo> for ProcMacroABI {
|
|
||||||
type Error = LoadProcMacroDylibError;
|
|
||||||
|
|
||||||
fn try_from(info: RustCInfo) -> Result<Self, Self::Error> {
|
|
||||||
if info.version.0 != 1 {
|
|
||||||
Err(LoadProcMacroDylibError::UnsupportedABI)
|
|
||||||
} else if info.version.1 < 47 {
|
|
||||||
Err(LoadProcMacroDylibError::UnsupportedABI)
|
|
||||||
} else if info.version.1 < 54 {
|
|
||||||
Ok(ProcMacroABI::Stable)
|
|
||||||
} else {
|
|
||||||
Ok(ProcMacroABI::Nightly)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LoadProcMacroDylibError {
|
pub enum LoadProcMacroDylibError {
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
|
LibLoading(libloading::Error),
|
||||||
UnsupportedABI,
|
UnsupportedABI,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +87,7 @@ impl fmt::Display for LoadProcMacroDylibError {
|
||||||
match self {
|
match self {
|
||||||
Self::Io(e) => e.fmt(f),
|
Self::Io(e) => e.fmt(f),
|
||||||
Self::UnsupportedABI => write!(f, "unsupported ABI version"),
|
Self::UnsupportedABI => write!(f, "unsupported ABI version"),
|
||||||
|
Self::LibLoading(e) => e.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,15 +98,16 @@ impl From<io::Error> for LoadProcMacroDylibError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ProcMacroLibraryLibloading {
|
impl From<libloading::Error> for LoadProcMacroDylibError {
|
||||||
StableProcMacroLibrary {
|
fn from(e: libloading::Error) -> Self {
|
||||||
_lib: Library,
|
LoadProcMacroDylibError::LibLoading(e)
|
||||||
exported_macros: Vec<crate::proc_macro::bridge::client::ProcMacro>,
|
}
|
||||||
},
|
}
|
||||||
NightlyProcMacroLibrary {
|
|
||||||
_lib: Library,
|
struct ProcMacroLibraryLibloading {
|
||||||
exported_macros: Vec<crate::proc_macro_nightly::bridge::client::ProcMacro>,
|
// Hold on to the library so it doesn't unload
|
||||||
},
|
_lib: Library,
|
||||||
|
abi: Abi,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcMacroLibraryLibloading {
|
impl ProcMacroLibraryLibloading {
|
||||||
|
@ -143,57 +117,10 @@ impl ProcMacroLibraryLibloading {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let version_info = read_dylib_info(file)?;
|
let version_info = read_dylib_info(file)?;
|
||||||
let macro_abi: ProcMacroABI = version_info.try_into()?;
|
|
||||||
|
|
||||||
let lib = load_library(file).map_err(invalid_data_err)?;
|
let lib = load_library(file).map_err(invalid_data_err)?;
|
||||||
match macro_abi {
|
let abi = Abi::from_lib(&lib, symbol_name, version_info)?;
|
||||||
ProcMacroABI::Stable => {
|
Ok(ProcMacroLibraryLibloading { _lib: lib, abi })
|
||||||
let macros: libloading::Symbol<&&[crate::proc_macro::bridge::client::ProcMacro]> =
|
|
||||||
unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
|
|
||||||
let macros_vec = macros.to_vec();
|
|
||||||
Ok(ProcMacroLibraryLibloading::StableProcMacroLibrary {
|
|
||||||
_lib: lib,
|
|
||||||
exported_macros: macros_vec,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ProcMacroABI::Nightly => {
|
|
||||||
let macros: libloading::Symbol<
|
|
||||||
&&[crate::proc_macro_nightly::bridge::client::ProcMacro],
|
|
||||||
> = unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
|
|
||||||
let macros_vec = macros.to_vec();
|
|
||||||
Ok(ProcMacroLibraryLibloading::NightlyProcMacroLibrary {
|
|
||||||
_lib: lib,
|
|
||||||
exported_macros: macros_vec,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum PanicMessage {
|
|
||||||
Stable(stable_bridge::PanicMessage),
|
|
||||||
Nightly(nightly_bridge::PanicMessage),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<stable_bridge::PanicMessage> for PanicMessage {
|
|
||||||
fn from(p: stable_bridge::PanicMessage) -> Self {
|
|
||||||
PanicMessage::Stable(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<nightly_bridge::PanicMessage> for PanicMessage {
|
|
||||||
fn from(p: nightly_bridge::PanicMessage) -> Self {
|
|
||||||
PanicMessage::Nightly(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PanicMessage {
|
|
||||||
pub fn as_str(&self) -> Option<&str> {
|
|
||||||
match self {
|
|
||||||
Self::Stable(p) => p.as_str(),
|
|
||||||
Self::Nightly(p) => p.as_str(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,28 +146,13 @@ impl Expander {
|
||||||
macro_name: &str,
|
macro_name: &str,
|
||||||
macro_body: &tt::Subtree,
|
macro_body: &tt::Subtree,
|
||||||
attributes: Option<&tt::Subtree>,
|
attributes: Option<&tt::Subtree>,
|
||||||
) -> Result<tt::Subtree, PanicMessage> {
|
) -> Result<tt::Subtree, String> {
|
||||||
match &self.inner {
|
let result = self.inner.abi.expand(macro_name, macro_body, attributes);
|
||||||
ProcMacroLibraryLibloading::StableProcMacroLibrary { exported_macros, .. } => {
|
result.map_err(|e| e.as_str().unwrap_or_else(|| "<unknown error>".to_string()))
|
||||||
expand_stable(macro_name, macro_body, attributes, &exported_macros[..])
|
|
||||||
.map_err(PanicMessage::from)
|
|
||||||
}
|
|
||||||
ProcMacroLibraryLibloading::NightlyProcMacroLibrary { exported_macros, .. } => {
|
|
||||||
expand_nightly(macro_name, macro_body, attributes, &exported_macros[..])
|
|
||||||
.map_err(PanicMessage::from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
|
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
|
||||||
match &self.inner {
|
self.inner.abi.list_macros()
|
||||||
ProcMacroLibraryLibloading::StableProcMacroLibrary { exported_macros, .. } => {
|
|
||||||
list_macros_stable(&exported_macros[..])
|
|
||||||
}
|
|
||||||
ProcMacroLibraryLibloading::NightlyProcMacroLibrary { exported_macros, .. } => {
|
|
||||||
list_macros_nightly(&exported_macros[..])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,153 +188,3 @@ fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
|
||||||
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
|
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
|
||||||
Ok(path.to_path_buf())
|
Ok(path.to_path_buf())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_nightly(
|
|
||||||
macro_name: &str,
|
|
||||||
macro_body: &tt::Subtree,
|
|
||||||
attributes: Option<&tt::Subtree>,
|
|
||||||
macros: &[NightlyProcMacro],
|
|
||||||
) -> Result<tt::Subtree, crate::proc_macro_nightly::bridge::PanicMessage> {
|
|
||||||
let parsed_body = NightlyTokenStream::with_subtree(macro_body.clone());
|
|
||||||
|
|
||||||
let parsed_attributes = attributes
|
|
||||||
.map_or(crate::rustc_server_nightly::TokenStream::new(), |attr| {
|
|
||||||
NightlyTokenStream::with_subtree(attr.clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
for proc_macro in macros {
|
|
||||||
match proc_macro {
|
|
||||||
crate::proc_macro_nightly::bridge::client::ProcMacro::CustomDerive {
|
|
||||||
trait_name,
|
|
||||||
client,
|
|
||||||
..
|
|
||||||
} if *trait_name == macro_name => {
|
|
||||||
let res = client.run(
|
|
||||||
&crate::proc_macro_nightly::bridge::server::SameThread,
|
|
||||||
crate::rustc_server_nightly::Rustc::default(),
|
|
||||||
parsed_body,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
return res.map(|it| it.into_subtree());
|
|
||||||
}
|
|
||||||
crate::proc_macro_nightly::bridge::client::ProcMacro::Bang { name, client }
|
|
||||||
if *name == macro_name =>
|
|
||||||
{
|
|
||||||
let res = client.run(
|
|
||||||
&crate::proc_macro_nightly::bridge::server::SameThread,
|
|
||||||
crate::rustc_server_nightly::Rustc::default(),
|
|
||||||
parsed_body,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
return res.map(|it| it.into_subtree());
|
|
||||||
}
|
|
||||||
crate::proc_macro_nightly::bridge::client::ProcMacro::Attr { name, client }
|
|
||||||
if *name == macro_name =>
|
|
||||||
{
|
|
||||||
let res = client.run(
|
|
||||||
&crate::proc_macro_nightly::bridge::server::SameThread,
|
|
||||||
crate::rustc_server_nightly::Rustc::default(),
|
|
||||||
parsed_attributes,
|
|
||||||
parsed_body,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
return res.map(|it| it.into_subtree());
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(crate::proc_macro_nightly::bridge::PanicMessage::String("Nothing to expand".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expand_stable(
|
|
||||||
macro_name: &str,
|
|
||||||
macro_body: &tt::Subtree,
|
|
||||||
attributes: Option<&tt::Subtree>,
|
|
||||||
macros: &[StableProcMacro],
|
|
||||||
) -> Result<tt::Subtree, crate::proc_macro::bridge::PanicMessage> {
|
|
||||||
let parsed_body = StableTokenStream::with_subtree(macro_body.clone());
|
|
||||||
|
|
||||||
let parsed_attributes = attributes.map_or(crate::rustc_server::TokenStream::new(), |attr| {
|
|
||||||
StableTokenStream::with_subtree(attr.clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
for proc_macro in macros {
|
|
||||||
match proc_macro {
|
|
||||||
crate::proc_macro::bridge::client::ProcMacro::CustomDerive {
|
|
||||||
trait_name,
|
|
||||||
client,
|
|
||||||
..
|
|
||||||
} if *trait_name == macro_name => {
|
|
||||||
let res = client.run(
|
|
||||||
&crate::proc_macro::bridge::server::SameThread,
|
|
||||||
crate::rustc_server::Rustc::default(),
|
|
||||||
parsed_body,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
return res.map(|it| it.into_subtree());
|
|
||||||
}
|
|
||||||
crate::proc_macro::bridge::client::ProcMacro::Bang { name, client }
|
|
||||||
if *name == macro_name =>
|
|
||||||
{
|
|
||||||
let res = client.run(
|
|
||||||
&crate::proc_macro::bridge::server::SameThread,
|
|
||||||
crate::rustc_server::Rustc::default(),
|
|
||||||
parsed_body,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
return res.map(|it| it.into_subtree());
|
|
||||||
}
|
|
||||||
crate::proc_macro::bridge::client::ProcMacro::Attr { name, client }
|
|
||||||
if *name == macro_name =>
|
|
||||||
{
|
|
||||||
let res = client.run(
|
|
||||||
&crate::proc_macro::bridge::server::SameThread,
|
|
||||||
crate::rustc_server::Rustc::default(),
|
|
||||||
parsed_attributes,
|
|
||||||
parsed_body,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
return res.map(|it| it.into_subtree());
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(crate::proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_macros_stable(macros: &[StableProcMacro]) -> Vec<(String, ProcMacroKind)> {
|
|
||||||
macros
|
|
||||||
.iter()
|
|
||||||
.map(|proc_macro| match proc_macro {
|
|
||||||
crate::proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
|
|
||||||
(trait_name.to_string(), ProcMacroKind::CustomDerive)
|
|
||||||
}
|
|
||||||
crate::proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
|
|
||||||
(name.to_string(), ProcMacroKind::FuncLike)
|
|
||||||
}
|
|
||||||
crate::proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
|
|
||||||
(name.to_string(), ProcMacroKind::Attr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_macros_nightly(macros: &[NightlyProcMacro]) -> Vec<(String, ProcMacroKind)> {
|
|
||||||
macros
|
|
||||||
.iter()
|
|
||||||
.map(|proc_macro| match proc_macro {
|
|
||||||
crate::proc_macro_nightly::bridge::client::ProcMacro::CustomDerive {
|
|
||||||
trait_name,
|
|
||||||
..
|
|
||||||
} => (trait_name.to_string(), ProcMacroKind::CustomDerive),
|
|
||||||
crate::proc_macro_nightly::bridge::client::ProcMacro::Bang { name, .. } => {
|
|
||||||
(name.to_string(), ProcMacroKind::FuncLike)
|
|
||||||
}
|
|
||||||
crate::proc_macro_nightly::bridge::client::ProcMacro::Attr { name, .. } => {
|
|
||||||
(name.to_string(), ProcMacroKind::Attr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,23 +11,10 @@
|
||||||
//! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)…
|
//! rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)…
|
||||||
#![allow(unreachable_pub)]
|
#![allow(unreachable_pub)]
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
mod proc_macro;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
mod proc_macro_nightly;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
mod rustc_server;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
mod rustc_server_nightly;
|
|
||||||
|
|
||||||
mod dylib;
|
mod dylib;
|
||||||
|
|
||||||
use proc_macro::bridge::client::TokenStream;
|
mod abis;
|
||||||
|
|
||||||
use proc_macro_api::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
|
use proc_macro_api::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::{hash_map::Entry, HashMap},
|
||||||
|
@ -62,10 +49,7 @@ impl ProcMacroSrv {
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(expansion) => Ok(ExpansionResult { expansion }),
|
Ok(expansion) => Ok(ExpansionResult { expansion }),
|
||||||
Err(msg) => {
|
Err(msg) => Err(format!("proc-macro panicked: {}", msg)),
|
||||||
let msg = msg.as_str().unwrap_or("<unknown error>");
|
|
||||||
Err(format!("proc-macro panicked: {}", msg))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,14 @@ pub mod fixtures {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_string(code: &str) -> Option<crate::rustc_server::TokenStream> {
|
fn parse_string(code: &str) -> Option<crate::abis::abi_1_47::TokenStream> {
|
||||||
Some(crate::rustc_server::TokenStream::from_str(code).unwrap())
|
// This is a bit strange. We need to parse a string into a token stream into
|
||||||
|
// order to create a tt::SubTree from it in fixtures. `into_subtree` is
|
||||||
|
// implemented by all the ABIs we have so we arbitrarily choose one ABI to
|
||||||
|
// write a `parse_string` function for and use that. The tests don't really
|
||||||
|
// care which ABI we're using as the `into_subtree` function isn't part of
|
||||||
|
// the ABI and shouldn't change between ABI versions.
|
||||||
|
crate::abis::abi_1_47::TokenStream::from_str(code).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_expand(macro_name: &str, ra_fixture: &str, expect: Expect) {
|
pub fn assert_expand(macro_name: &str, ra_fixture: &str, expect: Expect) {
|
||||||
|
|
Loading…
Reference in a new issue