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>
|
||||
//! augmented with removing unstable features
|
||||
|
||||
use super::super::TokenStream as CrateTokenStream;
|
||||
use super::*;
|
||||
|
||||
macro_rules! define_handles {
|
||||
|
@ -401,26 +402,26 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
|||
b
|
||||
}
|
||||
|
||||
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
||||
pub fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
|
||||
impl Client<fn(CrateTokenStream) -> CrateTokenStream> {
|
||||
pub fn expand1(f: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||
extern "C" fn run(
|
||||
bridge: Bridge<'_>,
|
||||
f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
|
||||
f: impl FnOnce(CrateTokenStream) -> CrateTokenStream,
|
||||
) -> 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 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
|
||||
pub fn expand2(f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream) -> Self {
|
||||
impl Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream> {
|
||||
pub fn expand2(f: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||
extern "C" fn run(
|
||||
bridge: Bridge<'_>,
|
||||
f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
||||
f: impl FnOnce(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||
) -> Buffer<u8> {
|
||||
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 }
|
||||
|
@ -433,17 +434,17 @@ pub enum ProcMacro {
|
|||
CustomDerive {
|
||||
trait_name: &'static str,
|
||||
attributes: &'static [&'static str],
|
||||
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
|
||||
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
|
||||
},
|
||||
|
||||
Attr {
|
||||
name: &'static str,
|
||||
client: Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream>,
|
||||
client: Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream>,
|
||||
},
|
||||
|
||||
Bang {
|
||||
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(
|
||||
trait_name: &'static str,
|
||||
attributes: &'static [&'static str],
|
||||
expand: fn(crate::TokenStream) -> crate::TokenStream,
|
||||
expand: fn(CrateTokenStream) -> CrateTokenStream,
|
||||
) -> Self {
|
||||
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
|
||||
}
|
||||
|
||||
pub fn attr(
|
||||
name: &'static str,
|
||||
expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
||||
expand: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||
) -> Self {
|
||||
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) }
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
pub use crate::proc_macro::{Delimiter, Level, LineColumn, Spacing};
|
||||
pub use super::{Delimiter, Level, LineColumn, Spacing};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::marker;
|
|
@ -3,6 +3,7 @@
|
|||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
|
||||
//! augmented with removing unstable features
|
||||
|
||||
use super::super::TokenStream as ProcMacroTokenStream;
|
||||
use super::*;
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
||||
impl client::Client<fn(ProcMacroTokenStream) -> ProcMacroTokenStream> {
|
||||
pub fn run<S: Server>(
|
||||
&self,
|
||||
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>(
|
||||
&self,
|
||||
strategy: &impl ExecutionStrategy,
|
|
@ -133,7 +133,7 @@ impl Extend<TokenStream> for TokenStream {
|
|||
|
||||
/// Public implementation details for the `TokenStream` type, such as iterators.
|
||||
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.
|
||||
/// 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
|
||||
|
||||
use crate::proc_macro::bridge::{self, server};
|
||||
use super::proc_macro::bridge::{self, server};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
@ -97,9 +97,9 @@ impl Extend<TokenStream> for TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
type Level = crate::proc_macro::Level;
|
||||
type LineColumn = crate::proc_macro::LineColumn;
|
||||
type SourceFile = crate::proc_macro::SourceFile;
|
||||
type Level = super::proc_macro::Level;
|
||||
type LineColumn = super::proc_macro::LineColumn;
|
||||
type SourceFile = super::proc_macro::SourceFile;
|
||||
|
||||
/// A structure representing a diagnostic message and associated children
|
||||
/// messages.
|
||||
|
@ -734,8 +734,8 @@ impl server::MultiSpan for Rustc {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::proc_macro::bridge::server::Literal;
|
||||
use super::*;
|
||||
use crate::proc_macro::bridge::server::Literal;
|
||||
|
||||
#[test]
|
||||
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>
|
||||
//! augmented with removing unstable features
|
||||
|
||||
use super::super::TokenStream as CrateTokenStream;
|
||||
use super::*;
|
||||
|
||||
macro_rules! define_handles {
|
||||
|
@ -401,26 +402,26 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
|
|||
b
|
||||
}
|
||||
|
||||
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
||||
pub fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
|
||||
impl Client<fn(CrateTokenStream) -> CrateTokenStream> {
|
||||
pub fn expand1(f: fn(CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||
extern "C" fn run(
|
||||
bridge: Bridge<'_>,
|
||||
f: impl FnOnce(crate::TokenStream) -> crate::TokenStream,
|
||||
f: impl FnOnce(CrateTokenStream) -> CrateTokenStream,
|
||||
) -> 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 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
|
||||
pub fn expand2(f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream) -> Self {
|
||||
impl Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream> {
|
||||
pub fn expand2(f: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream) -> Self {
|
||||
extern "C" fn run(
|
||||
bridge: Bridge<'_>,
|
||||
f: impl FnOnce(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
||||
f: impl FnOnce(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||
) -> Buffer<u8> {
|
||||
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 }
|
||||
|
@ -433,17 +434,17 @@ pub enum ProcMacro {
|
|||
CustomDerive {
|
||||
trait_name: &'static str,
|
||||
attributes: &'static [&'static str],
|
||||
client: Client<fn(crate::TokenStream) -> crate::TokenStream>,
|
||||
client: Client<fn(CrateTokenStream) -> CrateTokenStream>,
|
||||
},
|
||||
|
||||
Attr {
|
||||
name: &'static str,
|
||||
client: Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream>,
|
||||
client: Client<fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream>,
|
||||
},
|
||||
|
||||
Bang {
|
||||
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(
|
||||
trait_name: &'static str,
|
||||
attributes: &'static [&'static str],
|
||||
expand: fn(crate::TokenStream) -> crate::TokenStream,
|
||||
expand: fn(CrateTokenStream) -> CrateTokenStream,
|
||||
) -> Self {
|
||||
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
|
||||
}
|
||||
|
||||
pub fn attr(
|
||||
name: &'static str,
|
||||
expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
|
||||
expand: fn(CrateTokenStream, CrateTokenStream) -> CrateTokenStream,
|
||||
) -> Self {
|
||||
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) }
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/server.rs>
|
||||
//! augmented with removing unstable features
|
||||
|
||||
use super::super::TokenStream as CrateTokenStream;
|
||||
use super::*;
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
impl client::Client<fn(crate::TokenStream) -> crate::TokenStream> {
|
||||
impl client::Client<fn(CrateTokenStream) -> CrateTokenStream> {
|
||||
pub fn run<S: Server>(
|
||||
&self,
|
||||
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>(
|
||||
&self,
|
||||
strategy: &impl ExecutionStrategy,
|
|
@ -3,7 +3,7 @@
|
|||
//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/diagnostic.rs>
|
||||
//! augmented with removing unstable features
|
||||
|
||||
use crate::proc_macro::Span;
|
||||
use super::Span;
|
||||
|
||||
/// An enum representing a diagnostic level.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -146,15 +146,15 @@ impl Diagnostic {
|
|||
|
||||
/// Emit the diagnostic.
|
||||
pub fn emit(self) {
|
||||
fn to_internal(spans: Vec<Span>) -> crate::proc_macro::bridge::client::MultiSpan {
|
||||
let mut multi_span = crate::proc_macro::bridge::client::MultiSpan::new();
|
||||
fn to_internal(spans: Vec<Span>) -> super::bridge::client::MultiSpan {
|
||||
let mut multi_span = super::bridge::client::MultiSpan::new();
|
||||
for span in spans {
|
||||
multi_span.push(span.0);
|
||||
}
|
||||
multi_span
|
||||
}
|
||||
|
||||
let mut diag = crate::proc_macro::bridge::client::Diagnostic::new(
|
||||
let mut diag = super::bridge::client::Diagnostic::new(
|
||||
self.level,
|
||||
&self.message[..],
|
||||
to_internal(self.spans),
|
|
@ -8,7 +8,7 @@
|
|||
//!
|
||||
//! 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::hash::Hash;
|
||||
|
@ -97,9 +97,9 @@ impl Extend<TokenStream> for TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
type Level = crate::proc_macro_nightly::Level;
|
||||
type LineColumn = crate::proc_macro_nightly::LineColumn;
|
||||
type SourceFile = crate::proc_macro_nightly::SourceFile;
|
||||
type Level = super::proc_macro::Level;
|
||||
type LineColumn = super::proc_macro::LineColumn;
|
||||
type SourceFile = super::proc_macro::SourceFile;
|
||||
|
||||
/// A structure representing a diagnostic message and associated children
|
||||
/// messages.
|
||||
|
@ -737,8 +737,8 @@ impl server::MultiSpan for Rustc {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::proc_macro::bridge::server::Literal;
|
||||
use super::*;
|
||||
use crate::proc_macro_nightly::bridge::server::Literal;
|
||||
|
||||
#[test]
|
||||
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
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
fs::File,
|
||||
io,
|
||||
|
@ -11,16 +10,9 @@ use std::{
|
|||
use libloading::Library;
|
||||
use memmap2::Mmap;
|
||||
use object::Object;
|
||||
use proc_macro_api::{read_dylib_info, ProcMacroKind, RustCInfo};
|
||||
use proc_macro_api::{read_dylib_info, ProcMacroKind};
|
||||
|
||||
use crate::{
|
||||
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,
|
||||
};
|
||||
use super::abis::Abi;
|
||||
|
||||
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()) }
|
||||
}
|
||||
|
||||
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)]
|
||||
pub enum LoadProcMacroDylibError {
|
||||
Io(io::Error),
|
||||
LibLoading(libloading::Error),
|
||||
UnsupportedABI,
|
||||
}
|
||||
|
||||
|
@ -115,6 +87,7 @@ impl fmt::Display for LoadProcMacroDylibError {
|
|||
match self {
|
||||
Self::Io(e) => e.fmt(f),
|
||||
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 {
|
||||
StableProcMacroLibrary {
|
||||
_lib: Library,
|
||||
exported_macros: Vec<crate::proc_macro::bridge::client::ProcMacro>,
|
||||
},
|
||||
NightlyProcMacroLibrary {
|
||||
_lib: Library,
|
||||
exported_macros: Vec<crate::proc_macro_nightly::bridge::client::ProcMacro>,
|
||||
},
|
||||
impl From<libloading::Error> for LoadProcMacroDylibError {
|
||||
fn from(e: libloading::Error) -> Self {
|
||||
LoadProcMacroDylibError::LibLoading(e)
|
||||
}
|
||||
}
|
||||
|
||||
struct ProcMacroLibraryLibloading {
|
||||
// Hold on to the library so it doesn't unload
|
||||
_lib: Library,
|
||||
abi: Abi,
|
||||
}
|
||||
|
||||
impl ProcMacroLibraryLibloading {
|
||||
|
@ -143,57 +117,10 @@ impl ProcMacroLibraryLibloading {
|
|||
})?;
|
||||
|
||||
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)?;
|
||||
match macro_abi {
|
||||
ProcMacroABI::Stable => {
|
||||
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(),
|
||||
}
|
||||
let abi = Abi::from_lib(&lib, symbol_name, version_info)?;
|
||||
Ok(ProcMacroLibraryLibloading { _lib: lib, abi })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,28 +146,13 @@ impl Expander {
|
|||
macro_name: &str,
|
||||
macro_body: &tt::Subtree,
|
||||
attributes: Option<&tt::Subtree>,
|
||||
) -> Result<tt::Subtree, PanicMessage> {
|
||||
match &self.inner {
|
||||
ProcMacroLibraryLibloading::StableProcMacroLibrary { exported_macros, .. } => {
|
||||
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)
|
||||
}
|
||||
}
|
||||
) -> Result<tt::Subtree, String> {
|
||||
let result = self.inner.abi.expand(macro_name, macro_body, attributes);
|
||||
result.map_err(|e| e.as_str().unwrap_or_else(|| "<unknown error>".to_string()))
|
||||
}
|
||||
|
||||
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
|
||||
match &self.inner {
|
||||
ProcMacroLibraryLibloading::StableProcMacroLibrary { exported_macros, .. } => {
|
||||
list_macros_stable(&exported_macros[..])
|
||||
}
|
||||
ProcMacroLibraryLibloading::NightlyProcMacroLibrary { exported_macros, .. } => {
|
||||
list_macros_nightly(&exported_macros[..])
|
||||
}
|
||||
}
|
||||
self.inner.abi.list_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> {
|
||||
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)…
|
||||
#![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;
|
||||
|
||||
use proc_macro::bridge::client::TokenStream;
|
||||
mod abis;
|
||||
|
||||
use proc_macro_api::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap},
|
||||
|
@ -62,10 +49,7 @@ impl ProcMacroSrv {
|
|||
|
||||
match result {
|
||||
Ok(expansion) => Ok(ExpansionResult { expansion }),
|
||||
Err(msg) => {
|
||||
let msg = msg.as_str().unwrap_or("<unknown error>");
|
||||
Err(format!("proc-macro panicked: {}", msg))
|
||||
}
|
||||
Err(msg) => Err(format!("proc-macro panicked: {}", msg)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,14 @@ pub mod fixtures {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_string(code: &str) -> Option<crate::rustc_server::TokenStream> {
|
||||
Some(crate::rustc_server::TokenStream::from_str(code).unwrap())
|
||||
fn parse_string(code: &str) -> Option<crate::abis::abi_1_47::TokenStream> {
|
||||
// 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) {
|
||||
|
|
Loading…
Reference in a new issue