pub mod plugin;
pub mod service;
use crate::lang::TypeId;
use crate::lang::functions::{Argument, Signature};
use crate::lang::types::kind::{Primitive, TypeKind, TypePattern};
use crate::pass::model::common::types::all::Pass as TypesAll;
use interoptopus::lang::types::TypeInfo;
fn async_callback_inner(args: &[Argument], types: &TypesAll) -> Option<TypeId> {
let last = args.last()?;
let ty = types.get(last.ty)?;
match &ty.kind {
TypeKind::TypePattern(TypePattern::AsyncCallback(inner)) => Some(*inner),
_ => None,
}
}
fn resolve_ptr_to_service_id(type_id: TypeId, types: &TypesAll) -> Option<TypeId> {
let ty = types.get(type_id)?;
if let TypeKind::Pointer(p) = &ty.kind {
let target = types.get(p.target)?;
if matches!(&target.kind, TypeKind::Service) {
return Some(p.target);
}
}
None
}
fn resolve_rval_type(rval_id: TypeId, types: &TypesAll) -> TypeId {
if let Some(svc_id) = resolve_ptr_to_service_id(rval_id, types) {
return svc_id;
}
rval_id
}
pub(super) fn resolve_method_info(args: &[Argument], rval: TypeId, types: &TypesAll, unwrap_error_id: Option<TypeId>) -> (Signature, TypeId, bool, Option<TypeId>) {
let async_inner = async_callback_inner(args, types);
let is_async = async_inner.is_some();
let rval_is_task_handle = matches!(types.get(rval).map(|t| &t.kind), Some(TypeKind::TypePattern(TypePattern::TaskHandle)));
let rval_is_void = matches!(types.get(rval).map(|t| &t.kind), Some(TypeKind::Primitive(Primitive::Void)));
let raw_rval_id = if is_async && (rval_is_void || rval_is_task_handle) {
async_inner.unwrap_or(rval)
} else {
rval
};
let mut resolved_rval_id = resolve_rval_type(raw_rval_id, types);
let unwrapped_result_id = if let Some(err_id) = unwrap_error_id {
if let Some(ty) = types.get(resolved_rval_id) {
if let TypeKind::TypePattern(TypePattern::Result(ok, err, _)) = &ty.kind {
if *err == err_id {
let original = resolved_rval_id;
resolved_rval_id = resolve_rval_type(*ok, types);
Some(original)
} else {
None
}
} else {
None
}
} else {
None
}
} else {
None
};
let is_void = matches!(types.get(resolved_rval_id).map(|t| &t.kind), Some(TypeKind::Primitive(Primitive::Void)));
let effective_rval = if is_void && is_async { rval } else { resolved_rval_id };
let arg_count = if is_async { args.len().saturating_sub(1) } else { args.len() };
let mut arguments: Vec<Argument> = args.iter().take(arg_count).cloned().collect();
if is_async {
arguments.push(Argument { name: "ct".to_string(), ty: crate::lang::types::csharp::CANCELLATION_TOKEN });
}
(Signature { arguments, rval: effective_rval }, resolved_rval_id, is_async, unwrapped_result_id)
}