Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(codegen): fix some typescript codegen problems #989

Merged
merged 1 commit into from
Oct 13, 2023
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
8 changes: 7 additions & 1 deletion crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ pub enum Declaration<'a> {
impl<'a> Declaration<'a> {
pub fn is_typescript_syntax(&self) -> bool {
match self {
Self::VariableDeclaration(_) => false,
Self::VariableDeclaration(decl) => decl.is_typescript_syntax(),
Self::FunctionDeclaration(func) => func.is_typescript_syntax(),
Self::ClassDeclaration(class) => class.is_declare(),
_ => true,
Expand All @@ -1069,6 +1069,12 @@ pub struct VariableDeclaration<'a> {
pub modifiers: Modifiers<'a>,
}

impl<'a> VariableDeclaration<'a> {
pub fn is_typescript_syntax(&self) -> bool {
self.modifiers.contains(ModifierKind::Declare)
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "lowercase"))]
pub enum VariableDeclarationKind {
Expand Down
13 changes: 9 additions & 4 deletions crates/oxc_codegen/examples/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use oxc_span::SourceType;
// 2. run `cargo run -p oxc_codegen --example codegen` or `just example codegen`

fn main() {
let name = env::args().nth(1).unwrap_or_else(|| "test.ts".to_string());
let name = env::args().nth(1).unwrap_or_else(|| "test.tsx".to_string());
let path = Path::new(&name);
let source_text = std::fs::read_to_string(path).unwrap_or_else(|_| panic!("{name} not found"));
let source_type = SourceType::from_path(path).unwrap();
Expand All @@ -25,11 +25,16 @@ fn main() {
return;
}

println!("Original:");
println!("{source_text}");

let codegen_options = CodegenOptions;
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(&ret.program);
let printed = Codegen::<true>::new(source_text.len(), codegen_options).build(&ret.program);
println!("Printed:");
println!("{printed}");

let ret = Parser::new(&allocator, &printed, source_type).parse();
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(&ret.program);
println!("{printed}");
let minified = Codegen::<true>::new(source_text.len(), codegen_options).build(&ret.program);
println!("Minified:");
println!("{minified}");
}
49 changes: 22 additions & 27 deletions crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ fn print_directives_and_statements<const MINIFY: bool>(
p.print_semicolon_if_needed();
stmt.gen(p, ctx);
}
if !MINIFY && !statements.is_empty() {
p.print_semicolon_if_needed();
}
}

impl<const MINIFY: bool> Gen<MINIFY> for Hashbang {
Expand All @@ -80,9 +77,9 @@ impl<const MINIFY: bool> Gen<MINIFY> for Hashbang {
impl<const MINIFY: bool> Gen<MINIFY> for Directive {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_indent();
p.print(b'"');
p.print(b'\'');
p.print_str(self.directive.as_bytes());
p.print(b'"');
p.print(b'\'');
p.print_semicolon();
}
}
Expand Down Expand Up @@ -114,15 +111,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Statement<'a> {
}
}

impl<'a, const MINIFY: bool> Gen<MINIFY> for Option<Statement<'a>> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
match self {
Some(stmt) => stmt.gen(p, ctx),
None => p.print(b';'),
}
}
}

impl<'a, const MINIFY: bool> Gen<MINIFY> for ExpressionStatement<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_indent();
Expand Down Expand Up @@ -494,27 +482,31 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleDeclaration<'a> {
Self::ExportAllDeclaration(decl) => decl.gen(p, ctx),
Self::ExportDefaultDeclaration(decl) => decl.gen(p, ctx),
Self::ExportNamedDeclaration(decl) => decl.gen(p, ctx),
_ => {}
_ => p.needs_semicolon = false,
}
}
}

impl<'a, const MINIFY: bool> Gen<MINIFY> for Declaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
match self {
Self::VariableDeclaration(stmt) => {
p.print_indent();
stmt.gen(p, ctx);
p.print_semicolon_after_statement();
Self::VariableDeclaration(decl) => {
if !decl.is_typescript_syntax() {
p.print_indent();
decl.gen(p, ctx);
p.print_semicolon_after_statement();
}
}
Self::FunctionDeclaration(stmt) => {
p.print_indent();
p.print_space_before_identifier();
stmt.gen(p, ctx);
Self::FunctionDeclaration(decl) => {
if !decl.is_typescript_syntax() {
p.print_indent();
p.print_space_before_identifier();
decl.gen(p, ctx);
}
}
Self::ClassDeclaration(declaration) => {
Self::ClassDeclaration(decl) => {
p.print_space_before_identifier();
declaration.gen(p, ctx);
decl.gen(p, ctx);
}
Self::UsingDeclaration(declaration) => {
p.print_space_before_identifier();
Expand Down Expand Up @@ -738,7 +730,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> {
p.print_str(b"from");
source.gen(p, ctx);
}
p.print_semicolon_after_statement();
p.needs_semicolon = true;
}
}
}
Expand Down Expand Up @@ -1747,8 +1739,8 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttributeName<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttribute<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
self.name.gen(p, ctx);
p.print(b'=');
if let Some(value) = &self.value {
p.print(b'=');
value.gen(p, ctx);
}
}
Expand Down Expand Up @@ -1788,7 +1780,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttributeValue<'a> {

impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXSpreadAttribute<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_str(b"{...");
self.argument.gen_expr(p, Precedence::lowest(), Context::default());
p.print(b'}');
}
}

Expand All @@ -1806,6 +1800,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXOpeningElement<'a> {
p.print_str(b"<");
self.name.gen(p, ctx);
for attr in &self.attributes {
p.print_hard_space();
attr.gen(p, ctx);
}
if self.self_closing {
Expand Down
17 changes: 6 additions & 11 deletions crates/oxc_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
}
}

// pub fn with_mangler(&mut self, mangler: Mangler) {
// fn with_mangler(&mut self, mangler: Mangler) {
// self.mangler = Some(mangler);
// }

Expand All @@ -97,7 +97,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
self.into_code()
}

fn into_code(self) -> String {
pub fn into_code(self) -> String {
unsafe { String::from_utf8_unchecked(self.code) }
}

Expand Down Expand Up @@ -129,8 +129,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
self.print(b' ');
}

#[inline]
pub fn print_soft_newline(&mut self) {
fn print_soft_newline(&mut self) {
if !MINIFY {
self.print(b'\n');
}
Expand All @@ -157,21 +156,19 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
unsafe { from_utf8_unchecked(self.code()) }.chars().nth_back(n)
}

#[inline]
pub fn indent(&mut self) {
fn indent(&mut self) {
if !MINIFY {
self.indentation += 1;
}
}

#[inline]
pub fn dedent(&mut self) {
fn dedent(&mut self) {
if !MINIFY {
self.indentation -= 1;
}
}

pub fn print_indent(&mut self) {
fn print_indent(&mut self) {
if !MINIFY {
for _ in 0..self.indentation {
self.print(b'\t');
Expand Down Expand Up @@ -219,14 +216,12 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
}
}

#[inline]
fn print_block_start(&mut self) {
self.print(b'{');
self.print_soft_newline();
self.indent();
}

#[inline]
fn print_block_end(&mut self) {
self.dedent();
self.print_indent();
Expand Down
Loading
Loading