diff options
Diffstat (limited to 'cli/doc/class.rs')
-rw-r--r-- | cli/doc/class.rs | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/cli/doc/class.rs b/cli/doc/class.rs new file mode 100644 index 000000000..635fd585a --- /dev/null +++ b/cli/doc/class.rs @@ -0,0 +1,207 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +use serde::Serialize; +use swc_common; +use swc_common::SourceMap; +use swc_common::Spanned; +use swc_ecma_ast; + +use super::function::function_to_function_def; +use super::function::FunctionDef; +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 ClassConstructorDef { + pub js_doc: Option<String>, + pub accessibility: Option<swc_ecma_ast::Accessibility>, + pub name: String, + pub params: Vec<ParamDef>, + pub location: Location, +} + +#[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_ecma_ast::Accessibility>, + pub is_abstract: bool, + pub is_static: bool, + pub name: String, + pub location: Location, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ClassMethodDef { + pub js_doc: Option<String>, + // pub ts_type: Option<TsTypeDef>, + // pub readonly: bool, + pub accessibility: Option<swc_ecma_ast::Accessibility>, + pub is_abstract: bool, + pub is_static: bool, + pub name: String, + pub kind: swc_ecma_ast::MethodKind, + pub function_def: FunctionDef, + pub location: Location, +} + +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ClassDef { + // TODO: decorators, super_class, implements, + // type_params, super_type_params + pub is_abstract: bool, + pub constructors: Vec<ClassConstructorDef>, + pub properties: Vec<ClassPropertyDef>, + pub methods: Vec<ClassMethodDef>, +} + +fn prop_name_to_string( + source_map: &SourceMap, + prop_name: &swc_ecma_ast::PropName, +) -> String { + use swc_ecma_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.span_to_snippet(comp_prop_name.span).unwrap() + } + } +} + +pub fn get_doc_for_class_decl( + doc_parser: &DocParser, + class_decl: &swc_ecma_ast::ClassDecl, +) -> (String, ClassDef) { + let mut constructors = vec![]; + let mut methods = vec![]; + let mut properties = vec![]; + + for member in &class_decl.class.body { + use swc_ecma_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(&doc_parser.source_map, &ctor.key); + + let mut params = vec![]; + + for param in &ctor.params { + use swc_ecma_ast::Pat; + use swc_ecma_ast::PatOrTsParamProp::*; + + let param_def = match param { + Pat(pat) => match pat { + Pat::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, + }, + }, + TsParamProp(_) => ParamDef { + name: "<TODO>".to_string(), + ts_type: None, + }, + }; + params.push(param_def); + } + + let constructor_def = ClassConstructorDef { + js_doc: ctor_js_doc, + accessibility: ctor.accessibility, + name: constructor_name, + params, + location: doc_parser + .source_map + .lookup_char_pos(ctor.span.lo()) + .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(&doc_parser.source_map, &class_method.key); + 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, + 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 + .source_map + .lookup_char_pos(class_method.span.lo()) + .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(&doc_parser.source_map, rt)); + + use swc_ecma_ast::Expr; + let prop_name = match &*class_prop.key { + Expr::Ident(ident) => ident.sym.to_string(), + _ => "<TODO>".to_string(), + }; + + let prop_def = ClassPropertyDef { + js_doc: prop_js_doc, + ts_type, + readonly: class_prop.readonly, + is_abstract: class_prop.is_abstract, + is_static: class_prop.is_static, + accessibility: class_prop.accessibility, + name: prop_name, + location: doc_parser + .source_map + .lookup_char_pos(class_prop.span.lo()) + .into(), + }; + properties.push(prop_def); + } + // TODO: + TsIndexSignature(_) => {} + PrivateMethod(_) => {} + PrivateProp(_) => {} + } + } + + let class_name = class_decl.ident.sym.to_string(); + let class_def = ClassDef { + is_abstract: class_decl.class.is_abstract, + constructors, + properties, + methods, + }; + + (class_name, class_def) +} |