aboutsummaryrefslogtreecommitdiff
path: root/syn/codegen/src/visit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'syn/codegen/src/visit.rs')
-rw-r--r--syn/codegen/src/visit.rs265
1 files changed, 0 insertions, 265 deletions
diff --git a/syn/codegen/src/visit.rs b/syn/codegen/src/visit.rs
deleted file mode 100644
index 41bc9e9..0000000
--- a/syn/codegen/src/visit.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-use crate::operand::{Borrowed, Operand, Owned};
-use crate::{file, full, gen};
-use anyhow::Result;
-use proc_macro2::{Ident, Span, TokenStream};
-use quote::quote;
-use syn::Index;
-use syn_codegen::{Data, Definitions, Features, Node, Type};
-
-const VISIT_SRC: &str = "../src/gen/visit.rs";
-
-fn simple_visit(item: &str, name: &Operand) -> TokenStream {
- let ident = gen::under_name(item);
- let method = Ident::new(&format!("visit_{}", ident), Span::call_site());
- let name = name.ref_tokens();
- quote! {
- v.#method(#name)
- }
-}
-
-fn noop_visit(name: &Operand) -> TokenStream {
- let name = name.tokens();
- quote! {
- skip!(#name)
- }
-}
-
-fn visit(
- ty: &Type,
- features: &Features,
- defs: &Definitions,
- name: &Operand,
-) -> Option<TokenStream> {
- match ty {
- Type::Box(t) => {
- let name = name.owned_tokens();
- visit(t, features, defs, &Owned(quote!(*#name)))
- }
- Type::Vec(t) => {
- let operand = Borrowed(quote!(it));
- let val = visit(t, features, defs, &operand)?;
- let name = name.ref_tokens();
- Some(quote! {
- for it in #name {
- #val
- }
- })
- }
- Type::Punctuated(p) => {
- let operand = Borrowed(quote!(it));
- let val = visit(&p.element, features, defs, &operand)?;
- let name = name.ref_tokens();
- Some(quote! {
- for el in Punctuated::pairs(#name) {
- let (it, p) = el.into_tuple();
- #val;
- if let Some(p) = p {
- tokens_helper(v, &p.spans);
- }
- }
- })
- }
- Type::Option(t) => {
- let it = Borrowed(quote!(it));
- let val = visit(t, features, defs, &it)?;
- let name = name.owned_tokens();
- Some(quote! {
- if let Some(it) = &#name {
- #val
- }
- })
- }
- Type::Tuple(t) => {
- let mut code = TokenStream::new();
- for (i, elem) in t.iter().enumerate() {
- let name = name.tokens();
- let i = Index::from(i);
- let it = Owned(quote!((#name).#i));
- let val = visit(elem, features, defs, &it).unwrap_or_else(|| noop_visit(&it));
- code.extend(val);
- code.extend(quote!(;));
- }
- Some(code)
- }
- Type::Token(t) => {
- let name = name.tokens();
- let repr = &defs.tokens[t];
- let is_keyword = repr.chars().next().unwrap().is_alphabetic();
- let spans = if is_keyword {
- quote!(span)
- } else {
- quote!(spans)
- };
- Some(quote! {
- tokens_helper(v, &#name.#spans)
- })
- }
- Type::Group(_) => {
- let name = name.tokens();
- Some(quote! {
- tokens_helper(v, &#name.span)
- })
- }
- Type::Syn(t) => {
- fn requires_full(features: &Features) -> bool {
- features.any.contains("full") && features.any.len() == 1
- }
- let mut res = simple_visit(t, name);
- let target = defs.types.iter().find(|ty| ty.ident == *t).unwrap();
- if requires_full(&target.features) && !requires_full(features) {
- res = quote!(full!(#res));
- }
- Some(res)
- }
- Type::Ext(t) if gen::TERMINAL_TYPES.contains(&&t[..]) => Some(simple_visit(t, name)),
- Type::Ext(_) | Type::Std(_) => None,
- }
-}
-
-fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Definitions) {
- let under_name = gen::under_name(&s.ident);
- let ty = Ident::new(&s.ident, Span::call_site());
- let visit_fn = Ident::new(&format!("visit_{}", under_name), Span::call_site());
-
- let mut visit_impl = TokenStream::new();
-
- match &s.data {
- Data::Enum(variants) => {
- let mut visit_variants = TokenStream::new();
-
- for (variant, fields) in variants {
- let variant_ident = Ident::new(variant, Span::call_site());
-
- if fields.is_empty() {
- visit_variants.extend(quote! {
- #ty::#variant_ident => {}
- });
- } else {
- let mut bind_visit_fields = TokenStream::new();
- let mut visit_fields = TokenStream::new();
-
- for (idx, ty) in fields.iter().enumerate() {
- let name = format!("_binding_{}", idx);
- let binding = Ident::new(&name, Span::call_site());
-
- bind_visit_fields.extend(quote! {
- #binding,
- });
-
- let borrowed_binding = Borrowed(quote!(#binding));
-
- visit_fields.extend(
- visit(ty, &s.features, defs, &borrowed_binding)
- .unwrap_or_else(|| noop_visit(&borrowed_binding)),
- );
-
- visit_fields.extend(quote!(;));
- }
-
- visit_variants.extend(quote! {
- #ty::#variant_ident(#bind_visit_fields) => {
- #visit_fields
- }
- });
- }
- }
-
- let nonexhaustive = if s.exhaustive {
- None
- } else {
- Some(quote!(_ => unreachable!()))
- };
-
- visit_impl.extend(quote! {
- match node {
- #visit_variants
- #nonexhaustive
- }
- });
- }
- Data::Struct(fields) => {
- for (field, ty) in fields {
- if let Type::Syn(ty) = ty {
- if ty == "Reserved" {
- continue;
- }
- }
-
- let id = Ident::new(&field, Span::call_site());
- let ref_toks = Owned(quote!(node.#id));
- let visit_field = visit(&ty, &s.features, defs, &ref_toks)
- .unwrap_or_else(|| noop_visit(&ref_toks));
- visit_impl.extend(quote! {
- #visit_field;
- });
- }
- }
- Data::Private => {
- if ty == "Ident" {
- visit_impl.extend(quote! {
- v.visit_span(&node.span());
- });
- }
- }
- }
-
- let ast_lifetime = if s.ident == "Span" {
- None
- } else {
- Some(quote!('ast))
- };
-
- traits.extend(quote! {
- fn #visit_fn(&mut self, i: &#ast_lifetime #ty) {
- #visit_fn(self, i)
- }
- });
-
- impls.extend(quote! {
- pub fn #visit_fn<'ast, V>(v: &mut V, node: &#ast_lifetime #ty)
- where
- V: Visit<'ast> + ?Sized,
- {
- #visit_impl
- }
- });
-}
-
-pub fn generate(defs: &Definitions) -> Result<()> {
- let (traits, impls) = gen::traverse(defs, node);
- let full_macro = full::get_macro();
- file::write(
- VISIT_SRC,
- quote! {
- #![allow(unused_variables)]
-
- use crate::*;
- #[cfg(any(feature = "full", feature = "derive"))]
- use crate::punctuated::Punctuated;
- use proc_macro2::Span;
- #[cfg(any(feature = "full", feature = "derive"))]
- use crate::gen::helper::visit::*;
-
- #full_macro
-
- #[cfg(any(feature = "full", feature = "derive"))]
- macro_rules! skip {
- ($($tt:tt)*) => {};
- }
-
- /// Syntax tree traversal to walk a shared borrow of a syntax tree.
- ///
- /// See the [module documentation] for details.
- ///
- /// [module documentation]: self
- ///
- /// *This trait is available if Syn is built with the `"visit"` feature.*
- pub trait Visit<'ast> {
- #traits
- }
-
- #impls
- },
- )?;
- Ok(())
-}