Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 60 additions & 38 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1072,30 +1072,14 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for Expression<'a> {
Self::JSXFragment(fragment) => fragment.gen(p, ctx),
Self::ParenthesizedExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSAsExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSSatisfiesExpression(e) => {
e.expression.gen_expr(p, precedence, ctx);
p.print_str(" satisfies ");
e.type_annotation.gen(p, ctx);
}
Self::TSSatisfiesExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSTypeAssertion(e) => e.gen_expr(p, precedence, ctx),
Self::TSNonNullExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSInstantiationExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSNonNullExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSInstantiationExpression(e) => e.gen_expr(p, precedence, ctx),
}
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSAsExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
p.print_char(b'(');
p.print_char(b'(');
self.expression.gen_expr(p, precedence, ctx);
p.print_char(b')');
p.print_str(" as ");
self.type_annotation.gen(p, ctx);
p.print_char(b')');
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for ParenthesizedExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
self.expression.gen_expr(p, precedence, ctx);
Expand Down Expand Up @@ -1887,10 +1871,10 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for SimpleAssignmentTarget<'a> {
self.to_member_expression().gen_expr(p, precedence, ctx);
}
Self::TSAsExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSSatisfiesExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSNonNullExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSSatisfiesExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSNonNullExpression(e) => e.gen_expr(p, precedence, ctx),
Self::TSTypeAssertion(e) => e.gen_expr(p, precedence, ctx),
Self::TSInstantiationExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSInstantiationExpression(e) => e.gen_expr(p, precedence, ctx),
}
}
}
Expand Down Expand Up @@ -2127,6 +2111,60 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for NewExpression<'a> {
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSAsExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
p.print_char(b'(');
p.print_char(b'(');
self.expression.gen_expr(p, precedence, ctx);
p.print_char(b')');
p.print_str(" as ");
self.type_annotation.gen(p, ctx);
p.print_char(b')');
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSSatisfiesExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
// TODO: print properly
self.expression.gen_expr(p, precedence, ctx);
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSNonNullExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
p.wrap(matches!(self.expression, Expression::ParenthesizedExpression(_)), |p| {
self.expression.gen_expr(p, precedence, ctx);
});
p.print_char(b'!');
if MINIFY {
p.print_hard_space();
}
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSInstantiationExpression<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
// TODO: print properly
self.expression.gen_expr(p, precedence, ctx);
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSTypeAssertion<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
p.wrap(precedence >= self.precedence(), |p| {
p.print_str("<");
// var r = < <T>(x: T) => T > ((x) => { return null; });
// ^ make sure space is printed here.
if matches!(self.type_annotation, TSType::TSFunctionType(_)) {
p.print_hard_space();
}
self.type_annotation.gen(p, ctx);
p.print_str(">");
self.expression.gen_expr(p, Precedence::Member, ctx);
});
}
}

impl<'a, const MINIFY: bool> Gen<MINIFY> for MetaProperty<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.add_source_mapping(self.span.start);
Expand Down Expand Up @@ -3599,22 +3637,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSModuleReference<'a> {
}
}

impl<'a, const MINIFY: bool> GenExpr<MINIFY> for TSTypeAssertion<'a> {
fn gen_expr(&self, p: &mut Codegen<{ MINIFY }>, precedence: Precedence, ctx: Context) {
p.wrap(precedence >= self.precedence(), |p| {
p.print_str("<");
// var r = < <T>(x: T) => T > ((x) => { return null; });
// ^ make sure space is printed here.
if matches!(self.type_annotation, TSType::TSFunctionType(_)) {
p.print_hard_space();
}
self.type_annotation.gen(p, ctx);
p.print_str(">");
self.expression.gen_expr(p, Precedence::Member, ctx);
});
}
}

impl<const MINIFY: bool> Gen<MINIFY> for TSAccessibility {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
match self {
Expand Down
12 changes: 12 additions & 0 deletions crates/oxc_codegen/tests/integration/snapshots/ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,15 @@ abstract class A {private abstract static readonly prop: string}
abstract class A {
private abstract static readonly prop: string;
}

a = x!;
a = x!;

b = (x as y);
b = ((x) as y);

c = foo<string>;
c = foo;

d = x satisfies y;
d = x;
24 changes: 14 additions & 10 deletions crates/oxc_codegen/tests/integration/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ use oxc_codegen::{CodeGenerator, CodegenOptions};
use oxc_parser::Parser;
use oxc_span::SourceType;

fn codegen(source_text: &str) -> String {
let allocator = Allocator::default();
let source_type = SourceType::default().with_typescript(true).with_module(true);
let ret = Parser::new(&allocator, source_text, source_type).parse();
CodeGenerator::new()
.with_options(CodegenOptions { single_quote: true })
.build(&ret.program)
.source_text
}

#[test]
fn ts() {
let cases = [
Expand Down Expand Up @@ -36,6 +46,10 @@ fn ts() {
"class A {constructor(public readonly a: number) {}}",
"abstract class A {private abstract static m() {}}",
"abstract class A {private abstract static readonly prop: string}",
"a = x!;",
"b = (x as y);",
"c = foo<string>;",
"d = x satisfies y;",
];

let snapshot = cases.into_iter().fold(String::new(), |mut w, case| {
Expand All @@ -47,13 +61,3 @@ fn ts() {
insta::assert_snapshot!("ts", snapshot);
});
}

fn codegen(source_text: &str) -> String {
let allocator = Allocator::default();
let source_type = SourceType::default().with_typescript(true).with_module(true);
let ret = Parser::new(&allocator, source_text, source_type).parse();
CodeGenerator::new()
.with_options(CodegenOptions { single_quote: true })
.build(&ret.program)
.source_text
}
3 changes: 2 additions & 1 deletion tasks/coverage/transformer_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ commit: d8086f14

transformer_typescript Summary:
AST Parsed : 6456/6456 (100.00%)
Positive Passed: 6453/6456 (99.95%)
Positive Passed: 6452/6456 (99.94%)
Mismatch: "compiler/constEnumNamespaceReferenceCausesNoImport2.ts"
Mismatch: "compiler/incrementOnNullAssertion.ts"
Mismatch: "conformance/externalModules/typeOnly/exportDeclaration.ts"
Mismatch: "conformance/jsx/inline/inlineJsxAndJsxFragPragmaOverridesCompilerOptions.tsx"