From 81b943c21f10e9d9ae15c3674b68a3ca1c046e4d Mon Sep 17 00:00:00 2001 From: crowlkats Date: Sun, 28 Apr 2024 02:15:20 +0200 Subject: [PATCH] fix namespace handling (Closes #566) --- src/html/mod.rs | 35 ++++- src/html/pages.rs | 229 +++++++++++++-------------------- src/html/partition.rs | 114 +++++++++------- src/html/render_context.rs | 32 ++--- src/html/search.rs | 22 +--- src/html/sidepanels.rs | 20 +-- src/html/symbols/class.rs | 9 +- src/html/symbols/interface.rs | 7 +- src/html/symbols/mod.rs | 22 ++-- src/html/symbols/namespace.rs | 19 +-- src/html/symbols/type_alias.rs | 9 +- src/html/symbols/variable.rs | 9 +- src/html/util.rs | 29 ++--- 13 files changed, 251 insertions(+), 305 deletions(-) diff --git a/src/html/mod.rs b/src/html/mod.rs index a6aaaa5a..12ff379e 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -290,14 +290,23 @@ impl DocNodeWithContext { } } + pub fn create_namespace_child( + &self, + doc_node: Arc, + qualifiers: Rc>, + ) -> Self { + let mut child = self.create_child(doc_node); + child.ns_qualifiers = qualifiers; + child + } + pub fn create_child_method( &self, mut method_doc_node: DocNode, - parent_name: &str, is_static: bool, ) -> Self { method_doc_node.name = - qualify_drilldown_name(parent_name, &method_doc_node.name, is_static); + qualify_drilldown_name(self.get_name(), &method_doc_node.name, is_static); method_doc_node.declaration_kind = self.declaration_kind; let mut new_node = self.create_child(Arc::new(method_doc_node)); @@ -309,11 +318,13 @@ impl DocNodeWithContext { pub fn create_child_property( &self, mut property_doc_node: DocNode, - parent_name: &str, is_static: bool, ) -> Self { - property_doc_node.name = - qualify_drilldown_name(parent_name, &property_doc_node.name, is_static); + property_doc_node.name = qualify_drilldown_name( + self.get_name(), + &property_doc_node.name, + is_static, + ); property_doc_node.declaration_kind = self.declaration_kind; let mut new_node = self.create_child(Arc::new(property_doc_node)); @@ -321,6 +332,20 @@ impl DocNodeWithContext { new_node.kind_with_drilldown = DocNodeKindWithDrilldown::Property; new_node } + + pub fn get_qualified_name(&self) -> String { + if self.ns_qualifiers.is_empty() { + self.get_name().to_string() + } else { + format!("{}.{}", self.ns_qualifiers.join("."), self.get_name()) + } + } + + pub fn sub_qualifier(&self) -> Vec { + let mut ns_qualifiers = (*self.ns_qualifiers).clone(); + ns_qualifiers.push(self.get_name().to_string()); + ns_qualifiers + } } impl core::ops::Deref for DocNodeWithContext { diff --git a/src/html/pages.rs b/src/html/pages.rs index fefee665..a8c53c22 100644 --- a/src/html/pages.rs +++ b/src/html/pages.rs @@ -10,6 +10,7 @@ use super::RenderContext; use super::ShortPath; use super::SymbolGroupCtx; use super::UrlResolveKind; +use std::rc::Rc; use super::FUSE_FILENAME; use super::PAGE_STYLESHEET_FILENAME; @@ -81,7 +82,7 @@ impl IndexCtx { /// short_path is None in the case this is a root index page but there is no main entrypoint pub fn new( ctx: &GenerateCtx, - short_path: Option>, + short_path: Option>, partitions: Partition, ) -> Self { // will be default on index page with no main entrypoint @@ -214,14 +215,16 @@ pub enum SymbolPage { pub fn generate_symbol_pages_for_module( ctx: &GenerateCtx, short_path: &ShortPath, - partitions_for_nodes: &Partition, - doc_nodes: &[DocNodeWithContext], + sidepanel_partitions: &Partition, + module_doc_nodes: &[DocNodeWithContext], ) -> Vec { let mut name_partitions = - super::partition::partition_nodes_by_name(doc_nodes); + super::partition::partition_nodes_by_name(module_doc_nodes, true); let mut drilldown_partitions = IndexMap::new(); - for (name, doc_nodes) in &name_partitions { + for doc_nodes in name_partitions.values() { + let has_class = + doc_nodes.iter().any(|node| node.kind == DocNodeKind::Class); for doc_node in doc_nodes { match doc_node.kind { DocNodeKind::Class => { @@ -239,14 +242,14 @@ pub fn generate_symbol_pages_for_module( method.js_doc.clone(), method.function_def.clone(), ), - name, method.is_static, ) }) .collect::>(); - drilldown_partitions - .extend(super::partition::partition_nodes_by_name(&method_nodes)); + drilldown_partitions.extend( + super::partition::partition_nodes_by_name(&method_nodes, false), + ); let property_nodes = class .properties @@ -254,46 +257,55 @@ pub fn generate_symbol_pages_for_module( .map(|property| { doc_node.create_child_property( DocNode::from(property.clone()), - name, property.is_static, ) }) .collect::>(); - drilldown_partitions - .extend(super::partition::partition_nodes_by_name(&property_nodes)); + drilldown_partitions.extend( + super::partition::partition_nodes_by_name(&property_nodes, false), + ); } DocNodeKind::Interface => { let interface = doc_node.interface_def.as_ref().unwrap(); let method_nodes = interface .methods .iter() - .map(|method| { - doc_node.create_child_method( - DocNode::from(method.clone()), - name, - true, - ) + .filter_map(|method| { + if has_class && method.name == "prototype" { + None + } else { + Some( + doc_node + .create_child_method(DocNode::from(method.clone()), true), + ) + } }) .collect::>(); - drilldown_partitions - .extend(super::partition::partition_nodes_by_name(&method_nodes)); + drilldown_partitions.extend( + super::partition::partition_nodes_by_name(&method_nodes, false), + ); - let property_nodes = interface - .properties - .iter() - .map(|property| { - doc_node.create_child_property( - DocNode::from(property.clone()), - name, - true, - ) - }) - .collect::>(); + let property_nodes = + interface + .properties + .iter() + .filter_map(|property| { + if has_class && property.name == "prototype" { + None + } else { + Some(doc_node.create_child_property( + DocNode::from(property.clone()), + true, + )) + } + }) + .collect::>(); - drilldown_partitions - .extend(super::partition::partition_nodes_by_name(&property_nodes)); + drilldown_partitions.extend( + super::partition::partition_nodes_by_name(&property_nodes, false), + ); } DocNodeKind::TypeAlias => { let type_alias = doc_node.type_alias_def.as_ref().unwrap(); @@ -304,32 +316,39 @@ pub fn generate_symbol_pages_for_module( let method_nodes = ts_type_literal .methods .iter() - .map(|method| { - doc_node.create_child_method( - DocNode::from(method.clone()), - name, - true, - ) + .filter_map(|method| { + if has_class && method.name == "prototype" { + None + } else { + Some( + doc_node + .create_child_method(DocNode::from(method.clone()), true), + ) + } }) .collect::>(); - drilldown_partitions - .extend(super::partition::partition_nodes_by_name(&method_nodes)); + drilldown_partitions.extend( + super::partition::partition_nodes_by_name(&method_nodes, false), + ); let property_nodes = ts_type_literal .properties .iter() - .map(|property| { - doc_node.create_child_property( - DocNode::from(property.clone()), - name, - true, - ) + .filter_map(|property| { + if has_class && property.name == "prototype" { + None + } else { + Some(doc_node.create_child_property( + DocNode::from(property.clone()), + true, + )) + } }) .collect::>(); drilldown_partitions.extend( - super::partition::partition_nodes_by_name(&property_nodes), + super::partition::partition_nodes_by_name(&property_nodes, false), ); } } @@ -345,87 +364,43 @@ pub fn generate_symbol_pages_for_module( .methods .iter() .map(|method| { - doc_node.create_child_method( - DocNode::from(method.clone()), - name, - true, - ) + doc_node + .create_child_method(DocNode::from(method.clone()), true) }) .collect::>(); - drilldown_partitions - .extend(super::partition::partition_nodes_by_name(&method_nodes)); + drilldown_partitions.extend( + super::partition::partition_nodes_by_name(&method_nodes, false), + ); let property_nodes = ts_type_literal .properties .iter() .map(|property| { - doc_node.create_child_property( - DocNode::from(property.clone()), - name, - true, - ) + doc_node + .create_child_property(DocNode::from(property.clone()), true) }) .collect::>(); drilldown_partitions.extend( - super::partition::partition_nodes_by_name(&property_nodes), + super::partition::partition_nodes_by_name(&property_nodes, false), ); } } - DocNodeKind::Enum => {} - DocNodeKind::Function => {} - DocNodeKind::Import => {} - DocNodeKind::ModuleDoc => {} - DocNodeKind::Namespace => {} + _ => {} } } } name_partitions.extend(drilldown_partitions); - generate_symbol_pages_inner( - ctx, - doc_nodes, - partitions_for_nodes, - &name_partitions, - short_path, - vec![], - ) -} - -fn generate_symbol_pages_inner( - ctx: &GenerateCtx, - doc_nodes_for_module: &[DocNodeWithContext], - partitions_for_nodes: &Partition, - name_partitions: &Partition, - short_path: &ShortPath, - namespace_paths: Vec<&str>, -) -> Vec { - let mut generated_pages = - Vec::with_capacity(name_partitions.values().len() * 2); + let mut generated_pages = Vec::with_capacity(name_partitions.values().len()); for (name, doc_nodes) in name_partitions { - let namespaced_name = if namespace_paths.is_empty() { - name.to_owned() - } else { - format!("{}.{name}", namespace_paths.join(".")) - }; - - let sidepanel_ctx = SidepanelCtx::new( - ctx, - partitions_for_nodes, - short_path, - &namespaced_name, - ); + let sidepanel_ctx = + SidepanelCtx::new(ctx, sidepanel_partitions, short_path, &name); - let (breadcrumbs_ctx, symbol_group_ctx) = render_symbol_page( - ctx, - doc_nodes_for_module, - short_path, - &namespace_paths, - &namespaced_name, - doc_nodes, - ); + let (breadcrumbs_ctx, symbol_group_ctx) = + render_symbol_page(ctx, module_doc_nodes, short_path, &name, &doc_nodes); generated_pages.push(SymbolPage::Symbol { breadcrumbs_ctx, @@ -433,11 +408,11 @@ fn generate_symbol_pages_inner( symbol_group_ctx, }); - if let Some(_doc_node) = doc_nodes + if doc_nodes .iter() - .find(|doc_node| doc_node.kind == DocNodeKind::Class) + .any(|doc_node| doc_node.kind == DocNodeKind::Class) { - let prototype_name = format!("{namespaced_name}.prototype"); + let prototype_name = format!("{name}.prototype"); generated_pages.push(SymbolPage::Redirect { href: ctx.href_resolver.resolve_path( UrlResolveKind::Symbol { @@ -446,43 +421,12 @@ fn generate_symbol_pages_inner( }, UrlResolveKind::Symbol { file: short_path, - symbol: &namespaced_name, + symbol: &name, }, ), current_symbol: prototype_name, }); } - - if let Some(doc_node) = doc_nodes - .iter() - .find(|doc_node| doc_node.kind == DocNodeKind::Namespace) - { - let namespace = doc_node.namespace_def.as_ref().unwrap(); - - let namespace_name_partitions = super::partition::partition_nodes_by_name( - &namespace - .elements - .iter() - .map(|element| doc_node.create_child(element.clone())) - .collect::>(), - ); - - let namespace_paths = { - let mut ns_paths = namespace_paths.clone(); - ns_paths.push(name); - ns_paths - }; - - let generated = generate_symbol_pages_inner( - ctx, - doc_nodes_for_module, - partitions_for_nodes, - &namespace_name_partitions, - short_path, - namespace_paths, - ); - generated_pages.extend(generated); - } } generated_pages @@ -504,7 +448,6 @@ pub fn render_symbol_page( ctx: &GenerateCtx, doc_nodes_for_module: &[DocNodeWithContext], short_path: &ShortPath, - namespace_paths: &[&str], namespaced_name: &str, doc_nodes: &[DocNodeWithContext], ) -> (BreadcrumbsCtx, SymbolGroupCtx) { @@ -516,8 +459,8 @@ pub fn render_symbol_page( symbol: namespaced_name, }, ); - if !namespace_paths.is_empty() { - render_ctx = render_ctx.with_namespace(namespace_paths.to_vec()) + if !doc_nodes[0].ns_qualifiers.is_empty() { + render_ctx = render_ctx.with_namespace(doc_nodes[0].ns_qualifiers.clone()); } // NOTE: `doc_nodes` should be sorted at this point. diff --git a/src/html/partition.rs b/src/html/partition.rs index 16744b1b..68dea4b1 100644 --- a/src/html/partition.rs +++ b/src/html/partition.rs @@ -10,27 +10,56 @@ use std::rc::Rc; pub type Partition = IndexMap>; -pub fn partition_nodes_by_name(doc_nodes: &[DocNodeWithContext]) -> Partition { - let mut partitions = IndexMap::default(); +pub fn partition_nodes_by_name( + doc_nodes: &[DocNodeWithContext], + flatten_namespaces: bool, +) -> Partition { + fn partition_nodes_by_name_inner( + partitions: &mut Partition, + doc_nodes: &[DocNodeWithContext], + flatten_namespaces: bool, + ) { + for node in doc_nodes { + if matches!(node.kind, DocNodeKind::ModuleDoc | DocNodeKind::Import) + || node.declaration_kind == crate::node::DeclarationKind::Private + { + continue; + } - for node in doc_nodes { - if matches!(node.kind, DocNodeKind::ModuleDoc | DocNodeKind::Import) - || node.declaration_kind == crate::node::DeclarationKind::Private - { - continue; - } + if flatten_namespaces && node.kind == DocNodeKind::Namespace { + let namespace_def = node.namespace_def.as_ref().unwrap(); + let ns_qualifiers = Rc::new(node.sub_qualifier()); + + partition_nodes_by_name_inner( + partitions, + &namespace_def + .elements + .iter() + .map(|element| { + node + .create_namespace_child(element.clone(), ns_qualifiers.clone()) + }) + .collect::>(), + true, + ); + } - partitions - .entry(node.get_name().to_string()) - .or_insert(vec![]) - .push(node.clone()); + partitions + .entry(node.get_qualified_name()) + .or_default() + .push(node.clone()); + } } + let mut partitions = IndexMap::default(); + + partition_nodes_by_name_inner(&mut partitions, doc_nodes, flatten_namespaces); + for val in partitions.values_mut() { val.sort_by_key(|n| n.kind); } - partitions.sort_by(|k1, _v1, k2, _v2| k1.cmp(k2)); + partitions.sort_keys(); partitions } @@ -56,10 +85,7 @@ pub fn partition_nodes_by_kind( if flatten_namespaces && node.kind == DocNodeKind::Namespace { let namespace_def = node.namespace_def.as_ref().unwrap(); - let mut namespace = (*node.ns_qualifiers).clone(); - namespace.push(node.get_name().to_string()); - - let ns_qualifiers = Rc::new(namespace); + let ns_qualifiers = Rc::new(node.sub_qualifier()); partition_nodes_by_kind_inner( partitions, @@ -67,9 +93,8 @@ pub fn partition_nodes_by_kind( .elements .iter() .map(|element| { - let mut child = node.create_child(element.clone()); - child.ns_qualifiers = ns_qualifiers.clone(); - child + node + .create_namespace_child(element.clone(), ns_qualifiers.clone()) }) .collect::>(), true, @@ -79,7 +104,7 @@ pub fn partition_nodes_by_kind( if let Some((node_kind, nodes)) = partitions.iter_mut().find(|(kind, nodes)| { nodes.iter().any(|n| { - n.get_name() == node.get_name() + n.get_qualified_name() == node.get_qualified_name() && n.kind_with_drilldown != node.kind_with_drilldown && kind != &&node.kind_with_drilldown }) @@ -90,7 +115,10 @@ pub fn partition_nodes_by_kind( nodes.push(node.clone()); } else { let entry = partitions.entry(node.kind_with_drilldown).or_default(); - if !entry.iter().any(|n| n.get_name() == node.get_name()) { + if !entry + .iter() + .any(|n| n.get_qualified_name() == node.get_qualified_name()) + { entry.push(node.clone()); } } @@ -134,10 +162,7 @@ pub fn partition_nodes_by_category( if flatten_namespaces && node.kind == DocNodeKind::Namespace { let namespace_def = node.namespace_def.as_ref().unwrap(); - let mut namespace = (*node.ns_qualifiers).clone(); - namespace.push(node.get_name().to_string()); - - let ns_qualifiers = Rc::new(namespace); + let ns_qualifiers = Rc::new(node.sub_qualifier()); partition_nodes_by_category_inner( partitions, @@ -145,9 +170,8 @@ pub fn partition_nodes_by_category( .elements .iter() .map(|element| { - let mut child = node.create_child(element.clone()); - child.ns_qualifiers = ns_qualifiers.clone(); - child + node + .create_namespace_child(element.clone(), ns_qualifiers.clone()) }) .collect::>(), true, @@ -169,10 +193,10 @@ pub fn partition_nodes_by_category( let entry = partitions.entry(category).or_default(); - if !entry - .iter() - .any(|n| n.get_name() == node.get_name() && n.kind == node.kind) - { + if !entry.iter().any(|n| { + n.get_qualified_name() == node.get_qualified_name() + && n.kind == node.kind + }) { entry.push(node.clone()); } } @@ -225,10 +249,7 @@ pub fn partition_nodes_by_entrypoint( if flatten_namespaces && node.kind == DocNodeKind::Namespace { let namespace_def = node.namespace_def.as_ref().unwrap(); - let mut namespace = (*node.ns_qualifiers).clone(); - namespace.push(node.get_name().to_string()); - - let ns_qualifiers = Rc::new(namespace); + let ns_qualifiers = Rc::new(node.sub_qualifier()); partition_nodes_by_entrypoint_inner( partitions, @@ -236,9 +257,8 @@ pub fn partition_nodes_by_entrypoint( .elements .iter() .map(|element| { - let mut child = node.create_child(element.clone()); - child.ns_qualifiers = ns_qualifiers.clone(); - child + node + .create_namespace_child(element.clone(), ns_qualifiers.clone()) }) .collect::>(), true, @@ -247,10 +267,10 @@ pub fn partition_nodes_by_entrypoint( let entry = partitions.entry(node.origin.clone()).or_default(); - if !entry - .iter() - .any(|n| n.get_name() == node.get_name() && n.kind == node.kind) - { + if !entry.iter().any(|n| { + n.get_qualified_name() == node.get_qualified_name() + && n.kind == node.kind + }) { entry.push(node.clone()); } } @@ -292,11 +312,11 @@ fn compare_node( .cmp(&!node1_is_deprecated) .then_with(|| { node1 - .get_name() + .get_qualified_name() .to_ascii_lowercase() - .cmp(&node2.get_name().to_ascii_lowercase()) + .cmp(&node2.get_qualified_name().to_ascii_lowercase()) }) - .then_with(|| node1.get_name().cmp(node2.get_name())) + .then_with(|| node1.get_qualified_name().cmp(&node2.get_qualified_name())) .then_with(|| node1.kind.cmp(&node2.kind)) } diff --git a/src/html/render_context.rs b/src/html/render_context.rs index ed58938c..7baae57c 100644 --- a/src/html/render_context.rs +++ b/src/html/render_context.rs @@ -18,7 +18,7 @@ pub struct RenderContext<'ctx> { current_type_params: Rc>, current_resolve: UrlResolveKind<'ctx>, /// A vector of parts of the current namespace, eg. `vec!["Deno", "errors"]`. - namespace_parts: Rc>, + namespace_parts: Rc>, } impl<'ctx> RenderContext<'ctx> { @@ -47,9 +47,9 @@ impl<'ctx> RenderContext<'ctx> { } } - pub fn with_namespace(&self, namespace_parts: Vec<&'ctx str>) -> Self { + pub fn with_namespace(&self, namespace_parts: Rc>) -> Self { Self { - namespace_parts: Rc::new(namespace_parts), + namespace_parts, ..self.clone() } } @@ -58,10 +58,6 @@ impl<'ctx> RenderContext<'ctx> { self.current_type_params.contains(name) } - pub fn get_namespace_parts(&self) -> &[&str] { - &self.namespace_parts - } - pub fn get_current_resolve(&self) -> UrlResolveKind { self.current_resolve } @@ -73,11 +69,7 @@ impl<'ctx> RenderContext<'ctx> { .collect::>(); if !self.namespace_parts.is_empty() { - let mut parts = self - .namespace_parts - .iter() - .map(|part| part.to_string()) - .collect::>(); + let mut parts = (*self.namespace_parts).clone(); while !parts.is_empty() { let mut current_parts = parts.clone(); current_parts.extend_from_slice(&target_symbol_parts); @@ -106,15 +98,13 @@ impl<'ctx> RenderContext<'ctx> { .get_file() .cloned() .unwrap_or_else(|| { - Rc::unwrap_or_clone( - self - .ctx - .doc_nodes - .keys() - .find(|short_path| short_path.is_main) - .unwrap() - .clone(), - ) + (**self + .ctx + .doc_nodes + .keys() + .find(|short_path| short_path.is_main) + .unwrap()) + .clone() }), symbol: target_symbol, }, diff --git a/src/html/search.rs b/src/html/search.rs index 9ffe38bf..5eddadcb 100644 --- a/src/html/search.rs +++ b/src/html/search.rs @@ -23,27 +23,14 @@ struct SearchIndexNode { /// node is flattened into a list of its elements. fn doc_node_into_search_index_nodes( ctx: &GenerateCtx, - name: &str, doc_nodes: &[&DocNodeWithContext], ) -> Vec { let kinds = doc_nodes.iter().map(|node| node.kind).collect(); let deprecated = super::util::all_deprecated(doc_nodes); - let name = if doc_nodes - .first() - .expect("doc_nodes should not be empty") - .ns_qualifiers - .is_empty() - { - html_escape::encode_text(name).into_owned() - } else { - format!( - "{}.{}", - doc_nodes[0].ns_qualifiers.join("."), - html_escape::encode_text(name) - ) - }; + let name = + html_escape::encode_text(&doc_nodes[0].get_qualified_name()).to_string(); if doc_nodes[0].kind != DocNodeKind::Namespace { let mut location = doc_nodes[0].location.clone(); @@ -156,7 +143,6 @@ fn doc_node_into_search_index_nodes( if el_nodes[0].kind == DocNodeKind::Namespace { nodes.extend(doc_node_into_search_index_nodes( ctx, - el_nodes[0].get_name(), &[&DocNodeWithContext { origin: doc_nodes[0].origin.clone(), ns_qualifiers: Rc::new(ns_qualifiers_), @@ -189,8 +175,8 @@ pub fn generate_search_index(ctx: &GenerateCtx) -> serde_json::Value { } let mut doc_nodes = grouped_nodes - .iter() - .flat_map(|(name, node)| doc_node_into_search_index_nodes(ctx, name, node)) + .values() + .flat_map(|node| doc_node_into_search_index_nodes(ctx, node)) .collect::>(); doc_nodes.sort_by(|a, b| a.file.cmp(&b.file)); diff --git a/src/html/sidepanels.rs b/src/html/sidepanels.rs index a4a05a21..da92e879 100644 --- a/src/html/sidepanels.rs +++ b/src/html/sidepanels.rs @@ -63,13 +63,9 @@ impl SidepanelCtx { let mut grouped_nodes = IndexMap::new(); for node in nodes { - let name = if !node.ns_qualifiers.is_empty() { - format!("{}.{}", node.ns_qualifiers.join("."), node.get_name()) - } else { - node.get_name().to_string() - }; - - let entry = grouped_nodes.entry(name).or_insert(vec![]); + let entry = grouped_nodes + .entry(node.get_qualified_name()) + .or_insert(vec![]); entry.push(node); } @@ -156,13 +152,9 @@ impl IndexSidepanelCtx { let mut grouped_nodes = IndexMap::new(); for node in &nodes { - let name = if !node.ns_qualifiers.is_empty() { - format!("{}.{}", node.ns_qualifiers.join("."), node.get_name()) - } else { - node.get_name().to_string() - }; - - let entry = grouped_nodes.entry(name).or_insert(vec![]); + let entry = grouped_nodes + .entry(node.get_qualified_name()) + .or_insert(vec![]); entry.push(node); } diff --git a/src/html/symbols/class.rs b/src/html/symbols/class.rs index 313e12ca..298551ed 100644 --- a/src/html/symbols/class.rs +++ b/src/html/symbols/class.rs @@ -16,6 +16,7 @@ use std::collections::HashSet; pub(crate) fn render_class( ctx: &RenderContext, doc_node: &DocNodeWithContext, + name: &str, ) -> Vec { let class_def = doc_node.class_def.as_ref().unwrap(); @@ -60,7 +61,7 @@ pub(crate) fn render_class( "Properties", SectionContentCtx::DocEntry(render_class_properties( ctx, - doc_node.get_name(), + name, class_items.properties, )), )); @@ -71,7 +72,7 @@ pub(crate) fn render_class( "Methods", SectionContentCtx::DocEntry(render_class_methods( ctx, - doc_node.get_name(), + name, class_items.methods, )), )); @@ -82,7 +83,7 @@ pub(crate) fn render_class( "Static Properties", SectionContentCtx::DocEntry(render_class_properties( ctx, - doc_node.get_name(), + name, class_items.static_properties, )), )); @@ -93,7 +94,7 @@ pub(crate) fn render_class( "Static Methods", SectionContentCtx::DocEntry(render_class_methods( ctx, - doc_node.get_name(), + name, class_items.static_methods, )), )); diff --git a/src/html/symbols/interface.rs b/src/html/symbols/interface.rs index cb09d1d4..2ae0a898 100644 --- a/src/html/symbols/interface.rs +++ b/src/html/symbols/interface.rs @@ -9,6 +9,7 @@ use crate::html::DocNodeWithContext; pub(crate) fn render_interface( ctx: &RenderContext, doc_node: &DocNodeWithContext, + name: &str, ) -> Vec { let interface_def = doc_node.interface_def.as_ref().unwrap(); @@ -43,14 +44,12 @@ pub(crate) fn render_interface( } if let Some(properties) = - render_properties(ctx, doc_node.get_name(), &interface_def.properties) + render_properties(ctx, name, &interface_def.properties) { sections.push(properties); } - if let Some(methods) = - render_methods(ctx, doc_node.get_name(), &interface_def.methods) - { + if let Some(methods) = render_methods(ctx, name, &interface_def.methods) { sections.push(methods); } diff --git a/src/html/symbols/mod.rs b/src/html/symbols/mod.rs index 8cdd34af..9682f7bd 100644 --- a/src/html/symbols/mod.rs +++ b/src/html/symbols/mod.rs @@ -276,27 +276,33 @@ impl SymbolInnerCtx { continue; } - DocNodeKind::Variable => variable::render_variable(ctx, doc_node), - DocNodeKind::Class => class::render_class(ctx, doc_node), + DocNodeKind::Variable => variable::render_variable(ctx, doc_node, name), + DocNodeKind::Class => class::render_class(ctx, doc_node, name), DocNodeKind::Enum => r#enum::render_enum(ctx, doc_node), - DocNodeKind::Interface => interface::render_interface(ctx, doc_node), - DocNodeKind::TypeAlias => type_alias::render_type_alias(ctx, doc_node), + DocNodeKind::Interface => { + interface::render_interface(ctx, doc_node, name) + } + DocNodeKind::TypeAlias => { + type_alias::render_type_alias(ctx, doc_node, name) + } DocNodeKind::Namespace => { let namespace_def = doc_node.namespace_def.as_ref().unwrap(); + let ns_qualifiers = std::rc::Rc::new(doc_node.sub_qualifier()); let namespace_nodes = namespace_def .elements .iter() - .map(|element| doc_node.create_child(element.clone())) + .map(|element| { + doc_node + .create_namespace_child(element.clone(), ns_qualifiers.clone()) + }) .collect::>(); let partitions = super::partition::partition_nodes_by_kind(&namespace_nodes, false); - let ns_parts = name.split('.').collect::>(); - namespace::render_namespace( - &ctx.with_namespace(ns_parts), + &ctx.with_namespace(ns_qualifiers), partitions .into_iter() .map(|(title, nodes)| { diff --git a/src/html/symbols/namespace.rs b/src/html/symbols/namespace.rs index 36abdd57..937347ae 100644 --- a/src/html/symbols/namespace.rs +++ b/src/html/symbols/namespace.rs @@ -26,11 +26,7 @@ fn get_namespace_section_render_ctx( for node in doc_nodes { let entry = grouped_nodes - .entry(if !node.ns_qualifiers.is_empty() { - format!("{}.{}", node.ns_qualifiers.join("."), node.get_name()) - } else { - node.get_name().to_string() - }) + .entry(node.get_qualified_name()) .or_insert(vec![]); entry.push(node); } @@ -60,18 +56,9 @@ pub struct NamespaceNodeCtx { impl NamespaceNodeCtx { fn new( ctx: &RenderContext, - mut name: String, + name: String, nodes: Vec, ) -> Self { - // TODO: linking - - let ns_parts = ctx.get_namespace_parts(); - if !ns_parts.is_empty() { - name = format!("{}.{}", ns_parts.join("."), name); - } - - let current_resolve = ctx.get_current_resolve(); - let docs = crate::html::jsdoc::jsdoc_body_to_html(ctx, &nodes[0].js_doc, true); @@ -89,7 +76,7 @@ impl NamespaceNodeCtx { Some(nodes[0].origin.display_name()) }, href: ctx.ctx.href_resolver.resolve_path( - current_resolve, + ctx.get_current_resolve(), UrlResolveKind::Symbol { file: &nodes[0].origin, symbol: &name, diff --git a/src/html/symbols/type_alias.rs b/src/html/symbols/type_alias.rs index 56133a5e..b10deee0 100644 --- a/src/html/symbols/type_alias.rs +++ b/src/html/symbols/type_alias.rs @@ -11,6 +11,7 @@ use std::collections::HashSet; pub(crate) fn render_type_alias( ctx: &RenderContext, doc_node: &DocNodeWithContext, + name: &str, ) -> Vec { let type_alias_def = doc_node.type_alias_def.as_ref().unwrap(); @@ -21,7 +22,7 @@ pub(crate) fn render_type_alias( .collect::>(); let ctx = &ctx.with_current_type_params(current_type_params); - let id = name_to_id("typeAlias", doc_node.get_name()); + let id = name_to_id("typeAlias", name); // TODO: tags @@ -50,14 +51,12 @@ pub(crate) fn render_type_alias( } if let Some(properties) = - render_properties(ctx, doc_node.get_name(), &ts_type_literal.properties) + render_properties(ctx, name, &ts_type_literal.properties) { sections.push(properties); } - if let Some(methods) = - render_methods(ctx, doc_node.get_name(), &ts_type_literal.methods) - { + if let Some(methods) = render_methods(ctx, name, &ts_type_literal.methods) { sections.push(methods); } } else { diff --git a/src/html/symbols/variable.rs b/src/html/symbols/variable.rs index ddc5e135..eaf2a4ea 100644 --- a/src/html/symbols/variable.rs +++ b/src/html/symbols/variable.rs @@ -11,6 +11,7 @@ use std::collections::HashSet; pub(crate) fn render_variable( ctx: &RenderContext, doc_node: &DocNodeWithContext, + name: &str, ) -> Vec { let variable_def = doc_node.variable_def.as_ref().unwrap(); @@ -18,7 +19,7 @@ pub(crate) fn render_variable( return vec![]; }; - let id = name_to_id("variable", doc_node.get_name()); + let id = name_to_id("variable", &doc_node.get_qualified_name()); let mut sections = vec![]; @@ -36,14 +37,12 @@ pub(crate) fn render_variable( } if let Some(properties) = - render_properties(ctx, doc_node.get_name(), &ts_type_literal.properties) + render_properties(ctx, name, &ts_type_literal.properties) { sections.push(properties); } - if let Some(methods) = - render_methods(ctx, doc_node.get_name(), &ts_type_literal.methods) - { + if let Some(methods) = render_methods(ctx, name, &ts_type_literal.methods) { sections.push(methods); } } else { diff --git a/src/html/util.rs b/src/html/util.rs index 4ff3a37e..d258f2d9 100644 --- a/src/html/util.rs +++ b/src/html/util.rs @@ -36,7 +36,7 @@ pub(crate) struct NamespacedSymbols(Rc>>); impl NamespacedSymbols { pub(crate) fn new(doc_nodes: &[DocNodeWithContext]) -> Self { - let symbols = compute_namespaced_symbols(doc_nodes.to_vec(), &[]); + let symbols = compute_namespaced_symbols(doc_nodes.to_vec()); Self(Rc::new(symbols)) } @@ -47,7 +47,6 @@ impl NamespacedSymbols { pub fn compute_namespaced_symbols( doc_nodes: Vec, - current_path: &[String], ) -> HashSet> { let mut namespaced_symbols = HashSet::new(); @@ -59,15 +58,14 @@ pub fn compute_namespaced_symbols( } // TODO: handle export aliasing - let mut name_path = current_path.to_vec(); - name_path.push(doc_node.get_name().to_string()); + let name_path = Rc::new(doc_node.sub_qualifier()); match doc_node.kind { DocNodeKind::Class => { let class_def = doc_node.class_def.as_ref().unwrap(); namespaced_symbols.extend(class_def.methods.iter().map(|method| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name( doc_node.get_name(), @@ -82,7 +80,7 @@ pub fn compute_namespaced_symbols( namespaced_symbols.extend(class_def.properties.iter().map( |property| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name( doc_node.get_name(), @@ -100,7 +98,7 @@ pub fn compute_namespaced_symbols( let interface_def = doc_node.interface_def.as_ref().unwrap(); namespaced_symbols.extend(interface_def.methods.iter().map(|method| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name(doc_node.get_name(), &method.name, true) .split('.') @@ -111,7 +109,7 @@ pub fn compute_namespaced_symbols( namespaced_symbols.extend(interface_def.properties.iter().map( |property| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name(doc_node.get_name(), &property.name, true) .split('.') @@ -128,7 +126,7 @@ pub fn compute_namespaced_symbols( { namespaced_symbols.extend(type_literal.methods.iter().map( |method| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name(doc_node.get_name(), &method.name, true) .split('.') @@ -140,7 +138,7 @@ pub fn compute_namespaced_symbols( namespaced_symbols.extend(type_literal.properties.iter().map( |property| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name( doc_node.get_name(), @@ -165,7 +163,7 @@ pub fn compute_namespaced_symbols( { namespaced_symbols.extend(type_literal.methods.iter().map( |method| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name(doc_node.get_name(), &method.name, true) .split('.') @@ -177,7 +175,7 @@ pub fn compute_namespaced_symbols( namespaced_symbols.extend(type_literal.properties.iter().map( |property| { - let mut method_path = current_path.to_vec(); + let mut method_path = (*doc_node.ns_qualifiers).clone(); method_path.extend( qualify_drilldown_name( doc_node.get_name(), @@ -195,7 +193,7 @@ pub fn compute_namespaced_symbols( _ => {} } - namespaced_symbols.insert(name_path.clone()); + namespaced_symbols.insert((*name_path).clone()); if doc_node.kind == DocNodeKind::Namespace { let namespace_def = doc_node.namespace_def.as_ref().unwrap(); @@ -203,9 +201,10 @@ pub fn compute_namespaced_symbols( namespace_def .elements .iter() - .map(|element| doc_node.create_child(element.clone())) + .map(|element| { + doc_node.create_namespace_child(element.clone(), name_path.clone()) + }) .collect(), - &name_path, )) } }