Skip to content

Commit

Permalink
Merge pull request #2024 from fzyzcjy/feat/12137
Browse files Browse the repository at this point in the history
Support trait methods and trait default implementations
  • Loading branch information
fzyzcjy authored Jun 4, 2024
2 parents e606b91 + 5e9241b commit 67ac654
Show file tree
Hide file tree
Showing 244 changed files with 17,601 additions and 2,503 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn get_methods_of_enum_or_struct<'a>(
all_funcs: &'a [MirFunc],
) -> Vec<&'a MirFunc> {
(all_funcs.iter())
.filter(|f| matches!(&f.owner, MirFuncOwnerInfo::Method(m) if &m.owner_ty_name() == name))
.filter(|f| matches!(&f.owner, MirFuncOwnerInfo::Method(m) if m.owner_ty_name().as_ref() == Some(name)))
.collect_vec()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ use crate::codegen::generator::wire::rust::spec_generator::base::{
use crate::codegen::generator::wire::rust::spec_generator::misc::wire_func::generate_wire_func;
use crate::codegen::generator::wire::rust::spec_generator::output_code::WireRustOutputCode;
use crate::codegen::generator::wire::rust::MirPackComputedCache;
use crate::codegen::ir::mir::func::MirFuncOwnerInfo;
use crate::codegen::ir::mir::pack::MirPack;
use crate::codegen::ir::mir::ty::rust_opaque::RustOpaqueCodecMode;
use crate::codegen::ir::mir::ty::MirType;
use crate::if_then_some;
use crate::library::codegen::generator::wire::rust::spec_generator::misc::ty::WireRustGeneratorMiscTrait;
use itertools::Itertools;
use serde::Serialize;
Expand Down Expand Up @@ -98,6 +100,15 @@ fn generate_imports(
.into_iter()
.join("\n");

let imports_from_functions = (context.mir_pack.funcs.iter())
.filter_map(
|func| if_then_some!(let MirFuncOwnerInfo::Method(method) = &func.owner, method),
)
.filter_map(|method| method.trait_def_name.clone())
.map(|name| format!("use {};\n", name.rust_style()))
.unique()
.join("");

// NOTE Do *not* use imports when possible, instead use fully specified name directly
let static_imports = "use flutter_rust_bridge::{Handler, IntoIntoDart};
use flutter_rust_bridge::for_generated::transform_result_dco;
Expand All @@ -114,7 +125,11 @@ use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, WriteBytesExt,
_ => "",
};

vec![(imports_from_types.clone() + static_imports + platform_imports).into()]
vec![(imports_from_types.clone()
+ &imports_from_functions
+ static_imports
+ platform_imports)
.into()]
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn generate_code_call_inner_func_result(func: &MirFunc, inner_func_args: Vec<Str
MirFuncOwnerInfo::Method(method) => {
format!(
r"{}::{}({})",
method.owner_ty_name().rust_style(),
method.owner_ty_name().unwrap().rust_style(),
method.actual_method_name,
inner_func_args.join(", ")
)
Expand Down
96 changes: 71 additions & 25 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/function.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,77 @@
use crate::utils::namespace::Namespace;
use crate::utils::namespace::{Namespace, NamespacedName};
use proc_macro2::Span;
use serde::Serialize;
use syn::spanned::Spanned;
use syn::{Attribute, ImplItemFn, ItemFn, ItemImpl, Signature, Visibility};
use syn::{Attribute, ImplItemFn, ItemFn, ItemImpl, Signature, TraitItemFn, Visibility};

#[derive(Debug, Clone, Serialize)]
pub(crate) struct HirFunction {
pub(crate) namespace: Namespace,
#[serde(skip_serializing)]
pub(crate) inner: HirFunctionInner,
pub(crate) owner: HirFunctionOwner,
#[serde(skip_serializing)]
pub(crate) item_fn: GeneralizedItemFn,
}

impl HirFunction {
pub(crate) fn with_namespace(&self, namespace: Namespace) -> Self {
Self {
namespace,
..self.clone()
}
}

pub(crate) fn owner_and_name(&self) -> SimpleOwnerAndName {
(self.owner.simple_name(), self.item_fn.name())
}

pub(crate) fn is_public(&self) -> Option<bool> {
match self.owner {
HirFunctionOwner::Function
| HirFunctionOwner::Method {
trait_def_name: None,
..
} => (self.item_fn.vis()).map(|vis| matches!(vis, Visibility::Public(_))),
HirFunctionOwner::Method {
trait_def_name: Some(_),
..
} => None,
}
}
}

#[derive(Debug, Clone)]
pub(crate) enum HirFunctionInner {
Function {
item_fn: ItemFn,
},
pub(crate) enum HirFunctionOwner {
Function,
Method {
item_impl: ItemImpl,
impl_item_fn: ImplItemFn,
trait_def_name: Option<NamespacedName>,
},
}

impl HirFunction {
pub(crate) fn with_namespace(&self, namespace: Namespace) -> Self {
Self {
namespace,
..self.clone()
impl HirFunctionOwner {
pub(crate) fn simple_name(&self) -> Option<String> {
match self {
Self::Function => None,
Self::Method { item_impl, .. } => Some(ty_to_string(&item_impl.self_ty)),
}
}
}

impl HirFunctionInner {
#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone)]
pub(crate) enum GeneralizedItemFn {
ItemFn(ItemFn),
ImplItemFn(ImplItemFn),
TraitItemFn(TraitItemFn),
}

impl GeneralizedItemFn {
pub(crate) fn sig(&self) -> &Signature {
match self {
HirFunctionInner::Function { item_fn } => &item_fn.sig,
HirFunctionInner::Method { impl_item_fn, .. } => &impl_item_fn.sig,
Self::ItemFn(inner) => &inner.sig,
Self::ImplItemFn(inner) => &inner.sig,
Self::TraitItemFn(inner) => &inner.sig,
}
}

Expand All @@ -45,29 +81,39 @@ impl HirFunctionInner {

pub(crate) fn attrs(&self) -> &Vec<Attribute> {
match self {
HirFunctionInner::Function { item_fn } => &item_fn.attrs,
HirFunctionInner::Method { impl_item_fn, .. } => &impl_item_fn.attrs,
Self::ItemFn(inner) => &inner.attrs,
Self::ImplItemFn(inner) => &inner.attrs,
Self::TraitItemFn(inner) => &inner.attrs,
}
}

pub(crate) fn attrs_mut(&mut self) -> &mut Vec<Attribute> {
match self {
HirFunctionInner::Function { item_fn } => &mut item_fn.attrs,
HirFunctionInner::Method { impl_item_fn, .. } => &mut impl_item_fn.attrs,
Self::ItemFn(inner) => &mut inner.attrs,
Self::ImplItemFn(inner) => &mut inner.attrs,
Self::TraitItemFn(inner) => &mut inner.attrs,
}
}

pub(crate) fn span(&self) -> Span {
match self {
HirFunctionInner::Function { item_fn } => item_fn.span(),
HirFunctionInner::Method { impl_item_fn, .. } => impl_item_fn.span(),
Self::ItemFn(inner) => inner.span(),
Self::ImplItemFn(inner) => inner.span(),
Self::TraitItemFn(inner) => inner.span(),
}
}

pub(crate) fn vis(&self) -> &Visibility {
pub(crate) fn vis(&self) -> Option<&Visibility> {
match self {
HirFunctionInner::Function { item_fn } => &item_fn.vis,
HirFunctionInner::Method { impl_item_fn, .. } => &impl_item_fn.vis,
Self::ItemFn(inner) => Some(&inner.vis),
Self::ImplItemFn(inner) => Some(&inner.vis),
Self::TraitItemFn(_) => None,
}
}
}

pub(crate) type SimpleOwnerAndName = (Option<String>, String);

fn ty_to_string(ty: &syn::Type) -> String {
quote::quote!(#ty).to_string()
}
1 change: 1 addition & 0 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ pub(crate) mod module;
pub(crate) mod pack;
pub(crate) mod struct_or_enum;
pub(crate) mod syn_item_struct_or_enum;
pub(crate) mod traits;
pub(crate) mod type_alias;
19 changes: 19 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/module.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::codegen::ir::hir::hierarchical::function::HirFunction;
use crate::codegen::ir::hir::hierarchical::struct_or_enum::HirEnum;
use crate::codegen::ir::hir::hierarchical::struct_or_enum::HirStruct;
use crate::codegen::ir::hir::hierarchical::traits::{HirTrait, HirTraitImpl};
use crate::codegen::ir::hir::hierarchical::type_alias::HirTypeAlias;
use crate::utils::namespace::Namespace;
use derivative::Derivative;
Expand All @@ -16,6 +17,22 @@ pub struct HirModule {
pub raw: Vec<String>,
}

impl HirModule {
pub(crate) fn visit<'a, F: FnMut(&'a HirModule)>(&'a self, f: &mut F) {
f(self);
for scope_module in self.content.modules.iter() {
scope_module.visit(f);
}
}

pub(crate) fn visit_mut<F: FnMut(&mut HirModule)>(&mut self, f: &mut F) {
f(self);
for scope_module in self.content.modules.iter_mut() {
scope_module.visit_mut(f);
}
}
}

#[derive(Clone, Derivative, Serialize)]
#[derivative(Debug)]
pub struct HirModuleMeta {
Expand All @@ -42,6 +59,8 @@ pub struct HirModuleContent {
// pub imports: Vec<Import>, // not implemented yet
pub type_alias: Vec<HirTypeAlias>,
pub functions: Vec<HirFunction>,
pub traits: Vec<HirTrait>,
pub trait_impls: Vec<HirTraitImpl>,
}

/// Mirrors syn::Visibility, but can be created without a token
Expand Down
13 changes: 13 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/pack.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::codegen::ir::hir::hierarchical::crates::HirCrate;
use crate::codegen::ir::hir::hierarchical::module::HirModule;
use crate::utils::crate_name::CrateName;

#[derive(Debug, Clone, serde::Serialize)]
Expand All @@ -10,4 +11,16 @@ impl HirPack {
pub(crate) fn get_mut_crate(&mut self, name: &CrateName) -> Option<&mut HirCrate> {
(self.crates.iter_mut()).find(|x| x.name.namespace() == name.namespace())
}

pub(crate) fn visit<'a, F: FnMut(&'a HirModule)>(&'a self, f: &mut F) {
for hir_crate in &self.crates {
hir_crate.root_module.visit(f);
}
}

pub(crate) fn visit_mut<F: FnMut(&mut HirModule)>(&mut self, f: &mut F) {
for hir_crate in &mut self.crates {
hir_crate.root_module.visit_mut(f);
}
}
}
17 changes: 17 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::utils::namespace::Namespace;
use serde::Serialize;
use syn::{ItemImpl, ItemTrait};

#[derive(Debug, Clone, Serialize)]
pub(crate) struct HirTrait {
pub(crate) namespace: Namespace,
#[serde(skip_serializing)]
pub(crate) item_trait: ItemTrait,
}

#[derive(Debug, Clone, Serialize)]
pub(crate) struct HirTraitImpl {
pub(crate) namespace: Namespace,
#[serde(skip_serializing)]
pub(crate) item_impl: ItemImpl,
}
9 changes: 5 additions & 4 deletions frb_codegen/src/library/codegen/ir/mir/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub struct MirFuncOwnerInfoMethod {
pub(crate) actual_method_name: String,
pub(crate) actual_method_dart_name: Option<String>,
pub(crate) mode: MirFuncOwnerInfoMethodMode,
pub(crate) trait_def_name: Option<NamespacedName>,
}

pub enum MirFuncOwnerInfoMethodMode {
Expand Down Expand Up @@ -159,8 +160,8 @@ impl MirFunc {
}

impl MirFuncOwnerInfoMethod {
pub(crate) fn owner_ty_name(&self) -> NamespacedName {
match &self.owner_ty {
pub(crate) fn owner_ty_name(&self) -> Option<NamespacedName> {
Some(match &self.owner_ty {
MirType::StructRef(ty) => ty.ident.0.clone(),
MirType::EnumRef(ty) => ty.ident.0.clone(),
MirType::Delegate(MirTypeDelegate::PrimitiveEnum(MirTypeDelegatePrimitiveEnum {
Expand All @@ -170,8 +171,8 @@ impl MirFuncOwnerInfoMethod {
MirType::RustAutoOpaqueImplicit(ty) => {
NamespacedName::new(ty.self_namespace().unwrap(), ty.rust_api_type())
}
ty => unimplemented!("enum_or_struct_name does not know {ty:?}"),
}
_ => return None,
})
}
}

Expand Down
17 changes: 2 additions & 15 deletions frb_codegen/src/library/codegen/parser/hir/flat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ where
V: Debug,
{
let mut ans = HashMap::new();
visit_pack(hir_pack, &mut |module| {
hir_pack.visit( &mut |module| {
if !is_interest_mod(module) {
return;
}
Expand All @@ -100,7 +100,7 @@ where
F: Fn(&'a HirModule) -> Vec<T>,
{
let mut ans = vec![];
visit_pack(hir_pack, &mut |module| {
hir_pack.visit(&mut |module| {
if !is_interest_mod(module) {
return;
}
Expand All @@ -115,16 +115,3 @@ fn is_interest_mod(module: &HirModule) -> bool {
// since for non-pub modes, it is impossible to use them even if we scanned them.
module.meta.namespace.path()[0] == CrateName::SELF_CRATE || module.meta.is_public()
}

fn visit_pack<'a, F: FnMut(&'a HirModule)>(hir_pack: &'a HirPack, f: &mut F) {
for hir_crate in &hir_pack.crates {
visit_modules(&hir_crate.root_module, f);
}
}

fn visit_modules<'a, F: FnMut(&'a HirModule)>(module: &'a HirModule, f: &mut F) {
f(module);
for scope_module in module.content.modules.iter() {
visit_modules(scope_module, f);
}
}
Loading

0 comments on commit 67ac654

Please sign in to comment.