Skip to content

Commit

Permalink
rewrite keyword enums with a macro
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Jun 6, 2023
1 parent 25ed153 commit 9776da6
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 239 deletions.
190 changes: 36 additions & 154 deletions crates/syn-solidity/src/attribute/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{kw, SolPath};
use super::{kw, utils::DebugPunctuated, SolPath};
use proc_macro2::{Span, TokenStream};
use std::{
fmt,
Expand All @@ -18,163 +18,43 @@ pub use function::{FunctionAttribute, FunctionAttributes};
mod variable;
pub use variable::{VariableAttribute, VariableAttributes};

/// A visibility attribute.
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Visibility {
/// `external`
External(kw::external),
/// `public`
Public(kw::public),
/// `internal`
Internal(kw::internal),
/// `private`
Private(kw::private),
}

impl fmt::Debug for Visibility {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_debug_str())
}
}

impl fmt::Display for Visibility {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
kw_enum! {
/// A storage location.
pub enum Storage {
/// `memory`
Memory(kw::memory),
/// `storage`
Storage(kw::storage),
/// `calldata`
Calldata(kw::calldata),
}
}

impl Parse for Visibility {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(kw::external) {
input.parse().map(Self::External)
} else if lookahead.peek(kw::public) {
input.parse().map(Self::Public)
} else if lookahead.peek(kw::internal) {
input.parse().map(Self::Internal)
} else if lookahead.peek(kw::private) {
input.parse().map(Self::Private)
} else {
Err(lookahead.error())
}
kw_enum! {
/// A visibility attribute.
pub enum Visibility {
/// `external`
External(kw::external),
/// `public`
Public(kw::public),
/// `internal`
Internal(kw::internal),
/// `private`
Private(kw::private),
}
}

impl Visibility {
pub fn span(&self) -> Span {
match self {
Self::External(kw) => kw.span,
Self::Public(kw) => kw.span,
Self::Internal(kw) => kw.span,
Self::Private(kw) => kw.span,
}
}

pub fn set_span(&mut self, span: Span) {
match self {
Self::External(kw) => kw.span = span,
Self::Public(kw) => kw.span = span,
Self::Internal(kw) => kw.span = span,
Self::Private(kw) => kw.span = span,
}
}

pub const fn as_debug_str(&self) -> &'static str {
match self {
Self::External(_) => "External",
Self::Public(_) => "Public",
Self::Internal(_) => "Internal",
Self::Private(_) => "Private",
}
}

pub const fn as_str(&self) -> &'static str {
match self {
Self::External(_) => "external",
Self::Public(_) => "public",
Self::Internal(_) => "internal",
Self::Private(_) => "private",
}
}
}

/// A mutability attribute.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum Mutability {
/// `pure`
Pure(kw::pure),
/// `view`
View(kw::view),
/// `constant`
Constant(kw::constant),
/// `payable`
Payable(kw::payable),
}

impl fmt::Debug for Mutability {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_debug_str())
}
}

impl fmt::Display for Mutability {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}

impl Parse for Mutability {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(kw::pure) {
input.parse().map(Self::Pure)
} else if lookahead.peek(kw::view) {
input.parse().map(Self::View)
} else if lookahead.peek(kw::constant) {
input.parse().map(Self::Constant)
} else if lookahead.peek(kw::payable) {
input.parse().map(Self::Payable)
} else {
Err(lookahead.error())
}
}
}

impl Mutability {
pub fn span(&self) -> Span {
match self {
Self::Pure(kw) => kw.span,
Self::View(kw) => kw.span,
Self::Constant(kw) => kw.span,
Self::Payable(kw) => kw.span,
}
}

pub fn set_span(&mut self, span: Span) {
match self {
Self::Pure(kw) => kw.span = span,
Self::View(kw) => kw.span = span,
Self::Constant(kw) => kw.span = span,
Self::Payable(kw) => kw.span = span,
}
}

pub const fn as_debug_str(&self) -> &'static str {
match self {
Self::Pure(_) => "Pure",
Self::View(_) => "View",
Self::Constant(_) => "Constant",
Self::Payable(_) => "Payable",
}
}

pub const fn as_str(&self) -> &'static str {
match self {
Self::Pure(_) => "pure",
Self::View(_) => "view",
Self::Constant(_) => "constant",
Self::Payable(_) => "payable",
}
kw_enum! {
/// A mutability attribute.
pub enum Mutability {
/// `pure`
Pure(kw::pure),
/// `view`
View(kw::view),
/// `constant`
Constant(kw::constant),
/// `payable`
Payable(kw::payable),
}
}

Expand All @@ -188,7 +68,9 @@ pub struct Override {

impl fmt::Debug for Override {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Override").field(&self.paths).finish()
f.debug_tuple("Override")
.field(DebugPunctuated::new(&self.paths))
.finish()
}
}

Expand Down Expand Up @@ -273,7 +155,7 @@ impl fmt::Debug for Modifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Modifier")
.field("name", &self.name)
.field("arguments", &self.arguments)
.field("arguments", DebugPunctuated::new(&self.arguments))
.finish()
}
}
Expand Down
13 changes: 13 additions & 0 deletions crates/syn-solidity/src/attribute/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{kw, Override, Visibility};
use proc_macro2::Span;
use std::{
collections::HashSet,
fmt,
hash::{Hash, Hasher},
mem,
};
Expand All @@ -11,6 +12,7 @@ use syn::{
};

/// A list of unique variable attributes.
#[derive(Clone, Debug)]
pub struct VariableAttributes(pub HashSet<VariableAttribute>);

impl Parse for VariableAttributes {
Expand Down Expand Up @@ -64,6 +66,17 @@ pub enum VariableAttribute {
Override(Override),
}

impl fmt::Debug for VariableAttribute {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Visibility(v) => v.fmt(f),
Self::Constant(_) => f.write_str("constant"),
Self::Immutable(_) => f.write_str("immutable"),
Self::Override(o) => o.fmt(f),
}
}
}

impl PartialEq for VariableAttribute {
fn eq(&self, other: &Self) -> bool {
mem::discriminant(self) == mem::discriminant(other)
Expand Down
1 change: 1 addition & 0 deletions crates/syn-solidity/src/item/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use syn::{
///
/// Solidity reference:
/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.errorDefinition>
#[derive(Clone)]
pub struct ItemError {
pub attrs: Vec<Attribute>,
pub error_token: kw::error,
Expand Down
1 change: 1 addition & 0 deletions crates/syn-solidity/src/item/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use syn::{
///
/// Solidity reference:
/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionDefinition>
#[derive(Clone)]
pub struct ItemFunction {
/// The `syn` attributes of the function.
pub attrs: Vec<Attribute>,
Expand Down
20 changes: 11 additions & 9 deletions crates/syn-solidity/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
#![doc = include_str!("../README.md")]
#![warn(unreachable_pub, unused_crate_dependencies)]
#![warn(
missing_copy_implementations,
missing_debug_implementations,
unreachable_pub,
unused_crate_dependencies
)]
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

extern crate proc_macro;

use syn::Result;

#[macro_use]
mod macros;

mod attribute;
pub use attribute::{
FunctionAttribute, FunctionAttributes, Modifier, Mutability, Override, VariableAttribute,
VariableAttributes, Visibility,
FunctionAttribute, FunctionAttributes, Modifier, Mutability, Override, Storage,
VariableAttribute, VariableAttributes, Visibility,
};

mod file;
Expand All @@ -22,12 +30,6 @@ pub use ident::{SolIdent, SolPath};
mod item;
pub use item::{Item, ItemError, ItemFunction, ItemStruct, ItemUdt};

#[macro_use]
mod macros;

mod storage;
pub use storage::Storage;

mod r#type;
pub use r#type::{SolArray, SolTuple, Type};

Expand Down
81 changes: 81 additions & 0 deletions crates/syn-solidity/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,84 @@ macro_rules! make_visitor {
)*
};
}

macro_rules! kw_enum {
(
$(#[$attr:meta])*
$vis:vis enum $name:ident {$(
$(#[$variant_attr:meta])*
$variant:ident(kw::$kw:ident)
),+ $(,)?}
) => {
$(#[$attr])*
#[derive(Clone, Copy, Eq)]
$vis enum $name {$(
$(#[$variant_attr])*
$variant($crate::kw::$kw),
)+}

impl ::core::cmp::PartialEq for $name {
fn eq(&self, other: &Self) -> bool {
::core::mem::discriminant(self) == ::core::mem::discriminant(other)
}
}

impl ::core::hash::Hash for $name {
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
::core::hash::Hash::hash(&::core::mem::discriminant(self), state)
}
}

impl ::core::fmt::Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(self.as_debug_str(), f)
}
}

impl ::core::fmt::Display for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Display::fmt(self.as_str(), f)
}
}

impl ::syn::parse::Parse for $name {
fn parse(input: ::syn::parse::ParseStream<'_>) -> ::syn::Result<Self> {
let l = input.lookahead1();
$(
if l.peek($crate::kw::$kw) {
input.parse::<$crate::kw::$kw>().map(Self::$variant)
} else
)+
{
Err(l.error())
}
}
}

impl $name {
pub const fn span(self) -> ::proc_macro2::Span {
match self {$(
Self::$variant(kw) => kw.span,
)+}
}

pub fn set_span(&mut self, span: ::proc_macro2::Span) {
match self {$(
Self::$variant(kw) => kw.span = span,
)+}
}

pub const fn as_str(self) -> &'static str {
match self {$(
Self::$variant(..) => stringify!($kw),
)+}
}

pub const fn as_debug_str(self) -> &'static str {
match self {$(
Self::$variant(..) => stringify!($variant),
)+}
}
}
};
}
Loading

0 comments on commit 9776da6

Please sign in to comment.