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).
This commit is contained in:
Yunfei He 2023-08-09 13:52:56 +08:00 committed by GitHub
parent f5b8690309
commit 35167599bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 45 additions and 47 deletions

View file

@ -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<Hashbang<'a>>,
pub directives: Vec<'a, Directive>,
pub hashbang: Option<Hashbang>,
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>>,
}

View file

@ -59,7 +59,7 @@ impl<'a> AstBuilder<'a> {
span: Span,
source_type: SourceType,
directives: Vec<'a, Directive>,
hashbang: Option<Hashbang<'a>>,
hashbang: Option<Hashbang>,
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 }
}

View file

@ -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<str> {
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(),

View file

@ -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);

View file

@ -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);
}

View file

@ -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<hir::Statement<'a>> {

View file

@ -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'"');

View file

@ -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<Hashbang<'a>>,
pub directives: Vec<'a, Directive>,
pub hashbang: Option<Hashbang>,
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>>,
}

View file

@ -66,7 +66,7 @@ impl<'a> HirBuilder<'a> {
&mut self,
span: Span,
directives: Vec<'a, Directive>,
hashbang: Option<Hashbang<'a>>,
hashbang: Option<Hashbang>,
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 }
}

View file

@ -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),

View file

@ -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);

View file

@ -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);
}

View file

@ -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());

View file

@ -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<Hashbang<'a>> {
pub(crate) fn parse_hashbang(&mut self) -> Option<Hashbang> {
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;
}