Unverified Commit 2cf8c3da authored by Michael Müller's avatar Michael Müller Committed by GitHub
Browse files

Extract functionality to `lang::ir::utils` (#1392)

parent 17ec5fa5
Pipeline #214412 canceled with stages
in 1 minute and 5 seconds
......@@ -14,11 +14,11 @@
use crate::{
ast,
ast::MetaNameValue,
error::ExtError as _,
utils::{
duplicate_config_err,
WhitelistedAttributes,
},
};
use std::collections::HashMap;
use syn::spanned::Spanned;
/// The ink! configuration.
#[derive(Debug, Default, PartialEq, Eq)]
......@@ -33,83 +33,6 @@ pub struct Config {
whitelisted_attributes: WhitelistedAttributes,
}
/// The set of attributes that can be passed to call builder or call forwarder in the codegen.
#[derive(Debug, PartialEq, Eq)]
pub struct WhitelistedAttributes(pub HashMap<String, ()>);
impl Default for WhitelistedAttributes {
fn default() -> Self {
Self(HashMap::from([
// Conditional compilation
("cfg".to_string(), ()),
("cfg_attr".to_string(), ()),
// Diagnostics
("allow".to_string(), ()),
("warn".to_string(), ()),
("deny".to_string(), ()),
("forbid".to_string(), ()),
("deprecated".to_string(), ()),
("must_use".to_string(), ()),
// Documentation
("doc".to_string(), ()),
// Formatting
("rustfmt".to_string(), ()),
]))
}
}
impl WhitelistedAttributes {
/// Parses the `MetaNameValue` argument of `keep_attr` attribute. If the argument has
/// a correct format `"foo, bar"` then `foo`, `bar` will be included in
/// the whitelist of attributes. Else error about parsing will be returned.
pub fn parse_arg_value(&mut self, arg: &MetaNameValue) -> Result<(), syn::Error> {
return if let ast::PathOrLit::Lit(syn::Lit::Str(attributes)) = &arg.value {
attributes.value().split(',').for_each(|attribute| {
self.0.insert(attribute.trim().to_string(), ());
});
Ok(())
} else {
Err(format_err_spanned!(
arg,
"expected a string with attributes separated by `,`",
))
}
}
/// Returns the filtered input vector of whitelisted attributes.
/// All not whitelisted attributes are removed.
pub fn filter_attr(&self, attrs: Vec<syn::Attribute>) -> Vec<syn::Attribute> {
attrs
.into_iter()
.filter(|attr| {
if let Some(ident) = attr.path.get_ident() {
self.0.contains_key(&ident.to_string())
} else {
false
}
})
.collect()
}
}
/// Return an error to notify about duplicate ink! configuration arguments.
fn duplicate_config_err<F, S>(first: F, second: S, name: &str) -> syn::Error
where
F: Spanned,
S: Spanned,
{
format_err!(
second.span(),
"encountered duplicate ink! `{}` configuration argument",
name,
)
.into_combine(format_err!(
first.span(),
"first `{}` configuration argument here",
name
))
}
impl TryFrom<ast::AttributeArgs> for Config {
type Error = syn::Error;
......@@ -120,7 +43,7 @@ impl TryFrom<ast::AttributeArgs> for Config {
for arg in args.into_iter() {
if arg.name.is_ident("env") {
if let Some((_, ast)) = env {
return Err(duplicate_config_err(ast, arg, "env"))
return Err(duplicate_config_err(ast, arg, "env", "contract"))
}
if let ast::PathOrLit::Path(path) = &arg.value {
env = Some((Environment { path: path.clone() }, arg))
......@@ -239,7 +162,7 @@ mod tests {
env = ::my::env::Types,
env = ::my::other::env::Types,
},
Err("encountered duplicate ink! `env` configuration argument"),
Err("encountered duplicate ink! contract `env` configuration argument"),
);
}
......
......@@ -14,9 +14,8 @@
use crate::{
ast,
error::ExtError as _,
utils::duplicate_config_err,
};
use syn::spanned::Spanned;
/// The ink! configuration.
#[derive(Debug, Default, PartialEq, Eq)]
......@@ -28,24 +27,6 @@ pub struct StorageItemConfig {
derive: bool,
}
/// Return an error to notify about duplicate ink! ink storage configuration arguments.
fn duplicate_config_err<F, S>(first: F, second: S, name: &str) -> syn::Error
where
F: Spanned,
S: Spanned,
{
format_err!(
second.span(),
"encountered duplicate ink! storage item `{}` configuration argument",
name,
)
.into_combine(format_err!(
first.span(),
"first `{}` configuration argument here",
name
))
}
impl TryFrom<ast::AttributeArgs> for StorageItemConfig {
type Error = syn::Error;
......@@ -54,7 +35,12 @@ impl TryFrom<ast::AttributeArgs> for StorageItemConfig {
for arg in args.into_iter() {
if arg.name.is_ident("derive") {
if let Some(lit_bool) = derive {
return Err(duplicate_config_err(lit_bool, arg, "derive"))
return Err(duplicate_config_err(
lit_bool,
arg,
"derive",
"storage item",
))
}
if let ast::PathOrLit::Lit(syn::Lit::Bool(lit_bool)) = &arg.value {
derive = Some(lit_bool.clone())
......
......@@ -14,10 +14,11 @@
use crate::{
ast,
error::ExtError as _,
ir::config::WhitelistedAttributes,
utils::{
duplicate_config_err,
WhitelistedAttributes,
},
};
use syn::spanned::Spanned;
/// The ink! configuration.
#[derive(Debug, Default, PartialEq, Eq)]
......@@ -48,24 +49,6 @@ impl TraitDefinitionConfig {
}
}
/// Return an error to notify about duplicate ink! trait definition configuration arguments.
fn duplicate_config_err<F, S>(first: F, second: S, name: &str) -> syn::Error
where
F: Spanned,
S: Spanned,
{
format_err!(
second.span(),
"encountered duplicate ink! trait definition `{}` configuration argument",
name,
)
.into_combine(format_err!(
first.span(),
"first `{}` configuration argument here",
name
))
}
impl TryFrom<ast::AttributeArgs> for TraitDefinitionConfig {
type Error = syn::Error;
......@@ -75,7 +58,12 @@ impl TryFrom<ast::AttributeArgs> for TraitDefinitionConfig {
for arg in args.into_iter() {
if arg.name.is_ident("namespace") {
if let Some((_, meta_name_value)) = namespace {
return Err(duplicate_config_err(meta_name_value, arg, "namespace"))
return Err(duplicate_config_err(
meta_name_value,
arg,
"namespace",
"trait definition",
))
}
if let ast::PathOrLit::Lit(syn::Lit::Str(lit_str)) = &arg.value {
if syn::parse_str::<syn::Ident>(&lit_str.value()).is_err() {
......
......@@ -13,9 +13,15 @@
// limitations under the License.
use super::Selector;
use crate::format_err;
use crate::{
ast,
ast::MetaNameValue,
error::ExtError as _,
format_err,
};
use proc_macro2::Span;
use syn::spanned::Spanned as _;
use std::collections::HashMap;
use syn::spanned::Spanned;
/// Ensures that the given visibility is `pub` and otherwise returns an appropriate error.
///
......@@ -55,3 +61,86 @@ pub fn local_message_id(ident: &syn::Ident) -> u32 {
let selector = Selector::compute(&input);
selector.into_be_u32()
}
/// The set of attributes that can be passed to call builder or call forwarder in the codegen.
#[derive(Debug, PartialEq, Eq)]
pub struct WhitelistedAttributes(pub HashMap<String, ()>);
impl Default for WhitelistedAttributes {
fn default() -> Self {
Self(HashMap::from([
// Conditional compilation
("cfg".to_string(), ()),
("cfg_attr".to_string(), ()),
// Diagnostics
("allow".to_string(), ()),
("warn".to_string(), ()),
("deny".to_string(), ()),
("forbid".to_string(), ()),
("deprecated".to_string(), ()),
("must_use".to_string(), ()),
// Documentation
("doc".to_string(), ()),
// Formatting
("rustfmt".to_string(), ()),
]))
}
}
impl WhitelistedAttributes {
/// Parses the `MetaNameValue` argument of `keep_attr` attribute. If the argument has
/// a correct format `"foo, bar"` then `foo`, `bar` will be included in
/// the whitelist of attributes. Else error about parsing will be returned.
pub fn parse_arg_value(&mut self, arg: &MetaNameValue) -> Result<(), syn::Error> {
return if let ast::PathOrLit::Lit(syn::Lit::Str(attributes)) = &arg.value {
attributes.value().split(',').for_each(|attribute| {
self.0.insert(attribute.trim().to_string(), ());
});
Ok(())
} else {
Err(format_err_spanned!(
arg,
"expected a string with attributes separated by `,`",
))
}
}
/// Returns the filtered input vector of whitelisted attributes.
/// All not whitelisted attributes are removed.
pub fn filter_attr(&self, attrs: Vec<syn::Attribute>) -> Vec<syn::Attribute> {
attrs
.into_iter()
.filter(|attr| {
if let Some(ident) = attr.path.get_ident() {
self.0.contains_key(&ident.to_string())
} else {
false
}
})
.collect()
}
}
/// Return an error to notify about duplicate ink! configuration arguments.
pub(crate) fn duplicate_config_err<F, S>(
first: F,
second: S,
name: &str,
ink_attr: &str,
) -> syn::Error
where
F: Spanned,
S: Spanned,
{
format_err!(
second.span(),
"encountered duplicate ink! {} `{}` configuration argument",
ink_attr,
name,
)
.into_combine(format_err!(
first.span(),
"first `{}` configuration argument here",
name
))
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment