diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-03-28 19:16:57 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-28 14:16:57 -0400 |
commit | 3fac487461abf055165fe0e2bb962573950277b8 (patch) | |
tree | c0ba09a2049975f9eb8625365e3ba395e67d8b50 /cli/doc/interface.rs | |
parent | bced52505f32d6cca4f944bb610a8a26767908a8 (diff) |
feat: Add "deno doc" subcommand (#4500)
Diffstat (limited to 'cli/doc/interface.rs')
-rw-r--r-- | cli/doc/interface.rs | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/cli/doc/interface.rs b/cli/doc/interface.rs new file mode 100644 index 000000000..b7e123773 --- /dev/null +++ b/cli/doc/interface.rs @@ -0,0 +1,243 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +use serde::Serialize; +use swc_ecma_ast; + +use super::parser::DocParser; +use super::ts_type::ts_type_ann_to_def; +use super::ts_type::TsTypeDef; +use super::Location; +use super::ParamDef; + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct InterfaceMethodDef { + // TODO: type_params + pub name: String, + pub location: Location, + pub js_doc: Option<String>, + pub params: Vec<ParamDef>, + pub return_type: Option<TsTypeDef>, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct InterfacePropertyDef { + // TODO: type_params + 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>, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct InterfaceCallSignatureDef { + // TODO: type_params + pub location: Location, + pub js_doc: Option<String>, + pub params: Vec<ParamDef>, + pub ts_type: Option<TsTypeDef>, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct InterfaceDef { + // TODO: extends, type params + pub methods: Vec<InterfaceMethodDef>, + pub properties: Vec<InterfacePropertyDef>, + pub call_signatures: Vec<InterfaceCallSignatureDef>, +} + +fn expr_to_name(expr: &swc_ecma_ast::Expr) -> String { + use swc_ecma_ast::Expr::*; + use swc_ecma_ast::ExprOrSuper::*; + + match expr { + Ident(ident) => ident.sym.to_string(), + Member(member_expr) => { + let left = match &member_expr.obj { + Super(_) => "TODO".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_ecma_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![]; + + for type_element in &interface_decl.body.body { + use swc_ecma_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 { + use swc_ecma_ast::TsFnParam::*; + + let param_def = match param { + Ident(ident) => { + let ts_type = ident + .type_ann + .as_ref() + .map(|rt| ts_type_ann_to_def(&doc_parser.source_map, rt)); + + ParamDef { + name: ident.sym.to_string(), + ts_type, + } + } + _ => ParamDef { + name: "<TODO>".to_string(), + ts_type: None, + }, + }; + + 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(&doc_parser.source_map, rt)); + + let method_def = InterfaceMethodDef { + name, + js_doc: method_js_doc, + location: doc_parser + .source_map + .lookup_char_pos(ts_method_sig.span.lo()) + .into(), + params, + return_type: maybe_return_type, + }; + methods.push(method_def); + } + TsPropertySignature(ts_prop_sig) => { + let prop_js_doc = doc_parser.js_doc_for_span(ts_prop_sig.span); + let name = match &*ts_prop_sig.key { + swc_ecma_ast::Expr::Ident(ident) => ident.sym.to_string(), + _ => "TODO".to_string(), + }; + + let mut params = vec![]; + + for param in &ts_prop_sig.params { + use swc_ecma_ast::TsFnParam::*; + + let param_def = match param { + Ident(ident) => { + let ts_type = ident + .type_ann + .as_ref() + .map(|rt| ts_type_ann_to_def(&doc_parser.source_map, rt)); + + ParamDef { + name: ident.sym.to_string(), + ts_type, + } + } + _ => ParamDef { + name: "<TODO>".to_string(), + ts_type: None, + }, + }; + + params.push(param_def); + } + + let ts_type = ts_prop_sig + .type_ann + .as_ref() + .map(|rt| ts_type_ann_to_def(&doc_parser.source_map, rt)); + + let prop_def = InterfacePropertyDef { + name, + js_doc: prop_js_doc, + location: doc_parser + .source_map + .lookup_char_pos(ts_prop_sig.span.lo()) + .into(), + params, + ts_type, + computed: ts_prop_sig.computed, + optional: ts_prop_sig.optional, + }; + 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 { + use swc_ecma_ast::TsFnParam::*; + + let param_def = match param { + Ident(ident) => { + let ts_type = ident + .type_ann + .as_ref() + .map(|rt| ts_type_ann_to_def(&doc_parser.source_map, rt)); + + ParamDef { + name: ident.sym.to_string(), + ts_type, + } + } + _ => ParamDef { + name: "<TODO>".to_string(), + ts_type: None, + }, + }; + + params.push(param_def); + } + + let ts_type = ts_call_sig + .type_ann + .as_ref() + .map(|rt| ts_type_ann_to_def(&doc_parser.source_map, rt)); + + let call_sig_def = InterfaceCallSignatureDef { + js_doc: call_sig_js_doc, + location: doc_parser + .source_map + .lookup_char_pos(ts_call_sig.span.lo()) + .into(), + params, + ts_type, + }; + call_signatures.push(call_sig_def); + } + // TODO: + TsConstructSignatureDecl(_) => {} + TsIndexSignature(_) => {} + } + } + + let interface_def = InterfaceDef { + methods, + properties, + call_signatures, + }; + + (interface_name, interface_def) +} |