Skip to content

Commit

Permalink
feat(parser): TypeScript 5.2 (#811)
Browse files Browse the repository at this point in the history
  • Loading branch information
camc314 committed Oct 4, 2023
1 parent 69f2364 commit 5b1e1e5
Show file tree
Hide file tree
Showing 25 changed files with 907 additions and 213 deletions.
15 changes: 15 additions & 0 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,7 @@ pub enum Declaration<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>),
FunctionDeclaration(Box<'a, Function<'a>>),
ClassDeclaration(Box<'a, Class<'a>>),
UsingDeclaration(Box<'a, UsingDeclaration<'a>>),

TSTypeAliasDeclaration(Box<'a, TSTypeAliasDeclaration<'a>>),
TSInterfaceDeclaration(Box<'a, TSInterfaceDeclaration<'a>>),
Expand Down Expand Up @@ -1069,6 +1070,18 @@ pub struct VariableDeclarator<'a> {
pub definite: bool,
}

/// Using Declaration
/// <https://github.com/tc39/proposal-explicit-resource-management>
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))]
pub struct UsingDeclaration<'a> {
#[cfg_attr(feature = "serde", serde(flatten))]
pub span: Span,
pub is_await: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub declarations: Vec<'a, VariableDeclarator<'a>>,
}

/// Empty Statement
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
Expand Down Expand Up @@ -1134,6 +1147,7 @@ pub struct ForStatement<'a> {
pub enum ForStatementInit<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>),
Expression(Expression<'a>),
UsingDeclaration(Box<'a, UsingDeclaration<'a>>),
}

impl<'a> ForStatementInit<'a> {
Expand Down Expand Up @@ -1172,6 +1186,7 @@ pub struct ForOfStatement<'a> {
pub enum ForStatementLeft<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>),
AssignmentTarget(AssignmentTarget<'a>),
UsingDeclaration(Box<'a, UsingDeclaration<'a>>),
}

impl<'a> ForStatementLeft<'a> {
Expand Down
22 changes: 22 additions & 0 deletions crates/oxc_ast/src/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ impl<'a> AstBuilder<'a> {
Statement::DebuggerStatement(self.alloc(DebuggerStatement { span }))
}

pub fn using_statement(
&self,
span: Span,
declarations: Vec<'a, VariableDeclarator<'a>>,
is_await: bool,
) -> Statement<'a> {
Statement::Declaration(Declaration::UsingDeclaration(self.alloc(UsingDeclaration {
span,
is_await,
declarations,
})))
}

pub fn do_while_statement(
&self,
span: Span,
Expand Down Expand Up @@ -742,6 +755,15 @@ impl<'a> AstBuilder<'a> {
VariableDeclarator { span, kind, id, init, definite }
}

pub fn using_declaration(
&self,
span: Span,
declarations: Vec<'a, VariableDeclarator<'a>>,
is_await: bool,
) -> UsingDeclaration<'a> {
UsingDeclaration { span, is_await, declarations }
}

/* ---------- Patterns ---------- */

pub fn binding_pattern(
Expand Down
6 changes: 6 additions & 0 deletions crates/oxc_ast/src/ast_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub enum AstKind<'a> {
VariableDeclaration(&'a VariableDeclaration<'a>),
VariableDeclarator(&'a VariableDeclarator<'a>),

UsingDeclaration(&'a UsingDeclaration<'a>),

IdentifierName(&'a IdentifierName),
IdentifierReference(&'a IdentifierReference),
BindingIdentifier(&'a BindingIdentifier),
Expand Down Expand Up @@ -271,6 +273,8 @@ impl<'a> GetSpan for AstKind<'a> {
Self::VariableDeclaration(x) => x.span,
Self::VariableDeclarator(x) => x.span,

Self::UsingDeclaration(x) => x.span,

Self::IdentifierName(x) => x.span,
Self::IdentifierReference(x) => x.span,
Self::BindingIdentifier(x) => x.span,
Expand Down Expand Up @@ -421,6 +425,8 @@ impl<'a> AstKind<'a> {
Self::VariableDeclaration(_) => "VariableDeclaration".into(),
Self::VariableDeclarator(_) => "VariableDeclarator".into(),

Self::UsingDeclaration(_) => "UsingDeclaration".into(),

Self::IdentifierName(x) => format!("IdentifierName({})", x.name).into(),
Self::IdentifierReference(x) => format!("IdentifierReference({})", x.name).into(),
Self::BindingIdentifier(x) => format!("BindingIdentifier({})", x.name).into(),
Expand Down
3 changes: 3 additions & 0 deletions crates/oxc_ast/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ impl<'a> GetSpan for Declaration<'a> {
match self {
Self::VariableDeclaration(decl) => decl.span,
Self::FunctionDeclaration(decl) => decl.span,
Self::UsingDeclaration(decl) => decl.span,
Self::ClassDeclaration(decl) => decl.span,
Self::TSTypeAliasDeclaration(decl) => decl.span,
Self::TSInterfaceDeclaration(decl) => decl.span,
Expand Down Expand Up @@ -235,6 +236,7 @@ impl<'a> GetSpan for ForStatementInit<'a> {
match self {
Self::VariableDeclaration(x) => x.span,
Self::Expression(x) => x.span(),
Self::UsingDeclaration(x) => x.span,
}
}
}
Expand All @@ -244,6 +246,7 @@ impl<'a> GetSpan for ForStatementLeft<'a> {
match self {
Self::VariableDeclaration(x) => x.span,
Self::AssignmentTarget(x) => x.span(),
Self::UsingDeclaration(x) => x.span,
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions crates/oxc_ast/src/syntax_directed_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ impl<'a> BoundNames for VariableDeclaration<'a> {
}
}

impl<'a> BoundNames for UsingDeclaration<'a> {
fn bound_names<F: FnMut(&BindingIdentifier)>(&self, f: &mut F) {
for declarator in &self.declarations {
declarator.id.bound_names(f);
}
}
}

impl<'a> BoundName for Function<'a> {
fn bound_name<F: FnMut(&BindingIdentifier)>(&self, f: &mut F) {
if let Some(ident) = &self.id {
Expand Down
16 changes: 16 additions & 0 deletions crates/oxc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ pub trait Visit<'a>: Sized {
let kind = AstKind::ForStatementInit(init);
self.enter_node(kind);
match init {
ForStatementInit::UsingDeclaration(decl) => {
self.visit_using_declaration(decl);
}
ForStatementInit::VariableDeclaration(decl) => {
self.visit_variable_declaration(decl);
}
Expand Down Expand Up @@ -167,6 +170,9 @@ pub trait Visit<'a>: Sized {
self.visit_variable_declaration(decl);
}
ForStatementLeft::AssignmentTarget(target) => self.visit_assignment_target(target),
ForStatementLeft::UsingDeclaration(decl) => {
self.visit_using_declaration(decl);
}
}
}

Expand Down Expand Up @@ -450,6 +456,15 @@ pub trait Visit<'a>: Sized {
self.leave_node(kind);
}

fn visit_using_declaration(&mut self, decl: &'a UsingDeclaration<'a>) {
let kind = AstKind::UsingDeclaration(decl);
self.enter_node(kind);
for decl in &decl.declarations {
self.visit_variable_declarator(decl);
}
self.leave_node(kind);
}

/* ---------- Expression ---------- */

fn visit_expression(&mut self, expr: &'a Expression<'a>) {
Expand Down Expand Up @@ -1264,6 +1279,7 @@ pub trait Visit<'a>: Sized {
Declaration::VariableDeclaration(decl) => self.visit_variable_declaration(decl),
Declaration::FunctionDeclaration(func) => self.visit_function(func),
Declaration::ClassDeclaration(class) => self.visit_class(class),
Declaration::UsingDeclaration(decl) => self.visit_using_declaration(decl),
Declaration::TSModuleDeclaration(module) => {
self.visit_ts_module_declaration(module);
}
Expand Down
13 changes: 13 additions & 0 deletions crates/oxc_ast/src/visit_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ pub trait VisitMut<'a, 'b>: Sized {
self.visit_variable_declaration(decl);
}
ForStatementInit::Expression(expr) => self.visit_expression(expr),
ForStatementInit::UsingDeclaration(decl) => {
self.visit_using_declaration(decl);
}
}
}

Expand All @@ -122,6 +125,9 @@ pub trait VisitMut<'a, 'b>: Sized {
self.visit_variable_declaration(decl);
}
ForStatementLeft::AssignmentTarget(target) => self.visit_assignment_target(target),
ForStatementLeft::UsingDeclaration(decl) => {
self.visit_using_declaration(decl);
}
}
}

Expand Down Expand Up @@ -212,6 +218,12 @@ pub trait VisitMut<'a, 'b>: Sized {
}
}

fn visit_using_declaration(&mut self, declaration: &'b mut UsingDeclaration<'a>) {
for decl in declaration.declarations.iter_mut() {
self.visit_variable_declarator(decl);
}
}

/* ---------- Function ---------- */

fn visit_function(&mut self, func: &'b mut Function<'a>) {
Expand Down Expand Up @@ -960,6 +972,7 @@ pub trait VisitMut<'a, 'b>: Sized {
Declaration::VariableDeclaration(decl) => self.visit_variable_declaration(decl),
Declaration::FunctionDeclaration(func) => self.visit_function(func),
Declaration::ClassDeclaration(class) => self.visit_class(class),
Declaration::UsingDeclaration(decl) => self.visit_using_declaration(decl),
Declaration::TSModuleDeclaration(module) => {
self.visit_ts_module_declaration(module);
}
Expand Down
18 changes: 18 additions & 0 deletions crates/oxc_formatter/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ impl<'a> Gen for ForStatement<'a> {
match init {
ForStatementInit::Expression(expr) => expr.gen(p),
ForStatementInit::VariableDeclaration(var) => var.gen(p),
ForStatementInit::UsingDeclaration(decl) => decl.gen(p),
}
}

Expand Down Expand Up @@ -225,6 +226,7 @@ impl<'a> Gen for ForStatementLeft<'a> {
match &self {
ForStatementLeft::VariableDeclaration(var) => var.gen(p),
ForStatementLeft::AssignmentTarget(target) => target.gen(p),
ForStatementLeft::UsingDeclaration(decl) => decl.gen(p),
}
}
}
Expand Down Expand Up @@ -447,6 +449,10 @@ impl<'a> Gen for Declaration<'a> {
declaration.gen(p);
p.print_newline();
}
Self::UsingDeclaration(declaration) => {
declaration.gen(p);
p.print_newline();
}
Self::TSTypeAliasDeclaration(_)
| Self::TSInterfaceDeclaration(_)
| Self::TSEnumDeclaration(_)
Expand All @@ -467,6 +473,18 @@ impl<'a> Gen for VariableDeclaration<'a> {
p.print_list(&self.declarations);
}
}
impl<'a> Gen for UsingDeclaration<'a> {
fn gen(&self, p: &mut Formatter) {
if self.is_await {
p.print_str(b"await");
p.print_space();
}
p.print_str(b"using");
p.print_space();
p.print_list(&self.declarations);
p.print_semicolon();
}
}

impl<'a> Gen for VariableDeclarator<'a> {
fn gen(&self, p: &mut Formatter) {
Expand Down
18 changes: 18 additions & 0 deletions crates/oxc_minifier/src/printer/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ impl<'a> Gen for ForStatement<'a> {
if let Some(init) = self.init.as_ref() {
let ctx = Context::empty();
match init {
ForStatementInit::UsingDeclaration(decl) => decl.gen(p, ctx),
ForStatementInit::Expression(expr) => {
expr.gen_expr(p, Precedence::lowest(), ctx);
}
Expand Down Expand Up @@ -267,6 +268,7 @@ impl<'a> Gen for ForOfStatement<'a> {
impl<'a> Gen for ForStatementLeft<'a> {
fn gen(&self, p: &mut Printer, ctx: Context) {
match &self {
ForStatementLeft::UsingDeclaration(var) => var.gen(p, ctx),
ForStatementLeft::VariableDeclaration(var) => var.gen(p, ctx),
ForStatementLeft::AssignmentTarget(target) => target.gen(p, ctx),
}
Expand Down Expand Up @@ -446,6 +448,9 @@ impl<'a> Gen for Declaration<'a> {
Self::ClassDeclaration(declaration) => {
declaration.gen(p, ctx);
}
Self::UsingDeclaration(declaration) => {
declaration.gen(p, ctx);
}
Self::TSEnumDeclaration(_) => {}
}
}
Expand All @@ -462,6 +467,19 @@ impl<'a> Gen for VariableDeclaration<'a> {
p.print_list(&self.declarations, ctx);
}
}
impl<'a> Gen for UsingDeclaration<'a> {
fn gen(&self, p: &mut Printer, ctx: Context) {
if self.is_await {
p.print_str(b"await");
p.print(b' ');
}
p.print_str(b"using");
p.print(b' ');

p.print_list(&self.declarations, ctx);
p.print_semicolon();
}
}

impl<'a> Gen for VariableDeclarator<'a> {
fn gen(&self, p: &mut Printer, ctx: Context) {
Expand Down
30 changes: 30 additions & 0 deletions crates/oxc_parser/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,33 @@ pub struct ReturnStatementOnlyInFunctionBody(#[label] pub Span);
#[error("TS18007: JSX expressions may not use the comma operator.")]
#[diagnostic(help("Did you mean to write an array?"))]
pub struct JSXExpressionsMayNotUseTheCommaOperator(#[label] pub Span);

#[derive(Debug, Error, Diagnostic)]
#[error("Line terminator not permitted before using declaration.")]
#[diagnostic()]
pub struct LineTerminatorBeforeUsingDeclaration(#[label] pub Span);

#[derive(Debug, Error, Diagnostic)]
#[error("Await is not allowed in using declarations.")]
#[diagnostic()]
pub struct AwaitInUsingDeclaration(#[label] pub Span);

#[derive(Debug, Error, Diagnostic)]
#[error("Using declarations may not have binding patterns.")]
#[diagnostic()]
pub struct InvalidIdentifierInUsingDeclaration(#[label] pub Span);

#[derive(Debug, Error, Diagnostic)]
#[error("The left-hand side of a for...in statement cannot be an await using declaration.")]
#[diagnostic()]
pub struct AwaitUsingDeclarationNotAllowedInForInStatement(#[label] pub Span);

#[derive(Debug, Error, Diagnostic)]
#[error("The left-hand side of a for...in statement cannot be an using declaration.")]
#[diagnostic()]
pub struct UsingDeclarationNotAllowedInForInStatement(#[label] pub Span);

#[derive(Debug, Error, Diagnostic)]
#[error("Using declarations must have an initializer.")]
#[diagnostic()]
pub struct UsingDeclarationsMustBeInitialized(#[label] pub Span);
Loading

0 comments on commit 5b1e1e5

Please sign in to comment.