From 9c4cafee2c0495f5cd5755af98c82ac528c14213 Mon Sep 17 00:00:00 2001 From: Olivier FAURE Date: Mon, 11 Apr 2022 18:51:54 +0200 Subject: [PATCH] Create GroupSpan type to display groups correctly. --- src/parse.rs | 14 +++++------ src/types.rs | 58 +++++++++++++++++++++++++++++++++++--------- src/types_edition.rs | 16 +++++++++--- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index aebbf15..2b4afbe 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -5,6 +5,7 @@ use crate::types::{ NamedStructFields, Struct, StructFields, TupleField, TupleStructFields, TyExpr, Union, VisMarker, WhereClause, WhereClauseItem, }; +use crate::types_edition::GroupSpan; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, TokenStream, TokenTree}; use std::iter::Peekable; @@ -37,7 +38,7 @@ fn consume_attributes(tokens: &mut TokenIter) -> Vec { attributes.push(Attribute { _hashbang: hashbang, child_tokens: group.stream().into_iter().collect(), - _braces: group, + _braces: GroupSpan::new(&group), }); } @@ -398,7 +399,7 @@ fn parse_tuple_fields(token_group: Group) -> TupleStructFields { TupleStructFields { fields, - tk_parens: token_group, + tk_parens: GroupSpan::new(&token_group), } } @@ -441,7 +442,7 @@ fn parse_named_fields(token_group: Group) -> NamedStructFields { NamedStructFields { fields, - tk_braces: token_group, + tk_braces: GroupSpan::new(&token_group), } } @@ -734,7 +735,7 @@ pub fn parse_declaration(tokens: TokenStream) -> Declaration { name: enum_name, generic_params, where_clause, - tk_braces: group, + tk_braces: GroupSpan::new(&group), variants: enum_variants, }) } @@ -746,9 +747,9 @@ pub fn parse_declaration(tokens: TokenStream) -> Declaration { let generic_params = consume_generic_params(&mut tokens); let where_clause = consume_where_clause(&mut tokens); - let (group, union_fields) = match tokens.next().unwrap() { + let union_fields = match tokens.next().unwrap() { TokenTree::Group(group) if group.delimiter() == Delimiter::Brace => { - (group.clone(), parse_named_fields(group.clone())) + parse_named_fields(group) } token => panic!("cannot parse union: unexpected token {:?}", token), }; @@ -760,7 +761,6 @@ pub fn parse_declaration(tokens: TokenStream) -> Declaration { name: union_name, generic_params, where_clause, - tk_braces: group, fields: union_fields, }) } diff --git a/src/types.rs b/src/types.rs index 9c33e9a..5430d76 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,6 @@ #![allow(missing_docs)] -use proc_macro2::{Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::{ToTokens, TokenStreamExt as _}; use crate::Punctuated; @@ -74,13 +74,13 @@ pub enum StructFields { #[derive(Clone)] pub struct TupleStructFields { pub fields: Punctuated, - pub tk_parens: Group, + pub tk_parens: GroupSpan, } #[derive(Clone)] pub struct NamedStructFields { pub fields: Punctuated, - pub tk_braces: Group, + pub tk_braces: GroupSpan, } /// Declaration of an enum. @@ -100,7 +100,7 @@ pub struct Enum { pub name: Ident, pub generic_params: Option, pub where_clause: Option, - pub tk_braces: Group, + pub tk_braces: GroupSpan, pub variants: Punctuated, } @@ -137,7 +137,6 @@ pub struct Union { pub name: Ident, pub generic_params: Option, pub where_clause: Option, - pub tk_braces: Group, pub fields: NamedStructFields, } @@ -238,7 +237,7 @@ pub struct NamedField { #[derive(Clone)] pub struct Attribute { pub _hashbang: Punct, - pub _braces: Group, + pub _braces: GroupSpan, pub child_tokens: Vec, } @@ -349,6 +348,12 @@ pub struct EnumDiscriminant { pub expression: Expression, } +#[derive(Clone)] +pub struct GroupSpan { + pub delimiter: Delimiter, + pub span: Span, +} + // --- Debug impls --- struct TokenRef<'a>(&'a TokenTree); @@ -492,8 +497,29 @@ impl std::fmt::Debug for TyExpr { } } +impl std::fmt::Debug for GroupSpan { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.delimiter { + Delimiter::Parenthesis => f.write_str("()"), + Delimiter::Brace => f.write_str("{}"), + Delimiter::Bracket => f.write_str("[]"), + Delimiter::None => f.write_str("Ø"), + } + } +} + // --- ToTokens impls --- +impl GroupSpan { + fn quote_with(&self, tokens: &mut TokenStream, f: impl FnOnce(&mut TokenStream)) { + let mut inner = TokenStream::new(); + f(&mut inner); + let mut g = Group::new(self.delimiter, inner); + g.set_span(self.span); + tokens.append(g); + } +} + impl ToTokens for Expression { fn to_tokens(&self, tokens: &mut TokenStream) { for token in &self.tokens { @@ -546,13 +572,17 @@ impl ToTokens for StructFields { impl ToTokens for TupleStructFields { fn to_tokens(&self, tokens: &mut TokenStream) { - self.tk_parens.to_tokens(tokens); + self.tk_parens.quote_with(tokens, |tokens| { + self.fields.to_tokens(tokens); + }); } } impl ToTokens for NamedStructFields { fn to_tokens(&self, tokens: &mut TokenStream) { - self.tk_braces.to_tokens(tokens); + self.tk_braces.quote_with(tokens, |tokens| { + self.fields.to_tokens(tokens); + }); } } @@ -566,7 +596,9 @@ impl ToTokens for Enum { self.name.to_tokens(tokens); self.generic_params.to_tokens(tokens); self.where_clause.to_tokens(tokens); - self.tk_braces.to_tokens(tokens); + self.tk_braces.quote_with(tokens, |tokens| { + self.variants.to_tokens(tokens); + }); } } @@ -592,7 +624,7 @@ impl ToTokens for Union { self.name.to_tokens(tokens); self.generic_params.to_tokens(tokens); self.where_clause.to_tokens(tokens); - self.tk_braces.to_tokens(tokens); + self.fields.to_tokens(tokens); } } @@ -660,7 +692,11 @@ impl ToTokens for NamedField { impl ToTokens for Attribute { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self._hashbang.clone()); - tokens.append(self._braces.clone()); + self._braces.quote_with(tokens, |tokens| { + for token in &self.child_tokens { + tokens.append(token.clone()) + } + }); } } diff --git a/src/types_edition.rs b/src/types_edition.rs index 793065c..72e6ace 100644 --- a/src/types_edition.rs +++ b/src/types_edition.rs @@ -3,10 +3,10 @@ pub use crate::types::{ Attribute, Declaration, Enum, EnumDiscriminant, EnumVariant, Function, GenericBound, - GenericParam, GenericParams, InlineGenericArgs, NamedField, Struct, StructFields, TupleField, - TyExpr, Union, VisMarker, WhereClause, WhereClauseItem, + GenericParam, GenericParams, GroupSpan, InlineGenericArgs, NamedField, Struct, StructFields, + TupleField, TyExpr, Union, VisMarker, WhereClause, WhereClauseItem, }; -use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use proc_macro2::{Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; impl Declaration { pub fn generic_params(&self) -> Option<&GenericParams> { @@ -498,3 +498,13 @@ impl WhereClauseItem { } } } + +impl GroupSpan { + /// Create from proc_macro2 Group. + pub fn new(group: &Group) -> Self { + Self { + span: group.span(), + delimiter: group.delimiter(), + } + } +}