Skip to content

Commit

Permalink
Merge pull request #2069 from fzyzcjy/feat/12219
Browse files Browse the repository at this point in the history
Support attributes on `impl` block ; Improve ignore category message ; Fix external methods are wrong ignored
  • Loading branch information
fzyzcjy authored Jun 12, 2024
2 parents a549b8d + 58b2166 commit c93793c
Show file tree
Hide file tree
Showing 35 changed files with 3,509 additions and 2,171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ fn compute_skips(mir_pack: &MirPack, namespace: &Namespace) -> Vec<MirSkip> {
.filter(|t| &t.namespace == namespace)
.map(|name| MirSkip {
name: name.clone(),
reason: MirSkipReason::IgnoredTypeNotUsedByPub,
reason: MirSkipReason::IgnoreBecauseTypeNotUsedByPub,
})
.collect_vec();

Expand Down
35 changes: 20 additions & 15 deletions frb_codegen/src/library/codegen/ir/mir/skip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,37 @@ pub struct MirSkip {

#[derive(Copy, PartialOrd, Ord)]
pub(crate) enum MirSkipReason {
IgnoredFunctionNotPub,
IgnoredFunctionGeneric,
IgnoredTypeNotUsedByPub,
IgnoredMisc,
IgnoredSilently,
IgnoreBecauseFunctionNotPub,
IgnoreBecauseFunctionGeneric,
IgnoreBecauseTypeNotUsedByPub,
IgnoreBecauseExplicitAttribute,
IgnoreBecauseType,
IgnoreBecauseParseMethodOwnerTy,
IgnoreBecauseParseOwnerCannotFindTrait,
IgnoreBecauseNotAllowedOwner,
IgnoreBecauseOwnerTyShouldIgnore,
IgnoreSilently,
Err,
}
}

impl MirSkipReason {
pub(crate) fn explanation_prefix(&self) -> Option<&'static str> {
pub(crate) fn explanation_prefix(&self) -> Option<String> {
Some(match self {
Self::IgnoredFunctionNotPub => {
"These functions are ignored because they are not marked as `pub`"
Self::IgnoreBecauseFunctionNotPub => {
"These functions are ignored because they are not marked as `pub`".to_owned()
}
Self::IgnoredFunctionGeneric => {
"These functions are ignored because they have generic arguments"
Self::IgnoreBecauseFunctionGeneric => {
"These functions are ignored because they have generic arguments".to_owned()
}
Self::IgnoredTypeNotUsedByPub => {
"These types are ignored because they are not used by any `pub` functions"
Self::IgnoreBecauseTypeNotUsedByPub => {
"These types are ignored because they are not used by any `pub` functions".to_owned()
}
Self::IgnoredMisc => "These functions are ignored",
Self::IgnoredSilently => return None,
Self::IgnoreSilently => return None,
Self::Err => {
"These functions have error during generation (see debug logs or enable `stop_on_error: true` for more details)"
"These functions have error during generation (see debug logs or enable `stop_on_error: true` for more details)".to_owned()
}
_ => format!("These functions are ignored (category: {:?})", self)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::codegen::ir::hir::misc::item_fn::GeneralizedItemFn;
use crate::codegen::ir::hir::naive_flat::item::HirNaiveFlatItemMeta;
use crate::if_then_some;
use itertools::Itertools;
use syn::{ImplItem, ItemImpl};
use syn::{Attribute, ImplItem, ImplItemFn, ItemImpl};

pub(crate) fn parse_syn_item_impl(
target: &mut HirFlatPack,
Expand All @@ -29,6 +29,8 @@ fn parse_functions(
meta: &HirNaiveFlatItemMeta,
trait_def_name: &Option<String>,
) -> Vec<HirFlatFunction> {
let attrs_item_impl = item_impl.attrs;

(item_impl.items.into_iter())
.filter_map(|item| if_then_some!(let ImplItem::Fn(impl_item_fn) = item, impl_item_fn))
.map(|impl_item_fn| HirFlatFunction {
Expand All @@ -37,12 +39,17 @@ fn parse_functions(
impl_ty: *item_impl.self_ty.clone(),
trait_def_name: trait_def_name.clone(),
},
item_fn: GeneralizedItemFn::ImplItemFn(impl_item_fn),
item_fn: GeneralizedItemFn::ImplItemFn(add_attrs(impl_item_fn, &attrs_item_impl)),
sources: meta.sources.clone(),
})
.collect_vec()
}

fn add_attrs(mut item: ImplItemFn, attrs: &[Attribute]) -> ImplItemFn {
item.attrs.extend(attrs.to_owned());
item
}

fn parse_trait_impl(item_impl: &ItemImpl, trait_name: &str) -> HirFlatTraitImpl {
HirFlatTraitImpl {
trait_name: trait_name.to_owned(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::codegen::ir::mir::field::{MirField, MirFieldSettings};
use crate::codegen::ir::mir::func::{MirFuncInput, MirFuncOwnerInfo};
use crate::codegen::ir::mir::func::{MirFuncOwnerInfoMethod, OwnershipMode};
use crate::codegen::ir::mir::ident::MirIdent;
use crate::codegen::ir::mir::skip::MirSkipReason;
use crate::codegen::ir::mir::ty::boxed::MirTypeBoxed;
use crate::codegen::ir::mir::ty::delegate::{MirTypeDelegate, MirTypeDelegateProxyEnum};
use crate::codegen::ir::mir::ty::MirType;
Expand Down Expand Up @@ -56,7 +57,7 @@ impl<'a, 'b> FunctionParser<'a, 'b> {

if ty.should_ignore(self.type_parser) {
return Ok(FunctionPartialInfo {
ignore_func: true,
ignore_func: Some(MirSkipReason::IgnoreBecauseType),
..Default::default()
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use crate::codegen::ir::mir::func::{
MirFunc, MirFuncArgMode, MirFuncImplMode, MirFuncImplModeDartOnly, MirFuncInput, MirFuncMode,
MirFuncOutput, MirFuncOwnerInfo, MirFuncOwnerInfoMethod, MirFuncOwnerInfoMethodMode,
};
use crate::codegen::ir::mir::skip::MirSkipReason::{IgnoredFunctionGeneric, IgnoredSilently};
use crate::codegen::ir::mir::skip::MirSkipReason::{
IgnoreBecauseExplicitAttribute, IgnoreBecauseFunctionGeneric, IgnoreBecauseOwnerTyShouldIgnore,
IgnoreSilently,
};
use crate::codegen::ir::mir::skip::{MirSkip, MirSkipReason};
use crate::codegen::ir::mir::ty::delegate::MirTypeDelegate;
use crate::codegen::ir::mir::ty::primitive::MirTypePrimitive;
Expand All @@ -27,7 +30,7 @@ use itertools::concat;
use log::{debug, warn};
use std::fmt::Debug;
use syn::*;
use MirSkipReason::{IgnoredFunctionNotPub, IgnoredMisc};
use MirSkipReason::IgnoreBecauseFunctionNotPub;
use MirType::Primitive;

pub(crate) mod argument;
Expand Down Expand Up @@ -115,16 +118,16 @@ impl<'a, 'b> FunctionParser<'a, 'b> {
debug!("parse_function function name: {:?}", func.item_fn.name());

if func.is_public() == Some(false) {
return Ok(create_output_skip(func, IgnoredFunctionNotPub));
return Ok(create_output_skip(func, IgnoreBecauseFunctionNotPub));
}
if !func.item_fn.sig().generics.params.is_empty() {
return Ok(create_output_skip(func, IgnoredFunctionGeneric));
return Ok(create_output_skip(func, IgnoreBecauseFunctionGeneric));
}

let src_lineno = func.item_fn.span().start().line;
let attributes = FrbAttributes::parse(func.item_fn.attrs())?;
if attributes.dart2rust().is_some() || attributes.rust2dart().is_some() {
return Ok(create_output_skip(func, IgnoredSilently));
return Ok(create_output_skip(func, IgnoreSilently));
}

let dart_name = parse_dart_name(&attributes, &func.item_fn.name());
Expand All @@ -140,18 +143,16 @@ impl<'a, 'b> FunctionParser<'a, 'b> {
};

let is_owner_trait_def = matches!(func.owner, HirFlatFunctionOwner::TraitDef { .. });
let owner = if let Some(owner) =
self.parse_owner(func, &create_context(None), dart_name.clone(), &attributes)?
{
owner
} else {
return Ok(create_output_skip(func, IgnoredMisc));
};
let owner =
match self.parse_owner(func, &create_context(None), dart_name.clone(), &attributes)? {
OwnerInfoOrSkip::Info(info) => info,
OwnerInfoOrSkip::Skip(reason) => return Ok(create_output_skip(func, reason)),
};

let func_name = parse_name(&func.item_fn.name(), &owner);

if attributes.ignore() {
return Ok(create_output_skip(func, IgnoredMisc));
return Ok(create_output_skip(func, IgnoreBecauseExplicitAttribute));
}

let context = create_context(Some(owner.clone()));
Expand All @@ -177,8 +178,8 @@ impl<'a, 'b> FunctionParser<'a, 'b> {

let impl_mode = compute_impl_mode(is_owner_trait_def, &func_name, &attributes, &output);

if info.ignore_func {
return Ok(create_output_skip(func, IgnoredMisc));
if let Some(ignore_func) = info.ignore_func {
return Ok(create_output_skip(func, ignore_func));
}

Ok(MirFuncOrSkip::Func(MirFunc {
Expand Down Expand Up @@ -212,32 +213,35 @@ impl<'a, 'b> FunctionParser<'a, 'b> {
context: &TypeParserParsingContext,
actual_method_dart_name: Option<String>,
attributes: &FrbAttributes,
) -> anyhow::Result<Option<MirFuncOwnerInfo>> {
) -> anyhow::Result<OwnerInfoOrSkip> {
use MirSkipReason::*;
use OwnerInfoOrSkip::*;

match &func.owner {
HirFlatFunctionOwner::Function => Ok(Some(MirFuncOwnerInfo::Function)),
HirFlatFunctionOwner::Function => Ok(Info(MirFuncOwnerInfo::Function)),
HirFlatFunctionOwner::StructOrEnum {
impl_ty,
trait_def_name,
} => {
let owner_ty = if let Some(x) = self.parse_method_owner_ty(impl_ty, context)? {
x
} else {
return Ok(None);
return Ok(Skip(IgnoreBecauseParseMethodOwnerTy));
};

let trait_def = if let Some(trait_def_name) = trait_def_name {
if let Some(ans) = parse_type_trait(trait_def_name, self.type_parser) {
Some(ans)
} else {
// If cannot find the trait, we directly skip the function currently
return Ok(None);
return Ok(Skip(IgnoreBecauseParseOwnerCannotFindTrait));
}
} else {
None
};

if !is_allowed_owner(&owner_ty, attributes) {
return Ok(None);
return Ok(Skip(IgnoreBecauseNotAllowedOwner));
}

self.parse_method_owner_inner(func, actual_method_dart_name, owner_ty, trait_def)
Expand All @@ -263,7 +267,9 @@ impl<'a, 'b> FunctionParser<'a, 'b> {
actual_method_dart_name: Option<String>,
owner_ty: MirType,
trait_def: Option<MirTypeTraitDef>,
) -> anyhow::Result<Option<MirFuncOwnerInfo>> {
) -> anyhow::Result<OwnerInfoOrSkip> {
use OwnerInfoOrSkip::*;

let sig = func.item_fn.sig();
let mode = if matches!(sig.inputs.first(), Some(FnArg::Receiver(..))) {
MirFuncOwnerInfoMethodMode::Instance
Expand All @@ -272,12 +278,12 @@ impl<'a, 'b> FunctionParser<'a, 'b> {
};

if owner_ty.should_ignore(self.type_parser) {
return Ok(None);
return Ok(Skip(IgnoreBecauseOwnerTyShouldIgnore));
}

let actual_method_name = sig.ident.to_string();

Ok(Some(MirFuncOwnerInfo::Method(MirFuncOwnerInfoMethod {
Ok(Info(MirFuncOwnerInfo::Method(MirFuncOwnerInfoMethod {
owner_ty,
actual_method_name,
actual_method_dart_name,
Expand Down Expand Up @@ -306,6 +312,11 @@ impl<'a, 'b> FunctionParser<'a, 'b> {
}
}

enum OwnerInfoOrSkip {
Info(MirFuncOwnerInfo),
Skip(MirSkipReason),
}

fn create_output_skip(func: &HirFlatFunction, reason: MirSkipReason) -> MirFuncOrSkip {
MirFuncOrSkip::Skip(MirSkip {
name: NamespacedName::new(func.namespace.clone(), func.item_fn.name().to_string()),
Expand Down Expand Up @@ -342,7 +353,7 @@ struct FunctionPartialInfo {
ok_output: Option<MirType>,
error_output: Option<MirType>,
mode: Option<MirFuncMode>,
ignore_func: bool,
ignore_func: Option<MirSkipReason>,
}

impl FunctionPartialInfo {
Expand All @@ -353,7 +364,8 @@ impl FunctionPartialInfo {
error_output: merge_option(self.error_output, other.error_output)
.context("error_output type")?,
mode: merge_option(self.mode, other.mode).context("mode")?,
ignore_func: self.ignore_func || other.ignore_func,
ignore_func: merge_option(self.ignore_func, other.ignore_func)
.context("ignore_func")?,
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'web_audio_api/node.dart';
import 'web_audio_api/worklet.dart';

// These types are ignored because they are not used by any `pub` functions: `AtomicF32`, `AtomicF64`, `ErrorEvent`, `MediaElement`, `MessagePort`
// These functions are ignored: `load`, `load`, `new`, `new`, `store`, `store`
// These functions are ignored (category: IgnoreBecauseOwnerTyShouldIgnore): `load`, `load`, `new`, `new`, `store`, `store`

// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<AudioBuffer>>
abstract class AudioBuffer implements RustOpaqueInterface {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import 'media_streams.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';

// These types are ignored because they are not used by any `pub` functions: `DeviceId`, `MediaDeviceInfoKind`, `MediaDeviceInfo`, `MediaTrackConstraints`
// These functions are ignored: `device_id`, `enumerate_devices_sync`, `group_id`, `kind`, `label`
// These functions are ignored (category: IgnoreBecauseExplicitAttribute): `enumerate_devices_sync`
// These functions are ignored (category: IgnoreBecauseOwnerTyShouldIgnore): `device_id`, `group_id`, `kind`, `label`

/// Prompt for permission to use a media input (audio only)
///
Expand Down
Loading

0 comments on commit c93793c

Please sign in to comment.