Skip to content

Commit

Permalink
Merge pull request #6 from thiolliere/gui-fix-spans
Browse files Browse the repository at this point in the history
Fix spans by using arguments blocks instead of single string
  • Loading branch information
sam0x17 committed Jun 6, 2023
2 parents 907eb27 + 9d9d84b commit bdcf6b1
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 63 deletions.
139 changes: 77 additions & 62 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#![no_std]
extern crate alloc;
use core::fmt::Display;

use alloc::{
format,
Expand All @@ -17,14 +16,18 @@ use libc_print::libc_println as println;

use derive_syn_parse::Parse;
use macro_magic_core_macros::*;
use proc_macro2::{Punct, Spacing, Span, TokenStream as TokenStream2};
use quote::{format_ident, quote, ToTokens};
use proc_macro2::{Delimiter, Group, Punct, Spacing, Span, TokenStream as TokenStream2};
use quote::{format_ident, quote, ToTokens, TokenStreamExt};
use syn::{
parse::Nothing, parse2, parse_quote, spanned::Spanned, token::Comma, Attribute, Error, FnArg,
Ident, Item, ItemFn, LitStr, Pat, Path, Result, Token, Visibility,
parse::Nothing,
parse2, parse_quote,
spanned::Spanned,
token::{Brace, Comma},
Attribute, Error, FnArg, Ident, Item, ItemFn, Pat, Path, Result, Token, Visibility,
};

pub const MACRO_MAGIC_ROOT: &'static str = get_macro_magic_root!();
pub use proc_macro2::TokenTree as TokenTree2;

/// Private module containing custom keywords used for parsing in this crate
mod keywords {
Expand All @@ -38,6 +41,25 @@ mod keywords {
custom_keyword!(__private_macro_magic_tokens_forwarded);
}

/// Used to parse args that were passed to [`forward_tokens_internal`] and
/// [`forward_tokens_inner_internal`].
///
/// You shouldn't need to use this directly.
#[derive(Parse)]
pub struct ForwardTokensExtraArg {
#[brace]
_brace: Brace,
#[inside(_brace)]
pub stream: TokenStream2,
}

impl ToTokens for ForwardTokensExtraArg {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let token = Group::new(Delimiter::Brace, self.stream.clone());
tokens.append(token);
}
}

/// Used to parse args that were passed to [`forward_tokens_internal`].
///
/// You shouldn't need to use this directly.
Expand All @@ -52,11 +74,11 @@ pub struct ForwardTokensArgs {
#[parse_if(_comma2.is_some())]
pub mm_path: Option<Path>,
_comma3: Option<Comma>,
/// Optional extra data. This is how [`import_tokens_attr_internal`] passes the item the
/// attribute macro is attached to, but this can be repurposed for other things potentially as
/// it wraps a token stream.
#[parse_if(_comma3.is_some())]
/// Optional extra data that can be passed as a [`struct@LitStr`]. This is how
/// [`import_tokens_attr_internal`] passes the item the attribute macro is attached to, but
/// this can be repurposed for other things potentially as [`str`] could encode anything.
pub extra: Option<LitStr>,
pub extra: Option<ForwardTokensExtraArg>,
}

/// Used to parse args that were passed to [`forward_tokens_inner_internal`].
Expand All @@ -70,11 +92,11 @@ pub struct ForwardedTokens {
/// The item whose tokens are being forwarded
pub item: Item,
_comma2: Option<Comma>,
/// Optional extra data. This is how [`import_tokens_attr_internal`] passes the item the
/// attribute macro is attached to, but this can be repurposed for other things potentially as
/// it wraps a token stream.
#[parse_if(_comma2.is_some())]
/// Optional extra data that can be passed as a [`struct@LitStr`]. This is how
/// [`import_tokens_attr_internal`] passes the item the attribute macro is attached to, but
/// this can be repurposed for other things potentially as [`str`] could encode anything.
pub extra: Option<LitStr>,
pub extra: Option<ForwardTokensExtraArg>,
}

/// Used to parse args passed to the inner pro macro auto-generated by
Expand All @@ -84,8 +106,28 @@ pub struct ForwardedTokens {
#[derive(Parse)]
pub struct AttrItemWithExtra {
pub imported_item: Item,
_comma: Comma,
pub extra: LitStr,
_comma1: Comma,
#[brace]
_brace: Brace,
#[brace]
#[inside(_brace)]
_tokens_ident_brace: Brace,
#[inside(_tokens_ident_brace)]
pub tokens_ident: TokenStream2,
#[inside(_brace)]
_comma2: Comma,
#[brace]
#[inside(_brace)]
_source_path_brace: Brace,
#[inside(_source_path_brace)]
pub source_path: TokenStream2,
#[inside(_brace)]
_comma3: Comma,
#[brace]
#[inside(_brace)]
_custom_tokens_brace: Brace,
#[inside(_custom_tokens_brace)]
pub custom_tokens: TokenStream2,
}

/// Used to parse the args for the [`import_tokens_internal`] function.
Expand Down Expand Up @@ -363,27 +405,6 @@ pub fn to_snake_case(input: impl Into<String>) -> String {
output.iter().collect::<String>()
}

/// Converts a string-like value (via [`Display`]) such that the sequence `~~` is safely escaped
/// so that `~~` can be used as a list delimiter.
///
/// Used by [`forward_tokens_internal`] to escape items appearing in the `extra` variable.
pub fn escape_extra<T: Display>(extra: T) -> String {
extra
.to_string()
.replace("\\", "\\\\")
.replace("~~", "\\~\\~")
}

/// Unescapes a `String` that has been escaped via [`escape_extra`].
///
/// Used by [`forward_tokens_internal`] to unescape items appearing in the `extra` variable.
pub fn unescape_extra<T: Display>(extra: T) -> String {
extra
.to_string()
.replace("\\\\", "\\")
.replace("\\~\\~", "~~")
}

/// "Flattens" an [`struct@Ident`] by converting it to snake case.
///
/// Used by [`export_tokens_macro_ident`].
Expand Down Expand Up @@ -460,11 +481,15 @@ pub fn export_tokens_internal<T: Into<TokenStream2>, E: Into<TokenStream2>>(
#[macro_export]
macro_rules! #ident {
// arm with extra support (used by attr)
($(::)?$($tokens_var:ident)::*, $(::)?$($callback:ident)::*, $extra:expr) => {
(
$(::)?$($tokens_var:ident)::*,
$(::)?$($callback:ident)::*,
{ $( $extra:tt )* }
) => {
$($callback)::*! {
$($tokens_var)::*,
#item,
$extra
{ $( $extra )* }
}
};
// regular arm (used by proc, import_tokens, etc)
Expand Down Expand Up @@ -756,22 +781,12 @@ pub fn import_tokens_attr_internal<T1: Into<TokenStream2>, T2: Into<TokenStream2
pub #orig_sig {
pub #inner_sig {
let __combined_args = #mm_path::__private::syn::parse_macro_input!(#attr_ident as #mm_path::mm_core::AttrItemWithExtra);
let (#attr_ident, #tokens_ident) = (__combined_args.imported_item, __combined_args.extra);
let #attr_ident: proc_macro::TokenStream = #attr_ident.to_token_stream().into();
let (#tokens_ident, __source_path, __custom_tokens) = {
use #mm_path::mm_core::unescape_extra;
let extra = #tokens_ident.value();
let mut extra_split = extra.split("~~");
let (tokens_string, foreign_path_string, custom_parsed_string) = (
unescape_extra(extra_split.next().unwrap()),
unescape_extra(extra_split.next().unwrap()),
unescape_extra(extra_split.next().unwrap()),
);
let foreign_path: proc_macro::TokenStream = foreign_path_string.as_str().parse().unwrap();
let tokens: proc_macro::TokenStream = tokens_string.as_str().parse().unwrap();
let custom_parsed_tokens: proc_macro::TokenStream = custom_parsed_string.as_str().parse().unwrap();
(tokens, foreign_path, custom_parsed_tokens)
};

let #attr_ident: proc_macro::TokenStream = __combined_args.imported_item.to_token_stream().into();
let #tokens_ident: proc_macro::TokenStream = __combined_args.tokens_ident.into();
let __source_path: proc_macro::TokenStream = __combined_args.source_path.into();
let __custom_tokens: proc_macro::TokenStream = __combined_args.custom_tokens.into();

#(#orig_stmts)
*
}
Expand All @@ -794,20 +809,20 @@ pub fn import_tokens_attr_internal<T1: Into<TokenStream2>, T2: Into<TokenStream2
#inner_macro_ident(attr_minus_first_token)
} else {
let attached_item = syn::parse_macro_input!(#tokens_ident as syn::Item);
let attached_item_str = attached_item.to_token_stream().to_string();
let attached_item = attached_item.to_token_stream();
#path_resolver
let extra = format!(
"{}~~{}~~{}",
escape_extra(attached_item_str),
escape_extra(path.to_token_stream().to_string().as_str()),
escape_extra(custom_parsed.to_token_stream().to_string().as_str())
);
let path = path.to_token_stream();
let custon_parsed = custom_parsed.to_token_stream();
quote::quote! {
#mm_override_path::forward_tokens! {
#pound path,
#orig_sig_ident,
#mm_override_path,
#pound extra
{
{ #pound attached_item },
{ #pound path },
{ #pound custom_parsed }
}
}
}.into()
}
Expand Down
6 changes: 5 additions & 1 deletion tests/isolated_crate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ use middle_crate::distant_re_export_attr;
use middle_crate::distant_re_export_proc;

#[distant_re_export_attr(middle_crate::ForeignItem)]
struct AttachedItem {}
struct AttachedItem {
// TODO: implement as UI test maybe
// Uncomment and see the error message with span
// foo: unresolved_path
}

#[test]
fn test_distant_re_export_attr() {
Expand Down

0 comments on commit bdcf6b1

Please sign in to comment.