Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support attributes on impl block ; Improve ignore category message ; Fix external methods are wrong ignored #2069

Merged
merged 16 commits into from
Jun 12, 2024
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::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 @@

if ty.should_ignore(self.type_parser) {
return Ok(FunctionPartialInfo {
ignore_func: true,
ignore_func: Some(MirSkipReason::IgnoreBecauseType),

Check warning on line 60 in frb_codegen/src/library/codegen/parser/mir/parser/function/real/argument.rs

View check run for this annotation

Codecov / codecov/patch

frb_codegen/src/library/codegen/parser/mir/parser/function/real/argument.rs#L60

Added line #L60 was not covered by tests
..Default::default()
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
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 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 @@
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 @@
};

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 @@

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));

Check warning on line 182 in frb_codegen/src/library/codegen/parser/mir/parser/function/real/mod.rs

View check run for this annotation

Codecov / codecov/patch

frb_codegen/src/library/codegen/parser/mir/parser/function/real/mod.rs#L182

Added line #L182 was not covered by tests
}

Ok(MirFuncOrSkip::Func(MirFunc {
Expand Down Expand Up @@ -212,32 +213,35 @@
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));

Check warning on line 229 in frb_codegen/src/library/codegen/parser/mir/parser/function/real/mod.rs

View check run for this annotation

Codecov / codecov/patch

frb_codegen/src/library/codegen/parser/mir/parser/function/real/mod.rs#L229

Added line #L229 was not covered by tests
};

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));

Check warning on line 237 in frb_codegen/src/library/codegen/parser/mir/parser/function/real/mod.rs

View check run for this annotation

Codecov / codecov/patch

frb_codegen/src/library/codegen/parser/mir/parser/function/real/mod.rs#L237

Added line #L237 was not covered by tests
}
} 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 @@
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 @@
};

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 @@
}
}

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 @@
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 @@
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
Loading