Unverified Commit d803c2e2 authored by Hero Bird's avatar Hero Bird Committed by GitHub
Browse files

Ink cleanup (#101)

* [ink] Fix some clippy warnings

* [lang] Major clean ups in preparation of greater refactorings
parent baefcfd8
......@@ -17,7 +17,10 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
not(feature = "std"),
feature(core_intrinsics, alloc_error_handler,)
feature(
alloc_error_handler,
core_intrinsics,
)
)]
// Use `wee_alloc` as the global allocator.
......
......@@ -67,7 +67,7 @@ fn initialize_for_lang(name: &str) -> Result<()> {
}
}
let mut outfile = fs::File::create(&outpath)?;
outfile.write(contents.as_bytes())?;
outfile.write_all(contents.as_bytes())?;
}
// Get and set permissions
......@@ -84,7 +84,7 @@ fn initialize_for_lang(name: &str) -> Result<()> {
Ok(())
}
pub(crate) fn execute_new(layer: &AbstractionLayer, name: &str) -> Result<()> {
pub(crate) fn execute_new(layer: AbstractionLayer, name: &str) -> Result<()> {
match layer {
AbstractionLayer::Core => {
Err(CommandError::new(
......
......@@ -106,7 +106,7 @@ fn main() -> cmd::Result<()> {
CommandErrorKind,
};
match &args.cmd {
Command::New { layer, name } => cmd::execute_new(layer, name),
Command::New { layer, name } => cmd::execute_new(*layer, name),
Command::Build {} => {
Err(CommandError::new(CommandErrorKind::UnimplementedCommand))
}
......
......@@ -122,15 +122,13 @@ impl CellChunkAlloc {
/// Allocates a new storage region that fits for a single cell.
fn alloc_cell(&mut self) -> Key {
let index = self.cells.put(());
let key = self.cell_index_to_key(index);
key
self.cell_index_to_key(index)
}
/// Allocates a new storage region that fits for a whole chunk.
fn alloc_chunk(&mut self) -> Key {
let index = self.chunks.put(());
let key = self.chunk_index_to_key(index);
key
self.chunk_index_to_key(index)
}
/// Deallocates a storage region fit for a single cell.
......
......@@ -16,17 +16,13 @@
use crate::{
ast,
errors::{
Errors,
Result,
},
hir,
ident_ext::IdentExt,
};
use serde::{
Deserialize,
Serialize,
};
use syn::{self, Result};
use std::convert::TryFrom;
/// Describes a message parameter or return type.
......@@ -59,7 +55,7 @@ pub enum OptionTypeDescription {
}
impl TryFrom<&syn::TypePath> for OptionTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(type_path: &syn::TypePath) -> Result<Self> {
if type_path.qself.is_some() || type_path.path.leading_colon.is_some() {
......@@ -107,7 +103,7 @@ pub enum VecTypeDescription {
}
impl TryFrom<&syn::TypePath> for VecTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(type_path: &syn::TypePath) -> Result<Self> {
if type_path.qself.is_some() || type_path.path.leading_colon.is_some() {
......@@ -154,7 +150,7 @@ pub enum ResultTypeDescription {
}
impl TryFrom<&syn::TypePath> for ResultTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(type_path: &syn::TypePath) -> Result<Self> {
if type_path.qself.is_some() || type_path.path.leading_colon.is_some() {
......@@ -194,7 +190,7 @@ impl TryFrom<&syn::TypePath> for ResultTypeDescription {
}
impl TryFrom<&syn::Type> for TypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(ty: &syn::Type) -> Result<Self> {
match ty {
......@@ -209,7 +205,7 @@ impl TryFrom<&syn::Type> for TypeDescription {
bail!(path, "invalid self qualifier or leading `::` for type")
}
let ident = &path.path.segments[0].ident;
match ident.to_owned_string().as_str() {
match ident.to_string().as_str() {
"Option" => {
OptionTypeDescription::try_from(path).map(TypeDescription::Option)
}
......@@ -270,7 +266,7 @@ pub enum PrimitiveTypeDescription {
}
impl TryFrom<&syn::TypePath> for PrimitiveTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(ty: &syn::TypePath) -> Result<Self> {
use quote::ToTokens;
......@@ -308,7 +304,7 @@ pub struct TupleTypeDescription {
}
impl TryFrom<&syn::TypeTuple> for TupleTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(arg: &syn::TypeTuple) -> Result<Self> {
let elems = arg
......@@ -333,7 +329,7 @@ pub enum ArrayTypeDescription {
}
impl TryFrom<&syn::TypeArray> for ArrayTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(arg: &syn::TypeArray) -> Result<Self> {
let ty = TypeDescription::try_from(&*arg.elem)?;
......@@ -363,11 +359,11 @@ pub struct ParamDescription {
}
impl TryFrom<&syn::ArgCaptured> for ParamDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(arg: &syn::ArgCaptured) -> Result<Self> {
let name = match &arg.pat {
syn::Pat::Ident(ident) => ident.ident.to_owned_string(),
syn::Pat::Ident(ident) => ident.ident.to_string(),
_ => {
bail!(arg.pat, "unsupported type pattern, currently only identifiers like `foo` are supported")
}
......@@ -387,7 +383,7 @@ pub struct DeployDescription {
}
impl TryFrom<&hir::DeployHandler> for DeployDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(deploy_handler: &hir::DeployHandler) -> Result<Self> {
let args = deploy_handler
......@@ -429,7 +425,7 @@ impl ReturnTypeDescription {
}
impl TryFrom<&syn::ReturnType> for ReturnTypeDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(ret_ty: &syn::ReturnType) -> Result<Self> {
match ret_ty {
......@@ -459,11 +455,11 @@ pub struct MessageDescription {
}
impl TryFrom<&hir::Message> for MessageDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(message: &hir::Message) -> Result<Self> {
Ok(Self {
name: message.sig.ident.to_owned_string(),
name: message.sig.ident.to_string(),
selector: message.selector().into(),
mutates: message.is_mut(),
args: {
......@@ -506,11 +502,11 @@ impl ContractDescription {
}
impl TryFrom<&hir::Contract> for ContractDescription {
type Error = Errors;
type Error = syn::Error;
fn try_from(contract: &hir::Contract) -> Result<Self> {
Ok(ContractDescription {
name: contract.name.to_owned_string(),
name: contract.name.to_string(),
deploy: DeployDescription::try_from(&contract.on_deploy)?,
messages: {
contract
......
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! 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.
//
// ink! 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 ink!. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::TokenStream as TokenStream2;
use syn::Result;
use crate::{
parser,
hir,
gen,
};
pub fn generate(input: TokenStream2) -> TokenStream2 {
match generate_or_err(input) {
Ok(tokens) => tokens,
Err(err) => err.to_compile_error(),
}
}
pub fn generate_or_err(input: TokenStream2) -> Result<TokenStream2> {
let ast_contract = parser::parse_contract(input.clone())?;
let hir_contract = hir::Contract::from_ast(&ast_contract)?;
generate_api_description(&hir_contract)?;
let tokens = gen::generate_code(&hir_contract);
Ok(tokens)
}
#[cfg(feature = "generate-api-description")]
fn generate_api_description(contract: &hir::Contract) -> Result<()> {
crate::api::generate_api_description(&contract)
}
#[cfg(not(feature = "generate-api-description"))]
fn generate_api_description(_contract: &hir::Contract) -> Result<()> {
Ok(())
}
......@@ -14,11 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::TokenStream as TokenStream2;
use quote::ToTokens;
use std::result::Result as StdResult;
pub use syn::parse::Error as SynError;
macro_rules! bail {
($($args:tt)*) => {
return Err(format_err!($($args)*).into())
......@@ -34,48 +29,3 @@ macro_rules! format_err {
}
}
}
/// A collection of errors.
///
/// # Note
///
/// This is used to allow for reporting multiple errors at the same time.
#[derive(Debug)]
pub struct Errors {
errors: Vec<SynError>,
}
impl From<SynError> for Errors {
fn from(err: SynError) -> Errors {
Errors { errors: vec![err] }
}
}
impl From<Vec<Errors>> for Errors {
fn from(err: Vec<Errors>) -> Errors {
let result = err.into_iter().flat_map(|v| v.errors).collect::<Vec<_>>();
assert!(!result.is_empty());
Errors { errors: result }
}
}
/// Used to create a TokenStream from a list of errors
impl ToTokens for Errors {
fn to_tokens(&self, tokens: &mut TokenStream2) {
for item in self.errors.iter() {
item.to_compile_error().to_tokens(tokens);
}
}
}
impl std::fmt::Display for Errors {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for err in &self.errors {
err.fmt(f)?;
}
Ok(())
}
}
/// Result type alias for an error type which allows for accumulating errors.
pub type Result<T> = StdResult<T, Errors>;
......@@ -243,10 +243,9 @@ fn codegen_for_instantiate(tokens: &mut TokenStream2, contract: &hir::Contract)
for message in &contract.messages {
let msg_ident = &message.sig.ident;
use crate::ident_ext::IdentExt as _;
use heck::CamelCase as _;
let camelcase_msg_ident = Ident::new(
&message.sig.ident.to_owned_string().to_camel_case(),
&message.sig.ident.to_string().to_camel_case(),
message.sig.ident.span(),
);
......@@ -466,10 +465,9 @@ fn codegen_for_messages(tokens: &mut TokenStream2, contract: &hir::Contract) {
);
msg_id.to_tokens(&mut content);
<Token![=>]>::default().to_tokens(&mut content);
use crate::ident_ext::IdentExt as _;
use heck::CamelCase as _;
let camel_case_ident = Ident::new(
&message.sig.ident.to_owned_string().to_camel_case(),
&message.sig.ident.to_string().to_camel_case(),
message.sig.ident.span(),
);
camel_case_ident.to_tokens(&mut content);
......
......@@ -62,7 +62,7 @@ fn generate_test_mod_body(contract: &hir::Contract) -> TokenStream2 {
///
/// For a contract called `Flipper` this returns `TestableFlipper`.
fn testable_contract_name(contract: &hir::Contract) -> proc_macro2::Ident {
proc_macro2::Ident::from_str(["Testable", &contract.name.to_owned_string()].concat())
proc_macro2::Ident::from_str(["Testable", &contract.name.to_string()].concat())
}
fn generate_test_struct(tokens: &mut TokenStream2, contract: &hir::Contract) {
......
......@@ -14,19 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use crate::{
ast,
errors::{
Result,
SynError,
},
};
use crate::ast;
use proc_macro2::{
Ident,
Span,
};
use syn::{
self,
Result,
punctuated::Punctuated,
Token,
};
......@@ -69,7 +64,7 @@ impl Contract {
contract: &ast::Contract,
) -> Result<Vec<Event>> {
let events = contract.events().collect::<Vec<_>>();
let mut unique_events = std::collections::HashSet::new();
let mut unique_events = std::collections::HashSet::<&ast::ItemEvent>::new();
for event in &events {
if &event.ident == contract_ident {
bail!(
......@@ -78,7 +73,7 @@ impl Contract {
)
}
if !unique_events.contains(event) {
unique_events.insert(event.clone());
unique_events.insert(event);
} else {
bail!(
event.ident,
......@@ -110,21 +105,19 @@ impl Contract {
fn extract_state(contract: &ast::Contract) -> Result<(&Ident, State)> {
let states = contract.states().collect::<Vec<_>>();
if states.is_empty() {
return Err(SynError::new(
return Err(syn::Error::new(
Span::call_site(),
"couldn't find a contract state `struct`",
)
.into())
))
}
if states.len() > 1 {
return Err(SynError::new(
return Err(syn::Error::new(
Span::call_site(),
format!(
"requires exactly one contract state `struct`; found {:?}",
states.len()
),
)
.into())
))
}
let state = states[0];
Ok((&state.ident, State::from(state)))
......@@ -136,11 +129,10 @@ impl Contract {
) -> Result<(Vec<Message>, Vec<Method>)> {
let impl_blocks = contract.impl_blocks().collect::<Vec<_>>();
if impl_blocks.is_empty() {
return Err(SynError::new(
return Err(syn::Error::new(
Span::call_site(),
"requires at least one contract impl block `struct`; found none",
)
.into())
))
}
for impl_block in impl_blocks.iter() {
if impl_block.self_ty != *contract_ident {
......@@ -441,8 +433,7 @@ impl Message {
/// Returns the message selector for this message.
pub fn selector(&self) -> u32 {
use crate::ident_ext::IdentExt;
raw_message_selector(self.sig.ident.to_owned_string().as_str())
raw_message_selector(self.sig.ident.to_string().as_str())
}
}
......
......@@ -18,15 +18,9 @@ use proc_macro2::{
Ident,
Span,
};
use std::fmt::Display;
/// Utilities for operating on `Ident` instances.
pub trait IdentExt: Display {
/// Creates a string out of the ident's name.
fn to_owned_string(&self) -> String {
format!("{}", self)
}
pub trait IdentExt {
/// Creates a new Ident from the given `str`.
fn from_str<T: AsRef<str>>(s: T) -> Ident {
Ident::new(s.as_ref(), Span::call_site())
......
......@@ -18,20 +18,8 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::ToTokens;
#[proc_macro]
pub fn contract(input: TokenStream) -> TokenStream {
match contract_gen_impl(input) {
Ok(tokens) => tokens,
Err(err) => err.into_token_stream().into(),
}
}
#[macro_use]
mod errors;
mod error;
#[cfg(feature = "generate-api-description")]
mod api;
......@@ -45,35 +33,14 @@ mod parser;
#[cfg(test)]
mod tests;
use errors::Result;
/// Simple wrapper from `proc_macro` to `proc_macro2` and back again.
///
/// # Note
///
/// The actual `proc_macro` interface has to operate on `proc_macro::TokenStream`
/// but to keep this library testable we want to use only `proc_macro2::*` entities
/// internally.
fn contract_gen_impl(input: TokenStream) -> Result<TokenStream> {
contract_gen_impl2(input.into()).map(Into::into)
}
mod contract;
/// Parses the given token stream as pDSL contract, performs some checks and returns
/// the corresponding contract as token stream.
pub(crate) fn contract_gen_impl2(input: TokenStream2) -> Result<TokenStream2> {
let ast_contract = parser::parse_contract(input.clone())?;
let hir_contract = hir::Contract::from_ast(&ast_contract)?;
generate_api_description(&hir_contract)?;
let tokens = gen::generate_code(&hir_contract);
Ok(tokens)
}
use proc_macro::TokenStream;
#[cfg(feature = "generate-api-description")]
fn generate_api_description(contract: &hir::Contract) -> Result<()> {
api::generate_api_description(&contract)
#[proc_macro]
pub fn contract(input: TokenStream) -> TokenStream {
contract::generate(input.into()).into()
}
#[cfg(not(feature = "generate-api-description"))]
fn generate_api_description(_contract: &hir::Contract) -> Result<()> {
Ok(())
}
#[cfg(test)]
pub use contract::generate_or_err;
......@@ -20,7 +20,7 @@ mod incrementer;
mod noop;
mod utils;
pub(crate) use crate::contract_gen_impl2;
pub(crate) use crate::generate_or_err;
pub(crate) use quote::quote;
pub(crate) use utils::{
assert_eq_tokenstreams,
......@@ -29,7 +29,7 @@ pub(crate) use utils::{
#[test]
fn empty_contract_input() {
assert!(contract_gen_impl2(quote! {}).is_err());
assert!(generate_or_err(quote! {}).is_err());
}
#[test]
......
......@@ -16,11 +16,11 @@
use pretty_assertions::assert_eq;
use crate::contract_gen_impl2;
use crate::generate_or_err;
use proc_macro2::TokenStream as TokenStream2;
pub fn assert_eq_tokenstreams(input: TokenStream2, expected: TokenStream2) {
let result = contract_gen_impl2(input)
let result = generate_or_err(input)
.map(|result| result.to_string())
.map_err(|err| err.to_string());
let expected = Ok(expected.to_string());
......@@ -29,7 +29,7 @@ pub fn assert_eq_tokenstreams(input: TokenStream2, expected: TokenStream2) {
pub fn assert_failure(input: TokenStream2, err_str: &'static str) {
assert_eq!(
contract_gen_impl2(input)
generate_or_err(input)
.map(|result| result.to_string())
.map_err(|err| err.to_string()),
Err(err_str.to_string())
......
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