Skip to content

Commit

Permalink
fix: add forc-doc impls for enums and fix sidebar (#6020)
Browse files Browse the repository at this point in the history
## Description

Closes #6018

Makes trait & inherent implementations show up for enums now: 

![image](https://github.com/FuelLabs/sway/assets/47993817/58308fb6-2807-44cd-aa4a-6f4ee314ceac)

And makes the sidebar include links to the impls:

![image](https://github.com/FuelLabs/sway/assets/47993817/55d9b17e-66dc-4f32-b1d8-325011eaef6f)


## Checklist

- [ ] I have linked to any relevant issues.
- [ ] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [ ] I have added tests that prove my fix is effective or that my
feature works.
- [ ] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [ ] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [ ] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: Joshua Batty <[email protected]>
  • Loading branch information
sdankel and JoshuaBatty authored May 19, 2024
1 parent d9985d8 commit f9a72da
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 60 deletions.
76 changes: 41 additions & 35 deletions forc-plugins/forc-doc/src/doc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,48 +79,54 @@ impl Documentation {
let mut impl_trait_vec: Vec<DocImplTrait> = Vec::new();
let mut inherent_impl_vec: Vec<DocImplTrait> = Vec::new();

match doc.item_body.ty_decl {
let decl_name = match doc.item_body.ty_decl {
TyDecl::StructDecl(ref decl) => {
for (impl_trait, module_info) in impl_traits.iter_mut() {
let struct_decl = engines.de().get_struct(&decl.decl_id);
let struct_name = struct_decl.name().as_str();

// Check if this implementation is for this struct.
if struct_name == impl_trait.implementing_for.span.as_str() {
let module_info_override = if let Some(decl_module_info) =
trait_decls.get(&impl_trait.trait_name.suffix)
{
Some(decl_module_info.module_prefixes.clone())
} else {
impl_trait.trait_name = impl_trait
.trait_name
.to_fullpath(engines, &typed_program.root.namespace);
None
};

if struct_name == impl_trait.trait_name.suffix.span().as_str() {
// If the trait name is the same as the struct name, it's an inherent implementation.
inherent_impl_vec.push(DocImplTrait {
impl_for_module: module_info.clone(),
impl_trait: impl_trait.clone(),
module_info_override: None,
});
} else {
// Otherwise, it's an implementation for a trait.
impl_trait_vec.push(DocImplTrait {
impl_for_module: module_info.clone(),
impl_trait: impl_trait.clone(),
module_info_override,
});
}
let struct_decl = engines.de().get_struct(&decl.decl_id);
Some(struct_decl.name().to_string())
}
TyDecl::EnumDecl(ref decl) => {
let enum_decl = engines.de().get_enum(&decl.decl_id);
Some(enum_decl.name().to_string())
}
_ => None,
};

if let Some(decl_name) = decl_name {
for (impl_trait, module_info) in impl_traits.iter_mut() {
// Check if this implementation is for this struct/enum.
if decl_name.as_str() == impl_trait.implementing_for.span.as_str() {
let module_info_override = if let Some(decl_module_info) =
trait_decls.get(&impl_trait.trait_name.suffix)
{
Some(decl_module_info.module_prefixes.clone())
} else {
impl_trait.trait_name = impl_trait
.trait_name
.to_fullpath(engines, &typed_program.root.namespace);
None
};

if decl_name.as_str() == impl_trait.trait_name.suffix.span().as_str() {
// If the trait name is the same as the declaration's name, it's an inherent implementation.
inherent_impl_vec.push(DocImplTrait {
impl_for_module: module_info.clone(),
impl_trait: impl_trait.clone(),
module_info_override: None,
});
} else {
// Otherwise, it's an implementation for a trait.
impl_trait_vec.push(DocImplTrait {
impl_for_module: module_info.clone(),
impl_trait: impl_trait.clone(),
module_info_override,
});
}
}
}
_ => continue,
}

if !impl_trait_vec.is_empty() {
doc.item_body.item_context.impl_traits = Some(impl_trait_vec.clone());
doc.item_body.item_context.impl_traits = Some(impl_trait_vec);
}

if !inherent_impl_vec.is_empty() {
Expand Down
56 changes: 46 additions & 10 deletions forc-plugins/forc-doc/src/render/item/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,42 @@ impl ItemContext {
}
}
}

if let Some(inherent_impls) = &self.inherent_impls {
let mut doc_links = Vec::new();
for inherent_impl in inherent_impls {
for item in &inherent_impl.impl_trait.items {
if let TyTraitItem::Fn(item_fn) = item {
let method_name = item_fn.name().to_string();
doc_links.push(DocLink {
name: method_name.clone(),
module_info: inherent_impl.impl_for_module.clone(),
html_filename: format!("{}method.{}", IDENTITY, method_name),
preview_opt: None,
})
}
}
}
links.insert(BlockTitle::ImplMethods, doc_links);
}

if let Some(impl_traits) = &self.impl_traits {
let doc_links = impl_traits
.iter()
.map(|impl_trait| DocLink {
name: impl_trait.impl_trait.trait_name.suffix.as_str().to_string(),
module_info: impl_trait.impl_for_module.clone(),
html_filename: format!(
"{}impl-{}",
IDENTITY,
impl_trait.impl_trait.trait_name.suffix.as_str()
),
preview_opt: None,
})
.collect();
links.insert(BlockTitle::ImplTraits, doc_links);
}

DocLinks {
style: DocStyle::Item {
title: None,
Expand Down Expand Up @@ -407,11 +443,11 @@ impl Renderable for ItemContext {
: Raw(context);
}
@ if !inherent_impls.is_empty() {
h2(id="inherent-implementations", class="small-section-header") {
h2(id="methods", class="small-section-header") {
: "Implementations";
a(href=format!("{IDENTITY}inherent-implementations"), class="anchor");
a(href=format!("{IDENTITY}methods"), class="anchor");
}
div(id="inherent-implementations-list") {
div(id="methods-list") {
@ for inherent_impl in inherent_impls {
: inherent_impl;
}
Expand Down Expand Up @@ -472,17 +508,17 @@ impl Renderable for DocImplTrait {
a(href=format!("{IDENTITY}impl-{}", trait_name.suffix.as_str()), class="anchor");
h3(class="code-header in-band") {
: "impl ";
@ if no_deps && is_external_item {
: trait_name.suffix.as_str();
} else {
a(class="trait", href=format!("{trait_link}")) {
@ if !is_inherent {
@ if no_deps && is_external_item {
: trait_name.suffix.as_str();
} else {
a(class="trait", href=format!("{trait_link}")) {
: trait_name.suffix.as_str();
}
}
}
@ if !is_inherent {
: " for ";
: implementing_for.span.as_str();
}
: implementing_for.span.as_str();
}
}
}
Expand Down
17 changes: 11 additions & 6 deletions forc-plugins/forc-doc/src/render/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,18 @@ impl Renderable for Sidebar {
}
_ => box_html! {
div(class="sidebar-elems") {
section {
div(class="block") {
ul {
@ for (title, _) in self.nav.links {
@ for (title, doc_links) in self.nav.links {
section {
h3 {
a(href=format!("{}{}", IDENTITY, title.html_title_string())) {
: title.as_str();
}
}
ul(class="block method") {
@ for doc_link in doc_links {
li {
a(href=format!("{}{}", IDENTITY, title.html_title_string())) {
: title.as_str();
a(href=format!("{}", doc_link.html_filename)) {
: doc_link.name;
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions forc-plugins/forc-doc/src/render/title.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ pub enum BlockTitle {
Fields,
Variants,
RequiredMethods,
ImplMethods,
ImplTraits,
}

impl BlockTitle {
pub fn as_str(&self) -> &str {
match self {
Expand All @@ -33,6 +36,8 @@ impl BlockTitle {
Self::Fields => "Fields",
Self::Variants => "Variants",
Self::RequiredMethods => "Required Methods",
Self::ImplMethods => "Methods",
Self::ImplTraits => "Trait Implementations",
}
}
pub fn item_title_str(&self) -> &str {
Expand All @@ -48,6 +53,8 @@ impl BlockTitle {
Self::Fields => "Fields",
Self::Variants => "Variants",
Self::RequiredMethods => "Required Methods",
Self::ImplMethods => "Methods",
Self::ImplTraits => "Trait Implementations",
}
}
pub fn class_title_str(&self) -> &str {
Expand Down
18 changes: 11 additions & 7 deletions forc-plugins/forc-doc/src/static.files/swaydoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@ a#all-types:active {
.block a,
h2.location a {
display: block;
padding: 0.25rem;
margin-left: 2em;
padding: 0.5rem;
margin-left: .25rem;
text-overflow: ellipsis;
overflow: hidden;
}
Expand All @@ -505,14 +505,18 @@ h2.location a {
.sidebar h3 {
font-size: 1.125rem;
font-weight: 500;
padding: 0;
padding: 1rem 1rem 0 0;
margin: 0;
}
.sidebar-elems .block {
margin-bottom: 2em;
.sidebar-elems,
.sidebar > .version,
.sidebar > h2 {
padding-left: 24px;
}
.sidebar-elems .block li a {
white-space: nowrap;
ul.block, .block li {
padding: 0;
margin: 0;
list-style: none;
}
.mobile-topbar {
display: none;
Expand Down
Loading

0 comments on commit f9a72da

Please sign in to comment.