From 35167599bca81d1dd56d47ec65b64439d29146c9 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Wed, 9 Aug 2023 13:52:56 +0800 Subject: [PATCH] refactor(ast): use `atom` for `Directive` and `Hashbang` (#701) The main reason is using Atom to remove the lifetime for convenience. And after removing the lifetime of these nodes, the `Program<'a>` doesn't rely on `&'a source` anymore, which allows us to [specify more accurate lifetimes](https://github.com/web-infra-dev/oxc/discussions/700). --- crates/oxc_ast/src/ast/js.rs | 14 +++++++------- crates/oxc_ast/src/ast_builder.rs | 11 +++-------- crates/oxc_ast/src/ast_kind.rs | 6 +++--- crates/oxc_ast/src/visit.rs | 2 +- crates/oxc_ast/src/visit_mut.rs | 2 +- crates/oxc_ast_lower/src/lib.rs | 8 ++++---- crates/oxc_formatter/src/gen.rs | 2 +- crates/oxc_hir/src/hir.rs | 14 +++++++------- crates/oxc_hir/src/hir_builder.rs | 8 ++++---- crates/oxc_hir/src/hir_kind.rs | 2 +- crates/oxc_hir/src/visit.rs | 2 +- crates/oxc_hir/src/visit_mut.rs | 2 +- crates/oxc_minifier/src/printer/gen.rs | 4 ++-- crates/oxc_parser/src/js/statement.rs | 15 +++++++++------ 14 files changed, 45 insertions(+), 47 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 624a1a49d..6e4362239 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -17,8 +17,8 @@ pub struct Program<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub source_type: SourceType, - pub directives: Vec<'a, Directive<'a>>, - pub hashbang: Option>, + pub directives: Vec<'a, Directive>, + pub hashbang: Option, pub body: Vec<'a, Statement<'a>>, } @@ -918,21 +918,21 @@ pub enum Statement<'a> { /// Directive Prologue #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Directive<'a> { +pub struct Directive { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub expression: StringLiteral, // directives should always use the unescaped raw string - pub directive: &'a str, + pub directive: Atom, } /// Hashbang #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Hashbang<'a> { +pub struct Hashbang { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub value: &'a str, + pub value: Atom, } /// Block Statement @@ -1447,7 +1447,7 @@ impl<'a> FormalParameters<'a> { pub struct FunctionBody<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub directives: Vec<'a, Directive<'a>>, + pub directives: Vec<'a, Directive>, pub statements: Vec<'a, Statement<'a>>, } diff --git a/crates/oxc_ast/src/ast_builder.rs b/crates/oxc_ast/src/ast_builder.rs index ba418c42e..f955d71e2 100644 --- a/crates/oxc_ast/src/ast_builder.rs +++ b/crates/oxc_ast/src/ast_builder.rs @@ -59,7 +59,7 @@ impl<'a> AstBuilder<'a> { span: Span, source_type: SourceType, directives: Vec<'a, Directive>, - hashbang: Option>, + hashbang: Option, body: Vec<'a, Statement<'a>>, ) -> Program<'a> { Program { span, source_type, directives, hashbang, body } @@ -109,16 +109,11 @@ impl<'a> AstBuilder<'a> { /* ---------- Statements ---------- */ - pub fn directive( - &self, - span: Span, - expression: StringLiteral, - directive: &'a str, - ) -> Directive<'a> { + pub fn directive(&self, span: Span, expression: StringLiteral, directive: Atom) -> Directive { Directive { span, expression, directive } } - pub fn hashbang(&self, span: Span, value: &'a str) -> Hashbang<'a> { + pub fn hashbang(&self, span: Span, value: Atom) -> Hashbang { Hashbang { span, value } } diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index bfea38a4e..2e4ef3f16 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -7,8 +7,8 @@ use crate::ast::*; #[derive(Debug, Clone, Copy)] pub enum AstKind<'a> { Program(&'a Program<'a>), - Directive(&'a Directive<'a>), - Hashbang(&'a Hashbang<'a>), + Directive(&'a Directive), + Hashbang(&'a Hashbang), BlockStatement(&'a BlockStatement<'a>), BreakStatement(&'a BreakStatement), @@ -387,7 +387,7 @@ impl<'a> AstKind<'a> { pub fn debug_name(&self) -> std::borrow::Cow { match self { Self::Program(_) => "Program".into(), - Self::Directive(d) => d.directive.into(), + Self::Directive(d) => d.directive.as_ref().into(), Self::Hashbang(_) => "Hashbang".into(), Self::BlockStatement(_) => "BlockStatement".into(), diff --git a/crates/oxc_ast/src/visit.rs b/crates/oxc_ast/src/visit.rs index 7312a5192..d903ea0e7 100644 --- a/crates/oxc_ast/src/visit.rs +++ b/crates/oxc_ast/src/visit.rs @@ -271,7 +271,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_directive(&mut self, directive: &'a Directive<'a>) { + fn visit_directive(&mut self, directive: &'a Directive) { let kind = AstKind::Directive(directive); self.enter_node(kind); self.visit_string_literal(&directive.expression); diff --git a/crates/oxc_ast/src/visit_mut.rs b/crates/oxc_ast/src/visit_mut.rs index f0af2bcb4..ea0346bda 100644 --- a/crates/oxc_ast/src/visit_mut.rs +++ b/crates/oxc_ast/src/visit_mut.rs @@ -193,7 +193,7 @@ pub trait VisitMut<'a, 'b>: Sized { self.visit_statement(&mut stmt.body); } - fn visit_directive(&mut self, directive: &'b mut Directive<'a>) { + fn visit_directive(&mut self, directive: &'b mut Directive) { self.visit_string_literal(&mut directive.expression); } diff --git a/crates/oxc_ast_lower/src/lib.rs b/crates/oxc_ast_lower/src/lib.rs index e1907e536..031aa901d 100644 --- a/crates/oxc_ast_lower/src/lib.rs +++ b/crates/oxc_ast_lower/src/lib.rs @@ -160,13 +160,13 @@ impl<'a> AstLower<'a> { self.hir.program(program.span, directives, hashbang, statements) } - fn lower_hasbang(&mut self, hashbang: &ast::Hashbang<'a>) -> hir::Hashbang<'a> { - self.hir.hashbang(hashbang.span, hashbang.value) + fn lower_hasbang(&mut self, hashbang: &ast::Hashbang) -> hir::Hashbang { + self.hir.hashbang(hashbang.span, hashbang.value.clone()) } - fn lower_directive(&mut self, directive: &ast::Directive<'a>) -> hir::Directive<'a> { + fn lower_directive(&mut self, directive: &ast::Directive) -> hir::Directive { let expression = self.lower_string_literal(&directive.expression); - self.hir.directive(directive.span, expression, directive.directive) + self.hir.directive(directive.span, expression, directive.directive.clone()) } fn lower_statement(&mut self, statement: &ast::Statement<'a>) -> Option> { diff --git a/crates/oxc_formatter/src/gen.rs b/crates/oxc_formatter/src/gen.rs index f4ef78b2f..895267d6d 100644 --- a/crates/oxc_formatter/src/gen.rs +++ b/crates/oxc_formatter/src/gen.rs @@ -30,7 +30,7 @@ impl<'a> Gen for Program<'a> { } } -impl<'a> Gen for Directive<'a> { +impl Gen for Directive { fn gen(&self, p: &mut Formatter) { p.print_indent(); p.print(b'"'); diff --git a/crates/oxc_hir/src/hir.rs b/crates/oxc_hir/src/hir.rs index a449bf009..a560d5870 100644 --- a/crates/oxc_hir/src/hir.rs +++ b/crates/oxc_hir/src/hir.rs @@ -25,8 +25,8 @@ use crate::HirId; pub struct Program<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub directives: Vec<'a, Directive<'a>>, - pub hashbang: Option>, + pub directives: Vec<'a, Directive>, + pub hashbang: Option, pub body: Vec<'a, Statement<'a>>, } @@ -1039,25 +1039,25 @@ pub enum Statement<'a> { /// Directive Prologue #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Directive<'a> { +pub struct Directive { #[cfg_attr(feature = "serde", serde(skip))] pub hir_id: HirId, #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub expression: StringLiteral, // directives should always use the unescaped raw string - pub directive: &'a str, + pub directive: Atom, } /// Hashbang #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] -pub struct Hashbang<'a> { +pub struct Hashbang { #[cfg_attr(feature = "serde", serde(skip))] pub hir_id: HirId, #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub value: &'a str, + pub value: Atom, } /// Block Statement @@ -1501,7 +1501,7 @@ impl<'a> FormalParameters<'a> { pub struct FunctionBody<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub directives: Vec<'a, Directive<'a>>, + pub directives: Vec<'a, Directive>, pub statements: Vec<'a, Statement<'a>>, } diff --git a/crates/oxc_hir/src/hir_builder.rs b/crates/oxc_hir/src/hir_builder.rs index 38903e0d9..f0499cbb9 100644 --- a/crates/oxc_hir/src/hir_builder.rs +++ b/crates/oxc_hir/src/hir_builder.rs @@ -66,7 +66,7 @@ impl<'a> HirBuilder<'a> { &mut self, span: Span, directives: Vec<'a, Directive>, - hashbang: Option>, + hashbang: Option, body: Vec<'a, Statement<'a>>, ) -> Program<'a> { Program { span, directives, hashbang, body } @@ -209,12 +209,12 @@ impl<'a> HirBuilder<'a> { &mut self, span: Span, expression: StringLiteral, - directive: &'a str, - ) -> Directive<'a> { + directive: Atom, + ) -> Directive { Directive { hir_id: self.next_id(), span, expression, directive } } - pub fn hashbang(&mut self, span: Span, value: &'a str) -> Hashbang<'a> { + pub fn hashbang(&mut self, span: Span, value: Atom) -> Hashbang { Hashbang { hir_id: self.next_id(), span, value } } diff --git a/crates/oxc_hir/src/hir_kind.rs b/crates/oxc_hir/src/hir_kind.rs index f1a5621dc..49d71a81d 100644 --- a/crates/oxc_hir/src/hir_kind.rs +++ b/crates/oxc_hir/src/hir_kind.rs @@ -9,7 +9,7 @@ pub enum HirKind<'a> { Root, Program(&'a Program<'a>), - Directive(&'a Directive<'a>), + Directive(&'a Directive), BlockStatement(&'a BlockStatement<'a>), BreakStatement(&'a BreakStatement), diff --git a/crates/oxc_hir/src/visit.rs b/crates/oxc_hir/src/visit.rs index e7d56d47e..bbcc574ee 100644 --- a/crates/oxc_hir/src/visit.rs +++ b/crates/oxc_hir/src/visit.rs @@ -313,7 +313,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_directive(&mut self, directive: &'a Directive<'a>) { + fn visit_directive(&mut self, directive: &'a Directive) { let kind = HirKind::Directive(directive); self.enter_node(kind); self.visit_string_literal(&directive.expression); diff --git a/crates/oxc_hir/src/visit_mut.rs b/crates/oxc_hir/src/visit_mut.rs index ac59575d1..c08398229 100644 --- a/crates/oxc_hir/src/visit_mut.rs +++ b/crates/oxc_hir/src/visit_mut.rs @@ -206,7 +206,7 @@ pub trait VisitMut<'a, 'b>: Sized { } } - fn visit_directive(&mut self, directive: &'b mut Directive<'a>) { + fn visit_directive(&mut self, directive: &'b mut Directive) { self.visit_string_literal(&mut directive.expression); } diff --git a/crates/oxc_minifier/src/printer/gen.rs b/crates/oxc_minifier/src/printer/gen.rs index e02b9568a..4cda073d1 100644 --- a/crates/oxc_minifier/src/printer/gen.rs +++ b/crates/oxc_minifier/src/printer/gen.rs @@ -53,14 +53,14 @@ impl<'a> Gen for Program<'a> { } } -impl<'a> Gen for Hashbang<'a> { +impl Gen for Hashbang { fn gen(&self, p: &mut Printer, ctx: Context) { p.print_str(b"#!"); p.print_str(self.value.as_bytes()); } } -impl<'a> Gen for Directive<'a> { +impl Gen for Directive { fn gen(&self, p: &mut Printer, ctx: Context) { p.print(b'"'); p.print_str(self.directive.as_bytes()); diff --git a/crates/oxc_parser/src/js/statement.rs b/crates/oxc_parser/src/js/statement.rs index 18fd4f835..9b26b6e33 100644 --- a/crates/oxc_parser/src/js/statement.rs +++ b/crates/oxc_parser/src/js/statement.rs @@ -1,7 +1,7 @@ use oxc_allocator::{Box, Vec}; use oxc_ast::ast::*; use oxc_diagnostics::Result; -use oxc_span::Span; +use oxc_span::{Atom, Span}; use super::{ declaration::{VariableDeclarationContext, VariableDeclarationParent}, @@ -14,13 +14,13 @@ impl<'a> Parser<'a> { // Section 12 // The InputElementHashbangOrRegExp goal is used at the start of a Script // or Module. - pub(crate) fn parse_hashbang(&mut self) -> Option> { + pub(crate) fn parse_hashbang(&mut self) -> Option { if self.cur_kind() == Kind::HashbangComment { let span = self.start_span(); self.bump_any(); let span = self.end_span(span); let src = &self.source_text[span.start as usize + 2..span.end as usize]; - Some(self.ast.hashbang(span, src)) + Some(self.ast.hashbang(span, Atom::from(src))) } else { None } @@ -33,7 +33,7 @@ impl<'a> Parser<'a> { pub(crate) fn parse_directives_and_statements( &mut self, is_top_level: bool, - ) -> Result<(Vec<'a, Directive<'a>>, Vec<'a, Statement<'a>>)> { + ) -> Result<(Vec<'a, Directive>, Vec<'a, Statement<'a>>)> { let mut directives = self.ast.new_vec(); let mut statements = self.ast.new_vec(); @@ -64,8 +64,11 @@ impl<'a> Parser<'a> { if let Expression::StringLiteral(string) = &expr.expression { let src = &self.source_text [string.span.start as usize + 1..string.span.end as usize - 1]; - let directive = - self.ast.directive(expr.span, (*string).clone(), src); + let directive = self.ast.directive( + expr.span, + (*string).clone(), + Atom::from(src), + ); directives.push(directive); continue; }