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<String>,
-  pub accessibility: Option<swc_ecmascript::ast::Accessibility>,
-  pub name: String,
-  pub params: Vec<ParamDef>,
-  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<String>,
-  pub ts_type: Option<TsTypeDef>,
-  pub readonly: bool,
-  pub accessibility: Option<swc_ecmascript::ast::Accessibility>,
-  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<ParamDef>,
-  pub ts_type: Option<TsTypeDef>,
-}
-
-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<String>,
-  pub accessibility: Option<swc_ecmascript::ast::Accessibility>,
-  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<ClassConstructorDef>,
-  pub properties: Vec<ClassPropertyDef>,
-  pub index_signatures: Vec<ClassIndexSignatureDef>,
-  pub methods: Vec<ClassMethodDef>,
-  pub extends: Option<String>,
-  pub implements: Vec<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-  pub super_type_params: Vec<TsTypeDef>,
-}
-
-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<String> = 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::<Vec<TsTypeDef>>();
-
-  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(
-              &param.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<T: Display> 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<swc_ecmascript::ast::Accessibility>,
-) -> 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<EnumMemberDef>,
-}
-
-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<ParamDef>,
-  pub return_type: Option<TsTypeDef>,
-  pub is_async: bool,
-  pub is_generator: bool,
-  pub type_params: Vec<TsTypeParamDef>,
-  // 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(&param.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<String>,
-  pub optional: bool,
-  pub params: Vec<ParamDef>,
-  pub return_type: Option<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-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<String>,
-  pub params: Vec<ParamDef>,
-  pub computed: bool,
-  pub optional: bool,
-  pub ts_type: Option<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-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<ParamDef>,
-  pub ts_type: Option<TsTypeDef>,
-}
-
-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<String>,
-  pub params: Vec<ParamDef>,
-  pub ts_type: Option<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct InterfaceDef {
-  pub extends: Vec<TsTypeDef>,
-  pub methods: Vec<InterfaceMethodDef>,
-  pub properties: Vec<InterfacePropertyDef>,
-  pub call_signatures: Vec<InterfaceCallSignatureDef>,
-  pub index_signatures: Vec<InterfaceIndexSignatureDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-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)
-    }
-    _ => "<TODO>".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::<Vec<TsTypeDef>>();
-
-  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<DocNode>,
-  name: String,
-) -> Vec<DocNode> {
-  let mut parts = name.splitn(2, '.');
-  let name = parts.next();
-  let leftover = parts.next();
-  if name.is_none() {
-    return doc_nodes;
-  }
-
-  let name = name.unwrap();
-  let doc_nodes = find_nodes_by_name(doc_nodes, name.to_string());
-
-  let mut found: Vec<DocNode> = vec![];
-  match leftover {
-    Some(leftover) => {
-      for node in doc_nodes {
-        let children = find_children_by_name(node, leftover.to_string());
-        found.extend(children);
-      }
-      found
-    }
-    None => doc_nodes,
-  }
-}
-
-fn find_nodes_by_name(doc_nodes: Vec<DocNode>, name: String) -> Vec<DocNode> {
-  let mut found: Vec<DocNode> = vec![];
-  for node in doc_nodes {
-    if node.name == name {
-      found.push(node);
-    }
-  }
-  found
-}
-
-fn find_children_by_name(node: DocNode, name: String) -> Vec<DocNode> {
-  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<DocNode>,
-}
-
-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<Location> 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<String>),
-}
-
-#[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<DocNode>,
-  pub reexports: Vec<Reexport>,
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct ImportDef {
-  pub src: String,
-  pub imported: Option<String>,
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct DocNode {
-  pub kind: DocNodeKind,
-  pub name: String,
-  pub location: Location,
-  pub js_doc: Option<String>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub function_def: Option<super::function::FunctionDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub variable_def: Option<super::variable::VariableDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub enum_def: Option<super::r#enum::EnumDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub class_def: Option<super::class::ClassDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub type_alias_def: Option<super::type_alias::TypeAliasDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub namespace_def: Option<super::namespace::NamespaceDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub interface_def: Option<super::interface::InterfaceDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub import_def: Option<ImportDef>,
-}
-
-impl DocNode {
-  pub fn function(
-    name: String,
-    location: Location,
-    js_doc: Option<String>,
-    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<String>,
-    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<String>,
-    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<String>,
-    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<String>,
-    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<String>,
-    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<String>,
-    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<String>,
-    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<Option<ParamDef>>,
-    optional: bool,
-    ts_type: Option<TsTypeDef>,
-  },
-  #[serde(rename_all = "camelCase")]
-  Assign {
-    left: Box<ParamDef>,
-    right: String,
-    ts_type: Option<TsTypeDef>,
-  },
-  #[serde(rename_all = "camelCase")]
-  Identifier {
-    name: String,
-    optional: bool,
-    ts_type: Option<TsTypeDef>,
-  },
-  #[serde(rename_all = "camelCase")]
-  Object {
-    props: Vec<ObjectPatPropDef>,
-    optional: bool,
-    ts_type: Option<TsTypeDef>,
-  },
-  #[serde(rename_all = "camelCase")]
-  Rest {
-    arg: Box<ParamDef>,
-    ts_type: Option<TsTypeDef>,
-  },
-}
-
-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<String> },
-  KeyValue { key: String, value: Box<ParamDef> },
-  Rest { arg: Box<ParamDef> },
-}
-
-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(|_| "<UNIMPLEMENTED>".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::<Vec<_>>();
-  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::<Vec<Option<_>>>();
-  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: "<UNIMPLEMENTED>".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(|| "<UNAVAILABLE>".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, OpError> {
-    ModuleSpecifier::resolve_import(specifier, referrer).map_err(OpError::from)
-  }
-
-  fn load_source_code(
-    &self,
-    specifier: &str,
-  ) -> Pin<Box<dyn Future<Output = Result<String, OpError>>>>;
-}
-
-pub struct DocParser {
-  pub ast_parser: AstParser,
-  pub loader: Box<dyn DocFileLoader>,
-  pub private: bool,
-}
-
-impl DocParser {
-  pub fn new(loader: Box<dyn DocFileLoader>, private: bool) -> Self {
-    DocParser {
-      loader,
-      ast_parser: AstParser::default(),
-      private,
-    }
-  }
-
-  fn parse_module(
-    &self,
-    file_name: &str,
-    source_code: &str,
-  ) -> Result<ModuleDoc, ErrBox> {
-    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<Vec<DocNode>, 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<Vec<DocNode>, 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<Vec<DocNode>, ErrBox> {
-    let mut by_src: HashMap<String, Vec<node::Reexport>> = HashMap::new();
-
-    let mut processed_reexports: Vec<DocNode> = 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<Vec<DocNode>, 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<swc_ecmascript::ast::ModuleItem>,
-    referrer: &str,
-  ) -> Result<Vec<DocNode>, 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<DocNode> {
-    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<DocNode> {
-    match stmt {
-      Stmt::Decl(decl) => self.get_doc_node_for_decl(decl),
-      _ => None,
-    }
-  }
-
-  fn details_for_span(&self, span: Span) -> (Option<String>, 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<DocNode> {
-    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<swc_ecmascript::ast::ModuleItem>,
-  ) -> Vec<node::Reexport> {
-    use swc_ecmascript::ast::ExportSpecifier::*;
-
-    let mut reexports: Vec<node::Reexport> = 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::<Vec<node::Reexport>>()
-            } 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<swc_ecmascript::ast::ModuleItem>,
-  ) -> Vec<DocNode> {
-    let mut doc_entries: Vec<DocNode> = 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<String> {
-    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::<Vec<String>>()
-      .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<String, String>,
-}
-
-impl TestLoader {
-  pub fn new(files_vec: Vec<(String, String)>) -> Box<Self> {
-    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<Box<dyn Future<Output = Result<String, OpError>>>> {
-    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<void> {
-        //
-    }
-
-    /** 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<number>
-}
-    "#;
-    [{
-      "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": "<UNIMPLEMENTED>"
-            },
-            {
-              "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": "<UNIMPLEMENTED>",
-          "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<number>
-}
-    "#;
-  [{
-      "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<T> {
-    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<number>;
-    "#;
-    [{
-    "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<A, B> extends Map<A, B> implements Iterator<A>, Iterable<B> {}";
-    "class Class<A, B> extends Map<A, B> implements Iterator<A>, Iterable<B>"
-  );
-
-  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<T>(a: T, b: T) { return a + b; }";
-    "function add<T>(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<T> {}
-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<T> {}";
-    "interface Interface<T>"
-  );
-
-  contains_test!(interface_generic_extends,
-    "export interface Interface<V> extends Iterable<V> {}";
-    "interface Interface<V> extends Iterable<V>"
-  );
-
-  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> = T";
-  "type A<T> = 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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<TsTypeDef> 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: "<UNIMPLEMENTED>".to_string(),
-        ..Default::default()
-      },
-    }
-  }
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct TsTypeRefDef {
-  pub type_params: Option<Vec<TsTypeDef>>,
-  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<f64>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub string: Option<String>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub boolean: Option<bool>,
-}
-
-#[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<ParamDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct TsConditionalDef {
-  pub check_type: Box<TsTypeDef>,
-  pub extends_type: Box<TsTypeDef>,
-  pub true_type: Box<TsTypeDef>,
-  pub false_type: Box<TsTypeDef>,
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct TsIndexedAccessDef {
-  pub readonly: bool,
-  pub obj_type: Box<TsTypeDef>,
-  pub index_type: Box<TsTypeDef>,
-}
-
-#[derive(Debug, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct LiteralMethodDef {
-  pub name: String,
-  pub params: Vec<ParamDef>,
-  pub return_type: Option<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-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<ParamDef>,
-  pub computed: bool,
-  pub optional: bool,
-  pub ts_type: Option<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-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<ParamDef>,
-  pub ts_type: Option<TsTypeDef>,
-  pub type_params: Vec<TsTypeParamDef>,
-}
-
-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<ParamDef>,
-  pub ts_type: Option<TsTypeDef>,
-}
-
-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<LiteralMethodDef>,
-  pub properties: Vec<LiteralPropertyDef>,
-  pub call_signatures: Vec<LiteralCallSignatureDef>,
-  pub index_signatures: Vec<LiteralIndexSignatureDef>,
-}
-
-#[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<TsTypeDefKind>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub keyword: Option<String>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub literal: Option<LiteralDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub type_ref: Option<TsTypeRefDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub union: Option<Vec<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub intersection: Option<Vec<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub array: Option<Box<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub tuple: Option<Vec<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub type_operator: Option<Box<TsTypeOperatorDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub parenthesized: Option<Box<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub rest: Option<Box<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub optional: Option<Box<TsTypeDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub type_query: Option<String>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub this: Option<bool>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub fn_or_constructor: Option<Box<TsFnOrConstructorDef>>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub conditional_type: Option<TsConditionalDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub indexed_access: Option<TsIndexedAccessDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub type_literal: Option<TsTypeLiteralDef>,
-}
-
-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: "<TODO>".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("<UNIMPLEMENTED>"));
-    }
-
-    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<TsTypeDef> {
-  if let Some(type_param_instantiation) = maybe_type_param_instantiation {
-    type_param_instantiation
-      .params
-      .iter()
-      .map(|type_param| type_param.as_ref().into())
-      .collect::<Vec<TsTypeDef>>()
-  } 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<TsTypeDef>,
-
-  #[serde(skip_serializing_if = "Option::is_none")]
-  pub default: Option<TsTypeDef>,
-}
-
-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<TsTypeParamDef> for &TsTypeParam {
-  fn into(self) -> TsTypeParamDef {
-    let name = self.name.sym.to_string();
-    let constraint: Option<TsTypeDef> =
-      if let Some(ts_type) = self.constraint.as_ref() {
-        let type_def: TsTypeDef = (&**ts_type).into();
-        Some(type_def)
-      } else {
-        None
-      };
-    let default: Option<TsTypeDef> =
-      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<TsTypeParamDef> {
-  if let Some(type_params_decl) = maybe_type_param_decl {
-    type_params_decl
-      .params
-      .iter()
-      .map(|type_param| type_param.into())
-      .collect::<Vec<TsTypeParamDef>>()
-  } 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<TsTypeParamDef>,
-}
-
-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<TsTypeDef>,
-  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(),
-    _ => "<TODO>".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<String, doc::DocError> {
+      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<Box<dyn Future<Output = Result<String, OpError>>>> {
+    ) -> Pin<Box<dyn Future<Output = Result<String, doc::DocError>>>> {
       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<Location> 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;