use crate::helpers::*;
use convert_case::{Case, Casing};
use genco::prelude::*;
use rust::Tokens;
use sails_idl_parser::{ast::visitor, ast::visitor::Visitor, ast::*};
pub(crate) struct CtorGenerator<'a> {
service_name: &'a str,
sails_path: &'a str,
ctor_tokens: Tokens,
io_tokens: Tokens,
trait_ctors_tokens: Tokens,
}
impl<'a> CtorGenerator<'a> {
pub(crate) fn new(service_name: &'a str, sails_path: &'a str) -> Self {
Self {
service_name,
sails_path,
ctor_tokens: Tokens::new(),
io_tokens: Tokens::new(),
trait_ctors_tokens: Tokens::new(),
}
}
pub(crate) fn finalize(self) -> Tokens {
quote! {
pub trait $(self.service_name)Ctors {
type Env: $(self.sails_path)::client::GearEnv;
$(self.trait_ctors_tokens)
}
impl<E: $(self.sails_path)::client::GearEnv> $(self.service_name)Ctors for $(self.sails_path)::client::Deployment<$(self.service_name)Program, E> {
type Env = E;
$(self.ctor_tokens)
}
$['\n']
pub mod io {
use super::*;
$(self.io_tokens)
}
}
}
}
impl<'ast> Visitor<'ast> for CtorGenerator<'_> {
fn visit_ctor(&mut self, ctor: &'ast Ctor) {
visitor::accept_ctor(ctor, self);
}
fn visit_ctor_func(&mut self, func: &'ast CtorFunc) {
let fn_name = func.name();
let fn_name_snake = &fn_name.to_case(Case::Snake);
let params_with_types = &fn_args_with_types(func.params());
let args = &encoded_args(func.params());
for doc in func.docs() {
quote_in! { self.trait_ctors_tokens =>
$['\r'] $("///") $doc
};
}
if fn_name_snake == "new" {
quote_in! {self.trait_ctors_tokens =>
$['\r'] #[allow(clippy::new_ret_no_self)]
$['\r'] #[allow(clippy::wrong_self_convention)]
};
}
quote_in! { self.trait_ctors_tokens =>
$['\r']
fn $fn_name_snake (self, $params_with_types) -> $(self.sails_path)::client::PendingCtor<$(self.service_name)Program, io::$fn_name, Self::Env>;
};
quote_in! { self.ctor_tokens =>
$['\r']
fn $fn_name_snake (self, $params_with_types) -> $(self.sails_path)::client::PendingCtor<$(self.service_name)Program, io::$fn_name, Self::Env> {
self.pending_ctor($args)
}
};
let params_with_types_super = &fn_args_with_types_path(func.params(), "super");
quote_in! { self.io_tokens =>
$(self.sails_path)::io_struct_impl!($fn_name ($params_with_types_super) -> ());
};
}
}