From 6d15d9c2eb4397b15908cda38f2e44e02d81ebc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Fri, 20 Sep 2024 14:44:20 +0900 Subject: [PATCH] fix(es/isolated-dts): Preserve comments (#9572) **Related issue:** - Closes https://github.com/swc-project/swc/issues/9550 --- .changeset/itchy-socks-marry.md | 6 ++++++ crates/swc/src/lib.rs | 14 +++++++++++--- .../ts-isolated-declaration/issues/input/.swcrc | 11 +++++++++++ .../issues/input/swc-issue-9550.ts | 9 +++++++++ .../issues/output/swc-issue-9550.d.ts | 6 ++++++ .../issues/output/swc-issue-9550.ts | 11 +++++++++++ .../oxc/output/async-function.d.ts | 3 +++ .../oxc/output/function-parameters.d.ts | 2 ++ .../oxc/output/generator.d.ts | 3 +++ .../oxc/output/infer-expression.d.ts | 1 + .../oxc/output/infer-return-type.d.ts | 3 +++ .../oxc/output/non-exported-binding-elements.d.ts | 2 ++ 12 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 .changeset/itchy-socks-marry.md create mode 100644 crates/swc/tests/ts-isolated-declaration/issues/input/.swcrc create mode 100644 crates/swc/tests/ts-isolated-declaration/issues/input/swc-issue-9550.ts create mode 100644 crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.d.ts create mode 100644 crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.ts diff --git a/.changeset/itchy-socks-marry.md b/.changeset/itchy-socks-marry.md new file mode 100644 index 000000000000..d4d5f348d53b --- /dev/null +++ b/.changeset/itchy-socks-marry.md @@ -0,0 +1,6 @@ +--- +swc_core: patch +swc: patch +--- + +fix(es/isolated-dts): Preserve comments diff --git a/crates/swc/src/lib.rs b/crates/swc/src/lib.rs index 83f5e11158a6..af0c54c11115 100644 --- a/crates/swc/src/lib.rs +++ b/crates/swc/src/lib.rs @@ -113,6 +113,7 @@ pub extern crate swc_atoms as atoms; extern crate swc_common as common; use std::{ + cell::RefCell, fs::{read_to_string, File}, io::ErrorKind, path::{Path, PathBuf}, @@ -136,7 +137,7 @@ use swc_common::{ pub use swc_compiler_base::{PrintArgs, TransformOutput}; pub use swc_config::config_types::{BoolConfig, BoolOr, BoolOrDataConfig}; use swc_ecma_ast::{EsVersion, Program}; -use swc_ecma_codegen::{to_code, Node}; +use swc_ecma_codegen::{to_code_with_comments, Node}; use swc_ecma_loader::resolvers::{ lru::CachingResolver, node::NodeModulesResolver, tsc::TsConfigResolver, }; @@ -724,7 +725,7 @@ impl Compiler { None }; - self.apply_transforms(handler, fm.clone(), orig.as_ref(), config) + self.apply_transforms(handler, comments.clone(), fm.clone(), orig.as_ref(), config) }) } @@ -944,6 +945,7 @@ impl Compiler { fn apply_transforms( &self, handler: &Handler, + comments: SingleThreadedComments, fm: Arc, orig: Option<&sourcemap::SourceMap>, config: BuiltInput, @@ -971,6 +973,12 @@ impl Compiler { }; let dts_code = if emit_dts && program.is_module() { + let (leading, trailing) = comments.borrow_all(); + + let leading = std::rc::Rc::new(RefCell::new(leading.clone())); + let trailing = std::rc::Rc::new(RefCell::new(trailing.clone())); + + let comments = SingleThreadedComments::from_leading_and_trailing(leading, trailing); let mut checker = FastDts::new(fm.name.clone()); let mut module = program.clone().expect_module(); @@ -983,7 +991,7 @@ impl Compiler { .struct_span_err(range.span, &issue.to_string()) .emit(); } - let dts_code = to_code(&module); + let dts_code = to_code_with_comments(Some(&comments), &module); Some(dts_code) } else { None diff --git a/crates/swc/tests/ts-isolated-declaration/issues/input/.swcrc b/crates/swc/tests/ts-isolated-declaration/issues/input/.swcrc new file mode 100644 index 000000000000..e9f895b14bf1 --- /dev/null +++ b/crates/swc/tests/ts-isolated-declaration/issues/input/.swcrc @@ -0,0 +1,11 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "experimental": { + "emitIsolatedDts": true + } + }, + "isModule": true +} \ No newline at end of file diff --git a/crates/swc/tests/ts-isolated-declaration/issues/input/swc-issue-9550.ts b/crates/swc/tests/ts-isolated-declaration/issues/input/swc-issue-9550.ts new file mode 100644 index 000000000000..f55a412fc6ac --- /dev/null +++ b/crates/swc/tests/ts-isolated-declaration/issues/input/swc-issue-9550.ts @@ -0,0 +1,9 @@ +/** + * Sample JSDoc that I wish was in the swc.transform output + * @param a - string param + * @param b - number param + * @returns - object with a and b + */ +function sampleFunc(a: string, b: number) { + return { a, b }; +} diff --git a/crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.d.ts b/crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.d.ts new file mode 100644 index 000000000000..446cdb086be8 --- /dev/null +++ b/crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.d.ts @@ -0,0 +1,6 @@ +/** + * Sample JSDoc that I wish was in the swc.transform output + * @param a - string param + * @param b - number param + * @returns - object with a and b + */ declare function sampleFunc(a: string, b: number); diff --git a/crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.ts b/crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.ts new file mode 100644 index 000000000000..9656554ea959 --- /dev/null +++ b/crates/swc/tests/ts-isolated-declaration/issues/output/swc-issue-9550.ts @@ -0,0 +1,11 @@ +/** + * Sample JSDoc that I wish was in the swc.transform output + * @param a - string param + * @param b - number param + * @returns - object with a and b + */ function sampleFunc(a, b) { + return { + a: a, + b: b + }; +} diff --git a/crates/swc/tests/ts-isolated-declaration/oxc/output/async-function.d.ts b/crates/swc/tests/ts-isolated-declaration/oxc/output/async-function.d.ts index f53fab55e8b1..c6c11dd53c29 100644 --- a/crates/swc/tests/ts-isolated-declaration/oxc/output/async-function.d.ts +++ b/crates/swc/tests/ts-isolated-declaration/oxc/output/async-function.d.ts @@ -1,4 +1,7 @@ +// Correct declare async function asyncFunctionGood(): Promise; declare const asyncFunctionGoo2: () => Promise; +// Need to explicit return type for async functions +// Incorrect declare async function asyncFunction(); declare const asyncFunction2: () => any; diff --git a/crates/swc/tests/ts-isolated-declaration/oxc/output/function-parameters.d.ts b/crates/swc/tests/ts-isolated-declaration/oxc/output/function-parameters.d.ts index facbc14cbd0a..7612081270dc 100644 --- a/crates/swc/tests/ts-isolated-declaration/oxc/output/function-parameters.d.ts +++ b/crates/swc/tests/ts-isolated-declaration/oxc/output/function-parameters.d.ts @@ -1,3 +1,4 @@ +// Correct export declare function fnDeclGood(p?: T, rParam?: string): void; export declare function fnDeclGood2(p?: T, rParam?: number): void; export declare function fooGood([a, b]?: any[]): number; @@ -5,6 +6,7 @@ export declare const fooGood2: (_dts_1: { a: number; b: number; }) => number; +// Incorrect export declare function fnDeclBad(p?: T, rParam?: T, r2: T): void; export declare function fnDeclBad2(p?: T, r2: T): void; export declare function fnDeclBad3(p?: T, rParam?: T, r2: T): void; diff --git a/crates/swc/tests/ts-isolated-declaration/oxc/output/generator.d.ts b/crates/swc/tests/ts-isolated-declaration/oxc/output/generator.d.ts index 343e7e950f92..bf6a530fdd26 100644 --- a/crates/swc/tests/ts-isolated-declaration/oxc/output/generator.d.ts +++ b/crates/swc/tests/ts-isolated-declaration/oxc/output/generator.d.ts @@ -1,2 +1,5 @@ +// Correct declare function* generatorGood(): Generator; +// Need to explicit return type for async functions +// Incorrect declare function* generatorGoodBad(); diff --git a/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-expression.d.ts b/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-expression.d.ts index a9884bfb02a7..5634a146251b 100644 --- a/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-expression.d.ts +++ b/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-expression.d.ts @@ -1,3 +1,4 @@ +// ParenthesizedExpression declare const n: any; declare const s: any; declare const t: any; diff --git a/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-return-type.d.ts b/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-return-type.d.ts index ba834d2b51b8..71e08e31a912 100644 --- a/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-return-type.d.ts +++ b/crates/swc/tests/ts-isolated-declaration/oxc/output/infer-return-type.d.ts @@ -1,4 +1,7 @@ declare function foo(); +// inferred type is number declare function bar(); +// inferred type is number | undefined declare function baz(); +// We can't infer return type if there are multiple return statements with different types declare function qux(); diff --git a/crates/swc/tests/ts-isolated-declaration/oxc/output/non-exported-binding-elements.d.ts b/crates/swc/tests/ts-isolated-declaration/oxc/output/non-exported-binding-elements.d.ts index b1eb175014d7..fdca39fedcb6 100644 --- a/crates/swc/tests/ts-isolated-declaration/oxc/output/non-exported-binding-elements.d.ts +++ b/crates/swc/tests/ts-isolated-declaration/oxc/output/non-exported-binding-elements.d.ts @@ -1,5 +1,7 @@ +// Correct declare const [A, B]; export declare function foo(): number; +// Incorrect declare const { c, d }; declare const [e]; export { c, d, e };