use ink_analyzer_macro::{FromInkAttribute, FromSyntax};
use ra_ap_syntax::ast;
use crate::traits::{FromInkAttribute, FromSyntax};
use crate::tree::utils;
use crate::{
Constructor, Event, InkArg, InkArgKind, InkAttrData, InkAttribute, InkE2ETest, InkImpl,
InkTest, Message, Storage,
};
#[derive(Debug, Clone, PartialEq, Eq, FromInkAttribute, FromSyntax)]
pub struct Contract {
#[macro_kind(Contract)]
ink_attr: InkAttrData<ast::Module>,
#[arg_kind(Storage)]
storage: Option<Storage>,
#[arg_kind(Event)]
events: Vec<Event>,
#[arg_kind(Impl)]
impls: Vec<InkImpl>,
#[arg_kind(Constructor)]
constructors: Vec<Constructor>,
#[arg_kind(Message)]
messages: Vec<Message>,
#[macro_kind(Test)]
tests: Vec<InkTest>,
#[macro_kind(E2ETest)]
e2e_tests: Vec<InkE2ETest>,
}
impl Contract {
pub fn module(&self) -> Option<&ast::Module> {
self.ink_attr.parent_ast()
}
pub fn env_arg(&self) -> Option<InkArg> {
utils::ink_arg_by_kind(self.syntax(), InkArgKind::Env)
}
pub fn keep_attr_arg(&self) -> Option<InkArg> {
utils::ink_arg_by_kind(self.syntax(), InkArgKind::KeepAttr)
}
pub fn storage(&self) -> Option<&Storage> {
self.storage.as_ref()
}
pub fn events(&self) -> &[Event] {
&self.events
}
pub fn impls(&self) -> &[InkImpl] {
&self.impls
}
pub fn constructors(&self) -> &[Constructor] {
&self.constructors
}
pub fn messages(&self) -> &[Message] {
&self.messages
}
pub fn tests(&self) -> &[InkTest] {
&self.tests
}
pub fn e2e_tests(&self) -> &[InkE2ETest] {
&self.e2e_tests
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::*;
use test_utils::quote_as_str;
#[test]
fn cast_works() {
let ink_attr = parse_first_ink_attribute(quote_as_str! {
#[ink::contract(env=my::env::Types, keep_attr="foo,bar")]
mod MyContract {
#[ink(storage)]
pub struct MyContract {}
#[ink(event)]
pub struct MyEvent {
}
#[ink(event, anonymous)]
pub struct MyEvent2 {
}
impl MyContract {
#[ink(constructor, payable, default, selector=_)]
pub fn my_constructor() -> Self {}
#[ink(message, payable, default, selector=_)]
pub fn my_message(&self) {}
}
impl MyTrait for MyContract {
#[ink(constructor, payable, default, selector=1)]
fn my_constructor() -> Self {}
#[ink(message, payable, default, selector=1)]
fn my_message(&self) {}
}
impl ::my_full::long_path::MyTrait for MyContract {
#[ink(constructor, payable, default, selector=0x2)]
fn my_constructor() -> Self {}
#[ink(message, payable, default, selector=0x2)]
fn my_message(&self) {}
}
impl relative_path::MyTrait for MyContract {
#[ink(constructor)]
fn my_constructor() -> Self {}
#[ink(message)]
fn my_message(&self) {}
}
#[ink(namespace="my_namespace")]
impl MyContract {
#[ink(constructor)]
pub fn my_constructor() -> Self {}
#[ink(message)]
pub fn my_message(&self) {}
}
#[ink(impl)]
impl MyContract {
#[ink(constructor)]
pub fn my_constructor() -> Self {}
#[ink(message)]
pub fn my_message(&self) {}
}
#[ink(impl, namespace="my_namespace")]
impl MyContract {
#[ink(constructor)]
pub fn my_constructor() -> Self {}
#[ink(message)]
pub fn my_message(&self) {}
}
#[ink(impl)]
impl MyContract {
}
#[cfg(test)]
mod tests {
#[ink::test]
fn it_works {
}
#[ink::test]
fn it_works2 {
}
}
}
});
let contract = Contract::cast(ink_attr).unwrap();
assert!(contract.env_arg().is_some());
assert!(contract.keep_attr_arg().is_some());
assert!(contract.storage().is_some());
assert_eq!(contract.events().len(), 2);
assert_eq!(contract.impls().len(), 8);
assert_eq!(contract.constructors().len(), 7);
assert_eq!(contract.messages().len(), 7);
assert_eq!(contract.tests().len(), 2);
assert!(contract.module().is_some());
}
}