From 3374c73fba3a96df22d0c04e6c17078ca8cce45b Mon Sep 17 00:00:00 2001 From: Valentin Anger Date: Sun, 12 Jul 2020 14:16:33 +0200 Subject: 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 --- cli/doc/ts_type.rs | 283 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 257 insertions(+), 26 deletions(-) (limited to 'cli/doc/ts_type.rs') diff --git a/cli/doc/ts_type.rs b/cli/doc/ts_type.rs index 7bb494541..36502ee5e 100644 --- a/cli/doc/ts_type.rs +++ b/cli/doc/ts_type.rs @@ -1,30 +1,23 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +use super::display::{display_readonly, SliceDisplayer}; use super::interface::expr_to_name; use super::params::ts_fn_param_to_param_def; use super::ts_type_param::maybe_type_param_decl_to_type_param_defs; use super::ts_type_param::TsTypeParamDef; use super::ParamDef; +use crate::colors; +use crate::doc; use crate::swc_ecma_ast; -use crate::swc_ecma_ast::TsArrayType; -use crate::swc_ecma_ast::TsConditionalType; -use crate::swc_ecma_ast::TsFnOrConstructorType; -use crate::swc_ecma_ast::TsIndexedAccessType; -use crate::swc_ecma_ast::TsKeywordType; -use crate::swc_ecma_ast::TsLit; -use crate::swc_ecma_ast::TsLitType; -use crate::swc_ecma_ast::TsOptionalType; -use crate::swc_ecma_ast::TsParenthesizedType; -use crate::swc_ecma_ast::TsRestType; -use crate::swc_ecma_ast::TsThisType; -use crate::swc_ecma_ast::TsTupleType; -use crate::swc_ecma_ast::TsType; -use crate::swc_ecma_ast::TsTypeAnn; -use crate::swc_ecma_ast::TsTypeLit; -use crate::swc_ecma_ast::TsTypeOperator; -use crate::swc_ecma_ast::TsTypeQuery; -use crate::swc_ecma_ast::TsTypeRef; -use crate::swc_ecma_ast::TsUnionOrIntersectionType; +use crate::swc_ecma_ast::{ + TsArrayType, TsConditionalType, TsExprWithTypeArgs, TsFnOrConstructorType, + TsIndexedAccessType, TsKeywordType, TsLit, TsLitType, TsOptionalType, + TsParenthesizedType, TsRestType, TsThisType, TsTupleType, TsType, TsTypeAnn, + TsTypeLit, TsTypeOperator, TsTypeParamInstantiation, TsTypeQuery, TsTypeRef, + TsUnionOrIntersectionType, +}; use serde::Serialize; +use std::fmt::{Display, Formatter, Result as FmtResult}; + // pub enum TsType { // * TsKeywordType(TsKeywordType), // * TsThisType(TsThisType), @@ -316,7 +309,37 @@ impl Into for &TsTypeRef { }; TsTypeDef { - repr: type_name.to_string(), + repr: type_name.clone(), + type_ref: Some(TsTypeRefDef { + type_name, + type_params, + }), + kind: Some(TsTypeDefKind::TypeRef), + ..Default::default() + } + } +} + +impl Into for &TsExprWithTypeArgs { + fn into(self) -> TsTypeDef { + let type_name = ts_entity_name_to_name(&self.expr); + + let type_params = if let Some(type_params_inst) = &self.type_args { + let mut ts_type_defs = vec![]; + + for type_box in &type_params_inst.params { + let ts_type: &TsType = &(*type_box); + let def: TsTypeDef = ts_type.into(); + ts_type_defs.push(def); + } + + Some(ts_type_defs) + } else { + None + }; + + TsTypeDef { + repr: type_name.clone(), type_ref: Some(TsTypeRefDef { type_name, type_params, @@ -348,6 +371,7 @@ impl Into for &TsTypeLit { let mut methods = vec![]; let mut properties = vec![]; let mut call_signatures = vec![]; + let mut index_signatures = vec![]; for type_element in &self.members { use crate::swc_ecma_ast::TsTypeElement::*; @@ -357,7 +381,7 @@ impl Into for &TsTypeLit { let mut params = vec![]; for param in &ts_method_sig.params { - let param_def = ts_fn_param_to_param_def(param); + let param_def = ts_fn_param_to_param_def(param, None); params.push(param_def); } @@ -384,7 +408,7 @@ impl Into for &TsTypeLit { let mut params = vec![]; for param in &ts_prop_sig.params { - let param_def = ts_fn_param_to_param_def(param); + let param_def = ts_fn_param_to_param_def(param, None); params.push(param_def); } @@ -409,7 +433,7 @@ impl Into for &TsTypeLit { TsCallSignatureDecl(ts_call_sig) => { let mut params = vec![]; for param in &ts_call_sig.params { - let param_def = ts_fn_param_to_param_def(param); + let param_def = ts_fn_param_to_param_def(param, None); params.push(param_def); } @@ -429,9 +453,27 @@ impl Into for &TsTypeLit { }; call_signatures.push(call_sig_def); } + TsIndexSignature(ts_index_sig) => { + let mut params = vec![]; + for param in &ts_index_sig.params { + let param_def = ts_fn_param_to_param_def(param, None); + params.push(param_def); + } + + let ts_type = ts_index_sig + .type_ann + .as_ref() + .map(|rt| (&*rt.type_ann).into()); + + let index_sig_def = LiteralIndexSignatureDef { + readonly: ts_index_sig.readonly, + params, + ts_type, + }; + index_signatures.push(index_sig_def); + } // TODO: TsConstructSignatureDecl(_) => {} - TsIndexSignature(_) => {} } } @@ -439,6 +481,7 @@ impl Into for &TsTypeLit { methods, properties, call_signatures, + index_signatures, }; TsTypeDef { @@ -475,7 +518,7 @@ impl Into for &TsFnOrConstructorType { let mut params = vec![]; for param in &ts_fn_type.params { - let param_def = ts_fn_param_to_param_def(param); + let param_def = ts_fn_param_to_param_def(param, None); params.push(param_def); } @@ -494,7 +537,7 @@ impl Into for &TsFnOrConstructorType { let mut params = vec![]; for param in &ctor_type.params { - let param_def = ts_fn_param_to_param_def(param); + let param_def = ts_fn_param_to_param_def(param, None); params.push(param_def); } @@ -619,6 +662,21 @@ pub struct LiteralMethodDef { pub type_params: Vec, } +impl Display for LiteralMethodDef { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!( + f, + "{}({})", + self.name, + SliceDisplayer::new(&self.params, ", ", false) + )?; + if let Some(return_type) = &self.return_type { + write!(f, ": {}", return_type)?; + } + Ok(()) + } +} + #[derive(Debug, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct LiteralPropertyDef { @@ -630,6 +688,15 @@ pub struct LiteralPropertyDef { pub type_params: Vec, } +impl Display for LiteralPropertyDef { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}", self.name)?; + if let Some(ts_type) = &self.ts_type { + write!(f, ": {}", ts_type)?; + } + Ok(()) + } +} #[derive(Debug, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct LiteralCallSignatureDef { @@ -638,12 +705,46 @@ pub struct LiteralCallSignatureDef { pub type_params: Vec, } +impl Display for LiteralCallSignatureDef { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "({})", SliceDisplayer::new(&self.params, ", ", false))?; + if let Some(ts_type) = &self.ts_type { + write!(f, ": {}", ts_type)?; + } + Ok(()) + } +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct LiteralIndexSignatureDef { + pub readonly: bool, + pub params: Vec, + pub ts_type: Option, +} + +impl Display for LiteralIndexSignatureDef { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!( + f, + "{}[{}]", + display_readonly(self.readonly), + SliceDisplayer::new(&self.params, ", ", false) + )?; + if let Some(ts_type) = &self.ts_type { + write!(f, ": {}", ts_type)?; + } + Ok(()) + } +} + #[derive(Debug, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct TsTypeLiteralDef { pub methods: Vec, pub properties: Vec, pub call_signatures: Vec, + pub index_signatures: Vec, } #[derive(Debug, PartialEq, Serialize, Clone)] @@ -753,3 +854,133 @@ pub fn ts_type_ann_to_def(type_ann: &TsTypeAnn) -> TsTypeDef { }, } } + +impl Display for TsTypeDef { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + if self.kind.is_none() { + return write!(f, "{}", colors::red("")); + } + + let kind = self.kind.as_ref().unwrap(); + match kind { + TsTypeDefKind::Array => write!(f, "{}[]", &*self.array.as_ref().unwrap()), + TsTypeDefKind::Conditional => { + let conditional = self.conditional_type.as_ref().unwrap(); + write!( + f, + "{} {} {} ? {} : {}", + &*conditional.check_type, + colors::magenta("extends"), + &*conditional.extends_type, + &*conditional.true_type, + &*conditional.false_type + ) + } + TsTypeDefKind::FnOrConstructor => { + let fn_or_constructor = self.fn_or_constructor.as_ref().unwrap(); + write!( + f, + "{}({}) => {}", + colors::magenta(if fn_or_constructor.constructor { + "new " + } else { + "" + }), + SliceDisplayer::new(&fn_or_constructor.params, ", ", false), + &fn_or_constructor.ts_type, + ) + } + TsTypeDefKind::IndexedAccess => { + let indexed_access = self.indexed_access.as_ref().unwrap(); + write!( + f, + "{}[{}]", + &*indexed_access.obj_type, &*indexed_access.index_type + ) + } + TsTypeDefKind::Intersection => { + let intersection = self.intersection.as_ref().unwrap(); + write!(f, "{}", SliceDisplayer::new(&intersection, " & ", false)) + } + TsTypeDefKind::Keyword => { + write!(f, "{}", colors::cyan(self.keyword.as_ref().unwrap())) + } + TsTypeDefKind::Literal => { + let literal = self.literal.as_ref().unwrap(); + match literal.kind { + doc::ts_type::LiteralDefKind::Boolean => write!( + f, + "{}", + colors::yellow(&literal.boolean.unwrap().to_string()) + ), + doc::ts_type::LiteralDefKind::String => write!( + f, + "{}", + colors::green(&format!("\"{}\"", literal.string.as_ref().unwrap())) + ), + doc::ts_type::LiteralDefKind::Number => write!( + f, + "{}", + colors::yellow(&literal.number.unwrap().to_string()) + ), + } + } + TsTypeDefKind::Optional => { + write!(f, "{}?", &*self.optional.as_ref().unwrap()) + } + TsTypeDefKind::Parenthesized => { + write!(f, "({})", &*self.parenthesized.as_ref().unwrap()) + } + TsTypeDefKind::Rest => write!(f, "...{}", &*self.rest.as_ref().unwrap()), + TsTypeDefKind::This => write!(f, "this"), + TsTypeDefKind::Tuple => { + let tuple = self.tuple.as_ref().unwrap(); + write!(f, "[{}]", SliceDisplayer::new(&tuple, ", ", false)) + } + TsTypeDefKind::TypeLiteral => { + let type_literal = self.type_literal.as_ref().unwrap(); + write!( + f, + "{{ {}{}{}{}}}", + SliceDisplayer::new(&type_literal.call_signatures, "; ", true), + SliceDisplayer::new(&type_literal.methods, "; ", true), + SliceDisplayer::new(&type_literal.properties, "; ", true), + SliceDisplayer::new(&type_literal.index_signatures, "; ", true), + ) + } + TsTypeDefKind::TypeOperator => { + let operator = self.type_operator.as_ref().unwrap(); + write!(f, "{} {}", operator.operator, &operator.ts_type) + } + TsTypeDefKind::TypeQuery => { + write!(f, "typeof {}", self.type_query.as_ref().unwrap()) + } + TsTypeDefKind::TypeRef => { + let type_ref = self.type_ref.as_ref().unwrap(); + write!(f, "{}", colors::intense_blue(&type_ref.type_name))?; + if let Some(type_params) = &type_ref.type_params { + write!(f, "<{}>", SliceDisplayer::new(type_params, ", ", false))?; + } + Ok(()) + } + TsTypeDefKind::Union => { + let union = self.union.as_ref().unwrap(); + write!(f, "{}", SliceDisplayer::new(union, " | ", false)) + } + } + } +} + +pub fn maybe_type_param_instantiation_to_type_defs( + maybe_type_param_instantiation: Option<&TsTypeParamInstantiation>, +) -> Vec { + if let Some(type_param_instantiation) = maybe_type_param_instantiation { + type_param_instantiation + .params + .iter() + .map(|type_param| type_param.as_ref().into()) + .collect::>() + } else { + vec![] + } +} -- cgit v1.2.3