Skip to content

feat: merge modules #2217

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

Open
wants to merge 1 commit into
base: spr/main/6b579de4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 61 additions & 4 deletions extensions/scarb-doc/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,72 @@ impl Crate {
pointer.insert_extern_function(item);
}
for item in all_pub_ues.use_submodules.into_iter() {
let ancestors = get_ancestors_vector(&mut Vec::new(), item.module_id, db);
self.ensure_module_structure(db, ancestors);
// todo! replace pointer with a new merged module because it cannot be determined at this point if
// pointer was a virtual module. If so, not all module items might be documented as expected.
let mut ancestors = get_ancestors_vector(&mut Vec::new(), item.module_id, db);
if let Some(last_path) = ancestors.pop() {
let pointer = self.ensure_module_structure(db, ancestors);
if let Some(index) = pointer
.submodules
.iter()
.position(|module| module.module_id == last_path)
{
merge_modules(&mut pointer.submodules[index], item);
}
}
}
self.to_owned()
}
}

/// Merges subitems of virtual_module into documented_module so it contains all unique data from both modules.
/// Note that documented_module might have been created by [`Module::new_virtual`].
fn merge_modules(documented_module: &mut Module, virtual_module: Module) -> &mut Module {
for constant in virtual_module.constants {
documented_module.insert_constant(constant);
}
for free_function in virtual_module.free_functions {
documented_module.insert_free_function(free_function);
}
for struct_ in virtual_module.structs {
documented_module.insert_struct(struct_);
}
for enum_ in virtual_module.enums {
documented_module.insert_enum(enum_);
}
for type_alias in virtual_module.type_aliases {
documented_module.insert_type_alias(type_alias);
}
for impl_alias in virtual_module.impl_aliases {
documented_module.insert_impl_alias(impl_alias);
}
for trait_ in virtual_module.traits {
documented_module.insert_trait(trait_);
}
for impl_ in virtual_module.impls {
documented_module.insert_impl(impl_);
}
for extern_type in virtual_module.extern_types {
documented_module.insert_extern_type(extern_type);
}
for extern_function in virtual_module.extern_functions {
documented_module.insert_extern_function(extern_function);
}
for submodule2 in virtual_module.submodules {
if let Some(submodule_index) = documented_module
.submodules
.iter()
.position(|submodule1| submodule1.module_id == submodule2.module_id)
{
merge_modules(
&mut documented_module.submodules[submodule_index],
submodule2,
);
} else {
documented_module.submodules.push(submodule2);
}
}
documented_module
}

fn get_ancestors_vector(
ancestors: &mut Vec<ModuleId>,
module_id: ModuleId,
Expand Down
261 changes: 261 additions & 0 deletions extensions/scarb-doc/tests/data/json_reexports_merged_module.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
{
"format_version": 1,
"packages_information": [
{
"crate_": {
"root_module": {
"item_data": {
"name": "hello_world",
"doc": null,
"signature": null,
"full_path": "hello_world"
},
"submodules": [
{
"item_data": {
"name": "Alejandro",
"doc": null,
"signature": null,
"full_path": "hello_world::Alejandro"
},
"submodules": [],
"constants": [],
"free_functions": [],
"structs": [],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": [
{
"item_data": {
"name": "Rodrigo",
"doc": null,
"signature": null,
"full_path": "hello_world::Rodrigo"
},
"submodules": [
{
"item_data": {
"name": "Valentina",
"doc": null,
"signature": null,
"full_path": "hello_world::Rodrigo::Valentina"
},
"submodules": [],
"constants": [],
"free_functions": [],
"structs": [],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": []
}
}
],
"constants": [],
"free_functions": [],
"structs": [],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": []
}
}
]
}
},
{
"item_data": {
"name": "Isabella",
"doc": null,
"signature": null,
"full_path": "hello_world::Isabella"
},
"submodules": [],
"constants": [],
"free_functions": [],
"structs": [],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [
{
"members": [],
"item_data": {
"name": "Mariana",
"doc": null,
"signature": "struct Mariana {}",
"full_path": "hello_world::Rodrigo::Mariana"
}
}
],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": []
}
},
{
"item_data": {
"name": "Rodrigo",
"doc": null,
"signature": null,
"full_path": "hello_world::Rodrigo"
},
"submodules": [
{
"item_data": {
"name": "Valentina",
"doc": null,
"signature": null,
"full_path": "hello_world::Rodrigo::Valentina"
},
"submodules": [],
"constants": [],
"free_functions": [],
"structs": [],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": []
}
}
],
"constants": [],
"free_functions": [],
"structs": [
{
"members": [],
"item_data": {
"name": "Mariana",
"doc": null,
"signature": "struct Mariana {}",
"full_path": "hello_world::Rodrigo::Mariana"
}
}
],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": []
}
}
],
"constants": [],
"free_functions": [],
"structs": [],
"enums": [],
"type_aliases": [],
"impl_aliases": [],
"traits": [],
"impls": [],
"extern_types": [],
"extern_functions": [],
"pub_uses": {
"use_constants": [],
"use_free_functions": [],
"use_structs": [],
"use_enums": [],
"use_module_type_aliases": [],
"use_impl_aliases": [],
"use_traits": [],
"use_impl_defs": [],
"use_extern_types": [],
"use_extern_functions": [],
"use_submodules": []
}
}
},
"metadata": {
"name": "hello_world",
"authors": null
}
}
]
}
36 changes: 36 additions & 0 deletions extensions/scarb-doc/tests/reexports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,39 @@ fn test_reexports() {
.expected("./data/json_reexports.json")
.assert_files_match();
}

#[test]
fn test_reexports_merged_modules() {
let root_dir = TempDir::new().unwrap();

ProjectBuilder::start()
.name("hello_world")
.lib_cairo(indoc! {r#"
pub mod Alejandro {
pub use crate::Rodrigo;
}

pub mod Isabella {
pub use crate::Rodrigo::Mariana;
}

mod Rodrigo {
struct Mariana {}
struct Vicente {}
pub mod Valentina {}
}
"#})
.build(&root_dir);

Scarb::quick_snapbox()
.arg("doc")
.args(["--output-format", "json"])
.current_dir(&root_dir)
.assert()
.success();

JsonTargetChecker::default()
.actual(&root_dir.path().join("target/doc/output.json"))
.expected("./data/json_reexports_merged_module.json")
.assert_files_match();
}
Loading