use ra_ap_syntax::ast;
use ra_ap_syntax::ast::HasName;
use crate::traits::IsInkTrait;
use crate::{Extension, Function};
#[ink_analyzer_macro::entity(macro_kind = ChainExtension)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChainExtension {
ast: ast::Trait,
extensions: Vec<Extension>,
functions: Vec<Function>,
}
impl_ast_type_trait!(ChainExtension, IsInkTrait);
impl ChainExtension {
pub fn id(&self) -> Option<u16> {
self.extension_arg()?.value()?.as_u16()
}
impl_pub_ink_arg_getter!(extension_arg, Extension, extension);
pub fn error_code(&self) -> Option<ast::TypeAlias> {
self.trait_item()?
.assoc_item_list()
.map(|assoc_item_list| {
assoc_item_list
.assoc_items()
.find_map(|assoc_item| match assoc_item {
ast::AssocItem::TypeAlias(type_alias) => {
let name = type_alias.name()?;
(name.to_string() == "ErrorCode").then_some(type_alias)
}
_ => None,
})
})?
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::*;
use crate::traits::InkEntity;
use test_utils::quote_as_str;
#[test]
fn cast_works() {
let node = parse_first_syntax_node(quote_as_str! {
#[ink::chain_extension]
pub trait MyChainExtension {
type ErrorCode = ();
#[ink(extension=1)]
fn my_extension();
#[ink(extension=2)]
fn my_extension2();
}
});
let chain_extension = ChainExtension::cast(node).unwrap();
assert!(chain_extension.error_code().is_some());
assert_eq!(chain_extension.extensions().len(), 2);
assert!(chain_extension.trait_item().is_some());
}
#[test]
fn cast_v5_works() {
let node = parse_first_syntax_node(quote_as_str! {
#[ink::chain_extension(extension=1)]
pub trait MyChainExtension {
type ErrorCode = ();
#[ink(function=1)]
fn my_function();
#[ink(function=2)]
fn my_function2();
}
});
let chain_extension = ChainExtension::cast(node).unwrap();
assert!(chain_extension.error_code().is_some());
assert!(chain_extension.extension_arg().is_some());
assert_eq!(chain_extension.id(), Some(1));
assert_eq!(chain_extension.functions().len(), 2);
assert!(chain_extension.trait_item().is_some());
}
}