Skip to content

Commit 3301da4

Browse files
authored
Doc / Add --document-private-items flag (#1528)
1 parent 25125cd commit 3301da4

11 files changed

+4718
-28
lines changed

extensions/scarb-doc/src/lib.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use cairo_lang_compiler::project::ProjectConfig;
2-
use cairo_lang_filesystem::db::FilesGroup;
2+
use cairo_lang_filesystem::db::{Edition, FilesGroup};
33
use cairo_lang_filesystem::ids::CrateLongId;
44
use scarb_metadata::{Metadata, PackageMetadata};
55
use serde::Serialize;
@@ -29,16 +29,29 @@ pub struct AdditionalMetadata {
2929
pub fn generate_packages_information(
3030
metadata: &Metadata,
3131
metadata_for_packages: &[PackageMetadata],
32+
document_private_items: bool,
3233
) -> Vec<PackageInformation> {
3334
let mut packages_information = vec![];
3435
for package_metadata in metadata_for_packages {
3536
let authors = package_metadata.manifest_metadata.authors.clone();
37+
let edition = package_metadata
38+
.edition
39+
.as_ref()
40+
.map(|edition| edition_from_string(edition).unwrap());
41+
42+
let should_ignore_visibility = match edition {
43+
Some(edition) => edition.ignore_visibility(),
44+
None => Edition::default().ignore_visibility(),
45+
};
46+
47+
let should_document_private_items = should_ignore_visibility || document_private_items;
3648

3749
let project_config = get_project_config(metadata, package_metadata);
3850

3951
let crate_ = generate_language_elements_tree_for_package(
4052
package_metadata.name.clone(),
4153
project_config,
54+
should_document_private_items,
4255
);
4356

4457
packages_information.push(PackageInformation {
@@ -55,10 +68,17 @@ pub fn generate_packages_information(
5568
fn generate_language_elements_tree_for_package(
5669
package_name: String,
5770
project_config: ProjectConfig,
71+
document_private_items: bool,
5872
) -> Crate {
5973
let db = ScarbDocDatabase::new(Some(project_config));
6074

6175
let main_crate_id = db.intern_crate(CrateLongId::Real(package_name.into()));
6276

63-
Crate::new(&db, main_crate_id)
77+
Crate::new(&db, main_crate_id, document_private_items)
78+
}
79+
80+
pub fn edition_from_string(edition_str: &str) -> Result<Edition, serde_json::Error> {
81+
// Format `edition` to be a valid JSON string.
82+
let edition = format!("\"{}\"", edition_str);
83+
serde_json::from_str(&edition)
6484
}

extensions/scarb-doc/src/main.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ struct Args {
3939
/// Specifies features to enable.
4040
#[command(flatten)]
4141
pub features: FeaturesSpec,
42+
43+
/// Generates documentation also for private items.
44+
#[arg(long, default_value_t = false)]
45+
document_private_items: bool,
4246
}
4347

4448
fn main_inner() -> Result<()> {
@@ -51,7 +55,12 @@ fn main_inner() -> Result<()> {
5155
.context("metadata command failed")?;
5256
let metadata_for_packages = args.packages_filter.match_many(&metadata)?;
5357
let output_dir = get_target_dir(&metadata).join(OUTPUT_DIR);
54-
let packages_information = generate_packages_information(&metadata, &metadata_for_packages);
58+
59+
let packages_information = generate_packages_information(
60+
&metadata,
61+
&metadata_for_packages,
62+
args.document_private_items,
63+
);
5564

5665
match args.output_format {
5766
OutputFormat::Json => {

extensions/scarb-doc/src/types.rs

+68-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// TODO(drknzz): Remove when not needed.
22
#![allow(dead_code)]
33

4+
use cairo_lang_semantic::items::visibility;
5+
use cairo_lang_utils::Upcast;
46
use itertools::Itertools;
57
use serde::Serialize;
68

@@ -27,13 +29,34 @@ pub struct Crate {
2729
}
2830

2931
impl Crate {
30-
pub fn new(db: &ScarbDocDatabase, crate_id: CrateId) -> Self {
32+
pub fn new(db: &ScarbDocDatabase, crate_id: CrateId, include_private_items: bool) -> Self {
33+
let root_module_id = ModuleId::CrateRoot(crate_id);
3134
Self {
32-
root_module: Module::new(db, ModuleId::CrateRoot(crate_id)),
35+
root_module: Module::new(db, root_module_id, root_module_id, include_private_items),
3336
}
3437
}
3538
}
3639

40+
fn is_visible_in_module(
41+
db: &ScarbDocDatabase,
42+
root_module_id: ModuleId,
43+
element_id: &dyn TopLevelLanguageElementId,
44+
) -> bool {
45+
let cotaining_module_id = element_id.parent_module(db);
46+
match db
47+
.module_item_info_by_name(cotaining_module_id, element_id.name(db.upcast()))
48+
.unwrap()
49+
{
50+
Some(module_item_info) => visibility::peek_visible_in(
51+
db,
52+
module_item_info.visibility,
53+
cotaining_module_id,
54+
root_module_id,
55+
),
56+
None => false,
57+
}
58+
}
59+
3760
#[derive(Serialize, Clone)]
3861
pub struct Module {
3962
#[serde(skip)]
@@ -54,7 +77,12 @@ pub struct Module {
5477
}
5578

5679
impl Module {
57-
pub fn new(db: &ScarbDocDatabase, module_id: ModuleId) -> Self {
80+
pub fn new(
81+
db: &ScarbDocDatabase,
82+
root_module_id: ModuleId,
83+
module_id: ModuleId,
84+
include_private_items: bool,
85+
) -> Self {
5886
// FIXME(#1438): compiler doesn't support fetching root crate doc
5987
let item_data = match module_id {
6088
ModuleId::CrateRoot(crate_id) => ItemData {
@@ -70,70 +98,95 @@ impl Module {
7098
),
7199
};
72100

101+
let should_include_item = |id: &dyn TopLevelLanguageElementId| {
102+
if include_private_items {
103+
return true;
104+
}
105+
is_visible_in_module(db, root_module_id, id)
106+
};
107+
73108
let module_constants = db.module_constants(module_id).unwrap();
74109
let constants = module_constants
75110
.iter()
111+
.filter(|(id, _)| should_include_item(*id))
76112
.map(|(id, _)| Constant::new(db, *id))
77113
.collect();
78114

79115
let module_free_functions = db.module_free_functions(module_id).unwrap();
80116
let free_functions = module_free_functions
81117
.iter()
118+
.filter(|(id, _)| should_include_item(*id))
82119
.map(|(id, _)| FreeFunction::new(db, *id))
83120
.collect();
84121

85122
let module_structs = db.module_structs(module_id).unwrap();
86123
let structs = module_structs
87124
.iter()
88-
.map(|(id, _)| Struct::new(db, *id))
125+
.filter(|(id, _)| should_include_item(*id))
126+
.map(|(id, _)| Struct::new(db, *id, root_module_id, include_private_items))
89127
.collect();
90128

91129
let module_enums = db.module_enums(module_id).unwrap();
92130
let enums = module_enums
93131
.iter()
132+
.filter(|(id, _)| should_include_item(*id))
94133
.map(|(id, _)| Enum::new(db, *id))
95134
.collect();
96135

97136
let module_type_aliases = db.module_type_aliases(module_id).unwrap();
98137
let type_aliases = module_type_aliases
99138
.iter()
139+
.filter(|(id, _)| should_include_item(*id))
100140
.map(|(id, _)| TypeAlias::new(db, *id))
101141
.collect();
102142

103143
let module_impl_aliases = db.module_impl_aliases(module_id).unwrap();
104144
let impl_aliases = module_impl_aliases
105145
.iter()
146+
.filter(|(id, _)| should_include_item(*id))
106147
.map(|(id, _)| ImplAlias::new(db, *id))
107148
.collect();
108149

109150
let module_traits = db.module_traits(module_id).unwrap();
110151
let traits = module_traits
111152
.iter()
153+
.filter(|(id, _)| should_include_item(*id))
112154
.map(|(id, _)| Trait::new(db, *id))
113155
.collect();
114156

115157
let module_impls = db.module_impls(module_id).unwrap();
116158
let impls = module_impls
117159
.iter()
160+
.filter(|(id, _)| should_include_item(*id))
118161
.map(|(id, _)| Impl::new(db, *id))
119162
.collect();
120163

121164
let module_extern_types = db.module_extern_types(module_id).unwrap();
122165
let extern_types = module_extern_types
123166
.iter()
167+
.filter(|(id, _)| should_include_item(*id))
124168
.map(|(id, _)| ExternType::new(db, *id))
125169
.collect();
126170

127171
let module_extern_functions = db.module_extern_functions(module_id).unwrap();
128172
let extern_functions = module_extern_functions
129173
.iter()
174+
.filter(|(id, _)| should_include_item(*id))
130175
.map(|(id, _)| ExternFunction::new(db, *id))
131176
.collect();
132177

133178
let module_submodules = db.module_submodules(module_id).unwrap();
134179
let submodules = module_submodules
135180
.iter()
136-
.map(|(id, _)| Self::new(db, ModuleId::Submodule(*id)))
181+
.filter(|(id, _)| should_include_item(*id))
182+
.map(|(id, _)| {
183+
Self::new(
184+
db,
185+
root_module_id,
186+
ModuleId::Submodule(*id),
187+
include_private_items,
188+
)
189+
})
137190
.collect();
138191

139192
Self {
@@ -253,7 +306,12 @@ pub struct Struct {
253306
}
254307

255308
impl Struct {
256-
pub fn new(db: &ScarbDocDatabase, id: StructId) -> Self {
309+
pub fn new(
310+
db: &ScarbDocDatabase,
311+
id: StructId,
312+
root_module_id: ModuleId,
313+
include_private_items: bool,
314+
) -> Self {
257315
let members = db.struct_members(id).unwrap();
258316

259317
let item_data = ItemData::new_without_signature(
@@ -264,6 +322,10 @@ impl Struct {
264322

265323
let members = members
266324
.iter()
325+
.filter(|(_, semantic_member)| {
326+
include_private_items
327+
|| is_visible_in_module(db, root_module_id, &semantic_member.id)
328+
})
267329
.map(|(_name, semantic_member)| {
268330
Member::new(db, semantic_member.id, item_data.full_path.clone())
269331
})

0 commit comments

Comments
 (0)