mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
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:
parent
f5b8690309
commit
35167599bc
14 changed files with 45 additions and 47 deletions
|
|
@ -17,8 +17,8 @@ pub struct Program<'a> {
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub source_type: SourceType,
|
pub source_type: SourceType,
|
||||||
pub directives: Vec<'a, Directive<'a>>,
|
pub directives: Vec<'a, Directive>,
|
||||||
pub hashbang: Option<Hashbang<'a>>,
|
pub hashbang: Option<Hashbang>,
|
||||||
pub body: Vec<'a, Statement<'a>>,
|
pub body: Vec<'a, Statement<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -918,21 +918,21 @@ pub enum Statement<'a> {
|
||||||
/// Directive Prologue
|
/// Directive Prologue
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
||||||
pub struct Directive<'a> {
|
pub struct Directive {
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub expression: StringLiteral,
|
pub expression: StringLiteral,
|
||||||
// directives should always use the unescaped raw string
|
// directives should always use the unescaped raw string
|
||||||
pub directive: &'a str,
|
pub directive: Atom,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hashbang
|
/// Hashbang
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
||||||
pub struct Hashbang<'a> {
|
pub struct Hashbang {
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub value: &'a str,
|
pub value: Atom,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block Statement
|
/// Block Statement
|
||||||
|
|
@ -1447,7 +1447,7 @@ impl<'a> FormalParameters<'a> {
|
||||||
pub struct FunctionBody<'a> {
|
pub struct FunctionBody<'a> {
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub directives: Vec<'a, Directive<'a>>,
|
pub directives: Vec<'a, Directive>,
|
||||||
pub statements: Vec<'a, Statement<'a>>,
|
pub statements: Vec<'a, Statement<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
source_type: SourceType,
|
source_type: SourceType,
|
||||||
directives: Vec<'a, Directive>,
|
directives: Vec<'a, Directive>,
|
||||||
hashbang: Option<Hashbang<'a>>,
|
hashbang: Option<Hashbang>,
|
||||||
body: Vec<'a, Statement<'a>>,
|
body: Vec<'a, Statement<'a>>,
|
||||||
) -> Program<'a> {
|
) -> Program<'a> {
|
||||||
Program { span, source_type, directives, hashbang, body }
|
Program { span, source_type, directives, hashbang, body }
|
||||||
|
|
@ -109,16 +109,11 @@ impl<'a> AstBuilder<'a> {
|
||||||
|
|
||||||
/* ---------- Statements ---------- */
|
/* ---------- Statements ---------- */
|
||||||
|
|
||||||
pub fn directive(
|
pub fn directive(&self, span: Span, expression: StringLiteral, directive: Atom) -> Directive {
|
||||||
&self,
|
|
||||||
span: Span,
|
|
||||||
expression: StringLiteral,
|
|
||||||
directive: &'a str,
|
|
||||||
) -> Directive<'a> {
|
|
||||||
Directive { span, expression, 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 }
|
Hashbang { span, value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use crate::ast::*;
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum AstKind<'a> {
|
pub enum AstKind<'a> {
|
||||||
Program(&'a Program<'a>),
|
Program(&'a Program<'a>),
|
||||||
Directive(&'a Directive<'a>),
|
Directive(&'a Directive),
|
||||||
Hashbang(&'a Hashbang<'a>),
|
Hashbang(&'a Hashbang),
|
||||||
|
|
||||||
BlockStatement(&'a BlockStatement<'a>),
|
BlockStatement(&'a BlockStatement<'a>),
|
||||||
BreakStatement(&'a BreakStatement),
|
BreakStatement(&'a BreakStatement),
|
||||||
|
|
@ -387,7 +387,7 @@ impl<'a> AstKind<'a> {
|
||||||
pub fn debug_name(&self) -> std::borrow::Cow<str> {
|
pub fn debug_name(&self) -> std::borrow::Cow<str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Program(_) => "Program".into(),
|
Self::Program(_) => "Program".into(),
|
||||||
Self::Directive(d) => d.directive.into(),
|
Self::Directive(d) => d.directive.as_ref().into(),
|
||||||
Self::Hashbang(_) => "Hashbang".into(),
|
Self::Hashbang(_) => "Hashbang".into(),
|
||||||
|
|
||||||
Self::BlockStatement(_) => "BlockStatement".into(),
|
Self::BlockStatement(_) => "BlockStatement".into(),
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ pub trait Visit<'a>: Sized {
|
||||||
self.leave_node(kind);
|
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);
|
let kind = AstKind::Directive(directive);
|
||||||
self.enter_node(kind);
|
self.enter_node(kind);
|
||||||
self.visit_string_literal(&directive.expression);
|
self.visit_string_literal(&directive.expression);
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ pub trait VisitMut<'a, 'b>: Sized {
|
||||||
self.visit_statement(&mut stmt.body);
|
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);
|
self.visit_string_literal(&mut directive.expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,13 +160,13 @@ impl<'a> AstLower<'a> {
|
||||||
self.hir.program(program.span, directives, hashbang, statements)
|
self.hir.program(program.span, directives, hashbang, statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_hasbang(&mut self, hashbang: &ast::Hashbang<'a>) -> hir::Hashbang<'a> {
|
fn lower_hasbang(&mut self, hashbang: &ast::Hashbang) -> hir::Hashbang {
|
||||||
self.hir.hashbang(hashbang.span, hashbang.value)
|
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);
|
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>> {
|
fn lower_statement(&mut self, statement: &ast::Statement<'a>) -> Option<hir::Statement<'a>> {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
fn gen(&self, p: &mut Formatter) {
|
||||||
p.print_indent();
|
p.print_indent();
|
||||||
p.print(b'"');
|
p.print(b'"');
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ use crate::HirId;
|
||||||
pub struct Program<'a> {
|
pub struct Program<'a> {
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub directives: Vec<'a, Directive<'a>>,
|
pub directives: Vec<'a, Directive>,
|
||||||
pub hashbang: Option<Hashbang<'a>>,
|
pub hashbang: Option<Hashbang>,
|
||||||
pub body: Vec<'a, Statement<'a>>,
|
pub body: Vec<'a, Statement<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1039,25 +1039,25 @@ pub enum Statement<'a> {
|
||||||
/// Directive Prologue
|
/// Directive Prologue
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
||||||
pub struct Directive<'a> {
|
pub struct Directive {
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "serde", serde(skip))]
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub expression: StringLiteral,
|
pub expression: StringLiteral,
|
||||||
// directives should always use the unescaped raw string
|
// directives should always use the unescaped raw string
|
||||||
pub directive: &'a str,
|
pub directive: Atom,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hashbang
|
/// Hashbang
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
|
||||||
pub struct Hashbang<'a> {
|
pub struct Hashbang {
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "serde", serde(skip))]
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub value: &'a str,
|
pub value: Atom,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Block Statement
|
/// Block Statement
|
||||||
|
|
@ -1501,7 +1501,7 @@ impl<'a> FormalParameters<'a> {
|
||||||
pub struct FunctionBody<'a> {
|
pub struct FunctionBody<'a> {
|
||||||
#[cfg_attr(feature = "serde", serde(flatten))]
|
#[cfg_attr(feature = "serde", serde(flatten))]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub directives: Vec<'a, Directive<'a>>,
|
pub directives: Vec<'a, Directive>,
|
||||||
pub statements: Vec<'a, Statement<'a>>,
|
pub statements: Vec<'a, Statement<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ impl<'a> HirBuilder<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
directives: Vec<'a, Directive>,
|
directives: Vec<'a, Directive>,
|
||||||
hashbang: Option<Hashbang<'a>>,
|
hashbang: Option<Hashbang>,
|
||||||
body: Vec<'a, Statement<'a>>,
|
body: Vec<'a, Statement<'a>>,
|
||||||
) -> Program<'a> {
|
) -> Program<'a> {
|
||||||
Program { span, directives, hashbang, body }
|
Program { span, directives, hashbang, body }
|
||||||
|
|
@ -209,12 +209,12 @@ impl<'a> HirBuilder<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
expression: StringLiteral,
|
expression: StringLiteral,
|
||||||
directive: &'a str,
|
directive: Atom,
|
||||||
) -> Directive<'a> {
|
) -> Directive {
|
||||||
Directive { hir_id: self.next_id(), span, expression, 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 }
|
Hashbang { hir_id: self.next_id(), span, value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ pub enum HirKind<'a> {
|
||||||
Root,
|
Root,
|
||||||
|
|
||||||
Program(&'a Program<'a>),
|
Program(&'a Program<'a>),
|
||||||
Directive(&'a Directive<'a>),
|
Directive(&'a Directive),
|
||||||
|
|
||||||
BlockStatement(&'a BlockStatement<'a>),
|
BlockStatement(&'a BlockStatement<'a>),
|
||||||
BreakStatement(&'a BreakStatement),
|
BreakStatement(&'a BreakStatement),
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,7 @@ pub trait Visit<'a>: Sized {
|
||||||
self.leave_node(kind);
|
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);
|
let kind = HirKind::Directive(directive);
|
||||||
self.enter_node(kind);
|
self.enter_node(kind);
|
||||||
self.visit_string_literal(&directive.expression);
|
self.visit_string_literal(&directive.expression);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
self.visit_string_literal(&mut directive.expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
fn gen(&self, p: &mut Printer, ctx: Context) {
|
||||||
p.print_str(b"#!");
|
p.print_str(b"#!");
|
||||||
p.print_str(self.value.as_bytes());
|
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) {
|
fn gen(&self, p: &mut Printer, ctx: Context) {
|
||||||
p.print(b'"');
|
p.print(b'"');
|
||||||
p.print_str(self.directive.as_bytes());
|
p.print_str(self.directive.as_bytes());
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use oxc_allocator::{Box, Vec};
|
use oxc_allocator::{Box, Vec};
|
||||||
use oxc_ast::ast::*;
|
use oxc_ast::ast::*;
|
||||||
use oxc_diagnostics::Result;
|
use oxc_diagnostics::Result;
|
||||||
use oxc_span::Span;
|
use oxc_span::{Atom, Span};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
declaration::{VariableDeclarationContext, VariableDeclarationParent},
|
declaration::{VariableDeclarationContext, VariableDeclarationParent},
|
||||||
|
|
@ -14,13 +14,13 @@ impl<'a> Parser<'a> {
|
||||||
// Section 12
|
// Section 12
|
||||||
// The InputElementHashbangOrRegExp goal is used at the start of a Script
|
// The InputElementHashbangOrRegExp goal is used at the start of a Script
|
||||||
// or Module.
|
// 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 {
|
if self.cur_kind() == Kind::HashbangComment {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
self.bump_any();
|
self.bump_any();
|
||||||
let span = self.end_span(span);
|
let span = self.end_span(span);
|
||||||
let src = &self.source_text[span.start as usize + 2..span.end as usize];
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ impl<'a> Parser<'a> {
|
||||||
pub(crate) fn parse_directives_and_statements(
|
pub(crate) fn parse_directives_and_statements(
|
||||||
&mut self,
|
&mut self,
|
||||||
is_top_level: bool,
|
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 directives = self.ast.new_vec();
|
||||||
let mut statements = 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 {
|
if let Expression::StringLiteral(string) = &expr.expression {
|
||||||
let src = &self.source_text
|
let src = &self.source_text
|
||||||
[string.span.start as usize + 1..string.span.end as usize - 1];
|
[string.span.start as usize + 1..string.span.end as usize - 1];
|
||||||
let directive =
|
let directive = self.ast.directive(
|
||||||
self.ast.directive(expr.span, (*string).clone(), src);
|
expr.span,
|
||||||
|
(*string).clone(),
|
||||||
|
Atom::from(src),
|
||||||
|
);
|
||||||
directives.push(directive);
|
directives.push(directive);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue