feat(codegen): print comments in TSTypeLiteral (#8679)

fixes #8665
This commit is contained in:
Boshen 2025-01-23 14:31:55 +00:00
parent 23b49a665f
commit 99607d3f82
11 changed files with 168 additions and 122 deletions

View file

@ -59,6 +59,9 @@ impl Codegen<'_> {
}
pub(crate) fn print_leading_comments(&mut self, start: u32) {
if !self.print_comments {
return;
}
let Some(comments) = self.comments.remove(&start) else {
return;
};

View file

@ -2350,9 +2350,7 @@ impl Gen for ClassBody<'_> {
p.print_curly_braces(self.span, self.body.is_empty(), |p| {
for item in &self.body {
p.print_semicolon_if_needed();
if p.print_comments {
p.print_leading_comments(item.span().start);
}
p.print_leading_comments(item.span().start);
p.print_indent();
item.print(p, ctx);
}
@ -3296,21 +3294,15 @@ impl Gen for TSTemplateLiteralType<'_> {
impl Gen for TSTypeLiteral<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
let single_line = self.members.len() <= 1;
p.print_curly_braces(self.span, single_line, |p| {
p.print_curly_braces(self.span, self.members.is_empty(), |p| {
for item in &self.members {
if single_line {
p.print_soft_space();
} else {
p.print_indent();
}
p.print_leading_comments(item.span().start);
p.print_indent();
item.print(p, ctx);
if single_line {
p.print_soft_space();
} else {
if p.options.minify {
p.print_semicolon();
p.print_soft_newline();
}
p.print_soft_newline();
}
});
}
@ -3399,36 +3391,7 @@ impl Gen for TSSignature<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
match self {
Self::TSIndexSignature(signature) => signature.print(p, ctx),
Self::TSPropertySignature(signature) => {
if signature.readonly {
p.print_str("readonly ");
}
if signature.computed {
p.print_ascii_byte(b'[');
signature.key.print(p, ctx);
p.print_ascii_byte(b']');
} else {
match &signature.key {
PropertyKey::StaticIdentifier(key) => {
key.print(p, ctx);
}
PropertyKey::PrivateIdentifier(key) => {
p.print_str(key.name.as_str());
}
key => {
key.to_expression().print_expr(p, Precedence::Comma, ctx);
}
}
}
if signature.optional {
p.print_str("?");
}
if let Some(type_annotation) = &signature.type_annotation {
p.print_colon();
p.print_soft_space();
type_annotation.print(p, ctx);
}
}
Self::TSPropertySignature(signature) => signature.r#gen(p, ctx),
Self::TSCallSignatureDeclaration(signature) => {
if let Some(type_parameters) = signature.type_parameters.as_ref() {
type_parameters.print(p, ctx);
@ -3512,6 +3475,39 @@ impl Gen for TSSignature<'_> {
}
}
impl Gen for TSPropertySignature<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
if self.readonly {
p.print_str("readonly ");
}
if self.computed {
p.print_ascii_byte(b'[');
self.key.print(p, ctx);
p.print_ascii_byte(b']');
} else {
match &self.key {
PropertyKey::StaticIdentifier(key) => {
key.print(p, ctx);
}
PropertyKey::PrivateIdentifier(key) => {
p.print_str(key.name.as_str());
}
key => {
key.to_expression().print_expr(p, Precedence::Comma, ctx);
}
}
}
if self.optional {
p.print_str("?");
}
if let Some(type_annotation) = &self.type_annotation {
p.print_colon();
p.print_soft_space();
type_annotation.print(p, ctx);
}
}
}
impl Gen for TSTypeQuery<'_> {
fn gen(&self, p: &mut Codegen, ctx: Context) {
p.print_str("typeof ");
@ -3742,9 +3738,7 @@ impl Gen for TSInterfaceDeclaration<'_> {
p.print_soft_space();
p.print_curly_braces(self.body.span, self.body.body.is_empty(), |p| {
for item in &self.body.body {
if p.print_comments {
p.print_leading_comments(item.span().start);
}
p.print_leading_comments(item.span().start);
p.print_indent();
item.print(p, ctx);
p.print_semicolon();
@ -3778,9 +3772,7 @@ impl Gen for TSEnumDeclaration<'_> {
p.print_space_before_identifier();
p.print_curly_braces(self.span, self.members.is_empty(), |p| {
for member in &self.members {
if p.print_comments {
p.print_leading_comments(member.span().start);
}
p.print_leading_comments(member.span().start);
p.print_indent();
member.print(p, ctx);
p.print_comma();

View file

@ -1,6 +1,5 @@
---
source: crates/oxc_codegen/tests/integration/main.rs
snapshot_kind: text
---
########## 0
let x: string = `\x01`;
@ -79,11 +78,11 @@ class A{readonly type="frame"}
########## 17
let foo: { <T>(t: T): void }
----------
let foo:{<T>(t:T):void};
let foo:{<T>(t:T):void;};
########## 18
let foo: { new <T>(t: T): void }
----------
let foo:{new <T>(t:T):void};
let foo:{new <T>(t:T):void;};
########## 19
function <const T>(){}
----------

View file

@ -1,6 +1,5 @@
---
source: crates/oxc_codegen/tests/integration/main.rs
snapshot_kind: text
---
########## 0
let x: string = `\x01`;
@ -112,12 +111,16 @@ class A {
########## 17
let foo: { <T>(t: T): void }
----------
let foo: { <T>(t: T): void };
let foo: {
<T>(t: T): void
};
########## 18
let foo: { new <T>(t: T): void }
----------
let foo: { new <T>(t: T): void };
let foo: {
new <T>(t: T): void
};
########## 19
function <const T>(){}

View file

@ -1,9 +1,18 @@
export interface X {
/**
* Comment
*/
set value(_: string);
}
export type A = {
/**
* Comment
*/
set value({ a, b, c }: { a: string; b: string; c: string });
/**
* Comment
*/
get value();
};
@ -24,4 +33,4 @@ export interface MultipleSetterAndGetter {
set ok(_: string)
get bad() // infer return type
set bad(_: string)
}
}

View file

@ -1,24 +1,25 @@
---
source: crates/oxc_isolated_declarations/tests/mod.rs
input_file: crates/oxc_isolated_declarations/tests/fixtures/as-const.ts
snapshot_kind: text
---
```
==================== .D.TS ====================
declare const F: {
readonly string: "string";
readonly templateLiteral: "templateLiteral";
readonly number: 1.23;
readonly bigint: -123n;
readonly boolean: true;
readonly null: null;
readonly undefined: undefined;
readonly function: (a: string) => void;
readonly arrow: (a: string) => void;
readonly string: "string"
readonly templateLiteral: "templateLiteral"
readonly number: 1.23
readonly bigint: -123n
readonly boolean: true
readonly null: null
readonly undefined: undefined
readonly function: (a: string) => void
readonly arrow: (a: string) => void
readonly object: {
readonly a: "a";
readonly b: "b";
};
readonly array: readonly ["a", undefined, { readonly b: "\n" }];
readonly a: "a"
readonly b: "b"
}
readonly array: readonly ["a", undefined, {
readonly b: "\n"
}]
};

View file

@ -8,5 +8,7 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/empty-export.ts
type A = string;
export declare function a(): A;
export declare const ShallowReactiveMarker: unique symbol;
export type ShallowReactive<T> = T & { [ShallowReactiveMarker]?: true };
export type ShallowReactive<T> = T & {
[ShallowReactiveMarker]?: true
};
export {};

View file

@ -8,8 +8,8 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/infer-template-liter
export declare const CSS_VARS_HELPER = "useCssVars";
export declare function g(func?: string): void;
export declare const F: {
readonly a: "a";
readonly b: readonly ["b"];
readonly a: "a"
readonly b: readonly ["b"]
};
export declare let GOOD: string;
export declare const BAD: unknown;

View file

@ -5,5 +5,7 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/readonly.ts
```
==================== .D.TS ====================
export declare const EMPTY_OBJ: { readonly [key: string]: any };
export declare const EMPTY_OBJ: {
readonly [key: string]: any
};
export declare const EMPTY_ARR: readonly never[];

View file

@ -6,19 +6,28 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/signatures.ts
==================== .D.TS ====================
export interface X {
/**
* Comment
*/
set value(_: string);
}
export type A = {
/**
* Comment
*/
set value({ a, b, c }: {
a: string;
b: string;
c: string;
});
a: string
b: string
c: string
})
/**
* Comment
*/
get value(): {
a: string;
b: string;
c: string;
};
a: string
b: string
c: string
}
};
export interface I {
set value(_: string);

View file

@ -12,17 +12,17 @@ export namespace presentNs {
}
const aliasing = Symbol;
export type A = {
[missing]: number;
[ns.missing]: number;
[presentNs.a]: number;
[Symbol.iterator]: number;
[globalThis.Symbol.toStringTag]: number;
[globalThis.Symbol.unscopables]: number;
[aliasing.isConcatSpreadable]: number;
[1]: number;
["2"]: number;
[missing2]: number;
[Math.random() > .5 ? "f1" : "f2"]: number;
[missing]: number
[ns.missing]: number
[presentNs.a]: number
[Symbol.iterator]: number
[globalThis.Symbol.toStringTag]: number
[globalThis.Symbol.unscopables]: number
[aliasing.isConcatSpreadable]: number
[1]: number
["2"]: number
[missing2]: number
[Math.random() > .5 ? "f1" : "f2"]: number
};
export interface B {
[missing]: number;
@ -70,17 +70,17 @@ export declare namespace presentNs {
}
declare const aliasing: unknown;
export type A = {
[missing]: number;
[ns.missing]: number;
[presentNs.a]: number;
[Symbol.iterator]: number;
[globalThis.Symbol.toStringTag]: number;
[globalThis.Symbol.unscopables]: number;
[aliasing.isConcatSpreadable]: number;
[1]: number;
["2"]: number;
[missing2]: number;
[Math.random() > .5 ? "f1" : "f2"]: number;
[missing]: number
[ns.missing]: number
[presentNs.a]: number
[Symbol.iterator]: number
[globalThis.Symbol.toStringTag]: number
[globalThis.Symbol.unscopables]: number
[aliasing.isConcatSpreadable]: number
[1]: number
["2"]: number
[missing2]: number
[Math.random() > .5 ? "f1" : "f2"]: number
};
export interface B {
[missing]: number;
@ -102,10 +102,10 @@ export declare class C {
["2"]: number;
}
export declare const D: {
Symbol.iterator: number;
globalThis.Symbol.toStringTag: number;
1: number;
"2": number;
Symbol.iterator: number
globalThis.Symbol.toStringTag: number
1: number
"2": number
};
export {};
@ -318,11 +318,15 @@ export function fnDeclBasic3(p: new () => any = class {}, rParam: string): void
;
export function fnDeclBasic4(p: [T] = [[]], rParam: string): void {}
;
export function fnDeclBasic5(p: { a: T } = { a: [] }, rParam: string): void {}
export function fnDeclBasic5(p: {
a: T
} = { a: [] }, rParam: string): void {}
;
export function fnDeclBasic6(p: `_${string}` = "_", rParam: string): void {}
;
export function fnDeclBasic7(p: { a?: string } & number[] = [], rParam: string): void {}
export function fnDeclBasic7(p: {
a?: string
} & number[] = [], rParam: string): void {}
;
export function fnDeclBasic8(p: (number[] | string[]) | number = [], rParam: string): void {}
;
@ -388,9 +392,13 @@ export declare function fnDeclBasic1(p: number[] | string[] | [T] | undefined, r
export declare function fnDeclBasic2(p: (n: T) => T | undefined, rParam: string): void;
export declare function fnDeclBasic3(p: new () => any | undefined, rParam: string): void;
export declare function fnDeclBasic4(p: [T] | undefined, rParam: string): void;
export declare function fnDeclBasic5(p: { a: T } | undefined, rParam: string): void;
export declare function fnDeclBasic5(p: {
a: T
} | undefined, rParam: string): void;
export declare function fnDeclBasic6(p: `_${string}` | undefined, rParam: string): void;
export declare function fnDeclBasic7(p: { a?: string } & number[] | undefined, rParam: string): void;
export declare function fnDeclBasic7(p: {
a?: string
} & number[] | undefined, rParam: string): void;
export declare function fnDeclBasic8(p: (number[] | string[]) | number | undefined, rParam: string): void;
export declare function fnDeclHasUndefined(p: T | undefined, rParam: string): void;
export declare function fnDeclBad(p: T, rParam: string): void;
@ -400,15 +408,33 @@ export declare const fnExprBad: (array: T, rParam: string) => void;
export declare const arrowOk1: (array: number[] | undefined, rParam: string) => void;
export declare const arrowOk2: (array: T | undefined, rParam: string) => void;
export declare const arrowBad: (array: T, rParam: string) => void;
export declare const inObjectLiteralFnExprOk1: { o: (array: number[] | undefined, rParam: string) => void };
export declare const inObjectLiteralFnExprOk2: { o: (array: T | undefined, rParam: string) => void };
export declare const inObjectLiteralFnExprBad: { o: (array: T, rParam: string) => void };
export declare const inObjectLiteralArrowOk1: { o: (array: number[] | undefined, rParam: string) => void };
export declare const inObjectLiteralArrowOk2: { o: (array: T | undefined, rParam: string) => void };
export declare const inObjectLiteralArrowBad: { o: (array: T, rParam: string) => void };
export declare const inObjectLiteralMethodOk1: { o(array: number[] | undefined, rParam: string): void };
export declare const inObjectLiteralMethodOk2: { o(array: T | undefined, rParam: string): void };
export declare const inObjectLiteralMethodBad: { o(array: T, rParam: string): void };
export declare const inObjectLiteralFnExprOk1: {
o: (array: number[] | undefined, rParam: string) => void
};
export declare const inObjectLiteralFnExprOk2: {
o: (array: T | undefined, rParam: string) => void
};
export declare const inObjectLiteralFnExprBad: {
o: (array: T, rParam: string) => void
};
export declare const inObjectLiteralArrowOk1: {
o: (array: number[] | undefined, rParam: string) => void
};
export declare const inObjectLiteralArrowOk2: {
o: (array: T | undefined, rParam: string) => void
};
export declare const inObjectLiteralArrowBad: {
o: (array: T, rParam: string) => void
};
export declare const inObjectLiteralMethodOk1: {
o(array: number[] | undefined, rParam: string): void
};
export declare const inObjectLiteralMethodOk2: {
o(array: T | undefined, rParam: string): void
};
export declare const inObjectLiteralMethodBad: {
o(array: T, rParam: string): void
};
export declare class InClassFnExprOk1 {
o: (array: number[] | undefined, rParam: string) => void;
}