cxx/syntax/tokens.rs
2021-01-02 23:25:53 -08:00

307 lines
8.6 KiB
Rust

use crate::syntax::atom::Atom::*;
use crate::syntax::{
Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Receiver, Ref,
Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote_spanned, ToTokens};
use syn::{token, Token};
impl ToTokens for Type {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Type::Ident(ident) => {
if ident.rust == Char {
let span = ident.rust.span();
tokens.extend(quote_spanned!(span=> ::std::os::raw::));
} else if ident.rust == CxxString {
let span = ident.rust.span();
tokens.extend(quote_spanned!(span=> ::cxx::));
}
ident.to_tokens(tokens);
}
Type::RustBox(ty)
| Type::UniquePtr(ty)
| Type::SharedPtr(ty)
| Type::WeakPtr(ty)
| Type::CxxVector(ty)
| Type::RustVec(ty) => ty.to_tokens(tokens),
Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
Type::Array(a) => a.to_tokens(tokens),
Type::Fn(f) => f.to_tokens(tokens),
Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
Type::SliceRef(r) => r.to_tokens(tokens),
}
}
}
impl ToTokens for Var {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Var {
doc: _,
attrs: _,
visibility: _,
name,
ty,
} = self;
name.rust.to_tokens(tokens);
Token![:](name.rust.span()).to_tokens(tokens);
ty.to_tokens(tokens);
}
}
impl ToTokens for Ty1 {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Ty1 {
name,
langle,
inner,
rangle,
} = self;
let span = name.span();
match name.to_string().as_str() {
"UniquePtr" | "SharedPtr" | "WeakPtr" | "CxxVector" => {
tokens.extend(quote_spanned!(span=> ::cxx::));
}
"Vec" => {
tokens.extend(quote_spanned!(span=> ::std::vec::));
}
_ => {}
}
name.to_tokens(tokens);
langle.to_tokens(tokens);
inner.to_tokens(tokens);
rangle.to_tokens(tokens);
}
}
impl ToTokens for Ref {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Ref {
pinned: _,
ampersand,
lifetime,
mutable: _,
inner,
pin_tokens,
mutability,
} = self;
if let Some((pin, langle, _rangle)) = pin_tokens {
tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
langle.to_tokens(tokens);
}
ampersand.to_tokens(tokens);
lifetime.to_tokens(tokens);
mutability.to_tokens(tokens);
inner.to_tokens(tokens);
if let Some((_pin, _langle, rangle)) = pin_tokens {
rangle.to_tokens(tokens);
}
}
}
impl ToTokens for SliceRef {
fn to_tokens(&self, tokens: &mut TokenStream) {
let SliceRef {
ampersand,
lifetime,
mutable: _,
bracket,
inner,
mutability,
} = self;
ampersand.to_tokens(tokens);
lifetime.to_tokens(tokens);
mutability.to_tokens(tokens);
bracket.surround(tokens, |tokens| {
inner.to_tokens(tokens);
});
}
}
impl ToTokens for Array {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Array {
bracket,
inner,
semi_token,
len: _,
len_token,
} = self;
bracket.surround(tokens, |tokens| {
inner.to_tokens(tokens);
semi_token.to_tokens(tokens);
len_token.to_tokens(tokens);
});
}
}
impl ToTokens for Atom {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
}
}
impl ToTokens for Derive {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(self.what.as_ref(), self.span).to_tokens(tokens);
}
}
impl ToTokens for ExternType {
fn to_tokens(&self, tokens: &mut TokenStream) {
// Notional token range for error reporting purposes.
self.type_token.to_tokens(tokens);
self.name.rust.to_tokens(tokens);
self.generics.to_tokens(tokens);
}
}
impl ToTokens for TypeAlias {
fn to_tokens(&self, tokens: &mut TokenStream) {
// Notional token range for error reporting purposes.
self.type_token.to_tokens(tokens);
self.name.rust.to_tokens(tokens);
self.generics.to_tokens(tokens);
}
}
impl ToTokens for Struct {
fn to_tokens(&self, tokens: &mut TokenStream) {
// Notional token range for error reporting purposes.
self.struct_token.to_tokens(tokens);
self.name.rust.to_tokens(tokens);
self.generics.to_tokens(tokens);
}
}
impl ToTokens for Enum {
fn to_tokens(&self, tokens: &mut TokenStream) {
// Notional token range for error reporting purposes.
self.enum_token.to_tokens(tokens);
self.name.rust.to_tokens(tokens);
self.generics.to_tokens(tokens);
}
}
impl ToTokens for ExternFn {
fn to_tokens(&self, tokens: &mut TokenStream) {
// Notional token range for error reporting purposes.
self.sig.fn_token.to_tokens(tokens);
self.semi_token.to_tokens(tokens);
}
}
impl ToTokens for Impl {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Impl {
impl_token,
impl_generics,
negative: _,
ty,
ty_generics: _,
brace_token,
negative_token,
} = self;
impl_token.to_tokens(tokens);
impl_generics.to_tokens(tokens);
negative_token.to_tokens(tokens);
ty.to_tokens(tokens);
brace_token.surround(tokens, |_tokens| {});
}
}
impl ToTokens for Lifetimes {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Lifetimes {
lt_token,
lifetimes,
gt_token,
} = self;
lt_token.to_tokens(tokens);
lifetimes.to_tokens(tokens);
gt_token.to_tokens(tokens);
}
}
impl ToTokens for Signature {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Signature {
unsafety: _,
fn_token,
generics: _,
receiver: _,
args,
ret,
throws: _,
paren_token,
throws_tokens,
} = self;
fn_token.to_tokens(tokens);
paren_token.surround(tokens, |tokens| {
args.to_tokens(tokens);
});
if let Some(ret) = ret {
Token![->](paren_token.span).to_tokens(tokens);
if let Some((result, langle, rangle)) = throws_tokens {
result.to_tokens(tokens);
langle.to_tokens(tokens);
ret.to_tokens(tokens);
rangle.to_tokens(tokens);
} else {
ret.to_tokens(tokens);
}
} else if let Some((result, langle, rangle)) = throws_tokens {
Token![->](paren_token.span).to_tokens(tokens);
result.to_tokens(tokens);
langle.to_tokens(tokens);
token::Paren(langle.span).surround(tokens, |_| ());
rangle.to_tokens(tokens);
}
}
}
impl ToTokens for NamedType {
fn to_tokens(&self, tokens: &mut TokenStream) {
let NamedType { rust, generics } = self;
rust.to_tokens(tokens);
generics.to_tokens(tokens);
}
}
pub struct ReceiverType<'a>(&'a Receiver);
impl Receiver {
// &TheType
pub fn ty(&self) -> ReceiverType {
ReceiverType(self)
}
}
impl ToTokens for ReceiverType<'_> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Receiver {
pinned: _,
ampersand,
lifetime,
mutable: _,
var: _,
ty,
shorthand: _,
pin_tokens,
mutability,
} = &self.0;
if let Some((pin, langle, _rangle)) = pin_tokens {
tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
langle.to_tokens(tokens);
}
ampersand.to_tokens(tokens);
lifetime.to_tokens(tokens);
mutability.to_tokens(tokens);
ty.to_tokens(tokens);
if let Some((_pin, _langle, rangle)) = pin_tokens {
rangle.to_tokens(tokens);
}
}
}