Skip to content

Commit

Permalink
Doc/support reexported modules (#1620)
Browse files Browse the repository at this point in the history
  • Loading branch information
wawel37 authored Oct 2, 2024
1 parent 253bed7 commit 01e46b0
Show file tree
Hide file tree
Showing 3 changed files with 844 additions and 60 deletions.
241 changes: 181 additions & 60 deletions extensions/scarb-doc/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
use cairo_lang_semantic::items::visibility;
use cairo_lang_semantic::items::functions::GenericFunctionId;
use cairo_lang_semantic::items::us::SemanticUseEx;
use cairo_lang_semantic::items::visibility::{self, Visibility};
use cairo_lang_semantic::resolve::ResolvedGenericItem;
use cairo_lang_syntax::node::helpers::QueryAttrs;
use cairo_lang_utils::Upcast;
use itertools::chain;
use serde::Serialize;

use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::{
ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, ImplAliasId,
ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, GenericTypeId, ImplAliasId,
ImplConstantDefId, ImplDefId, ImplFunctionId, ImplItemId, ImplTypeDefId, LanguageElementId,
LookupItemId, MemberId, ModuleId, ModuleItemId, ModuleTypeAliasId, StructId,
TopLevelLanguageElementId, TraitConstantId, TraitFunctionId, TraitId, TraitItemId, TraitTypeId,
VariantId,
LookupItemId, MemberId, ModuleId, ModuleItemId, ModuleTypeAliasId, NamedLanguageElementId,
StructId, SubmoduleId, TopLevelLanguageElementId, TraitConstantId, TraitFunctionId, TraitId,
TraitItemId, TraitTypeId, VariantId,
};
use cairo_lang_doc::db::DocGroup;
use cairo_lang_doc::documentable_item::DocumentableItemId;
Expand Down Expand Up @@ -72,6 +76,95 @@ pub struct Module {
pub extern_functions: Vec<ExternFunction>,
}

struct ModulePubUses {
pub use_constants: Vec<ConstantId>,
pub use_free_functions: Vec<FreeFunctionId>,
pub use_structs: Vec<StructId>,
pub use_enums: Vec<EnumId>,
pub use_module_type_aliases: Vec<ModuleTypeAliasId>,
pub use_impl_aliases: Vec<ImplAliasId>,
pub use_traits: Vec<TraitId>,
pub use_impl_defs: Vec<ImplDefId>,
pub use_extern_types: Vec<ExternTypeId>,
pub use_extern_functions: Vec<ExternFunctionId>,
pub use_submodules: Vec<SubmoduleId>,
pub use_crates: Vec<CrateId>,
}

impl ModulePubUses {
pub fn new(db: &ScarbDocDatabase, module_id: ModuleId) -> Self {
let module_use_items: Vec<ResolvedGenericItem> = db
.module_uses(module_id)
.unwrap()
.iter()
.filter_map(|(use_id, _)| {
let visibility = db
.module_item_info_by_name(module_id, use_id.name(db))
.unwrap()
.unwrap()
.visibility;
if visibility == Visibility::Public {
Some(db.use_resolved_item(*use_id).unwrap())
} else {
None
}
})
.collect();

let mut use_constants = Vec::new();
let mut use_free_functions = Vec::new();
let mut use_structs = Vec::new();
let mut use_enums = Vec::new();
let mut use_module_type_aliases = Vec::new();
let mut use_impl_aliases = Vec::new();
let mut use_traits = Vec::new();
let mut use_impl_defs = Vec::new();
let mut use_extern_types = Vec::new();
let mut use_extern_functions = Vec::new();
let mut use_submodules = Vec::new();
let mut use_crates = Vec::new();

for item in module_use_items {
match item {
ResolvedGenericItem::GenericConstant(id) => use_constants.push(id),
ResolvedGenericItem::GenericFunction(GenericFunctionId::Free(id)) => {
use_free_functions.push(id)
}
ResolvedGenericItem::GenericType(GenericTypeId::Struct(id)) => use_structs.push(id),
ResolvedGenericItem::GenericType(GenericTypeId::Enum(id)) => use_enums.push(id),
ResolvedGenericItem::GenericTypeAlias(id) => use_module_type_aliases.push(id),
ResolvedGenericItem::GenericImplAlias(id) => use_impl_aliases.push(id),
ResolvedGenericItem::Trait(id) => use_traits.push(id),
ResolvedGenericItem::Impl(id) => use_impl_defs.push(id),
ResolvedGenericItem::GenericType(GenericTypeId::Extern(id)) => {
use_extern_types.push(id)
}
ResolvedGenericItem::GenericFunction(GenericFunctionId::Extern(id)) => {
use_extern_functions.push(id)
}
ResolvedGenericItem::Module(ModuleId::Submodule(id)) => use_submodules.push(id),
ResolvedGenericItem::Module(ModuleId::CrateRoot(id)) => use_crates.push(id),
_ => (),
}
}

Self {
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,
use_crates,
}
}
}

impl Module {
pub fn new(
db: &ScarbDocDatabase,
Expand All @@ -80,12 +173,7 @@ impl Module {
include_private_items: bool,
) -> Self {
let item_data = match module_id {
ModuleId::CrateRoot(crate_id) => ItemData {
name: crate_id.name(db).to_string(),
doc: db.get_item_documentation(DocumentableItemId::Crate(crate_id)),
signature: None,
full_path: module_id.full_path(db),
},
ModuleId::CrateRoot(crate_id) => ItemData::new_crate(db, crate_id),
ModuleId::Submodule(submodule_id) => ItemData::new_without_signature(
db,
submodule_id,
Expand All @@ -100,90 +188,114 @@ impl Module {
&& !is_doc_hidden_attr(db, &syntax_node)
};

let module_pubuses = ModulePubUses::new(db, module_id);

let module_constants = db.module_constants(module_id).unwrap();
let constants = module_constants
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| Constant::new(db, *id))
let constants = chain!(module_constants.keys(), module_pubuses.use_constants.iter())
.filter(|id| should_include_item(*id))
.map(|id| Constant::new(db, *id))
.collect();

let module_free_functions = db.module_free_functions(module_id).unwrap();
let free_functions = module_free_functions
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| FreeFunction::new(db, *id))
.collect();
let free_functions = chain!(
module_free_functions.keys(),
module_pubuses.use_free_functions.iter()
)
.filter(|id| should_include_item(*id))
.map(|id| FreeFunction::new(db, *id))
.collect();

let module_structs = db.module_structs(module_id).unwrap();
let structs = module_structs
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| Struct::new(db, *id, root_module_id, include_private_items))
let structs = chain!(module_structs.keys(), module_pubuses.use_structs.iter())
.filter(|id| should_include_item(*id))
.map(|id| Struct::new(db, *id, root_module_id, include_private_items))
.collect();

let module_enums = db.module_enums(module_id).unwrap();
let enums = module_enums
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| Enum::new(db, *id))
let enums = chain!(module_enums.keys(), module_pubuses.use_enums.iter())
.filter(|id| should_include_item(*id))
.map(|id| Enum::new(db, *id))
.collect();

let module_type_aliases = db.module_type_aliases(module_id).unwrap();
let type_aliases = module_type_aliases
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| TypeAlias::new(db, *id))
.collect();
let type_aliases = chain!(
module_type_aliases.keys(),
module_pubuses.use_module_type_aliases.iter()
)
.filter(|id| should_include_item(*id))
.map(|id| TypeAlias::new(db, *id))
.collect();

let module_impl_aliases = db.module_impl_aliases(module_id).unwrap();
let impl_aliases = module_impl_aliases
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| ImplAlias::new(db, *id))
.collect();
let impl_aliases = chain!(
module_impl_aliases.keys(),
module_pubuses.use_impl_aliases.iter()
)
.filter(|id| should_include_item(*id))
.map(|id| ImplAlias::new(db, *id))
.collect();

let module_traits = db.module_traits(module_id).unwrap();
let traits = module_traits
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| Trait::new(db, *id))
let traits = chain!(module_traits.keys(), module_pubuses.use_traits.iter())
.filter(|id| should_include_item(*id))
.map(|id| Trait::new(db, *id))
.collect();

let module_impls = db.module_impls(module_id).unwrap();
let impls = module_impls
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| Impl::new(db, *id))
let impls = chain!(module_impls.keys(), module_pubuses.use_impl_defs.iter())
.filter(|id| should_include_item(*id))
.map(|id| Impl::new(db, *id))
.collect();

let module_extern_types = db.module_extern_types(module_id).unwrap();
let extern_types = module_extern_types
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| ExternType::new(db, *id))
.collect();
let extern_types = chain!(
module_extern_types.keys(),
module_pubuses.use_extern_types.iter()
)
.filter(|id| should_include_item(*id))
.map(|id| ExternType::new(db, *id))
.collect();

let module_extern_functions = db.module_extern_functions(module_id).unwrap();
let extern_functions = module_extern_functions
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| ExternFunction::new(db, *id))
.collect();
let extern_functions = chain!(
module_extern_functions.keys(),
module_pubuses.use_extern_functions.iter()
)
.filter(|id| should_include_item(*id))
.map(|id| ExternFunction::new(db, *id))
.collect();

let module_submodules = db.module_submodules(module_id).unwrap();
let submodules = module_submodules
let mut submodules: Vec<Module> = chain!(
module_submodules.keys(),
module_pubuses.use_submodules.iter()
)
.filter(|id| should_include_item(*id))
.map(|id| {
Self::new(
db,
root_module_id,
ModuleId::Submodule(*id),
include_private_items,
)
})
.collect();

let reexported_crates_as_modules: Vec<Module> = module_pubuses
.use_crates
.iter()
.filter(|(id, _)| should_include_item(*id))
.map(|(id, _)| {
.map(|id| {
Self::new(
db,
root_module_id,
ModuleId::Submodule(*id),
ModuleId::CrateRoot(*id),
include_private_items,
)
})
.collect();

submodules.extend(reexported_crates_as_modules);

Self {
module_id,
item_data,
Expand Down Expand Up @@ -240,6 +352,15 @@ impl ItemData {
full_path: id.full_path(db),
}
}

pub fn new_crate(db: &ScarbDocDatabase, id: CrateId) -> Self {
Self {
name: id.name(db).into(),
doc: db.get_item_documentation(DocumentableItemId::Crate(id)),
signature: None,
full_path: ModuleId::CrateRoot(id).full_path(db),
}
}
}

#[derive(Serialize, Clone)]
Expand Down
Loading

0 comments on commit 01e46b0

Please sign in to comment.