1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

#![recursion_limit = "256"]
#![deny(clippy::disallowed_methods)]
#![deny(clippy::disallowed_types)]
#![deny(clippy::print_stderr)]
#![deny(clippy::print_stdout)]

#[macro_use]
extern crate cfg_if;
#[macro_use]
extern crate lazy_static;
#[cfg(test)]
#[macro_use]
extern crate serde_json;

pub mod class;
mod colors;
mod decorators;
mod diagnostics;
mod display;
pub mod r#enum;
pub mod function;
pub mod interface;
pub mod js_doc;
pub mod node;
mod params;
mod parser;
mod ts_type;
mod ts_type_param;
pub mod type_alias;
mod util;
pub mod variable;
mod visibility;

pub use node::DocNode;
pub use node::DocNodeKind;
pub use node::Location;

use node::ImportDef;
use node::ReexportKind;
use params::ParamDef;

cfg_if! {
  if #[cfg(feature = "rust")] {
    mod printer;
    pub use diagnostics::DocDiagnostic;
    pub use diagnostics::DocDiagnosticKind;
    pub use printer::DocPrinter;
  }
}

pub use parser::DocError;
pub use parser::DocParser;
pub use parser::DocParserOptions;

cfg_if! {
  if #[cfg(feature = "html")] {
    pub mod html;
  }
}

#[cfg(test)]
mod tests;

#[cfg(feature = "rust")]
pub fn find_nodes_by_name_recursively(
  doc_nodes: Vec<DocNode>,
  name: String,
) -> Vec<DocNode> {
  let mut parts = name.splitn(2, '.');
  let name = parts.next();
  let leftover = parts.next();
  if name.is_none() {
    return doc_nodes;
  }

  let name = name.unwrap();
  let doc_nodes = find_nodes_by_name(doc_nodes, name.to_string());

  let mut found: Vec<DocNode> = vec![];
  match leftover {
    Some(leftover) => {
      for node in doc_nodes {
        let children = get_children_of_node(node);
        found.extend(find_nodes_by_name_recursively(
          children,
          leftover.to_string(),
        ));
      }
      found
    }
    None => doc_nodes,
  }
}

#[cfg(feature = "rust")]
fn find_nodes_by_name(doc_nodes: Vec<DocNode>, name: String) -> Vec<DocNode> {
  let mut found: Vec<DocNode> = vec![];
  for node in doc_nodes {
    if node.name == name {
      found.push(node);
    }
  }
  found
}

#[cfg(feature = "rust")]
fn get_children_of_node(node: DocNode) -> Vec<DocNode> {
  match node.kind {
    DocNodeKind::Namespace => {
      let namespace_def = node.namespace_def.unwrap();
      namespace_def
        .elements
        .into_iter()
        .map(std::sync::Arc::unwrap_or_clone)
        .collect()
    }
    DocNodeKind::Interface => {
      let interface_def = node.interface_def.unwrap();
      let mut doc_nodes: Vec<DocNode> = vec![];
      for method in interface_def.methods {
        doc_nodes.push(method.into());
      }
      for property in interface_def.properties {
        doc_nodes.push(property.into());
      }
      doc_nodes
    }
    DocNodeKind::Class => {
      let class_def = node.class_def.unwrap();
      let mut doc_nodes: Vec<DocNode> = vec![];
      for method in class_def.methods {
        doc_nodes.push(method.into());
      }
      for property in class_def.properties {
        doc_nodes.push(property.into());
      }
      doc_nodes
    }
    _ => vec![],
  }
}