Skip to content

Commit

Permalink
Merge pull request #2011 from fzyzcjy/feat/12119
Browse files Browse the repository at this point in the history
Support overriding things in third party crate (part 1)
  • Loading branch information
fzyzcjy committed Jun 2, 2024
2 parents 2645f09 + 9cc246c commit 517b75e
Show file tree
Hide file tree
Showing 32 changed files with 311 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ impl<'a> ApiDartGeneratorInfoTrait for PrimitiveListApiDartGenerator<'a> {
MirTypePrimitive::I16 => "Int16List",
MirTypePrimitive::U32 => "Uint32List",
MirTypePrimitive::I32 => "Int32List",
MirTypePrimitive::U64 => "Uint64List",
MirTypePrimitive::I64 => "Int64List",
MirTypePrimitive::U64 | MirTypePrimitive::Usize => "Uint64List",
MirTypePrimitive::I64 | MirTypePrimitive::Isize => "Int64List",
MirTypePrimitive::F32 => "Float32List",
MirTypePrimitive::F64 => "Float64List",
// frb-coverage:ignore-start
Expand Down
2 changes: 2 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/crates.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// This file is named `crates` not `crate`, because the latter is a Rust keyword

use crate::codegen::ir::hir::hierarchical::module::HirModule;
use crate::utils::crate_name::CrateName;

/// Represents a crate, including a map of its modules, imports, structs and enums.
#[derive(Debug, Clone, serde::Serialize)]
pub struct HirCrate {
pub(crate) name: CrateName,
pub(crate) root_module: HirModule,
}
11 changes: 11 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,24 @@ impl HirFunctionInner {
}
}

pub(crate) fn name(&self) -> String {
self.sig().ident.to_string()
}

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

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

pub(crate) fn span(&self) -> Span {
match self {
HirFunctionInner::Function { item_fn } => item_fn.span(),
Expand Down
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 @@ -3,4 +3,5 @@ pub(crate) mod function;
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 type_alias;
22 changes: 21 additions & 1 deletion frb_codegen/src/library/codegen/ir/hir/hierarchical/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,28 @@ pub enum HirVisibility {
}

impl HirModuleContent {
pub(crate) fn get_module_index_by_name(&self, mod_name: &str) -> Option<usize> {
self.modules
.iter()
.enumerate()
.filter(|(_, m)| *m.meta.namespace.path().last().unwrap() == mod_name)
.map(|(i, _)| i)
.next()
}

pub(crate) fn get_module_by_name(&self, mod_name: &str) -> Option<&HirModule> {
(self.modules.iter()).find(|m| *m.meta.namespace.path().last().unwrap() == mod_name)
self.get_module_index_by_name(mod_name)
.map(|i| &self.modules[i])
}

pub(crate) fn get_mut_module_by_name(&mut self, mod_name: &str) -> Option<&mut HirModule> {
self.get_module_index_by_name(mod_name)
.map(|i| self.modules.get_mut(i).unwrap())
}

pub(crate) fn remove_module_by_name(&mut self, mod_name: &str) -> Option<HirModule> {
self.get_module_index_by_name(mod_name)
.map(|index| self.modules.remove(index))
}

pub(crate) fn get_module_nested(&self, mod_names: &[&str]) -> Option<&HirModule> {
Expand Down
9 changes: 7 additions & 2 deletions frb_codegen/src/library/codegen/ir/hir/hierarchical/pack.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use crate::codegen::ir::hir::hierarchical::crates::HirCrate;
use crate::utils::crate_name::CrateName;
use std::collections::HashMap;

#[derive(Debug, Clone, serde::Serialize)]
pub struct HirPack {
pub(crate) crates: HashMap<CrateName, HirCrate>,
pub(crate) crates: Vec<HirCrate>,
}

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())
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use crate::codegen::ir::hir::hierarchical::module::HirVisibility;
use crate::codegen::ir::hir::hierarchical::syn_item_struct_or_enum::SynItemStructOrEnum;
use crate::utils::namespace::{Namespace, NamespacedName};
use derivative::Derivative;
use proc_macro2::Ident;
use quote::ToTokens;
use serde::{Serialize, Serializer};
use syn::{Attribute, ItemEnum, ItemStruct};
use syn::{ItemEnum, ItemStruct};

// This struct is surely used many times, but coverage tool thinks it is never used
// (possibly because of the macro?), so we manually exclude it from coverage report
// frb-coverage:ignore-start
#[derive(Clone, Derivative, Serialize)]
#[derivative(Debug)]
pub struct HirStructOrEnum<Item> {
pub struct HirStructOrEnum<Item: SynItemStructOrEnum> {
#[serde(serialize_with = "serialize_syn")]
pub(crate) ident: Ident,
#[derivative(Debug = "ignore")]
Expand All @@ -23,43 +24,11 @@ pub struct HirStructOrEnum<Item> {
}
// frb-coverage:ignore-end

#[derive(Clone, Debug, Serialize)]
pub struct HirStruct(pub HirStructOrEnum<ItemStruct>);
pub type HirStruct = HirStructOrEnum<ItemStruct>;
pub type HirEnum = HirStructOrEnum<ItemEnum>;

#[derive(Clone, Debug, Serialize)]
pub struct HirEnum(pub HirStructOrEnum<ItemEnum>);

pub trait HirStructOrEnumWrapper<Item> {
fn inner(&self) -> &HirStructOrEnum<Item>;

fn attrs(&self) -> &[Attribute];

fn with_namespace(&self, namespace: Namespace) -> Self;
}

macro_rules! struct_or_enum_wrapper {
($name:ident, $item:ident) => {
impl HirStructOrEnumWrapper<$item> for $name {
fn inner(&self) -> &HirStructOrEnum<$item> {
&self.0
}

fn attrs(&self) -> &[Attribute] {
&self.0.src.attrs
}

fn with_namespace(&self, namespace: Namespace) -> Self {
Self(self.0.with_namespace(namespace))
}
}
};
}

struct_or_enum_wrapper!(HirStruct, ItemStruct);
struct_or_enum_wrapper!(HirEnum, ItemEnum);

impl<Item: Clone> HirStructOrEnum<Item> {
fn with_namespace(&self, namespace: Namespace) -> Self {
impl<Item: SynItemStructOrEnum> HirStructOrEnum<Item> {
pub(crate) fn with_namespace(&self, namespace: Namespace) -> Self {
Self {
namespaced_name: NamespacedName::new(namespace, self.namespaced_name.name.clone()),
..self.to_owned()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use syn::*;

pub(crate) trait SynItemStructOrEnum: Clone {
fn attrs(&self) -> &[Attribute];

fn attrs_mut(&mut self) -> &mut Vec<Attribute>;
}

macro_rules! impl_trait {
($name:ident) => {
impl SynItemStructOrEnum for $name {
fn attrs(&self) -> &[syn::Attribute] {
&self.attrs
}

fn attrs_mut(&mut self) -> &mut Vec<syn::Attribute> {
&mut self.attrs
}
}
};
}

impl_trait!(ItemStruct);
impl_trait!(ItemEnum);
9 changes: 9 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/raw/crates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// This file is named `crates` not `crate`, because the latter is a Rust keyword

use crate::utils::crate_name::CrateName;

#[derive(Debug, Clone)]
pub struct HirRawCrate {
pub(crate) name: CrateName,
pub(crate) syn_file: syn::File,
}
8 changes: 2 additions & 6 deletions frb_codegen/src/library/codegen/ir/hir/raw/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
use crate::utils::crate_name::CrateName;
use std::collections::HashMap;

pub(crate) struct HirRawPack {
pub crates: HashMap<CrateName, syn::File>,
}
pub(crate) mod crates;
pub(crate) mod pack;
5 changes: 5 additions & 0 deletions frb_codegen/src/library/codegen/ir/hir/raw/pack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use crate::codegen::ir::hir::raw::crates::HirRawCrate;

pub(crate) struct HirRawPack {
pub crates: Vec<HirRawCrate>,
}
6 changes: 3 additions & 3 deletions frb_codegen/src/library/codegen/parser/hir/flat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ fn collect_structs(hir_pack: &HirPack) -> HashMap<String, &HirStruct> {
collect_objects_map(
hir_pack,
|module| &module.content.structs,
|x| (x.0.ident.to_string(), x),
|x| (x.ident.to_string(), x),
)
}

fn collect_enums(hir_pack: &HirPack) -> HashMap<String, &HirEnum> {
collect_objects_map(
hir_pack,
|module| &module.content.enums,
|x| (x.0.ident.to_string(), x),
|x| (x.ident.to_string(), x),
)
}

Expand Down Expand Up @@ -117,7 +117,7 @@ fn is_interest_mod(module: &HirModule) -> bool {
}

fn visit_pack<'a, F: FnMut(&'a HirModule)>(hir_pack: &'a HirPack, f: &mut F) {
for hir_crate in hir_pack.crates.values() {
for hir_crate in &hir_pack.crates {
visit_modules(&hir_crate.root_module, f);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ pub(crate) fn parse_crate(
namespace: crate_name.namespace(),
};
let root_module = parse_module(&file.items, info, config)?;
Ok(HirCrate { root_module })
Ok(HirCrate {
name: crate_name.to_owned(),
root_module,
})
}
16 changes: 9 additions & 7 deletions frb_codegen/src/library/codegen/parser/hir/hierarchical/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::codegen::ir::hir::hierarchical::pack::HirPack;
use crate::codegen::ir::hir::raw::HirRawPack;
use crate::codegen::ir::hir::raw::pack::HirRawPack;
use crate::codegen::parser::hir::hierarchical::crates::parse_crate;
use crate::codegen::parser::hir::internal_config::ParserHirInternalConfig;

Expand All @@ -10,21 +10,23 @@ pub(crate) mod mirror_ident;
pub(crate) mod module;
mod pub_use;
pub(crate) mod struct_or_enum;
mod third_party_override_transformer;
pub(crate) mod visibility;

pub(crate) fn parse(
config: &ParserHirInternalConfig,
hir_raw: &HirRawPack,
) -> anyhow::Result<HirPack> {
let pack = parse_raw(config, hir_raw)?;
let pack = third_party_override_transformer::transform(pack)?;
Ok(pack)
}

fn parse_raw(config: &ParserHirInternalConfig, hir_raw: &HirRawPack) -> anyhow::Result<HirPack> {
let crates = hir_raw
.crates
.iter()
.map(|(crate_name, syn_file)| {
Ok((
crate_name.to_owned(),
parse_crate(config, syn_file, crate_name)?,
))
})
.map(|c| parse_crate(config, &c.syn_file, &c.name))
.collect::<anyhow::Result<Vec<_>>>()?
.into_iter()
.collect();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::codegen::ir::hir::hierarchical::module::HirModule;
use crate::codegen::ir::hir::hierarchical::struct_or_enum::HirStructOrEnumWrapper;
use crate::utils::namespace::Namespace;
use itertools::Itertools;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::codegen::ir::hir::hierarchical::struct_or_enum::{HirEnum, HirStruct, HirStructOrEnum};
use crate::codegen::ir::hir::hierarchical::syn_item_struct_or_enum::SynItemStructOrEnum;
use crate::codegen::parser::hir::hierarchical::mirror_ident::{
parse_mirror_ident, ParseMirrorIdentOutput,
};
Expand All @@ -12,41 +13,23 @@ pub(crate) fn parse_syn_item_struct(
item: &ItemStruct,
namespace: &Namespace,
) -> anyhow::Result<Vec<HirStruct>> {
parse_syn_item_struct_or_enum(
item,
namespace,
&item.ident,
&item.attrs,
&item.vis,
HirStruct,
)
parse_syn_item_struct_or_enum(item, namespace, &item.ident, &item.attrs, &item.vis)
}

pub(crate) fn parse_syn_item_enum(
item: &ItemEnum,
namespace: &Namespace,
) -> anyhow::Result<Vec<HirEnum>> {
parse_syn_item_struct_or_enum(
item,
namespace,
&item.ident,
&item.attrs,
&item.vis,
HirEnum,
)
parse_syn_item_struct_or_enum(item, namespace, &item.ident, &item.attrs, &item.vis)
}

fn parse_syn_item_struct_or_enum<I: Clone, F, T>(
fn parse_syn_item_struct_or_enum<I: SynItemStructOrEnum>(
item: &I,
namespace: &Namespace,
item_ident: &Ident,
item_attrs: &[Attribute],
item_vis: &syn::Visibility,
constructor: F,
) -> anyhow::Result<Vec<T>>
where
F: Fn(HirStructOrEnum<I>) -> T,
{
) -> anyhow::Result<Vec<HirStructOrEnum<I>>> {
debug!("parse_syn_item_struct_or_enum item_ident={item_ident:?}");

let ParseMirrorIdentOutput { idents, mirror } = parse_mirror_ident(item_ident, item_attrs)?;
Expand All @@ -55,13 +38,13 @@ where
.into_iter()
.map(|ident| {
let ident_str = ident.to_string();
constructor(HirStructOrEnum {
HirStructOrEnum {
ident,
src: item.clone(),
visibility: item_vis.into(),
namespaced_name: NamespacedName::new(namespace.to_owned(), ident_str),
mirror,
})
}
})
.collect_vec())
}
Loading

0 comments on commit 517b75e

Please sign in to comment.