Vendor things

This commit is contained in:
John Doty 2024-03-08 11:03:01 -08:00
parent 5deceec006
commit 977e3c17e5
19434 changed files with 10682014 additions and 0 deletions

View file

@ -0,0 +1,36 @@
//!
//!
use super::SpanExt;
use proc_macro2::Span;
use syn::punctuated::Pair;
use syn::*;
/// Creates a comment from `s`.
pub fn comment<S>(s: S) -> Attribute
where
S: AsRef<str>,
{
let span = Span::call_site();
Attribute {
style: AttrStyle::Outer,
bracket_token: span.as_token(),
pound_token: span.as_token(),
meta: Meta::NameValue(MetaNameValue {
path: Path {
leading_colon: None,
segments: vec![Pair::End(PathSegment {
ident: Ident::new("doc", span),
arguments: Default::default(),
})]
.into_iter()
.collect(),
},
eq_token: span.as_token(),
value: Expr::Lit(ExprLit {
attrs: Default::default(),
lit: Lit::Str(LitStr::new(s.as_ref(), span)),
}),
}),
}
}

62
third-party/vendor/pmutil/src/lib.rs vendored Normal file
View file

@ -0,0 +1,62 @@
//! Utils for implementing proc-macro. Works on stable.
//!
//!
//!
#![recursion_limit = "128"]
extern crate proc_macro;
pub use proc_macro2;
pub use quote;
pub use syn;
pub use self::span_ext::SpanExt;
use proc_macro2::TokenStream;
use quote::ToTokens;
pub use spanned_quote::Quote;
use syn::Ident;
pub mod comment;
pub mod prelude;
pub mod respan;
mod span_ext;
pub mod spanned_quote;
pub mod synom_ext;
/// Extension trait for [syn::Ident][].
///
///
///[syn::Ident]:../syn/struct.Ident.html
pub trait IdentExt {
/// Creates a new ident with same span by applying `map` to `self`.
fn new_ident_with<F, S>(&self, map: F) -> Ident
where
F: for<'a> FnOnce(&'a str) -> S,
S: AsRef<str>;
}
impl IdentExt for Ident {
/// Creates a new ident with same span by applying `map` to `self`.
fn new_ident_with<F, S>(&self, map: F) -> Ident
where
F: for<'a> FnOnce(&'a str) -> S,
S: AsRef<str>,
{
Ident::new(map(&format!("{self}")).as_ref(), self.span())
}
}
pub trait ToTokensExt: ToTokens {
fn dump(&self) -> TokenStream {
let mut tmp = TokenStream::new();
self.to_tokens(&mut tmp);
tmp
}
/// Usage: `Quote::new(body.first_last())`
fn first_last(&self) -> respan::FirstLast {
respan::FirstLast::from_tokens(&self)
}
}
impl<T: ToTokens> ToTokensExt for T {}

View file

@ -0,0 +1,6 @@
//! Prelude for convenience.
pub use super::comment::comment;
pub use super::spanned_quote::Quote;
pub use super::{IdentExt, SpanExt, ToTokensExt};
pub use crate::{q, smart_quote};

76
third-party/vendor/pmutil/src/respan.rs vendored Normal file
View file

@ -0,0 +1,76 @@
//! Span support for quasi-quotting.
use proc_macro2::{Span, TokenStream, TokenTree};
use quote::ToTokens;
use std::cell::Cell;
pub trait Respan {
/// Used while quasi quotting.
fn next_span(&self) -> Span;
fn respan(&self, mut tt: TokenTree) -> TokenTree {
let span = self.next_span();
match tt {
TokenTree::Group(ref mut tt) => tt.set_span(span),
TokenTree::Ident(ref mut tt) => tt.set_span(span),
TokenTree::Punct(ref mut tt) => tt.set_span(span),
TokenTree::Literal(ref mut tt) => tt.set_span(span),
}
tt
}
}
impl Respan for Span {
fn next_span(&self) -> Span {
*self
}
}
impl<'a, S> Respan for &'a S
where
S: ?Sized + Respan,
{
fn next_span(&self) -> Span {
<S as Respan>::next_span(self)
}
}
impl<S> Respan for Box<S>
where
S: ?Sized + Respan,
{
fn next_span(&self) -> Span {
<S as Respan>::next_span(self)
}
}
#[derive(Debug, Clone)]
pub struct FirstLast {
first: Cell<Option<Span>>,
last: Span,
}
impl Respan for FirstLast {
fn next_span(&self) -> Span {
// Default value of Option<_> is None, so Cell<Option<_>>.take() works
self.first.take().unwrap_or(self.last)
}
}
impl FirstLast {
pub fn from_tokens(tokens: &dyn ToTokens) -> Self {
let mut spans = TokenStream::new();
tokens.to_tokens(&mut spans);
let good_tokens = spans.into_iter().collect::<Vec<_>>();
let first_span = good_tokens
.first()
.map(|t| t.span())
.unwrap_or(Span::call_site());
let last = good_tokens.last().map(|t| t.span()).unwrap_or(first_span);
FirstLast {
first: Cell::new(Some(first_span)),
last,
}
}
}

View file

@ -0,0 +1,32 @@
use crate::synom_ext::FromSpan;
use proc_macro2::Span;
/// Extension trait for [Span][] and [syn::Span][].
///
///
///[Span]:../proc_macro2/struct.Span.html
///[syn::Span]:../syn/struct.Span.html
pub trait SpanExt: Copy {
fn new_ident<S>(self, s: S) -> syn::Ident
where
S: AsRef<str>,
{
syn::Ident::new(s.as_ref(), self.into_pm2_span())
}
/// Creates `Token` from `self`.
fn as_token<Token>(self) -> Token
where
Token: FromSpan,
{
Token::from_span(self.into_pm2_span())
}
fn into_pm2_span(self) -> Span;
}
impl SpanExt for Span {
fn into_pm2_span(self) -> Self {
self
}
}

View file

@ -0,0 +1,283 @@
//! Span-aware quasi quotting built on top of `quote` crate.
//!
mod buffer;
pub use self::buffer::{Location, Quote};
#[macro_export]
#[doc(hidden)]
macro_rules! quoter_location {
() => {{
$crate::spanned_quote::Location {
line: line!(),
col: column!(),
file_name: file!(),
}
}};
}
// ----- Start of variable handling macros.
/// Usage: __sq_handle_vars! { a, b: expression(), c, };
///
#[doc(hidden)]
#[macro_export]
macro_rules! handle_vars_for_quote {
(
@NORMALIZED {
$(
$name:ident: $value:expr,
)*
},
) => {
$crate::declare_vars_for_quote!(
$($name: $value,)*
);
};
(
@NORMALIZED {
$($norm:tt)*
},
$name:ident,
$($rest:tt)*
) => {
$crate::handle_vars_for_quote!(
@NORMALIZED {
$($norm)*
$name: $name,
},
$($rest)*
)
};
(
@NORMALIZED {
$($norm:tt)*
},
$name:ident
) => {
$crate::handle_vars_for_quote!(
@NORMALIZED {
$($norm)*
$name: $name,
},
)
};
(
@NORMALIZED {
$($norm:tt)*
},
$name:ident: $value:expr,
$($rest:tt)*
) => {
$crate::handle_vars_for_quote!(
@NORMALIZED {
$($norm)*
$name: $value,
},
$($rest)*
)
};
(
@NORMALIZED {
$($norm:tt)*
},
$name:ident: $value:expr
) => {
$crate::handle_vars_for_quote!(
@NORMALIZED {
$($norm)*
$name: $value,
},
)
};
}
/// This macro handles `Vars`, and creates a new hidden macro used inside quasi-quotting.
#[doc(hidden)]
#[macro_export]
macro_rules! declare_vars_for_quote {
(
$(
$name:ident: $val:expr,
)*
) => {
$(
#[allow(non_snake_case)]
let $name = $val;
)*
// This macro quotes only one token at once.
macro_rules! __sq_push_token_custom {
$(
($tokens:expr, $name) => {
$tokens.push_tokens(&$name);
};
)*
// default (stringify + parse)
($tokens:expr, $t:tt) => {
$tokens.push_parsed(stringify!($t));
};
}
};
}
// ----- End of variable handling macros.
/// This macro assumes that `Vars` is already handled.
#[doc(hidden)]
#[macro_export]
macro_rules! __sq_quote_tokens_to {
// Done.
($tokens:expr,) => {{}};
($tokens:expr, ( $($inner:tt)* ) $($rest:tt)*) => {{
$tokens.push_group(::proc_macro2::Delimiter::Parenthesis, $crate::__sq_quote_closure! {
$($inner)*
});
$crate::__sq_quote_tokens_to!($tokens, $($rest)*);
}};
($tokens:expr, { $($inner:tt)* } $($rest:tt)*) => {{
$tokens.push_group(::proc_macro2::Delimiter::Brace, $crate::__sq_quote_closure! {
$($inner)*
});
$crate::__sq_quote_tokens_to!($tokens, $($rest)*);
}};
($tokens:expr, [ $($inner:tt)* ] $($rest:tt)*) => {{
$tokens.push_group(::proc_macro2::Delimiter::Bracket, $crate::__sq_quote_closure! {
$($inner)*
});
$crate::__sq_quote_tokens_to!($tokens, $($rest)*);
}};
// If we have to quote one token, check if user declared variable.
($tokens:expr, $first:tt $($rest:tt)*) => {
__sq_push_token_custom!($tokens, $first);
$crate::__sq_quote_tokens_to!($tokens, $($rest)*);
};
}
/// ide-friendly quasi quotting.
///
///# Syntax
///## Vars
///Syntax is simillar to field initialization syntax.
///
///```rust,ignore
///Vars {
/// a,
/// b: expr_b,
/// c: fn_c(),
/// d,
///}
/// // is equivalent to
///Vars {
/// a: a,
/// b: expr_b,
/// c: fn_c(),
/// d: d,
///}
///
///```
///
///Note that `Vars{}` is required even if there's no variable.
///
///## Tokens
/// As parsers for syntax highligters implement error recovery,
/// tokens are wrapped in block or paren like `{ tokens.. }`/ `( tokens.. )`.
///
///# Example
///
///```rust,ignore
/// smart_quote!(Vars{
/// OrigTrait: tr.ident,
/// SpecializerTrait: tr.ident.new_ident_with(|tr| format!("{}Specializer", tr)),
/// }, {
/// impl<T> OrigTrait for T where T: SpecializerTrait {
/// }
/// })
///```
///
///# Example (no variable)
///
///```rust,ignore
/// smart_quote!(Vars{}, {
/// yield ();
/// })
///```
#[macro_export]
macro_rules! smart_quote {
(
Vars{ $($vars:tt)* },
{
$(
$tokens:tt
)*
}
) => {{
|_tokens: &mut $crate::Quote| {
$crate::handle_vars_for_quote!(@NORMALIZED{}, $($vars)*);
_tokens.report_loc($crate::quoter_location!());
$crate::__sq_quote_tokens_to!(_tokens, $($tokens)*);
}
}};
(
{
$(
$tokens:tt
)*
}
) => {{
$crate::smart_quote!(Vars {}, { $($tokens)* })
}};
(
Vars{ $($vars:tt)* },
(
$(
$tokens:tt
)*
)
) => {
$crate::smart_quote!(Vars { $($vars)* }, { $($tokens)* })
};
(
(
$(
$tokens:tt
)*
)
) => {
$crate::smart_quote!(Vars {}, { $($tokens)* })
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __sq_quote_closure {
( $($tokens:tt)* ) => {{
|_tokens: &mut $crate::Quote| {
_tokens.report_loc($crate::quoter_location!());
$crate::__sq_quote_tokens_to!(_tokens, $($tokens)*);
}
}};
}
/// Shortcut for `Quote::new_call_site().quote_with(smart_quote!( $tokens ))`
#[macro_export]
macro_rules! q {
( $($tokens:tt)* ) => {{
$crate::Quote::new_call_site().quote_with($crate::smart_quote!( $($tokens)* ))
}};
}

View file

@ -0,0 +1,227 @@
use crate::respan::{self, Respan};
use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::{ToTokens, TokenStreamExt};
use std::collections::HashSet;
use std::env;
use std::fmt::{self, Display, Formatter, Write};
use syn::parse::Parse;
/// Buffer for quasi quotting.
pub struct Quote {
tts: TokenStream,
span: Option<Box<(dyn Respan + 'static)>>,
/// Location of smart_quote! invokations.
/// Used for error reporting.
sources: HashSet<Location>,
}
const INVALID_SPAN_STATE: &str = "Span is in invalid state.
Closure provided to push_group should not panic.";
/// Location of `smart_quote!` macro invocation.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Location {
pub file_name: &'static str,
pub line: u32,
pub col: u32,
}
impl Display for Location {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}:{}:{}", self.file_name, self.line, self.col)?;
Ok(())
}
}
impl Quote {
pub fn new<S: Respan + 'static>(span: S) -> Self {
Quote {
span: Some(Box::new(span)),
tts: TokenStream::new(),
sources: Default::default(),
}
}
/// Shorthand for
///
/// ```rust,ignore
/// Quote::new(Span::call_site())
/// ```
pub fn new_call_site() -> Self {
Self::new(Span::call_site())
}
/// Shorthand for
///
/// ```rust,ignore
/// Quote::new(tokens.first_last())
/// ```
pub fn from_tokens(tokens: &dyn ToTokens) -> Self {
Self::new(respan::FirstLast::from_tokens(tokens))
}
/// Shorthand for
///
///```rust,ignore
/// tokens
/// .as_ref()
/// .map(|tokens| Quote::from_tokens(tokens))
/// .unwrap_or_else(|| Quote::new(default_span))
///```
///
pub fn from_tokens_or<T: ToTokens>(tokens: &Option<T>, default_span: Span) -> Self {
match *tokens {
Some(ref tokens) => Self::from_tokens(tokens),
None => Self::new(default_span),
}
}
}
impl Quote {
/// Parse tokens as `Node`.
/// Panics if parsing failed.
pub fn parse<Node>(self) -> Node
where
Node: Parse,
{
// TODO: Use span to report error.
let Quote { tts, sources, .. } = self;
let debug_tts = if env::var("DBG_DUMP").is_ok() {
Some(tts.clone())
} else {
None
};
syn::parse2(tts).unwrap_or_else(|err| {
let debug_tts: &dyn Display = match debug_tts {
Some(ref tts) => tts,
None => {
&"To get code failed to parse,
please set environment variable `DBG_DUMP` and run in again"
}
};
let notes = {
let mut b = String::from("Note: quasi quotting was invoked from:\n");
for src in &sources {
writeln!(b, " {src}").unwrap();
}
b
};
panic!(
"Quote::parse() failed.
{notes}
Error from syn: {err}
>>>>>
{debug_tts}
<<<<<",
notes = notes,
err = err,
debug_tts = debug_tts
)
})
}
}
/// Methods for quasi-quotting.
impl Quote {
#[doc(hidden)]
/// Reports location of `smart_quote!` invocation.
pub fn report_loc(&mut self, loc: Location) {
self.sources.insert(loc);
}
pub fn quote_with<F>(mut self, quote: F) -> Self
where
F: FnOnce(&mut Self),
{
(quote)(&mut self);
self
}
/// Parse `token` and append it to `self`.
pub fn push_parsed(&mut self, token: &str) {
let Quote {
ref mut span,
ref mut tts,
..
} = *self;
token
.parse::<TokenStream>()
.expect("Failed to parse token to quote")
.into_iter()
.map(|tt| span.as_ref().expect(INVALID_SPAN_STATE).respan(tt))
.for_each(|tt| tts.append(tt));
}
/// Append `tt` to `self`.
pub fn push_tt(&mut self, tt: TokenTree) {
self.tts.append(tt)
}
/// Respan symbol and append it to `self`.
pub fn push_sym(&mut self, term: &str) {
let span = self.next_span();
self.push_tt(TokenTree::Ident(Ident::new(term, span)))
}
fn next_span(&self) -> Span {
self.span.as_ref().expect(INVALID_SPAN_STATE).next_span()
}
/// Respan and append `TokenStream::Group`
pub fn push_group<F>(&mut self, delim: Delimiter, child: F)
where
F: FnOnce(&mut Quote),
{
//TODO: Exception safety
let span = self.span.take().expect(INVALID_SPAN_STATE);
let mut sub = Quote::new(span);
child(&mut sub);
self.sources.extend(sub.sources);
debug_assert!(self.span.is_none());
self.span = Some(sub.span.expect(INVALID_SPAN_STATE));
self.push_tt(TokenTree::Group(Group::new(delim, sub.tts)))
}
/// Appends node into `self` **without respanning**.
pub fn push_tokens<T: ?Sized + ToTokens>(&mut self, node: &T) {
node.to_tokens(&mut self.tts);
}
}
impl IntoIterator for Quote {
type IntoIter = <TokenStream as IntoIterator>::IntoIter;
type Item = <TokenStream as IntoIterator>::Item;
fn into_iter(self) -> Self::IntoIter {
self.tts.into_iter()
}
}
impl From<Quote> for TokenStream {
fn from(quote: Quote) -> Self {
quote.tts
}
}
impl From<Quote> for proc_macro::TokenStream {
fn from(quote: Quote) -> Self {
TokenStream::from(quote).into()
}
}
impl ToTokens for Quote {
fn to_tokens(&self, dst: &mut TokenStream) {
self.tts.to_tokens(dst)
}
fn into_token_stream(self) -> TokenStream {
self.tts
}
}

View file

@ -0,0 +1,110 @@
//! Utils for tokens from synom::tokens.
use proc_macro2::Span;
use syn::token::*;
/// See [SpanExt#as_token][] for usage. Create tokens from [Span][].
///
///
///[SpanExt#as_token]:../trait.SpanExt.html#method.as_token
///[Span]:../../proc_macro2/struct.Span.html
pub trait FromSpan {
fn from_span(span: Span) -> Self;
}
impl FromSpan for Span {
#[inline(always)]
fn from_span(span: Span) -> Self {
span
}
}
macro_rules! impl_array {
($n:expr) => {
impl<T: FromSpan + Copy> FromSpan for [T; $n] {
#[inline(always)]
fn from_span(span: Span) -> Self{
let e = FromSpan::from_span(span);
[e; $n]
}
}
};
($n:expr, $($rest:tt)*) => {
impl_array!($n);
impl_array!($($rest)*);
};
}
impl_array!(1, 2, 3, 4);
macro_rules! bridge_spans {
// Done
($t:path) => {
impl FromSpan for $t {
fn from_span(span: Span) -> Self {
let spans = FromSpan::from_span(span);
$t { spans }
}
}
};
($t:path, $($rest:tt)+) => {
bridge_spans!($t);
bridge_spans!($($rest)*);
};
}
macro_rules! bridge {
// Done
($t:path) => {
impl FromSpan for $t {
fn from_span(span: Span) -> Self {
let span = FromSpan::from_span(span);
$t { span }
}
}
};
($t:path,) => {
bridge!($t);
};
($t:path, $($rest:tt)+) => {
bridge!($t);
bridge!($($rest)*);
};
}
macro_rules! bridge_group {
// Done
($t:path) => {
impl FromSpan for $t {
fn from_span(span: Span) -> Self {
$t(span)
}
}
};
($t:path,) => {
bridge_group!($t);
};
($t:path, $($rest:tt)+) => {
bridge_group!($t);
bridge_group!($($rest)*);
};
}
bridge_spans!(
And, AndAnd, AndEq, At, Caret, CaretEq, Colon, Comma, Dollar, Dot, DotDot, DotDotDot, DotDotEq,
Eq, EqEq, FatArrow, Ge, Gt, LArrow, Le, Lt, Minus, MinusEq, Ne, Not, Or, OrEq, OrOr, PathSep,
Percent, PercentEq, Plus, PlusEq, Pound, Question, RArrow, Semi, Shl, ShlEq, Shr, ShrEq, Slash,
SlashEq, Star, StarEq, Tilde, Underscore
);
bridge_group!(Brace, Bracket, Paren);
bridge!(
Abstract, As, Async, Auto, Await, Become, Box, Break, Const, Continue, Crate, Default, Do, Dyn,
Else, Enum, Extern, Final, Fn, For, If, Impl, In, Let, Loop, Macro, Match, Mod, Move, Mut,
Override, Priv, Pub, Ref, Return, SelfType, SelfValue, Static, Struct, Super, Trait, Try, Type,
Typeof, Union, Unsafe, Unsized, Use, Virtual, Where, While, Yield,
);