Skip to content

Commit

Permalink
Make paths displed on left nav bar if duplicated (#1592)
Browse files Browse the repository at this point in the history
  • Loading branch information
wawel37 authored Sep 17, 2024
1 parent 861c013 commit b23eaaa
Show file tree
Hide file tree
Showing 19 changed files with 331 additions and 8 deletions.
12 changes: 10 additions & 2 deletions extensions/scarb-doc/src/docs_generation/markdown/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use crate::docs_generation::markdown::traits::TopLevelMarkdownDocItem;
use crate::docs_generation::markdown::BASE_HEADER_LEVEL;
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 {
let header = str::repeat("#", BASE_HEADER_LEVEL);

Expand Down Expand Up @@ -51,8 +53,14 @@ fn generate_markdown_list_summary_for_top_level_subitems<T: TopLevelMarkdownDocI
T::ITEMS_SUMMARY_FILENAME
)
.unwrap();
for item in subitems {
writeln!(&mut markdown, " {}", item.generate_markdown_list_item()).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();
}
}

Expand Down
81 changes: 75 additions & 6 deletions extensions/scarb-doc/src/docs_generation/markdown/traits.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use itertools::Itertools;
use std::collections::HashMap;
use std::fmt::Write;

use crate::docs_generation::{DocItem, PrimitiveDocItem, TopLevelDocItem};
Expand All @@ -14,12 +15,15 @@ pub trait TopLevelMarkdownDocItem: MarkdownDocItem + TopLevelDocItem {
format!("{}.md", self.full_path().replace("::", "-"))
}

fn md_ref(&self) -> String {
format!("[{}](./{})", self.name(), self.filename())
fn md_ref(&self, relative_path: Option<String>) -> String {
match relative_path {
Some(path) => format!("[{}](./{})", path, self.filename()),
None => format!("[{}](./{})", self.name(), self.filename()),
}
}

fn generate_markdown_list_item(&self) -> String {
format!("- {}\n", self.md_ref())
fn generate_markdown_list_item(&self, relative_path: Option<String>) -> String {
format!("- {}\n", self.md_ref(relative_path))
}
}

Expand Down Expand Up @@ -153,6 +157,65 @@ impl MarkdownDocItem for Trait {
}
}

/// Takes items, and appends for each of them a path, that was trimmed based on the common prefix of all of the items,
/// cthat share the same name.
pub fn mark_duplicated_item_with_relative_path<'a, T: TopLevelMarkdownDocItem + 'a>(
items: &'a [&'a T],
) -> Vec<(&&'a T, Option<String>)> {
let mut paths_for_item_name = HashMap::<String, Vec<String>>::new();
for item in items {
paths_for_item_name
.entry(item.name().to_string())
.or_default()
.push(item.name().to_string());
}

let common_path_prefix_lengths_for_item: HashMap<String, usize> = paths_for_item_name
.iter()
.filter(|(_, paths)| paths.len() > 1)
.map(|(name, paths)| {
let splitted_paths: Vec<Vec<String>> = paths
.iter()
.map(|path| path.split("::").map(|val| val.to_string()).collect())
.collect();

let min_len = splitted_paths
.iter()
.map(|vec| vec.len())
.min()
.unwrap_or(0);

let mut prefix_len = min_len;
for i in 0..min_len {
let first = &splitted_paths[0][i];
if !splitted_paths.iter().all(|vec| &vec[i] == first) {
prefix_len = i;
break;
}
}

(name.clone(), prefix_len)
})
.collect();

items
.iter()
.map(|item| {
let relative_path =
common_path_prefix_lengths_for_item
.get(item.name())
.map(|common_prefix_length| {
item.full_path()
.split("::")
.skip(*common_prefix_length)
.collect::<Vec<_>>()
.join("::")
});
(item, relative_path)
})
.collect::<Vec<_>>()
}

pub fn generate_markdown_list_for_top_level_subitems<T: TopLevelMarkdownDocItem>(
subitems: &[&T],
header_level: usize,
Expand All @@ -163,8 +226,14 @@ pub fn generate_markdown_list_for_top_level_subitems<T: TopLevelMarkdownDocItem>
let header = str::repeat("#", header_level);

writeln!(&mut markdown, "{header} {}\n", T::HEADER).unwrap();
for item in subitems {
writeln!(&mut markdown, "{}", item.generate_markdown_list_item()).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();
}
}

Expand Down
19 changes: 19 additions & 0 deletions extensions/scarb-doc/tests/data/duplicated_item_names/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[book]
authors = ["<unknown>"]
language = "en"
multilingual = false
src = "src"
title = "hello_world - Cairo"

[output.html]
no-section-label = true

[output.html.playground]
runnable = false

[output.html.fold]
enable = true
level = 0

[output.html.code.hidelines]
cairo = "#"
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Summary

- [Modules](./modules.md)

- [hello_world](./hello_world.md)

- [sub_module](./hello_world-sub_module.md)

- [Free functions](./free_functions.md)

- [main](./hello_world-main.md)

- [unique_function_name](./hello_world-unique_function_name.md)

- [duplicated_function_name](./hello_world-duplicated_function_name.md)

- [sub_module::duplicated_function_name](./hello_world-sub_module-duplicated_function_name.md)

- [Enums](./enums.md)

- [DuplicatedEnumName](./hello_world-DuplicatedEnumName.md)

- [sub_module::DuplicatedEnumName](./hello_world-sub_module-DuplicatedEnumName.md)

- [Traits](./traits.md)

- [DuplicatedTraitName](./hello_world-DuplicatedTraitName.md)

- [sub_module::DuplicatedTraitName](./hello_world-sub_module-DuplicatedTraitName.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Enums

- [DuplicatedEnumName](./hello_world-DuplicatedEnumName.md)

- [sub_module::DuplicatedEnumName](./hello_world-sub_module-DuplicatedEnumName.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Free functions

- [main](./hello_world-main.md)

- [unique_function_name](./hello_world-unique_function_name.md)

- [duplicated_function_name](./hello_world-duplicated_function_name.md)

- [sub_module::duplicated_function_name](./hello_world-sub_module-duplicated_function_name.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DuplicatedEnumName

Fully qualified path: `hello_world::DuplicatedEnumName`

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# DuplicatedTraitName

Fully qualified path: `hello_world::DuplicatedTraitName`

```rust
trait DuplicatedTraitName
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# duplicated_function_name

Fully qualified path: `hello_world::duplicated_function_name`

```rust
fn duplicated_function_name()
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# main

Fully qualified path: `hello_world::main`

```rust
fn main()
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DuplicatedEnumName

Fully qualified path: `hello_world::sub_module::DuplicatedEnumName`

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# DuplicatedTraitName

Fully qualified path: `hello_world::sub_module::DuplicatedTraitName`

```rust
trait DuplicatedTraitName
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# duplicated_function_name

Fully qualified path: `hello_world::sub_module::duplicated_function_name`

```rust
fn duplicated_function_name()
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# sub_module

Fully qualified path: `hello_world::sub_module`

## Free functions

- [duplicated_function_name](./hello_world-sub_module-duplicated_function_name.md)

## Enums

- [DuplicatedEnumName](./hello_world-sub_module-DuplicatedEnumName.md)

## Traits

- [DuplicatedTraitName](./hello_world-sub_module-DuplicatedTraitName.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# unique_function_name

Fully qualified path: `hello_world::unique_function_name`

```rust
fn unique_function_name()
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# hello_world

Fully qualified path: `hello_world`

## Modules

- [sub_module](./hello_world-sub_module.md)

## Free functions

- [main](./hello_world-main.md)

- [unique_function_name](./hello_world-unique_function_name.md)

- [duplicated_function_name](./hello_world-duplicated_function_name.md)

## Enums

- [DuplicatedEnumName](./hello_world-DuplicatedEnumName.md)

## Traits

- [DuplicatedTraitName](./hello_world-DuplicatedTraitName.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Modules

- [hello_world](./hello_world.md)

- [sub_module](./hello_world-sub_module.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Traits

- [DuplicatedTraitName](./hello_world-DuplicatedTraitName.md)

- [sub_module::DuplicatedTraitName](./hello_world-sub_module-DuplicatedTraitName.md)

73 changes: 73 additions & 0 deletions extensions/scarb-doc/tests/duplicated_names.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use assert_fs::TempDir;
use indoc::indoc;
use scarb_test_support::command::Scarb;
use scarb_test_support::project_builder::ProjectBuilder;

pub mod markdown_target;
use markdown_target::MarkdownTargetChecker;

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

ProjectBuilder::start()
.name("hello_world")
.lib_cairo(indoc! {r#"
mod sub_module;
fn main() {
println!("hellow")
}
fn unique_function_name() {
// pass
}
fn duplicated_function_name() {
// pass
}
enum DuplicatedEnumName {
// pass
}
trait DuplicatedTraitName {
// pass
}
"#})
.src(
"src/sub_module.cairo",
indoc! {r#"
fn duplicated_function_name() {
// pass
}
enum DuplicatedEnumName {
// pass
}
trait DuplicatedTraitName {
// pass
}
"#},
)
.build(&root_dir);

Scarb::quick_snapbox()
.arg("doc")
.args(["--document-private-items"])
.current_dir(&root_dir)
.assert()
.success();

MarkdownTargetChecker::default()
.actual(
root_dir
.path()
.join("target/doc/hello_world")
.to_str()
.unwrap(),
)
.expected("tests/data/duplicated_item_names")
.assert_all_files_match();
}

0 comments on commit b23eaaa

Please sign in to comment.