summaryrefslogtreecommitdiff
path: root/cli/doc/printer.rs
diff options
context:
space:
mode:
authorValentin Anger <syrupthinker@gryphno.de>2020-07-12 14:16:33 +0200
committerGitHub <noreply@github.com>2020-07-12 14:16:33 +0200
commit3374c73fba3a96df22d0c04e6c17078ca8cce45b (patch)
tree91d996554a2e276724a86ecb3bff19ea5411238b /cli/doc/printer.rs
parent871f9255e37b4d2e63439c84da8e9bed6b388034 (diff)
feat(doc): Improve terminal printer (#6594)
- Add more support for generics - Add the --private flag - displays documentation for not exported and private nodes - Display more attributes like abstract, static and readonly - Display type aliases - Refactor module to use the Display trait - Use a bit more color
Diffstat (limited to 'cli/doc/printer.rs')
-rw-r--r--cli/doc/printer.rs861
1 files changed, 392 insertions, 469 deletions
diff --git a/cli/doc/printer.rs b/cli/doc/printer.rs
index b563a6adc..2e55c752a 100644
--- a/cli/doc/printer.rs
+++ b/cli/doc/printer.rs
@@ -12,540 +12,463 @@
use crate::colors;
use crate::doc;
-use crate::doc::ts_type::TsTypeDefKind;
+use crate::doc::display::{
+ display_abstract, display_async, display_generator, Indent, SliceDisplayer,
+};
use crate::doc::DocNodeKind;
use crate::swc_ecma_ast;
+use std::fmt::{Display, Formatter, Result as FmtResult};
-pub fn format(doc_nodes: Vec<doc::DocNode>) -> String {
- format_(doc_nodes, 0)
+pub struct DocPrinter<'a> {
+ doc_nodes: &'a [doc::DocNode],
+ details: bool,
+ private: bool,
}
-pub fn format_details(node: doc::DocNode) -> String {
- let mut details = String::new();
+impl<'a> DocPrinter<'a> {
+ pub fn new(
+ doc_nodes: &[doc::DocNode],
+ details: bool,
+ private: bool,
+ ) -> DocPrinter {
+ DocPrinter {
+ doc_nodes,
+ details,
+ private,
+ }
+ }
- details.push_str(&format!(
- "{}",
- colors::gray(&format!(
- "Defined in {}:{}:{} \n\n",
- node.location.filename, node.location.line, node.location.col
- ))
- ));
+ pub fn format(&self, w: &mut Formatter<'_>) -> FmtResult {
+ if self.details {
+ self.format_details(w, self.doc_nodes, 0)
+ } else {
+ self.format_summary(w, self.doc_nodes, 0)
+ }
+ }
- details.push_str(&format_signature(&node, 0));
+ fn format_summary(
+ &self,
+ w: &mut Formatter<'_>,
+ doc_nodes: &[doc::DocNode],
+ indent: i64,
+ ) -> FmtResult {
+ let mut sorted = Vec::from(doc_nodes);
+ sorted.sort_unstable_by(|a, b| {
+ let kind_cmp = self.kind_order(&a.kind).cmp(&self.kind_order(&b.kind));
+ if kind_cmp == core::cmp::Ordering::Equal {
+ a.name.cmp(&b.name)
+ } else {
+ kind_cmp
+ }
+ });
- let js_doc = node.js_doc.clone();
- if let Some(js_doc) = js_doc {
- details.push_str(&format_jsdoc(js_doc, 1));
- }
- details.push_str("\n");
+ for node in sorted {
+ self.format_signature(w, &node, indent)?;
- let maybe_extra = match node.kind {
- DocNodeKind::Class => Some(format_class_details(node)),
- DocNodeKind::Enum => Some(format_enum_details(node)),
- DocNodeKind::Namespace => Some(format_namespace_details(node)),
- _ => None,
- };
+ if let Some(js_doc) = &node.js_doc {
+ self.format_jsdoc(w, js_doc, indent + 1, self.details)?;
+ }
- if let Some(extra) = maybe_extra {
- details.push_str(&extra);
- }
+ writeln!(w)?;
- details
-}
+ if DocNodeKind::Namespace == node.kind {
+ self.format_summary(
+ w,
+ &node.namespace_def.as_ref().unwrap().elements,
+ indent + 1,
+ )?;
-fn kind_order(kind: &doc::DocNodeKind) -> i64 {
- match kind {
- DocNodeKind::Function => 0,
- DocNodeKind::Variable => 1,
- DocNodeKind::Class => 2,
- DocNodeKind::Enum => 3,
- DocNodeKind::Interface => 4,
- DocNodeKind::TypeAlias => 5,
- DocNodeKind::Namespace => 6,
- }
-}
+ writeln!(w)?;
+ };
+ }
-fn format_signature(node: &doc::DocNode, indent: i64) -> String {
- match node.kind {
- DocNodeKind::Function => format_function_signature(&node, indent),
- DocNodeKind::Variable => format_variable_signature(&node, indent),
- DocNodeKind::Class => format_class_signature(&node, indent),
- DocNodeKind::Enum => format_enum_signature(&node, indent),
- DocNodeKind::Interface => format_interface_signature(&node, indent),
- DocNodeKind::TypeAlias => format_type_alias_signature(&node, indent),
- DocNodeKind::Namespace => format_namespace_signature(&node, indent),
+ Ok(())
}
-}
-fn format_(doc_nodes: Vec<doc::DocNode>, indent: i64) -> String {
- let mut sorted = doc_nodes;
- sorted.sort_unstable_by(|a, b| {
- let kind_cmp = kind_order(&a.kind).cmp(&kind_order(&b.kind));
- if kind_cmp == core::cmp::Ordering::Equal {
- a.name.cmp(&b.name)
- } else {
- kind_cmp
+ fn format_details(
+ &self,
+ w: &mut Formatter<'_>,
+ doc_nodes: &[doc::DocNode],
+ indent: i64,
+ ) -> FmtResult {
+ for node in doc_nodes {
+ write!(
+ w,
+ "{}",
+ colors::italic_gray(&format!(
+ "Defined in {}:{}:{} \n\n",
+ node.location.filename, node.location.line, node.location.col
+ ))
+ )?;
+
+ self.format_signature(w, &node, indent)?;
+
+ let js_doc = &node.js_doc;
+ if let Some(js_doc) = js_doc {
+ self.format_jsdoc(w, js_doc, indent + 1, self.details)?;
+ }
+ writeln!(w)?;
+
+ match node.kind {
+ DocNodeKind::Class => self.format_class_details(w, node)?,
+ DocNodeKind::Enum => self.format_enum_details(w, node)?,
+ DocNodeKind::Interface => self.format_interface_details(w, node)?,
+ DocNodeKind::Namespace => self.format_namespace_details(w, node)?,
+ _ => {}
+ }
}
- });
- let mut output = String::new();
+ Ok(())
+ }
- for node in sorted {
- output.push_str(&format_signature(&node, indent));
- if let Some(js_doc) = node.js_doc {
- output.push_str(&format_jsdoc(js_doc, indent));
+ fn kind_order(&self, kind: &doc::DocNodeKind) -> i64 {
+ match kind {
+ DocNodeKind::Function => 0,
+ DocNodeKind::Variable => 1,
+ DocNodeKind::Class => 2,
+ DocNodeKind::Enum => 3,
+ DocNodeKind::Interface => 4,
+ DocNodeKind::TypeAlias => 5,
+ DocNodeKind::Namespace => 6,
}
- output.push_str("\n");
- if DocNodeKind::Namespace == node.kind {
- output.push_str(&format_(
- node.namespace_def.as_ref().unwrap().elements.clone(),
- indent + 1,
- ));
- output.push_str("\n");
- };
}
- output
-}
-
-fn render_params(params: Vec<doc::ParamDef>) -> String {
- let mut rendered = String::from("");
- if !params.is_empty() {
- for param in params {
- rendered += param.name.as_str();
- if param.optional {
- rendered += "?";
+ fn format_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ match node.kind {
+ DocNodeKind::Function => self.format_function_signature(w, node, indent),
+ DocNodeKind::Variable => self.format_variable_signature(w, node, indent),
+ DocNodeKind::Class => self.format_class_signature(w, node, indent),
+ DocNodeKind::Enum => self.format_enum_signature(w, node, indent),
+ DocNodeKind::Interface => {
+ self.format_interface_signature(w, node, indent)
+ }
+ DocNodeKind::TypeAlias => {
+ self.format_type_alias_signature(w, node, indent)
}
- if let Some(ts_type) = param.ts_type {
- rendered += ": ";
- rendered += render_ts_type(ts_type).as_str();
+ DocNodeKind::Namespace => {
+ self.format_namespace_signature(w, node, indent)
}
- rendered += ", ";
}
- rendered.truncate(rendered.len() - 2);
}
- rendered
-}
-fn render_ts_type(ts_type: doc::ts_type::TsTypeDef) -> String {
- if ts_type.kind.is_none() {
- return "<UNIMPLEMENTED>".to_string();
- }
- let kind = ts_type.kind.unwrap();
- match kind {
- TsTypeDefKind::Array => {
- format!("{}[]", render_ts_type(*ts_type.array.unwrap()))
- }
- TsTypeDefKind::Conditional => {
- let conditional = ts_type.conditional_type.unwrap();
- format!(
- "{} extends {} ? {} : {}",
- render_ts_type(*conditional.check_type),
- render_ts_type(*conditional.extends_type),
- render_ts_type(*conditional.true_type),
- render_ts_type(*conditional.false_type)
- )
- }
- TsTypeDefKind::FnOrConstructor => {
- let fn_or_constructor = ts_type.fn_or_constructor.unwrap();
- format!(
- "{}({}) => {}",
- if fn_or_constructor.constructor {
- "new "
- } else {
- ""
- },
- render_params(fn_or_constructor.params),
- render_ts_type(fn_or_constructor.ts_type),
- )
- }
- TsTypeDefKind::IndexedAccess => {
- let indexed_access = ts_type.indexed_access.unwrap();
- format!(
- "{}[{}]",
- render_ts_type(*indexed_access.obj_type),
- render_ts_type(*indexed_access.index_type)
- )
+ // TODO(SyrupThinker) this should use a JSDoc parser
+ fn format_jsdoc(
+ &self,
+ w: &mut Formatter<'_>,
+ jsdoc: &str,
+ indent: i64,
+ details: bool,
+ ) -> FmtResult {
+ for line in jsdoc.lines() {
+ // Only show the first paragraph when summarising
+ // This should use the @summary JSDoc tag instead
+ if !details && line.is_empty() {
+ break;
+ }
+
+ writeln!(w, "{}{}", Indent(indent), colors::gray(&line))?;
}
- TsTypeDefKind::Intersection => {
- let intersection = ts_type.intersection.unwrap();
- let mut output = "".to_string();
- if !intersection.is_empty() {
- for ts_type in intersection {
- output += render_ts_type(ts_type).as_str();
- output += " & "
- }
- output.truncate(output.len() - 3);
+
+ Ok(())
+ }
+
+ fn format_class_details(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ ) -> FmtResult {
+ let class_def = node.class_def.as_ref().unwrap();
+ for node in &class_def.constructors {
+ writeln!(w, "{}{}", Indent(1), node,)?;
+ if let Some(js_doc) = &node.js_doc {
+ self.format_jsdoc(w, &js_doc, 2, self.details)?;
}
- output
}
- TsTypeDefKind::Keyword => ts_type.keyword.unwrap(),
- TsTypeDefKind::Literal => {
- let literal = ts_type.literal.unwrap();
- match literal.kind {
- doc::ts_type::LiteralDefKind::Boolean => {
- format!("{}", literal.boolean.unwrap())
- }
- doc::ts_type::LiteralDefKind::String => {
- "\"".to_string() + literal.string.unwrap().as_str() + "\""
- }
- doc::ts_type::LiteralDefKind::Number => {
- format!("{}", literal.number.unwrap())
- }
+ for node in class_def.properties.iter().filter(|node| {
+ self.private
+ || node
+ .accessibility
+ .unwrap_or(swc_ecma_ast::Accessibility::Public)
+ != swc_ecma_ast::Accessibility::Private
+ }) {
+ writeln!(w, "{}{}", Indent(1), node,)?;
+ if let Some(js_doc) = &node.js_doc {
+ self.format_jsdoc(w, &js_doc, 2, self.details)?;
}
}
- TsTypeDefKind::Optional => {
- format!("{}?", render_ts_type(*ts_type.optional.unwrap()))
+ for index_sign_def in &class_def.index_signatures {
+ writeln!(w, "{}{}", Indent(1), index_sign_def)?;
}
- TsTypeDefKind::Parenthesized => {
- format!("({})", render_ts_type(*ts_type.parenthesized.unwrap()))
+ for node in class_def.methods.iter().filter(|node| {
+ self.private
+ || node
+ .accessibility
+ .unwrap_or(swc_ecma_ast::Accessibility::Public)
+ != swc_ecma_ast::Accessibility::Private
+ }) {
+ writeln!(w, "{}{}", Indent(1), node,)?;
+ if let Some(js_doc) = &node.js_doc {
+ self.format_jsdoc(w, js_doc, 2, self.details)?;
+ }
}
- TsTypeDefKind::Rest => {
- format!("...{}", render_ts_type(*ts_type.rest.unwrap()))
+ writeln!(w)
+ }
+
+ fn format_enum_details(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ ) -> FmtResult {
+ let enum_def = node.enum_def.as_ref().unwrap();
+ for member in &enum_def.members {
+ writeln!(w, "{}{}", Indent(1), colors::bold(&member.name))?;
}
- TsTypeDefKind::This => "this".to_string(),
- TsTypeDefKind::Tuple => {
- let tuple = ts_type.tuple.unwrap();
- let mut output = "[".to_string();
- if !tuple.is_empty() {
- for ts_type in tuple {
- output += render_ts_type(ts_type).as_str();
- output += ", "
- }
- output.truncate(output.len() - 2);
+ writeln!(w)
+ }
+
+ fn format_interface_details(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ ) -> FmtResult {
+ let interface_def = node.interface_def.as_ref().unwrap();
+
+ for property_def in &interface_def.properties {
+ writeln!(w, "{}{}", Indent(1), property_def)?;
+ if let Some(js_doc) = &property_def.js_doc {
+ self.format_jsdoc(w, js_doc, 2, self.details)?;
}
- output += "]";
- output
}
- TsTypeDefKind::TypeLiteral => {
- let mut output = "".to_string();
- let type_literal = ts_type.type_literal.unwrap();
- for node in type_literal.call_signatures {
- output += format!(
- "({}){}, ",
- render_params(node.params),
- if let Some(ts_type) = node.ts_type {
- format!(": {}", render_ts_type(ts_type))
- } else {
- "".to_string()
- }
- )
- .as_str()
- }
- for node in type_literal.methods {
- output += format!(
- "{}({}){}, ",
- node.name,
- render_params(node.params),
- if let Some(return_type) = node.return_type {
- format!(": {}", render_ts_type(return_type))
- } else {
- "".to_string()
- }
- )
- .as_str()
- }
- for node in type_literal.properties {
- output += format!(
- "{}{}, ",
- node.name,
- if let Some(ts_type) = node.ts_type {
- format!(": {}", render_ts_type(ts_type))
- } else {
- "".to_string()
- }
- )
- .as_str()
+ for method_def in &interface_def.methods {
+ writeln!(w, "{}{}", Indent(1), method_def)?;
+ if let Some(js_doc) = &method_def.js_doc {
+ self.format_jsdoc(w, js_doc, 2, self.details)?;
}
- if !output.is_empty() {
- output.truncate(output.len() - 2);
- }
- "{ ".to_string() + output.as_str() + " }"
- }
- TsTypeDefKind::TypeOperator => {
- let operator = ts_type.type_operator.unwrap();
- format!("{} {}", operator.operator, render_ts_type(operator.ts_type))
- }
- TsTypeDefKind::TypeQuery => {
- format!("typeof {}", ts_type.type_query.unwrap())
}
- TsTypeDefKind::TypeRef => {
- let type_ref = ts_type.type_ref.unwrap();
- let mut final_output = type_ref.type_name;
- if let Some(type_params) = type_ref.type_params {
- let mut output = "".to_string();
- if !type_params.is_empty() {
- for ts_type in type_params {
- output += render_ts_type(ts_type).as_str();
- output += ", "
- }
- output.truncate(output.len() - 2);
- }
- final_output += format!("<{}>", output).as_str();
- }
- final_output
+ for index_sign_def in &interface_def.index_signatures {
+ writeln!(w, "{}{}", Indent(1), index_sign_def)?;
}
- TsTypeDefKind::Union => {
- let union = ts_type.union.unwrap();
- let mut output = "".to_string();
- if !union.is_empty() {
- for ts_type in union {
- output += render_ts_type(ts_type).as_str();
- output += " | "
- }
- output.truncate(output.len() - 3);
+ writeln!(w)
+ }
+
+ fn format_namespace_details(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ ) -> FmtResult {
+ let elements = &node.namespace_def.as_ref().unwrap().elements;
+ for node in elements {
+ self.format_signature(w, &node, 1)?;
+ if let Some(js_doc) = &node.js_doc {
+ self.format_jsdoc(w, js_doc, 2, false)?;
}
- output
}
+ writeln!(w)
}
-}
-fn add_indent(string: String, indent: i64) -> String {
- let mut indent_str = String::new();
- for _ in 0..(indent * 2) {
- indent_str += " ";
- }
- indent_str += string.as_str();
- indent_str
-}
+ fn format_class_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ let class_def = node.class_def.as_ref().unwrap();
+ write!(
+ w,
+ "{}{}{} {}",
+ Indent(indent),
+ display_abstract(class_def.is_abstract),
+ colors::magenta("class"),
+ colors::bold(&node.name),
+ )?;
+ if !class_def.type_params.is_empty() {
+ write!(
+ w,
+ "<{}>",
+ SliceDisplayer::new(&class_def.type_params, ", ", false)
+ )?;
+ }
-// TODO: this should use some sort of markdown to console parser.
-fn format_jsdoc(jsdoc: String, indent: i64) -> String {
- let lines = jsdoc.split("\n\n").map(|line| line.replace("\n", " "));
+ if let Some(extends) = &class_def.extends {
+ write!(w, " {} {}", colors::magenta("extends"), extends)?;
+ }
+ if !class_def.super_type_params.is_empty() {
+ write!(
+ w,
+ "<{}>",
+ SliceDisplayer::new(&class_def.super_type_params, ", ", false)
+ )?;
+ }
- let mut js_doc = String::new();
+ if !class_def.implements.is_empty() {
+ write!(
+ w,
+ " {} {}",
+ colors::magenta("implements"),
+ SliceDisplayer::new(&class_def.implements, ", ", false)
+ )?;
+ }
- for line in lines {
- js_doc.push_str(&add_indent(format!("{}\n", line), indent + 1));
+ writeln!(w)
}
- format!("{}", colors::gray(&js_doc))
-}
-
-fn format_class_details(node: doc::DocNode) -> String {
- let mut details = String::new();
-
- let class_def = node.class_def.unwrap();
- for node in class_def.constructors {
- details.push_str(&add_indent(
- format!(
- "{} {}({})\n",
- colors::magenta("constructor"),
- colors::bold(&node.name),
- render_params(node.params),
- ),
- 1,
- ));
- }
- for node in class_def.properties.iter().filter(|node| {
- node
- .accessibility
- .unwrap_or(swc_ecma_ast::Accessibility::Public)
- != swc_ecma_ast::Accessibility::Private
- }) {
- details.push_str(&add_indent(
- format!(
- "{}{}{}{}\n",
- colors::magenta(
- match node
- .accessibility
- .unwrap_or(swc_ecma_ast::Accessibility::Public)
- {
- swc_ecma_ast::Accessibility::Protected => "protected ",
- _ => "",
- }
- ),
- colors::bold(&node.name),
- if node.optional {
- "?".to_string()
- } else {
- "".to_string()
- },
- if let Some(ts_type) = node.ts_type.clone() {
- format!(": {}", render_ts_type(ts_type))
- } else {
- "".to_string()
- }
- ),
- 1,
- ));
- }
- for node in class_def.methods.iter().filter(|node| {
- node
- .accessibility
- .unwrap_or(swc_ecma_ast::Accessibility::Public)
- != swc_ecma_ast::Accessibility::Private
- }) {
- let function_def = node.function_def.clone();
- details.push_str(&add_indent(
- format!(
- "{}{}{}{}({}){}\n",
- colors::magenta(
- match node
- .accessibility
- .unwrap_or(swc_ecma_ast::Accessibility::Public)
- {
- swc_ecma_ast::Accessibility::Protected => "protected ",
- _ => "",
- }
- ),
- colors::magenta(match node.kind {
- swc_ecma_ast::MethodKind::Getter => "get ",
- swc_ecma_ast::MethodKind::Setter => "set ",
- _ => "",
- }),
- colors::bold(&node.name),
- if node.optional { "?" } else { "" },
- render_params(function_def.params),
- if let Some(return_type) = function_def.return_type {
- format!(": {}", render_ts_type(return_type))
- } else {
- "".to_string()
- }
- ),
- 1,
- ));
+ fn format_enum_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ writeln!(
+ w,
+ "{}{} {}",
+ Indent(indent),
+ colors::magenta("enum"),
+ colors::bold(&node.name)
+ )
}
- details.push_str("\n");
- details
-}
-fn format_enum_details(node: doc::DocNode) -> String {
- let mut details = String::new();
- let enum_def = node.enum_def.unwrap();
- for member in enum_def.members {
- details
- .push_str(&add_indent(format!("{}\n", colors::bold(&member.name)), 1));
+ fn format_function_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ let function_def = node.function_def.as_ref().unwrap();
+ write!(
+ w,
+ "{}{}{}{} {}",
+ Indent(indent),
+ display_async(function_def.is_async),
+ colors::magenta("function"),
+ display_generator(function_def.is_generator),
+ colors::bold(&node.name)
+ )?;
+ if !function_def.type_params.is_empty() {
+ write!(
+ w,
+ "<{}>",
+ SliceDisplayer::new(&function_def.type_params, ", ", false)
+ )?;
+ }
+ write!(
+ w,
+ "({})",
+ SliceDisplayer::new(&function_def.params, ", ", false)
+ )?;
+ if let Some(return_type) = &function_def.return_type {
+ write!(w, ": {}", return_type)?;
+ }
+ writeln!(w)
}
- details.push_str("\n");
- details
-}
-fn format_namespace_details(node: doc::DocNode) -> String {
- let mut ns = String::new();
+ fn format_interface_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ let interface_def = node.interface_def.as_ref().unwrap();
+ write!(
+ w,
+ "{}{} {}",
+ Indent(indent),
+ colors::magenta("interface"),
+ colors::bold(&node.name)
+ )?;
+
+ if !interface_def.type_params.is_empty() {
+ write!(
+ w,
+ "<{}>",
+ SliceDisplayer::new(&interface_def.type_params, ", ", false)
+ )?;
+ }
+
+ if !interface_def.extends.is_empty() {
+ write!(
+ w,
+ " {} {}",
+ colors::magenta("extends"),
+ SliceDisplayer::new(&interface_def.extends, ", ", false)
+ )?;
+ }
- let elements = node.namespace_def.unwrap().elements;
- for node in elements {
- ns.push_str(&format_signature(&node, 1));
+ writeln!(w)
}
- ns.push_str("\n");
- ns
-}
-fn format_function_signature(node: &doc::DocNode, indent: i64) -> String {
- let function_def = node.function_def.clone().unwrap();
- add_indent(
- format!(
- "{} {}({}){}\n",
- colors::magenta("function"),
+ fn format_type_alias_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ let type_alias_def = node.type_alias_def.as_ref().unwrap();
+ write!(
+ w,
+ "{}{} {}",
+ Indent(indent),
+ colors::magenta("type"),
colors::bold(&node.name),
- render_params(function_def.params),
- if let Some(return_type) = function_def.return_type {
- format!(": {}", render_ts_type(return_type).as_str())
- } else {
- "".to_string()
- }
- ),
- indent,
- )
-}
+ )?;
+
+ if !type_alias_def.type_params.is_empty() {
+ write!(
+ w,
+ "<{}>",
+ SliceDisplayer::new(&type_alias_def.type_params, ", ", false)
+ )?;
+ }
-fn format_class_signature(node: &doc::DocNode, indent: i64) -> String {
- let class_def = node.class_def.clone().unwrap();
- let extends_suffix = if let Some(extends) = class_def.extends {
- format!(" {} {}", colors::magenta("extends"), colors::bold(&extends))
- } else {
- String::from("")
- };
-
- let implements = &class_def.implements;
- let implements_suffix = if !implements.is_empty() {
- format!(
- " {} {}",
- colors::magenta("implements"),
- colors::bold(&implements.join(", "))
- )
- } else {
- String::from("")
- };
+ writeln!(w, " = {}", type_alias_def.ts_type)
+ }
- add_indent(
- format!(
- "{} {}{}{}\n",
- colors::magenta("class"),
- colors::bold(&node.name),
- extends_suffix,
- implements_suffix,
- ),
- indent,
- )
-}
+ fn format_namespace_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ writeln!(
+ w,
+ "{}{} {}",
+ Indent(indent),
+ colors::magenta("namespace"),
+ colors::bold(&node.name)
+ )
+ }
-fn format_variable_signature(node: &doc::DocNode, indent: i64) -> String {
- let variable_def = node.variable_def.clone().unwrap();
- add_indent(
- format!(
- "{} {}{}\n",
+ fn format_variable_signature(
+ &self,
+ w: &mut Formatter<'_>,
+ node: &doc::DocNode,
+ indent: i64,
+ ) -> FmtResult {
+ let variable_def = node.variable_def.as_ref().unwrap();
+ write!(
+ w,
+ "{}{} {}",
+ Indent(indent),
colors::magenta(match variable_def.kind {
swc_ecma_ast::VarDeclKind::Const => "const",
swc_ecma_ast::VarDeclKind::Let => "let",
swc_ecma_ast::VarDeclKind::Var => "var",
}),
colors::bold(&node.name),
- if let Some(ts_type) = variable_def.ts_type {
- format!(": {}", render_ts_type(ts_type))
- } else {
- "".to_string()
- }
- ),
- indent,
- )
-}
-
-fn format_enum_signature(node: &doc::DocNode, indent: i64) -> String {
- add_indent(
- format!("{} {}\n", colors::magenta("enum"), colors::bold(&node.name)),
- indent,
- )
-}
-
-fn format_interface_signature(node: &doc::DocNode, indent: i64) -> String {
- let interface_def = node.interface_def.clone().unwrap();
- let extends = &interface_def.extends;
- let extends_suffix = if !extends.is_empty() {
- format!(
- " {} {}",
- colors::magenta("extends"),
- colors::bold(&extends.join(", "))
- )
- } else {
- String::from("")
- };
- add_indent(
- format!(
- "{} {}{}\n",
- colors::magenta("interface"),
- colors::bold(&node.name),
- extends_suffix
- ),
- indent,
- )
-}
-
-fn format_type_alias_signature(node: &doc::DocNode, indent: i64) -> String {
- add_indent(
- format!("{} {}\n", colors::magenta("type"), colors::bold(&node.name)),
- indent,
- )
+ )?;
+ if let Some(ts_type) = &variable_def.ts_type {
+ write!(w, ": {}", ts_type)?;
+ }
+ writeln!(w)
+ }
}
-fn format_namespace_signature(node: &doc::DocNode, indent: i64) -> String {
- add_indent(
- format!(
- "{} {}\n",
- colors::magenta("namespace"),
- colors::bold(&node.name)
- ),
- indent,
- )
+impl<'a> Display for DocPrinter<'a> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
+ self.format(f)
+ }
}