Skip to content

Commit

Permalink
Scarb Doc: cross item linkage (#1690)
Browse files Browse the repository at this point in the history
Waiting for [this](starkware-libs/cairo#6522) to
be merged.
  • Loading branch information
wawel37 authored Nov 25, 2024
1 parent aff9981 commit 200aa8f
Show file tree
Hide file tree
Showing 14 changed files with 469 additions and 212 deletions.
278 changes: 123 additions & 155 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions extensions/scarb-doc/src/docs_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::types::{
ImplFunction, ImplType, Member, Module, Struct, Trait, TraitConstant, TraitFunction, TraitType,
TypeAlias, Variant,
};
use cairo_lang_doc::parser::DocumentationCommentToken;

pub mod markdown;

Expand Down Expand Up @@ -71,6 +72,7 @@ fn collect_all_top_level_items_internal<'a, 'b>(

// Trait for items with no descendants.
// Used to enforce constraints on generic implementations of traits like `MarkdownDocItem`.

trait PrimitiveDocItem: DocItem {}

impl PrimitiveDocItem for Constant {}
Expand Down Expand Up @@ -109,7 +111,7 @@ trait DocItem {
const HEADER: &'static str;

fn name(&self) -> &str;
fn doc(&self) -> &Option<String>;
fn doc(&self) -> &Option<Vec<DocumentationCommentToken>>;
fn signature(&self) -> &Option<String>;
fn full_path(&self) -> &str;
}
Expand All @@ -123,7 +125,7 @@ macro_rules! impl_doc_item {
&self.item_data.name
}

fn doc(&self) -> &Option<String> {
fn doc(&self) -> &Option<Vec<DocumentationCommentToken>> {
&self.item_data.doc
}

Expand Down
33 changes: 19 additions & 14 deletions extensions/scarb-doc/src/docs_generation/markdown.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use anyhow::Result;
use camino::Utf8Path;
use context::MarkdownGenerationContext;
use itertools::chain;
use std::fs;

Expand All @@ -17,20 +18,22 @@ use crate::types::{
use crate::PackageInformation;

mod book_toml;
mod context;
mod summary;
mod traits;

const BASE_HEADER_LEVEL: usize = 1;
const SOURCE_DIRECTORY: &str = "src";
const BOOK_TOML_FILENAME: &str = "book.toml";
const SUMMARY_FILENAME: &str = "SUMMARY.md";
pub const SUMMARY_FILENAME: &str = "SUMMARY.md";

type Filename = String;
type GeneratedFile = (Filename, String);

pub struct MarkdownContent {
book_toml: String,
summary: String,
doc_files: Vec<(Filename, String)>,
doc_files: Vec<GeneratedFile>,
}

impl MarkdownContent {
Expand All @@ -52,18 +55,19 @@ impl MarkdownContent {
extern_functions,
} = top_level_items;

let context = MarkdownGenerationContext::from_crate(&package_information.crate_);
let docs_for_top_level_items = chain!(
generate_top_level_docs_contents(&modules)?,
generate_top_level_docs_contents(&constants)?,
generate_top_level_docs_contents(&free_functions)?,
generate_top_level_docs_contents(&structs)?,
generate_top_level_docs_contents(&enums)?,
generate_top_level_docs_contents(&type_aliases)?,
generate_top_level_docs_contents(&impl_aliases)?,
generate_top_level_docs_contents(&traits)?,
generate_top_level_docs_contents(&impls)?,
generate_top_level_docs_contents(&extern_types)?,
generate_top_level_docs_contents(&extern_functions)?,
generate_top_level_docs_contents(&modules, &context)?,
generate_top_level_docs_contents(&constants, &context)?,
generate_top_level_docs_contents(&free_functions, &context)?,
generate_top_level_docs_contents(&structs, &context)?,
generate_top_level_docs_contents(&enums, &context)?,
generate_top_level_docs_contents(&type_aliases, &context)?,
generate_top_level_docs_contents(&impl_aliases, &context)?,
generate_top_level_docs_contents(&traits, &context)?,
generate_top_level_docs_contents(&impls, &context)?,
generate_top_level_docs_contents(&extern_types, &context)?,
generate_top_level_docs_contents(&extern_functions, &context)?,
)
.collect::<Vec<(String, String)>>();

Expand Down Expand Up @@ -149,12 +153,13 @@ impl MarkdownContent {

fn generate_top_level_docs_contents(
items: &[&impl TopLevelMarkdownDocItem],
context: &MarkdownGenerationContext,
) -> Result<Vec<(Filename, String)>> {
items
.iter()
.map(|item| {
let filename = item.filename();
item.generate_markdown(BASE_HEADER_LEVEL)
item.generate_markdown(context, BASE_HEADER_LEVEL)
.map(|markdown| (filename, markdown))
})
.collect()
Expand Down
74 changes: 74 additions & 0 deletions extensions/scarb-doc/src/docs_generation/markdown/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::docs_generation::markdown::traits::WithPath;
use crate::docs_generation::markdown::SUMMARY_FILENAME;
use crate::types::Crate;
use cairo_lang_defs::ids::{ImplItemId, LookupItemId, TraitItemId};
use cairo_lang_doc::documentable_item::DocumentableItemId;
use cairo_lang_doc::parser::CommentLinkToken;
use std::collections::HashMap;

pub type IncludedItems<'a> = HashMap<DocumentableItemId, &'a dyn WithPath>;

pub struct MarkdownGenerationContext<'a> {
included_items: IncludedItems<'a>,
}

impl<'a> MarkdownGenerationContext<'a> {
pub fn from_crate(crate_: &'a Crate) -> Self {
let included_items = crate_.root_module.get_all_item_ids();
Self {
included_items: included_items
.into_iter()
.map(|(id, item)| {
let item: &dyn WithPath = item;
(id, item)
})
.collect(),
}
}

pub fn resolve_markdown_file_path_from_link(&self, link: &CommentLinkToken) -> String {
match link.resolved_item {
Some(resolved_item_id) => match self.included_items.get(&resolved_item_id) {
Some(resolved_item) => match resolved_item_id {
DocumentableItemId::Member(_)
| DocumentableItemId::Variant(_)
| DocumentableItemId::LookupItem(LookupItemId::TraitItem(TraitItemId::Type(
_,
)))
| DocumentableItemId::LookupItem(LookupItemId::TraitItem(
TraitItemId::Function(_),
))
| DocumentableItemId::LookupItem(LookupItemId::TraitItem(
TraitItemId::Constant(_),
))
| DocumentableItemId::LookupItem(LookupItemId::ImplItem(ImplItemId::Type(_)))
| DocumentableItemId::LookupItem(LookupItemId::ImplItem(
ImplItemId::Function(_),
))
| DocumentableItemId::LookupItem(LookupItemId::ImplItem(
ImplItemId::Constant(_),
)) => {
match resolved_item.parent_full_path() {
Some(parent_path) => {
format!(
"{}#{}",
path_to_file_link(&parent_path),
resolved_item.name().to_lowercase()
)
}
// Only root_module / crate doesn't have the parent.
_ => SUMMARY_FILENAME.to_string(),
}
}
_ => path_to_file_link(&resolved_item.full_path()),
},
None => link.to_string(),
},
None => link.to_string(),
}
}
}

fn path_to_file_link(path: &str) -> String {
format!("./{}.md", path.replace("::", "-"))
}
Loading

0 comments on commit 200aa8f

Please sign in to comment.