Skip to content

Commit

Permalink
Merge pull request #2052 from fzyzcjy/feat/12187
Browse files Browse the repository at this point in the history
Support `#[frb(proxy)]` (part 2)
  • Loading branch information
fzyzcjy authored Jun 9, 2024
2 parents f3ff967 + 5b2b349 commit 1868cb3
Show file tree
Hide file tree
Showing 76 changed files with 9,694 additions and 15,309 deletions.
11 changes: 8 additions & 3 deletions frb_codegen/src/library/codegen/generator/api_dart/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ pub(crate) fn compute_path_from_namespace(
namespace: &Namespace,
) -> PathBuf {
let raw_path = namespace.path();
let chunks = match raw_path[0] {
CrateName::SELF_CRATE => raw_path[1..].to_owned(),
_ => concat([vec![THIRD_PARTY_DIR_NAME], raw_path.clone()]),
let chunks = if namespace == &CrateName::self_crate().namespace() {
// workaround - for `lib.rs`, we cannot just output `/` which is invalid
vec!["lib"]
} else {
match raw_path[0] {
CrateName::SELF_CRATE => raw_path[1..].to_owned(),
_ => concat([vec![THIRD_PARTY_DIR_NAME], raw_path.clone()]),
}
};

let ans_without_extension =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::codegen::generator::api_dart::spec_generator::base::{
use crate::codegen::ir::mir::func::MirFuncMode;
use crate::codegen::ir::mir::ty::delegate::MirTypeDelegateProxyVariant;
use crate::library::codegen::generator::api_dart::spec_generator::info::ApiDartGeneratorInfoTrait;
use convert_case::{Case, Casing};

pub(crate) fn compute_func_implementation(
ir: &MirTypeDelegateProxyVariant,
Expand All @@ -25,7 +26,9 @@ pub(crate) fn compute_dart_extra_type(
let upstream_dart_api_type =
ApiDartGenerator::new(ir.upstream.clone(), context).dart_api_type();
format!(
"{}ProxyVariant{}",
inner_dart_api_type, upstream_dart_api_type
"{}ProxyVariant{}{}",
inner_dart_api_type,
upstream_dart_api_type,
ir.upstream_method_name.to_case(Case::Pascal),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,23 @@ fn generate_imports_from_ty(
let import_ty_itself = if let Some(ty_namespace) = ty.self_namespace() {
if &ty_namespace != current_file_namespace {
let dummy_base_path = PathBuf::from("/".to_owned());
let path_diff = diff_paths(
api_dart::misc::compute_path_from_namespace(&dummy_base_path, &ty_namespace),
(api_dart::misc::compute_path_from_namespace(
&dummy_base_path,
current_file_namespace,

let path_a =
api_dart::misc::compute_path_from_namespace(&dummy_base_path, &ty_namespace);

let path_b_inner = api_dart::misc::compute_path_from_namespace(
&dummy_base_path,
current_file_namespace,
);
let path_b = (path_b_inner.parent()).with_context(|| {
format!(
"no parent for path_b_inner={path_b_inner:?} \
(current_file_namespace={current_file_namespace}, ty_namespace={ty_namespace} current_file_namespace={current_file_namespace:?} ty={ty:?})"
)
.parent())
.unwrap(),
)
.context("cannot diff path")?;
});

let path_diff = diff_paths(path_a, path_b?).context("cannot diff path")?;

format!(
"import '{}';\n",
path_to_string(&path_diff).unwrap().replace('\\', "/")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::codegen::ir::mir::func::{MirFunc, MirFuncInput, OwnershipMode};
use crate::codegen::ir::mir::ty::delegate::MirTypeDelegate;
use crate::codegen::ir::mir::ty::MirType;
use convert_case::{Case, Casing};
use itertools::Itertools;
Expand Down Expand Up @@ -45,8 +46,8 @@ pub(crate) fn generate_code_inner_decode(func: &MirFunc) -> String {
""
};
format!(
"let {mutability}api_{name} = api_{name}_decoded.unwrap();\n",
name = get_variable_name(info.field)
"let {mutability}api_{name} = &{mutability}*api_{name}_decoded.unwrap();\n",
name = get_variable_name(info.field),
)
})
.join("");
Expand Down Expand Up @@ -83,19 +84,21 @@ fn get_variable_name(field: &MirFuncInput) -> &str {

fn filter_interest_fields(func: &MirFunc) -> Vec<FieldInfo> {
(func.inputs.iter())
.filter_map(|field| compute_interest_field(field))
.filter_map(|field| {
compute_interest_field(&field.inner.ty).map(|ownership_mode| FieldInfo {
field,
ownership_mode,
})
})
.collect_vec()
}

fn compute_interest_field(field: &MirFuncInput) -> Option<FieldInfo> {
match &field.inner.ty {
fn compute_interest_field(ty: &MirType) -> Option<OwnershipMode> {
match &ty {
MirType::RustAutoOpaqueImplicit(ty) if ty.ownership_mode != OwnershipMode::Owned => {
Some(FieldInfo {
field,
ownership_mode: ty.ownership_mode,
})
Some(ty.ownership_mode)
}
// TODO: ProxyEnum here
MirType::Delegate(MirTypeDelegate::ProxyEnum(ty)) => compute_interest_field(&ty.original),
_ => None,
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::codegen::generator::wire::rust::spec_generator::base::*;
use crate::codegen::generator::wire::rust::spec_generator::misc::ty::WireRustGeneratorMiscTrait;
use crate::codegen::ir::mir::ty::delegate::MirTypeDelegate;
use crate::library::codegen::ir::mir::ty::MirTypeTrait;

impl<'a> WireRustGeneratorMiscTrait for DelegateWireRustGenerator<'a> {
// the function signature is not covered while the whole body is covered - looks like a bug in coverage tool
Expand All @@ -13,4 +14,12 @@ impl<'a> WireRustGeneratorMiscTrait for DelegateWireRustGenerator<'a> {
None
}
}

fn generate_wire_func_call_decode_type(&self) -> Option<String> {
if let MirTypeDelegate::ProxyEnum(mir) = &self.mir {
Some(mir.get_delegate().rust_api_type())
} else {
None
}
}
}
3 changes: 2 additions & 1 deletion frb_codegen/src/library/codegen/ir/mir/ty/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub struct MirTypeDelegateRustAutoOpaqueExplicit {
pub struct MirTypeDelegateProxyVariant {
pub inner: Box<MirType>,
pub upstream: Box<MirType>,
pub upstream_method_name: String,
}

pub struct MirTypeDelegateProxyEnum {
Expand Down Expand Up @@ -145,7 +146,7 @@ impl MirTypeTrait for MirTypeDelegate {
format!("AutoExplicit_{}", mir.inner.safe_ident())
} // MirTypeDelegate::DynTrait(mir) => mir.safe_ident(),
MirTypeDelegate::ProxyVariant(mir) => {
format!("ProxyVariant_{}", mir.inner.safe_ident())
format!("ProxyVariant_{}_{}", mir.upstream.safe_ident(), mir.upstream_method_name)
}
MirTypeDelegate::ProxyEnum(mir) => format!("ProxyEnum_{}", mir.get_delegate().safe_ident()),
}
Expand Down
14 changes: 1 addition & 13 deletions frb_codegen/src/library/codegen/parser/early_generator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
mod proxy_enum;
mod trait_impl_enum;
pub(crate) mod utils;

use crate::codegen::dumper::Dumper;
use crate::codegen::ir::early_generator::pack::IrEarlyGeneratorPack;
use crate::codegen::ir::hir::flat::pack::HirFlatPack;
use crate::codegen::parser::hir::flat::extra_code_injector::inject_extra_code;
use crate::codegen::parser::mir;
use crate::codegen::parser::mir::internal_config::ParserMirInternalConfig;

Expand All @@ -29,15 +29,3 @@ pub(crate) fn execute(

Ok(pack)
}

fn inject_extra_code_to_rust_output(
pack: &mut HirFlatPack,
extra_code: &str,
config_mir: &ParserMirInternalConfig,
) -> anyhow::Result<()> {
inject_extra_code(
pack,
extra_code,
&(config_mir.rust_input_namespace_pack).rust_output_path_namespace,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ use crate::codegen::ir::mir::ty::delegate::{
MirTypeDelegate, MirTypeDelegateProxyEnum, MirTypeDelegateProxyVariant,
};
use crate::codegen::ir::mir::ty::MirType;
use crate::codegen::parser::early_generator::inject_extra_code_to_rust_output;
use crate::codegen::parser::early_generator::utils::lockable;
use crate::codegen::parser::hir::flat::extra_code_injector::{
inject_extra_codes, InjectExtraCodeBlock,
};
use crate::codegen::parser::mir::internal_config::ParserMirInternalConfig;
use crate::codegen::parser::mir::parser::function::real::FUNC_PREFIX_FRB_INTERNAL_NO_IMPL;
use crate::if_then_some;
use crate::library::codegen::ir::mir::ty::MirTypeTrait;
use crate::utils::namespace::Namespace;
use itertools::Itertools;
use std::collections::HashMap;

Expand All @@ -24,63 +28,62 @@ pub(crate) fn generate(
.filter_map(|ty| if_then_some!(let MirType::Delegate(MirTypeDelegate::ProxyVariant(inner)) = ty, inner.clone()))
.collect_vec();

let output_namespace = &(config_mir.rust_input_namespace_pack).rust_output_path_namespace;

let proxy_variants_of_enum =
(proxy_variants.iter()).into_group_map_by(|ty| ty.upstream.safe_ident());

let proxied_types = compute_proxied_types(&proxy_variants_of_enum, config_mir);
let proxied_types = compute_proxied_types(&proxy_variants_of_enum, &output_namespace);

let extra_code = proxy_variants_of_enum
.into_values()
.map(|proxy_variants| generate_proxy_enum(&proxy_variants))
.join("");
let extra_codes = (proxy_variants_of_enum.values())
.map(|proxy_variants| generate_proxy_enum(proxy_variants))
.collect::<anyhow::Result<Vec<_>>>()?
.into_iter()
.flatten()
.collect_vec();

inject_extra_code_to_rust_output(&mut pack.hir_flat_pack, &extra_code, config_mir)?;
inject_extra_codes(&mut pack.hir_flat_pack, output_namespace, &extra_codes)?;
(pack.proxied_types).extend(proxied_types);

Ok(())
}

fn compute_proxied_types(
proxy_variants_of_enum: &HashMap<String, Vec<&MirTypeDelegateProxyVariant>>,
config_mir: &ParserMirInternalConfig,
proxy_enum_namespace: &Namespace,
) -> Vec<IrEarlyGeneratorProxiedType> {
(proxy_variants_of_enum.values())
.map(|variants| {
let proxy_enum_namespace = config_mir
.rust_input_namespace_pack
.rust_output_path_namespace
.clone();

IrEarlyGeneratorProxiedType {
proxy_enum_namespace,
original_ty: (*variants[0].inner).to_owned(),
variants: variants.iter().map(|&x| x.to_owned()).collect_vec(),
}
.map(|variants| IrEarlyGeneratorProxiedType {
proxy_enum_namespace: proxy_enum_namespace.clone(),
original_ty: (*variants[0].inner).to_owned(),
variants: variants.iter().map(|&x| x.to_owned()).collect_vec(),
})
.collect_vec()
}

fn generate_proxy_enum(proxy_variants: &[&MirTypeDelegateProxyVariant]) -> String {
fn generate_proxy_enum(
proxy_variants: &[&MirTypeDelegateProxyVariant],
) -> anyhow::Result<Vec<InjectExtraCodeBlock>> {
let proxy_enum_ty = *proxy_variants[0].inner.clone();

let enum_name = MirTypeDelegateProxyEnum::proxy_enum_name_raw(&proxy_enum_ty);

let variants = (proxy_variants.iter().enumerate())
.map(|(index, variant)| {
format!(
"Variant{index}(RustAutoOpaque<{}>),\n",
&variant.upstream.rust_api_type()
)
.map(|(index, variant)| lockable::VariantInfo {
enum_variant_name: format!("Variant{index}"),
ty_name: variant.upstream.rust_api_type(),
deref_extra_code: format!(".{}()", variant.upstream_method_name),
})
.join("");
.collect_vec();

format!(
"
enum {enum_name} {{
{variants}
}}
let deref_target = compute_deref_target(&proxy_enum_ty);

lockable::generate(&enum_name, &deref_target, false, &variants)
}

pub fn {FUNC_PREFIX_FRB_INTERNAL_NO_IMPL}_dummy_function_{enum_name}(a: {enum_name}) {{ }}
"
)
fn compute_deref_target(ty: &MirType) -> String {
match ty {
MirType::RustAutoOpaqueImplicit(ty) => ty.raw.string.clone(),
_ => unimplemented!(),
}
}
Loading

0 comments on commit 1868cb3

Please sign in to comment.