From be1e7ab5320c0a110998818c3916c79b39710613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Wed, 19 Aug 2020 19:13:43 +0200 Subject: [PATCH] refactor: move cli/doc/ to separate crate (#7103) --- Cargo.lock | 18 + cli/Cargo.toml | 2 +- cli/doc/class.rs | 339 ------- cli/doc/display.rs | 91 -- cli/doc/enum.rs | 40 - cli/doc/function.rs | 58 -- cli/doc/interface.rs | 303 ------ cli/doc/mod.rs | 75 -- cli/doc/module.rs | 59 -- cli/doc/namespace.rs | 67 -- cli/doc/node.rs | 287 ------ cli/doc/params.rs | 289 ------ cli/doc/parser.rs | 505 ---------- cli/doc/printer.rs | 426 -------- cli/doc/tests.rs | 2002 -------------------------------------- cli/doc/ts_type.rs | 985 ------------------- cli/doc/ts_type_param.rs | 71 -- cli/doc/type_alias.rs | 30 - cli/doc/variable.rs | 39 - cli/global_state.rs | 2 +- cli/main.rs | 58 +- cli/module_graph.rs | 2 +- cli/swc_util.rs | 26 + cli/tsc.rs | 2 +- 24 files changed, 93 insertions(+), 5683 deletions(-) delete mode 100644 cli/doc/class.rs delete mode 100644 cli/doc/display.rs delete mode 100644 cli/doc/enum.rs delete mode 100644 cli/doc/function.rs delete mode 100644 cli/doc/interface.rs delete mode 100644 cli/doc/mod.rs delete mode 100644 cli/doc/module.rs delete mode 100644 cli/doc/namespace.rs delete mode 100644 cli/doc/node.rs delete mode 100644 cli/doc/params.rs delete mode 100644 cli/doc/parser.rs delete mode 100644 cli/doc/printer.rs delete mode 100644 cli/doc/tests.rs delete mode 100644 cli/doc/ts_type.rs delete mode 100644 cli/doc/ts_type_param.rs delete mode 100644 cli/doc/type_alias.rs delete mode 100644 cli/doc/variable.rs diff --git a/Cargo.lock b/Cargo.lock index cfbe630f18..c220be9a99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,6 +329,7 @@ dependencies = [ "bytes", "clap", "deno_core", + "deno_doc", "deno_lint", "deno_web", "dissimilar", @@ -392,6 +393,23 @@ dependencies = [ "url", ] +[[package]] +name = "deno_doc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1700f692f75fb14c854ca5e2b5e74c23c5b5cc2b3ea9adec4ff0cd5693deab0" +dependencies = [ + "futures", + "lazy_static", + "regex", + "serde", + "serde_derive", + "serde_json", + "swc_common", + "swc_ecmascript", + "termcolor", +] + [[package]] name = "deno_lint" version = "0.1.23" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index c9371352f0..d35ce7951c 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -24,9 +24,9 @@ winapi = "0.3.9" [dependencies] deno_core = { path = "../core", version = "0.53.0" } +deno_doc = { version = "0.1.0" } deno_lint = { version = "0.1.23", features = ["json"] } - atty = "0.2.14" base64 = "0.12.3" bytes = "0.5.6" diff --git a/cli/doc/class.rs b/cli/doc/class.rs deleted file mode 100644 index 292aa4b97d..0000000000 --- a/cli/doc/class.rs +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::colors; -use crate::doc::display::{ - display_abstract, display_accessibility, display_async, display_generator, - display_method, display_optional, display_readonly, display_static, - SliceDisplayer, -}; -use serde::Serialize; -use swc_common::Spanned; - -use super::function::function_to_function_def; -use super::function::FunctionDef; -use super::interface::expr_to_name; -use super::params::{ - assign_pat_to_param_def, ident_to_param_def, pat_to_param_def, - prop_name_to_string, ts_fn_param_to_param_def, -}; -use super::parser::DocParser; -use super::ts_type::{ - maybe_type_param_instantiation_to_type_defs, ts_type_ann_to_def, TsTypeDef, -}; -use super::ts_type_param::maybe_type_param_decl_to_type_param_defs; -use super::ts_type_param::TsTypeParamDef; -use super::Location; -use super::ParamDef; - -use std::fmt::{Display, Formatter, Result as FmtResult}; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct ClassConstructorDef { - pub js_doc: Option, - pub accessibility: Option, - pub name: String, - pub params: Vec, - pub location: Location, -} - -impl Display for ClassConstructorDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!( - f, - "{}{}({})", - display_accessibility(self.accessibility), - colors::magenta("constructor"), - SliceDisplayer::new(&self.params, ", ", false), - ) - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct ClassPropertyDef { - pub js_doc: Option, - pub ts_type: Option, - pub readonly: bool, - pub accessibility: Option, - pub optional: bool, - pub is_abstract: bool, - pub is_static: bool, - pub name: String, - pub location: Location, -} - -impl Display for ClassPropertyDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!( - f, - "{}{}{}{}{}{}", - display_abstract(self.is_abstract), - display_accessibility(self.accessibility), - display_static(self.is_static), - display_readonly(self.readonly), - colors::bold(&self.name), - display_optional(self.optional), - )?; - if let Some(ts_type) = &self.ts_type { - write!(f, ": {}", ts_type)?; - } - Ok(()) - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct ClassIndexSignatureDef { - pub readonly: bool, - pub params: Vec, - pub ts_type: Option, -} - -impl Display for ClassIndexSignatureDef { - 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 ClassMethodDef { - pub js_doc: Option, - pub accessibility: Option, - pub optional: bool, - pub is_abstract: bool, - pub is_static: bool, - pub name: String, - pub kind: swc_ecmascript::ast::MethodKind, - pub function_def: FunctionDef, - pub location: Location, -} - -impl Display for ClassMethodDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!( - f, - "{}{}{}{}{}{}{}{}({})", - display_abstract(self.is_abstract), - display_accessibility(self.accessibility), - display_static(self.is_static), - display_async(self.function_def.is_async), - display_method(self.kind), - display_generator(self.function_def.is_generator), - colors::bold(&self.name), - display_optional(self.optional), - SliceDisplayer::new(&self.function_def.params, ", ", false), - )?; - if let Some(return_type) = &self.function_def.return_type { - write!(f, ": {}", return_type)?; - } - Ok(()) - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct ClassDef { - // TODO(bartlomieju): decorators - pub is_abstract: bool, - pub constructors: Vec, - pub properties: Vec, - pub index_signatures: Vec, - pub methods: Vec, - pub extends: Option, - pub implements: Vec, - pub type_params: Vec, - pub super_type_params: Vec, -} - -pub fn class_to_class_def( - doc_parser: &DocParser, - class: &swc_ecmascript::ast::Class, -) -> ClassDef { - let mut constructors = vec![]; - let mut methods = vec![]; - let mut properties = vec![]; - let mut index_signatures = vec![]; - - let extends: Option = match &class.super_class { - Some(boxed) => { - use swc_ecmascript::ast::Expr; - let expr: &Expr = &**boxed; - match expr { - Expr::Ident(ident) => Some(ident.sym.to_string()), - _ => None, - } - } - None => None, - }; - - let implements = class - .implements - .iter() - .map(|expr| expr.into()) - .collect::>(); - - for member in &class.body { - use swc_ecmascript::ast::ClassMember::*; - - match member { - Constructor(ctor) => { - let ctor_js_doc = doc_parser.js_doc_for_span(ctor.span()); - let constructor_name = prop_name_to_string( - &ctor.key, - Some(&doc_parser.ast_parser.source_map), - ); - - let mut params = vec![]; - - for param in &ctor.params { - use swc_ecmascript::ast::ParamOrTsParamProp::*; - - let param_def = match param { - Param(param) => pat_to_param_def( - ¶m.pat, - Some(&doc_parser.ast_parser.source_map), - ), - TsParamProp(ts_param_prop) => { - use swc_ecmascript::ast::TsParamPropParam; - - match &ts_param_prop.param { - TsParamPropParam::Ident(ident) => ident_to_param_def( - ident, - Some(&doc_parser.ast_parser.source_map), - ), - TsParamPropParam::Assign(assign_pat) => { - assign_pat_to_param_def( - assign_pat, - Some(&doc_parser.ast_parser.source_map), - ) - } - } - } - }; - params.push(param_def); - } - - let constructor_def = ClassConstructorDef { - js_doc: ctor_js_doc, - accessibility: ctor.accessibility, - name: constructor_name, - params, - location: doc_parser.ast_parser.get_span_location(ctor.span).into(), - }; - constructors.push(constructor_def); - } - Method(class_method) => { - let method_js_doc = doc_parser.js_doc_for_span(class_method.span()); - let method_name = prop_name_to_string( - &class_method.key, - Some(&doc_parser.ast_parser.source_map), - ); - let fn_def = - function_to_function_def(&doc_parser, &class_method.function); - let method_def = ClassMethodDef { - js_doc: method_js_doc, - accessibility: class_method.accessibility, - optional: class_method.is_optional, - is_abstract: class_method.is_abstract, - is_static: class_method.is_static, - name: method_name, - kind: class_method.kind, - function_def: fn_def, - location: doc_parser - .ast_parser - .get_span_location(class_method.span) - .into(), - }; - methods.push(method_def); - } - ClassProp(class_prop) => { - let prop_js_doc = doc_parser.js_doc_for_span(class_prop.span()); - - let ts_type = class_prop - .type_ann - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - let prop_name = expr_to_name(&*class_prop.key); - - let prop_def = ClassPropertyDef { - js_doc: prop_js_doc, - ts_type, - readonly: class_prop.readonly, - optional: class_prop.is_optional, - is_abstract: class_prop.is_abstract, - is_static: class_prop.is_static, - accessibility: class_prop.accessibility, - name: prop_name, - location: doc_parser - .ast_parser - .get_span_location(class_prop.span) - .into(), - }; - properties.push(prop_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 = ClassIndexSignatureDef { - readonly: ts_index_sig.readonly, - params, - ts_type, - }; - index_signatures.push(index_sig_def); - } - // TODO(bartlomieju): - PrivateMethod(_) => {} - PrivateProp(_) => {} - _ => {} - } - } - - let type_params = - maybe_type_param_decl_to_type_param_defs(class.type_params.as_ref()); - - let super_type_params = maybe_type_param_instantiation_to_type_defs( - class.super_type_params.as_ref(), - ); - - ClassDef { - is_abstract: class.is_abstract, - extends, - implements, - constructors, - properties, - index_signatures, - methods, - type_params, - super_type_params, - } -} - -pub fn get_doc_for_class_decl( - doc_parser: &DocParser, - class_decl: &swc_ecmascript::ast::ClassDecl, -) -> (String, ClassDef) { - let class_name = class_decl.ident.sym.to_string(); - let class_def = class_to_class_def(doc_parser, &class_decl.class); - - (class_name, class_def) -} diff --git a/cli/doc/display.rs b/cli/doc/display.rs deleted file mode 100644 index 44ed624151..0000000000 --- a/cli/doc/display.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::colors; -use std::fmt::{Display, Formatter, Result}; - -pub(crate) struct Indent(pub i64); - -impl Display for Indent { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - for _ in 0..self.0 { - write!(f, " ")?; - } - Ok(()) - } -} - -pub(crate) struct SliceDisplayer<'a, T: Display>(&'a [T], &'a str, bool); - -impl<'a, T: Display> SliceDisplayer<'a, T> { - pub fn new( - slice: &'a [T], - separator: &'a str, - trailing: bool, - ) -> SliceDisplayer<'a, T> { - SliceDisplayer(slice, separator, trailing) - } -} - -impl Display for SliceDisplayer<'_, T> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - if self.0.is_empty() { - return Ok(()); - } - - write!(f, "{}", self.0[0])?; - for v in &self.0[1..] { - write!(f, "{}{}", self.1, v)?; - } - - if self.2 { - write!(f, "{}", self.1)?; - } - - Ok(()) - } -} - -pub(crate) fn display_abstract(is_abstract: bool) -> impl Display { - colors::magenta(if is_abstract { "abstract " } else { "" }) -} - -pub(crate) fn display_accessibility( - accessibility: Option, -) -> impl Display { - colors::magenta( - match accessibility.unwrap_or(swc_ecmascript::ast::Accessibility::Public) { - swc_ecmascript::ast::Accessibility::Public => "", - swc_ecmascript::ast::Accessibility::Protected => "protected ", - swc_ecmascript::ast::Accessibility::Private => "private ", - }, - ) -} - -pub(crate) fn display_async(is_async: bool) -> impl Display { - colors::magenta(if is_async { "async " } else { "" }) -} - -pub(crate) fn display_generator(is_generator: bool) -> impl Display { - colors::magenta(if is_generator { "*" } else { "" }) -} - -pub(crate) fn display_method( - method: swc_ecmascript::ast::MethodKind, -) -> impl Display { - colors::magenta(match method { - swc_ecmascript::ast::MethodKind::Getter => "get ", - swc_ecmascript::ast::MethodKind::Setter => "set ", - _ => "", - }) -} - -pub(crate) fn display_optional(is_optional: bool) -> impl Display { - colors::magenta(if is_optional { "?" } else { "" }) -} - -pub(crate) fn display_readonly(is_readonly: bool) -> impl Display { - colors::magenta(if is_readonly { "readonly " } else { "" }) -} - -pub(crate) fn display_static(is_static: bool) -> impl Display { - colors::magenta(if is_static { "static " } else { "" }) -} diff --git a/cli/doc/enum.rs b/cli/doc/enum.rs deleted file mode 100644 index 8161337ce7..0000000000 --- a/cli/doc/enum.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use serde::Serialize; - -use super::parser::DocParser; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct EnumMemberDef { - pub name: String, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct EnumDef { - pub members: Vec, -} - -pub fn get_doc_for_ts_enum_decl( - _doc_parser: &DocParser, - enum_decl: &swc_ecmascript::ast::TsEnumDecl, -) -> (String, EnumDef) { - let enum_name = enum_decl.id.sym.to_string(); - let mut members = vec![]; - - for enum_member in &enum_decl.members { - use swc_ecmascript::ast::TsEnumMemberId::*; - - let member_name = match &enum_member.id { - Ident(ident) => ident.sym.to_string(), - Str(str_) => str_.value.to_string(), - }; - - let member_def = EnumMemberDef { name: member_name }; - members.push(member_def); - } - - let enum_def = EnumDef { members }; - - (enum_name, enum_def) -} diff --git a/cli/doc/function.rs b/cli/doc/function.rs deleted file mode 100644 index ab6430ec60..0000000000 --- a/cli/doc/function.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use super::params::pat_to_param_def; -use super::parser::DocParser; -use super::ts_type::ts_type_ann_to_def; -use super::ts_type::TsTypeDef; -use super::ts_type_param::maybe_type_param_decl_to_type_param_defs; -use super::ts_type_param::TsTypeParamDef; -use super::ParamDef; -use serde::Serialize; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct FunctionDef { - pub params: Vec, - pub return_type: Option, - pub is_async: bool, - pub is_generator: bool, - pub type_params: Vec, - // TODO(bartlomieju): decorators -} - -pub fn function_to_function_def( - doc_parser: &DocParser, - function: &swc_ecmascript::ast::Function, -) -> FunctionDef { - let mut params = vec![]; - - for param in &function.params { - let param_def = - pat_to_param_def(¶m.pat, Some(&doc_parser.ast_parser.source_map)); - params.push(param_def); - } - - let maybe_return_type = function - .return_type - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - let type_params = - maybe_type_param_decl_to_type_param_defs(function.type_params.as_ref()); - - FunctionDef { - params, - return_type: maybe_return_type, - is_async: function.is_async, - is_generator: function.is_generator, - type_params, - } -} - -pub fn get_doc_for_fn_decl( - doc_parser: &DocParser, - fn_decl: &swc_ecmascript::ast::FnDecl, -) -> (String, FunctionDef) { - let name = fn_decl.ident.sym.to_string(); - let fn_def = function_to_function_def(&doc_parser, &fn_decl.function); - (name, fn_def) -} diff --git a/cli/doc/interface.rs b/cli/doc/interface.rs deleted file mode 100644 index 3c72bac23a..0000000000 --- a/cli/doc/interface.rs +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::colors; -use crate::doc::display::{display_optional, display_readonly, SliceDisplayer}; -use serde::Serialize; - -use super::params::ts_fn_param_to_param_def; -use super::parser::DocParser; -use super::ts_type::ts_type_ann_to_def; -use super::ts_type::TsTypeDef; -use super::ts_type_param::maybe_type_param_decl_to_type_param_defs; -use super::ts_type_param::TsTypeParamDef; -use super::Location; -use super::ParamDef; - -use std::fmt::{Display, Formatter, Result as FmtResult}; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct InterfaceMethodDef { - pub name: String, - pub location: Location, - pub js_doc: Option, - pub optional: bool, - pub params: Vec, - pub return_type: Option, - pub type_params: Vec, -} - -impl Display for InterfaceMethodDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!( - f, - "{}{}({})", - colors::bold(&self.name), - display_optional(self.optional), - 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 InterfacePropertyDef { - pub name: String, - pub location: Location, - pub js_doc: Option, - pub params: Vec, - pub computed: bool, - pub optional: bool, - pub ts_type: Option, - pub type_params: Vec, -} - -impl Display for InterfacePropertyDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!( - f, - "{}{}", - colors::bold(&self.name), - display_optional(self.optional), - )?; - if let Some(ts_type) = &self.ts_type { - write!(f, ": {}", ts_type)?; - } - Ok(()) - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct InterfaceIndexSignatureDef { - pub readonly: bool, - pub params: Vec, - pub ts_type: Option, -} - -impl Display for InterfaceIndexSignatureDef { - 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 InterfaceCallSignatureDef { - pub location: Location, - pub js_doc: Option, - pub params: Vec, - pub ts_type: Option, - pub type_params: Vec, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct InterfaceDef { - pub extends: Vec, - pub methods: Vec, - pub properties: Vec, - pub call_signatures: Vec, - pub index_signatures: Vec, - pub type_params: Vec, -} - -pub fn expr_to_name(expr: &swc_ecmascript::ast::Expr) -> String { - use swc_ecmascript::ast::Expr::*; - use swc_ecmascript::ast::ExprOrSuper::*; - - match expr { - Ident(ident) => ident.sym.to_string(), - Member(member_expr) => { - let left = match &member_expr.obj { - Super(_) => "super".to_string(), - Expr(boxed_expr) => expr_to_name(&*boxed_expr), - }; - let right = expr_to_name(&*member_expr.prop); - format!("[{}.{}]", left, right) - } - _ => "".to_string(), - } -} - -pub fn get_doc_for_ts_interface_decl( - doc_parser: &DocParser, - interface_decl: &swc_ecmascript::ast::TsInterfaceDecl, -) -> (String, InterfaceDef) { - let interface_name = interface_decl.id.sym.to_string(); - - let mut methods = vec![]; - let mut properties = vec![]; - let mut call_signatures = vec![]; - let mut index_signatures = vec![]; - - for type_element in &interface_decl.body.body { - use swc_ecmascript::ast::TsTypeElement::*; - - match &type_element { - TsMethodSignature(ts_method_sig) => { - let method_js_doc = doc_parser.js_doc_for_span(ts_method_sig.span); - - let mut params = vec![]; - - for param in &ts_method_sig.params { - let param_def = ts_fn_param_to_param_def( - param, - Some(&doc_parser.ast_parser.source_map), - ); - params.push(param_def); - } - - let name = expr_to_name(&*ts_method_sig.key); - - let maybe_return_type = ts_method_sig - .type_ann - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_method_sig.type_params.as_ref(), - ); - - let method_def = InterfaceMethodDef { - name, - js_doc: method_js_doc, - location: doc_parser - .ast_parser - .get_span_location(ts_method_sig.span) - .into(), - optional: ts_method_sig.optional, - params, - return_type: maybe_return_type, - type_params, - }; - methods.push(method_def); - } - TsPropertySignature(ts_prop_sig) => { - let prop_js_doc = doc_parser.js_doc_for_span(ts_prop_sig.span); - let name = expr_to_name(&*ts_prop_sig.key); - - let mut params = vec![]; - - for param in &ts_prop_sig.params { - let param_def = ts_fn_param_to_param_def( - param, - Some(&doc_parser.ast_parser.source_map), - ); - params.push(param_def); - } - - let ts_type = ts_prop_sig - .type_ann - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_prop_sig.type_params.as_ref(), - ); - - let prop_def = InterfacePropertyDef { - name, - js_doc: prop_js_doc, - location: doc_parser - .ast_parser - .get_span_location(ts_prop_sig.span) - .into(), - params, - ts_type, - computed: ts_prop_sig.computed, - optional: ts_prop_sig.optional, - type_params, - }; - properties.push(prop_def); - } - TsCallSignatureDecl(ts_call_sig) => { - let call_sig_js_doc = doc_parser.js_doc_for_span(ts_call_sig.span); - - let mut params = vec![]; - for param in &ts_call_sig.params { - let param_def = ts_fn_param_to_param_def( - param, - Some(&doc_parser.ast_parser.source_map), - ); - params.push(param_def); - } - - let ts_type = ts_call_sig - .type_ann - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_call_sig.type_params.as_ref(), - ); - - let call_sig_def = InterfaceCallSignatureDef { - js_doc: call_sig_js_doc, - location: doc_parser - .ast_parser - .get_span_location(ts_call_sig.span) - .into(), - params, - ts_type, - type_params, - }; - 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 = InterfaceIndexSignatureDef { - readonly: ts_index_sig.readonly, - params, - ts_type, - }; - index_signatures.push(index_sig_def); - } - // TODO: - TsConstructSignatureDecl(_) => {} - } - } - - let type_params = maybe_type_param_decl_to_type_param_defs( - interface_decl.type_params.as_ref(), - ); - - let extends = interface_decl - .extends - .iter() - .map(|expr| expr.into()) - .collect::>(); - - let interface_def = InterfaceDef { - extends, - methods, - properties, - call_signatures, - index_signatures, - type_params, - }; - - (interface_name, interface_def) -} diff --git a/cli/doc/mod.rs b/cli/doc/mod.rs deleted file mode 100644 index d015d9e4c0..0000000000 --- a/cli/doc/mod.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -pub mod class; -mod display; -pub mod r#enum; -pub mod function; -pub mod interface; -pub mod module; -pub mod namespace; -mod node; -pub mod params; -pub mod parser; -pub mod printer; -pub mod ts_type; -pub mod ts_type_param; -pub mod type_alias; -pub mod variable; - -pub use node::DocNode; -pub use node::DocNodeKind; -pub use node::ImportDef; -pub use node::Location; -pub use params::ParamDef; -pub use parser::DocParser; -pub use printer::DocPrinter; - -#[cfg(test)] -mod tests; - -pub fn find_nodes_by_name_recursively( - doc_nodes: Vec, - name: String, -) -> Vec { - 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 = vec![]; - match leftover { - Some(leftover) => { - for node in doc_nodes { - let children = find_children_by_name(node, leftover.to_string()); - found.extend(children); - } - found - } - None => doc_nodes, - } -} - -fn find_nodes_by_name(doc_nodes: Vec, name: String) -> Vec { - let mut found: Vec = vec![]; - for node in doc_nodes { - if node.name == name { - found.push(node); - } - } - found -} - -fn find_children_by_name(node: DocNode, name: String) -> Vec { - match node.kind { - DocNodeKind::Namespace => { - let namespace_def = node.namespace_def.unwrap(); - find_nodes_by_name_recursively(namespace_def.elements, name) - } - // TODO(#4516) handle class, interface etc... - _ => vec![], - } -} diff --git a/cli/doc/module.rs b/cli/doc/module.rs deleted file mode 100644 index 69effdde8b..0000000000 --- a/cli/doc/module.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use swc_common::Spanned; - -use super::parser::DocParser; -use super::DocNode; - -pub fn get_doc_node_for_export_decl( - doc_parser: &DocParser, - export_decl: &swc_ecmascript::ast::ExportDecl, -) -> DocNode { - let export_span = export_decl.span(); - use swc_ecmascript::ast::Decl; - - let js_doc = doc_parser.js_doc_for_span(export_span); - let location = doc_parser.ast_parser.get_span_location(export_span).into(); - - match &export_decl.decl { - Decl::Class(class_decl) => { - let (name, class_def) = - super::class::get_doc_for_class_decl(doc_parser, class_decl); - DocNode::class(name, location, js_doc, class_def) - } - Decl::Fn(fn_decl) => { - let (name, function_def) = - super::function::get_doc_for_fn_decl(doc_parser, fn_decl); - DocNode::function(name, location, js_doc, function_def) - } - Decl::Var(var_decl) => { - let (name, var_def) = super::variable::get_doc_for_var_decl(var_decl); - DocNode::variable(name, location, js_doc, var_def) - } - Decl::TsInterface(ts_interface_decl) => { - let (name, interface_def) = - super::interface::get_doc_for_ts_interface_decl( - doc_parser, - ts_interface_decl, - ); - DocNode::interface(name, location, js_doc, interface_def) - } - Decl::TsTypeAlias(ts_type_alias) => { - let (name, type_alias_def) = - super::type_alias::get_doc_for_ts_type_alias_decl( - doc_parser, - ts_type_alias, - ); - DocNode::type_alias(name, location, js_doc, type_alias_def) - } - Decl::TsEnum(ts_enum) => { - let (name, enum_def) = - super::r#enum::get_doc_for_ts_enum_decl(doc_parser, ts_enum); - DocNode::r#enum(name, location, js_doc, enum_def) - } - Decl::TsModule(ts_module) => { - let (name, namespace_def) = - super::namespace::get_doc_for_ts_module(doc_parser, ts_module); - DocNode::namespace(name, location, js_doc, namespace_def) - } - } -} diff --git a/cli/doc/namespace.rs b/cli/doc/namespace.rs deleted file mode 100644 index 7bb3903aec..0000000000 --- a/cli/doc/namespace.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use serde::Serialize; - -use super::parser::DocParser; -use super::DocNode; - -#[derive(Debug, Serialize, Clone)] -pub struct NamespaceDef { - pub elements: Vec, -} - -pub fn get_doc_for_ts_namespace_decl( - doc_parser: &DocParser, - ts_namespace_decl: &swc_ecmascript::ast::TsNamespaceDecl, -) -> DocNode { - let js_doc = doc_parser.js_doc_for_span(ts_namespace_decl.span); - let location = doc_parser - .ast_parser - .get_span_location(ts_namespace_decl.span) - .into(); - let namespace_name = ts_namespace_decl.id.sym.to_string(); - - use swc_ecmascript::ast::TsNamespaceBody::*; - - let elements = match &*ts_namespace_decl.body { - TsModuleBlock(ts_module_block) => { - doc_parser.get_doc_nodes_for_module_body(ts_module_block.body.clone()) - } - TsNamespaceDecl(ts_namespace_decl) => { - vec![get_doc_for_ts_namespace_decl(doc_parser, ts_namespace_decl)] - } - }; - - let ns_def = NamespaceDef { elements }; - - DocNode::namespace(namespace_name, location, js_doc, ns_def) -} - -pub fn get_doc_for_ts_module( - doc_parser: &DocParser, - ts_module_decl: &swc_ecmascript::ast::TsModuleDecl, -) -> (String, NamespaceDef) { - use swc_ecmascript::ast::TsModuleName; - let namespace_name = match &ts_module_decl.id { - TsModuleName::Ident(ident) => ident.sym.to_string(), - TsModuleName::Str(str_) => str_.value.to_string(), - }; - - let elements = if let Some(body) = &ts_module_decl.body { - use swc_ecmascript::ast::TsNamespaceBody::*; - - match &body { - TsModuleBlock(ts_module_block) => { - doc_parser.get_doc_nodes_for_module_body(ts_module_block.body.clone()) - } - TsNamespaceDecl(ts_namespace_decl) => { - vec![get_doc_for_ts_namespace_decl(doc_parser, ts_namespace_decl)] - } - } - } else { - vec![] - }; - - let ns_def = NamespaceDef { elements }; - - (namespace_name, ns_def) -} diff --git a/cli/doc/node.rs b/cli/doc/node.rs deleted file mode 100644 index 226fdc8fa4..0000000000 --- a/cli/doc/node.rs +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use serde::Serialize; - -#[derive(Debug, PartialEq, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub enum DocNodeKind { - Function, - Variable, - Class, - Enum, - Interface, - TypeAlias, - Namespace, - Import, -} - -#[derive(Debug, Serialize, Clone, PartialEq)] -pub struct Location { - pub filename: String, - pub line: usize, - pub col: usize, -} - -impl Into for swc_common::Loc { - fn into(self) -> Location { - use swc_common::FileName::*; - - let filename = match &self.file.name { - Real(path_buf) => path_buf.to_string_lossy().to_string(), - Custom(str_) => str_.to_string(), - _ => panic!("invalid filename"), - }; - - Location { - filename, - line: self.line, - col: self.col_display, - } - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub enum ReexportKind { - /// export * from "./path/to/module.js"; - All, - /// export * as someNamespace from "./path/to/module.js"; - Namespace(String), - /// export default from "./path/to/module.js"; - Default, - /// (identifier, optional alias) - /// export { foo } from "./path/to/module.js"; - /// export { foo as bar } from "./path/to/module.js"; - Named(String, Option), -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct Reexport { - pub kind: ReexportKind, - pub src: String, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct ModuleDoc { - pub definitions: Vec, - pub reexports: Vec, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct ImportDef { - pub src: String, - pub imported: Option, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct DocNode { - pub kind: DocNodeKind, - pub name: String, - pub location: Location, - pub js_doc: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub function_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub variable_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub enum_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub class_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub type_alias_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub namespace_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub interface_def: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub import_def: Option, -} - -impl DocNode { - pub fn function( - name: String, - location: Location, - js_doc: Option, - fn_def: super::function::FunctionDef, - ) -> Self { - Self { - kind: DocNodeKind::Function, - name, - location, - js_doc, - function_def: Some(fn_def), - variable_def: None, - enum_def: None, - class_def: None, - type_alias_def: None, - namespace_def: None, - interface_def: None, - import_def: None, - } - } - - pub fn variable( - name: String, - location: Location, - js_doc: Option, - var_def: super::variable::VariableDef, - ) -> Self { - Self { - kind: DocNodeKind::Variable, - name, - location, - js_doc, - function_def: None, - variable_def: Some(var_def), - enum_def: None, - class_def: None, - type_alias_def: None, - namespace_def: None, - interface_def: None, - import_def: None, - } - } - - pub fn r#enum( - name: String, - location: Location, - js_doc: Option, - enum_def: super::r#enum::EnumDef, - ) -> Self { - Self { - kind: DocNodeKind::Enum, - name, - location, - js_doc, - function_def: None, - variable_def: None, - enum_def: Some(enum_def), - class_def: None, - type_alias_def: None, - namespace_def: None, - interface_def: None, - import_def: None, - } - } - - pub fn class( - name: String, - location: Location, - js_doc: Option, - class_def: super::class::ClassDef, - ) -> Self { - Self { - kind: DocNodeKind::Class, - name, - location, - js_doc, - function_def: None, - variable_def: None, - enum_def: None, - class_def: Some(class_def), - type_alias_def: None, - namespace_def: None, - interface_def: None, - import_def: None, - } - } - - pub fn type_alias( - name: String, - location: Location, - js_doc: Option, - type_alias_def: super::type_alias::TypeAliasDef, - ) -> Self { - Self { - kind: DocNodeKind::TypeAlias, - name, - location, - js_doc, - function_def: None, - variable_def: None, - enum_def: None, - class_def: None, - type_alias_def: Some(type_alias_def), - namespace_def: None, - interface_def: None, - import_def: None, - } - } - - pub fn namespace( - name: String, - location: Location, - js_doc: Option, - namespace_def: super::namespace::NamespaceDef, - ) -> Self { - Self { - kind: DocNodeKind::Namespace, - name, - location, - js_doc, - function_def: None, - variable_def: None, - enum_def: None, - class_def: None, - type_alias_def: None, - namespace_def: Some(namespace_def), - interface_def: None, - import_def: None, - } - } - - pub fn interface( - name: String, - location: Location, - js_doc: Option, - interface_def: super::interface::InterfaceDef, - ) -> Self { - Self { - kind: DocNodeKind::Interface, - name, - location, - js_doc, - function_def: None, - variable_def: None, - enum_def: None, - class_def: None, - type_alias_def: None, - namespace_def: None, - interface_def: Some(interface_def), - import_def: None, - } - } - - pub fn import( - name: String, - location: Location, - js_doc: Option, - import_def: ImportDef, - ) -> Self { - Self { - kind: DocNodeKind::Import, - name, - location, - js_doc, - function_def: None, - variable_def: None, - enum_def: None, - class_def: None, - type_alias_def: None, - namespace_def: None, - interface_def: None, - import_def: Some(import_def), - } - } -} diff --git a/cli/doc/params.rs b/cli/doc/params.rs deleted file mode 100644 index 088a4e2837..0000000000 --- a/cli/doc/params.rs +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use super::display::{display_optional, SliceDisplayer}; -use super::ts_type::{ts_type_ann_to_def, TsTypeDef}; -use serde::Serialize; -use std::fmt::{Display, Formatter, Result as FmtResult}; -use swc_common::SourceMap; -use swc_ecmascript::ast::{ObjectPatProp, Pat, TsFnParam}; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -#[serde(tag = "kind")] -pub enum ParamDef { - #[serde(rename_all = "camelCase")] - Array { - elements: Vec>, - optional: bool, - ts_type: Option, - }, - #[serde(rename_all = "camelCase")] - Assign { - left: Box, - right: String, - ts_type: Option, - }, - #[serde(rename_all = "camelCase")] - Identifier { - name: String, - optional: bool, - ts_type: Option, - }, - #[serde(rename_all = "camelCase")] - Object { - props: Vec, - optional: bool, - ts_type: Option, - }, - #[serde(rename_all = "camelCase")] - Rest { - arg: Box, - ts_type: Option, - }, -} - -impl Display for ParamDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - match self { - Self::Array { - elements, - optional, - ts_type, - } => { - write!(f, "[")?; - if !elements.is_empty() { - if let Some(v) = &elements[0] { - write!(f, "{}", v)?; - } - for maybe_v in &elements[1..] { - write!(f, ", ")?; - if let Some(v) = maybe_v { - write!(f, "{}", v)?; - } - } - } - write!(f, "]")?; - write!(f, "{}", display_optional(*optional))?; - if let Some(ts_type) = ts_type { - write!(f, ": {}", ts_type)?; - } - Ok(()) - } - Self::Assign { left, ts_type, .. } => { - write!(f, "{}", left)?; - if let Some(ts_type) = ts_type { - write!(f, ": {}", ts_type)?; - } - // TODO(SyrupThinker) As we cannot display expressions the value is just omitted - // write!(f, " = {}", right)?; - Ok(()) - } - Self::Identifier { - name, - optional, - ts_type, - } => { - write!(f, "{}{}", name, display_optional(*optional))?; - if let Some(ts_type) = ts_type { - write!(f, ": {}", ts_type)?; - } - Ok(()) - } - Self::Object { - props, - optional, - ts_type, - } => { - write!( - f, - "{{{}}}{}", - SliceDisplayer::new(&props, ", ", false), - display_optional(*optional) - )?; - if let Some(ts_type) = ts_type { - write!(f, ": {}", ts_type)?; - } - Ok(()) - } - Self::Rest { arg, ts_type } => { - write!(f, "...{}", arg)?; - if let Some(ts_type) = ts_type { - write!(f, ": {}", ts_type)?; - } - Ok(()) - } - } - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -#[serde(tag = "kind")] -pub enum ObjectPatPropDef { - Assign { key: String, value: Option }, - KeyValue { key: String, value: Box }, - Rest { arg: Box }, -} - -impl Display for ObjectPatPropDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - match self { - Self::KeyValue { key, .. } => { - // The internal identifier does not need to be exposed - write!(f, "{}", key) - } - Self::Assign { key, value } => { - if let Some(_value) = value { - // TODO(SyrupThinker) As we cannot display expressions the value is just omitted - write!(f, "{}", key) - } else { - write!(f, "{}", key) - } - } - Self::Rest { arg } => write!(f, "...{}", arg), - } - } -} - -pub fn ident_to_param_def( - ident: &swc_ecmascript::ast::Ident, - _source_map: Option<&SourceMap>, -) -> ParamDef { - let ts_type = ident.type_ann.as_ref().map(|rt| ts_type_ann_to_def(rt)); - - ParamDef::Identifier { - name: ident.sym.to_string(), - optional: ident.optional, - ts_type, - } -} - -fn rest_pat_to_param_def( - rest_pat: &swc_ecmascript::ast::RestPat, - source_map: Option<&SourceMap>, -) -> ParamDef { - let ts_type = rest_pat.type_ann.as_ref().map(|rt| ts_type_ann_to_def(rt)); - - ParamDef::Rest { - arg: Box::new(pat_to_param_def(&*rest_pat.arg, source_map)), - ts_type, - } -} - -fn object_pat_prop_to_def( - object_pat_prop: &ObjectPatProp, - source_map: Option<&SourceMap>, -) -> ObjectPatPropDef { - match object_pat_prop { - ObjectPatProp::Assign(assign) => ObjectPatPropDef::Assign { - key: assign.key.sym.to_string(), - value: assign.value.as_ref().map(|_| "".to_string()), - }, - ObjectPatProp::KeyValue(keyvalue) => ObjectPatPropDef::KeyValue { - key: prop_name_to_string(&keyvalue.key, source_map), - value: Box::new(pat_to_param_def(&*keyvalue.value, source_map)), - }, - ObjectPatProp::Rest(rest) => ObjectPatPropDef::Rest { - arg: Box::new(pat_to_param_def(&*rest.arg, source_map)), - }, - } -} - -fn object_pat_to_param_def( - object_pat: &swc_ecmascript::ast::ObjectPat, - source_map: Option<&SourceMap>, -) -> ParamDef { - let props = object_pat - .props - .iter() - .map(|prop| object_pat_prop_to_def(prop, source_map)) - .collect::>(); - let ts_type = object_pat - .type_ann - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - ParamDef::Object { - props, - optional: object_pat.optional, - ts_type, - } -} - -fn array_pat_to_param_def( - array_pat: &swc_ecmascript::ast::ArrayPat, - source_map: Option<&SourceMap>, -) -> ParamDef { - let elements = array_pat - .elems - .iter() - .map(|elem| elem.as_ref().map(|e| pat_to_param_def(e, source_map))) - .collect::>>(); - let ts_type = array_pat.type_ann.as_ref().map(|rt| ts_type_ann_to_def(rt)); - - ParamDef::Array { - elements, - optional: array_pat.optional, - ts_type, - } -} - -pub fn assign_pat_to_param_def( - assign_pat: &swc_ecmascript::ast::AssignPat, - source_map: Option<&SourceMap>, -) -> ParamDef { - let ts_type = assign_pat - .type_ann - .as_ref() - .map(|rt| ts_type_ann_to_def(rt)); - - ParamDef::Assign { - left: Box::new(pat_to_param_def(&*assign_pat.left, source_map)), - right: "".to_string(), - ts_type, - } -} - -pub fn pat_to_param_def( - pat: &swc_ecmascript::ast::Pat, - source_map: Option<&SourceMap>, -) -> ParamDef { - match pat { - Pat::Ident(ident) => ident_to_param_def(ident, source_map), - Pat::Array(array_pat) => array_pat_to_param_def(array_pat, source_map), - Pat::Rest(rest_pat) => rest_pat_to_param_def(rest_pat, source_map), - Pat::Object(object_pat) => object_pat_to_param_def(object_pat, source_map), - Pat::Assign(assign_pat) => assign_pat_to_param_def(assign_pat, source_map), - _ => unreachable!(), - } -} - -pub fn ts_fn_param_to_param_def( - ts_fn_param: &swc_ecmascript::ast::TsFnParam, - source_map: Option<&SourceMap>, -) -> ParamDef { - match ts_fn_param { - TsFnParam::Ident(ident) => ident_to_param_def(ident, source_map), - TsFnParam::Array(array_pat) => { - array_pat_to_param_def(array_pat, source_map) - } - TsFnParam::Rest(rest_pat) => rest_pat_to_param_def(rest_pat, source_map), - TsFnParam::Object(object_pat) => { - object_pat_to_param_def(object_pat, source_map) - } - } -} - -pub fn prop_name_to_string( - prop_name: &swc_ecmascript::ast::PropName, - source_map: Option<&SourceMap>, -) -> String { - use swc_ecmascript::ast::PropName; - match prop_name { - PropName::Ident(ident) => ident.sym.to_string(), - PropName::Str(str_) => str_.value.to_string(), - PropName::Num(num) => num.value.to_string(), - PropName::Computed(comp_prop_name) => source_map - .map(|sm| sm.span_to_snippet(comp_prop_name.span).unwrap()) - .unwrap_or_else(|| "".to_string()), - } -} diff --git a/cli/doc/parser.rs b/cli/doc/parser.rs deleted file mode 100644 index 8950ad74bf..0000000000 --- a/cli/doc/parser.rs +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::file_fetcher::map_file_extension; -use crate::op_error::OpError; -use crate::swc_util::AstParser; -use swc_common::comments::CommentKind; -use swc_common::Span; -use swc_ecmascript::ast::Decl; -use swc_ecmascript::ast::DefaultDecl; -use swc_ecmascript::ast::ModuleDecl; -use swc_ecmascript::ast::Stmt; - -use deno_core::ErrBox; -use deno_core::ModuleSpecifier; -use futures::Future; -use regex::Regex; -use std::collections::HashMap; -use std::path::PathBuf; -use std::pin::Pin; - -use super::namespace::NamespaceDef; -use super::node; -use super::node::ModuleDoc; -use super::DocNode; -use super::DocNodeKind; -use super::ImportDef; -use super::Location; - -pub trait DocFileLoader { - fn resolve( - &self, - specifier: &str, - referrer: &str, - ) -> Result { - ModuleSpecifier::resolve_import(specifier, referrer).map_err(OpError::from) - } - - fn load_source_code( - &self, - specifier: &str, - ) -> Pin>>>; -} - -pub struct DocParser { - pub ast_parser: AstParser, - pub loader: Box, - pub private: bool, -} - -impl DocParser { - pub fn new(loader: Box, private: bool) -> Self { - DocParser { - loader, - ast_parser: AstParser::default(), - private, - } - } - - fn parse_module( - &self, - file_name: &str, - source_code: &str, - ) -> Result { - let media_type = map_file_extension(&PathBuf::from(file_name)); - let parse_result = - self - .ast_parser - .parse_module(file_name, media_type, source_code); - let module = parse_result?; - let mut doc_entries = - self.get_doc_nodes_for_module_body(module.body.clone()); - let import_doc_entries = - self.get_doc_nodes_for_module_imports(module.body.clone(), file_name)?; - doc_entries.extend(import_doc_entries); - let reexports = self.get_reexports_for_module_body(module.body); - let module_doc = ModuleDoc { - definitions: doc_entries, - reexports, - }; - Ok(module_doc) - } - - pub async fn parse(&self, file_name: &str) -> Result, ErrBox> { - let source_code = self.loader.load_source_code(file_name).await?; - - self.parse_source(file_name, source_code.as_str()) - } - - pub fn parse_source( - &self, - file_name: &str, - source_code: &str, - ) -> Result, ErrBox> { - let module_doc = self.parse_module(file_name, &source_code)?; - Ok(module_doc.definitions) - } - - async fn flatten_reexports( - &self, - reexports: &[node::Reexport], - referrer: &str, - ) -> Result, ErrBox> { - let mut by_src: HashMap> = HashMap::new(); - - let mut processed_reexports: Vec = vec![]; - - for reexport in reexports { - if by_src.get(&reexport.src).is_none() { - by_src.insert(reexport.src.to_string(), vec![]); - } - - let bucket = by_src.get_mut(&reexport.src).unwrap(); - bucket.push(reexport.clone()); - } - - for specifier in by_src.keys() { - let resolved_specifier = self.loader.resolve(specifier, referrer)?; - let doc_nodes = self.parse(&resolved_specifier.to_string()).await?; - let reexports_for_specifier = by_src.get(specifier).unwrap(); - - for reexport in reexports_for_specifier { - match &reexport.kind { - node::ReexportKind::All => { - processed_reexports.extend(doc_nodes.clone()) - } - node::ReexportKind::Namespace(ns_name) => { - let ns_def = NamespaceDef { - elements: doc_nodes.clone(), - }; - let ns_doc_node = DocNode { - kind: DocNodeKind::Namespace, - name: ns_name.to_string(), - location: Location { - filename: specifier.to_string(), - line: 1, - col: 0, - }, - js_doc: None, - namespace_def: Some(ns_def), - enum_def: None, - type_alias_def: None, - interface_def: None, - variable_def: None, - function_def: None, - class_def: None, - import_def: None, - }; - processed_reexports.push(ns_doc_node); - } - node::ReexportKind::Named(ident, maybe_alias) => { - // Try to find reexport. - // NOTE: the reexport might actually be reexport from another - // module; for now we're skipping nested reexports. - let maybe_doc_node = - doc_nodes.iter().find(|node| &node.name == ident); - - if let Some(doc_node) = maybe_doc_node { - let doc_node = doc_node.clone(); - let doc_node = if let Some(alias) = maybe_alias { - DocNode { - name: alias.to_string(), - ..doc_node - } - } else { - doc_node - }; - - processed_reexports.push(doc_node); - } - } - node::ReexportKind::Default => { - // TODO: handle default export from child module - } - } - } - } - - Ok(processed_reexports) - } - - pub async fn parse_with_reexports( - &self, - file_name: &str, - ) -> Result, ErrBox> { - let source_code = self.loader.load_source_code(file_name).await?; - - let module_doc = self.parse_module(file_name, &source_code)?; - - let flattened_docs = if !module_doc.reexports.is_empty() { - let mut flattenned_reexports = self - .flatten_reexports(&module_doc.reexports, file_name) - .await?; - flattenned_reexports.extend(module_doc.definitions); - flattenned_reexports - } else { - module_doc.definitions - }; - - Ok(flattened_docs) - } - - fn get_doc_nodes_for_module_imports( - &self, - module_body: Vec, - referrer: &str, - ) -> Result, ErrBox> { - let mut imports = vec![]; - - for node in module_body.iter() { - if let swc_ecmascript::ast::ModuleItem::ModuleDecl(module_decl) = node { - if let ModuleDecl::Import(import_decl) = module_decl { - let (js_doc, location) = self.details_for_span(import_decl.span); - for specifier in &import_decl.specifiers { - use swc_ecmascript::ast::ImportSpecifier::*; - - let (name, maybe_imported_name, src) = match specifier { - Named(named_specifier) => ( - named_specifier.local.sym.to_string(), - named_specifier - .imported - .as_ref() - .map(|ident| ident.sym.to_string()) - .or_else(|| Some(named_specifier.local.sym.to_string())), - import_decl.src.value.to_string(), - ), - Default(default_specifier) => ( - default_specifier.local.sym.to_string(), - Some("default".to_string()), - import_decl.src.value.to_string(), - ), - Namespace(namespace_specifier) => ( - namespace_specifier.local.sym.to_string(), - None, - import_decl.src.value.to_string(), - ), - }; - - let resolved_specifier = self.loader.resolve(&src, referrer)?; - let import_def = ImportDef { - src: resolved_specifier.to_string(), - imported: maybe_imported_name, - }; - - let doc_node = DocNode::import( - name, - location.clone(), - js_doc.clone(), - import_def, - ); - - imports.push(doc_node); - } - } - } - } - - Ok(imports) - } - - pub fn get_doc_nodes_for_module_exports( - &self, - module_decl: &ModuleDecl, - ) -> Vec { - match module_decl { - ModuleDecl::ExportDecl(export_decl) => { - vec![super::module::get_doc_node_for_export_decl( - self, - export_decl, - )] - } - ModuleDecl::ExportDefaultDecl(export_default_decl) => { - let (js_doc, location) = - self.details_for_span(export_default_decl.span); - let name = "default".to_string(); - - let doc_node = match &export_default_decl.decl { - DefaultDecl::Class(class_expr) => { - let class_def = - crate::doc::class::class_to_class_def(self, &class_expr.class); - DocNode::class(name, location, js_doc, class_def) - } - DefaultDecl::Fn(fn_expr) => { - let function_def = crate::doc::function::function_to_function_def( - self, - &fn_expr.function, - ); - DocNode::function(name, location, js_doc, function_def) - } - DefaultDecl::TsInterfaceDecl(interface_decl) => { - let (_, interface_def) = - crate::doc::interface::get_doc_for_ts_interface_decl( - self, - interface_decl, - ); - DocNode::interface(name, location, js_doc, interface_def) - } - }; - - vec![doc_node] - } - ModuleDecl::ExportDefaultExpr(_export_default_expr) => vec![], - _ => vec![], - } - } - - pub fn get_doc_node_for_stmt(&self, stmt: &Stmt) -> Option { - match stmt { - Stmt::Decl(decl) => self.get_doc_node_for_decl(decl), - _ => None, - } - } - - fn details_for_span(&self, span: Span) -> (Option, Location) { - let js_doc = self.js_doc_for_span(span); - let location = self.ast_parser.get_span_location(span).into(); - (js_doc, location) - } - - pub fn get_doc_node_for_decl(&self, decl: &Decl) -> Option { - match decl { - Decl::Class(class_decl) => { - if !self.private && !class_decl.declare { - return None; - } - let (name, class_def) = - super::class::get_doc_for_class_decl(self, class_decl); - let (js_doc, location) = self.details_for_span(class_decl.class.span); - Some(DocNode::class(name, location, js_doc, class_def)) - } - Decl::Fn(fn_decl) => { - if !self.private && !fn_decl.declare { - return None; - } - let (name, function_def) = - super::function::get_doc_for_fn_decl(self, fn_decl); - let (js_doc, location) = self.details_for_span(fn_decl.function.span); - Some(DocNode::function(name, location, js_doc, function_def)) - } - Decl::Var(var_decl) => { - if !self.private && !var_decl.declare { - return None; - } - let (name, var_def) = super::variable::get_doc_for_var_decl(var_decl); - let (js_doc, location) = self.details_for_span(var_decl.span); - Some(DocNode::variable(name, location, js_doc, var_def)) - } - Decl::TsInterface(ts_interface_decl) => { - if !self.private && !ts_interface_decl.declare { - return None; - } - let (name, interface_def) = - super::interface::get_doc_for_ts_interface_decl( - self, - ts_interface_decl, - ); - let (js_doc, location) = self.details_for_span(ts_interface_decl.span); - Some(DocNode::interface(name, location, js_doc, interface_def)) - } - Decl::TsTypeAlias(ts_type_alias) => { - if !self.private && !ts_type_alias.declare { - return None; - } - let (name, type_alias_def) = - super::type_alias::get_doc_for_ts_type_alias_decl( - self, - ts_type_alias, - ); - let (js_doc, location) = self.details_for_span(ts_type_alias.span); - Some(DocNode::type_alias(name, location, js_doc, type_alias_def)) - } - Decl::TsEnum(ts_enum) => { - if !self.private && !ts_enum.declare { - return None; - } - let (name, enum_def) = - super::r#enum::get_doc_for_ts_enum_decl(self, ts_enum); - let (js_doc, location) = self.details_for_span(ts_enum.span); - Some(DocNode::r#enum(name, location, js_doc, enum_def)) - } - Decl::TsModule(ts_module) => { - if !self.private && !ts_module.declare { - return None; - } - let (name, namespace_def) = - super::namespace::get_doc_for_ts_module(self, ts_module); - let (js_doc, location) = self.details_for_span(ts_module.span); - Some(DocNode::namespace(name, location, js_doc, namespace_def)) - } - } - } - - pub fn get_reexports_for_module_body( - &self, - module_body: Vec, - ) -> Vec { - use swc_ecmascript::ast::ExportSpecifier::*; - - let mut reexports: Vec = vec![]; - - for node in module_body.iter() { - if let swc_ecmascript::ast::ModuleItem::ModuleDecl(module_decl) = node { - let r = match module_decl { - ModuleDecl::ExportNamed(named_export) => { - if let Some(src) = &named_export.src { - let src_str = src.value.to_string(); - named_export - .specifiers - .iter() - .map(|export_specifier| match export_specifier { - Namespace(ns_export) => node::Reexport { - kind: node::ReexportKind::Namespace( - ns_export.name.sym.to_string(), - ), - src: src_str.to_string(), - }, - Default(_) => node::Reexport { - kind: node::ReexportKind::Default, - src: src_str.to_string(), - }, - Named(named_export) => { - let ident = named_export.orig.sym.to_string(); - let maybe_alias = - named_export.exported.as_ref().map(|e| e.sym.to_string()); - let kind = node::ReexportKind::Named(ident, maybe_alias); - node::Reexport { - kind, - src: src_str.to_string(), - } - } - }) - .collect::>() - } else { - vec![] - } - } - ModuleDecl::ExportAll(export_all) => { - let reexport = node::Reexport { - kind: node::ReexportKind::All, - src: export_all.src.value.to_string(), - }; - vec![reexport] - } - _ => vec![], - }; - - reexports.extend(r); - } - } - - reexports - } - - pub fn get_doc_nodes_for_module_body( - &self, - module_body: Vec, - ) -> Vec { - let mut doc_entries: Vec = vec![]; - for node in module_body.iter() { - match node { - swc_ecmascript::ast::ModuleItem::ModuleDecl(module_decl) => { - doc_entries - .extend(self.get_doc_nodes_for_module_exports(module_decl)); - } - swc_ecmascript::ast::ModuleItem::Stmt(stmt) => { - if let Some(doc_node) = self.get_doc_node_for_stmt(stmt) { - doc_entries.push(doc_node); - } - } - } - } - doc_entries - } - - pub fn js_doc_for_span(&self, span: Span) -> Option { - let comments = self.ast_parser.get_span_comments(span); - let js_doc_comment = comments.iter().rev().find(|comment| { - comment.kind == CommentKind::Block && comment.text.starts_with('*') - })?; - - let mut margin_pat = String::from(""); - if let Some(margin) = self.ast_parser.source_map.span_to_margin(span) { - for _ in 0..margin { - margin_pat.push(' '); - } - } - - let js_doc_re = Regex::new(r#" ?\* ?"#).unwrap(); - let txt = js_doc_comment - .text - .split('\n') - .map(|line| js_doc_re.replace(line, "").to_string()) - .map(|line| { - if line.starts_with(&margin_pat) { - line[margin_pat.len()..].to_string() - } else { - line - } - }) - .collect::>() - .join("\n"); - - let txt = txt.trim_start().trim_end().to_string(); - - Some(txt) - } -} diff --git a/cli/doc/printer.rs b/cli/doc/printer.rs deleted file mode 100644 index 01609d0e2b..0000000000 --- a/cli/doc/printer.rs +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. - -// TODO(ry) This module builds up output by appending to a string. Instead it -// should either use a formatting trait -// https://doc.rust-lang.org/std/fmt/index.html#formatting-traits -// Or perhaps implement a Serializer for serde -// https://docs.serde.rs/serde/ser/trait.Serializer.html - -// TODO(ry) The methods in this module take ownership of the DocNodes, this is -// unnecessary and can result in unnecessary copying. Instead they should take -// references. - -use crate::colors; -use crate::doc; -use crate::doc::display::{ - display_abstract, display_async, display_generator, Indent, SliceDisplayer, -}; -use crate::doc::DocNodeKind; -use std::fmt::{Display, Formatter, Result as FmtResult}; - -pub struct DocPrinter<'a> { - doc_nodes: &'a [doc::DocNode], - private: bool, -} - -impl<'a> DocPrinter<'a> { - pub fn new(doc_nodes: &[doc::DocNode], private: bool) -> DocPrinter { - DocPrinter { doc_nodes, private } - } - - pub fn format(&self, w: &mut Formatter<'_>) -> FmtResult { - self.format_(w, self.doc_nodes, 0) - } - - fn format_( - &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 - } - }); - - for node in &sorted { - 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)?; - } - writeln!(w)?; - - match node.kind { - DocNodeKind::Class => self.format_class(w, node)?, - DocNodeKind::Enum => self.format_enum(w, node)?, - DocNodeKind::Interface => self.format_interface(w, node)?, - DocNodeKind::Namespace => self.format_namespace(w, node)?, - _ => {} - } - } - - Ok(()) - } - - 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, - DocNodeKind::Import => 7, - } - } - - 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) - } - DocNodeKind::Namespace => { - self.format_namespace_signature(w, node, indent) - } - DocNodeKind::Import => Ok(()), - } - } - - // TODO(SyrupThinker) this should use a JSDoc parser - fn format_jsdoc( - &self, - w: &mut Formatter<'_>, - jsdoc: &str, - indent: i64, - ) -> FmtResult { - for line in jsdoc.lines() { - writeln!(w, "{}{}", Indent(indent), colors::gray(&line))?; - } - - Ok(()) - } - - fn format_class( - &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)?; - } - } - for node in class_def.properties.iter().filter(|node| { - self.private - || node - .accessibility - .unwrap_or(swc_ecmascript::ast::Accessibility::Public) - != swc_ecmascript::ast::Accessibility::Private - }) { - writeln!(w, "{}{}", Indent(1), node,)?; - if let Some(js_doc) = &node.js_doc { - self.format_jsdoc(w, &js_doc, 2)?; - } - } - for index_sign_def in &class_def.index_signatures { - writeln!(w, "{}{}", Indent(1), index_sign_def)?; - } - for node in class_def.methods.iter().filter(|node| { - self.private - || node - .accessibility - .unwrap_or(swc_ecmascript::ast::Accessibility::Public) - != swc_ecmascript::ast::Accessibility::Private - }) { - writeln!(w, "{}{}", Indent(1), node,)?; - if let Some(js_doc) = &node.js_doc { - self.format_jsdoc(w, js_doc, 2)?; - } - } - writeln!(w) - } - - fn format_enum( - &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))?; - } - writeln!(w) - } - - fn format_interface( - &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)?; - } - } - 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)?; - } - } - for index_sign_def in &interface_def.index_signatures { - writeln!(w, "{}{}", Indent(1), index_sign_def)?; - } - writeln!(w) - } - - fn format_namespace( - &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)?; - } - } - writeln!(w) - } - - 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) - )?; - } - - 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) - )?; - } - - if !class_def.implements.is_empty() { - write!( - w, - " {} {}", - colors::magenta("implements"), - SliceDisplayer::new(&class_def.implements, ", ", false) - )?; - } - - writeln!(w) - } - - 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) - ) - } - - 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) - } - - 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) - )?; - } - - writeln!(w) - } - - 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), - )?; - - if !type_alias_def.type_params.is_empty() { - write!( - w, - "<{}>", - SliceDisplayer::new(&type_alias_def.type_params, ", ", false) - )?; - } - - writeln!(w, " = {}", type_alias_def.ts_type) - } - - 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( - &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_ecmascript::ast::VarDeclKind::Const => "const", - swc_ecmascript::ast::VarDeclKind::Let => "let", - swc_ecmascript::ast::VarDeclKind::Var => "var", - }), - colors::bold(&node.name), - )?; - if let Some(ts_type) = &variable_def.ts_type { - write!(w, ": {}", ts_type)?; - } - writeln!(w) - } -} - -impl<'a> Display for DocPrinter<'a> { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - self.format(f) - } -} diff --git a/cli/doc/tests.rs b/cli/doc/tests.rs deleted file mode 100644 index 2faf617cc7..0000000000 --- a/cli/doc/tests.rs +++ /dev/null @@ -1,2002 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use super::DocParser; -use super::DocPrinter; -use crate::colors; -use serde_json::json; - -use super::parser::DocFileLoader; -use crate::op_error::OpError; -use std::collections::HashMap; - -use futures::Future; -use futures::FutureExt; -use std::pin::Pin; - -pub struct TestLoader { - files: HashMap, -} - -impl TestLoader { - pub fn new(files_vec: Vec<(String, String)>) -> Box { - let mut files = HashMap::new(); - - for file_tuple in files_vec { - files.insert(file_tuple.0, file_tuple.1); - } - - Box::new(Self { files }) - } -} - -impl DocFileLoader for TestLoader { - fn load_source_code( - &self, - specifier: &str, - ) -> Pin>>> { - let res = match self.files.get(specifier) { - Some(source_code) => Ok(source_code.to_string()), - None => Err(OpError::other("not found".to_string())), - }; - - async move { res }.boxed_local() - } -} - -macro_rules! doc_test { - ( $name:ident, $source:expr; $block:block ) => { - doc_test!($name, $source, false; $block); - }; - - ( $name:ident, $source:expr, private; $block:block ) => { - doc_test!($name, $source, true; $block); - }; - - ( $name:ident, $source:expr, $private:expr; $block:block ) => { - #[tokio::test] - async fn $name() { - let source_code = $source; - let private = $private; - - let loader = - TestLoader::new(vec![("test.ts".to_string(), source_code.to_string())]); - let entries = DocParser::new(loader, private) - .parse("test.ts") - .await - .unwrap(); - - let doc = DocPrinter::new(&entries, private).to_string(); - #[allow(unused_variables)] - let doc = colors::strip_ansi_codes(&doc); - - $block - } - }; -} - -macro_rules! contains_test { - ( $name:ident, $source:expr; - $( $contains:expr ),* $( ; $( $notcontains:expr ),* )? ) => { - contains_test!($name, $source, false; $($contains),* $(;$($notcontains),*)?); - }; - - ( $name:ident, $source:expr, private; - $( $contains:expr ),* $( ; $( $notcontains:expr ),* )? ) => { - contains_test!($name, $source, true; $($contains),* $(;$($notcontains),*)?); - }; - - ( $name:ident, $source:expr, $private:expr; - $( $contains:expr ),* $( ; $( $notcontains:expr ),* )? ) => { - doc_test!($name, $source, $private; { - $( - assert!(doc.contains($contains)); - )* - $( - $( - assert!(!doc.contains($notcontains)); - )* - )? - }); - }; -} - -macro_rules! json_test { - ( $name:ident, $source:expr; $json:tt ) => { - json_test!($name, $source, false; $json); - }; - - ( $name:ident, $source:expr, private; $json:tt ) => { - json_test!($name, $source, true; $json); - }; - - ( $name:ident, $source:expr, $private:expr; $json:tt ) => { - doc_test!($name, $source, $private; { - let actual = serde_json::to_value(&entries).unwrap(); - let expected_json = json!($json); - assert_eq!(actual, expected_json); - }); - }; -} - -#[tokio::test] -async fn reexports() { - let nested_reexport_source_code = r#" -/** - * JSDoc for bar - */ -export const bar = "bar"; - -export default 42; -"#; - let reexport_source_code = r#" -import { bar } from "./nested_reexport.ts"; - -/** - * JSDoc for const - */ -export const foo = "foo"; - -export const fizz = "fizz"; -"#; - let test_source_code = r#" -export { default, foo as fooConst } from "./reexport.ts"; -import { fizz as buzz } from "./reexport.ts"; - -/** JSDoc for function */ -export function fooFn(a: number) { - return a; -} -"#; - let loader = TestLoader::new(vec![ - ("file:///test.ts".to_string(), test_source_code.to_string()), - ( - "file:///reexport.ts".to_string(), - reexport_source_code.to_string(), - ), - ( - "file:///nested_reexport.ts".to_string(), - nested_reexport_source_code.to_string(), - ), - ]); - let entries = DocParser::new(loader, false) - .parse_with_reexports("file:///test.ts") - .await - .unwrap(); - assert_eq!(entries.len(), 3); - - let expected_json = json!([ - { - "kind": "variable", - "name": "fooConst", - "location": { - "filename": "file:///reexport.ts", - "line": 7, - "col": 0 - }, - "jsDoc": "JSDoc for const", - "variableDef": { - "tsType": null, - "kind": "const" - } - }, - { - "kind": "function", - "name": "fooFn", - "location": { - "filename": "file:///test.ts", - "line": 6, - "col": 0 - }, - "jsDoc": "JSDoc for function", - "functionDef": { - "params": [ - { - "name": "a", - "kind": "identifier", - "optional": false, - "tsType": { - "keyword": "number", - "kind": "keyword", - "repr": "number", - }, - } - ], - "typeParams": [], - "returnType": null, - "isAsync": false, - "isGenerator": false - }, - }, - { - "kind": "import", - "name": "buzz", - "location": { - "filename": "file:///test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": null, - "importDef": { - "src": "file:///reexport.ts", - "imported": "fizz", - } - } - ]); - let actual = serde_json::to_value(&entries).unwrap(); - assert_eq!(actual, expected_json); - - assert!(colors::strip_ansi_codes( - DocPrinter::new(&entries, false).to_string().as_str() - ) - .contains("function fooFn(a: number)")); -} - -#[tokio::test] -async fn filter_nodes_by_name() { - use super::find_nodes_by_name_recursively; - let source_code = r#" -export namespace Deno { - export class Buffer {} - export function test(options: object): void; - export function test(name: string, fn: Function): void; - export function test(name: string | object, fn?: Function): void {} -} - -export namespace Deno { - export namespace Inner { - export function a(): void {} - export const b = 100; - } -} -"#; - let loader = - TestLoader::new(vec![("test.ts".to_string(), source_code.to_string())]); - let entries = DocParser::new(loader, false) - .parse("test.ts") - .await - .unwrap(); - - let found = - find_nodes_by_name_recursively(entries.clone(), "Deno".to_string()); - assert_eq!(found.len(), 2); - assert_eq!(found[0].name, "Deno".to_string()); - assert_eq!(found[1].name, "Deno".to_string()); - - let found = - find_nodes_by_name_recursively(entries.clone(), "Deno.test".to_string()); - assert_eq!(found.len(), 3); - assert_eq!(found[0].name, "test".to_string()); - assert_eq!(found[1].name, "test".to_string()); - assert_eq!(found[2].name, "test".to_string()); - - let found = - find_nodes_by_name_recursively(entries.clone(), "Deno.Inner.a".to_string()); - assert_eq!(found.len(), 1); - assert_eq!(found[0].name, "a".to_string()); - - let found = - find_nodes_by_name_recursively(entries.clone(), "Deno.test.a".to_string()); - assert_eq!(found.len(), 0); - - let found = find_nodes_by_name_recursively(entries, "a.b.c".to_string()); - assert_eq!(found.len(), 0); -} - -mod serialization { - use super::*; - - json_test!(declare_namespace, - r#" -/** Namespace JSdoc */ -declare namespace RootNs { - declare const a = "a"; - - /** Nested namespace JSDoc */ - declare namespace NestedNs { - declare enum Foo { - a = 1, - b = 2, - c = 3, - } - } -} - "#; - [{ - "kind": "namespace", - "name": "RootNs", - "location": { - "filename": "test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": "Namespace JSdoc", - "namespaceDef": { - "elements": [ - { - "kind": "variable", - "name": "a", - "location": { - "filename": "test.ts", - "line": 4, - "col": 12 - }, - "jsDoc": null, - "variableDef": { - "tsType": null, - "kind": "const" - } - }, - { - "kind": "namespace", - "name": "NestedNs", - "location": { - "filename": "test.ts", - "line": 7, - "col": 4 - }, - "jsDoc": "Nested namespace JSDoc", - "namespaceDef": { - "elements": [ - { - "kind": "enum", - "name": "Foo", - "location": { - "filename": "test.ts", - "line": 8, - "col": 6 - }, - "jsDoc": null, - "enumDef": { - "members": [ - { - "name": "a" - }, - { - "name": "b" - }, - { - "name": "c" - } - ] - } - } - ] - } - } - ] - } - }]); - - json_test!(export_class, - r#" -/** Class doc */ -export class Foobar extends Fizz implements Buzz, Aldrin { - private private1?: boolean; - protected protected1: number; - public public1: boolean; - public2: number; - - /** Constructor js doc */ - constructor(name: string, private private2: number, protected protected2: number) {} - - /** Async foo method */ - async foo(): Promise { - // - } - - /** Sync bar method */ - bar?(): void { - // - } -} - "#; - [{ - "kind": "class", - "name": "Foobar", - "location": { - "filename": "test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": "Class doc", - "classDef": { - "isAbstract": false, - "extends": "Fizz", - "implements": [ - { - "repr": "Buzz", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "Buzz" - } - }, - { - "repr": "Aldrin", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "Aldrin" - } - } - ], - "typeParams": [], - "superTypeParams": [], - "constructors": [ - { - "jsDoc": "Constructor js doc", - "accessibility": null, - "name": "constructor", - "params": [ - { - "name": "name", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - } - }, - { - "name": "private2", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - }, - { - "name": "protected2", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - } - ], - "location": { - "filename": "test.ts", - "line": 10, - "col": 4 - } - } - ], - "properties": [ - { - "jsDoc": null, - "tsType": { - "repr": "boolean", - "kind": "keyword", - "keyword": "boolean" - }, - "readonly": false, - "accessibility": "private", - "optional": true, - "isAbstract": false, - "isStatic": false, - "name": "private1", - "location": { - "filename": "test.ts", - "line": 4, - "col": 4 - } - }, - { - "jsDoc": null, - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - }, - "readonly": false, - "accessibility": "protected", - "optional": false, - "isAbstract": false, - "isStatic": false, - "name": "protected1", - "location": { - "filename": "test.ts", - "line": 5, - "col": 4 - } - }, - { - "jsDoc": null, - "tsType": { - "repr": "boolean", - "kind": "keyword", - "keyword": "boolean" - }, - "readonly": false, - "accessibility": "public", - "optional": false, - "isAbstract": false, - "isStatic": false, - "name": "public1", - "location": { - "filename": "test.ts", - "line": 6, - "col": 4 - } - }, - { - "jsDoc": null, - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - }, - "readonly": false, - "accessibility": null, - "optional": false, - "isAbstract": false, - "isStatic": false, - "name": "public2", - "location": { - "filename": "test.ts", - "line": 7, - "col": 4 - } - } - ], - "indexSignatures": [], - "methods": [ - { - "jsDoc": "Async foo method", - "accessibility": null, - "optional": false, - "isAbstract": false, - "isStatic": false, - "name": "foo", - "kind": "method", - "functionDef": { - "params": [], - "returnType": { - "repr": "Promise", - "kind": "typeRef", - "typeRef": { - "typeParams": [ - { - "repr": "void", - "kind": "keyword", - "keyword": "void" - } - ], - "typeName": "Promise" - } - }, - "typeParams": [], - "isAsync": true, - "isGenerator": false - }, - "location": { - "filename": "test.ts", - "line": 13, - "col": 4 - } - }, - { - "jsDoc": "Sync bar method", - "accessibility": null, - "optional": true, - "isAbstract": false, - "isStatic": false, - "name": "bar", - "kind": "method", - "functionDef": { - "params": [], - "returnType": { - "repr": "void", - "kind": "keyword", - "keyword": "void" - }, - "isAsync": false, - "isGenerator": false, - "typeParams": [] - }, - "location": { - "filename": "test.ts", - "line": 18, - "col": 4 - } - } - ] - } - }]); - - json_test!(export_const, - r#" -/** Something about fizzBuzz */ -export const fizzBuzz = "fizzBuzz"; - -export const env: { - /** get doc */ - get(key: string): string | undefined; - - /** set doc */ - set(key: string, value: string): void; -} - "#; - [ - { - "kind":"variable", - "name":"fizzBuzz", - "location":{ - "filename":"test.ts", - "line":3, - "col":0 - }, - "jsDoc":"Something about fizzBuzz", - "variableDef":{ - "tsType":null, - "kind":"const" - } - }, - { - "kind":"variable", - "name":"env", - "location":{ - "filename":"test.ts", - "line":5, - "col":0 - }, - "jsDoc":null, - "variableDef":{ - "tsType":{ - "repr":"", - "kind":"typeLiteral", - "typeLiteral":{ - "methods":[{ - "name":"get", - "params":[ - { - "name":"key", - "kind":"identifier", - "optional":false, - "tsType":{ - "repr":"string", - "kind":"keyword", - "keyword":"string" - } - } - ], - "returnType":{ - "repr":"", - "kind":"union", - "union":[ - { - "repr":"string", - "kind":"keyword", - "keyword":"string" - }, - { - "repr":"undefined", - "kind":"keyword", - "keyword":"undefined" - } - ] - }, - "typeParams":[] - }, { - "name":"set", - "params":[ - { - "name":"key", - "kind":"identifier", - "optional":false, - "tsType":{ - "repr":"string", - "kind":"keyword", - "keyword":"string" - } - }, - { - "name":"value", - "kind":"identifier", - "optional":false, - "tsType":{ - "repr":"string", - "kind":"keyword", - "keyword":"string" - } - } - ], - "returnType":{ - "repr":"void", - "kind":"keyword", - "keyword":"void" - }, - "typeParams":[] - } - ], - "properties":[], - "callSignatures":[], - "indexSignatures": [] - } - }, - "kind":"const" - } - } - ] - ); - - json_test!(export_default_class, - r#" -/** Class doc */ -export default class Foobar { - /** Constructor js doc */ - constructor(name: string, private private2: number, protected protected2: number) {} -} - "#; - [{ - "kind": "class", - "name": "default", - "location": { - "filename": "test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": "Class doc", - "classDef": { - "isAbstract": false, - "extends": null, - "implements": [], - "typeParams": [], - "superTypeParams": [], - "constructors": [ - { - "jsDoc": "Constructor js doc", - "accessibility": null, - "name": "constructor", - "params": [ - { - "name": "name", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "string", - "kind": "keyword", - "keyword": "string" - } - }, - { - "name": "private2", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - }, - { - "name": "protected2", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - } - ], - "location": { - "filename": "test.ts", - "line": 5, - "col": 4 - } - } - ], - "properties": [], - "indexSignatures": [], - "methods": [] - } - }]); - - json_test!(export_default_fn, - r#" -export default function foo(a: number) { - return a; -} - "#; - [{ - "kind": "function", - "name": "default", - "location": { - "filename": "test.ts", - "line": 2, - "col": 15 - }, - "jsDoc": null, - "functionDef": { - "params": [ - { - "name": "a", - "kind": "identifier", - "optional": false, - "tsType": { - "keyword": "number", - "kind": "keyword", - "repr": "number", - }, - } - ], - "typeParams": [], - "returnType": null, - "isAsync": false, - "isGenerator": false - } - }]); - - json_test!(export_default_interface, - r#" -/** - * Interface js doc - */ -export default interface Reader { - /** Read n bytes */ - read?(buf: Uint8Array, something: unknown): Promise -} - "#; - [{ - "kind": "interface", - "name": "default", - "location": { - "filename": "test.ts", - "line": 5, - "col": 0 - }, - "jsDoc": "Interface js doc", - "interfaceDef": { - "extends": [], - "methods": [ - { - "name": "read", - "location": { - "filename": "test.ts", - "line": 7, - "col": 4 - }, - "optional": true, - "jsDoc": "Read n bytes", - "params": [ - { - "name": "buf", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "Uint8Array", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "Uint8Array" - } - } - }, - { - "name": "something", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "unknown", - "kind": "keyword", - "keyword": "unknown" - } - } - ], - "typeParams": [], - "returnType": { - "repr": "Promise", - "kind": "typeRef", - "typeRef": { - "typeParams": [ - { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - ], - "typeName": "Promise" - } - } - } - ], - "properties": [], - "callSignatures": [], - "indexSignatures": [], - "typeParams": [] - } - }]); - - json_test!(export_enum, - r#" -/** - * Some enum for good measure - */ -export enum Hello { - World = "world", - Fizz = "fizz", - Buzz = "buzz", -} - "#; - [{ - "kind": "enum", - "name": "Hello", - "location": { - "filename": "test.ts", - "line": 5, - "col": 0 - }, - "jsDoc": "Some enum for good measure", - "enumDef": { - "members": [ - { - "name": "World" - }, - { - "name": "Fizz" - }, - { - "name": "Buzz" - } - ] - } - }]); - - json_test!(export_fn, - r#"/** -* @module foo -*/ - -/** -* Hello there, this is a multiline JSdoc. -* -* It has many lines -* -* Or not that many? -*/ -export function foo(a: string, b?: number, cb: (...cbArgs: unknown[]) => void, ...args: unknown[]): void { - /** - * @todo document all the things. - */ - console.log("Hello world"); -} - "#; - [{ - "functionDef": { - "isAsync": false, - "isGenerator": false, - "typeParams": [], - "params": [ - { - "name": "a", - "kind": "identifier", - "optional": false, - "tsType": { - "keyword": "string", - "kind": "keyword", - "repr": "string", - }, - }, - { - "name": "b", - "kind": "identifier", - "optional": true, - "tsType": { - "keyword": "number", - "kind": "keyword", - "repr": "number", - }, - }, - { - "name": "cb", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "", - "kind": "fnOrConstructor", - "fnOrConstructor": { - "constructor": false, - "tsType": { - "keyword": "void", - "kind": "keyword", - "repr": "void" - }, - "typeParams": [], - "params": [{ - "arg": { - "name": "cbArgs", - "kind": "identifier", - "optional": false, - "tsType": null - }, - "kind": "rest", - "tsType": { - "repr": "", - "kind": "array", - "array": { - "repr": "unknown", - "kind": "keyword", - "keyword": "unknown" - } - }, - }] - } - }, - }, - { - "arg": { - "name": "args", - "kind": "identifier", - "optional": false, - "tsType": null - }, - "kind": "rest", - "tsType": { - "array": { - "keyword": "unknown", - "kind": "keyword", - "repr": "unknown" - }, - "kind": "array", - "repr": "" - } - } - ], - "returnType": { - "keyword": "void", - "kind": "keyword", - "repr": "void", - }, - }, - "jsDoc": "Hello there, this is a multiline JSdoc.\n\nIt has many lines\n\nOr not that many?", - "kind": "function", - "location": { - "col": 0, - "filename": "test.ts", - "line": 12, - }, - "name": "foo", - }]); - - json_test!(export_fn2, - r#" -interface AssignOpts { - a: string; - b: number; -} - -export function foo([e,,f, ...g]: number[], { c, d: asdf, i = "asdf", ...rest}, ops: AssignOpts = {}): void { - console.log("Hello world"); -} - "#; - [{ - "functionDef": { - "isAsync": false, - "isGenerator": false, - "typeParams": [], - "params": [ - { - "elements": [ - { - "name": "e", - "kind": "identifier", - "optional": false, - "tsType": null - }, - null, - { - "name": "f", - "kind": "identifier", - "optional": false, - "tsType": null - }, - { - "arg": { - "name": "g", - "kind": "identifier", - "optional": false, - "tsType": null - }, - "kind": "rest", - "tsType": null - } - ], - "kind": "array", - "optional": false, - "tsType": { - "repr": "", - "kind": "array", - "array": { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - } - }, - { - "kind": "object", - "optional": false, - "props": [ - { - "kind": "assign", - "key": "c", - "value": null - }, - { - "kind": "keyValue", - "key": "d", - "value": { - "name": "asdf", - "kind": "identifier", - "optional": false, - "tsType": null - } - }, - { - "kind": "assign", - "key": "i", - "value": "" - }, - { - "arg": { - "name": "rest", - "kind": "identifier", - "optional": false, - "tsType": null - }, - "kind": "rest" - } - ], - "tsType": null - }, - { - "kind": "assign", - "left": { - "name": "ops", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "AssignOpts", - "kind": "typeRef", - "typeRef": { - "typeName": "AssignOpts", - "typeParams": null, - } - } - }, - "right": "", - "tsType": null - } - ], - "returnType": { - "keyword": "void", - "kind": "keyword", - "repr": "void", - }, - }, - "jsDoc": null, - "kind": "function", - "location": { - "col": 0, - "filename": "test.ts", - "line": 7, - }, - "name": "foo", - }]); - - json_test!(export_interface, - r#" -interface Foo { - foo(): void; -} -interface Bar { - bar(): void; -} -/** - * Interface js doc - */ -export interface Reader extends Foo, Bar { - /** Read n bytes */ - read?(buf: Uint8Array, something: unknown): Promise -} - "#; - [{ - "kind": "interface", - "name": "Reader", - "location": { - "filename": "test.ts", - "line": 11, - "col": 0 - }, - "jsDoc": "Interface js doc", - "interfaceDef": { - "extends": [ - { - "repr": "Foo", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "Foo" - } - }, - { - "repr": "Bar", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "Bar" - } - } - ], - "methods": [ - { - "name": "read", - "location": { - "filename": "test.ts", - "line": 13, - "col": 4 - }, - "optional": true, - "jsDoc": "Read n bytes", - "params": [ - { - "name": "buf", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "Uint8Array", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "Uint8Array" - } - } - }, - { - "name": "something", - "kind": "identifier", - "optional": false, - "tsType": { - "repr": "unknown", - "kind": "keyword", - "keyword": "unknown" - } - } - ], - "typeParams": [], - "returnType": { - "repr": "Promise", - "kind": "typeRef", - "typeRef": { - "typeParams": [ - { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - ], - "typeName": "Promise" - } - } - } - ], - "properties": [], - "callSignatures": [], - "indexSignatures": [], - "typeParams": [], - } - }]); - - json_test!(export_interface2, - r#" -export interface TypedIface { - something(): T -} - "#; - [{ - "kind": "interface", - "name": "TypedIface", - "location": { - "filename": "test.ts", - "line": 2, - "col": 0 - }, - "jsDoc": null, - "interfaceDef": { - "extends": [], - "methods": [ - { - "name": "something", - "location": { - "filename": "test.ts", - "line": 3, - "col": 4 - }, - "jsDoc": null, - "optional": false, - "params": [], - "typeParams": [], - "returnType": { - "repr": "T", - "kind": "typeRef", - "typeRef": { - "typeParams": null, - "typeName": "T" - } - } - } - ], - "properties": [], - "callSignatures": [], - "indexSignatures": [], - "typeParams": [ - { "name": "T" } - ], - } - }]); - - json_test!(export_type_alias, - r#" -/** Array holding numbers */ -export type NumberArray = Array; - "#; - [{ - "kind": "typeAlias", - "name": "NumberArray", - "location": { - "filename": "test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": "Array holding numbers", - "typeAliasDef": { - "typeParams": [], - "tsType": { - "repr": "Array", - "kind": "typeRef", - "typeRef": { - "typeParams": [ - { - "repr": "number", - "kind": "keyword", - "keyword": "number" - } - ], - "typeName": "Array" - } - } - } - }]); - - json_test!(export_namespace, - r#" -/** Namespace JSdoc */ -export namespace RootNs { - export const a = "a"; - - /** Nested namespace JSDoc */ - export namespace NestedNs { - export enum Foo { - a = 1, - b = 2, - c = 3, - } - } -} - "#; - [{ - "kind": "namespace", - "name": "RootNs", - "location": { - "filename": "test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": "Namespace JSdoc", - "namespaceDef": { - "elements": [ - { - "kind": "variable", - "name": "a", - "location": { - "filename": "test.ts", - "line": 4, - "col": 4 - }, - "jsDoc": null, - "variableDef": { - "tsType": null, - "kind": "const" - } - }, - { - "kind": "namespace", - "name": "NestedNs", - "location": { - "filename": "test.ts", - "line": 7, - "col": 4 - }, - "jsDoc": "Nested namespace JSDoc", - "namespaceDef": { - "elements": [ - { - "kind": "enum", - "name": "Foo", - "location": { - "filename": "test.ts", - "line": 8, - "col": 6 - }, - "jsDoc": null, - "enumDef": { - "members": [ - { - "name": "a" - }, - { - "name": "b" - }, - { - "name": "c" - } - ] - } - } - ] - } - } - ] - } - }]); - - json_test!(optional_return_type, - r#" - export function foo(a: number) { - return a; - } - "#; - [{ - "kind": "function", - "name": "foo", - "location": { - "filename": "test.ts", - "line": 2, - "col": 2 - }, - "jsDoc": null, - "functionDef": { - "params": [ - { - "name": "a", - "kind": "identifier", - "optional": false, - "tsType": { - "keyword": "number", - "kind": "keyword", - "repr": "number", - }, - } - ], - "typeParams": [], - "returnType": null, - "isAsync": false, - "isGenerator": false - } - }] - ); - - json_test!(ts_lit_types, - r#" -export type boolLit = false; -export type strLit = "text"; -export type tplLit = `text`; -export type numLit = 5; - "#; - [ - { - "kind": "typeAlias", - "name": "boolLit", - "location": { - "filename": "test.ts", - "line": 2, - "col": 0 - }, - "jsDoc": null, - "typeAliasDef": { - "tsType": { - "repr": "false", - "kind": "literal", - "literal": { - "kind": "boolean", - "boolean": false - } - }, - "typeParams": [] - } - }, { - "kind": "typeAlias", - "name": "strLit", - "location": { - "filename": "test.ts", - "line": 3, - "col": 0 - }, - "jsDoc": null, - "typeAliasDef": { - "tsType": { - "repr": "text", - "kind": "literal", - "literal": { - "kind": "string", - "string": "text" - } - }, - "typeParams": [] - } - }, { - "kind": "typeAlias", - "name": "tplLit", - "location": { - "filename": "test.ts", - "line": 4, - "col": 0 - }, - "jsDoc": null, - "typeAliasDef": { - "tsType": { - "repr": "text", - "kind": "literal", - "literal": { - "kind": "string", - "string": "text" - } - }, - "typeParams": [] - } - }, { - "kind": "typeAlias", - "name": "numLit", - "location": { - "filename": "test.ts", - "line": 5, - "col": 0 - }, - "jsDoc": null, - "typeAliasDef": { - "tsType": { - "repr": "5", - "kind": "literal", - "literal": { - "kind": "number", - "number": 5.0 - } - }, - "typeParams": [] - } - } - ]); -} - -mod printer { - use super::*; - - contains_test!(abstract_class, - "export abstract class Class {}"; - "abstract class Class" - ); - - contains_test!(abstract_class_abstract_method, - r#" -export abstract class Class { - abstract method() {} -} - "#; - "abstract method()" - ); - - contains_test!(class_async_method, - r#" -export class Class { - async amethod(v) {} -} - "#; - "async amethod(v)" - ); - - contains_test!(class_constructor, - r#" -export class Class { - constructor(a, b) {} -} - "#; - "constructor(a, b)" - ); - - contains_test!(class_details, - r#" -export class C { - /** a doc */ - a() {} - f: number; -} - "#; - "class C", - "a()", - "f: number" - ); - - contains_test!(class_details_all_with_private, - r#" -export class Class { - private pri() {} - protected pro() {} - public pub() {} -} - "#, - private; - "private pri()", - "protected pro()", - "pub()" - ); - - contains_test!(class_details_only_non_private_without_private, - r#" -export class Class { - private pri() {} - protected pro() {} - public pub() {} -} - "#; - "protected pro()", - "pub()" - ); - - contains_test!(class_declaration, - "export class Class {}"; - "class Class" - ); - - contains_test!(class_extends, - "export class Class extends Object {}"; - "class Class extends Object" - ); - - contains_test!(class_extends_implements, - "export class Class extends Object implements Iterator, Iterable {}"; - "class Class extends Object implements Iterator, Iterable" - ); - - contains_test!(class_generic_extends_implements, - "export class Class extends Map implements Iterator, Iterable {}"; - "class Class extends Map implements Iterator, Iterable" - ); - - contains_test!(class_getter_and_setter, - r#" -export class Class { - get a(): void {} - set b(_v: void) {} -} - "#; - "get a(): void", - "set b(_v: void)" - ); - - contains_test!(class_index_signature, - r#" -export class C { - [key: string]: number; -} - "#; - "[key: string]: number" - ); - - contains_test!(class_implements, - "export class Class implements Iterator {}"; - "class Class implements Iterator" - ); - - contains_test!(class_implements2, - "export class Class implements Iterator, Iterable {}"; - "class Class implements Iterator, Iterable" - ); - - contains_test!(class_method, - r#" -export class Class { - method(v) {} -} - "#; - "method(v)" - ); - - contains_test!(class_property, - r#" -export class Class { - someproperty: bool; - optproperty: bigint; -} - "#; - "someproperty: bool", - "optproperty: bigint" - ); - - contains_test!(class_readonly_index_signature, - r#" -export class C { - readonly [key: string]: number; -} - "#; - "readonly [key: string]: number" - ); - - contains_test!(class_static_property, - r#" -export class Class { - static property = ""; -} - "#; - "static property" - ); - - contains_test!(class_readonly_property, - r#" -export class Class { - readonly property = ""; -} - "#; - "readonly property" - ); - - contains_test!(class_private_property, - r#" -export class Class { - private property = ""; -} - "#, - private; - "private property" - ); - - contains_test!(const_declaration, - "export const Const = 0;"; - "const Const" - ); - - contains_test!(enum_declaration, - "export enum Enum {}"; - "enum Enum" - ); - - contains_test!(exports_all_with_private, - r#" -export function a() {} -function b() {} -export class C {} -class D {} -export interface E {} -interface F {} -export namespace G {} -namespace H {} - "#, - private; - "function a()", - "class C", - "interface E", - "namespace G", - "function b()", - "class D", - "interface F", - "namespace H" - ); - - contains_test!(function_async, - "export async function a() {}"; - "async function a()" - ); - - contains_test!(function_array_deconstruction, - "export function f([a, b, ...c]) {}"; - "function f([a, b, ...c])" - ); - - contains_test!(function_async_generator, - "export async function* ag() {}"; - "async function* ag()" - ); - - contains_test!(function_declaration, - "export function fun() {}"; - "function fun()" - ); - - contains_test!(function_generator, - "export function* g() {}"; - "function* g()" - ); - - contains_test!(function_generic, - "export function add(a: T, b: T) { return a + b; }"; - "function add(a: T, b: T)" - ); - - contains_test!(function_object_deconstruction, - "export function f({ a, b, ...c }) {}"; - "function f({a, b, ...c})" - ); - - /* TODO(SyrupThinker) NYI - contains_test!(function_type_predicate, - r#" - export function isFish(pet: Fish | Bird): pet is Fish { - return (pet as Fish).swim !== undefined; - } - "#; - "pet is Fish" - ); - */ - - contains_test!(generic_instantiated_with_tuple_type, - r#" -interface Generic {} -export function f(): Generic<[string, number]> { return {}; } - "#; - "Generic<[string, number]>" - ); - - contains_test!(type_literal_declaration, - "export type T = {}"; - "{ }" - ); - - contains_test!(type_literal_index_signature, - "export type T = { [key: string]: number; }"; - "[key: string]: number" - ); - - contains_test!(type_literal_readonly_index_signature, - "export type T = { readonly [key: string]: number; }"; - "readonly [key: string]: number" - ); - - contains_test!(interface_declaration, - "export interface Interface {}"; - "interface Interface" - ); - - contains_test!(interface_extends, - "export interface Interface extends Iterator {}"; - "interface Interface extends Iterator" - ); - - contains_test!(interface_extends2, - "export interface Interface extends Iterator, Iterable {}"; - "interface Interface extends Iterator, Iterable" - ); - - contains_test!(interface_generic, - "export interface Interface {}"; - "interface Interface" - ); - - contains_test!(interface_generic_extends, - "export interface Interface extends Iterable {}"; - "interface Interface extends Iterable" - ); - - contains_test!(interface_index_signature, - r#" -export interface Interface { - [index: number]: Interface; -} - "#; - "[index: number]: Interface" - ); - - contains_test!(interface_method, - r#" -export interface I { - m(a, b); - mo?(c); -} - "#; - "m(a, b)", - "mo?(c)" - ); - - contains_test!(interface_property, - r#" -export interface I { - p: string; - po?: number; -} - "#; - "p: string", - "po?: number" - ); - - contains_test!(interface_readonly_index_signature, - r#" -export interface Interface { - readonly [index: number]: Interface; -} - "#; - "readonly [index: number]: Interface" - ); - - contains_test!(jsdoc, - r#" -/** - * A is a class - * - * Nothing more - */ -export class A {} -/** - * B is an interface - * - * Should be - */ -export interface B {} -/** - * C is a function - * - * Summarised - */ -export function C() {} - "#; - "A is a class", - "B is an interface", - "C is a function", - "Nothing more", - "Should be", - "Summarised" - ); - - contains_test!(namespace_declaration, - "export namespace Namespace {}"; - "namespace Namespace" - ); - - contains_test!(namespace_details, - r#" -export namespace Namespace { - /** - * Doc comment 1 - * - * Details 1 - */ - export function a() {} - /** - * Doc comment 2 - * - * Details 2 - */ - export class B {} -} - "#; - "namespace Namespace", - "function a()", - "class B", - "Doc comment 1", - "Doc comment 2", - "Details 1", - "Details 2" - ); - - contains_test!(type_alias, - "export type A = number"; - "type A = number" - ); - - contains_test!(type_generic_alias, - "export type A = T"; - "type A = T" - ); -} diff --git a/cli/doc/ts_type.rs b/cli/doc/ts_type.rs deleted file mode 100644 index b2eb3438d2..0000000000 --- a/cli/doc/ts_type.rs +++ /dev/null @@ -1,985 +0,0 @@ -// 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 serde::Serialize; -use std::fmt::{Display, Formatter, Result as FmtResult}; -use swc_ecmascript::ast::{ - TsArrayType, TsConditionalType, TsExprWithTypeArgs, TsFnOrConstructorType, - TsIndexedAccessType, TsKeywordType, TsLit, TsLitType, TsOptionalType, - TsParenthesizedType, TsRestType, TsThisType, TsTupleType, TsType, TsTypeAnn, - TsTypeLit, TsTypeOperator, TsTypeParamInstantiation, TsTypeQuery, TsTypeRef, - TsUnionOrIntersectionType, -}; - -// pub enum TsType { -// * TsKeywordType(TsKeywordType), -// * TsThisType(TsThisType), -// * TsFnOrConstructorType(TsFnOrConstructorType), -// * TsTypeRef(TsTypeRef), -// * TsTypeQuery(TsTypeQuery), -// * TsTypeLit(TsTypeLit), -// * TsArrayType(TsArrayType), -// * TsTupleType(TsTupleType), -// * TsOptionalType(TsOptionalType), -// * TsRestType(TsRestType), -// * TsUnionOrIntersectionType(TsUnionOrIntersectionType), -// * TsConditionalType(TsConditionalType), -// * TsParenthesizedType(TsParenthesizedType), -// * TsTypeOperator(TsTypeOperator), -// * TsIndexedAccessType(TsIndexedAccessType), -// * TsLitType(TsLitType), -// TsInferType(TsInferType), -// TsMappedType(TsMappedType), -// TsTypePredicate(TsTypePredicate), -// TsImportType(TsImportType), -// } - -impl Into for &TsLitType { - fn into(self) -> TsTypeDef { - let (repr, lit) = match &self.lit { - TsLit::Number(num) => ( - format!("{}", num.value), - LiteralDef { - kind: LiteralDefKind::Number, - number: Some(num.value), - string: None, - boolean: None, - }, - ), - TsLit::Str(str_) => ( - str_.value.to_string(), - LiteralDef { - kind: LiteralDefKind::String, - number: None, - string: Some(str_.value.to_string()), - boolean: None, - }, - ), - TsLit::Tpl(tpl) => { - // A template literal in a type is not allowed to have - // expressions, so there will only be one quasi. - let quasi = tpl.quasis.get(0).expect("Expected tpl to have a quasi."); - let text = quasi.raw.value.to_string(); - ( - text.clone(), - LiteralDef { - kind: LiteralDefKind::String, // semantically the same - number: None, - string: Some(text), - boolean: None, - }, - ) - } - TsLit::Bool(bool_) => ( - bool_.value.to_string(), - LiteralDef { - kind: LiteralDefKind::Boolean, - number: None, - string: None, - boolean: Some(bool_.value), - }, - ), - }; - - TsTypeDef { - repr, - kind: Some(TsTypeDefKind::Literal), - literal: Some(lit), - ..Default::default() - } - } -} - -impl Into for &TsArrayType { - fn into(self) -> TsTypeDef { - let ts_type_def: TsTypeDef = (&*self.elem_type).into(); - - TsTypeDef { - array: Some(Box::new(ts_type_def)), - kind: Some(TsTypeDefKind::Array), - ..Default::default() - } - } -} - -impl Into for &TsTupleType { - fn into(self) -> TsTypeDef { - let mut type_defs = vec![]; - - for type_box in &self.elem_types { - let ts_type: &TsType = &type_box.ty; - let def: TsTypeDef = ts_type.into(); - type_defs.push(def) - } - - TsTypeDef { - tuple: Some(type_defs), - kind: Some(TsTypeDefKind::Tuple), - ..Default::default() - } - } -} - -impl Into for &TsUnionOrIntersectionType { - fn into(self) -> TsTypeDef { - use swc_ecmascript::ast::TsUnionOrIntersectionType::*; - - match self { - TsUnionType(union_type) => { - let mut types_union = vec![]; - - for type_box in &union_type.types { - let ts_type: &TsType = &(*type_box); - let def: TsTypeDef = ts_type.into(); - types_union.push(def); - } - - TsTypeDef { - union: Some(types_union), - kind: Some(TsTypeDefKind::Union), - ..Default::default() - } - } - TsIntersectionType(intersection_type) => { - let mut types_intersection = vec![]; - - for type_box in &intersection_type.types { - let ts_type: &TsType = &(*type_box); - let def: TsTypeDef = ts_type.into(); - types_intersection.push(def); - } - - TsTypeDef { - intersection: Some(types_intersection), - kind: Some(TsTypeDefKind::Intersection), - ..Default::default() - } - } - } - } -} - -impl Into for &TsKeywordType { - fn into(self) -> TsTypeDef { - use swc_ecmascript::ast::TsKeywordTypeKind::*; - - let keyword_str = match self.kind { - TsAnyKeyword => "any", - TsUnknownKeyword => "unknown", - TsNumberKeyword => "number", - TsObjectKeyword => "object", - TsBooleanKeyword => "boolean", - TsBigIntKeyword => "bigint", - TsStringKeyword => "string", - TsSymbolKeyword => "symbol", - TsVoidKeyword => "void", - TsUndefinedKeyword => "undefined", - TsNullKeyword => "null", - TsNeverKeyword => "never", - }; - - TsTypeDef { - repr: keyword_str.to_string(), - kind: Some(TsTypeDefKind::Keyword), - keyword: Some(keyword_str.to_string()), - ..Default::default() - } - } -} - -impl Into for &TsTypeOperator { - fn into(self) -> TsTypeDef { - let ts_type = (&*self.type_ann).into(); - let type_operator_def = TsTypeOperatorDef { - operator: self.op.as_str().to_string(), - ts_type, - }; - - TsTypeDef { - type_operator: Some(Box::new(type_operator_def)), - kind: Some(TsTypeDefKind::TypeOperator), - ..Default::default() - } - } -} - -impl Into for &TsParenthesizedType { - fn into(self) -> TsTypeDef { - let ts_type = (&*self.type_ann).into(); - - TsTypeDef { - parenthesized: Some(Box::new(ts_type)), - kind: Some(TsTypeDefKind::Parenthesized), - ..Default::default() - } - } -} - -impl Into for &TsRestType { - fn into(self) -> TsTypeDef { - let ts_type = (&*self.type_ann).into(); - - TsTypeDef { - rest: Some(Box::new(ts_type)), - kind: Some(TsTypeDefKind::Rest), - ..Default::default() - } - } -} - -impl Into for &TsOptionalType { - fn into(self) -> TsTypeDef { - let ts_type = (&*self.type_ann).into(); - - TsTypeDef { - optional: Some(Box::new(ts_type)), - kind: Some(TsTypeDefKind::Optional), - ..Default::default() - } - } -} - -impl Into for &TsThisType { - fn into(self) -> TsTypeDef { - TsTypeDef { - repr: "this".to_string(), - this: Some(true), - kind: Some(TsTypeDefKind::This), - ..Default::default() - } - } -} - -pub fn ts_entity_name_to_name( - entity_name: &swc_ecmascript::ast::TsEntityName, -) -> String { - use swc_ecmascript::ast::TsEntityName::*; - - match entity_name { - Ident(ident) => ident.sym.to_string(), - TsQualifiedName(ts_qualified_name) => { - let left = ts_entity_name_to_name(&ts_qualified_name.left); - let right = ts_qualified_name.right.sym.to_string(); - format!("{}.{}", left, right) - } - } -} - -impl Into for &TsTypeQuery { - fn into(self) -> TsTypeDef { - use swc_ecmascript::ast::TsTypeQueryExpr::*; - - let type_name = match &self.expr_name { - TsEntityName(entity_name) => ts_entity_name_to_name(&*entity_name), - Import(import_type) => import_type.arg.value.to_string(), - }; - - TsTypeDef { - repr: type_name.to_string(), - type_query: Some(type_name), - kind: Some(TsTypeDefKind::TypeQuery), - ..Default::default() - } - } -} - -impl Into for &TsTypeRef { - fn into(self) -> TsTypeDef { - let type_name = ts_entity_name_to_name(&self.type_name); - - let type_params = if let Some(type_params_inst) = &self.type_params { - 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, - }), - 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, - }), - kind: Some(TsTypeDefKind::TypeRef), - ..Default::default() - } - } -} - -impl Into for &TsIndexedAccessType { - fn into(self) -> TsTypeDef { - let indexed_access_def = TsIndexedAccessDef { - readonly: self.readonly, - obj_type: Box::new((&*self.obj_type).into()), - index_type: Box::new((&*self.index_type).into()), - }; - - TsTypeDef { - indexed_access: Some(indexed_access_def), - kind: Some(TsTypeDefKind::IndexedAccess), - ..Default::default() - } - } -} - -impl Into for &TsTypeLit { - fn into(self) -> TsTypeDef { - 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 swc_ecmascript::ast::TsTypeElement::*; - - match &type_element { - TsMethodSignature(ts_method_sig) => { - let mut params = vec![]; - - for param in &ts_method_sig.params { - let param_def = ts_fn_param_to_param_def(param, None); - params.push(param_def); - } - - let maybe_return_type = ts_method_sig - .type_ann - .as_ref() - .map(|rt| (&*rt.type_ann).into()); - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_method_sig.type_params.as_ref(), - ); - let name = expr_to_name(&*ts_method_sig.key); - let method_def = LiteralMethodDef { - name, - params, - return_type: maybe_return_type, - type_params, - }; - methods.push(method_def); - } - TsPropertySignature(ts_prop_sig) => { - let name = expr_to_name(&*ts_prop_sig.key); - - let mut params = vec![]; - - for param in &ts_prop_sig.params { - let param_def = ts_fn_param_to_param_def(param, None); - params.push(param_def); - } - - let ts_type = ts_prop_sig - .type_ann - .as_ref() - .map(|rt| (&*rt.type_ann).into()); - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_prop_sig.type_params.as_ref(), - ); - let prop_def = LiteralPropertyDef { - name, - params, - ts_type, - computed: ts_prop_sig.computed, - optional: ts_prop_sig.optional, - type_params, - }; - properties.push(prop_def); - } - 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, None); - params.push(param_def); - } - - let ts_type = ts_call_sig - .type_ann - .as_ref() - .map(|rt| (&*rt.type_ann).into()); - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_call_sig.type_params.as_ref(), - ); - - let call_sig_def = LiteralCallSignatureDef { - params, - ts_type, - type_params, - }; - 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(_) => {} - } - } - - let type_literal = TsTypeLiteralDef { - methods, - properties, - call_signatures, - index_signatures, - }; - - TsTypeDef { - kind: Some(TsTypeDefKind::TypeLiteral), - type_literal: Some(type_literal), - ..Default::default() - } - } -} - -impl Into for &TsConditionalType { - fn into(self) -> TsTypeDef { - let conditional_type_def = TsConditionalDef { - check_type: Box::new((&*self.check_type).into()), - extends_type: Box::new((&*self.extends_type).into()), - true_type: Box::new((&*self.true_type).into()), - false_type: Box::new((&*self.false_type).into()), - }; - - TsTypeDef { - kind: Some(TsTypeDefKind::Conditional), - conditional_type: Some(conditional_type_def), - ..Default::default() - } - } -} - -impl Into for &TsFnOrConstructorType { - fn into(self) -> TsTypeDef { - use swc_ecmascript::ast::TsFnOrConstructorType::*; - - let fn_def = match self { - TsFnType(ts_fn_type) => { - let mut params = vec![]; - - for param in &ts_fn_type.params { - let param_def = ts_fn_param_to_param_def(param, None); - params.push(param_def); - } - - let type_params = maybe_type_param_decl_to_type_param_defs( - ts_fn_type.type_params.as_ref(), - ); - - TsFnOrConstructorDef { - constructor: false, - ts_type: ts_type_ann_to_def(&ts_fn_type.type_ann), - params, - type_params, - } - } - TsConstructorType(ctor_type) => { - let mut params = vec![]; - - for param in &ctor_type.params { - let param_def = ts_fn_param_to_param_def(param, None); - params.push(param_def); - } - - let type_params = maybe_type_param_decl_to_type_param_defs( - ctor_type.type_params.as_ref(), - ); - TsFnOrConstructorDef { - constructor: true, - ts_type: ts_type_ann_to_def(&ctor_type.type_ann), - params, - type_params, - } - } - }; - - TsTypeDef { - kind: Some(TsTypeDefKind::FnOrConstructor), - fn_or_constructor: Some(Box::new(fn_def)), - ..Default::default() - } - } -} - -impl Into for &TsType { - fn into(self) -> TsTypeDef { - use swc_ecmascript::ast::TsType::*; - - match self { - TsKeywordType(ref keyword_type) => keyword_type.into(), - TsLitType(ref lit_type) => lit_type.into(), - TsTypeRef(ref type_ref) => type_ref.into(), - TsUnionOrIntersectionType(union_or_inter) => union_or_inter.into(), - TsArrayType(array_type) => array_type.into(), - TsTupleType(tuple_type) => tuple_type.into(), - TsTypeOperator(type_op_type) => type_op_type.into(), - TsParenthesizedType(paren_type) => paren_type.into(), - TsRestType(rest_type) => rest_type.into(), - TsOptionalType(optional_type) => optional_type.into(), - TsTypeQuery(type_query) => type_query.into(), - TsThisType(this_type) => this_type.into(), - TsFnOrConstructorType(fn_or_con_type) => fn_or_con_type.into(), - TsConditionalType(conditional_type) => conditional_type.into(), - TsIndexedAccessType(indexed_access_type) => indexed_access_type.into(), - TsTypeLit(type_literal) => type_literal.into(), - _ => TsTypeDef { - repr: "".to_string(), - ..Default::default() - }, - } - } -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsTypeRefDef { - pub type_params: Option>, - pub type_name: String, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub enum LiteralDefKind { - Number, - String, - Boolean, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct LiteralDef { - pub kind: LiteralDefKind, - - #[serde(skip_serializing_if = "Option::is_none")] - pub number: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub string: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub boolean: Option, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsTypeOperatorDef { - pub operator: String, - pub ts_type: TsTypeDef, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsFnOrConstructorDef { - pub constructor: bool, - pub ts_type: TsTypeDef, - pub params: Vec, - pub type_params: Vec, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsConditionalDef { - pub check_type: Box, - pub extends_type: Box, - pub true_type: Box, - pub false_type: Box, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsIndexedAccessDef { - pub readonly: bool, - pub obj_type: Box, - pub index_type: Box, -} - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct LiteralMethodDef { - pub name: String, - pub params: Vec, - pub return_type: Option, - 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 { - pub name: String, - pub params: Vec, - pub computed: bool, - pub optional: bool, - pub ts_type: Option, - 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 { - pub params: Vec, - pub ts_type: Option, - 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)] -#[serde(rename_all = "camelCase")] -pub enum TsTypeDefKind { - Keyword, - Literal, - TypeRef, - Union, - Intersection, - Array, - Tuple, - TypeOperator, - Parenthesized, - Rest, - Optional, - TypeQuery, - This, - FnOrConstructor, - Conditional, - IndexedAccess, - TypeLiteral, -} - -#[derive(Debug, Default, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsTypeDef { - pub repr: String, - - pub kind: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub keyword: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub literal: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub type_ref: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub union: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub intersection: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub array: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub tuple: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub type_operator: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub parenthesized: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub rest: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub optional: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub type_query: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub this: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub fn_or_constructor: Option>, - - #[serde(skip_serializing_if = "Option::is_none")] - pub conditional_type: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub indexed_access: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub type_literal: Option, -} - -pub fn ts_type_ann_to_def(type_ann: &TsTypeAnn) -> TsTypeDef { - use swc_ecmascript::ast::TsType::*; - - match &*type_ann.type_ann { - TsKeywordType(keyword_type) => keyword_type.into(), - TsLitType(lit_type) => lit_type.into(), - TsTypeRef(type_ref) => type_ref.into(), - TsUnionOrIntersectionType(union_or_inter) => union_or_inter.into(), - TsArrayType(array_type) => array_type.into(), - TsTupleType(tuple_type) => tuple_type.into(), - TsTypeOperator(type_op_type) => type_op_type.into(), - TsParenthesizedType(paren_type) => paren_type.into(), - TsRestType(rest_type) => rest_type.into(), - TsOptionalType(optional_type) => optional_type.into(), - TsTypeQuery(type_query) => type_query.into(), - TsThisType(this_type) => this_type.into(), - TsFnOrConstructorType(fn_or_con_type) => fn_or_con_type.into(), - TsConditionalType(conditional_type) => conditional_type.into(), - TsIndexedAccessType(indexed_access_type) => indexed_access_type.into(), - TsTypeLit(type_literal) => type_literal.into(), - _ => TsTypeDef { - repr: "".to_string(), - ..Default::default() - }, - } -} - -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![] - } -} diff --git a/cli/doc/ts_type_param.rs b/cli/doc/ts_type_param.rs deleted file mode 100644 index 52ecb74cc5..0000000000 --- a/cli/doc/ts_type_param.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use super::ts_type::TsTypeDef; -use serde::Serialize; -use std::fmt::{Display, Formatter, Result as FmtResult}; -use swc_ecmascript::ast::TsTypeParam; -use swc_ecmascript::ast::TsTypeParamDecl; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TsTypeParamDef { - pub name: String, - - #[serde(skip_serializing_if = "Option::is_none")] - pub constraint: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, -} - -impl Display for TsTypeParamDef { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}", self.name)?; - if let Some(constraint) = &self.constraint { - write!(f, " extends {}", constraint)?; - } - if let Some(default) = &self.default { - write!(f, " = {}", default)?; - } - Ok(()) - } -} - -impl Into for &TsTypeParam { - fn into(self) -> TsTypeParamDef { - let name = self.name.sym.to_string(); - let constraint: Option = - if let Some(ts_type) = self.constraint.as_ref() { - let type_def: TsTypeDef = (&**ts_type).into(); - Some(type_def) - } else { - None - }; - let default: Option = - if let Some(ts_type) = self.default.as_ref() { - let type_def: TsTypeDef = (&**ts_type).into(); - Some(type_def) - } else { - None - }; - - TsTypeParamDef { - name, - constraint, - default, - } - } -} - -pub fn maybe_type_param_decl_to_type_param_defs( - maybe_type_param_decl: Option<&TsTypeParamDecl>, -) -> Vec { - if let Some(type_params_decl) = maybe_type_param_decl { - type_params_decl - .params - .iter() - .map(|type_param| type_param.into()) - .collect::>() - } else { - vec![] - } -} diff --git a/cli/doc/type_alias.rs b/cli/doc/type_alias.rs deleted file mode 100644 index 446e8fbec7..0000000000 --- a/cli/doc/type_alias.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use super::parser::DocParser; -use super::ts_type::TsTypeDef; -use super::ts_type_param::maybe_type_param_decl_to_type_param_defs; -use super::ts_type_param::TsTypeParamDef; -use serde::Serialize; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct TypeAliasDef { - pub ts_type: TsTypeDef, - pub type_params: Vec, -} - -pub fn get_doc_for_ts_type_alias_decl( - _doc_parser: &DocParser, - type_alias_decl: &swc_ecmascript::ast::TsTypeAliasDecl, -) -> (String, TypeAliasDef) { - let alias_name = type_alias_decl.id.sym.to_string(); - let ts_type = type_alias_decl.type_ann.as_ref().into(); - let type_params = maybe_type_param_decl_to_type_param_defs( - type_alias_decl.type_params.as_ref(), - ); - let type_alias_def = TypeAliasDef { - ts_type, - type_params, - }; - - (alias_name, type_alias_def) -} diff --git a/cli/doc/variable.rs b/cli/doc/variable.rs deleted file mode 100644 index 4c2fcea140..0000000000 --- a/cli/doc/variable.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use serde::Serialize; - -use super::ts_type::ts_type_ann_to_def; -use super::ts_type::TsTypeDef; - -#[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] -pub struct VariableDef { - pub ts_type: Option, - pub kind: swc_ecmascript::ast::VarDeclKind, -} - -// TODO: change this function to return Vec<(String, VariableDef)> as single -// var declaration can have multiple declarators -pub fn get_doc_for_var_decl( - var_decl: &swc_ecmascript::ast::VarDecl, -) -> (String, VariableDef) { - assert!(!var_decl.decls.is_empty()); - let var_declarator = var_decl.decls.get(0).unwrap(); - let var_name = match &var_declarator.name { - swc_ecmascript::ast::Pat::Ident(ident) => ident.sym.to_string(), - _ => "".to_string(), - }; - - let maybe_ts_type = match &var_declarator.name { - swc_ecmascript::ast::Pat::Ident(ident) => { - ident.type_ann.as_ref().map(|rt| ts_type_ann_to_def(rt)) - } - _ => None, - }; - - let variable_def = VariableDef { - ts_type: maybe_ts_type, - kind: var_decl.kind, - }; - - (var_name, variable_def) -} diff --git a/cli/global_state.rs b/cli/global_state.rs index a1d4af86c6..daabcf5198 100644 --- a/cli/global_state.rs +++ b/cli/global_state.rs @@ -313,8 +313,8 @@ fn thread_safe() { #[test] fn test_should_allow_js() { - use crate::doc::Location; use crate::module_graph::ImportDescriptor; + use crate::swc_util::Location; assert!(should_allow_js(&[ &ModuleGraphFile { diff --git a/cli/main.rs b/cli/main.rs index c1774f5b90..353b7763f9 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -29,7 +29,6 @@ pub mod deno_dir; pub mod diagnostics; mod diff; mod disk_cache; -mod doc; mod file_fetcher; pub mod flags; mod flags_allow_net; @@ -69,14 +68,13 @@ pub mod version; mod web_worker; pub mod worker; -use crate::doc::parser::DocFileLoader; +use crate::file_fetcher::map_file_extension; use crate::file_fetcher::SourceFile; use crate::file_fetcher::SourceFileFetcher; use crate::file_fetcher::TextDocument; use crate::fs as deno_fs; use crate::global_state::GlobalState; use crate::msg::MediaType; -use crate::op_error::OpError; use crate::permissions::Permissions; use crate::tsc::TargetLib; use crate::worker::MainWorker; @@ -85,6 +83,8 @@ use deno_core::Deps; use deno_core::ErrBox; use deno_core::EsIsolate; use deno_core::ModuleSpecifier; +use deno_doc as doc; +use deno_doc::parser::DocFileLoader; use flags::DenoSubcommand; use flags::Flags; use futures::future::FutureExt; @@ -505,19 +505,39 @@ async fn doc_command( let source_file = source_file.unwrap_or_else(|| "--builtin".to_string()); impl DocFileLoader for SourceFileFetcher { + fn resolve( + &self, + specifier: &str, + referrer: &str, + ) -> Result { + ModuleSpecifier::resolve_import(specifier, referrer) + .map(|specifier| specifier.to_string()) + .map_err(|e| doc::DocError::Resolve(e.to_string())) + } + fn load_source_code( &self, specifier: &str, - ) -> Pin>>> { + ) -> Pin>>> { let fetcher = self.clone(); - let specifier = specifier.to_string(); + let specifier = ModuleSpecifier::resolve_url_or_path(specifier) + .expect("Expected valid specifier"); async move { - let specifier = ModuleSpecifier::resolve_url_or_path(&specifier) - .map_err(OpError::from)?; let source_file = fetcher .fetch_source_file(&specifier, None, Permissions::allow_all()) - .await?; - source_file.source_code.to_string().map_err(OpError::from) + .await + .map_err(|e| { + doc::DocError::Io(std::io::Error::new( + std::io::ErrorKind::Other, + e.to_string(), + )) + })?; + source_file.source_code.to_string().map_err(|e| { + doc::DocError::Io(std::io::Error::new( + std::io::ErrorKind::Other, + e.to_string(), + )) + }) } .boxed_local() } @@ -525,14 +545,20 @@ async fn doc_command( let loader = Box::new(global_state.file_fetcher.clone()); let doc_parser = doc::DocParser::new(loader, private); + let media_type = map_file_extension(&PathBuf::from(&source_file)); + let syntax = swc_util::get_syntax_for_media_type(media_type); let parse_result = if source_file == "--builtin" { - doc_parser.parse_source("lib.deno.d.ts", get_types(flags.unstable).as_str()) + doc_parser.parse_source( + "lib.deno.d.ts", + syntax, + get_types(flags.unstable).as_str(), + ) } else { let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file).unwrap(); doc_parser - .parse_with_reexports(&module_specifier.to_string()) + .parse_with_reexports(&module_specifier.to_string(), syntax) .await }; @@ -555,9 +581,15 @@ async fn doc_command( eprintln!("Node {} was not found!", filter); std::process::exit(1); } - format!("{}", doc::DocPrinter::new(&nodes, private)) + format!( + "{}", + doc::DocPrinter::new(&nodes, colors::use_color(), private) + ) } else { - format!("{}", doc::DocPrinter::new(&doc_nodes, private)) + format!( + "{}", + doc::DocPrinter::new(&doc_nodes, colors::use_color(), private) + ) }; write_to_stdout_ignore_sigpipe(details.as_bytes()).map_err(ErrBox::from) diff --git a/cli/module_graph.rs b/cli/module_graph.rs index 3c07acd3b4..5b15c0cd47 100644 --- a/cli/module_graph.rs +++ b/cli/module_graph.rs @@ -1,6 +1,5 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::checksum; -use crate::doc::Location; use crate::file_fetcher::map_file_extension; use crate::file_fetcher::SourceFile; use crate::file_fetcher::SourceFileFetcher; @@ -8,6 +7,7 @@ use crate::import_map::ImportMap; use crate::msg::MediaType; use crate::op_error::OpError; use crate::permissions::Permissions; +use crate::swc_util::Location; use crate::tsc::pre_process_file; use crate::tsc::ImportDesc; use crate::tsc::TsReferenceDesc; diff --git a/cli/swc_util.rs b/cli/swc_util.rs index d1115e024c..13d1651135 100644 --- a/cli/swc_util.rs +++ b/cli/swc_util.rs @@ -1,6 +1,7 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::msg::MediaType; use deno_core::ErrBox; +use serde::Serialize; use std::error::Error; use std::fmt; use std::rc::Rc; @@ -31,6 +32,31 @@ use swc_ecmascript::transforms::fixer; use swc_ecmascript::transforms::typescript; use swc_ecmascript::visit::FoldWith; +#[derive(Debug, Serialize, Clone, PartialEq)] +pub struct Location { + pub filename: String, + pub line: usize, + pub col: usize, +} + +impl Into for swc_common::Loc { + fn into(self) -> Location { + use swc_common::FileName::*; + + let filename = match &self.file.name { + Real(path_buf) => path_buf.to_string_lossy().to_string(), + Custom(str_) => str_.to_string(), + _ => panic!("invalid filename"), + }; + + Location { + filename, + line: self.line, + col: self.col_display, + } + } +} + struct DummyHandler; impl swc_ecmascript::codegen::Handlers for DummyHandler {} diff --git a/cli/tsc.rs b/cli/tsc.rs index f0b2e037be..5fa8b67a35 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -3,7 +3,6 @@ use crate::colors; use crate::diagnostics::Diagnostic; use crate::diagnostics::DiagnosticItem; use crate::disk_cache::DiskCache; -use crate::doc::Location; use crate::file_fetcher::SourceFile; use crate::file_fetcher::SourceFileFetcher; use crate::flags::Flags; @@ -20,6 +19,7 @@ use crate::source_maps::SourceMapGetter; use crate::startup_data; use crate::state::State; use crate::swc_util::AstParser; +use crate::swc_util::Location; use crate::swc_util::SwcDiagnosticBuffer; use crate::version; use crate::worker::Worker;