diff --git a/src/util/swc.rs b/src/util/swc.rs index cb49aecc2..d27123797 100644 --- a/src/util/swc.rs +++ b/src/util/swc.rs @@ -47,7 +47,19 @@ pub(crate) fn js_doc_for_range_include_ignore( if let Some(js_doc_comment) = comments.iter().rev().find(|comment| { comment.kind == CommentKind::Block && comment.text.starts_with('*') }) { - parse_js_doc(js_doc_comment, module_info) + let js_doc = parse_js_doc(js_doc_comment, module_info); + // A `@module` JSDoc block belongs to the file as a whole, not to the + // first symbol that happens to follow it. Without this guard the + // module-level documentation gets duplicated onto the first + // undocumented exported symbol (denoland/deno#30783). + if js_doc + .tags + .iter() + .any(|tag| matches!(tag, JsDocTag::Module { .. })) + { + return JsDoc::default(); + } + js_doc } else { JsDoc::default() } diff --git a/tests/specs/module_docs_undocumented_first_symbol.txt b/tests/specs/module_docs_undocumented_first_symbol.txt new file mode 100644 index 000000000..3feeaa66f --- /dev/null +++ b/tests/specs/module_docs_undocumented_first_symbol.txt @@ -0,0 +1,97 @@ +# mod.ts +/** + * The module docs. + * + * @module + */ + +export function foo() {} + +/** This is the bar function. */ +export function bar() {} + +# diagnostics +error[missing-jsdoc]: exported symbol is missing JSDoc documentation + --> /mod.ts:7:1 + | +7 | export function foo() {} + | ^ + +# output.txt +The module docs. +@module + +Defined in file:///mod.ts:9:1 + +function bar(): void + This is the bar function. + +Defined in file:///mod.ts:6:1 + +function foo(): void + + +# output.json +{ + "module_doc": { + "doc": "The module docs.\n", + "tags": [ + { + "kind": "module" + } + ] + }, + "symbols": [ + { + "name": "foo", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 6, + "col": 0, + "byteIndex": 43 + }, + "declarationKind": "export", + "kind": "function", + "def": { + "params": [], + "returnType": { + "repr": "void", + "kind": "keyword", + "value": "void" + }, + "hasBody": true + } + } + ] + }, + { + "name": "bar", + "declarations": [ + { + "location": { + "filename": "file:///mod.ts", + "line": 9, + "col": 0, + "byteIndex": 102 + }, + "declarationKind": "export", + "jsDoc": { + "doc": "This is the bar function." + }, + "kind": "function", + "def": { + "params": [], + "returnType": { + "repr": "void", + "kind": "keyword", + "value": "void" + }, + "hasBody": true + } + } + ] + } + ] +}