mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
refactor: move cli/doc/ to separate crate (#7103)
This commit is contained in:
parent
1507a8cf2d
commit
be1e7ab532
24 changed files with 93 additions and 5683 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -329,6 +329,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"clap",
|
"clap",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
"deno_doc",
|
||||||
"deno_lint",
|
"deno_lint",
|
||||||
"deno_web",
|
"deno_web",
|
||||||
"dissimilar",
|
"dissimilar",
|
||||||
|
@ -392,6 +393,23 @@ dependencies = [
|
||||||
"url",
|
"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]]
|
[[package]]
|
||||||
name = "deno_lint"
|
name = "deno_lint"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
|
|
|
@ -24,9 +24,9 @@ winapi = "0.3.9"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deno_core = { path = "../core", version = "0.53.0" }
|
deno_core = { path = "../core", version = "0.53.0" }
|
||||||
|
deno_doc = { version = "0.1.0" }
|
||||||
deno_lint = { version = "0.1.23", features = ["json"] }
|
deno_lint = { version = "0.1.23", features = ["json"] }
|
||||||
|
|
||||||
|
|
||||||
atty = "0.2.14"
|
atty = "0.2.14"
|
||||||
base64 = "0.12.3"
|
base64 = "0.12.3"
|
||||||
bytes = "0.5.6"
|
bytes = "0.5.6"
|
||||||
|
|
339
cli/doc/class.rs
339
cli/doc/class.rs
|
@ -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(
|
|
||||||
¶m.pat,
|
|
||||||
Some(&doc_parser.ast_parser.source_map),
|
|
||||||
),
|
|
||||||
TsParamProp(ts_param_prop) => {
|
|
||||||
use swc_ecmascript::ast::TsParamPropParam;
|
|
||||||
|
|
||||||
match &ts_param_prop.param {
|
|
||||||
TsParamPropParam::Ident(ident) => ident_to_param_def(
|
|
||||||
ident,
|
|
||||||
Some(&doc_parser.ast_parser.source_map),
|
|
||||||
),
|
|
||||||
TsParamPropParam::Assign(assign_pat) => {
|
|
||||||
assign_pat_to_param_def(
|
|
||||||
assign_pat,
|
|
||||||
Some(&doc_parser.ast_parser.source_map),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
params.push(param_def);
|
|
||||||
}
|
|
||||||
|
|
||||||
let constructor_def = ClassConstructorDef {
|
|
||||||
js_doc: ctor_js_doc,
|
|
||||||
accessibility: ctor.accessibility,
|
|
||||||
name: constructor_name,
|
|
||||||
params,
|
|
||||||
location: doc_parser.ast_parser.get_span_location(ctor.span).into(),
|
|
||||||
};
|
|
||||||
constructors.push(constructor_def);
|
|
||||||
}
|
|
||||||
Method(class_method) => {
|
|
||||||
let method_js_doc = doc_parser.js_doc_for_span(class_method.span());
|
|
||||||
let method_name = prop_name_to_string(
|
|
||||||
&class_method.key,
|
|
||||||
Some(&doc_parser.ast_parser.source_map),
|
|
||||||
);
|
|
||||||
let fn_def =
|
|
||||||
function_to_function_def(&doc_parser, &class_method.function);
|
|
||||||
let method_def = ClassMethodDef {
|
|
||||||
js_doc: method_js_doc,
|
|
||||||
accessibility: class_method.accessibility,
|
|
||||||
optional: class_method.is_optional,
|
|
||||||
is_abstract: class_method.is_abstract,
|
|
||||||
is_static: class_method.is_static,
|
|
||||||
name: method_name,
|
|
||||||
kind: class_method.kind,
|
|
||||||
function_def: fn_def,
|
|
||||||
location: doc_parser
|
|
||||||
.ast_parser
|
|
||||||
.get_span_location(class_method.span)
|
|
||||||
.into(),
|
|
||||||
};
|
|
||||||
methods.push(method_def);
|
|
||||||
}
|
|
||||||
ClassProp(class_prop) => {
|
|
||||||
let prop_js_doc = doc_parser.js_doc_for_span(class_prop.span());
|
|
||||||
|
|
||||||
let ts_type = class_prop
|
|
||||||
.type_ann
|
|
||||||
.as_ref()
|
|
||||||
.map(|rt| ts_type_ann_to_def(rt));
|
|
||||||
|
|
||||||
let prop_name = expr_to_name(&*class_prop.key);
|
|
||||||
|
|
||||||
let prop_def = ClassPropertyDef {
|
|
||||||
js_doc: prop_js_doc,
|
|
||||||
ts_type,
|
|
||||||
readonly: class_prop.readonly,
|
|
||||||
optional: class_prop.is_optional,
|
|
||||||
is_abstract: class_prop.is_abstract,
|
|
||||||
is_static: class_prop.is_static,
|
|
||||||
accessibility: class_prop.accessibility,
|
|
||||||
name: prop_name,
|
|
||||||
location: doc_parser
|
|
||||||
.ast_parser
|
|
||||||
.get_span_location(class_prop.span)
|
|
||||||
.into(),
|
|
||||||
};
|
|
||||||
properties.push(prop_def);
|
|
||||||
}
|
|
||||||
TsIndexSignature(ts_index_sig) => {
|
|
||||||
let mut params = vec![];
|
|
||||||
for param in &ts_index_sig.params {
|
|
||||||
let param_def = ts_fn_param_to_param_def(param, None);
|
|
||||||
params.push(param_def);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ts_type = ts_index_sig
|
|
||||||
.type_ann
|
|
||||||
.as_ref()
|
|
||||||
.map(|rt| (&*rt.type_ann).into());
|
|
||||||
|
|
||||||
let index_sig_def = ClassIndexSignatureDef {
|
|
||||||
readonly: ts_index_sig.readonly,
|
|
||||||
params,
|
|
||||||
ts_type,
|
|
||||||
};
|
|
||||||
index_signatures.push(index_sig_def);
|
|
||||||
}
|
|
||||||
// TODO(bartlomieju):
|
|
||||||
PrivateMethod(_) => {}
|
|
||||||
PrivateProp(_) => {}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let type_params =
|
|
||||||
maybe_type_param_decl_to_type_param_defs(class.type_params.as_ref());
|
|
||||||
|
|
||||||
let super_type_params = maybe_type_param_instantiation_to_type_defs(
|
|
||||||
class.super_type_params.as_ref(),
|
|
||||||
);
|
|
||||||
|
|
||||||
ClassDef {
|
|
||||||
is_abstract: class.is_abstract,
|
|
||||||
extends,
|
|
||||||
implements,
|
|
||||||
constructors,
|
|
||||||
properties,
|
|
||||||
index_signatures,
|
|
||||||
methods,
|
|
||||||
type_params,
|
|
||||||
super_type_params,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_doc_for_class_decl(
|
|
||||||
doc_parser: &DocParser,
|
|
||||||
class_decl: &swc_ecmascript::ast::ClassDecl,
|
|
||||||
) -> (String, ClassDef) {
|
|
||||||
let class_name = class_decl.ident.sym.to_string();
|
|
||||||
let class_def = class_to_class_def(doc_parser, &class_decl.class);
|
|
||||||
|
|
||||||
(class_name, class_def)
|
|
||||||
}
|
|
|
@ -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 { "" })
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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(¶m.pat, Some(&doc_parser.ast_parser.source_map));
|
|
||||||
params.push(param_def);
|
|
||||||
}
|
|
||||||
|
|
||||||
let maybe_return_type = function
|
|
||||||
.return_type
|
|
||||||
.as_ref()
|
|
||||||
.map(|rt| ts_type_ann_to_def(rt));
|
|
||||||
|
|
||||||
let type_params =
|
|
||||||
maybe_type_param_decl_to_type_param_defs(function.type_params.as_ref());
|
|
||||||
|
|
||||||
FunctionDef {
|
|
||||||
params,
|
|
||||||
return_type: maybe_return_type,
|
|
||||||
is_async: function.is_async,
|
|
||||||
is_generator: function.is_generator,
|
|
||||||
type_params,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_doc_for_fn_decl(
|
|
||||||
doc_parser: &DocParser,
|
|
||||||
fn_decl: &swc_ecmascript::ast::FnDecl,
|
|
||||||
) -> (String, FunctionDef) {
|
|
||||||
let name = fn_decl.ident.sym.to_string();
|
|
||||||
let fn_def = function_to_function_def(&doc_parser, &fn_decl.function);
|
|
||||||
(name, fn_def)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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![],
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
287
cli/doc/node.rs
287
cli/doc/node.rs
|
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
2002
cli/doc/tests.rs
2002
cli/doc/tests.rs
File diff suppressed because it is too large
Load diff
|
@ -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![]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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![]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -313,8 +313,8 @@ fn thread_safe() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_should_allow_js() {
|
fn test_should_allow_js() {
|
||||||
use crate::doc::Location;
|
|
||||||
use crate::module_graph::ImportDescriptor;
|
use crate::module_graph::ImportDescriptor;
|
||||||
|
use crate::swc_util::Location;
|
||||||
|
|
||||||
assert!(should_allow_js(&[
|
assert!(should_allow_js(&[
|
||||||
&ModuleGraphFile {
|
&ModuleGraphFile {
|
||||||
|
|
58
cli/main.rs
58
cli/main.rs
|
@ -29,7 +29,6 @@ pub mod deno_dir;
|
||||||
pub mod diagnostics;
|
pub mod diagnostics;
|
||||||
mod diff;
|
mod diff;
|
||||||
mod disk_cache;
|
mod disk_cache;
|
||||||
mod doc;
|
|
||||||
mod file_fetcher;
|
mod file_fetcher;
|
||||||
pub mod flags;
|
pub mod flags;
|
||||||
mod flags_allow_net;
|
mod flags_allow_net;
|
||||||
|
@ -69,14 +68,13 @@ pub mod version;
|
||||||
mod web_worker;
|
mod web_worker;
|
||||||
pub mod 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::SourceFile;
|
||||||
use crate::file_fetcher::SourceFileFetcher;
|
use crate::file_fetcher::SourceFileFetcher;
|
||||||
use crate::file_fetcher::TextDocument;
|
use crate::file_fetcher::TextDocument;
|
||||||
use crate::fs as deno_fs;
|
use crate::fs as deno_fs;
|
||||||
use crate::global_state::GlobalState;
|
use crate::global_state::GlobalState;
|
||||||
use crate::msg::MediaType;
|
use crate::msg::MediaType;
|
||||||
use crate::op_error::OpError;
|
|
||||||
use crate::permissions::Permissions;
|
use crate::permissions::Permissions;
|
||||||
use crate::tsc::TargetLib;
|
use crate::tsc::TargetLib;
|
||||||
use crate::worker::MainWorker;
|
use crate::worker::MainWorker;
|
||||||
|
@ -85,6 +83,8 @@ use deno_core::Deps;
|
||||||
use deno_core::ErrBox;
|
use deno_core::ErrBox;
|
||||||
use deno_core::EsIsolate;
|
use deno_core::EsIsolate;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_doc as doc;
|
||||||
|
use deno_doc::parser::DocFileLoader;
|
||||||
use flags::DenoSubcommand;
|
use flags::DenoSubcommand;
|
||||||
use flags::Flags;
|
use flags::Flags;
|
||||||
use futures::future::FutureExt;
|
use futures::future::FutureExt;
|
||||||
|
@ -505,19 +505,39 @@ async fn doc_command(
|
||||||
let source_file = source_file.unwrap_or_else(|| "--builtin".to_string());
|
let source_file = source_file.unwrap_or_else(|| "--builtin".to_string());
|
||||||
|
|
||||||
impl DocFileLoader for SourceFileFetcher {
|
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(
|
fn load_source_code(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<String, OpError>>>> {
|
) -> Pin<Box<dyn Future<Output = Result<String, doc::DocError>>>> {
|
||||||
let fetcher = self.clone();
|
let fetcher = self.clone();
|
||||||
let specifier = specifier.to_string();
|
let specifier = ModuleSpecifier::resolve_url_or_path(specifier)
|
||||||
|
.expect("Expected valid specifier");
|
||||||
async move {
|
async move {
|
||||||
let specifier = ModuleSpecifier::resolve_url_or_path(&specifier)
|
|
||||||
.map_err(OpError::from)?;
|
|
||||||
let source_file = fetcher
|
let source_file = fetcher
|
||||||
.fetch_source_file(&specifier, None, Permissions::allow_all())
|
.fetch_source_file(&specifier, None, Permissions::allow_all())
|
||||||
.await?;
|
.await
|
||||||
source_file.source_code.to_string().map_err(OpError::from)
|
.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()
|
.boxed_local()
|
||||||
}
|
}
|
||||||
|
@ -525,14 +545,20 @@ async fn doc_command(
|
||||||
|
|
||||||
let loader = Box::new(global_state.file_fetcher.clone());
|
let loader = Box::new(global_state.file_fetcher.clone());
|
||||||
let doc_parser = doc::DocParser::new(loader, private);
|
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" {
|
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 {
|
} else {
|
||||||
let module_specifier =
|
let module_specifier =
|
||||||
ModuleSpecifier::resolve_url_or_path(&source_file).unwrap();
|
ModuleSpecifier::resolve_url_or_path(&source_file).unwrap();
|
||||||
doc_parser
|
doc_parser
|
||||||
.parse_with_reexports(&module_specifier.to_string())
|
.parse_with_reexports(&module_specifier.to_string(), syntax)
|
||||||
.await
|
.await
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -555,9 +581,15 @@ async fn doc_command(
|
||||||
eprintln!("Node {} was not found!", filter);
|
eprintln!("Node {} was not found!", filter);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
format!("{}", doc::DocPrinter::new(&nodes, private))
|
format!(
|
||||||
|
"{}",
|
||||||
|
doc::DocPrinter::new(&nodes, colors::use_color(), private)
|
||||||
|
)
|
||||||
} else {
|
} 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)
|
write_to_stdout_ignore_sigpipe(details.as_bytes()).map_err(ErrBox::from)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
use crate::checksum;
|
use crate::checksum;
|
||||||
use crate::doc::Location;
|
|
||||||
use crate::file_fetcher::map_file_extension;
|
use crate::file_fetcher::map_file_extension;
|
||||||
use crate::file_fetcher::SourceFile;
|
use crate::file_fetcher::SourceFile;
|
||||||
use crate::file_fetcher::SourceFileFetcher;
|
use crate::file_fetcher::SourceFileFetcher;
|
||||||
|
@ -8,6 +7,7 @@ use crate::import_map::ImportMap;
|
||||||
use crate::msg::MediaType;
|
use crate::msg::MediaType;
|
||||||
use crate::op_error::OpError;
|
use crate::op_error::OpError;
|
||||||
use crate::permissions::Permissions;
|
use crate::permissions::Permissions;
|
||||||
|
use crate::swc_util::Location;
|
||||||
use crate::tsc::pre_process_file;
|
use crate::tsc::pre_process_file;
|
||||||
use crate::tsc::ImportDesc;
|
use crate::tsc::ImportDesc;
|
||||||
use crate::tsc::TsReferenceDesc;
|
use crate::tsc::TsReferenceDesc;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
use crate::msg::MediaType;
|
use crate::msg::MediaType;
|
||||||
use deno_core::ErrBox;
|
use deno_core::ErrBox;
|
||||||
|
use serde::Serialize;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -31,6 +32,31 @@ use swc_ecmascript::transforms::fixer;
|
||||||
use swc_ecmascript::transforms::typescript;
|
use swc_ecmascript::transforms::typescript;
|
||||||
use swc_ecmascript::visit::FoldWith;
|
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;
|
struct DummyHandler;
|
||||||
|
|
||||||
impl swc_ecmascript::codegen::Handlers for DummyHandler {}
|
impl swc_ecmascript::codegen::Handlers for DummyHandler {}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::colors;
|
||||||
use crate::diagnostics::Diagnostic;
|
use crate::diagnostics::Diagnostic;
|
||||||
use crate::diagnostics::DiagnosticItem;
|
use crate::diagnostics::DiagnosticItem;
|
||||||
use crate::disk_cache::DiskCache;
|
use crate::disk_cache::DiskCache;
|
||||||
use crate::doc::Location;
|
|
||||||
use crate::file_fetcher::SourceFile;
|
use crate::file_fetcher::SourceFile;
|
||||||
use crate::file_fetcher::SourceFileFetcher;
|
use crate::file_fetcher::SourceFileFetcher;
|
||||||
use crate::flags::Flags;
|
use crate::flags::Flags;
|
||||||
|
@ -20,6 +19,7 @@ use crate::source_maps::SourceMapGetter;
|
||||||
use crate::startup_data;
|
use crate::startup_data;
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
use crate::swc_util::AstParser;
|
use crate::swc_util::AstParser;
|
||||||
|
use crate::swc_util::Location;
|
||||||
use crate::swc_util::SwcDiagnosticBuffer;
|
use crate::swc_util::SwcDiagnosticBuffer;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
use crate::worker::Worker;
|
use crate::worker::Worker;
|
||||||
|
|
Loading…
Reference in a new issue