use tokrepr::TokRepr;
use tokrepr::proc_macro2::TokenStream;
use tokrepr::quote::{format_ident, quote};
use crate::{SyntaxNode, span::Spanned, syntax::*};
trait NamedNode {
fn name(&self) -> Option<String>;
}
impl NamedNode for GlobalDeclaration {
fn name(&self) -> Option<String> {
self.ident().map(|id| id.to_string())
}
}
impl NamedNode for StructMember {
fn name(&self) -> Option<String> {
Some(self.ident.to_string())
}
}
impl NamedNode for Attribute {
fn name(&self) -> Option<String> {
if let Attribute::Custom(attr) = self {
Some(attr.name.to_string())
} else {
None
}
}
}
impl NamedNode for Expression {
fn name(&self) -> Option<String> {
if let Expression::TypeOrIdentifier(ty) = self {
Some(ty.ident.to_string())
} else {
None
}
}
}
impl NamedNode for Statement {
fn name(&self) -> Option<String> {
if let Statement::Compound(stmt) = self {
if stmt.statements.is_empty() {
if let [attr] = stmt.attributes.as_slice() {
if let Attribute::Custom(attr) = attr.node() {
return Some(attr.name.to_string());
}
}
}
}
None
}
}
impl<T: NamedNode + TokRepr> TokRepr for Spanned<T> {
fn tok_repr(&self) -> TokenStream {
let node = self.node().tok_repr();
let span = self.span().tok_repr();
if let Some(name) = self.name() {
if let Some(suffix) = name.strip_prefix("#") {
let ident = format_ident!("{}", suffix);
return quote! {
Spanned::new(#ident.to_owned().into(), #span)
};
}
}
quote! {
Spanned::new(#node, #span)
}
}
}
impl TokRepr for Ident {
fn tok_repr(&self) -> TokenStream {
let name = self.name();
if let Some(name) = name.strip_prefix("#") {
let ident = format_ident!("{}", name);
quote! {
Ident::from(#ident.to_owned())
}
} else {
let name = name.as_str();
quote! {
Ident::new(#name.to_string())
}
}
}
}