1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00

fix(doc): Safely deal with optional type (#4526)

This commit is contained in:
Luca Casonato 2020-03-30 04:41:27 +02:00 committed by GitHub
parent 92f1c71a6f
commit d795d34362
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 30 deletions

View file

@ -90,12 +90,8 @@ fn format_(doc_nodes: Vec<doc::DocNode>, indent: i64) -> String {
for node in sorted { for node in sorted {
output.push_str(&format_signature(&node, indent)); output.push_str(&format_signature(&node, indent));
if node.js_doc.is_some() { if let Some(js_doc) = node.js_doc {
output.push_str(&format_jsdoc( output.push_str(&format_jsdoc(js_doc, true, indent));
node.js_doc.as_ref().unwrap().to_string(),
true,
indent,
));
} }
output.push_str("\n"); output.push_str("\n");
if DocNodeKind::Namespace == node.kind { if DocNodeKind::Namespace == node.kind {
@ -115,9 +111,9 @@ fn render_params(params: Vec<doc::ParamDef>) -> String {
if !params.is_empty() { if !params.is_empty() {
for param in params { for param in params {
rendered += param.name.as_str(); rendered += param.name.as_str();
if param.ts_type.is_some() { if let Some(ts_type) = param.ts_type {
rendered += ": "; rendered += ": ";
rendered += render_ts_type(param.ts_type.unwrap()).as_str(); rendered += render_ts_type(ts_type).as_str();
} }
rendered += ", "; rendered += ", ";
} }
@ -215,25 +211,40 @@ fn render_ts_type(ts_type: doc::ts_type::TsTypeDef) -> String {
let type_literal = ts_type.type_literal.unwrap(); let type_literal = ts_type.type_literal.unwrap();
for node in type_literal.call_signatures { for node in type_literal.call_signatures {
output += format!( output += format!(
"({}): {}, ", "({}){}, ",
render_params(node.params), render_params(node.params),
render_ts_type(node.ts_type.unwrap()) if let Some(ts_type) = node.ts_type {
format!(": {}", render_ts_type(ts_type))
} else {
"".to_string()
}
) )
.as_str() .as_str()
} }
for node in type_literal.methods { for node in type_literal.methods {
output += format!( output += format!(
"{}({}): {}, ", "{}({}){}, ",
node.name, node.name,
render_params(node.params), render_params(node.params),
render_ts_type(node.return_type.unwrap()) if let Some(return_type) = node.return_type {
format!(": {}", render_ts_type(return_type))
} else {
"".to_string()
}
) )
.as_str() .as_str()
} }
for node in type_literal.properties { for node in type_literal.properties {
output += output += format!(
format!("{}: {}, ", node.name, render_ts_type(node.ts_type.unwrap())) "{}{}, ",
.as_str() node.name,
if let Some(ts_type) = node.ts_type {
format!(": {}", render_ts_type(ts_type))
} else {
"".to_string()
}
)
.as_str()
} }
if !output.is_empty() { if !output.is_empty() {
output.truncate(output.len() - 2); output.truncate(output.len() - 2);
@ -250,9 +261,8 @@ fn render_ts_type(ts_type: doc::ts_type::TsTypeDef) -> String {
TsTypeDefKind::TypeRef => { TsTypeDefKind::TypeRef => {
let type_ref = ts_type.type_ref.unwrap(); let type_ref = ts_type.type_ref.unwrap();
let mut final_output = type_ref.type_name; let mut final_output = type_ref.type_name;
if type_ref.type_params.is_some() { if let Some(type_params) = type_ref.type_params {
let mut output = "".to_string(); let mut output = "".to_string();
let type_params = type_ref.type_params.unwrap();
if !type_params.is_empty() { if !type_params.is_empty() {
for ts_type in type_params { for ts_type in type_params {
output += render_ts_type(ts_type).as_str(); output += render_ts_type(ts_type).as_str();
@ -328,7 +338,7 @@ fn format_class_details(node: doc::DocNode) -> String {
}) { }) {
details.push_str(&add_indent( details.push_str(&add_indent(
format!( format!(
"{}{}: {}\n", "{}{}{}\n",
colors::magenta( colors::magenta(
match node match node
.accessibility .accessibility
@ -339,7 +349,11 @@ fn format_class_details(node: doc::DocNode) -> String {
} }
), ),
colors::bold(node.name.clone()), colors::bold(node.name.clone()),
render_ts_type(node.ts_type.clone().unwrap()) if let Some(ts_type) = node.ts_type.clone() {
format!(": {}", render_ts_type(ts_type))
} else {
"".to_string()
}
), ),
1, 1,
)); ));
@ -353,7 +367,7 @@ fn format_class_details(node: doc::DocNode) -> String {
let function_def = node.function_def.clone(); let function_def = node.function_def.clone();
details.push_str(&add_indent( details.push_str(&add_indent(
format!( format!(
"{}{}{}({}): {}\n", "{}{}{}({}){}\n",
colors::magenta( colors::magenta(
match node match node
.accessibility .accessibility
@ -370,7 +384,11 @@ fn format_class_details(node: doc::DocNode) -> String {
}), }),
colors::bold(node.name.clone()), colors::bold(node.name.clone()),
render_params(function_def.params), render_params(function_def.params),
render_ts_type(function_def.return_type.unwrap()) if let Some(return_type) = function_def.return_type {
format!(": {}", render_ts_type(return_type))
} else {
"".to_string()
}
), ),
1, 1,
)); ));
@ -392,17 +410,17 @@ fn format_namespace_details(node: doc::DocNode) -> String {
fn format_function_signature(node: &doc::DocNode, indent: i64) -> String { fn format_function_signature(node: &doc::DocNode, indent: i64) -> String {
let function_def = node.function_def.clone().unwrap(); let function_def = node.function_def.clone().unwrap();
let return_type = function_def.return_type.unwrap();
add_indent( add_indent(
format!( format!(
"{} {}{}\n", "{} {}({}){}\n",
colors::magenta("function".to_string()), colors::magenta("function".to_string()),
colors::bold(node.name.clone()), colors::bold(node.name.clone()),
format!( render_params(function_def.params),
"({}): {}", if let Some(return_type) = function_def.return_type {
render_params(function_def.params), format!(": {}", render_ts_type(return_type).as_str())
render_ts_type(return_type).as_str() } else {
) "".to_string()
}
), ),
indent, indent,
) )
@ -430,8 +448,8 @@ fn format_variable_signature(node: &doc::DocNode, indent: i64) -> String {
swc_ecma_ast::VarDeclKind::Var => "var".to_string(), swc_ecma_ast::VarDeclKind::Var => "var".to_string(),
}), }),
colors::bold(node.name.clone()), colors::bold(node.name.clone()),
if variable_def.ts_type.is_some() { if let Some(ts_type) = variable_def.ts_type {
format!(": {}", render_ts_type(variable_def.ts_type.unwrap())) format!(": {}", render_ts_type(ts_type))
} else { } else {
"".to_string() "".to_string()
} }

View file

@ -590,3 +590,49 @@ export namespace RootNs {
.contains("namespace RootNs") .contains("namespace RootNs")
); );
} }
#[test]
fn optional_return_type() {
let source_code = r#"
export function foo(a: number) {
return a;
}
"#;
let entries = DocParser::default()
.parse("test.ts".to_string(), source_code.to_string())
.unwrap();
assert_eq!(entries.len(), 1);
let entry = &entries[0];
let expected_json = json!({
"kind": "function",
"name": "foo",
"location": {
"filename": "test.ts",
"line": 2,
"col": 2
},
"jsDoc": null,
"functionDef": {
"params": [
{
"name": "a",
"tsType": {
"keyword": "number",
"kind": "keyword",
"repr": "number",
},
}
],
"returnType": null,
"isAsync": false,
"isGenerator": false
}
});
let actual = serde_json::to_value(entry).unwrap();
assert_eq!(actual, expected_json);
assert!(
colors::strip_ansi_codes(super::printer::format(entries).as_str())
.contains("function foo(a: number)")
);
}