use crate::codegen::generator::codec::structs::CodecModePack;
use crate::codegen::ir::mir::comment::MirComment;
use crate::codegen::ir::mir::field::MirField;
use crate::codegen::ir::mir::ident::MirIdent;
use crate::codegen::ir::mir::ty::delegate::{
MirTypeDelegate, MirTypeDelegatePrimitiveEnum, MirTypeDelegateProxyVariant,
};
use crate::codegen::ir::mir::ty::primitive::MirTypePrimitive;
use crate::codegen::ir::mir::ty::trait_def::MirTypeTraitDef;
use crate::codegen::ir::mir::ty::{MirContext, MirType, MirTypeTrait};
use crate::if_then_some;
use crate::utils::namespace::{Namespace, NamespacedName};
use convert_case::{Case, Casing};
use itertools::Itertools;
crate::mir! {
pub struct MirFunc {
pub namespace: Namespace,
pub name: MirIdent,
pub id: Option<i32>,
pub inputs: Vec<MirFuncInput>,
pub output: MirFuncOutput,
pub owner: MirFuncOwnerInfo,
pub mode: MirFuncMode,
pub stream_dart_await: bool,
pub rust_async: bool,
pub initializer: bool,
pub arg_mode: MirFuncArgMode,
pub accessor: Option<MirFuncAccessorMode>,
pub comments: Vec<MirComment>,
pub codec_mode_pack: CodecModePack,
pub rust_call_code: Option<String>,
pub rust_aop_after: Option<String>,
pub impl_mode: MirFuncImplMode,
#[serde(skip_serializing)]
pub src_lineno_pseudo: usize,
}
pub struct MirFuncInput {
pub ownership_mode: Option<OwnershipMode>,
pub inner: MirField,
pub needs_extend_lifetime: bool,
}
pub struct MirFuncOutput {
pub normal: MirType,
pub error: Option<MirType>,
}
#[derive(Copy)]
pub enum MirFuncMode {
Normal,
Sync,
}
#[derive(Copy)]
pub enum MirFuncArgMode {
Positional,
Named,
}
pub enum MirFuncImplMode {
Normal,
NoImpl,
DartOnly(MirFuncImplModeDartOnly),
}
pub enum MirFuncImplModeDartOnly {
CreateProxyVariant(MirTypeDelegateProxyVariant),
}
#[allow(clippy::large_enum_variant)]
pub enum MirFuncOwnerInfo {
Function,
Method(MirFuncOwnerInfoMethod),
}
pub struct MirFuncOwnerInfoMethod {
pub(crate) owner_ty: MirType,
pub(crate) owner_ty_raw: String,
pub(crate) actual_method_name: String,
pub(crate) actual_method_dart_name: Option<String>,
pub(crate) mode: MirFuncOwnerInfoMethodMode,
pub(crate) trait_def: Option<MirTypeTraitDef>,
}
pub enum MirFuncOwnerInfoMethodMode {
Static,
Instance,
}
#[derive(Copy)]
pub enum MirFuncAccessorMode {
Getter,
Setter,
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, serde::Serialize, strum_macros::Display)]
pub enum OwnershipMode {
Owned,
Ref,
RefMut,
}
impl OwnershipMode {
pub(crate) fn prefix(&self) -> &'static str {
match self {
OwnershipMode::Owned => "",
OwnershipMode::Ref => "&",
OwnershipMode::RefMut => "&mut ",
}
}
}
impl MirFunc {
pub(crate) fn fallible(&self) -> bool {
self.output.error.is_some()
}
pub(crate) fn visit_types<F: FnMut(&MirType) -> bool>(
&self,
f: &mut F,
mir_context: &impl MirContext,
) {
for field in &self.inputs {
field.inner.ty.visit_types(f, mir_context);
}
self.output.normal.visit_types(f, mir_context);
let error_output = (self.output.error.as_ref().cloned())
.unwrap_or(MirType::Primitive(MirTypePrimitive::Unit));
error_output.visit_types(f, mir_context);
if let MirFuncOwnerInfo::Method(MirFuncOwnerInfoMethod {
owner_ty: enum_or_struct_ty,
..
}) = &self.owner
{
enum_or_struct_ty.visit_types(f, mir_context);
}
}
pub(crate) fn default_constructor_mode(&self) -> Option<MirFuncDefaultConstructorMode> {
let method_info =
if_then_some!(let MirFuncOwnerInfo::Method(info) = &self.owner , info).unwrap();
if method_info.actual_method_name == "new" {
if method_info.mode == MirFuncOwnerInfoMethodMode::Static
&& self.mode == MirFuncMode::Sync
{
Some(MirFuncDefaultConstructorMode::DartConstructor)
} else {
Some(MirFuncDefaultConstructorMode::StaticMethod)
}
} else {
None
}
}
pub(crate) fn namespaced_name_rust_style(&self, strip_raw_identifier: bool) -> String {
NamespacedName::new(
self.namespace.clone(),
self.name.rust_style(strip_raw_identifier),
)
.rust_style()
}
pub(crate) fn name_dart_api(&self) -> String {
self.name.dart_style()
}
pub(crate) fn name_dart_wire(&self) -> String {
let raw = format!(
"{}_{}",
self.namespace.path().into_iter().join("_"),
self.name.rust_style(true)
);
raw.to_case(Case::Camel)
}
}
impl MirFuncOwnerInfoMethod {
pub(crate) fn owner_ty_name(&self) -> Option<NamespacedName> {
compute_interest_name_of_owner_ty(&self.owner_ty)
}
}
pub(crate) fn compute_interest_name_of_owner_ty(owner_ty: &MirType) -> Option<NamespacedName> {
Some(match owner_ty {
MirType::StructRef(ty) => ty.ident.0.clone(),
MirType::EnumRef(ty) => ty.ident.0.clone(),
MirType::Delegate(MirTypeDelegate::PrimitiveEnum(MirTypeDelegatePrimitiveEnum {
mir,
..
})) => mir.ident.0.clone(),
MirType::RustAutoOpaqueImplicit(ty) => {
NamespacedName::new(ty.self_namespace().unwrap(), ty.rust_api_type())
}
MirType::Delegate(MirTypeDelegate::Lifetimeable(ty)) => {
return compute_interest_name_of_owner_ty(&MirType::RustAutoOpaqueImplicit(
ty.api_type.clone(),
))
}
MirType::TraitDef(ty) => ty.name.clone(),
_ => return None,
})
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub(crate) enum MirFuncDefaultConstructorMode {
DartConstructor,
StaticMethod,
}
impl MirFuncAccessorMode {
pub(crate) fn verb_str(&self) -> &'static str {
match self {
MirFuncAccessorMode::Getter => "get",
MirFuncAccessorMode::Setter => "set",
}
}
}