From c7d98b9ee1603bb4ae1517dda9339cabd0079237 Mon Sep 17 00:00:00 2001 From: Robert Masen Date: Mon, 9 Jul 2018 11:07:57 -0500 Subject: [PATCH 1/2] add js doc @param and @returns annotations --- crates/cli-support/src/js/js2rust.rs | 12 ++++++++-- crates/cli-support/src/js/mod.rs | 33 +++++++++++++++++----------- crates/cli-support/src/js/rust2js.rs | 4 ++-- tests/all/comments.rs | 3 ++- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index b67352fb3..5664209e4 100644 --- a/crates/cli-support/src/js/js2rust.rs +++ b/crates/cli-support/src/js/js2rust.rs @@ -368,6 +368,14 @@ impl<'a, 'b> Js2Rust<'a, 'b> { Ok(self) } + pub fn js_doc_comments(&self) -> String { + let mut ret: String = self.js_arguments.iter().map(|a| { + format!("@param {{{}}} {}\n", a.1, a.0) + }).collect(); + ret.push_str(&format!("@returns {{{}}}", self.ret_ty)); + ret + } + /// Generate the actual function. /// /// The `prefix` specified is typically the string "function" but may be @@ -377,7 +385,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { /// Returns two strings, the first of which is the JS expression for the /// generated function shim and the second is a TypeScript signature of the /// JS expression. - pub fn finish(&self, prefix: &str, invoc: &str) -> (String, String) { + pub fn finish(&self, prefix: &str, invoc: &str) -> (String, String, String) { let js_args = self .js_arguments .iter() @@ -417,6 +425,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> { "{} {}({}): {};\n", prefix, self.js_name, ts_args, self.ret_ty ); - (js, ts) + (js, ts, self.js_doc_comments()) } } diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 3a95720c7..ca8ce2336 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -43,7 +43,7 @@ pub struct ExportedClass { } struct ClassField { - comments: String, + comments: Vec, name: String, readonly: bool, } @@ -55,7 +55,6 @@ pub struct SubContext<'a, 'b: 'a> { impl<'a> Context<'a> { fn export(&mut self, name: &str, contents: &str, comments: Option) { - let contents = contents; let contents = contents.trim(); if let Some(ref c) = comments { self.globals.push_str(c); @@ -596,14 +595,14 @@ impl<'a> Context<'a> { )); cx.finish("", &format!("wasm.{}", wasm_setter)).0 }; - let (get, _ts) = Js2Rust::new(&field.name, self) + let (get, _ts, js_doc) = Js2Rust::new(&field.name, self) .method(true, false) .ret(&Some(descriptor))? .finish("", &format!("wasm.{}", wasm_getter)); if !dst.ends_with("\n") { dst.push_str("\n"); } - dst.push_str(&field.comments); + dst.push_str(&format_doc_comments(&field.comments, Some(js_doc))); dst.push_str("get "); dst.push_str(&field.name); dst.push_str(&get); @@ -1653,11 +1652,11 @@ impl<'a, 'b> SubContext<'a, 'b> { .exported_classes .entry(s.name.clone()) .or_insert_with(Default::default); - class.comments = format_doc_comments(&s.comments); + class.comments = format_doc_comments(&s.comments, None); class.fields.extend(s.fields.iter().map(|f| ClassField { name: f.name.clone(), readonly: f.readonly, - comments: format_doc_comments(&f.comments), + comments: f.comments.clone(), })); } @@ -1674,13 +1673,13 @@ impl<'a, 'b> SubContext<'a, 'b> { Some(d) => d, }; - let (js, ts) = Js2Rust::new(&export.function.name, self.cx) + let (js, ts, js_doc) = Js2Rust::new(&export.function.name, self.cx) .process(descriptor.unwrap_function())? .finish("function", &format!("wasm.{}", export.function.name)); self.cx.export( &export.function.name, &js, - Some(format_doc_comments(&export.comments)), + Some(format_doc_comments(&export.comments, Some(js_doc))), ); self.cx.globals.push_str("\n"); self.cx.typescript.push_str("export "); @@ -1701,10 +1700,11 @@ impl<'a, 'b> SubContext<'a, 'b> { Some(d) => d, }; - let (js, ts) = Js2Rust::new(&export.function.name, self.cx) + let (js, ts, js_doc) = Js2Rust::new(&export.function.name, self.cx) .method(export.method, export.consumed) .process(descriptor.unwrap_function())? .finish("", &format!("wasm.{}", wasm_name)); + let class = self .cx .exported_classes @@ -1712,7 +1712,7 @@ impl<'a, 'b> SubContext<'a, 'b> { .or_insert(ExportedClass::default()); class .contents - .push_str(&format_doc_comments(&export.comments)); + .push_str(&format_doc_comments(&export.comments, Some(js_doc))); if !export.method { class.contents.push_str("static "); class.typescript.push_str("static "); @@ -1960,7 +1960,7 @@ impl<'a, 'b> SubContext<'a, 'b> { self.cx.export( &enum_.name, &format!("Object.freeze({{ {} }})", variants), - Some(format_doc_comments(&enum_.comments)), + Some(format_doc_comments(&enum_.comments, None)), ); self.cx .typescript @@ -2011,10 +2011,17 @@ impl<'a, 'b> SubContext<'a, 'b> { } } -fn format_doc_comments(comments: &Vec) -> String { +fn format_doc_comments(comments: &Vec, js_doc_comments: Option) -> String { let body: String = comments .iter() .map(|c| format!("*{}\n", c.trim_matches('"'))) .collect(); - format!("/**\n{}*/\n", body) + let doc = if let Some(docs) = js_doc_comments { + docs.lines() + .map(|l| format!("* {} \n", l)) + .collect() + } else { + String::new() + }; + format!("/**\n{}{}*/\n", body, doc) } diff --git a/crates/cli-support/src/js/rust2js.rs b/crates/cli-support/src/js/rust2js.rs index 1b6726029..ec9ad937e 100644 --- a/crates/cli-support/src/js/rust2js.rs +++ b/crates/cli-support/src/js/rust2js.rs @@ -142,7 +142,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { } if let Some((f, mutable)) = arg.stack_closure() { - let (js, _ts) = { + let (js, _ts, _js_doc) = { let mut builder = Js2Rust::new("", self.cx); if mutable { builder @@ -179,7 +179,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { } if let Some(closure) = arg.ref_closure() { - let (js, _ts) = { + let (js, _ts, _js_doc) = { let mut builder = Js2Rust::new("", self.cx); if closure.mutable { builder diff --git a/tests/all/comments.rs b/tests/all/comments.rs index 30ceb7c2b..d6fdf3f07 100644 --- a/tests/all/comments.rs +++ b/tests/all/comments.rs @@ -41,7 +41,8 @@ fn works() { p.gen_bindings(); let js = p.read_js(); let comments = extract_doc_comments(&js); - assert!(comments.iter().all(|c| c == "This comment should exist")); + assert!(comments.iter().all(|c| c == "This comment should exist" || + c.starts_with("@"))); } /// Pull out all lines in a js string that start with From 1d826e96de5d3d088ed7b474fba723b2ef292829 Mon Sep 17 00:00:00 2001 From: Robert Masen Date: Mon, 9 Jul 2018 14:55:25 -0500 Subject: [PATCH 2/2] fix reformatting for new syntax --- crates/cli-support/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index 728678f42..410700f3d 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -443,7 +443,7 @@ fn reset_indentation(s: &str) -> String { for line in s.lines() { let line = line.trim(); - if line.starts_with('}') || line.ends_with('}') { + if line.starts_with('}') || (line.ends_with('}') && !line.starts_with('*')) { indent = indent.saturating_sub(1); } let extra = if line.starts_with(':') || line.starts_with('?') { 1 } else { 0 };