-
Notifications
You must be signed in to change notification settings - Fork 305
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2025 from fzyzcjy/feat/12138
Improve pub use parsing and trait definition parsing in third party crates
- Loading branch information
Showing
16 changed files
with
204 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
use crate::utils::namespace::Namespace; | ||
use proc_macro2::Ident; | ||
|
||
pub(crate) trait HirCommon { | ||
fn with_namespace(&self, namespace: Namespace) -> Self; | ||
|
||
fn ident(&self) -> Ident; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 30 additions & 3 deletions
33
frb_codegen/src/library/codegen/ir/hir/hierarchical/traits.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,44 @@ | ||
use crate::codegen::ir::hir::hierarchical::misc::HirCommon; | ||
use crate::utils::namespace::Namespace; | ||
use serde::Serialize; | ||
use proc_macro2::Ident; | ||
use serde::{Serialize, Serializer}; | ||
use syn::{ItemImpl, ItemTrait}; | ||
|
||
#[derive(Debug, Clone, Serialize)] | ||
pub(crate) struct HirTrait { | ||
pub(crate) namespace: Namespace, | ||
#[serde(skip_serializing)] | ||
#[serde(serialize_with = "serialize_item_trait")] | ||
pub(crate) item_trait: ItemTrait, | ||
} | ||
|
||
#[derive(Debug, Clone, Serialize)] | ||
pub(crate) struct HirTraitImpl { | ||
pub(crate) namespace: Namespace, | ||
#[serde(skip_serializing)] | ||
#[serde(serialize_with = "serialize_item_impl")] | ||
pub(crate) item_impl: ItemImpl, | ||
} | ||
|
||
impl HirCommon for HirTrait { | ||
fn with_namespace(&self, namespace: Namespace) -> Self { | ||
Self { | ||
namespace, | ||
..self.to_owned() | ||
} | ||
} | ||
|
||
fn ident(&self) -> Ident { | ||
self.item_trait.ident.clone() | ||
} | ||
} | ||
|
||
fn serialize_item_trait<S: Serializer>(x: &ItemTrait, s: S) -> Result<S::Ok, S::Error> { | ||
s.serialize_str(&format!("ident={}", x.ident)) | ||
} | ||
|
||
fn serialize_item_impl<S: Serializer>(x: &ItemImpl, s: S) -> Result<S::Ok, S::Error> { | ||
s.serialize_str(&format!("self_ty={}", ty_to_string(&x.self_ty))) | ||
} | ||
|
||
fn ty_to_string(ty: &syn::Type) -> String { | ||
quote::quote!(#ty).to_string() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 71 additions & 20 deletions
91
frb_codegen/src/library/codegen/parser/hir/hierarchical/module/pub_use_transformer.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,111 @@ | ||
use crate::codegen::ir::hir::hierarchical::misc::HirCommon; | ||
use crate::codegen::ir::hir::hierarchical::module::HirModule; | ||
use crate::utils::namespace::Namespace; | ||
use itertools::Itertools; | ||
|
||
pub(crate) fn transform(mut module: HirModule, items: &[syn::Item]) -> anyhow::Result<HirModule> { | ||
let pub_use_names = parse_pub_use_from_items(items); | ||
for pub_use_name in pub_use_names { | ||
transform_module_by_pub_use_single(&mut module, &pub_use_name)?; | ||
// Only apply to third party crate currently, since in self crate usually no need to care about this | ||
if module.meta.namespace.crate_name().is_self_crate() { | ||
return Ok(module); | ||
} | ||
|
||
let pub_use_infos = parse_pub_use_from_items(items); | ||
for pub_use_info in pub_use_infos { | ||
transform_module_by_pub_use_single(&mut module, &pub_use_info)?; | ||
} | ||
Ok(module) | ||
} | ||
|
||
fn parse_pub_use_from_items(items: &[syn::Item]) -> Vec<Namespace> { | ||
fn parse_pub_use_from_items(items: &[syn::Item]) -> Vec<PubUseInfo> { | ||
items | ||
.iter() | ||
.filter_map(parse_pub_use_from_item) | ||
.collect_vec() | ||
} | ||
|
||
fn parse_pub_use_from_item(item: &syn::Item) -> Option<Namespace> { | ||
fn parse_pub_use_from_item(item: &syn::Item) -> Option<PubUseInfo> { | ||
if let syn::Item::Use(item_use) = item { | ||
if matches!(item_use.vis, syn::Visibility::Public(_)) { | ||
let tree = &item_use.tree; | ||
let tree_string = quote::quote!(#tree).to_string().replace(' ', ""); | ||
if let Some(interest_use_part) = tree_string.strip_suffix("::*") { | ||
return Some(Namespace::new_raw(interest_use_part.to_owned())); | ||
} | ||
let tree_parts = tree_string.split(Namespace::SEP).collect_vec(); | ||
let name_filters = match *tree_parts.last().unwrap() { | ||
"*" => None, | ||
x => Some(vec![x.to_string()]), | ||
}; | ||
|
||
return Some(PubUseInfo { | ||
namespace: Namespace::new( | ||
(tree_parts[..tree_parts.len() - 1].iter()) | ||
.map(ToString::to_string) | ||
.collect_vec(), | ||
), | ||
name_filters, | ||
}); | ||
} | ||
} | ||
None | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
struct PubUseInfo { | ||
namespace: Namespace, | ||
name_filters: Option<Vec<String>>, | ||
} | ||
|
||
impl PubUseInfo { | ||
fn is_interest_name(&self, name: &str) -> bool { | ||
if let Some(name_filters) = &self.name_filters { | ||
name_filters.contains(&name.to_owned()) | ||
} else { | ||
true | ||
} | ||
} | ||
} | ||
|
||
fn transform_module_by_pub_use_single( | ||
module: &mut HirModule, | ||
pub_use_name: &Namespace, | ||
pub_use_info: &PubUseInfo, | ||
) -> anyhow::Result<()> { | ||
if let Some(src_mod) = module.content.get_module_nested(&pub_use_name.path()) { | ||
if let Some(src_mod) = (module.content).get_module_nested(&pub_use_info.namespace.path()) { | ||
log::debug!( | ||
"transform_module_by_pub_use_single pub_use_info={:?}", | ||
pub_use_info | ||
); | ||
|
||
if src_mod.meta.is_public() { | ||
log::debug!("transform_module_by_pub_use_single skip `{pub_use_info:?}` since src mod already public"); | ||
return Ok(()); | ||
} | ||
|
||
let self_namespace = &module.meta.namespace; | ||
|
||
let src_functions = (src_mod.content.functions.iter()) | ||
.map(|x| x.with_namespace(self_namespace.clone())) | ||
.collect_vec(); | ||
let src_structs = (src_mod.content.structs.iter()) | ||
.map(|x| x.with_namespace(self_namespace.clone())) | ||
.collect_vec(); | ||
let src_enums = (src_mod.content.enums.iter()) | ||
.map(|x| x.with_namespace(self_namespace.clone())) | ||
.collect_vec(); | ||
let src_functions = | ||
transform_items(&src_mod.content.functions, self_namespace, pub_use_info); | ||
let src_structs = transform_items(&src_mod.content.structs, self_namespace, pub_use_info); | ||
let src_enums = transform_items(&src_mod.content.enums, self_namespace, pub_use_info); | ||
let src_traits = transform_items(&src_mod.content.traits, self_namespace, pub_use_info); | ||
|
||
module.content.functions.extend(src_functions); | ||
module.content.structs.extend(src_structs); | ||
module.content.enums.extend(src_enums); | ||
module.content.traits.extend(src_traits); | ||
} else { | ||
log::debug!( | ||
"transform_module_by_pub_use_single skip `{pub_use_name}` since cannot find mod" | ||
"transform_module_by_pub_use_single skip `{pub_use_info:?}` since cannot find mod" | ||
); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn transform_items<T: HirCommon>( | ||
items: &[T], | ||
self_namespace: &Namespace, | ||
pub_use_info: &PubUseInfo, | ||
) -> Vec<T> { | ||
(items.iter()) | ||
.filter(|x| pub_use_info.is_interest_name(&x.ident().to_string())) | ||
.map(|x| x.with_namespace(self_namespace.clone())) | ||
.collect_vec() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.