Skip to content

Commit

Permalink
Add diagnostics and handle errors gracefully / Upgrade Cairo. (#1590)
Browse files Browse the repository at this point in the history
### Please, during review check if the speed of diagnostics during doc
generation is acceptable.

---------

Signed-off-by: maciektr <[email protected]>
Co-authored-by: Maciej Trątnowiecki <[email protected]>
  • Loading branch information
wawel37 and maciektr authored Oct 14, 2024
1 parent d01ccee commit 4d91be7
Show file tree
Hide file tree
Showing 18 changed files with 857 additions and 345 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions extensions/scarb-doc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ cairo-lang-semantic.workspace = true
cairo-lang-starknet.workspace = true
cairo-lang-syntax.workspace = true
cairo-lang-utils.workspace = true
cairo-lang-lowering.workspace = true
cairo-lang-diagnostics.workspace = true
expect-test.workspace = true
indoc.workspace = true
itertools.workspace = true
Expand All @@ -30,6 +32,7 @@ serde.workspace = true
serde_json.workspace = true
salsa.workspace = true
smol_str.workspace = true
thiserror.workspace = true

[dev-dependencies]
assert_fs.workspace = true
Expand Down
22 changes: 15 additions & 7 deletions extensions/scarb-doc/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use cairo_lang_filesystem::db::{
init_files_group, AsFilesGroupMut, ExternalFiles, FilesDatabase, FilesGroup, CORELIB_CRATE_NAME,
};
use cairo_lang_filesystem::ids::VirtualFile;
use cairo_lang_lowering::db::{LoweringDatabase, LoweringGroup};
use cairo_lang_parser::db::{ParserDatabase, ParserGroup};
use cairo_lang_semantic::db::{SemanticDatabase, SemanticGroup};
use cairo_lang_semantic::inline_macros::get_default_plugin_suite;
Expand All @@ -25,27 +26,28 @@ use salsa;
SyntaxDatabase,
DefsDatabase,
SemanticDatabase,
DocDatabase
DocDatabase,
LoweringDatabase
)]
pub struct ScarbDocDatabase {
storage: salsa::Storage<Self>,
}

impl ScarbDocDatabase {
pub fn new(project_config: Option<ProjectConfig>) -> Self {
let plugin_suite = [get_default_plugin_suite(), starknet_plugin_suite()]
.into_iter()
.fold(PluginSuite::default(), |mut acc, suite| {
acc.add(suite);
acc
});
let mut db = Self {
storage: Default::default(),
};

init_files_group(&mut db);

db.set_cfg_set(Self::initial_cfg_set().into());
let plugin_suite = [get_default_plugin_suite(), starknet_plugin_suite()]
.into_iter()
.fold(PluginSuite::default(), |mut acc, suite| {
acc.add(suite);
acc
});

db.apply_plugin_suite(plugin_suite);

Expand Down Expand Up @@ -131,3 +133,9 @@ impl Upcast<dyn DocGroup> for ScarbDocDatabase {
self
}
}

impl Upcast<dyn LoweringGroup> for ScarbDocDatabase {
fn upcast(&self) -> &(dyn LoweringGroup + 'static) {
self
}
}
82 changes: 45 additions & 37 deletions extensions/scarb-doc/src/docs_generation/markdown.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::{Context, Result};
use anyhow::Result;
use camino::Utf8Path;
use itertools::{chain, Itertools};
use itertools::chain;
use std::fs;

use crate::docs_generation::markdown::book_toml::generate_book_toml_content;
Expand All @@ -9,6 +9,7 @@ use crate::docs_generation::markdown::traits::{
generate_markdown_list_for_top_level_subitems, TopLevelMarkdownDocItem,
};
use crate::docs_generation::{collect_all_top_level_items, TopLevelItems};
use crate::errors::{IODirectoryCreationError, IOWriteError};
use crate::types::{
Constant, Enum, ExternFunction, ExternType, FreeFunction, Impl, ImplAlias, Module, Struct,
Trait, TypeAlias,
Expand All @@ -33,10 +34,10 @@ pub struct MarkdownContent {
}

impl MarkdownContent {
pub fn from_crate(package_information: &PackageInformation) -> Self {
pub fn from_crate(package_information: &PackageInformation) -> Result<Self> {
let top_level_items = collect_all_top_level_items(&package_information.crate_);

let summary_file_content = generate_summary_file_content(&top_level_items);
let summary_file_content = generate_summary_file_content(&top_level_items)?;
let TopLevelItems {
modules,
constants,
Expand All @@ -52,91 +53,94 @@ impl MarkdownContent {
} = top_level_items;

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)?,
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)?,
)
.collect_vec();
.collect::<Vec<(String, String)>>();

let summaries_for_top_level_items = vec![
(
Module::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&modules, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&modules, BASE_HEADER_LEVEL)?,
),
(
Constant::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&constants, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&constants, BASE_HEADER_LEVEL)?,
),
(
FreeFunction::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&free_functions, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&free_functions, BASE_HEADER_LEVEL)?,
),
(
Struct::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&structs, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&structs, BASE_HEADER_LEVEL)?,
),
(
Enum::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&enums, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&enums, BASE_HEADER_LEVEL)?,
),
(
TypeAlias::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&type_aliases, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&type_aliases, BASE_HEADER_LEVEL)?,
),
(
ImplAlias::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&impl_aliases, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&impl_aliases, BASE_HEADER_LEVEL)?,
),
(
Trait::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&traits, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&traits, BASE_HEADER_LEVEL)?,
),
(
Impl::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&impls, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&impls, BASE_HEADER_LEVEL)?,
),
(
ExternType::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&extern_types, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(&extern_types, BASE_HEADER_LEVEL)?,
),
(
ExternFunction::ITEMS_SUMMARY_FILENAME.to_string(),
generate_markdown_list_for_top_level_subitems(&extern_functions, BASE_HEADER_LEVEL),
generate_markdown_list_for_top_level_subitems(
&extern_functions,
BASE_HEADER_LEVEL,
)?,
),
]
.into_iter()
.filter(|(_filename, content)| !content.is_empty())
.collect_vec();
.collect::<Vec<_>>();

Self {
Ok(Self {
book_toml: generate_book_toml_content(&package_information.metadata),
summary: summary_file_content,
doc_files: chain!(docs_for_top_level_items, summaries_for_top_level_items).collect(),
}
})
}

pub fn save(self, output_dir: &Utf8Path) -> Result<()> {
let source_directory_path = output_dir.join(SOURCE_DIRECTORY);
fs::create_dir_all(&source_directory_path)
.context("failed to create directory for docs")?;
.map_err(|e| IODirectoryCreationError::new(e, "generated documentation"))?;

fs::write(output_dir.join(BOOK_TOML_FILENAME), self.book_toml)
.context("failed to write book.toml content to a file")?;
.map_err(|e| IOWriteError::new(e, "book.toml"))?;

fs::write(source_directory_path.join(SUMMARY_FILENAME), self.summary)
.context("failed to write summary content to a file")?;
.map_err(|e| IOWriteError::new(e, "summary"))?;

for (filename, file_content) in self.doc_files {
fs::write(source_directory_path.join(filename), file_content)
.context("failed to write content to a doc file")?;
fs::write(source_directory_path.join(filename.clone()), file_content)
.map_err(|e| IOWriteError::new(e, filename.as_ref()))?;
}

Ok(())
Expand All @@ -145,9 +149,13 @@ impl MarkdownContent {

fn generate_top_level_docs_contents(
items: &[&impl TopLevelMarkdownDocItem],
) -> Vec<(Filename, String)> {
) -> Result<Vec<(Filename, String)>> {
items
.iter()
.map(|item| (item.filename(), item.generate_markdown(BASE_HEADER_LEVEL)))
.map(|item| {
let filename = item.filename();
item.generate_markdown(BASE_HEADER_LEVEL)
.map(|markdown| (filename, markdown))
})
.collect()
}
37 changes: 18 additions & 19 deletions extensions/scarb-doc/src/docs_generation/markdown/summary.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Result;
use std::fmt::Write;

use crate::docs_generation::markdown::traits::TopLevelMarkdownDocItem;
Expand All @@ -6,7 +7,7 @@ use crate::docs_generation::TopLevelItems;

use super::traits::mark_duplicated_item_with_relative_path;

pub fn generate_summary_file_content(top_level_items: &TopLevelItems) -> String {
pub fn generate_summary_file_content(top_level_items: &TopLevelItems) -> Result<String> {
let header = str::repeat("#", BASE_HEADER_LEVEL);

let mut markdown = format!("{header} Summary\n\n");
Expand All @@ -25,24 +26,24 @@ pub fn generate_summary_file_content(top_level_items: &TopLevelItems) -> String
extern_functions,
} = top_level_items;

markdown += &generate_markdown_list_summary_for_top_level_subitems(modules);
markdown += &generate_markdown_list_summary_for_top_level_subitems(constants);
markdown += &generate_markdown_list_summary_for_top_level_subitems(free_functions);
markdown += &generate_markdown_list_summary_for_top_level_subitems(structs);
markdown += &generate_markdown_list_summary_for_top_level_subitems(enums);
markdown += &generate_markdown_list_summary_for_top_level_subitems(type_aliases);
markdown += &generate_markdown_list_summary_for_top_level_subitems(impl_aliases);
markdown += &generate_markdown_list_summary_for_top_level_subitems(traits);
markdown += &generate_markdown_list_summary_for_top_level_subitems(impls);
markdown += &generate_markdown_list_summary_for_top_level_subitems(extern_types);
markdown += &generate_markdown_list_summary_for_top_level_subitems(extern_functions);
markdown += &generate_markdown_list_summary_for_top_level_subitems(modules)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(constants)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(free_functions)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(structs)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(enums)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(type_aliases)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(impl_aliases)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(traits)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(impls)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(extern_types)?;
markdown += &generate_markdown_list_summary_for_top_level_subitems(extern_functions)?;

markdown
Ok(markdown)
}

fn generate_markdown_list_summary_for_top_level_subitems<T: TopLevelMarkdownDocItem>(
subitems: &[&T],
) -> String {
) -> Result<String> {
let mut markdown = String::new();

if !subitems.is_empty() {
Expand All @@ -51,18 +52,16 @@ fn generate_markdown_list_summary_for_top_level_subitems<T: TopLevelMarkdownDocI
"- [{}](./{})\n",
T::HEADER,
T::ITEMS_SUMMARY_FILENAME
)
.unwrap();
)?;
let items_with_relative_path = mark_duplicated_item_with_relative_path(subitems);
for (item, relative_path) in items_with_relative_path {
writeln!(
&mut markdown,
" {}",
item.generate_markdown_list_item(relative_path)
)
.unwrap();
)?;
}
}

markdown
Ok(markdown)
}
Loading

0 comments on commit 4d91be7

Please sign in to comment.