// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::Span; use std::collections::HashSet; use syn::{ parse::{Parse, ParseStream}, spanned::Spanned, token, Error, Ident, Result, Token, }; mod keyword { syn::custom_keyword!(Block); syn::custom_keyword!(NodeBlock); syn::custom_keyword!(UncheckedExtrinsic); syn::custom_keyword!(Module); syn::custom_keyword!(Call); syn::custom_keyword!(Storage); syn::custom_keyword!(Event); syn::custom_keyword!(Config); syn::custom_keyword!(Origin); syn::custom_keyword!(Inherent); syn::custom_keyword!(ValidateUnsigned); } #[derive(Debug)] pub struct RuntimeDefinition { pub visibility_token: Token![pub], pub enum_token: Token![enum], pub name: Ident, pub where_section: WhereSection, pub modules: ext::Braces>, } impl Parse for RuntimeDefinition { fn parse(input: ParseStream) -> Result { Ok(Self { visibility_token: input.parse()?, enum_token: input.parse()?, name: input.parse()?, where_section: input.parse()?, modules: input.parse()?, }) } } #[derive(Debug)] pub struct WhereSection { pub block: syn::TypePath, pub node_block: syn::TypePath, pub unchecked_extrinsic: syn::TypePath, } impl Parse for WhereSection { fn parse(input: ParseStream) -> Result { input.parse::()?; let mut definitions = Vec::new(); while !input.peek(token::Brace) { let definition: WhereDefinition = input.parse()?; definitions.push(definition); if !input.peek(Token![,]) { if !input.peek(token::Brace) { return Err(input.error("Expected `,` or `{`")); } break; } input.parse::()?; } let block = remove_kind(input, WhereKind::Block, &mut definitions)?.value; let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value; let unchecked_extrinsic = remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value; if let Some(WhereDefinition { ref kind_span, ref kind, .. }) = definitions.first() { let msg = format!( "`{:?}` was declared above. Please use exactly one declaration for `{:?}`.", kind, kind ); return Err(Error::new(*kind_span, msg)); } Ok(Self { block, node_block, unchecked_extrinsic, }) } } #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum WhereKind { Block, NodeBlock, UncheckedExtrinsic, } #[derive(Debug)] pub struct WhereDefinition { pub kind_span: Span, pub kind: WhereKind, pub value: syn::TypePath, } impl Parse for WhereDefinition { fn parse(input: ParseStream) -> Result { let lookahead = input.lookahead1(); let (kind_span, kind) = if lookahead.peek(keyword::Block) { (input.parse::()?.span(), WhereKind::Block) } else if lookahead.peek(keyword::NodeBlock) { ( input.parse::()?.span(), WhereKind::NodeBlock, ) } else if lookahead.peek(keyword::UncheckedExtrinsic) { ( input.parse::()?.span(), WhereKind::UncheckedExtrinsic, ) } else { return Err(lookahead.error()); }; Ok(Self { kind_span, kind, value: { let _: Token![=] = input.parse()?; input.parse()? }, }) } } #[derive(Debug)] pub struct ModuleDeclaration { pub name: Ident, pub module: Ident, pub instance: Option, pub module_parts: Vec, } impl Parse for ModuleDeclaration { fn parse(input: ParseStream) -> Result { let name = input.parse()?; let _: Token![:] = input.parse()?; let module = input.parse()?; let instance = if input.peek(Token![::]) && input.peek3(Token![<]) { let _: Token![::] = input.parse()?; let _: Token![<] = input.parse()?; let res = Some(input.parse()?); let _: Token![>] = input.parse()?; res } else { None }; let _: Token![::] = input.parse()?; let module_parts = parse_module_parts(input)?; let parsed = Self { name, module, instance, module_parts, }; Ok(parsed) } } impl ModuleDeclaration { /// Get resolved module parts pub fn module_parts(&self) -> &[ModulePart] { &self.module_parts } pub fn find_part(&self, name: &str) -> Option<&ModulePart> { self.module_parts.iter().find(|part| part.name() == name) } pub fn exists_part(&self, name: &str) -> bool { self.find_part(name).is_some() } } /// Parse [`ModulePart`]'s from a braces enclosed list that is split by commas, e.g. /// /// `{ Call, Event }` fn parse_module_parts(input: ParseStream) -> Result> { let module_parts :ext::Braces> = input.parse()?; let mut resolved = HashSet::new(); for part in module_parts.content.inner.iter() { if !resolved.insert(part.name()) { let msg = format!( "`{}` was already declared before. Please remove the duplicate declaration", part.name(), ); return Err(Error::new(part.keyword.span(), msg)); } } Ok(module_parts.content.inner.into_iter().collect()) } #[derive(Debug, Clone)] pub enum ModulePartKeyword { Module(keyword::Module), Call(keyword::Call), Storage(keyword::Storage), Event(keyword::Event), Config(keyword::Config), Origin(keyword::Origin), Inherent(keyword::Inherent), ValidateUnsigned(keyword::ValidateUnsigned), } impl Parse for ModulePartKeyword { fn parse(input: ParseStream) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(keyword::Module) { Ok(Self::Module(input.parse()?)) } else if lookahead.peek(keyword::Call) { Ok(Self::Call(input.parse()?)) } else if lookahead.peek(keyword::Storage) { Ok(Self::Storage(input.parse()?)) } else if lookahead.peek(keyword::Event) { Ok(Self::Event(input.parse()?)) } else if lookahead.peek(keyword::Config) { Ok(Self::Config(input.parse()?)) } else if lookahead.peek(keyword::Origin) { Ok(Self::Origin(input.parse()?)) } else if lookahead.peek(keyword::Inherent) { Ok(Self::Inherent(input.parse()?)) } else if lookahead.peek(keyword::ValidateUnsigned) { Ok(Self::ValidateUnsigned(input.parse()?)) } else { Err(lookahead.error()) } } } impl ModulePartKeyword { /// Returns the name of `Self`. fn name(&self) -> &'static str { match self { Self::Module(_) => "Module", Self::Call(_) => "Call", Self::Storage(_) => "Storage", Self::Event(_) => "Event", Self::Config(_) => "Config", Self::Origin(_) => "Origin", Self::Inherent(_) => "Inherent", Self::ValidateUnsigned(_) => "ValidateUnsigned", } } /// Returns the name as `Ident`. fn ident(&self) -> Ident { Ident::new(self.name(), self.span()) } /// Returns `true` if this module part allows to have an argument. /// /// For example `Inherent(Timestamp)`. fn allows_arg(&self) -> bool { Self::all_allow_arg().iter().any(|n| *n == self.name()) } /// Returns the names of all module parts that allow to have an argument. fn all_allow_arg() -> &'static [&'static str] { &["Inherent"] } /// Returns `true` if this module part is allowed to have generic arguments. fn allows_generic(&self) -> bool { Self::all_generic_arg().iter().any(|n| *n == self.name()) } /// Returns the names of all module parts that allow to have a generic argument. fn all_generic_arg() -> &'static [&'static str] { &["Event", "Origin", "Config"] } } impl Spanned for ModulePartKeyword { fn span(&self) -> Span { match self { Self::Module(inner) => inner.span(), Self::Call(inner) => inner.span(), Self::Storage(inner) => inner.span(), Self::Event(inner) => inner.span(), Self::Config(inner) => inner.span(), Self::Origin(inner) => inner.span(), Self::Inherent(inner) => inner.span(), Self::ValidateUnsigned(inner) => inner.span(), } } } #[derive(Debug, Clone)] pub struct ModulePart { pub keyword: ModulePartKeyword, pub generics: syn::Generics, pub args: Option>>, } impl Parse for ModulePart { fn parse(input: ParseStream) -> Result { let keyword: ModulePartKeyword = input.parse()?; let generics: syn::Generics = input.parse()?; if !generics.params.is_empty() && !keyword.allows_generic() { let valid_generics = ModulePart::format_names(ModulePartKeyword::all_generic_arg()); let msg = format!( "`{}` is not allowed to have generics. \ Only the following modules are allowed to have generics: {}.", keyword.name(), valid_generics, ); return Err(syn::Error::new(keyword.span(), msg)); } let args = if input.peek(token::Paren) { if !keyword.allows_arg() { let syn::group::Parens { token: parens, .. } = syn::group::parse_parens(input)?; let valid_names = ModulePart::format_names(ModulePartKeyword::all_allow_arg()); let msg = format!( "`{}` is not allowed to have arguments in parens. \ Only the following modules are allowed to have arguments in parens: {}.", keyword.name(), valid_names, ); return Err(syn::Error::new(parens.span, msg)); } Some(input.parse()?) } else { None }; Ok(Self { keyword, generics, args, }) } } impl ModulePart { pub fn format_names(names: &[&'static str]) -> String { let res: Vec<_> = names.into_iter().map(|s| format!("`{}`", s)).collect(); res.join(", ") } /// The name of this module part. pub fn name(&self) -> &'static str { self.keyword.name() } /// The name of this module part as `Ident`. pub fn ident(&self) -> Ident { self.keyword.ident() } } fn remove_kind( input: ParseStream, kind: WhereKind, definitions: &mut Vec, ) -> Result { if let Some(pos) = definitions.iter().position(|d| d.kind == kind) { Ok(definitions.remove(pos)) } else { let msg = format!( "Missing associated type for `{:?}`. Add `{:?}` = ... to where section.", kind, kind ); Err(input.error(msg)) } }