diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index b67352fb..5664209e 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 3a95720c..ca8ce233 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 1b672602..ec9ad937 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 30ceb7c2..d6fdf3f0 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