mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
Typescript & parser for decorators
swc_atoms: - add some atoms swc_ecma_ast: - ast nodes for typescript - `ClassMethod` -> `Method`, `ClassMethodKind` -> `MethodKind` - private class method / class property - use separate type for tagged template literals - add `declare` field to `Decl`s - make function body optional swc_ecma_parser: - rename Type to TokenContext - support decorators Note: error reporting for invalid decorator is not implemented yet - merge `Config` into `Syntax` - Use DiagnosticBuilder for error type This is to make backtracking cheaper. swc_ecma_transforms: - add `strip` pass
This commit is contained in:
parent
2e22397f42
commit
ea610c6ded
@ -63,7 +63,7 @@ notifications:
|
||||
env:
|
||||
global:
|
||||
- CASHER_TIME_OUT=600
|
||||
- RUST_MIN_STACK=4194304
|
||||
- RUST_MIN_STACK=16777216
|
||||
- CARGO_INCREMENTAL=0
|
||||
- RUSTFLAGS="--cfg procmacro2_semver_exempt"
|
||||
- secure: Z4RSNlpg/12Qx2fIjS+7TToYxPJQgK70X7u9A5lJiCIa0JfzWCxr1ZEKXfAVLG9o4nQok+nWOZa+vxR1IgyUVnf6oSanjjWl1pSRbvccxMS799NvHmGzIAiqSKAlxiSJuxf7MQbs1XBuI3XahsWLfXGPo7vPT6sKe4AAf9gT6igJr61D5hpHkVIXK7P6rnrWQALQYplyaox0NlU9UlqSXXBjdJfp3138rl7FIeYRsMMow44unBNPvs+mhVP8PWpeFWeop0jxbNbTHwnJUbCm4ZWrvqnJ/m70IMlBMN1AskLmz4KeXOhPx+XR9VtdWBX4q8lJ7s9J0hMBxrEnxgiYVBPMlLoEX+wW3zwZ5F+DQs7uLpRHYRUpxpi/7ZuQjp+uT3mN9PMMSvbHwHLH2r/CC9olKYWySXIsGsGVyyMnZeUwvgzwxiYLoeCWe4zZY99zc7jvGKbSmk0RtPu6hApPwL5A6novXbXL2QsXzqqeWpgMLmZyb7KYhM5IGIAB1oPQIqI++Re9Z+/ea/DRSUJOsA96yRQ+vVbiuClrVgDhaAaJOGYCtR1XZ5N2zRb9+Spu/ECtfisLOb9Xs1584DyRbqG69nRdjuscjYOTFZUlOoOeFvuADY65Jt0kF6u7g8NIDkJ1ROb3heKQtY/bAQUrBNUJydOQnn5tBwn8Z618+Ac=
|
||||
|
@ -3,7 +3,10 @@ extern crate string_cache_codegen;
|
||||
use std::{env, path::Path};
|
||||
|
||||
fn main() {
|
||||
let strs = include_str!("words.txt").lines().map(|l| l.trim()).collect::<Vec<_>>();
|
||||
let strs = include_str!("words.txt")
|
||||
.lines()
|
||||
.map(|l| l.trim())
|
||||
.collect::<Vec<_>>();
|
||||
gen("js_word", "JsWord", &strs);
|
||||
}
|
||||
|
||||
|
@ -7,10 +7,13 @@ RegExp
|
||||
_extends
|
||||
_toConsumableArray
|
||||
abstract
|
||||
any
|
||||
apply
|
||||
as
|
||||
async
|
||||
await
|
||||
bigint
|
||||
boolean
|
||||
break
|
||||
call
|
||||
case
|
||||
@ -23,6 +26,7 @@ continue
|
||||
createClass
|
||||
createReactClass
|
||||
debugger
|
||||
declare
|
||||
default
|
||||
delete
|
||||
do
|
||||
@ -37,17 +41,26 @@ for
|
||||
from
|
||||
function
|
||||
get
|
||||
global
|
||||
if
|
||||
implements
|
||||
import
|
||||
in
|
||||
infer
|
||||
instanceof
|
||||
interface
|
||||
is
|
||||
key
|
||||
keyof
|
||||
length
|
||||
let
|
||||
module
|
||||
namespace
|
||||
never
|
||||
new
|
||||
null
|
||||
number
|
||||
object
|
||||
of
|
||||
package
|
||||
private
|
||||
@ -55,18 +68,24 @@ process
|
||||
protected
|
||||
public
|
||||
readonly
|
||||
require
|
||||
return
|
||||
set
|
||||
static
|
||||
string
|
||||
super
|
||||
switch
|
||||
symbol
|
||||
target
|
||||
this
|
||||
throw
|
||||
true
|
||||
try
|
||||
type
|
||||
typeof
|
||||
undefined
|
||||
unique
|
||||
unknown
|
||||
var
|
||||
void
|
||||
while
|
||||
|
@ -1,30 +1,114 @@
|
||||
use super::{Expr, Function, PropName};
|
||||
use crate::{
|
||||
expr::Expr,
|
||||
function::{Function, PatOrTsParamProp},
|
||||
ident::PrivateName,
|
||||
prop::PropName,
|
||||
stmt::BlockStmt,
|
||||
typescript::{
|
||||
Accessibility, TsExprWithTypeArgs, TsIndexSignature, TsTypeAnn, TsTypeParamDecl,
|
||||
TsTypeParamInstantiation,
|
||||
},
|
||||
};
|
||||
use swc_common::{ast_node, Fold, Span};
|
||||
|
||||
#[ast_node]
|
||||
pub struct Class {
|
||||
pub span: Span,
|
||||
|
||||
pub body: Vec<ClassMethod>,
|
||||
pub decorators: Vec<Decorator>,
|
||||
|
||||
pub body: Vec<ClassMember>,
|
||||
pub super_class: Option<Box<Expr>>,
|
||||
|
||||
pub is_abstract: bool,
|
||||
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub super_type_params: Option<TsTypeParamInstantiation>,
|
||||
|
||||
/// Typescript extension.
|
||||
pub implements: Vec<TsExprWithTypeArgs>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct ClassMethod {
|
||||
pub enum ClassMember {
|
||||
Constructor(Constructor),
|
||||
/// `es2015`
|
||||
Method(Method),
|
||||
PrivateMethod(PrivateMethod),
|
||||
/// stage 0 / Typescript
|
||||
ClassProp(ClassProp),
|
||||
PrivateProp(PrivateProp),
|
||||
TsIndexSignature(TsIndexSignature),
|
||||
}
|
||||
|
||||
pub type ClassProp = ClassProperty<Box<Expr>>;
|
||||
pub type PrivateProp = ClassProperty<PrivateName>;
|
||||
|
||||
#[ast_node]
|
||||
pub struct ClassProperty<K> {
|
||||
pub span: Span,
|
||||
|
||||
#[fold(bound)]
|
||||
pub key: K,
|
||||
pub value: Option<Box<Expr>>,
|
||||
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
|
||||
pub is_static: bool,
|
||||
pub decorators: Vec<Decorator>,
|
||||
|
||||
/// Typescript extension.
|
||||
pub accessibility: Option<Accessibility>,
|
||||
/// Typescript extension.
|
||||
pub is_abstract: bool,
|
||||
pub is_optional: bool,
|
||||
|
||||
pub readonly: bool,
|
||||
pub definite: bool,
|
||||
}
|
||||
|
||||
pub type Method = ClassMethod<PropName>;
|
||||
pub type PrivateMethod = ClassMethod<PrivateName>;
|
||||
|
||||
#[ast_node]
|
||||
pub struct Constructor {
|
||||
pub span: Span,
|
||||
pub key: PropName,
|
||||
pub params: Vec<PatOrTsParamProp>,
|
||||
pub body: Option<BlockStmt>,
|
||||
pub accessibility: Option<Accessibility>,
|
||||
pub is_optional: bool,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct ClassMethod<K> {
|
||||
pub span: Span,
|
||||
#[fold(bound)]
|
||||
pub key: K,
|
||||
|
||||
pub function: Function,
|
||||
|
||||
#[fold(ignore)]
|
||||
pub kind: ClassMethodKind,
|
||||
pub kind: MethodKind,
|
||||
|
||||
pub is_static: bool,
|
||||
|
||||
/// Typescript extension.
|
||||
pub accessibility: Option<Accessibility>,
|
||||
/// Typescript extension.
|
||||
pub is_abstract: bool,
|
||||
pub is_optional: bool,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct Decorator {
|
||||
pub span: Span,
|
||||
|
||||
pub expr: Box<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Fold)]
|
||||
pub enum ClassMethodKind {
|
||||
Constructor,
|
||||
pub enum MethodKind {
|
||||
Method,
|
||||
Getter,
|
||||
Setter,
|
||||
|
@ -1,4 +1,11 @@
|
||||
use super::{Class, Expr, Function, Ident, Pat};
|
||||
use crate::{
|
||||
class::Class,
|
||||
expr::Expr,
|
||||
function::Function,
|
||||
ident::Ident,
|
||||
pat::Pat,
|
||||
typescript::{TsEnumDecl, TsInterfaceDecl, TsModuleDecl, TsTypeAliasDecl},
|
||||
};
|
||||
use swc_common::{ast_node, Fold, Span};
|
||||
|
||||
#[ast_node]
|
||||
@ -6,11 +13,16 @@ pub enum Decl {
|
||||
Class(ClassDecl),
|
||||
Fn(FnDecl),
|
||||
Var(VarDecl),
|
||||
TsInterface(TsInterfaceDecl),
|
||||
TsTypeAlias(TsTypeAliasDecl),
|
||||
TsEnum(TsEnumDecl),
|
||||
TsModule(TsModuleDecl),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct FnDecl {
|
||||
pub ident: Ident,
|
||||
pub declare: bool,
|
||||
#[span]
|
||||
pub function: Function,
|
||||
}
|
||||
@ -18,6 +30,7 @@ pub struct FnDecl {
|
||||
#[ast_node]
|
||||
pub struct ClassDecl {
|
||||
pub ident: Ident,
|
||||
pub declare: bool,
|
||||
#[span]
|
||||
pub class: Class,
|
||||
}
|
||||
@ -26,7 +39,7 @@ pub struct ClassDecl {
|
||||
pub struct VarDecl {
|
||||
pub span: Span,
|
||||
pub kind: VarDeclKind,
|
||||
|
||||
pub declare: bool,
|
||||
pub decls: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
@ -47,4 +60,7 @@ pub struct VarDeclarator {
|
||||
pub name: Pat,
|
||||
/// Initialization expresion.
|
||||
pub init: Option<(Box<Expr>)>,
|
||||
|
||||
/// Typescript onpy
|
||||
pub definite: bool,
|
||||
}
|
||||
|
@ -1,6 +1,17 @@
|
||||
use super::{
|
||||
AssignOp, BinaryOp, BlockStmt, Class, Function, Ident, JSXElement, JSXEmptyExpr, JSXFragment,
|
||||
JSXMemberExpr, JSXNamespacedName, Lit, Pat, Prop, Str, UnaryOp, UpdateOp,
|
||||
use crate::{
|
||||
class::Class,
|
||||
function::Function,
|
||||
ident::Ident,
|
||||
jsx::{JSXElement, JSXEmptyExpr, JSXFragment, JSXMemberExpr, JSXNamespacedName},
|
||||
lit::{Lit, Str},
|
||||
operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp},
|
||||
pat::Pat,
|
||||
prop::Prop,
|
||||
stmt::BlockStmt,
|
||||
typescript::{
|
||||
TsAsExpr, TsNonNullExpr, TsTypeAnn, TsTypeAssertion, TsTypeCastExpr, TsTypeParamDecl,
|
||||
TsTypeParamInstantiation,
|
||||
},
|
||||
};
|
||||
use swc_common::{ast_node, Fold, Span, Spanned};
|
||||
|
||||
@ -50,7 +61,9 @@ pub enum Expr {
|
||||
|
||||
Lit(Lit),
|
||||
|
||||
Tpl(TplLit),
|
||||
Tpl(Tpl),
|
||||
|
||||
TaggedTpl(TaggedTpl),
|
||||
|
||||
Arrow(ArrowExpr),
|
||||
|
||||
@ -69,6 +82,11 @@ pub enum Expr {
|
||||
JSXEmpty(JSXEmptyExpr),
|
||||
JSXElement(JSXElement),
|
||||
JSXFragment(JSXFragment),
|
||||
|
||||
TsTypeAssertion(TsTypeAssertion),
|
||||
TsNonNull(TsNonNullExpr),
|
||||
TsTypeCast(TsTypeCastExpr),
|
||||
TsAs(TsAsExpr),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
@ -178,6 +196,8 @@ pub struct CallExpr {
|
||||
pub span: Span,
|
||||
pub callee: ExprOrSuper,
|
||||
pub args: Vec<ExprOrSpread>,
|
||||
pub type_args: Option<TsTypeParamInstantiation>,
|
||||
// pub type_params: Option<TsTypeParamInstantiation>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
@ -185,6 +205,8 @@ pub struct NewExpr {
|
||||
pub span: Span,
|
||||
pub callee: Box<Expr>,
|
||||
pub args: Option<(Vec<ExprOrSpread>)>,
|
||||
pub type_args: Option<TsTypeParamInstantiation>,
|
||||
// pub type_params: Option<TsTypeParamInstantiation>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
@ -201,6 +223,8 @@ pub struct ArrowExpr {
|
||||
pub body: BlockStmtOrExpr,
|
||||
pub is_async: bool,
|
||||
pub is_generator: bool,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub return_type: Option<TsTypeAnn>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
@ -223,13 +247,21 @@ pub struct AwaitExpr {
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TplLit {
|
||||
pub struct Tpl {
|
||||
pub span: Span,
|
||||
pub tag: Option<(Box<Expr>)>,
|
||||
pub exprs: Vec<(Box<Expr>)>,
|
||||
pub quasis: Vec<TplElement>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TaggedTpl {
|
||||
pub span: Span,
|
||||
pub tag: Box<Expr>,
|
||||
pub exprs: Vec<(Box<Expr>)>,
|
||||
pub quasis: Vec<TplElement>,
|
||||
pub type_params: Option<TsTypeParamInstantiation>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TplElement {
|
||||
pub span: Span,
|
||||
|
@ -1,17 +1,32 @@
|
||||
use super::{BlockStmt, Pat};
|
||||
use crate::{
|
||||
class::Decorator,
|
||||
pat::Pat,
|
||||
stmt::BlockStmt,
|
||||
typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl},
|
||||
};
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
/// Common parts of function and method.
|
||||
#[ast_node]
|
||||
pub struct Function {
|
||||
pub params: Vec<Pat>,
|
||||
|
||||
pub decorators: Vec<Decorator>,
|
||||
pub span: Span,
|
||||
|
||||
pub body: BlockStmt,
|
||||
pub body: Option<BlockStmt>,
|
||||
|
||||
/// if it's a generator.
|
||||
pub is_generator: bool,
|
||||
|
||||
/// if it's an async function.
|
||||
pub is_async: bool,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub return_type: Option<TsTypeAnn>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum PatOrTsParamProp {
|
||||
Pat(Pat),
|
||||
TsParamProp(TsParamProp),
|
||||
}
|
||||
|
@ -1,5 +1,59 @@
|
||||
use crate::Ident;
|
||||
use crate::typescript::TsTypeAnn;
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{ast_node, Fold, Span, Spanned};
|
||||
|
||||
/// Ident with span.
|
||||
#[derive(Spanned, Fold, Clone, PartialEq)]
|
||||
pub struct Ident {
|
||||
pub span: Span,
|
||||
#[fold(ignore)]
|
||||
pub sym: JsWord,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
/// TypeScript only. Used in case of an optional parameter.
|
||||
pub optional: bool,
|
||||
}
|
||||
|
||||
impl Debug for Ident {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_struct("Ident")
|
||||
.field("sym", &DebugUsingDisplay(&self.sym))
|
||||
.field("span", &self.span)
|
||||
.field("type_ann", &self.type_ann)
|
||||
.field("optional", &self.optional)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct PrivateName {
|
||||
pub span: Span,
|
||||
pub id: Ident,
|
||||
}
|
||||
|
||||
impl AsRef<str> for Ident {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.sym
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugUsingDisplay<T: Display>(T);
|
||||
impl<T: Display> Debug for DebugUsingDisplay<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ident {
|
||||
pub const fn new(sym: JsWord, span: Span) -> Self {
|
||||
Ident {
|
||||
span,
|
||||
sym,
|
||||
type_ann: None,
|
||||
optional: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IdentExt: AsRef<str> {
|
||||
fn is_reserved_for_es3(&self) -> bool {
|
@ -1,9 +1,15 @@
|
||||
use super::{Expr, Ident, Lit, SpreadElement};
|
||||
use crate::{
|
||||
expr::{Expr, SpreadElement},
|
||||
ident::Ident,
|
||||
lit::Lit,
|
||||
typescript::TsTypeParamInstantiation,
|
||||
};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
/// Used for `obj` property of `JSXMemberExpr`.
|
||||
#[ast_node]
|
||||
#[allow(variant_size_differences)]
|
||||
pub enum JSXObject {
|
||||
JSXMemberExpr(Box<JSXMemberExpr>),
|
||||
Ident(Ident),
|
||||
@ -65,6 +71,7 @@ pub struct JSXOpeningElement {
|
||||
pub span: Span,
|
||||
pub attrs: Vec<JSXAttrOrSpread>,
|
||||
pub self_closing: bool,
|
||||
pub type_args: Option<TsTypeParamInstantiation>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
|
@ -15,22 +15,25 @@ extern crate swc_atoms;
|
||||
extern crate swc_common;
|
||||
|
||||
pub use self::{
|
||||
class::{Class, ClassMethod, ClassMethodKind},
|
||||
class::{
|
||||
Class, ClassMember, ClassMethod, ClassProp, ClassProperty, Constructor, Decorator, Method,
|
||||
MethodKind, PrivateMethod, PrivateProp,
|
||||
},
|
||||
decl::{ClassDecl, Decl, FnDecl, VarDecl, VarDeclKind, VarDeclarator},
|
||||
expr::{
|
||||
ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BlockStmtOrExpr, CallExpr, ClassExpr,
|
||||
CondExpr, Expr, ExprOrSpread, ExprOrSuper, FnExpr, MemberExpr, MetaPropExpr, NewExpr,
|
||||
ObjectLit, ParenExpr, PatOrExpr, PropOrSpread, SeqExpr, SpreadElement, ThisExpr,
|
||||
TplElement, TplLit, UnaryExpr, UpdateExpr, YieldExpr,
|
||||
ObjectLit, ParenExpr, PatOrExpr, PropOrSpread, SeqExpr, SpreadElement, TaggedTpl, ThisExpr,
|
||||
Tpl, TplElement, UnaryExpr, UpdateExpr, YieldExpr,
|
||||
},
|
||||
function::Function,
|
||||
function::{Function, PatOrTsParamProp},
|
||||
ident::{Ident, IdentExt, PrivateName},
|
||||
jsx::{
|
||||
JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, JSXClosingFragment,
|
||||
JSXElement, JSXElementChild, JSXElementName, JSXEmptyExpr, JSXExpr, JSXExprContainer,
|
||||
JSXFragment, JSXMemberExpr, JSXNamespacedName, JSXObject, JSXOpeningElement,
|
||||
JSXOpeningFragment, JSXSpreadChild, JSXText,
|
||||
},
|
||||
keywords::IdentExt,
|
||||
lit::{Bool, Lit, Null, Number, Regex, RegexFlags, Str},
|
||||
module::{Module, ModuleItem},
|
||||
module_decl::{
|
||||
@ -47,17 +50,29 @@ pub use self::{
|
||||
ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt, Stmt, SwitchCase,
|
||||
SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, VarDeclOrPat, WhileStmt, WithStmt,
|
||||
},
|
||||
typescript::{
|
||||
Accessibility, TruePlusMinus, TsArrayType, TsAsExpr, TsCallSignatureDecl,
|
||||
TsConditionalType, TsConstructSignatureDecl, TsConstructorType, TsEntityName, TsEnumDecl,
|
||||
TsEnumMember, TsEnumMemberId, TsExportAssignment, TsExprWithTypeArgs, TsExternalModuleRef,
|
||||
TsFnOrConstructorType, TsFnParam, TsFnType, TsImportEqualsDecl, TsIndexSignature,
|
||||
TsIndexedAccessType, TsInferType, TsInterfaceBody, TsInterfaceDecl, TsIntersectionType,
|
||||
TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsMappedType, TsMethodSignature,
|
||||
TsModuleBlock, TsModuleDecl, TsModuleName, TsModuleRef, TsNamespaceBody, TsNamespaceDecl,
|
||||
TsNamespaceExportDecl, TsNonNullExpr, TsOptionalType, TsParamProp, TsParamPropParam,
|
||||
TsParenthesizedType, TsPropertySignature, TsQualifiedName, TsRestType, TsSignatureDecl,
|
||||
TsThisType, TsThisTypeOrIdent, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn,
|
||||
TsTypeAssertion, TsTypeCastExpr, TsTypeElement, TsTypeLit, TsTypeOperator,
|
||||
TsTypeOperatorOp, TsTypeParam, TsTypeParamDecl, TsTypeParamInstantiation, TsTypePredicate,
|
||||
TsTypeQuery, TsTypeRef, TsUnionOrIntersectionType, TsUnionType,
|
||||
},
|
||||
};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{Fold, Span, Spanned};
|
||||
|
||||
mod class;
|
||||
mod decl;
|
||||
mod expr;
|
||||
mod function;
|
||||
mod ident;
|
||||
mod jsx;
|
||||
mod keywords;
|
||||
mod lit;
|
||||
mod macros;
|
||||
mod module;
|
||||
@ -66,39 +81,4 @@ mod operators;
|
||||
mod pat;
|
||||
mod prop;
|
||||
mod stmt;
|
||||
|
||||
/// Ident with span.
|
||||
#[derive(Spanned, Fold, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Ident {
|
||||
pub span: Span,
|
||||
#[fold(ignore)]
|
||||
pub sym: JsWord,
|
||||
}
|
||||
|
||||
impl Debug for Ident {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Ident")
|
||||
.field(&DebugUsingDisplay(&self.sym))
|
||||
.field(&self.span)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Ident {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.sym
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugUsingDisplay<T: Display>(T);
|
||||
impl<T: Display> Debug for DebugUsingDisplay<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ident {
|
||||
pub fn new(sym: JsWord, span: Span) -> Self {
|
||||
Ident { span, sym }
|
||||
}
|
||||
}
|
||||
mod typescript;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::JSXText;
|
||||
use crate::jsx::JSXText;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{ast_node, Span};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{ModuleDecl, Stmt};
|
||||
use crate::{module_decl::ModuleDecl, stmt::Stmt};
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
#[ast_node]
|
||||
|
@ -1,4 +1,10 @@
|
||||
use super::{ClassExpr, Decl, Expr, FnExpr, Ident, Str, VarDecl};
|
||||
use crate::{
|
||||
decl::{Decl, VarDecl},
|
||||
expr::{ClassExpr, Expr, FnExpr},
|
||||
ident::Ident,
|
||||
lit::Str,
|
||||
typescript::{TsExportAssignment, TsImportEqualsDecl, TsInterfaceDecl, TsNamespaceExportDecl},
|
||||
};
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
#[ast_node]
|
||||
@ -11,6 +17,9 @@ pub enum ModuleDecl {
|
||||
|
||||
ExportDefaultExpr(Box<Expr>),
|
||||
ExportAll(ExportAll),
|
||||
TsImportEqualsDecl(TsImportEqualsDecl),
|
||||
TsExportAssignment(TsExportAssignment),
|
||||
TsNamespaceExportDecl(TsNamespaceExportDecl),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
@ -45,6 +54,8 @@ pub enum ExportDefaultDecl {
|
||||
Fn(FnExpr),
|
||||
|
||||
Var(VarDecl),
|
||||
|
||||
TsInterfaceDecl(TsInterfaceDecl),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{Expr, Ident, PropName};
|
||||
use crate::{expr::Expr, ident::Ident, prop::PropName, typescript::TsTypeAnn};
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
#[ast_node]
|
||||
@ -21,12 +21,14 @@ pub enum Pat {
|
||||
pub struct ArrayPat {
|
||||
pub span: Span,
|
||||
pub elems: Vec<(Option<Pat>)>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct ObjectPat {
|
||||
pub span: Span,
|
||||
pub props: Vec<ObjectPatProp>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
@ -34,6 +36,7 @@ pub struct AssignPat {
|
||||
pub span: Span,
|
||||
pub left: Box<Pat>,
|
||||
pub right: Box<Expr>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
}
|
||||
|
||||
/// EsTree `RestElement`
|
||||
@ -43,6 +46,7 @@ pub struct RestPat {
|
||||
pub dot3_token: Span,
|
||||
#[span(hi)]
|
||||
pub arg: Box<Pat>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
|
@ -1,4 +1,11 @@
|
||||
use super::{BlockStmt, Expr, Function, Ident, Number, Pat, Str};
|
||||
use crate::{
|
||||
expr::Expr,
|
||||
function::Function,
|
||||
ident::Ident,
|
||||
lit::{Number, Str},
|
||||
pat::Pat,
|
||||
stmt::BlockStmt,
|
||||
};
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
#[ast_node]
|
||||
@ -35,14 +42,14 @@ pub struct AssignProp {
|
||||
pub struct GetterProp {
|
||||
pub span: Span,
|
||||
pub key: PropName,
|
||||
pub body: BlockStmt,
|
||||
pub body: Option<BlockStmt>,
|
||||
}
|
||||
#[ast_node]
|
||||
pub struct SetterProp {
|
||||
pub span: Span,
|
||||
pub key: PropName,
|
||||
pub param: Pat,
|
||||
pub body: BlockStmt,
|
||||
pub body: Option<BlockStmt>,
|
||||
}
|
||||
#[ast_node]
|
||||
pub struct MethodProp {
|
||||
|
@ -1,4 +1,9 @@
|
||||
use super::{Decl, Expr, Ident, Pat, VarDecl};
|
||||
use crate::{
|
||||
decl::{Decl, VarDecl},
|
||||
expr::Expr,
|
||||
ident::Ident,
|
||||
pat::Pat,
|
||||
};
|
||||
use swc_common::{ast_node, Span};
|
||||
|
||||
/// Use when only block statements are allowed.
|
||||
|
566
ecmascript/ast/src/typescript.rs
Normal file
566
ecmascript/ast/src/typescript.rs
Normal file
@ -0,0 +1,566 @@
|
||||
#![allow(missing_copy_implementations)]
|
||||
|
||||
use crate::{
|
||||
class::Decorator,
|
||||
expr::Expr,
|
||||
ident::Ident,
|
||||
lit::{Bool, Number, Str},
|
||||
module::ModuleItem,
|
||||
pat::{AssignPat, ObjectPat, RestPat},
|
||||
};
|
||||
use swc_common::{ast_node, Fold, Span};
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeAnn {
|
||||
pub span: Span,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeParamDecl {
|
||||
pub span: Span,
|
||||
pub params: Vec<TsTypeParam>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeParam {
|
||||
pub span: Span,
|
||||
pub name: Ident,
|
||||
pub constraint: Option<Box<TsType>>,
|
||||
pub default: Option<Box<TsType>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeParamInstantiation {
|
||||
pub span: Span,
|
||||
pub params: Vec<Box<TsType>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeCastExpr {
|
||||
pub span: Span,
|
||||
pub expr: Box<Expr>,
|
||||
pub type_ann: TsTypeAnn,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsParamProp {
|
||||
pub span: Span,
|
||||
pub decorators: Vec<Decorator>,
|
||||
/// At least one of `accessibility` or `readonly` must be set.
|
||||
pub accessibility: Option<Accessibility>,
|
||||
pub readonly: bool,
|
||||
pub param: TsParamPropParam,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsParamPropParam {
|
||||
Ident(Ident),
|
||||
Assign(AssignPat),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsQualifiedName {
|
||||
#[span(lo)]
|
||||
pub left: TsEntityName,
|
||||
#[span(hi)]
|
||||
pub right: Ident,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
#[allow(variant_size_differences)]
|
||||
pub enum TsEntityName {
|
||||
TsQualifiedName(Box<TsQualifiedName>),
|
||||
Ident(Ident),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsSignatureDecl {
|
||||
TsCallSignatureDecl(TsCallSignatureDecl),
|
||||
TsConstructSignatureDecl(TsConstructSignatureDecl),
|
||||
TsMethodSignature(TsMethodSignature),
|
||||
TsFnType(TsFnType),
|
||||
TsConstructorType(TsConstructorType),
|
||||
}
|
||||
|
||||
// ================
|
||||
// TypeScript type members (for type literal / interface / class)
|
||||
// ================
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsTypeElement {
|
||||
TsCallSignatureDecl(TsCallSignatureDecl),
|
||||
TsConstructSignatureDecl(TsConstructSignatureDecl),
|
||||
TsPropertySignature(TsPropertySignature),
|
||||
TsMethodSignature(TsMethodSignature),
|
||||
TsIndexSignature(TsIndexSignature),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsCallSignatureDecl {
|
||||
pub span: Span,
|
||||
pub params: Vec<TsFnParam>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsConstructSignatureDecl {
|
||||
pub span: Span,
|
||||
pub params: Vec<TsFnParam>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsPropertySignature {
|
||||
pub span: Span,
|
||||
pub readonly: bool,
|
||||
pub key: Box<Expr>,
|
||||
pub computed: bool,
|
||||
pub optional: bool,
|
||||
pub init: Option<Box<Expr>>,
|
||||
pub params: Vec<TsFnParam>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsMethodSignature {
|
||||
pub span: Span,
|
||||
pub readonly: bool,
|
||||
pub key: Box<Expr>,
|
||||
pub computed: bool,
|
||||
pub optional: bool,
|
||||
pub params: Vec<TsFnParam>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsIndexSignature {
|
||||
pub params: Vec<TsFnParam>,
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
|
||||
pub readonly: bool,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
// ================
|
||||
// TypeScript types
|
||||
// ================
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsType {
|
||||
TsKeywordType(TsKeywordType),
|
||||
TsThisType(TsThisType),
|
||||
TsFnOrConstructorType(TsFnOrConstructorType),
|
||||
TsTypeRef(TsTypeRef),
|
||||
TsTypeQuery(TsTypeQuery),
|
||||
TsTypeLit(TsTypeLit),
|
||||
TsArrayType(TsArrayType),
|
||||
TsTupleType(TsTupleType),
|
||||
TsOptionalType(TsOptionalType),
|
||||
TsRestType(TsRestType),
|
||||
TsUnionOrIntersectionType(TsUnionOrIntersectionType),
|
||||
TsConditionalType(TsConditionalType),
|
||||
TsInferType(TsInferType),
|
||||
TsParenthesizedType(TsParenthesizedType),
|
||||
TsTypeOperator(TsTypeOperator),
|
||||
TsIndexedAccessType(TsIndexedAccessType),
|
||||
TsMappedType(TsMappedType),
|
||||
TsLitType(TsLitType),
|
||||
TsTypePredicate(TsTypePredicate),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsFnOrConstructorType {
|
||||
TsFnType(TsFnType),
|
||||
TsConstructorType(TsConstructorType),
|
||||
}
|
||||
|
||||
impl From<TsFnType> for TsType {
|
||||
fn from(t: TsFnType) -> Self {
|
||||
TsFnOrConstructorType::TsFnType(t).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TsConstructorType> for TsType {
|
||||
fn from(t: TsConstructorType) -> Self {
|
||||
TsFnOrConstructorType::TsConstructorType(t).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TsUnionType> for TsType {
|
||||
fn from(t: TsUnionType) -> Self {
|
||||
TsUnionOrIntersectionType::TsUnionType(t).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TsIntersectionType> for TsType {
|
||||
fn from(t: TsIntersectionType) -> Self {
|
||||
TsUnionOrIntersectionType::TsIntersectionType(t).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsKeywordType {
|
||||
pub span: Span,
|
||||
pub kind: TsKeywordTypeKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Fold)]
|
||||
pub enum TsKeywordTypeKind {
|
||||
TsAnyKeyword,
|
||||
TsUnknownKeyword,
|
||||
TsNumberKeyword,
|
||||
TsObjectKeyword,
|
||||
TsBooleanKeyword,
|
||||
TsBigIntKeyword,
|
||||
TsStringKeyword,
|
||||
TsSymbolKeyword,
|
||||
TsVoidKeyword,
|
||||
TsUndefinedKeyword,
|
||||
TsNullKeyword,
|
||||
TsNeverKeyword,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsThisType {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsFnParam {
|
||||
Ident(Ident),
|
||||
Rest(RestPat),
|
||||
Object(ObjectPat),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsFnType {
|
||||
pub span: Span,
|
||||
pub params: Vec<TsFnParam>,
|
||||
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub type_ann: TsTypeAnn,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsConstructorType {
|
||||
pub span: Span,
|
||||
pub params: Vec<TsFnParam>,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub type_ann: TsTypeAnn,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeRef {
|
||||
pub span: Span,
|
||||
pub type_name: TsEntityName,
|
||||
pub type_params: Option<TsTypeParamInstantiation>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypePredicate {
|
||||
pub span: Span,
|
||||
pub param_name: TsThisTypeOrIdent,
|
||||
pub type_ann: TsTypeAnn,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
#[allow(variant_size_differences)]
|
||||
pub enum TsThisTypeOrIdent {
|
||||
TsThisType(TsThisType),
|
||||
Ident(Ident),
|
||||
}
|
||||
|
||||
/// `typeof` operator
|
||||
#[ast_node]
|
||||
pub struct TsTypeQuery {
|
||||
pub span: Span,
|
||||
pub expr_name: TsEntityName,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeLit {
|
||||
pub span: Span,
|
||||
pub members: Vec<TsTypeElement>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsArrayType {
|
||||
pub span: Span,
|
||||
pub elem_type: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTupleType {
|
||||
pub span: Span,
|
||||
pub elem_types: Vec<Box<TsType>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsOptionalType {
|
||||
pub span: Span,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsRestType {
|
||||
pub span: Span,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsUnionOrIntersectionType {
|
||||
TsUnionType(TsUnionType),
|
||||
TsIntersectionType(TsIntersectionType),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsUnionType {
|
||||
pub span: Span,
|
||||
pub types: Vec<Box<TsType>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsIntersectionType {
|
||||
pub span: Span,
|
||||
pub types: Vec<Box<TsType>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsConditionalType {
|
||||
pub span: Span,
|
||||
pub check_type: Box<TsType>,
|
||||
pub extends_type: Box<TsType>,
|
||||
pub true_type: Box<TsType>,
|
||||
pub false_type: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsInferType {
|
||||
pub span: Span,
|
||||
pub type_param: TsTypeParam,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsParenthesizedType {
|
||||
pub span: Span,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeOperator {
|
||||
pub span: Span,
|
||||
pub op: TsTypeOperatorOp,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Fold)]
|
||||
pub enum TsTypeOperatorOp {
|
||||
KeyOf,
|
||||
Unique,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsIndexedAccessType {
|
||||
pub span: Span,
|
||||
pub obj_type: Box<TsType>,
|
||||
pub index_type: Box<TsType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Fold)]
|
||||
pub enum TruePlusMinus {
|
||||
True,
|
||||
Plus,
|
||||
Minus,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsMappedType {
|
||||
pub span: Span,
|
||||
pub readonly: Option<TruePlusMinus>,
|
||||
pub type_param: TsTypeParam,
|
||||
pub optional: Option<TruePlusMinus>,
|
||||
pub type_ann: Option<Box<TsType>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsLitType {
|
||||
pub span: Span,
|
||||
pub lit: TsLit,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsLit {
|
||||
Number(Number),
|
||||
Str(Str),
|
||||
Bool(Bool),
|
||||
}
|
||||
|
||||
// // ================
|
||||
// // TypeScript declarations
|
||||
// // ================
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsInterfaceDecl {
|
||||
pub span: Span,
|
||||
pub id: Ident,
|
||||
pub declare: bool,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub extends: Vec<TsExprWithTypeArgs>,
|
||||
pub body: TsInterfaceBody,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsInterfaceBody {
|
||||
pub span: Span,
|
||||
pub body: Vec<TsTypeElement>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsExprWithTypeArgs {
|
||||
pub span: Span,
|
||||
pub expr: TsEntityName,
|
||||
pub type_params: Option<TsTypeParamInstantiation>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeAliasDecl {
|
||||
pub span: Span,
|
||||
pub declare: bool,
|
||||
pub id: Ident,
|
||||
pub type_params: Option<TsTypeParamDecl>,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsEnumDecl {
|
||||
pub span: Span,
|
||||
pub declare: bool,
|
||||
pub is_const: bool,
|
||||
pub id: Ident,
|
||||
pub members: Vec<TsEnumMember>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsEnumMember {
|
||||
pub span: Span,
|
||||
pub id: TsEnumMemberId,
|
||||
pub init: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsEnumMemberId {
|
||||
Ident(Ident),
|
||||
Str(Str),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsModuleDecl {
|
||||
pub span: Span,
|
||||
pub declare: bool,
|
||||
/// In TypeScript, this is only available through`node.flags`.
|
||||
pub global: bool,
|
||||
pub id: TsModuleName,
|
||||
pub body: Option<TsNamespaceBody>,
|
||||
}
|
||||
|
||||
/// `namespace A.B { }` is a namespace named `A` with another TsNamespaceDecl as
|
||||
/// its body.
|
||||
#[ast_node]
|
||||
pub enum TsNamespaceBody {
|
||||
TsModuleBlock(TsModuleBlock),
|
||||
TsNamespaceDecl(TsNamespaceDecl),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsModuleBlock {
|
||||
pub span: Span,
|
||||
pub body: Vec<ModuleItem>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsNamespaceDecl {
|
||||
pub span: Span,
|
||||
pub declare: bool,
|
||||
/// In TypeScript, this is only available through`node.flags`.
|
||||
pub global: bool,
|
||||
pub id: Ident,
|
||||
pub body: Box<TsNamespaceBody>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsModuleName {
|
||||
Ident(Ident),
|
||||
Str(Str),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsImportEqualsDecl {
|
||||
pub span: Span,
|
||||
pub declare: bool,
|
||||
pub is_export: bool,
|
||||
pub id: Ident,
|
||||
pub module_ref: TsModuleRef,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub enum TsModuleRef {
|
||||
TsEntityName(TsEntityName),
|
||||
TsExternalModuleRef(TsExternalModuleRef),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsExternalModuleRef {
|
||||
pub span: Span,
|
||||
pub expr: Str,
|
||||
}
|
||||
|
||||
/// TypeScript's own parser uses ExportAssignment for both `export default` and
|
||||
/// `export =`. But for @babel/parser, `export default` is an ExportDefaultDecl,
|
||||
/// so a TsExportAssignment is always `export =`.
|
||||
#[ast_node]
|
||||
pub struct TsExportAssignment {
|
||||
pub span: Span,
|
||||
pub expr: Box<Expr>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsNamespaceExportDecl {
|
||||
pub span: Span,
|
||||
pub id: Ident,
|
||||
}
|
||||
|
||||
// // ================
|
||||
// // TypeScript exprs
|
||||
// // ================
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsAsExpr {
|
||||
pub span: Span,
|
||||
pub expr: Box<Expr>,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsTypeAssertion {
|
||||
pub span: Span,
|
||||
pub expr: Box<Expr>,
|
||||
pub type_ann: Box<TsType>,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub struct TsNonNullExpr {
|
||||
pub span: Span,
|
||||
pub expr: Box<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Fold)]
|
||||
pub enum Accessibility {
|
||||
Public,
|
||||
Protected,
|
||||
Private,
|
||||
}
|
@ -90,14 +90,17 @@ module.exports = {
|
||||
fn emit_colors(b: &mut Bencher) {
|
||||
b.bytes = SOURCE.len() as _;
|
||||
|
||||
let _ = ::testing::run_test(|cm, handler| {
|
||||
let session = Session {
|
||||
handler: &handler,
|
||||
cfg: Default::default(),
|
||||
};
|
||||
let _ = ::testing::run_test(true, |cm, handler| {
|
||||
let session = Session { handler: &handler };
|
||||
let fm = cm.new_source_file(FileName::Anon(0), SOURCE.into());
|
||||
let mut parser = Parser::new(session, Syntax::Es2019, SourceFileInput::from(&*fm));
|
||||
let module = parser.parse_module().unwrap();
|
||||
let mut parser = Parser::new(session, Syntax::Es, SourceFileInput::from(&*fm));
|
||||
let module = parser
|
||||
.parse_module()
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let buf = vec![];
|
||||
|
@ -14,6 +14,10 @@ impl<'a> Emitter<'a> {
|
||||
emit!(n);
|
||||
semi!(); // VarDecl is also used for for-loops
|
||||
}
|
||||
Decl::TsEnum(ref n) => emit!(n),
|
||||
Decl::TsInterface(ref n) => emit!(n),
|
||||
Decl::TsModule(ref n) => emit!(n),
|
||||
Decl::TsTypeAlias(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ pub mod list;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod text_writer;
|
||||
mod typescript;
|
||||
pub mod util;
|
||||
|
||||
pub type Result = io::Result<()>;
|
||||
@ -121,6 +122,9 @@ impl<'a> Emitter<'a> {
|
||||
semi!();
|
||||
}
|
||||
ModuleDecl::ExportAll(ref d) => emit!(d),
|
||||
ModuleDecl::TsExportAssignment(ref n) => emit!(n),
|
||||
ModuleDecl::TsImportEqualsDecl(ref n) => emit!(n),
|
||||
ModuleDecl::TsNamespaceExportDecl(ref n) => emit!(n),
|
||||
}
|
||||
self.wr.write_line()?;
|
||||
}
|
||||
@ -132,9 +136,10 @@ impl<'a> Emitter<'a> {
|
||||
keyword!("default");
|
||||
space!();
|
||||
match *node {
|
||||
ExportDefaultDecl::Class(ref class) => emit!(class),
|
||||
ExportDefaultDecl::Fn(ref f) => emit!(f),
|
||||
ExportDefaultDecl::Var(ref decl) => emit!(decl),
|
||||
ExportDefaultDecl::Class(ref n) => emit!(n),
|
||||
ExportDefaultDecl::Fn(ref n) => emit!(n),
|
||||
ExportDefaultDecl::Var(ref n) => emit!(n),
|
||||
ExportDefaultDecl::TsInterfaceDecl(ref n) => emit!(n),
|
||||
}
|
||||
semi!();
|
||||
}
|
||||
@ -369,6 +374,7 @@ impl<'a> Emitter<'a> {
|
||||
Expr::Object(ref n) => emit!(n),
|
||||
Expr::Paren(ref n) => emit!(n),
|
||||
Expr::Seq(ref n) => emit!(n),
|
||||
Expr::TaggedTpl(ref n) => emit!(n),
|
||||
Expr::This(ref n) => emit!(n),
|
||||
Expr::Tpl(ref n) => emit!(n),
|
||||
Expr::Unary(ref n) => emit!(n),
|
||||
@ -380,6 +386,11 @@ impl<'a> Emitter<'a> {
|
||||
Expr::JSXEmpty(ref n) => emit!(n),
|
||||
Expr::JSXElement(ref n) => emit!(n),
|
||||
Expr::JSXFragment(ref n) => emit!(n),
|
||||
|
||||
Expr::TsAs(ref n) => emit!(n),
|
||||
Expr::TsNonNull(ref n) => emit!(n),
|
||||
Expr::TsTypeAssertion(ref n) => emit!(n),
|
||||
Expr::TsTypeCast(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,16 +531,50 @@ impl<'a> Emitter<'a> {
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_class_method(&mut self, node: &ClassMethod) -> Result {
|
||||
pub fn emit_class_memeber(&mut self, node: &ClassMember) -> Result {
|
||||
match *node {
|
||||
ClassMember::Constructor(ref n) => emit!(n),
|
||||
ClassMember::ClassProp(ref n) => emit!(n),
|
||||
ClassMember::Method(ref n) => emit!(n),
|
||||
ClassMember::PrivateMethod(ref n) => emit!(n),
|
||||
ClassMember::PrivateProp(ref n) => emit!(n),
|
||||
ClassMember::TsIndexSignature(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_private_method(&mut self, n: &PrivateMethod) -> Result {
|
||||
unimplemented!("emit_private_method")
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_private_prop(&mut self, n: &PrivateProp) -> Result {
|
||||
unimplemented!("emit_private_prop")
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_class_prop(&mut self, node: &ClassProp) -> Result {
|
||||
unimplemented!("emit_class_prop")
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_class_constructor(&mut self, n: &Constructor) -> Result {
|
||||
keyword!("constructor");
|
||||
punct!("(");
|
||||
self.emit_list(n.span(), Some(&n.params), ListFormat::Parameters)?;
|
||||
punct!(")");
|
||||
|
||||
emit!(n.body);
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_class_method(&mut self, node: &Method) -> Result {
|
||||
if node.is_static {
|
||||
keyword!("static");
|
||||
space!();
|
||||
}
|
||||
match node.kind {
|
||||
ClassMethodKind::Constructor => {
|
||||
keyword!("constructor");
|
||||
}
|
||||
ClassMethodKind::Method => {
|
||||
MethodKind::Method => {
|
||||
if node.function.is_async {
|
||||
keyword!("async");
|
||||
}
|
||||
@ -540,13 +585,13 @@ impl<'a> Emitter<'a> {
|
||||
|
||||
emit!(node.key);
|
||||
}
|
||||
ClassMethodKind::Getter => {
|
||||
MethodKind::Getter => {
|
||||
keyword!("get");
|
||||
space!();
|
||||
|
||||
emit!(node.key);
|
||||
}
|
||||
ClassMethodKind::Setter => {
|
||||
MethodKind::Setter => {
|
||||
keyword!("set");
|
||||
space!();
|
||||
|
||||
@ -602,8 +647,8 @@ impl<'a> Emitter<'a> {
|
||||
self.emit_fn_trailing(&node.function)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
/// prints `(b){}` from `function a(b){}`
|
||||
#[emitter]
|
||||
pub fn emit_fn_trailing(&mut self, node: &Function) -> Result {
|
||||
punct!("(");
|
||||
self.emit_list(node.span, Some(&node.params), ListFormat::CommaListElements)?;
|
||||
@ -631,22 +676,39 @@ impl<'a> Emitter<'a> {
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_tpl_lit(&mut self, node: &TplLit) -> Result {
|
||||
pub fn emit_tpl_lit(&mut self, node: &Tpl) -> Result {
|
||||
debug_assert!(node.quasis.len() == node.exprs.len() + 1);
|
||||
|
||||
if let Some(ref tag) = node.tag {
|
||||
emit!(tag);
|
||||
}
|
||||
punct!("`");
|
||||
let i = 0;
|
||||
println!("{:?}", node.exprs.len() + node.quasis.len());
|
||||
|
||||
for i in 0..(node.quasis.len() + node.exprs.len()) {
|
||||
if i % 2 == 0 {
|
||||
emit!(node.quasis[i / 2]);
|
||||
} else {
|
||||
punct!("$");
|
||||
punct!("{");
|
||||
punct!("${");
|
||||
emit!(node.exprs[i / 2]);
|
||||
punct!("}");
|
||||
}
|
||||
}
|
||||
|
||||
punct!("`");
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_tagged_tpl_lit(&mut self, node: &TaggedTpl) -> Result {
|
||||
debug_assert!(node.quasis.len() == node.exprs.len() + 1);
|
||||
|
||||
emit!(node.tag);
|
||||
emit!(node.type_params);
|
||||
punct!("`");
|
||||
let i = 0;
|
||||
|
||||
for i in 0..(node.quasis.len() + node.exprs.len()) {
|
||||
if i % 2 == 0 {
|
||||
emit!(node.quasis[i / 2]);
|
||||
} else {
|
||||
punct!("${");
|
||||
emit!(node.exprs[i / 2]);
|
||||
punct!("}");
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ fn test_from_to(from: &str, to: &str) {
|
||||
where
|
||||
F: for<'a> FnOnce(&mut Parser<'a, SourceFileInput>) -> PResult<'a, Ret>,
|
||||
{
|
||||
self::testing::run_test(|cm, handler| {
|
||||
self::testing::run_test(true, |cm, handler| {
|
||||
let src = cm.new_source_file(FileName::Real(file_name.into()), s.to_string());
|
||||
println!(
|
||||
"Source: \n{}\nPos: {:?} ~ {:?}",
|
||||
@ -79,13 +79,14 @@ fn test_from_to(from: &str, to: &str) {
|
||||
);
|
||||
|
||||
let res = f(&mut Parser::new(
|
||||
Session {
|
||||
handler: &handler,
|
||||
cfg: Default::default(),
|
||||
},
|
||||
Syntax::Es2019,
|
||||
Session { handler: &handler },
|
||||
Syntax::Es,
|
||||
(&*src).into(),
|
||||
));
|
||||
))
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
});
|
||||
|
||||
res
|
||||
})
|
||||
|
330
ecmascript/codegen/src/typescript.rs
Normal file
330
ecmascript/codegen/src/typescript.rs
Normal file
@ -0,0 +1,330 @@
|
||||
use super::{Emitter, Result};
|
||||
use crate::list::ListFormat;
|
||||
use swc_common::Spanned;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen_macros::emitter;
|
||||
|
||||
impl<'a> Emitter<'a> {
|
||||
#[emitter]
|
||||
pub fn emit_pat_or_ts_param_prop(&mut self, n: &PatOrTsParamProp) -> Result {
|
||||
match *n {
|
||||
PatOrTsParamProp::Pat(ref n) => emit!(n),
|
||||
PatOrTsParamProp::TsParamProp(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_array_type(&mut self, n: &TsArrayType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_as_expr(&mut self, n: &TsAsExpr) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_call_signature_decl(&mut self, n: &TsCallSignatureDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_cond_type(&mut self, n: &TsConditionalType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_constructor_signature_decl(&mut self, n: &TsConstructSignatureDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_constructor_type(&mut self, n: &TsConstructorType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_entity_name(&mut self, n: &TsEntityName) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_enum_decl(&mut self, n: &TsEnumDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_enum_member(&mut self, n: &TsEnumMember) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_enum_member_id(&mut self, n: &TsEnumMemberId) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_export_assignment(&mut self, n: &TsExportAssignment) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_expr_with_type_args(&mut self, n: &TsExprWithTypeArgs) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_external_module_ref(&mut self, n: &TsExternalModuleRef) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_fn_or_constructor_type(&mut self, n: &TsFnOrConstructorType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_fn_param(&mut self, n: &TsFnParam) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_fn_type(&mut self, n: &TsFnType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_import_equals_decl(&mut self, n: &TsImportEqualsDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_index_signature(&mut self, n: &TsIndexSignature) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_index_accessed_type(&mut self, n: &TsIndexedAccessType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_infer_type(&mut self, n: &TsInferType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_interface_body(&mut self, n: &TsInterfaceBody) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_interface_decl(&mut self, n: &TsInterfaceDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_intersection_type(&mut self, n: &TsIntersectionType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_keyword_type(&mut self, n: &TsKeywordType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_lit(&mut self, n: &TsLit) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_lit_type(&mut self, n: &TsLitType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_mapped_type(&mut self, n: &TsMappedType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_method_signature(&mut self, n: &TsMethodSignature) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_module_block(&mut self, n: &TsModuleBlock) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_module_decl(&mut self, n: &TsModuleDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_module_name(&mut self, n: &TsModuleName) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_module_ref(&mut self, n: &TsModuleRef) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_ns_body(&mut self, n: &TsNamespaceBody) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_ns_decl(&mut self, n: &TsNamespaceDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_ns_export_decl(&mut self, n: &TsNamespaceExportDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_non_null_expr(&mut self, n: &TsNonNullExpr) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_optional_type(&mut self, n: &TsOptionalType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_param_prop(&mut self, n: &TsParamProp) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_param_prop_param(&mut self, n: &TsParamPropParam) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_paren_type(&mut self, n: &TsParenthesizedType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_property_signature(&mut self, n: &TsPropertySignature) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_qualified_name(&mut self, n: &TsQualifiedName) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_rest_type(&mut self, n: &TsRestType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_signature_decl(&mut self, n: &TsSignatureDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_this_type(&mut self, n: &TsThisType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_this_type_or_ident(&mut self, n: &TsThisTypeOrIdent) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_tuple_type(&mut self, n: &TsTupleType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type(&mut self, n: &TsType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_alias_decl(&mut self, n: &TsTypeAliasDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_ann(&mut self, n: &TsTypeAnn) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_assertion(&mut self, n: &TsTypeAssertion) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_cast_expr(&mut self, n: &TsTypeCastExpr) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_element(&mut self, n: &TsTypeElement) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_lit(&mut self, n: &TsTypeLit) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_operator(&mut self, n: &TsTypeOperator) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_param(&mut self, n: &TsTypeParam) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_param_decl(&mut self, n: &TsTypeParamDecl) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_param_instantiation(&mut self, n: &TsTypeParamInstantiation) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_predicate(&mut self, n: &TsTypePredicate) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_query(&mut self, n: &TsTypeQuery) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_type_ref(&mut self, n: &TsTypeRef) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_union_or_intersection_type(&mut self, n: &TsUnionOrIntersectionType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_ts_union_type(&mut self, n: &TsUnionType) -> Result {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
@ -190,12 +190,21 @@ impl StartsWithAlphaNum for Expr {
|
||||
false
|
||||
}
|
||||
|
||||
Expr::TaggedTpl(TaggedTpl { ref tag, .. }) => tag.starts_with_alpha_num(),
|
||||
|
||||
// it's empty
|
||||
Expr::JSXEmpty(..) => false,
|
||||
// start with `<`
|
||||
Expr::JSXFragment(..) | Expr::JSXElement(..) => false,
|
||||
Expr::JSXNamespacedName(..) => true,
|
||||
Expr::JSXMebmer(..) => true,
|
||||
|
||||
Expr::TsTypeAssertion(..) => false,
|
||||
Expr::TsNonNull(TsNonNullExpr { ref expr, .. })
|
||||
| Expr::TsAs(TsAsExpr { ref expr, .. }) => expr.starts_with_alpha_num(),
|
||||
|
||||
// TODO
|
||||
Expr::TsTypeCast(..) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
class a{
|
||||
constructor() {
|
||||
constructor(){
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a extends b{
|
||||
constructor() {
|
||||
constructor(){
|
||||
()=>{
|
||||
super();
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a extends b{
|
||||
constructor() {
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a extends b{
|
||||
constructor() {
|
||||
constructor(){
|
||||
()=>super();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a extends b{
|
||||
constructor() {
|
||||
constructor(){
|
||||
super.c;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a{
|
||||
constructor() {
|
||||
constructor(){
|
||||
}
|
||||
['constructor']() {
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a extends b{
|
||||
constructor() {
|
||||
constructor(){
|
||||
({
|
||||
c: super()
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
class a{
|
||||
constructor() {
|
||||
constructor(){
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
class a{
|
||||
constructor() {
|
||||
constructor(){
|
||||
}
|
||||
b() {
|
||||
}
|
||||
}
|
||||
;
|
||||
class c{
|
||||
constructor(...d) {
|
||||
constructor(...d){
|
||||
}
|
||||
b() {
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
class a extends b{
|
||||
constructor() {
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
(class{
|
||||
constructor() {
|
||||
constructor(){
|
||||
super.a;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
class a{
|
||||
static constructor() {
|
||||
constructor(){
|
||||
}
|
||||
static constructor() {
|
||||
constructor(){
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
class a extends b{
|
||||
constructor(c = super()) {
|
||||
constructor(c = super()){
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
(class{
|
||||
static constructor() {
|
||||
constructor(){
|
||||
}
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
(class extends a{
|
||||
constructor() {
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
});
|
||||
|
@ -16,8 +16,7 @@ use std::{
|
||||
path::Path,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use swc_common::{sync::Lrc, Fold, FoldWith, Span};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_common::sync::Lrc;
|
||||
use swc_ecma_codegen::Emitter;
|
||||
use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
|
||||
use test::{test_main, Options, ShouldPanic::No, TestDesc, TestDescAndFn, TestFn, TestName};
|
||||
@ -27,6 +26,7 @@ const IGNORED_PASS_TESTS: &[&str] = &[
|
||||
// Temporalily ignored
|
||||
"431ecef8c85d4d24.js",
|
||||
"8386fbff927a9e0e.js",
|
||||
"5654d4106d7025c2.js",
|
||||
// Wrong tests (variable name or value is different)
|
||||
"0339fa95c78c11bd.js",
|
||||
"0426f15dac46e92d.js",
|
||||
@ -136,7 +136,7 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
|
||||
);
|
||||
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
|
||||
|
||||
::testing::run_test(|cm, handler| {
|
||||
::testing::run_test(false, |cm, handler| {
|
||||
let src = cm.load_file(&entry.path()).expect("failed to load file");
|
||||
eprintln!(
|
||||
"{}\nPos: {:?} ~ {:?} (L{})",
|
||||
@ -147,14 +147,8 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
|
||||
);
|
||||
|
||||
let handlers = box MyHandlers;
|
||||
let mut parser: Parser<SourceFileInput> = Parser::new(
|
||||
Session {
|
||||
handler: &handler,
|
||||
cfg: Default::default(),
|
||||
},
|
||||
Syntax::Es2019,
|
||||
(&*src).into(),
|
||||
);
|
||||
let mut parser: Parser<SourceFileInput> =
|
||||
Parser::new(Session { handler: &handler }, Syntax::Es, (&*src).into());
|
||||
|
||||
let s: Lrc<String> = src.src.as_ref().map(|s| s.clone()).unwrap();
|
||||
let mut src_map_builder = SourceMapBuilder::new(Some(&s));
|
||||
@ -174,9 +168,19 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
|
||||
|
||||
// Parse source
|
||||
if module {
|
||||
emitter.emit_module(&parser.parse_module()?).unwrap();
|
||||
emitter
|
||||
.emit_module(&parser.parse_module().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})?)
|
||||
.unwrap();
|
||||
} else {
|
||||
emitter.emit_script(&parser.parse_script()?).unwrap();
|
||||
emitter
|
||||
.emit_script(&parser.parse_script().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})?)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
let ref_file = format!("{}", ref_dir.join(&file_name).display());
|
||||
@ -202,87 +206,6 @@ fn identity() {
|
||||
test_main(&args, tests, Options::new());
|
||||
}
|
||||
|
||||
pub fn normalize<T>(t: T) -> T
|
||||
where
|
||||
Normalizer: Fold<T>,
|
||||
{
|
||||
let mut n = Normalizer;
|
||||
n.fold(t)
|
||||
}
|
||||
|
||||
pub struct Normalizer;
|
||||
impl Fold<Span> for Normalizer {
|
||||
fn fold(&mut self, _: Span) -> Span {
|
||||
Span::default()
|
||||
}
|
||||
}
|
||||
impl Fold<Str> for Normalizer {
|
||||
fn fold(&mut self, s: Str) -> Str {
|
||||
Str {
|
||||
span: Default::default(),
|
||||
has_escape: false,
|
||||
..s
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Fold<Expr> for Normalizer {
|
||||
fn fold(&mut self, e: Expr) -> Expr {
|
||||
let e = e.fold_children(self);
|
||||
|
||||
match e {
|
||||
Expr::Paren(ParenExpr { expr, .. }) => *expr,
|
||||
Expr::New(NewExpr {
|
||||
callee,
|
||||
args: None,
|
||||
span,
|
||||
}) => Expr::New(NewExpr {
|
||||
span,
|
||||
callee,
|
||||
args: Some(vec![]),
|
||||
}),
|
||||
// Flatten comma expressions.
|
||||
Expr::Seq(SeqExpr { mut exprs, span }) => {
|
||||
let need_work = exprs.iter().any(|n| match **n {
|
||||
Expr::Seq(..) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
if need_work {
|
||||
exprs = exprs.into_iter().fold(vec![], |mut v, e| {
|
||||
match *e {
|
||||
Expr::Seq(SeqExpr { exprs, .. }) => v.extend(exprs),
|
||||
_ => v.push(e),
|
||||
}
|
||||
v
|
||||
});
|
||||
}
|
||||
Expr::Seq(SeqExpr { exprs, span })
|
||||
}
|
||||
_ => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<PropName> for Normalizer {
|
||||
fn fold(&mut self, n: PropName) -> PropName {
|
||||
let n = n.fold_children(self);
|
||||
|
||||
match n {
|
||||
PropName::Ident(Ident { sym, .. }) => PropName::Str(Str {
|
||||
span: Default::default(),
|
||||
value: sym,
|
||||
has_escape: false,
|
||||
}),
|
||||
PropName::Num(num) => PropName::Str(Str {
|
||||
span: Default::default(),
|
||||
value: num.to_string().into(),
|
||||
has_escape: false,
|
||||
}),
|
||||
_ => n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Buf(Arc<RwLock<Vec<u8>>>);
|
||||
impl Write for Buf {
|
||||
|
@ -87,16 +87,17 @@ fn add_golden_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
|
||||
file_name, input
|
||||
);
|
||||
|
||||
let stderr = ::testing::run_test(|cm, handler| {
|
||||
let stderr = ::testing::run_test(false, |cm, handler| {
|
||||
let fm = cm.new_source_file(FileName::Real(path.clone()), input);
|
||||
|
||||
let module = {
|
||||
let session = parser::Session {
|
||||
cfg: Default::default(),
|
||||
handler: &handler,
|
||||
};
|
||||
parser::Parser::new(session, Syntax::Es2019, SourceFileInput::from(&*fm))
|
||||
.parse_module()?
|
||||
let session = parser::Session { handler: &handler };
|
||||
parser::Parser::new(session, Syntax::Es, SourceFileInput::from(&*fm))
|
||||
.parse_module()
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})?
|
||||
};
|
||||
|
||||
lints::lint_all(&handler, &module);
|
||||
|
@ -53,16 +53,13 @@ fn yui(b: &mut Bencher) {
|
||||
fn bench_module(b: &mut Bencher, src: &'static str) {
|
||||
b.bytes = src.len() as _;
|
||||
|
||||
let _ = ::testing::run_test(|cm, handler| {
|
||||
let session = Session {
|
||||
handler: &handler,
|
||||
cfg: Default::default(),
|
||||
};
|
||||
let _ = ::testing::run_test(false, |cm, handler| {
|
||||
let session = Session { handler: &handler };
|
||||
let fm = cm.new_source_file(FileName::Anon(0), src.into());
|
||||
|
||||
b.iter(|| {
|
||||
test::black_box({
|
||||
let mut parser = Parser::new(session, Syntax::Es2019, SourceFileInput::from(&*fm));
|
||||
let mut parser = Parser::new(session, Syntax::Es, SourceFileInput::from(&*fm));
|
||||
let _ = parser.parse_module();
|
||||
})
|
||||
});
|
||||
|
@ -60,7 +60,11 @@ impl Fold for InjectSelf {
|
||||
}
|
||||
}
|
||||
|
||||
if i.method == "parse_with" || i.method == "spanned" {
|
||||
if i.method == "parse_with"
|
||||
|| i.method == "spanned"
|
||||
|| i.method == "try_parse_ts"
|
||||
|| i.method == "ts_in_no_context"
|
||||
{
|
||||
//TODO
|
||||
let parser = get_parser_arg(&i);
|
||||
return fold::fold_expr_method_call(
|
||||
@ -107,7 +111,7 @@ impl Fold for InjectSelf {
|
||||
let span = get_joinned_span(&i.path);
|
||||
|
||||
match &*name {
|
||||
"vec" | "unreachable" | "tok" | "op" | "js_word" => return i,
|
||||
"smallvec" | "vec" | "unreachable" | "tok" | "op" | "js_word" => return i,
|
||||
"println" | "print" | "format" | "assert" | "assert_eq" | "assert_ne"
|
||||
| "debug_assert" | "debug_assert_eq" | "debug_assert_ne" => {
|
||||
let mut args: Punctuated<Expr, token::Comma> = parse_args(i.tts.into());
|
||||
|
@ -83,6 +83,7 @@ pub(crate) enum SyntaxError {
|
||||
left: String,
|
||||
left_span: Span,
|
||||
},
|
||||
Hash,
|
||||
LineBreakInThrow,
|
||||
LineBreakBeforeArrow,
|
||||
|
||||
@ -110,6 +111,7 @@ pub(crate) enum SyntaxError {
|
||||
/// `()`
|
||||
EmptyParenExpr,
|
||||
InvalidPat,
|
||||
InvalidExpr,
|
||||
NotSimpleAssign,
|
||||
ExpectedIdent,
|
||||
ExpctedSemi,
|
||||
@ -134,6 +136,20 @@ pub(crate) enum SyntaxError {
|
||||
JSXExpectedClosingTag {
|
||||
tag: JsWord,
|
||||
},
|
||||
InvalidLeadingDecorator,
|
||||
DecoratorOnExport,
|
||||
|
||||
TsNonLastRest,
|
||||
TsRequiredAfterOptional,
|
||||
TsInvalidParamPropPat,
|
||||
|
||||
SpaceBetweenHashAndIdent,
|
||||
|
||||
AsyncConstructor,
|
||||
PropertyNamedConstructor,
|
||||
ClassProperty,
|
||||
ReadOnlyMethod,
|
||||
TsBindingPatCannotBeOptional,
|
||||
}
|
||||
|
||||
impl<'a> From<ErrorToDiag<'a>> for Error {
|
||||
@ -190,6 +206,7 @@ impl<'a> From<ErrorToDiag<'a>> for DiagnosticBuilder<'a> {
|
||||
identifier in string mode"
|
||||
.into(),
|
||||
UnaryInExp { .. } => "** cannot be applied to unary expression".into(),
|
||||
Hash => "Unexpected token '#'".into(),
|
||||
LineBreakInThrow => "LineBreak cannot follow 'throw'".into(),
|
||||
LineBreakBeforeArrow => "Unexpected line break between arrow head and arrow".into(),
|
||||
Unexpected { ref got } => format!("Unexpected token {}", got).into(),
|
||||
@ -213,6 +230,7 @@ impl<'a> From<ErrorToDiag<'a>> for DiagnosticBuilder<'a> {
|
||||
SpreadInParenExpr => "Parenthesized expression cannot contain spread operator".into(),
|
||||
EmptyParenExpr => "Parenthized expression cannot be empty".into(),
|
||||
InvalidPat => "Not a pattern".into(),
|
||||
InvalidExpr => "Not an expression".into(),
|
||||
// TODO
|
||||
NotSimpleAssign => "Cannot assign to this".into(),
|
||||
ExpectedIdent => "Expected ident".into(),
|
||||
@ -242,6 +260,29 @@ impl<'a> From<ErrorToDiag<'a>> for DiagnosticBuilder<'a> {
|
||||
JSXExpectedClosingTag { ref tag } => {
|
||||
format!("Expected corresponding JSX closing tag for <{}>", tag).into()
|
||||
}
|
||||
InvalidLeadingDecorator => {
|
||||
"Leading decorators must be attached to a class declaration".into()
|
||||
}
|
||||
DecoratorOnExport => "Using the export keyword between a decorator and a class is not \
|
||||
allowed. Please use `export @dec class` instead."
|
||||
.into(),
|
||||
TsNonLastRest => "A rest element must be last in a tuple type.".into(),
|
||||
TsRequiredAfterOptional => {
|
||||
"A required element cannot follow an optional element.".into()
|
||||
}
|
||||
TsInvalidParamPropPat => {
|
||||
"Typescript parameter property must be identifer or assignment pattern".into()
|
||||
}
|
||||
SpaceBetweenHashAndIdent => "Unexpected space between # and identifier".into(),
|
||||
AsyncConstructor => "Constructor can't be an async function".into(),
|
||||
PropertyNamedConstructor => {
|
||||
"Classes may not have a non-static field named 'constructor'".into()
|
||||
}
|
||||
ClassProperty => "Class property requires `esnext.classProperty` to be true".into(),
|
||||
ReadOnlyMethod => "A method cannot be readonly".into(),
|
||||
TsBindingPatCannotBeOptional => "A binding pattern parameter cannot be optional in an \
|
||||
implementation signature."
|
||||
.into(),
|
||||
};
|
||||
|
||||
let d = e.handler.error(&msg).span(e.span);
|
||||
|
@ -108,14 +108,20 @@ impl<'a> Input for SourceFileInput<'a> {
|
||||
self.start_pos = to;
|
||||
self.last_pos = to;
|
||||
}
|
||||
|
||||
fn is_at_start(&self) -> bool {
|
||||
self.fm.start_pos == self.last_pos
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Input {
|
||||
pub trait Input: Clone {
|
||||
fn cur(&mut self) -> Option<char>;
|
||||
fn peek(&mut self) -> Option<char>;
|
||||
fn peek_ahead(&mut self) -> Option<char>;
|
||||
fn bump(&mut self);
|
||||
|
||||
fn is_at_start(&self) -> bool;
|
||||
|
||||
fn cur_pos(&mut self) -> BytePos;
|
||||
|
||||
fn last_pos(&self) -> BytePos;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#![allow(unused_mut)]
|
||||
#![allow(unused_variables)]
|
||||
pub use self::input::Input;
|
||||
pub(crate) use self::state::{TokenContext, TokenContexts};
|
||||
use self::{state::State, util::*};
|
||||
use crate::{
|
||||
error::{Error, SyntaxError},
|
||||
@ -26,6 +27,7 @@ pub mod util;
|
||||
|
||||
pub(crate) type LexResult<T> = Result<T, Error>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Lexer<'a, I: Input> {
|
||||
session: Session<'a>,
|
||||
pub ctx: Context,
|
||||
@ -54,6 +56,7 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
let start = self.cur_pos();
|
||||
|
||||
let token = match c {
|
||||
'#' => return self.read_token_number_sign(),
|
||||
// Identifier or keyword. '\uXXXX' sequences are allowed in
|
||||
// identifiers, so '\' also dispatches to that.
|
||||
c if c == '\\' || c.is_ident_start() => return self.read_ident_or_keyword().map(Some),
|
||||
@ -110,7 +113,7 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
':' => {
|
||||
self.input.bump();
|
||||
|
||||
if self.session.cfg.fn_bind && self.input.cur() == Some(':') {
|
||||
if self.syntax.fn_bind() && self.input.cur() == Some(':') {
|
||||
self.input.bump();
|
||||
return Ok(Some(tok!("::")));
|
||||
}
|
||||
@ -278,6 +281,47 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
Ok(Some(token))
|
||||
}
|
||||
|
||||
/// `#`
|
||||
fn read_token_number_sign(&mut self) -> LexResult<Option<Token>> {
|
||||
assert!(self.cur().is_some());
|
||||
|
||||
let start = self.input.cur_pos();
|
||||
|
||||
if self.input.is_at_start() && self.read_token_interpreter()? {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if self.syntax.class_private_props() || self.syntax.class_private_methods() {
|
||||
self.input.bump(); // '#'
|
||||
return Ok(Some(Token::Hash));
|
||||
}
|
||||
|
||||
self.error(start, SyntaxError::Hash)?
|
||||
}
|
||||
|
||||
fn read_token_interpreter(&mut self) -> LexResult<bool> {
|
||||
if !self.input.is_at_start() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let start = self.input.cur_pos();
|
||||
self.input.bump();
|
||||
let c = self.input.cur();
|
||||
if c == Some('!') {
|
||||
loop {
|
||||
while let Some(c) = self.input.cur() {
|
||||
if c != '\n' && c != '\r' && c != '\u{8232}' && c != '\u{8233}' {
|
||||
self.input.bump();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.input.reset_to(start);
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Read an escaped charater for string literal.
|
||||
///
|
||||
/// In template literal, we should preserve raw string.
|
||||
@ -766,6 +810,10 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
pub fn had_line_break_before_last(&self) -> bool {
|
||||
self.state.had_line_break
|
||||
}
|
||||
|
||||
pub fn set_expr_allowed(&mut self, allow: bool) {
|
||||
self.state.is_expr_allowed = allow;
|
||||
}
|
||||
}
|
||||
|
||||
fn pos_span(p: BytePos) -> Span {
|
||||
|
@ -226,7 +226,7 @@ impl<'a, I: Input> Lexer<'a, I> {
|
||||
let mut total: Ret = Default::default();
|
||||
|
||||
while let Some(c) = self.cur() {
|
||||
if self.session.cfg.num_sep {
|
||||
if self.syntax.num_sep() {
|
||||
// let prev: char = unimplemented!("prev");
|
||||
// let next = self.input.peek();
|
||||
|
||||
@ -288,7 +288,7 @@ mod tests {
|
||||
F: FnOnce(&mut Lexer<SourceFileInput>) -> Ret,
|
||||
{
|
||||
crate::with_test_sess(s, |sess, fm| {
|
||||
let mut l = Lexer::new(sess, Syntax::Es2019, fm.into());
|
||||
let mut l = Lexer::new(sess, Syntax::Es, fm.into());
|
||||
Ok(f(&mut l))
|
||||
})
|
||||
.unwrap()
|
||||
@ -376,7 +376,7 @@ mod tests {
|
||||
|
||||
let vec = panic::catch_unwind(|| {
|
||||
crate::with_test_sess(case, |mut sess, input| {
|
||||
let mut l = Lexer::new(sess, Syntax::Es2019, input);
|
||||
let mut l = Lexer::new(sess, Syntax::Es, input);
|
||||
l.ctx.strict = strict;
|
||||
Ok(l.map(|ts| ts.token).collect::<Vec<_>>())
|
||||
})
|
||||
|
@ -7,7 +7,7 @@ use swc_common::BytePos;
|
||||
/// State of lexer.
|
||||
///
|
||||
/// Ported from babylon.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct State {
|
||||
pub is_expr_allowed: bool,
|
||||
pub octal_pos: Option<BytePos>,
|
||||
@ -19,7 +19,7 @@ pub(super) struct State {
|
||||
pub cur_line: usize,
|
||||
pub line_start: BytePos,
|
||||
|
||||
context: Context,
|
||||
context: TokenContexts,
|
||||
syntax: Syntax,
|
||||
|
||||
token_type: Option<TokenType>,
|
||||
@ -74,7 +74,7 @@ impl<'a> From<&'a Token> for TokenType {
|
||||
Token::JSXName { .. } => TokenType::JSXName,
|
||||
Token::BinOp(op) => TokenType::BinOp(op),
|
||||
|
||||
Token::Word(Keyword(k)) => TokenType::Keyword(k),
|
||||
Token::Word(Word::Keyword(k)) => TokenType::Keyword(k),
|
||||
_ => TokenType::Other {
|
||||
before_expr: t.before_expr(),
|
||||
},
|
||||
@ -82,6 +82,18 @@ impl<'a> From<&'a Token> for TokenType {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Input> Lexer<'a, I> {
|
||||
pub const fn token_context(&self) -> &TokenContexts {
|
||||
&self.state.context
|
||||
}
|
||||
pub fn token_context_mut(&mut self) -> &mut TokenContexts {
|
||||
&mut self.state.context
|
||||
}
|
||||
|
||||
pub fn set_token_context(&mut self, c: TokenContexts) {
|
||||
self.state.context = c;
|
||||
}
|
||||
}
|
||||
impl<'a, I: Input> Iterator for Lexer<'a, I> {
|
||||
type Item = TokenAndSpan;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -107,8 +119,8 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> {
|
||||
}
|
||||
};
|
||||
|
||||
match self.input.cur() {
|
||||
Some(..) => {}
|
||||
let c = match self.input.cur() {
|
||||
Some(c) => c,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
@ -122,9 +134,19 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> {
|
||||
self.state.start = start;
|
||||
|
||||
let res = (|| -> Result<Option<_>, _> {
|
||||
if self.syntax.jsx() {
|
||||
if self.syntax.typescript() && self.ctx.in_type {
|
||||
if c == '<' {
|
||||
self.input.bump();
|
||||
return Ok(Some(tok!('<')));
|
||||
} else if c == '>' {
|
||||
self.input.bump();
|
||||
return Ok(Some(tok!('>')));
|
||||
}
|
||||
}
|
||||
|
||||
if self.syntax.jsx() && !self.ctx.in_property_name {
|
||||
//jsx
|
||||
if self.state.context.current() == Some(Type::JSXExpr) {
|
||||
if self.state.context.current() == Some(TokenContext::JSXExpr) {
|
||||
let start = self.cur_pos();
|
||||
|
||||
return self.read_jsx_token();
|
||||
@ -132,8 +154,8 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> {
|
||||
|
||||
let c = self.cur();
|
||||
if let Some(c) = c {
|
||||
if self.state.context.current() == Some(Type::JSXOpeningTag)
|
||||
|| self.state.context.current() == Some(Type::JSXClosingTag)
|
||||
if self.state.context.current() == Some(TokenContext::JSXOpeningTag)
|
||||
|| self.state.context.current() == Some(TokenContext::JSXClosingTag)
|
||||
{
|
||||
if c.is_ident_start() {
|
||||
return self.read_jsx_word().map(Some);
|
||||
@ -145,7 +167,7 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> {
|
||||
}
|
||||
|
||||
if (c == '\'' || c == '"')
|
||||
&& self.state.context.current() == Some(Type::JSXOpeningTag)
|
||||
&& self.state.context.current() == Some(TokenContext::JSXOpeningTag)
|
||||
{
|
||||
return self.read_jsx_str(c).map(Some);
|
||||
}
|
||||
@ -158,7 +180,7 @@ impl<'a, I: Input> Iterator for Lexer<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(Type::Tpl {
|
||||
if let Some(TokenContext::Tpl {
|
||||
start: start_pos_of_tpl,
|
||||
}) = self.state.context.current()
|
||||
{
|
||||
@ -195,7 +217,7 @@ impl State {
|
||||
octal_pos: None,
|
||||
is_first: true,
|
||||
had_line_break: false,
|
||||
context: Context(smallvec![Type::BraceStmt]),
|
||||
context: TokenContexts(smallvec![TokenContext::BraceStmt]),
|
||||
token_type: None,
|
||||
start: BytePos(0),
|
||||
line_start: BytePos(0),
|
||||
@ -244,7 +266,7 @@ impl State {
|
||||
/// `is_expr_allowed`: previous value.
|
||||
/// `start`: start of newly produced token.
|
||||
fn is_expr_allowed_on_next(
|
||||
context: &mut Context,
|
||||
context: &mut TokenContexts,
|
||||
syntax: Syntax,
|
||||
prev: Option<TokenType>,
|
||||
start: BytePos,
|
||||
@ -253,7 +275,7 @@ impl State {
|
||||
is_expr_allowed: bool,
|
||||
) -> bool {
|
||||
let is_next_keyword = match next {
|
||||
&Word(Keyword(..)) => true,
|
||||
&Word(Word::Keyword(..)) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
@ -271,13 +293,15 @@ impl State {
|
||||
let out = context.pop().unwrap();
|
||||
|
||||
// let a = function(){}
|
||||
if out == Type::BraceStmt && context.current() == Some(Type::FnExpr) {
|
||||
if out == TokenContext::BraceStmt
|
||||
&& context.current() == Some(TokenContext::FnExpr)
|
||||
{
|
||||
context.pop();
|
||||
return false;
|
||||
}
|
||||
|
||||
// ${} in template
|
||||
if out == Type::TplQuasi {
|
||||
if out == TokenContext::TplQuasi {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -291,20 +315,22 @@ impl State {
|
||||
if is_expr_allowed
|
||||
&& !context.is_brace_block(prev, had_line_break, is_expr_allowed)
|
||||
{
|
||||
context.push(Type::FnExpr);
|
||||
context.push(TokenContext::FnExpr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// for (a of b) {}
|
||||
tok!("of") if Some(Type::ParenStmt { is_for_loop: true }) == context.current() => {
|
||||
tok!("of")
|
||||
if Some(TokenContext::ParenStmt { is_for_loop: true }) == context.current() =>
|
||||
{
|
||||
// e.g. for (a of _) => true
|
||||
!prev
|
||||
.expect("context.current() if ParenStmt, so prev token cannot be None")
|
||||
.before_expr()
|
||||
}
|
||||
|
||||
Word(Ident(ref ident)) => {
|
||||
Word(Word::Ident(ref ident)) => {
|
||||
// variable declaration
|
||||
return match prev {
|
||||
Some(prev) => match prev {
|
||||
@ -324,16 +350,16 @@ impl State {
|
||||
|
||||
tok!('{') => {
|
||||
let cur = context.current();
|
||||
if syntax.jsx() && cur == Some(Type::JSXOpeningTag) {
|
||||
context.push(Type::BraceExpr)
|
||||
} else if syntax.jsx() && cur == Some(Type::JSXExpr) {
|
||||
context.push(Type::TplQuasi);
|
||||
if syntax.jsx() && cur == Some(TokenContext::JSXOpeningTag) {
|
||||
context.push(TokenContext::BraceExpr)
|
||||
} else if syntax.jsx() && cur == Some(TokenContext::JSXExpr) {
|
||||
context.push(TokenContext::TplQuasi);
|
||||
} else {
|
||||
let next_ctxt =
|
||||
if context.is_brace_block(prev, had_line_break, is_expr_allowed) {
|
||||
Type::BraceStmt
|
||||
TokenContext::BraceStmt
|
||||
} else {
|
||||
Type::BraceExpr
|
||||
TokenContext::BraceExpr
|
||||
};
|
||||
context.push(next_ctxt);
|
||||
}
|
||||
@ -343,12 +369,12 @@ impl State {
|
||||
tok!('/') if syntax.jsx() && prev == Some(TokenType::JSXTagStart) => {
|
||||
context.pop();
|
||||
context.pop(); // do not consider JSX expr -> JSX open tag -> ... anymore
|
||||
context.push(Type::JSXClosingTag); // reconsider as closing tag context
|
||||
context.push(TokenContext::JSXClosingTag); // reconsider as closing tag context
|
||||
false
|
||||
}
|
||||
|
||||
tok!("${") => {
|
||||
context.push(Type::TplQuasi);
|
||||
context.push(TokenContext::TplQuasi);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -357,11 +383,11 @@ impl State {
|
||||
|
||||
context.push(match prev {
|
||||
Some(TokenType::Keyword(k)) => match k {
|
||||
If | With | While => Type::ParenStmt { is_for_loop: false },
|
||||
For => Type::ParenStmt { is_for_loop: true },
|
||||
_ => Type::ParenExpr,
|
||||
If | With | While => TokenContext::ParenStmt { is_for_loop: false },
|
||||
For => TokenContext::ParenStmt { is_for_loop: true },
|
||||
_ => TokenContext::ParenExpr,
|
||||
},
|
||||
_ => Type::ParenExpr,
|
||||
_ => TokenContext::ParenExpr,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@ -371,30 +397,30 @@ impl State {
|
||||
|
||||
tok!('`') => {
|
||||
// If we are in template, ` terminates template.
|
||||
if let Some(Type::Tpl { .. }) = context.current() {
|
||||
if let Some(TokenContext::Tpl { .. }) = context.current() {
|
||||
context.pop();
|
||||
} else {
|
||||
context.push(Type::Tpl { start });
|
||||
context.push(TokenContext::Tpl { start });
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// tt.jsxTagStart.updateContext
|
||||
Token::JSXTagStart => {
|
||||
context.push(Type::JSXExpr); // treat as beginning of JSX expression
|
||||
context.push(Type::JSXOpeningTag); // start opening tag context
|
||||
context.push(TokenContext::JSXExpr); // treat as beginning of JSX expression
|
||||
context.push(TokenContext::JSXOpeningTag); // start opening tag context
|
||||
return false;
|
||||
}
|
||||
|
||||
// tt.jsxTagEnd.updateContext
|
||||
Token::JSXTagEnd => {
|
||||
let out = context.pop();
|
||||
if (out == Some(Type::JSXOpeningTag)
|
||||
if (out == Some(TokenContext::JSXOpeningTag)
|
||||
&& prev == Some(TokenType::BinOp(BinOpToken::Div)))
|
||||
|| out == Some(Type::JSXClosingTag)
|
||||
|| out == Some(TokenContext::JSXClosingTag)
|
||||
{
|
||||
context.pop();
|
||||
return context.current() == Some(Type::JSXExpr);
|
||||
return context.current() == Some(TokenContext::JSXExpr);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@ -408,9 +434,9 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Context(SmallVec<[Type; 32]>);
|
||||
impl Context {
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct TokenContexts(pub SmallVec<[TokenContext; 32]>);
|
||||
impl TokenContexts {
|
||||
/// Returns true if following `LBrace` token is `block statement` according
|
||||
/// to `ctx`, `prev`, `is_expr_allowed`.
|
||||
fn is_brace_block(
|
||||
@ -421,10 +447,10 @@ impl Context {
|
||||
) -> bool {
|
||||
match prev {
|
||||
Some(TokenType::Colon) => match self.current() {
|
||||
Some(Type::BraceStmt) => return true,
|
||||
Some(TokenContext::BraceStmt) => return true,
|
||||
// `{ a: {} }`
|
||||
// ^ ^
|
||||
Some(Type::BraceExpr) => return false,
|
||||
Some(TokenContext::BraceExpr) => return false,
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
@ -452,7 +478,7 @@ impl Context {
|
||||
}
|
||||
|
||||
// If previous token was `{`
|
||||
Some(TokenType::LBrace) => return self.current() == Some(Type::BraceStmt),
|
||||
Some(TokenType::LBrace) => return self.current() == Some(TokenContext::BraceStmt),
|
||||
|
||||
// `class C<T> { ... }`
|
||||
Some(TokenType::BinOp(Lt)) | Some(TokenType::BinOp(Gt)) => return true,
|
||||
@ -462,18 +488,18 @@ impl Context {
|
||||
return !is_expr_allowed;
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
fn pop(&mut self) -> Option<Type> {
|
||||
pub fn pop(&mut self) -> Option<TokenContext> {
|
||||
let opt = self.0.pop();
|
||||
trace!("context.pop({:?})", opt);
|
||||
opt
|
||||
}
|
||||
fn current(&self) -> Option<Type> {
|
||||
pub fn current(&self) -> Option<TokenContext> {
|
||||
self.0.last().cloned()
|
||||
}
|
||||
fn push(&mut self, t: Type) {
|
||||
fn push(&mut self, t: TokenContext) {
|
||||
trace!("context.push({:?})", t);
|
||||
self.0.push(t);
|
||||
}
|
||||
@ -484,7 +510,7 @@ impl Context {
|
||||
/// See https://github.com/mozilla/sweet.js/wiki/design
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Kind)]
|
||||
#[kind(fucntion(is_expr = "bool", preserve_space = "bool"))]
|
||||
enum Type {
|
||||
pub(crate) enum TokenContext {
|
||||
BraceStmt,
|
||||
#[kind(is_expr)]
|
||||
BraceExpr,
|
||||
@ -522,7 +548,7 @@ where
|
||||
let mut l = Lexer::new(sess, syntax, fm);
|
||||
let res = f(&mut l);
|
||||
|
||||
let c: SmallVec<[Type; 32]> = smallvec![Type::BraceStmt];
|
||||
let c: SmallVec<[TokenContext; 32]> = smallvec![TokenContext::BraceStmt];
|
||||
assert_eq!(l.state.context.0, c);
|
||||
|
||||
res
|
||||
|
@ -76,12 +76,12 @@ impl WithSpan for f64 {
|
||||
}
|
||||
impl<'a> WithSpan for &'a str {
|
||||
fn into_token(self) -> Token {
|
||||
Word(Ident(self.into()))
|
||||
Word(Word::Ident(self.into()))
|
||||
}
|
||||
}
|
||||
impl WithSpan for Keyword {
|
||||
fn into_token(self) -> Token {
|
||||
Word(Keyword(self))
|
||||
Word(Word::Keyword(self))
|
||||
}
|
||||
}
|
||||
impl WithSpan for Word {
|
||||
@ -103,7 +103,7 @@ impl WithSpan for AssignOpToken {
|
||||
#[test]
|
||||
fn module_legacy_octal() {
|
||||
assert_eq!(
|
||||
lex_module(Syntax::Es2019, "01"),
|
||||
lex_module(Syntax::Es, "01"),
|
||||
vec![Token::Error(Error {
|
||||
span: sp(0..2),
|
||||
error: SyntaxError::LegacyOctal,
|
||||
@ -115,7 +115,7 @@ fn module_legacy_octal() {
|
||||
#[test]
|
||||
fn module_legacy_decimal() {
|
||||
assert_eq!(
|
||||
lex_module(Syntax::Es2019, "08"),
|
||||
lex_module(Syntax::Es, "08"),
|
||||
vec![Token::Error(Error {
|
||||
span: sp(0..2),
|
||||
error: SyntaxError::LegacyDecimal,
|
||||
@ -128,7 +128,7 @@ fn module_legacy_decimal() {
|
||||
#[test]
|
||||
fn module_legacy_comment_1() {
|
||||
assert_eq!(
|
||||
lex_module(Syntax::Es2019, "<!-- foo oo"),
|
||||
lex_module(Syntax::Es, "<!-- foo oo"),
|
||||
vec![Token::Error(Error {
|
||||
span: sp(0..11),
|
||||
error: SyntaxError::LegacyCommentInModule,
|
||||
@ -141,7 +141,7 @@ fn module_legacy_comment_1() {
|
||||
#[test]
|
||||
fn module_legacy_comment_2() {
|
||||
assert_eq!(
|
||||
lex_module(Syntax::Es2019, "-->"),
|
||||
lex_module(Syntax::Es, "-->"),
|
||||
vec![Token::Error(Error {
|
||||
span: sp(0..3),
|
||||
error: SyntaxError::LegacyCommentInModule,
|
||||
@ -162,7 +162,7 @@ fn test262_lexer_error_0001() {
|
||||
1.span(7..8),
|
||||
RParen.span(8..9),
|
||||
],
|
||||
lex(Syntax::Es2019, "123..a(1)")
|
||||
lex(Syntax::Es, "123..a(1)")
|
||||
)
|
||||
}
|
||||
|
||||
@ -178,41 +178,35 @@ fn test262_lexer_error_0002() {
|
||||
.lb(),
|
||||
Semi.span(15..16),
|
||||
],
|
||||
lex(Syntax::Es2019, r#"'use\x20strict';"#)
|
||||
lex(Syntax::Es, r#"'use\x20strict';"#)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test262_lexer_error_0003() {
|
||||
assert_eq!(vec!["a".span(0..6).lb()], lex(Syntax::Es2019, r#"\u0061"#));
|
||||
assert_eq!(vec!["a".span(0..6).lb()], lex(Syntax::Es, r#"\u0061"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test262_lexer_error_0004() {
|
||||
assert_eq!(
|
||||
vec![tok!('+'), tok!('{'), tok!('}'), tok!('/'), 1.into_token()],
|
||||
lex_tokens(Syntax::Es2019, "+{} / 1")
|
||||
lex_tokens(Syntax::Es, "+{} / 1")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ident_escape_unicode() {
|
||||
assert_eq!(
|
||||
vec!["aa".span(0..7).lb()],
|
||||
lex(Syntax::Es2019, r#"a\u0061"#)
|
||||
);
|
||||
assert_eq!(vec!["aa".span(0..7).lb()], lex(Syntax::Es, r#"a\u0061"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ident_escape_unicode_2() {
|
||||
assert_eq!(
|
||||
vec!["℘℘".span(0..6).lb()],
|
||||
lex(Syntax::Es2019, "℘℘")
|
||||
);
|
||||
assert_eq!(vec!["℘℘".span(0..6).lb()], lex(Syntax::Es, "℘℘"));
|
||||
|
||||
assert_eq!(
|
||||
vec!["℘℘".span(0..9).lb()],
|
||||
lex(Syntax::Es2019, r#"℘\u2118"#)
|
||||
lex(Syntax::Es, r#"℘\u2118"#)
|
||||
);
|
||||
}
|
||||
|
||||
@ -220,7 +214,7 @@ fn ident_escape_unicode_2() {
|
||||
fn tpl_multiline() {
|
||||
assert_eq!(
|
||||
lex_tokens(
|
||||
Syntax::Es2019,
|
||||
Syntax::Es,
|
||||
"`this
|
||||
is
|
||||
multiline`"
|
||||
@ -240,7 +234,7 @@ multiline`"
|
||||
#[test]
|
||||
fn tpl_raw_unicode_escape() {
|
||||
assert_eq!(
|
||||
lex_tokens(Syntax::Es2019, r"`\u{0010}`"),
|
||||
lex_tokens(Syntax::Es, r"`\u{0010}`"),
|
||||
vec![
|
||||
tok!('`'),
|
||||
Token::Template {
|
||||
@ -256,7 +250,7 @@ fn tpl_raw_unicode_escape() {
|
||||
#[test]
|
||||
fn str_escape() {
|
||||
assert_eq!(
|
||||
lex_tokens(Syntax::Es2019, r#"'\n'"#),
|
||||
lex_tokens(Syntax::Es, r#"'\n'"#),
|
||||
vec![Token::Str {
|
||||
value: "\n".into(),
|
||||
has_escape: true
|
||||
@ -267,7 +261,7 @@ fn str_escape() {
|
||||
#[test]
|
||||
fn str_escape_2() {
|
||||
assert_eq!(
|
||||
lex_tokens(Syntax::Es2019, r#"'\\n'"#),
|
||||
lex_tokens(Syntax::Es, r#"'\\n'"#),
|
||||
vec![Token::Str {
|
||||
value: "\\n".into(),
|
||||
has_escape: true
|
||||
@ -278,7 +272,7 @@ fn str_escape_2() {
|
||||
#[test]
|
||||
fn str_escape_hex() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, r#"'\x61'"#),
|
||||
lex(Syntax::Es, r#"'\x61'"#),
|
||||
vec![Token::Str {
|
||||
value: "a".into(),
|
||||
has_escape: true,
|
||||
@ -291,7 +285,7 @@ fn str_escape_hex() {
|
||||
#[test]
|
||||
fn str_escape_octal() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, r#"'Hello\012World'"#),
|
||||
lex(Syntax::Es, r#"'Hello\012World'"#),
|
||||
vec![Token::Str {
|
||||
value: "Hello\nWorld".into(),
|
||||
has_escape: true,
|
||||
@ -304,7 +298,7 @@ fn str_escape_octal() {
|
||||
#[test]
|
||||
fn str_escape_unicode_long() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, r#"'\u{00000000034}'"#),
|
||||
lex(Syntax::Es, r#"'\u{00000000034}'"#),
|
||||
vec![Token::Str {
|
||||
value: "4".into(),
|
||||
has_escape: true,
|
||||
@ -317,7 +311,7 @@ fn str_escape_unicode_long() {
|
||||
#[test]
|
||||
fn regexp_unary_void() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, "void /test/"),
|
||||
lex(Syntax::Es, "void /test/"),
|
||||
vec![
|
||||
Void.span(0..4).lb(),
|
||||
Regex(
|
||||
@ -332,7 +326,7 @@ fn regexp_unary_void() {
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, "void (/test/)"),
|
||||
lex(Syntax::Es, "void (/test/)"),
|
||||
vec![
|
||||
Void.span(0..4).lb(),
|
||||
LParen.span(5..6),
|
||||
@ -353,7 +347,7 @@ fn regexp_unary_void() {
|
||||
#[test]
|
||||
fn non_regexp_unary_plus() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, "+{} / 1"),
|
||||
lex(Syntax::Es, "+{} / 1"),
|
||||
vec![
|
||||
tok!('+').span(0..1).lb(),
|
||||
tok!('{').span(1..2),
|
||||
@ -370,7 +364,7 @@ fn non_regexp_unary_plus() {
|
||||
fn paren_semi() {
|
||||
assert_eq!(
|
||||
vec![LParen.span(0).lb(), RParen.span(1), Semi.span(2)],
|
||||
lex(Syntax::Es2019, "();")
|
||||
lex(Syntax::Es, "();")
|
||||
);
|
||||
}
|
||||
|
||||
@ -384,7 +378,7 @@ fn ident_paren() {
|
||||
RParen.span(4),
|
||||
Semi.span(5),
|
||||
],
|
||||
lex(Syntax::Es2019, "a(bc);")
|
||||
lex(Syntax::Es, "a(bc);")
|
||||
);
|
||||
}
|
||||
|
||||
@ -392,14 +386,14 @@ fn ident_paren() {
|
||||
fn read_word() {
|
||||
assert_eq!(
|
||||
vec!["a".span(0).lb(), "b".span(2), "c".span(4)],
|
||||
lex(Syntax::Es2019, "a b c"),
|
||||
lex(Syntax::Es, "a b c"),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_regex() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, "x = /42/i"),
|
||||
lex(Syntax::Es, "x = /42/i"),
|
||||
vec![
|
||||
"x".span(0).lb(),
|
||||
Assign.span(2),
|
||||
@ -420,7 +414,7 @@ fn simple_regex() {
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, "/42/"),
|
||||
lex(Syntax::Es, "/42/"),
|
||||
vec![Regex(
|
||||
Str {
|
||||
span: sp(1..3),
|
||||
@ -438,12 +432,12 @@ fn simple_regex() {
|
||||
fn complex_regex() {
|
||||
assert_eq_ignore_span!(
|
||||
vec![
|
||||
Word(Ident("f".into())),
|
||||
Word(Word::Ident("f".into())),
|
||||
LParen,
|
||||
RParen,
|
||||
Semi,
|
||||
Word(Keyword(Function)),
|
||||
Word(Ident("foo".into())),
|
||||
Word(Word::Keyword(Function)),
|
||||
Word(Word::Ident("foo".into())),
|
||||
LParen,
|
||||
RParen,
|
||||
LBrace,
|
||||
@ -461,7 +455,7 @@ fn complex_regex() {
|
||||
}),
|
||||
),
|
||||
],
|
||||
lex_tokens(Syntax::Es2019, "f(); function foo() {} /42/i")
|
||||
lex_tokens(Syntax::Es, "f(); function foo() {} /42/i")
|
||||
)
|
||||
}
|
||||
|
||||
@ -469,7 +463,7 @@ fn complex_regex() {
|
||||
fn simple_div() {
|
||||
assert_eq!(
|
||||
vec!["a".span(0).lb(), Div.span(2), "b".span(4)],
|
||||
lex(Syntax::Es2019, "a / b")
|
||||
lex(Syntax::Es, "a / b")
|
||||
);
|
||||
}
|
||||
|
||||
@ -477,20 +471,20 @@ fn simple_div() {
|
||||
fn complex_divide() {
|
||||
assert_eq!(
|
||||
vec![
|
||||
Word(Ident("x".into())),
|
||||
Word(Word::Ident("x".into())),
|
||||
AssignOp(Assign),
|
||||
Word(Keyword(Function)),
|
||||
Word(Ident("foo".into())),
|
||||
Word(Word::Keyword(Function)),
|
||||
Word(Word::Ident("foo".into())),
|
||||
LParen,
|
||||
RParen,
|
||||
LBrace,
|
||||
RBrace,
|
||||
BinOp(Div),
|
||||
Word(Ident("a".into())),
|
||||
Word(Word::Ident("a".into())),
|
||||
BinOp(Div),
|
||||
Word(Ident("i".into())),
|
||||
Word(Word::Ident("i".into())),
|
||||
],
|
||||
lex_tokens(Syntax::Es2019, "x = function foo() {} /a/i"),
|
||||
lex_tokens(Syntax::Es, "x = function foo() {} /a/i"),
|
||||
"/ should be parsed as div operator"
|
||||
)
|
||||
}
|
||||
@ -500,22 +494,22 @@ fn complex_divide() {
|
||||
#[test]
|
||||
fn spec_001() {
|
||||
let expected = vec![
|
||||
Word(Ident("a".into())),
|
||||
Word(Word::Ident("a".into())),
|
||||
AssignOp(Assign),
|
||||
Word(Ident("b".into())),
|
||||
Word(Word::Ident("b".into())),
|
||||
BinOp(Div),
|
||||
Word(Ident("hi".into())),
|
||||
Word(Word::Ident("hi".into())),
|
||||
BinOp(Div),
|
||||
Word(Ident("g".into())),
|
||||
Word(Word::Ident("g".into())),
|
||||
Dot,
|
||||
Word(Ident("exec".into())),
|
||||
Word(Word::Ident("exec".into())),
|
||||
LParen,
|
||||
Word(Ident("c".into())),
|
||||
Word(Word::Ident("c".into())),
|
||||
RParen,
|
||||
Dot,
|
||||
Word(Ident("map".into())),
|
||||
Word(Word::Ident("map".into())),
|
||||
LParen,
|
||||
Word(Ident("d".into())),
|
||||
Word(Word::Ident("d".into())),
|
||||
RParen,
|
||||
Semi,
|
||||
];
|
||||
@ -523,14 +517,14 @@ fn spec_001() {
|
||||
assert_eq!(
|
||||
expected,
|
||||
lex_tokens(
|
||||
Syntax::Es2019,
|
||||
Syntax::Es,
|
||||
"a = b
|
||||
/hi/g.exec(c).map(d);"
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
expected,
|
||||
lex_tokens(Syntax::Es2019, "a = b / hi / g.exec(c).map(d);")
|
||||
lex_tokens(Syntax::Es, "a = b / hi / g.exec(c).map(d);")
|
||||
);
|
||||
}
|
||||
|
||||
@ -539,7 +533,7 @@ fn spec_001() {
|
||||
#[test]
|
||||
fn after_if() {
|
||||
assert_eq!(
|
||||
lex(Syntax::Es2019, "if(x){} /y/.test(z)"),
|
||||
lex(Syntax::Es, "if(x){} /y/.test(z)"),
|
||||
vec![
|
||||
Keyword::If.span(0..2).lb(),
|
||||
LParen.span(2),
|
||||
@ -567,7 +561,7 @@ fn after_if() {
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
assert_eq!(lex(Syntax::Es2019, ""), vec![]);
|
||||
assert_eq!(lex(Syntax::Es, ""), vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -584,7 +578,7 @@ fn invalid_number_failure() {
|
||||
// BlockComment(" hello world ".into()).span(0..17),
|
||||
// Regex("42".into(), "".into()).span(17..21),
|
||||
// ],
|
||||
// lex(Syntax::Es2019, "/* hello world */ /42/")
|
||||
// lex(Syntax::Es, "/* hello world */ /42/")
|
||||
// )
|
||||
// }
|
||||
|
||||
@ -599,7 +593,7 @@ fn invalid_number_failure() {
|
||||
// 42.span(13..15),
|
||||
// LineComment(" the Ultimate".into()).span(17..32),
|
||||
// ],
|
||||
// lex(Syntax::Es2019, "var answer = 42 // the Ultimate"),
|
||||
// lex(Syntax::Es, "var answer = 42 // the Ultimate"),
|
||||
// )
|
||||
// }
|
||||
|
||||
@ -620,7 +614,7 @@ fn migrated_0002() {
|
||||
.span(9..13),
|
||||
RParen.span(13),
|
||||
],
|
||||
lex(Syntax::Es2019, "tokenize(/42/)")
|
||||
lex(Syntax::Es, "tokenize(/42/)")
|
||||
)
|
||||
}
|
||||
|
||||
@ -635,7 +629,7 @@ fn migrated_0003() {
|
||||
42.span(9..11),
|
||||
Div.span(11),
|
||||
],
|
||||
lex(Syntax::Es2019, "(false) /42/"),
|
||||
lex(Syntax::Es, "(false) /42/"),
|
||||
)
|
||||
}
|
||||
|
||||
@ -659,7 +653,7 @@ fn migrated_0004() {
|
||||
)
|
||||
.span(15..19),
|
||||
],
|
||||
lex(Syntax::Es2019, "function f(){} /42/")
|
||||
lex(Syntax::Es, "function f(){} /42/")
|
||||
);
|
||||
}
|
||||
|
||||
@ -677,7 +671,7 @@ fn migrated_0004() {
|
||||
// Div.span(13),
|
||||
// 42.span(14..16),
|
||||
// ],
|
||||
// lex(Syntax::Es2019, "function (){} /42")
|
||||
// lex(Syntax::Es, "function (){} /42")
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -686,7 +680,7 @@ fn migrated_0006() {
|
||||
// This test seems wrong.
|
||||
// assert_eq!(
|
||||
// vec![LBrace.span(0).lb(), RBrace.span(1), Div.span(3), 42.span(4..6)],
|
||||
// lex(Syntax::Es2019, "{} /42")
|
||||
// lex(Syntax::Es, "{} /42")
|
||||
// )
|
||||
|
||||
assert_eq!(
|
||||
@ -703,7 +697,7 @@ fn migrated_0006() {
|
||||
)
|
||||
.span(3..7),
|
||||
],
|
||||
lex(Syntax::Es2019, "{} /42/")
|
||||
lex(Syntax::Es, "{} /42/")
|
||||
)
|
||||
}
|
||||
|
||||
@ -714,21 +708,21 @@ fn str_lit() {
|
||||
value: "abcde".into(),
|
||||
has_escape: false,
|
||||
}],
|
||||
lex_tokens(Syntax::Es2019, "'abcde'")
|
||||
lex_tokens(Syntax::Es, "'abcde'")
|
||||
);
|
||||
assert_eq_ignore_span!(
|
||||
vec![Token::Str {
|
||||
value: "abc".into(),
|
||||
has_escape: true,
|
||||
}],
|
||||
lex_tokens(Syntax::Es2019, "'\\\nabc'")
|
||||
lex_tokens(Syntax::Es, "'\\\nabc'")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_empty() {
|
||||
assert_eq!(
|
||||
lex_tokens(Syntax::Es2019, r#"``"#),
|
||||
lex_tokens(Syntax::Es, r#"``"#),
|
||||
vec![
|
||||
tok!('`'),
|
||||
Template {
|
||||
@ -744,7 +738,7 @@ fn tpl_empty() {
|
||||
#[test]
|
||||
fn tpl() {
|
||||
assert_eq!(
|
||||
lex_tokens(Syntax::Es2019, r#"`${a}`"#),
|
||||
lex_tokens(Syntax::Es, r#"`${a}`"#),
|
||||
vec![
|
||||
tok!('`'),
|
||||
Template {
|
||||
@ -753,7 +747,7 @@ fn tpl() {
|
||||
has_escape: false
|
||||
},
|
||||
tok!("${"),
|
||||
Word(Ident("a".into())),
|
||||
Word(Word::Ident("a".into())),
|
||||
tok!('}'),
|
||||
Template {
|
||||
raw: "".into(),
|
||||
@ -769,12 +763,12 @@ fn tpl() {
|
||||
fn comment() {
|
||||
assert_eq!(
|
||||
lex(
|
||||
Syntax::Es2019,
|
||||
Syntax::Es,
|
||||
"// foo
|
||||
a"
|
||||
),
|
||||
vec![TokenAndSpan {
|
||||
token: Word(Ident("a".into())),
|
||||
token: Word(Word::Ident("a".into())),
|
||||
span: sp(7..8),
|
||||
// first line
|
||||
had_line_break: true
|
||||
@ -786,13 +780,13 @@ a"
|
||||
fn comment_2() {
|
||||
assert_eq!(
|
||||
lex(
|
||||
Syntax::Es2019,
|
||||
Syntax::Es,
|
||||
"// foo
|
||||
// bar
|
||||
a"
|
||||
),
|
||||
vec![TokenAndSpan {
|
||||
token: Word(Ident("a".into())),
|
||||
token: Word(Word::Ident("a".into())),
|
||||
span: sp(14..15),
|
||||
// first line
|
||||
had_line_break: true
|
||||
@ -875,7 +869,7 @@ fn lex_colors_js(b: &mut Bencher) {
|
||||
b.bytes = include_str!("../../colors.js").len() as _;
|
||||
|
||||
b.iter(|| {
|
||||
let _ = with_lexer(Syntax::Es2019, include_str!("../../colors.js"), |lexer| {
|
||||
let _ = with_lexer(Syntax::Es, include_str!("../../colors.js"), |lexer| {
|
||||
for _ in lexer {}
|
||||
Ok(())
|
||||
});
|
||||
|
@ -35,10 +35,7 @@
|
||||
//! let handler =
|
||||
//! Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone()));
|
||||
//!
|
||||
//! let session = Session {
|
||||
//! handler: &handler,
|
||||
//! cfg: Default::default(),
|
||||
//! };
|
||||
//! let session = Session { handler: &handler };
|
||||
//!
|
||||
//! // Real usage
|
||||
//! // let fm = cm
|
||||
@ -50,9 +47,15 @@
|
||||
//! "function foo() {}".into(),
|
||||
//! );
|
||||
//!
|
||||
//! let mut parser = Parser::new(session, Syntax::Es2019, SourceFileInput::from(&*fm));
|
||||
//! let mut parser = Parser::new(session, Syntax::Es, SourceFileInput::from(&*fm));
|
||||
//!
|
||||
//! let _module = parser.parse_module().expect("failed to parser module");
|
||||
//! let _module = parser
|
||||
//! .parse_module()
|
||||
//! .map_err(|e| {
|
||||
//! e.emit();
|
||||
//! ()
|
||||
//! })
|
||||
//! .expect("failed to parser module");
|
||||
//! });
|
||||
//! }
|
||||
//! ```
|
||||
@ -109,16 +112,24 @@ mod parser;
|
||||
mod token;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[serde(tag = "syntax")]
|
||||
pub enum Syntax {
|
||||
Es2019,
|
||||
#[serde = "esnext"]
|
||||
EsNext(EsNextConfig),
|
||||
/// Standard
|
||||
#[serde = "es"]
|
||||
Es,
|
||||
#[serde = "jsx"]
|
||||
Jsx,
|
||||
#[serde = "typescript"]
|
||||
Typescript,
|
||||
#[serde = "tsx"]
|
||||
Tsx,
|
||||
}
|
||||
|
||||
impl Default for Syntax{
|
||||
fn default()->Self{
|
||||
Syntax::Es2019
|
||||
impl Default for Syntax {
|
||||
fn default() -> Self {
|
||||
Syntax::Es
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,20 +141,107 @@ impl Syntax {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fn_bind(self) -> bool {
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig { fn_bind: true, .. }) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_sep(self) -> bool {
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig { num_sep: true, .. }) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decorators(self) -> bool {
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig {
|
||||
decorators: true, ..
|
||||
})
|
||||
| Syntax::Typescript
|
||||
| Syntax::Tsx => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn class_private_methods(self) -> bool {
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig {
|
||||
class_private_methods: true,
|
||||
..
|
||||
}) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn class_private_props(self) -> bool {
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig {
|
||||
class_private_props: true,
|
||||
..
|
||||
}) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn class_props(self) -> bool {
|
||||
if self.typescript() {
|
||||
return true;
|
||||
}
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig {
|
||||
class_props: true, ..
|
||||
}) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decorators_before_export(self) -> bool {
|
||||
match self {
|
||||
Syntax::EsNext(EsNextConfig {
|
||||
decorators_before_export: true,
|
||||
..
|
||||
}) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Should we pare typescript?
|
||||
pub fn typescript(self) -> bool {
|
||||
match self {
|
||||
Syntax::Typescript | Syntax::Tsx => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct Config {
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct EsNextConfig {
|
||||
/// Support numeric separator.
|
||||
pub num_sep: bool,
|
||||
|
||||
pub class_private_props: bool,
|
||||
pub class_private_methods: bool,
|
||||
pub class_props: bool,
|
||||
|
||||
/// Support function bind expression.
|
||||
pub fn_bind: bool,
|
||||
|
||||
/// Enable decorators.
|
||||
pub decorators: bool,
|
||||
|
||||
/// babel: `decorators.decoratorsBeforeExport`
|
||||
///
|
||||
/// Effective only if `decorator` is true.
|
||||
pub decorators_before_export: bool,
|
||||
}
|
||||
|
||||
/// Syntatic context.
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
struct Context {
|
||||
pub(crate) struct Context {
|
||||
/// Is in module code?
|
||||
module: bool,
|
||||
strict: bool,
|
||||
@ -155,16 +253,24 @@ struct Context {
|
||||
/// keyword.
|
||||
in_generator: bool,
|
||||
|
||||
in_type: bool,
|
||||
/// Typescript extension.
|
||||
in_declare: bool,
|
||||
|
||||
in_function: bool,
|
||||
|
||||
in_parameters: bool,
|
||||
|
||||
in_method: bool,
|
||||
in_class_prop: bool,
|
||||
|
||||
in_property_name: bool,
|
||||
|
||||
in_forced_jsx_context: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Session<'a> {
|
||||
pub cfg: Config,
|
||||
pub handler: &'a Handler,
|
||||
}
|
||||
|
||||
@ -175,15 +281,9 @@ where
|
||||
{
|
||||
use swc_common::FileName;
|
||||
|
||||
::testing::run_test(|cm, handler| {
|
||||
::testing::run_test(true, |cm, handler| {
|
||||
let fm = cm.new_source_file(FileName::Real("testing".into()), src.into());
|
||||
|
||||
f(
|
||||
Session {
|
||||
handler: &handler,
|
||||
cfg: Default::default(),
|
||||
},
|
||||
(&*fm).into(),
|
||||
)
|
||||
f(Session { handler: &handler }, (&*fm).into())
|
||||
})
|
||||
}
|
||||
|
@ -1,226 +1,336 @@
|
||||
macro_rules! tok {
|
||||
('`') => {
|
||||
Token::BackQuote
|
||||
crate::token::Token::BackQuote
|
||||
};
|
||||
// (';') => { Token::Semi };
|
||||
('@') => {
|
||||
crate::token::Token::At
|
||||
};
|
||||
('#') => {
|
||||
crate::token::Token::Hash
|
||||
};
|
||||
|
||||
('&') => {
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::BitAnd)
|
||||
};
|
||||
('+') => {
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Add)
|
||||
};
|
||||
('-') => {
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Sub)
|
||||
};
|
||||
('~') => {
|
||||
crate::token::Token::Tilde
|
||||
};
|
||||
('!') => {
|
||||
crate::token::Token::Bang
|
||||
};
|
||||
|
||||
('|') => {
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::BitOr)
|
||||
};
|
||||
|
||||
(',') => {
|
||||
Token::Comma
|
||||
crate::token::Token::Comma
|
||||
};
|
||||
('?') => {
|
||||
Token::QuestionMark
|
||||
crate::token::Token::QuestionMark
|
||||
};
|
||||
(':') => {
|
||||
Token::Colon
|
||||
crate::token::Token::Colon
|
||||
};
|
||||
("::") => {
|
||||
Token::ColonColon
|
||||
crate::token::Token::ColonColon
|
||||
};
|
||||
('.') => {
|
||||
Token::Dot
|
||||
crate::token::Token::Dot
|
||||
};
|
||||
("=>") => {
|
||||
Token::Arrow
|
||||
crate::token::Token::Arrow
|
||||
};
|
||||
("...") => {
|
||||
Token::DotDotDot
|
||||
crate::token::Token::DotDotDot
|
||||
};
|
||||
("${") => {
|
||||
Token::DollarLBrace
|
||||
crate::token::Token::DollarLBrace
|
||||
};
|
||||
|
||||
('+') => {
|
||||
Token::BinOp(Add)
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Add)
|
||||
};
|
||||
('-') => {
|
||||
Token::BinOp(Sub)
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Sub)
|
||||
};
|
||||
('*') => {
|
||||
Token::BinOp(Mul)
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Mul)
|
||||
};
|
||||
('/') => {
|
||||
Token::BinOp(Div)
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Div)
|
||||
};
|
||||
("/=") => {
|
||||
Token::AssignOp(DivAssign)
|
||||
crate::token::Token::AssignOp(DivAssign)
|
||||
};
|
||||
('%') => {
|
||||
Token::BinOp(Mod)
|
||||
};
|
||||
('!') => {
|
||||
Token::Bang
|
||||
crate::token::Token::BinOp(Mod)
|
||||
};
|
||||
('~') => {
|
||||
Token::Tilde
|
||||
crate::token::Token::Tilde
|
||||
};
|
||||
('<') => {
|
||||
Token::BinOp(Lt)
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Lt)
|
||||
};
|
||||
('>') => {
|
||||
Token::BinOp(Gt)
|
||||
crate::token::Token::BinOp(crate::token::BinOpToken::Gt)
|
||||
};
|
||||
|
||||
("++") => {
|
||||
Token::PlusPlus
|
||||
crate::token::Token::PlusPlus
|
||||
};
|
||||
("--") => {
|
||||
Token::MinusMinus
|
||||
crate::token::Token::MinusMinus
|
||||
};
|
||||
|
||||
('=') => {
|
||||
Token::AssignOp(Assign)
|
||||
crate::token::Token::AssignOp(crate::token::AssignOpToken::Assign)
|
||||
};
|
||||
|
||||
('(') => {
|
||||
Token::LParen
|
||||
crate::token::Token::LParen
|
||||
};
|
||||
(')') => {
|
||||
Token::RParen
|
||||
crate::token::Token::RParen
|
||||
};
|
||||
('{') => {
|
||||
Token::LBrace
|
||||
crate::token::Token::LBrace
|
||||
};
|
||||
('}') => {
|
||||
Token::RBrace
|
||||
crate::token::Token::RBrace
|
||||
};
|
||||
('[') => {
|
||||
Token::LBracket
|
||||
crate::token::Token::LBracket
|
||||
};
|
||||
(']') => {
|
||||
Token::RBracket
|
||||
crate::token::Token::RBracket
|
||||
};
|
||||
|
||||
("async") => {
|
||||
Token::Word(Word::Ident(js_word!("async")))
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("async")))
|
||||
};
|
||||
("as") => {
|
||||
Token::Word(Word::Ident(js_word!("as")))
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("as")))
|
||||
};
|
||||
("await") => {
|
||||
Token::Word(Keyword(Await))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Await))
|
||||
};
|
||||
("break") => {
|
||||
Token::Word(Keyword(Break))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Break))
|
||||
};
|
||||
("case") => {
|
||||
Token::Word(Keyword(Case))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Case))
|
||||
};
|
||||
("catch") => {
|
||||
Token::Word(Keyword(Catch))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Catch))
|
||||
};
|
||||
("class") => {
|
||||
Token::Word(Keyword(Class))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Class))
|
||||
};
|
||||
("const") => {
|
||||
Token::Word(Keyword(Const))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Const))
|
||||
};
|
||||
("continue") => {
|
||||
Token::Word(Keyword(Continue))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Continue))
|
||||
};
|
||||
("debugger") => {
|
||||
Token::Word(Keyword(Debugger))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Debugger))
|
||||
};
|
||||
("default") => {
|
||||
Token::Word(Keyword(Default_))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Default_))
|
||||
};
|
||||
("delete") => {
|
||||
Token::Word(Keyword(Delete))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Delete))
|
||||
};
|
||||
("do") => {
|
||||
Token::Word(Keyword(Do))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Do))
|
||||
};
|
||||
("else") => {
|
||||
Token::Word(Keyword(Else))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Else))
|
||||
};
|
||||
("export") => {
|
||||
Token::Word(Keyword(Export))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Export))
|
||||
};
|
||||
("extends") => {
|
||||
Token::Word(Keyword(Extends))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Extends))
|
||||
};
|
||||
("false") => {
|
||||
Token::Word(False)
|
||||
crate::token::Token::Word(crate::token::Word::False)
|
||||
};
|
||||
("finally") => {
|
||||
Token::Word(Keyword(Finally))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Finally))
|
||||
};
|
||||
("for") => {
|
||||
Token::Word(Keyword(For))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::For))
|
||||
};
|
||||
("from") => {
|
||||
Token::Word(Word::Ident(js_word!("from")))
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("from")))
|
||||
};
|
||||
("function") => {
|
||||
Token::Word(Keyword(Function))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Function))
|
||||
};
|
||||
("if") => {
|
||||
Token::Word(Keyword(If))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::If))
|
||||
};
|
||||
("in") => {
|
||||
Token::Word(Keyword(In))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::In))
|
||||
};
|
||||
("import") => {
|
||||
Token::Word(Keyword(Import))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Import))
|
||||
};
|
||||
("let") => {
|
||||
Token::Word(Keyword(Let))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Let))
|
||||
};
|
||||
("new") => {
|
||||
Token::Word(Keyword(New))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::New))
|
||||
};
|
||||
("null") => {
|
||||
Token::Word(Null)
|
||||
crate::token::Token::Word(crate::token::Word::Null)
|
||||
};
|
||||
("of") => {
|
||||
Token::Word(Ident(js_word!("of")))
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("of")))
|
||||
};
|
||||
("return") => {
|
||||
Token::Word(Keyword(Return))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Return))
|
||||
};
|
||||
("super") => {
|
||||
Token::Word(Keyword(Super))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Super))
|
||||
};
|
||||
("static") => {
|
||||
Token::Word(Word::Ident(js_word!("static")))
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("static")))
|
||||
};
|
||||
("switch") => {
|
||||
Token::Word(Keyword(Switch))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Switch))
|
||||
};
|
||||
("target") => {
|
||||
Token::Word(Word::Ident(js_word!("target")))
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("target")))
|
||||
};
|
||||
("this") => {
|
||||
Token::Word(Keyword(This))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::This))
|
||||
};
|
||||
("throw") => {
|
||||
Token::Word(Keyword(Throw))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Throw))
|
||||
};
|
||||
("true") => {
|
||||
Token::Word(True)
|
||||
crate::token::Token::Word(crate::token::Word::True)
|
||||
};
|
||||
("try") => {
|
||||
Token::Word(Keyword(Try))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Try))
|
||||
};
|
||||
("typeof") => {
|
||||
Token::Word(Keyword(TypeOf))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::TypeOf))
|
||||
};
|
||||
("var") => {
|
||||
Token::Word(Keyword(Var))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Var))
|
||||
};
|
||||
("void") => {
|
||||
Token::Word(Keyword(Void))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Void))
|
||||
};
|
||||
("while") => {
|
||||
Token::Word(Keyword(While))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::While))
|
||||
};
|
||||
("with") => {
|
||||
Token::Word(Keyword(With))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::With))
|
||||
};
|
||||
("yield") => {
|
||||
Token::Word(Keyword(Yield))
|
||||
crate::token::Token::Word(crate::token::Word::Keyword(crate::token::Keyword::Yield))
|
||||
};
|
||||
|
||||
// ----------
|
||||
// JSX
|
||||
// ----------
|
||||
(JSXTagStart) => {
|
||||
crate::token::Token::JSXTagStart
|
||||
};
|
||||
|
||||
(JSXTagEnd) => {
|
||||
Token::JSXTagEnd
|
||||
crate::token::Token::JSXTagEnd
|
||||
};
|
||||
|
||||
// ----------
|
||||
// Typescript
|
||||
// ----------
|
||||
("implements") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("implements")))
|
||||
};
|
||||
("is") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("is")))
|
||||
};
|
||||
("new") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("new")))
|
||||
};
|
||||
("keyof") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("keyof")))
|
||||
};
|
||||
("unique") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("unique")))
|
||||
};
|
||||
("object") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("object")))
|
||||
};
|
||||
("global") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("global")))
|
||||
};
|
||||
("require") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("require")))
|
||||
};
|
||||
("enum") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("enum")))
|
||||
};
|
||||
("readonly") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("readonly")))
|
||||
};
|
||||
("as") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("as")))
|
||||
};
|
||||
("namespace") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("namespace")))
|
||||
};
|
||||
("abstract") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("abstract")))
|
||||
};
|
||||
("infer") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("infer")))
|
||||
};
|
||||
("any") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("any")))
|
||||
};
|
||||
("boolean") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("boolean")))
|
||||
};
|
||||
("bigint") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("bigint")))
|
||||
};
|
||||
("never") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("never")))
|
||||
};
|
||||
("number") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("number")))
|
||||
};
|
||||
("string") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("string")))
|
||||
};
|
||||
("symbol") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("symbol")))
|
||||
};
|
||||
("unknown") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("unknown")))
|
||||
};
|
||||
("require") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("require")))
|
||||
};
|
||||
("interface") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("interface")))
|
||||
};
|
||||
("declare") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(js_word!("declare")))
|
||||
};
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
use super::{pat::PatType, util::ExprExt, *};
|
||||
use crate::{lexer::TokenContext, token::AssignOpToken};
|
||||
use either::Either;
|
||||
use swc_common::Spanned;
|
||||
use swc_common::{ast_node, Spanned};
|
||||
|
||||
mod ops;
|
||||
#[cfg(test)]
|
||||
@ -28,16 +29,71 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
///`parseMaybeAssign` (overrided)
|
||||
pub(super) fn parse_assignment_expr(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
if self.input.syntax().typescript() {
|
||||
// Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid
|
||||
// syntax.
|
||||
|
||||
if is!(JSXTagStart) {
|
||||
let cur_context = self.input.token_context().current();
|
||||
assert_eq!(cur_context, Some(TokenContext::JSXOpeningTag));
|
||||
// Only time j_oTag is pushed is right after j_expr.
|
||||
assert_eq!(
|
||||
self.input.token_context().0[self.input.token_context().len() - 2],
|
||||
TokenContext::JSXExpr
|
||||
);
|
||||
|
||||
let res = self.try_parse_ts(|p| p.parse_assignment_expr_base().map(Some));
|
||||
if let Some(res) = res {
|
||||
return Ok(res);
|
||||
} else {
|
||||
assert_eq!(
|
||||
self.input.token_context().current(),
|
||||
Some(TokenContext::JSXOpeningTag)
|
||||
);
|
||||
self.input.token_context_mut().pop();
|
||||
assert_eq!(
|
||||
self.input.token_context().current(),
|
||||
Some(TokenContext::JSXExpr)
|
||||
);
|
||||
self.input.token_context_mut().pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let res = self.try_parse_ts(|p| {
|
||||
let type_parameters = p.parse_ts_type_params()?;
|
||||
let mut arrow = p.parse_assignment_expr_base()?;
|
||||
match *arrow {
|
||||
Expr::Arrow(ArrowExpr {
|
||||
ref mut type_params,
|
||||
..
|
||||
}) => {
|
||||
*type_params = Some(type_parameters);
|
||||
}
|
||||
_ => unexpected!(),
|
||||
}
|
||||
Ok(Some(arrow))
|
||||
});
|
||||
if let Some(res) = res {
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
self.parse_assignment_expr_base()
|
||||
}
|
||||
|
||||
/// Parse an assignment expression. This includes applications of
|
||||
/// operators like `+=`.
|
||||
pub(super) fn parse_assignment_expr(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
///
|
||||
/// `parseMaybeAssign`
|
||||
fn parse_assignment_expr_base(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
if self.ctx().in_generator && is!("yield") {
|
||||
return self.parse_yield_expr();
|
||||
}
|
||||
|
||||
// TODO: Check if cur!(true) correct.
|
||||
self.state.potential_arrow_start = match *cur!(true)? {
|
||||
Word(Ident(..)) | tok!('(') | tok!("yield") => Some(cur_pos!()),
|
||||
Word(Word::Ident(..)) | tok!('(') | tok!("yield") => Some(cur_pos!()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -56,8 +112,8 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
|
||||
match cur!(false) {
|
||||
Ok(&AssignOp(op)) => {
|
||||
let left = if op == Assign {
|
||||
Ok(&Token::AssignOp(op)) => {
|
||||
let left = if op == AssignOpToken::Assign {
|
||||
self.reparse_expr_as_pat(PatType::AssignPat, cond)
|
||||
.map(Box::new)
|
||||
.map(PatOrExpr::Pat)?
|
||||
@ -117,23 +173,33 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let can_be_arrow = self
|
||||
.state
|
||||
.potential_arrow_start
|
||||
.map(|s| s == cur_pos!())
|
||||
.map(|s| s == start)
|
||||
.unwrap_or(false);
|
||||
|
||||
if eat!("this") {
|
||||
return Ok(box Expr::This(ThisExpr { span: span!(start) }));
|
||||
}
|
||||
|
||||
// Handle async function expression
|
||||
if is!("async") {
|
||||
if peeked_is!("function") && !self.input.has_linebreak_between_cur_and_peeked() {
|
||||
// handle `async function` expression
|
||||
return self.parse_async_fn_expr();
|
||||
}
|
||||
|
||||
if can_be_arrow && self.input.syntax().typescript() && peeked_is!('<') {
|
||||
// try parsing `async<T>() => {}`
|
||||
if let Some(res) = self.try_parse_ts(|p| {
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!("async");
|
||||
p.try_parse_ts_generic_async_arrow_fn(start)
|
||||
}) {
|
||||
return Ok(box Expr::Arrow(res));
|
||||
}
|
||||
}
|
||||
|
||||
if can_be_arrow && peeked_is!('(') {
|
||||
let start = cur_pos!();
|
||||
expect!("async");
|
||||
let async_span = span!(start);
|
||||
let async_span = self.input.prev_span();
|
||||
return self.parse_paren_expr_or_arrow_fn(can_be_arrow, Some(async_span));
|
||||
}
|
||||
}
|
||||
@ -157,7 +223,11 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// Literals
|
||||
if {
|
||||
match *cur!(false)? {
|
||||
tok!("null") | tok!("true") | tok!("false") | Num(..) | Token::Str { .. } => true,
|
||||
tok!("null")
|
||||
| tok!("true")
|
||||
| tok!("false")
|
||||
| Token::Num(..)
|
||||
| Token::Str { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
} {
|
||||
@ -167,12 +237,12 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// Regexp
|
||||
if {
|
||||
match *cur!(false)? {
|
||||
Regex(..) => true,
|
||||
Token::Regex(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
} {
|
||||
match bump!() {
|
||||
Regex(exp, flags) => {
|
||||
Token::Regex(exp, flags) => {
|
||||
return Ok(box Expr::Lit(Lit::Regex(Regex {
|
||||
span: span!(start),
|
||||
exp,
|
||||
@ -185,17 +255,16 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
if is!('`') {
|
||||
// parse template literal
|
||||
return Ok(box Expr::Tpl(self.parse_tpl_lit(None)?));
|
||||
return Ok(box Expr::Tpl(self.parse_tpl()?));
|
||||
}
|
||||
|
||||
if is!('(') {
|
||||
return self.parse_paren_expr_or_arrow_fn(can_be_arrow, None);
|
||||
}
|
||||
|
||||
if is!("let") || is!(IdentRef) {
|
||||
if is!("let") || (self.input.syntax().typescript() && is!(IdentName)) || is!(IdentRef) {
|
||||
// TODO: Handle [Yield, Await]
|
||||
let id = self.parse_ident_ref()?;
|
||||
|
||||
let id = self.parse_ident_name()?;
|
||||
if can_be_arrow && id.sym == js_word!("async") && is!(BindingIdent) {
|
||||
// async a => body
|
||||
let arg = self.parse_binding_ident().map(Pat::from)?;
|
||||
@ -208,6 +277,8 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
params,
|
||||
is_async: true,
|
||||
is_generator: false,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
}));
|
||||
} else if can_be_arrow && !self.input.had_line_break_before_cur() && eat!("=>") {
|
||||
let params = vec![id.into()];
|
||||
@ -219,6 +290,10 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
params,
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
// TODO
|
||||
return_type: None,
|
||||
// TODO
|
||||
type_params: None,
|
||||
}));
|
||||
} else {
|
||||
return Ok(box Expr::Ident(id));
|
||||
@ -269,14 +344,8 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let start_of_target = cur_pos!();
|
||||
if eat!("target") {
|
||||
return Ok(box Expr::MetaProp(MetaPropExpr {
|
||||
meta: Ident {
|
||||
span: span_of_new,
|
||||
sym: js_word!("new"),
|
||||
},
|
||||
prop: Ident {
|
||||
span: span!(start_of_target),
|
||||
sym: js_word!("target"),
|
||||
},
|
||||
meta: Ident::new(js_word!("new"), span_of_new),
|
||||
prop: Ident::new(js_word!("target"), span!(start_of_target)),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -287,6 +356,18 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let callee = self.parse_member_expr_or_new_expr(is_new_expr)?;
|
||||
return_if_arrow!(callee);
|
||||
|
||||
let type_args = if self.input.syntax().typescript() && is!('<') {
|
||||
self.try_parse_ts(|p| {
|
||||
let args = p.parse_ts_type_args()?;
|
||||
if !is!('(') {
|
||||
unexpected!()
|
||||
}
|
||||
Ok(Some(args))
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if !is_new_expr || is!('(') {
|
||||
// Parsed with 'MemberExpression' production.
|
||||
let args = self.parse_args().map(Some)?;
|
||||
@ -295,6 +376,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
callee,
|
||||
args,
|
||||
type_args,
|
||||
}));
|
||||
|
||||
// We should parse subscripts for MemberExpression.
|
||||
@ -308,6 +390,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
callee,
|
||||
args: None,
|
||||
type_args,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -323,7 +406,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
/// Parse `NewExpresion`.
|
||||
/// This includes `MemberExpression`.
|
||||
fn parse_new_expr(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
pub(super) fn parse_new_expr(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
self.parse_member_expr_or_new_expr(true)
|
||||
}
|
||||
|
||||
@ -381,19 +464,33 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// But as all patterns of javascript is subset of
|
||||
// expressions, we can parse both as expression.
|
||||
|
||||
let expr_or_spreads = self.include_in_expr(true).parse_args_or_pats()?;
|
||||
let paren_items = self.include_in_expr(true).parse_args_or_pats()?;
|
||||
let has_pattern = paren_items.iter().any(|item| match item {
|
||||
PatOrExprOrSpread::Pat(..) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let return_type = if self.input.syntax().typescript() && is!(':') {
|
||||
let start = cur_pos!();
|
||||
Some(self.parse_ts_type_or_type_predicate_ann(&tok!(':'))?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// we parse arrow function at here, to handle it efficiently.
|
||||
if is!("=>") {
|
||||
if has_pattern || return_type.is_some() || is!("=>") {
|
||||
if self.input.had_line_break_before_cur() {
|
||||
syntax_error!(span!(start), SyntaxError::LineBreakBeforeArrow);
|
||||
}
|
||||
if !can_be_arrow {
|
||||
unexpected!();
|
||||
unexpected!()
|
||||
}
|
||||
assert_and_bump!("=>");
|
||||
expect!("=>");
|
||||
|
||||
let params = self.parse_exprs_as_params(expr_or_spreads)?;
|
||||
let params = self
|
||||
.parse_paren_items_as_params(paren_items)?
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
let body: BlockStmtOrExpr = self.parse_fn_body(async_span.is_some(), false)?;
|
||||
return Ok(box Expr::Arrow(ArrowExpr {
|
||||
@ -402,14 +499,27 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
is_generator: false,
|
||||
params,
|
||||
body,
|
||||
return_type,
|
||||
type_params: None,
|
||||
}));
|
||||
}
|
||||
|
||||
let expr_or_spreads = paren_items
|
||||
.into_iter()
|
||||
.map(|item| -> PResult<'a, _> {
|
||||
match item {
|
||||
PatOrExprOrSpread::ExprOrSpread(e) => Ok(e),
|
||||
_ => syntax_error!(item.span(), SyntaxError::InvalidExpr),
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
if let Some(async_span) = async_span {
|
||||
// It's a call expression
|
||||
return Ok(box Expr::Call(CallExpr {
|
||||
span: span!(start).with_lo(async_span.lo()),
|
||||
span: span!(async_span.lo()),
|
||||
callee: ExprOrSuper::Expr(box Expr::Ident(Ident::new("async".into(), async_span))),
|
||||
args: expr_or_spreads,
|
||||
type_args: None,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -468,13 +578,10 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_tpl_lit(&mut self, tag: Option<(Box<Expr>)>) -> PResult<'a, TplLit> {
|
||||
let start = cur_pos!();
|
||||
|
||||
assert_and_bump!('`');
|
||||
|
||||
let is_tagged = tag.is_some();
|
||||
|
||||
fn parse_tpl_elements(
|
||||
&mut self,
|
||||
is_tagged: bool,
|
||||
) -> PResult<'a, (Vec<Box<Expr>>, Vec<TplElement>)> {
|
||||
let mut exprs = vec![];
|
||||
|
||||
let cur_elem = self.parse_tpl_element(is_tagged)?;
|
||||
@ -490,13 +597,45 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
quasis.push(elem);
|
||||
}
|
||||
|
||||
Ok((exprs, quasis))
|
||||
}
|
||||
|
||||
fn parse_tagged_tpl(
|
||||
&mut self,
|
||||
tag: Box<Expr>,
|
||||
type_params: Option<TsTypeParamInstantiation>,
|
||||
) -> PResult<'a, TaggedTpl> {
|
||||
let start = cur_pos!();
|
||||
|
||||
assert_and_bump!('`');
|
||||
|
||||
let (exprs, quasis) = self.parse_tpl_elements(false)?;
|
||||
|
||||
expect!('`');
|
||||
|
||||
let span = span!(start);
|
||||
Ok(TplLit {
|
||||
Ok(TaggedTpl {
|
||||
span,
|
||||
tag,
|
||||
exprs,
|
||||
type_params,
|
||||
quasis,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_tpl(&mut self) -> PResult<'a, Tpl> {
|
||||
let start = cur_pos!();
|
||||
|
||||
assert_and_bump!('`');
|
||||
|
||||
let (exprs, quasis) = self.parse_tpl_elements(false)?;
|
||||
|
||||
expect!('`');
|
||||
|
||||
let span = span!(start);
|
||||
Ok(Tpl {
|
||||
span,
|
||||
exprs,
|
||||
quasis,
|
||||
})
|
||||
}
|
||||
@ -505,8 +644,8 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let start = cur_pos!();
|
||||
|
||||
let (raw, cooked) = match *cur!(true)? {
|
||||
Template { .. } => match bump!() {
|
||||
Template {
|
||||
Token::Template { .. } => match bump!() {
|
||||
Token::Template {
|
||||
raw,
|
||||
cooked,
|
||||
has_escape,
|
||||
@ -556,8 +695,92 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
no_call: bool,
|
||||
) -> PResult<'a, (Box<Expr>, bool)> {
|
||||
let _ = cur!(false);
|
||||
|
||||
let start = cur_pos!();
|
||||
|
||||
if self.input.syntax().typescript() {
|
||||
if !self.input.had_line_break_before_cur() && is!('!') {
|
||||
self.input.set_expr_allowed(false);
|
||||
assert_and_bump!('!');
|
||||
|
||||
let expr = match obj {
|
||||
ExprOrSuper::Super(..) => unimplemented!("super!"),
|
||||
ExprOrSuper::Expr(expr) => expr,
|
||||
};
|
||||
return Ok((
|
||||
box Expr::TsNonNull(TsNonNullExpr {
|
||||
span: span!(start),
|
||||
expr,
|
||||
}),
|
||||
true,
|
||||
));
|
||||
}
|
||||
|
||||
// TODO(kdy1): Remove this.
|
||||
let obj = obj.clone();
|
||||
if {
|
||||
match obj {
|
||||
ExprOrSuper::Expr(..) => true,
|
||||
// super() cannot be generic
|
||||
_ => false,
|
||||
}
|
||||
} && is!('<')
|
||||
{
|
||||
// tsTryParseAndCatch is expensive, so avoid if not necessary.
|
||||
// There are number of things we are going to "maybe" parse, like type arguments
|
||||
// on tagged template expressions. If any of them fail, walk it back and
|
||||
// continue.
|
||||
let result = self.try_parse_ts(|p| {
|
||||
if !no_call
|
||||
&& p.at_possible_async(match obj {
|
||||
ExprOrSuper::Expr(ref expr) => &*expr,
|
||||
_ => unreachable!(),
|
||||
})?
|
||||
{
|
||||
// Almost certainly this is a generic async function `async <T>() => ...
|
||||
// But it might be a call with a type argument `async<T>();`
|
||||
let async_arrow_fn = p.try_parse_ts_generic_async_arrow_fn(start)?;
|
||||
if let Some(async_arrow_fn) = async_arrow_fn {
|
||||
return Ok(Some((box Expr::Arrow(async_arrow_fn), true)));
|
||||
}
|
||||
}
|
||||
|
||||
let type_args = p.parse_ts_type_args()?;
|
||||
|
||||
if !no_call && is!('(') {
|
||||
// possibleAsync always false here, because we would have handled it
|
||||
// above. (won't be any undefined arguments)
|
||||
let args = p.parse_args()?;
|
||||
|
||||
return Ok(Some((
|
||||
box Expr::Call(CallExpr {
|
||||
span: span!(start),
|
||||
callee: obj,
|
||||
type_args: Some(type_args),
|
||||
args,
|
||||
}),
|
||||
true,
|
||||
)));
|
||||
} else if is!('`') {
|
||||
return p
|
||||
.parse_tagged_tpl(
|
||||
match obj {
|
||||
ExprOrSuper::Expr(obj) => obj,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Some(type_args),
|
||||
)
|
||||
.map(|expr| (box Expr::TaggedTpl(expr), true))
|
||||
.map(Some);
|
||||
} else {
|
||||
unexpected!()
|
||||
}
|
||||
});
|
||||
if let Some(result) = result {
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// member expression
|
||||
// $obj.name
|
||||
if eat!('.') {
|
||||
@ -596,6 +819,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
callee: obj,
|
||||
args,
|
||||
type_args: None,
|
||||
}),
|
||||
true,
|
||||
));
|
||||
@ -605,8 +829,8 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
ExprOrSuper::Expr(expr) => {
|
||||
// MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged]
|
||||
if is!('`') {
|
||||
let tpl = self.parse_tpl_lit(Some(expr))?;
|
||||
return Ok((box Expr::Tpl(tpl), true));
|
||||
let tpl = self.parse_tagged_tpl(expr, None)?;
|
||||
return Ok((box Expr::TaggedTpl(tpl), true));
|
||||
}
|
||||
|
||||
Ok((expr, false))
|
||||
@ -650,7 +874,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// jsx as the lt sign is not allowed in places that expect an expression
|
||||
|
||||
// FIXME:
|
||||
// this.finishToken(tt.jsxTagStart);
|
||||
// self.finishToken(tt.jsxTagStart);
|
||||
|
||||
return self.parse_jsx_element().map(into_expr);
|
||||
}
|
||||
@ -665,16 +889,33 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let callee = self.parse_new_expr()?;
|
||||
return_if_arrow!(callee);
|
||||
|
||||
let type_args = if self.input.syntax().typescript() && is!('<') {
|
||||
self.try_parse_ts(|p| {
|
||||
let type_args = p.parse_ts_type_args()?;
|
||||
if is!('(') {
|
||||
Ok(Some(type_args))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match *callee {
|
||||
// If this is parsed using 'NewExpression' rule, just return it.
|
||||
// Because it's not left-recursive.
|
||||
Expr::New(NewExpr { args: None, .. }) => {
|
||||
Expr::New(ne @ NewExpr { args: None, .. }) => {
|
||||
if type_args.is_some() {
|
||||
// This fails with `expected (`
|
||||
expect!('(');
|
||||
}
|
||||
assert_ne!(
|
||||
cur!(false).ok(),
|
||||
Some(&LParen),
|
||||
Some(&tok!('(')),
|
||||
"parse_new_expr() should eat paren if it exists"
|
||||
);
|
||||
return Ok(callee);
|
||||
return Ok(box Expr::New(NewExpr { type_args, ..ne }));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -685,15 +926,21 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// This is parsed using production MemberExpression,
|
||||
// which is left-recursive.
|
||||
let args = self.parse_args()?;
|
||||
|
||||
let call_expr = box Expr::Call(CallExpr {
|
||||
span: span!(start),
|
||||
|
||||
callee: ExprOrSuper::Expr(callee),
|
||||
args,
|
||||
type_args,
|
||||
});
|
||||
|
||||
return self.parse_subscripts(ExprOrSuper::Expr(call_expr), false);
|
||||
}
|
||||
if type_args.is_some() {
|
||||
// This fails
|
||||
expect!('(');
|
||||
}
|
||||
|
||||
// This is parsed using production 'NewExpression', which contains
|
||||
// 'MemberExpression'
|
||||
@ -703,11 +950,140 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
pub(super) fn parse_expr_or_pat(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
self.parse_expr()
|
||||
}
|
||||
pub(super) fn parse_args_or_pats(&mut self) -> PResult<'a, (Vec<ExprOrSpread>)> {
|
||||
self.parse_args()
|
||||
|
||||
pub(super) fn parse_args_or_pats(&mut self) -> PResult<'a, Vec<PatOrExprOrSpread>> {
|
||||
expect!('(');
|
||||
|
||||
let mut first = true;
|
||||
let mut items = vec![];
|
||||
let mut rest_span = None;
|
||||
|
||||
// TODO(kdy1): optimize (once we parsed a pattern, we can parse everything else
|
||||
// as a pattern instead of reparsing)
|
||||
|
||||
while !eof!() && !is!(')') {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
expect!(',');
|
||||
// Handle trailing comma.
|
||||
if is!(')') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let arg = {
|
||||
if self.input.syntax().typescript()
|
||||
&& (is!(IdentRef) || (is!("...") && peeked_is!(IdentRef)))
|
||||
{
|
||||
let spread = if eat!("...") {
|
||||
Some(self.input.prev_span())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// At here, we use parse_bin_expr() instead of parse_assignment_expr()
|
||||
// because `x?: number` should not be parsed as a conditional expression
|
||||
let expr = if spread.is_some() {
|
||||
self.include_in_expr(true).parse_bin_expr()?
|
||||
} else {
|
||||
self.parse_bin_expr()?
|
||||
};
|
||||
|
||||
ExprOrSpread { spread, expr }
|
||||
} else {
|
||||
self.include_in_expr(true).parse_expr_or_spread()?
|
||||
}
|
||||
};
|
||||
let optional = if self.input.syntax().typescript() {
|
||||
if eat!('?') {
|
||||
match arg {
|
||||
ExprOrSpread {
|
||||
expr: box Expr::Ident(..),
|
||||
..
|
||||
} => {}
|
||||
_ => syntax_error!(arg.span(), SyntaxError::TsBindingPatCannotBeOptional),
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if optional || (self.input.syntax().typescript() && is!(':')) {
|
||||
let start = cur_pos!();
|
||||
let mut pat = self.reparse_expr_as_pat(PatType::BindingPat, arg.expr)?;
|
||||
if optional {
|
||||
match pat {
|
||||
Pat::Ident(ref mut i) => i.optional = true,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
if let Some(span) = arg.spread {
|
||||
if let Some(rest_span) = rest_span {
|
||||
// Rest pattern must be last one.
|
||||
syntax_error!(rest_span, SyntaxError::NonLastRestParam);
|
||||
}
|
||||
rest_span = Some(span);
|
||||
pat = Pat::Rest(RestPat {
|
||||
dot3_token: span,
|
||||
arg: box pat,
|
||||
type_ann: None,
|
||||
});
|
||||
}
|
||||
match pat {
|
||||
Pat::Ident(Ident {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Array(ArrayPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Assign(AssignPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Object(ObjectPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Rest(RestPat {
|
||||
ref mut type_ann, ..
|
||||
}) => {
|
||||
*type_ann = self
|
||||
.parse_ts_type_ann(/* eat_colon */ true, start)
|
||||
.map(Some)?
|
||||
}
|
||||
Pat::Expr(ref expr) => unreachable!("invalid pattern: Expr({:?})", expr),
|
||||
}
|
||||
|
||||
if eat!('=') {
|
||||
//TODO: is parse_expr correct?
|
||||
let right = self.parse_expr()?;
|
||||
pat = Pat::Assign(AssignPat {
|
||||
span: span!(start),
|
||||
left: box pat,
|
||||
right,
|
||||
type_ann: None,
|
||||
});
|
||||
}
|
||||
|
||||
items.push(PatOrExprOrSpread::Pat(pat))
|
||||
} else {
|
||||
items.push(PatOrExprOrSpread::ExprOrSpread(arg));
|
||||
}
|
||||
}
|
||||
|
||||
expect!(')');
|
||||
Ok(items)
|
||||
}
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
pub(in crate::parser) enum PatOrExprOrSpread {
|
||||
Pat(Pat),
|
||||
ExprOrSpread(ExprOrSpread),
|
||||
}
|
||||
|
||||
/// simple leaf methods.
|
||||
#[parser]
|
||||
impl<'a, I: Input> Parser<'a, I> {
|
||||
@ -743,17 +1119,30 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
fn at_possible_async(&mut self, expr: &Expr) -> PResult<'a, bool> {
|
||||
// TODO(kdy1): !this.state.containsEsc &&
|
||||
|
||||
Ok(self.state.potential_arrow_start == Some(expr.span().lo())
|
||||
&& match *expr {
|
||||
Expr::Ident(Ident {
|
||||
sym: js_word!("async"),
|
||||
..
|
||||
}) => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// 12.2.5 Array Initializer
|
||||
fn parse_lit(&mut self) -> PResult<'a, Lit> {
|
||||
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
|
||||
let start = cur_pos!();
|
||||
|
||||
let v = match *cur!(true)? {
|
||||
Word(Null) => {
|
||||
Word(Word::Null) => {
|
||||
bump!();
|
||||
let span = span!(start);
|
||||
Lit::Null(Null { span })
|
||||
}
|
||||
Word(True) | Word(False) => {
|
||||
Word(Word::True) | Word(Word::False) => {
|
||||
let value = is!("true");
|
||||
bump!();
|
||||
let span = span!(start);
|
||||
@ -768,8 +1157,8 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Num(..) => match bump!() {
|
||||
Num(value) => Lit::Num(Number {
|
||||
Token::Num(..) => match bump!() {
|
||||
Token::Num(value) => Lit::Num(Number {
|
||||
span: span!(start),
|
||||
value,
|
||||
}),
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Parser for unary operations and binary operations.
|
||||
use super::{util::ExprExt, *};
|
||||
use crate::token::Keyword;
|
||||
use swc_common::Spanned;
|
||||
|
||||
#[parser]
|
||||
@ -17,11 +18,29 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
/// `minPrec` provides context that allows the function to stop and
|
||||
/// defer further parser to one of its callers when it encounters an
|
||||
/// operator that has a lower precedence than the set it is parsing.
|
||||
///
|
||||
/// `parseExprOp`
|
||||
fn parse_bin_op_recursively(
|
||||
&mut self,
|
||||
left: Box<Expr>,
|
||||
min_prec: u8,
|
||||
) -> PResult<'a, (Box<Expr>)> {
|
||||
) -> PResult<'a, Box<Expr>> {
|
||||
const PREC_OF_IN: u8 = 7;
|
||||
|
||||
if self.input.syntax().typescript() {
|
||||
if PREC_OF_IN > min_prec && !self.input.had_line_break_before_cur() && is!("as") {
|
||||
let span = span!(left.span().lo());
|
||||
let expr = left;
|
||||
let type_ann = self.next_then_parse_ts_type()?;
|
||||
let node = box Expr::TsAs(TsAsExpr {
|
||||
span,
|
||||
expr,
|
||||
type_ann,
|
||||
});
|
||||
return self.parse_bin_op_recursively(node, min_prec);
|
||||
}
|
||||
}
|
||||
|
||||
let op = match {
|
||||
// Return left on eof
|
||||
match cur!(false) {
|
||||
@ -29,9 +48,9 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
Err(..) => return Ok(left),
|
||||
}
|
||||
} {
|
||||
&Word(Keyword(In)) if self.ctx().include_in_expr => op!("in"),
|
||||
&Word(Keyword(InstanceOf)) => op!("instanceof"),
|
||||
&BinOp(op) => op.into(),
|
||||
&Word(Word::Keyword(Keyword::In)) if self.ctx().include_in_expr => op!("in"),
|
||||
&Word(Word::Keyword(Keyword::InstanceOf)) => op!("instanceof"),
|
||||
&Token::BinOp(op) => op.into(),
|
||||
_ => {
|
||||
return Ok(left);
|
||||
}
|
||||
@ -99,12 +118,16 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
/// Parse unary expression and update expression.
|
||||
///
|
||||
/// spec: 'UnaryExpression'
|
||||
fn parse_unary_expr(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
pub(in crate::parser) fn parse_unary_expr(&mut self) -> PResult<'a, (Box<Expr>)> {
|
||||
let start = cur_pos!();
|
||||
|
||||
if !self.input.syntax().jsx() && eat!('<') {
|
||||
return self.parse_ts_type_assertion().map(Expr::from).map(Box::new);
|
||||
}
|
||||
|
||||
// Parse update expression
|
||||
if is!("++") || is!("--") {
|
||||
let op = if bump!() == PlusPlus {
|
||||
let op = if bump!() == tok!("++") {
|
||||
op!("++")
|
||||
} else {
|
||||
op!("--")
|
||||
@ -126,13 +149,13 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// Parse unary expression
|
||||
if is_one_of!("delete", "void", "typeof", '+', '-', '~', '!') {
|
||||
let op = match bump!() {
|
||||
Word(Keyword(Delete)) => op!("delete"),
|
||||
Word(Keyword(Void)) => op!("void"),
|
||||
Word(Keyword(TypeOf)) => op!("typeof"),
|
||||
BinOp(Add) => op!(unary, "+"),
|
||||
BinOp(Sub) => op!(unary, "-"),
|
||||
Tilde => op!("~"),
|
||||
Bang => op!("!"),
|
||||
tok!("delete") => op!("delete"),
|
||||
tok!("void") => op!("void"),
|
||||
tok!("typeof") => op!("typeof"),
|
||||
tok!('+') => op!(unary, "+"),
|
||||
tok!('-') => op!(unary, "-"),
|
||||
tok!('~') => op!("~"),
|
||||
tok!('!') => op!("!"),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let arg = self.parse_unary_expr()?;
|
||||
@ -163,7 +186,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
|
||||
let start = cur_pos!();
|
||||
let op = if bump!() == PlusPlus {
|
||||
let op = if bump!() == tok!("++") {
|
||||
op!("++")
|
||||
} else {
|
||||
op!("--")
|
||||
@ -200,15 +223,17 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_common::DUMMY_SP as span;
|
||||
|
||||
fn bin(s: &'static str) -> Box<Expr> {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_bin_expr())
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_bin_expr().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
const span: Span = DUMMY_SP;
|
||||
|
||||
#[test]
|
||||
fn simple() {
|
||||
assert_eq_ignore_span!(
|
||||
|
@ -2,23 +2,43 @@ use super::*;
|
||||
use swc_common::DUMMY_SP as span;
|
||||
|
||||
fn lhs(s: &'static str) -> Box<Expr> {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_lhs_expr())
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_lhs_expr().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn new_expr(s: &'static str) -> Box<Expr> {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_new_expr())
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_new_expr().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn member_expr(s: &'static str) -> Box<Expr> {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_member_expr())
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_member_expr().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn expr(s: &'static str) -> Box<Expr> {
|
||||
test_parser(s, Syntax::Es2019, |p| {
|
||||
p.parse_stmt(true).map(|stmt| match stmt {
|
||||
Stmt::Expr(expr) => expr,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_stmt(true)
|
||||
.map(|stmt| match stmt {
|
||||
Stmt::Expr(expr) => expr,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -28,13 +48,7 @@ fn arrow_assign() {
|
||||
expr("a = b => false"),
|
||||
box Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left: PatOrExpr::Pat(
|
||||
box Ident {
|
||||
span,
|
||||
sym: "a".into(),
|
||||
}
|
||||
.into()
|
||||
),
|
||||
left: PatOrExpr::Pat(box Ident::new("a".into(), span).into()),
|
||||
op: op!("="),
|
||||
right: expr("b => false"),
|
||||
})
|
||||
@ -49,6 +63,7 @@ fn async_call() {
|
||||
span,
|
||||
callee: ExprOrSuper::Expr(expr("async")),
|
||||
args: vec![],
|
||||
type_args: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -63,6 +78,8 @@ fn async_arrow() {
|
||||
is_generator: false,
|
||||
params: vec![],
|
||||
body: BlockStmtOrExpr::Expr(expr("foo")),
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -79,14 +96,18 @@ fn object_rest_pat() {
|
||||
span,
|
||||
props: vec![ObjectPatProp::Rest(RestPat {
|
||||
dot3_token: span,
|
||||
arg: box Pat::Ident(Ident::new("a34".into(), span))
|
||||
})]
|
||||
arg: box Pat::Ident(Ident::new("a34".into(), span)),
|
||||
type_ann: None,
|
||||
})],
|
||||
type_ann: None
|
||||
})
|
||||
.into()],
|
||||
body: BlockStmtOrExpr::BlockStmt(BlockStmt {
|
||||
span,
|
||||
stmts: vec![]
|
||||
})
|
||||
}),
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -97,38 +118,17 @@ fn object_spread() {
|
||||
expr("foo = {a, ...bar, b}"),
|
||||
box Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(
|
||||
Ident {
|
||||
span,
|
||||
sym: "foo".into()
|
||||
}
|
||||
.into()
|
||||
)),
|
||||
left: PatOrExpr::Pat(box Pat::Ident(Ident::new("foo".into(), span))),
|
||||
op: op!("="),
|
||||
right: box Expr::Object(ObjectLit {
|
||||
span,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(
|
||||
box Ident {
|
||||
span,
|
||||
sym: "a".into()
|
||||
}
|
||||
.into()
|
||||
),
|
||||
PropOrSpread::Prop(box Ident::new("a".into(), span).into()),
|
||||
PropOrSpread::Spread(SpreadElement {
|
||||
dot3_token: span,
|
||||
expr: box Expr::Ident(Ident {
|
||||
span,
|
||||
sym: "bar".into(),
|
||||
})
|
||||
expr: box Expr::Ident(Ident::new("bar".into(), span))
|
||||
}),
|
||||
PropOrSpread::Prop(
|
||||
box Ident {
|
||||
span,
|
||||
sym: "b".into()
|
||||
}
|
||||
.into()
|
||||
),
|
||||
PropOrSpread::Prop(box Ident::new("b".into(), span).into()),
|
||||
]
|
||||
})
|
||||
})
|
||||
@ -142,11 +142,7 @@ fn new_expr_should_not_eat_too_much() {
|
||||
box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: ExprOrSuper::Expr(member_expr("new Date()")),
|
||||
prop: box Ident {
|
||||
sym: "toString".into(),
|
||||
span,
|
||||
}
|
||||
.into(),
|
||||
prop: box Ident::new("toString".into(), span).into(),
|
||||
computed: false,
|
||||
})
|
||||
);
|
||||
@ -159,6 +155,7 @@ fn lhs_expr_as_new_expr_prod() {
|
||||
span,
|
||||
callee: lhs("Date.toString"),
|
||||
args: Some(vec![]),
|
||||
type_args: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -171,6 +168,7 @@ fn lhs_expr_as_call() {
|
||||
span,
|
||||
callee: ExprOrSuper::Expr(lhs("new Date.toString()")),
|
||||
args: vec![],
|
||||
type_args: None,
|
||||
})
|
||||
)
|
||||
}
|
||||
@ -185,6 +183,8 @@ fn arrow_fn_no_args() {
|
||||
is_generator: false,
|
||||
params: vec![],
|
||||
body: BlockStmtOrExpr::Expr(expr("1")),
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -196,11 +196,10 @@ fn arrow_fn() {
|
||||
span,
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
params: vec![Pat::Ident(Ident {
|
||||
span,
|
||||
sym: "a".into(),
|
||||
})],
|
||||
params: vec![Pat::Ident(Ident::new("a".into(), span)).into()],
|
||||
body: BlockStmtOrExpr::Expr(expr("1")),
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -214,12 +213,13 @@ fn arrow_fn_rest() {
|
||||
is_generator: false,
|
||||
params: vec![Pat::Rest(RestPat {
|
||||
dot3_token: span,
|
||||
arg: box Pat::Ident(Ident {
|
||||
span,
|
||||
sym: "a".into(),
|
||||
}),
|
||||
})],
|
||||
arg: box Pat::Ident(Ident::new("a".into(), span)),
|
||||
type_ann: None
|
||||
})
|
||||
.into()],
|
||||
body: BlockStmtOrExpr::Expr(expr("1")),
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -231,11 +231,10 @@ fn arrow_fn_no_paren() {
|
||||
span,
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
params: vec![Pat::Ident(Ident {
|
||||
span,
|
||||
sym: "a".into(),
|
||||
})],
|
||||
params: vec![Pat::Ident(Ident::new("a".into(), span)).into()],
|
||||
body: BlockStmtOrExpr::Expr(expr("1")),
|
||||
type_params: None,
|
||||
return_type: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -248,6 +247,7 @@ fn new_no_paren() {
|
||||
span,
|
||||
callee: expr("a"),
|
||||
args: None,
|
||||
type_args: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -260,6 +260,7 @@ fn new_new_no_paren() {
|
||||
span,
|
||||
callee: expr("new a"),
|
||||
args: None,
|
||||
type_args: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -1,9 +1,37 @@
|
||||
//! 12.1 Identifiers
|
||||
|
||||
use super::*;
|
||||
use crate::token::Keyword;
|
||||
use either::Either;
|
||||
|
||||
#[parser]
|
||||
impl<'a, I: Input> Parser<'a, I> {
|
||||
pub(super) fn parse_maybe_private_name(&mut self) -> PResult<'a, Either<PrivateName, Ident>> {
|
||||
let start = cur_pos!();
|
||||
let is_private = is!('#');
|
||||
|
||||
if is_private {
|
||||
self.parse_private_name().map(Either::Left)
|
||||
} else {
|
||||
self.parse_ident_name().map(Either::Right)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn parse_private_name(&mut self) -> PResult<'a, PrivateName> {
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!('#');
|
||||
|
||||
let hash_end = self.input.prev_span().hi();
|
||||
if self.input.cur_pos() - hash_end != BytePos(0) {
|
||||
syntax_error!(span!(start), SyntaxError::SpaceBetweenHashAndIdent);
|
||||
}
|
||||
|
||||
let id = self.parse_ident(true, true)?;
|
||||
Ok(PrivateName {
|
||||
span: span!(start),
|
||||
id,
|
||||
})
|
||||
}
|
||||
|
||||
/// IdentifierReference
|
||||
pub(super) fn parse_ident_ref(&mut self) -> PResult<'a, Ident> {
|
||||
let ctx = self.ctx();
|
||||
@ -55,18 +83,18 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// StringValue of IdentifierName is: "implements", "interface", "let",
|
||||
// "package", "private", "protected", "public", "static", or "yield".
|
||||
match w {
|
||||
Ident(js_word!("enum")) => {
|
||||
Word::Ident(js_word!("enum")) => {
|
||||
syntax_error!(p.input.prev_span(), SyntaxError::InvalidIdentInStrict)
|
||||
}
|
||||
Keyword(Yield)
|
||||
| Ident(js_word!("static"))
|
||||
| Ident(js_word!("implements"))
|
||||
| Ident(js_word!("interface"))
|
||||
| Ident(js_word!("let"))
|
||||
| Ident(js_word!("package"))
|
||||
| Ident(js_word!("private"))
|
||||
| Ident(js_word!("protected"))
|
||||
| Ident(js_word!("public"))
|
||||
Word::Keyword(Keyword::Yield)
|
||||
| Word::Ident(js_word!("static"))
|
||||
| Word::Ident(js_word!("implements"))
|
||||
| Word::Ident(js_word!("interface"))
|
||||
| Word::Ident(js_word!("let"))
|
||||
| Word::Ident(js_word!("package"))
|
||||
| Word::Ident(js_word!("private"))
|
||||
| Word::Ident(js_word!("protected"))
|
||||
| Word::Ident(js_word!("public"))
|
||||
if strict =>
|
||||
{
|
||||
syntax_error!(p.input.prev_span(), SyntaxError::InvalidIdentInStrict)
|
||||
@ -82,14 +110,17 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
match w {
|
||||
// It is a Syntax Error if the goal symbol of the syntactic grammar is Module
|
||||
// and the StringValue of IdentifierName is "await".
|
||||
Keyword(Await) if p.ctx().module => {
|
||||
Word::Keyword(Keyword::Await) if p.ctx().module => {
|
||||
syntax_error!(p.input.prev_span(), SyntaxError::ExpectedIdent)
|
||||
}
|
||||
Keyword(Let) => Ok(w.into()),
|
||||
Ident(ident) => Ok(ident),
|
||||
Keyword(Yield) if incl_yield => Ok(js_word!("yield")),
|
||||
Keyword(Await) if incl_await => Ok(js_word!("await")),
|
||||
Keyword(..) | Null | True | False => {
|
||||
Word::Keyword(Keyword::This) if p.input.syntax().typescript() => {
|
||||
Ok(js_word!("this"))
|
||||
}
|
||||
Word::Keyword(Keyword::Let) => Ok(js_word!("let")),
|
||||
Word::Ident(ident) => Ok(ident),
|
||||
Word::Keyword(Keyword::Yield) if incl_yield => Ok(js_word!("yield")),
|
||||
Word::Keyword(Keyword::Await) if incl_await => Ok(js_word!("await")),
|
||||
Word::Keyword(..) | Word::Null | Word::True | Word::False => {
|
||||
syntax_error!(p.input.prev_span(), SyntaxError::ExpectedIdent)
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
use crate::{
|
||||
lexer::{Input, Lexer},
|
||||
lexer::{self, Input, Lexer},
|
||||
token::*,
|
||||
Context, Syntax,
|
||||
};
|
||||
use swc_common::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
/// This struct is responsible for managing current token and peeked token.
|
||||
#[derive(Clone)]
|
||||
pub(super) struct ParserInput<'a, I: Input> {
|
||||
iter: Lexer<'a, I>,
|
||||
/// Span of the previous token.
|
||||
@ -127,7 +128,7 @@ impl<'a, I: Input> ParserInput<'a, I> {
|
||||
}
|
||||
|
||||
pub fn eat_keyword(&mut self, kwd: Keyword) -> bool {
|
||||
self.eat(&Word(Keyword(kwd)))
|
||||
self.eat(&Word(Word::Keyword(kwd)))
|
||||
}
|
||||
|
||||
/// Returns start of current token.
|
||||
@ -170,4 +171,18 @@ impl<'a, I: Input> ParserInput<'a, I> {
|
||||
pub const fn syntax(&self) -> Syntax {
|
||||
self.iter.syntax
|
||||
}
|
||||
|
||||
pub fn set_expr_allowed(&mut self, allow: bool) {
|
||||
self.iter.set_expr_allowed(allow)
|
||||
}
|
||||
|
||||
pub(crate) const fn token_context(&self) -> &lexer::TokenContexts {
|
||||
self.iter.token_context()
|
||||
}
|
||||
pub fn token_context_mut(&mut self) -> &mut lexer::TokenContexts {
|
||||
self.iter.token_context_mut()
|
||||
}
|
||||
pub(crate) fn set_token_context(&mut self, c: lexer::TokenContexts) {
|
||||
self.iter.set_token_context(c)
|
||||
}
|
||||
}
|
||||
|
@ -175,14 +175,20 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
.map(Either::Right)
|
||||
}
|
||||
|
||||
/// `jsxParseOpeningElementAfterName`
|
||||
pub(super) fn parse_jsx_opening_element_after_name(
|
||||
&mut self,
|
||||
name: JSXElementName,
|
||||
) -> PResult<'a, JSXOpeningElement> {
|
||||
debug_assert!(self.input.syntax().jsx());
|
||||
|
||||
let start = name.span().lo();
|
||||
|
||||
let type_args = if self.input.syntax().typescript() {
|
||||
self.try_parse_ts(|p| p.parse_ts_type_args().map(Some))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut attrs = vec![];
|
||||
while let Ok(..) = cur!(false) {
|
||||
if is!('/') || is!(JSXTagEnd) {
|
||||
@ -201,6 +207,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
name,
|
||||
attrs,
|
||||
self_closing,
|
||||
type_args,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,12 @@ use crate::parser::test_parser;
|
||||
use swc_common::DUMMY_SP as span;
|
||||
|
||||
fn jsx(src: &'static str) -> Box<Expr> {
|
||||
test_parser(src, Syntax::Jsx, |p| p.parse_expr())
|
||||
test_parser(src, Syntax::Jsx, |p| {
|
||||
p.parse_expr().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -16,7 +21,8 @@ fn self_closing_01() {
|
||||
span,
|
||||
name: JSXElementName::Ident(Ident::new("a".into(), span)),
|
||||
self_closing: true,
|
||||
attrs: vec![]
|
||||
attrs: vec![],
|
||||
type_args: None,
|
||||
},
|
||||
children: vec![],
|
||||
closing: None,
|
||||
@ -34,7 +40,8 @@ fn normal_01() {
|
||||
span,
|
||||
name: JSXElementName::Ident(Ident::new("a".into(), span)),
|
||||
self_closing: false,
|
||||
attrs: vec![]
|
||||
attrs: vec![],
|
||||
type_args: None,
|
||||
},
|
||||
children: vec![JSXElementChild::JSXText(JSXText {
|
||||
span,
|
||||
@ -68,6 +75,7 @@ fn escape_in_attr() {
|
||||
})],
|
||||
name: JSXElementName::Ident(Ident::new("div".into(), span)),
|
||||
self_closing: true,
|
||||
type_args: None,
|
||||
},
|
||||
children: vec![],
|
||||
closing: None
|
||||
|
@ -9,7 +9,7 @@ macro_rules! unexpected {
|
||||
///
|
||||
/// Returns bool.
|
||||
macro_rules! is {
|
||||
($p:expr,BindingIdent) => {{
|
||||
($p:expr, BindingIdent) => {{
|
||||
let ctx = $p.ctx();
|
||||
match cur!($p, false) {
|
||||
Ok(&Word(ref w)) => !ctx.is_reserved_word(&w.clone().into()),
|
||||
@ -17,7 +17,7 @@ macro_rules! is {
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr,IdentRef) => {{
|
||||
($p:expr, IdentRef) => {{
|
||||
let ctx = $p.ctx();
|
||||
match cur!($p, false) {
|
||||
Ok(&Word(ref w)) => !ctx.is_reserved_word(&w.clone().into()),
|
||||
@ -44,6 +44,39 @@ macro_rules! is {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! peeked_is {
|
||||
($p:expr, BindingIdent) => {{
|
||||
let ctx = $p.ctx();
|
||||
match peek!($p) {
|
||||
Ok(&Word(ref w)) => !ctx.is_reserved_word(&w.clone().into()),
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr, IdentRef) => {{
|
||||
let ctx = $p.ctx();
|
||||
match peek!($p) {
|
||||
Ok(&Word(ref w)) => !ctx.is_reserved_word(&w.clone().into()),
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr,IdentName) => {{
|
||||
match peek!($p) {
|
||||
Ok(&Word(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr, ';') => {{
|
||||
compile_error!("peeked_is!(';') is invalid");
|
||||
}};
|
||||
|
||||
($p:expr, $t:tt) => {
|
||||
$p.input.peeked_is(&tok!($t))
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns true on eof.
|
||||
macro_rules! eof {
|
||||
($p:expr) => {
|
||||
@ -51,12 +84,6 @@ macro_rules! eof {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! peeked_is {
|
||||
($p:expr, $t:tt) => {
|
||||
$p.input.peeked_is(&tok!($t))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! is_one_of {
|
||||
($p:expr, $($t:tt),+) => {{
|
||||
false
|
||||
@ -86,7 +113,7 @@ macro_rules! assert_and_bump {
|
||||
/// Returns bool if token is static, and Option<Token>
|
||||
/// if token has data like string.
|
||||
macro_rules! eat {
|
||||
($p:expr,';') => {{
|
||||
($p:expr, ';') => {{
|
||||
trace!("eat(';'): cur={:?}", cur!($p, true));
|
||||
$p.input.eat(&Token::Semi)
|
||||
|| eof!($p)
|
||||
@ -95,7 +122,6 @@ macro_rules! eat {
|
||||
}};
|
||||
|
||||
($p:expr, $t:tt) => {{
|
||||
const TOKEN: &Token = &tok!($t);
|
||||
if is!($p, $t) {
|
||||
bump!($p);
|
||||
true
|
||||
@ -150,13 +176,13 @@ macro_rules! cur {
|
||||
if is_err_token {
|
||||
match $p.input.bump() {
|
||||
$crate::token::Token::Error(e) => {
|
||||
::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag {
|
||||
handler: &$p.session.handler,
|
||||
span: e.span,
|
||||
error: e.error,
|
||||
})
|
||||
.emit();
|
||||
let err: Result<!, _> = Err(());
|
||||
let err =
|
||||
::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag {
|
||||
handler: &$p.session.handler,
|
||||
span: e.span,
|
||||
error: e.error,
|
||||
});
|
||||
let err: Result<!, _> = Err(err);
|
||||
err?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@ -167,13 +193,17 @@ macro_rules! cur {
|
||||
Some(c) => Ok(c),
|
||||
None => {
|
||||
if $required {
|
||||
::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof {
|
||||
let err = ::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof {
|
||||
last,
|
||||
handler: &$p.session.handler,
|
||||
})
|
||||
.emit();
|
||||
});
|
||||
let err: Result<!, _> = Err(err);
|
||||
err?
|
||||
}
|
||||
Err(())
|
||||
Err($crate::error::Eof {
|
||||
last,
|
||||
handler: &$p.session.handler,
|
||||
})
|
||||
}
|
||||
}
|
||||
}};
|
||||
@ -193,13 +223,12 @@ Current token is {:?}",
|
||||
match $p.input.peek() {
|
||||
Some(c) => Ok(c),
|
||||
None => {
|
||||
::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof {
|
||||
let err = ::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof {
|
||||
//TODO: Use whole span
|
||||
last,
|
||||
handler: &$p.session.handler,
|
||||
})
|
||||
.emit();
|
||||
Err(())
|
||||
});
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}};
|
||||
@ -269,13 +298,12 @@ macro_rules! syntax_error {
|
||||
};
|
||||
|
||||
($p:expr, $span:expr, $err:expr) => {{
|
||||
::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag {
|
||||
let err = ::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag {
|
||||
handler: $p.session.handler,
|
||||
span: $span,
|
||||
error: $err,
|
||||
})
|
||||
.emit();
|
||||
let res: Result<!, _> = Err(());
|
||||
res?
|
||||
});
|
||||
let err: Result<!, _> = Err(err);
|
||||
err?
|
||||
}};
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ use crate::{
|
||||
error::SyntaxError,
|
||||
lexer::{Input, Lexer},
|
||||
parser_macros::parser,
|
||||
token::*,
|
||||
token::{Token, Word},
|
||||
Context, Session, Syntax,
|
||||
};
|
||||
use ast::*;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{BytePos, Span};
|
||||
use swc_common::{errors::DiagnosticBuilder, BytePos, Span};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
@ -23,19 +23,21 @@ mod jsx;
|
||||
mod object;
|
||||
mod pat;
|
||||
mod stmt;
|
||||
mod typescript;
|
||||
mod util;
|
||||
|
||||
/// When error ocurred, error is emiited and parser returnes Err(()).
|
||||
pub type PResult<'a, T> = Result<T, ()>;
|
||||
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
|
||||
|
||||
/// EcmaScript parser.
|
||||
#[derive(Clone)]
|
||||
pub struct Parser<'a, I: Input> {
|
||||
session: Session<'a>,
|
||||
state: State,
|
||||
input: ParserInput<'a, I>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct State {
|
||||
labels: Vec<JsWord>,
|
||||
/// Start position of an assignment expression.
|
||||
@ -92,14 +94,3 @@ where
|
||||
crate::with_test_sess(s, |sess, input| f(&mut Parser::new(sess, syntax, input)))
|
||||
.unwrap_or_else(|output| panic!("test_parser(): failed to parse \n{}\n{}", s, output))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_legacy() {
|
||||
test_parser("<!--", Syntax::Es2019, |f| {
|
||||
let res = f.parse_module();
|
||||
assert!(f.ctx().module);
|
||||
assert!(f.ctx().strict);
|
||||
let _ = res.expect_err("!");
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
@ -35,44 +35,48 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
/// spec: 'PropertyName'
|
||||
pub(super) fn parse_prop_name(&mut self) -> PResult<'a, PropName> {
|
||||
let start = cur_pos!();
|
||||
let ctx = self.ctx();
|
||||
self.with_ctx(Context {
|
||||
in_property_name: true,
|
||||
..ctx
|
||||
})
|
||||
.parse_with(|p| {
|
||||
let start = cur_pos!();
|
||||
|
||||
let v = match *cur!(true)? {
|
||||
Token::Str { .. } => match bump!() {
|
||||
Token::Str { value, has_escape } => PropName::Str(Str {
|
||||
span: span!(start),
|
||||
value,
|
||||
has_escape,
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Num(_) => match bump!() {
|
||||
Num(value) => PropName::Num(Number {
|
||||
span: span!(start),
|
||||
value,
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Word(..) => match bump!() {
|
||||
Word(w) => PropName::Ident(Ident {
|
||||
span: span!(start),
|
||||
sym: w.into(),
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
LBracket => {
|
||||
bump!();
|
||||
let expr = self
|
||||
.include_in_expr(true)
|
||||
.parse_assignment_expr()
|
||||
.map(PropName::Computed)?;
|
||||
expect!(']');
|
||||
expr
|
||||
}
|
||||
_ => unexpected!(),
|
||||
};
|
||||
let v = match *cur!(true)? {
|
||||
Token::Str { .. } => match bump!() {
|
||||
Token::Str { value, has_escape } => PropName::Str(Str {
|
||||
span: span!(start),
|
||||
value,
|
||||
has_escape,
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Token::Num(_) => match bump!() {
|
||||
Token::Num(value) => PropName::Num(Number {
|
||||
span: span!(start),
|
||||
value,
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Word(..) => match bump!() {
|
||||
Word(w) => PropName::Ident(Ident::new(w.into(), span!(start))),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
tok!('[') => {
|
||||
bump!();
|
||||
let expr = p
|
||||
.include_in_expr(true)
|
||||
.parse_assignment_expr()
|
||||
.map(PropName::Computed)?;
|
||||
expect!(']');
|
||||
expr
|
||||
}
|
||||
_ => unexpected!(),
|
||||
};
|
||||
|
||||
Ok(v)
|
||||
Ok(v)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +107,14 @@ impl<'a, I: Input> ParseObject<'a, (Box<Expr>)> for Parser<'a, I> {
|
||||
|
||||
let name = self.parse_prop_name()?;
|
||||
return self
|
||||
.parse_fn_args_body(start, Parser::parse_unique_formal_params, false, true)
|
||||
.parse_fn_args_body(
|
||||
// no decorator in an object literal
|
||||
vec![],
|
||||
start,
|
||||
Parser::parse_unique_formal_params,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.map(|function| {
|
||||
PropOrSpread::Prop(box Prop::Method(MethodProp {
|
||||
key: name,
|
||||
@ -127,9 +138,16 @@ impl<'a, I: Input> ParseObject<'a, (Box<Expr>)> for Parser<'a, I> {
|
||||
}
|
||||
|
||||
// Handle `a(){}` (and async(){} / get(){} / set(){})
|
||||
if is!('(') {
|
||||
if (self.input.syntax().typescript() && is!('<')) || is!('(') {
|
||||
return self
|
||||
.parse_fn_args_body(start, Parser::parse_unique_formal_params, false, false)
|
||||
.parse_fn_args_body(
|
||||
// no decorator in an object literal
|
||||
vec![],
|
||||
start,
|
||||
Parser::parse_unique_formal_params,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.map(|function| box Prop::Method(MethodProp { key, function }))
|
||||
.map(PropOrSpread::Prop);
|
||||
}
|
||||
@ -167,7 +185,14 @@ impl<'a, I: Input> ParseObject<'a, (Box<Expr>)> for Parser<'a, I> {
|
||||
|
||||
return match ident.sym {
|
||||
js_word!("get") => self
|
||||
.parse_fn_args_body(start, |_| Ok(vec![]), false, false)
|
||||
.parse_fn_args_body(
|
||||
// no decorator in an object literal
|
||||
vec![],
|
||||
start,
|
||||
|_| Ok(vec![]),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.map(|Function { body, .. }| {
|
||||
PropOrSpread::Prop(box Prop::Getter(GetterProp {
|
||||
span: span!(start),
|
||||
@ -177,6 +202,8 @@ impl<'a, I: Input> ParseObject<'a, (Box<Expr>)> for Parser<'a, I> {
|
||||
}),
|
||||
js_word!("set") => self
|
||||
.parse_fn_args_body(
|
||||
// no decorator in an object literal
|
||||
vec![],
|
||||
start,
|
||||
|p| p.parse_formal_param().map(|pat| vec![pat]),
|
||||
false,
|
||||
@ -192,7 +219,14 @@ impl<'a, I: Input> ParseObject<'a, (Box<Expr>)> for Parser<'a, I> {
|
||||
}))
|
||||
}),
|
||||
js_word!("async") => self
|
||||
.parse_fn_args_body(start, Parser::parse_unique_formal_params, true, false)
|
||||
.parse_fn_args_body(
|
||||
// no decorator in an object literal
|
||||
vec![],
|
||||
start,
|
||||
Parser::parse_unique_formal_params,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.map(|function| {
|
||||
PropOrSpread::Prop(box Prop::Method(MethodProp { key, function }))
|
||||
}),
|
||||
@ -209,7 +243,11 @@ impl<'a, I: Input> ParseObject<'a, Pat> for Parser<'a, I> {
|
||||
type Prop = ObjectPatProp;
|
||||
|
||||
fn make_object(span: Span, props: Vec<Self::Prop>) -> Pat {
|
||||
Pat::Object(ObjectPat { span, props })
|
||||
Pat::Object(ObjectPat {
|
||||
span,
|
||||
props,
|
||||
type_ann: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Production 'BindingProperty'
|
||||
@ -222,7 +260,11 @@ impl<'a, I: Input> ParseObject<'a, Pat> for Parser<'a, I> {
|
||||
|
||||
let arg = box self.parse_binding_pat_or_ident()?;
|
||||
|
||||
return Ok(ObjectPatProp::Rest(RestPat { dot3_token, arg }));
|
||||
return Ok(ObjectPatProp::Rest(RestPat {
|
||||
dot3_token,
|
||||
arg,
|
||||
type_ann: None,
|
||||
}));
|
||||
}
|
||||
|
||||
let key = self.parse_prop_name()?;
|
||||
|
@ -1,12 +1,13 @@
|
||||
//! 13.3.3 Destructuring Binding Patterns
|
||||
use super::{util::ExprExt, *};
|
||||
use crate::{parser::expr::PatOrExprOrSpread, token::AssignOpToken};
|
||||
use std::iter;
|
||||
use swc_common::Spanned;
|
||||
|
||||
#[parser]
|
||||
impl<'a, I: Input> Parser<'a, I> {
|
||||
pub(super) fn parse_opt_binding_ident(&mut self) -> PResult<'a, (Option<Ident>)> {
|
||||
if is!(BindingIdent) {
|
||||
if is!(BindingIdent) || (self.input.syntax().typescript() && is!("this")) {
|
||||
self.parse_binding_ident().map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
@ -60,6 +61,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
left: box left,
|
||||
right,
|
||||
type_ann: None,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -94,6 +96,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let pat = Pat::Rest(RestPat {
|
||||
dot3_token,
|
||||
arg: box pat,
|
||||
type_ann: None,
|
||||
});
|
||||
elems.push(Some(pat));
|
||||
// Trailing comma isn't allowed
|
||||
@ -108,17 +111,67 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
Ok(Pat::Array(ArrayPat {
|
||||
span: span!(start),
|
||||
elems,
|
||||
type_ann: None,
|
||||
}))
|
||||
}
|
||||
|
||||
/// spec: 'FormalParameter'
|
||||
///
|
||||
/// babel: `parseAssignableListItem`
|
||||
pub(super) fn parse_formal_param(&mut self) -> PResult<'a, Pat> {
|
||||
self.parse_binding_element()
|
||||
let start = cur_pos!();
|
||||
|
||||
let mut pat = self.parse_binding_element()?;
|
||||
if self.input.syntax().typescript() {
|
||||
if eat!('?') {
|
||||
match pat {
|
||||
Pat::Ident(Ident {
|
||||
ref mut optional, ..
|
||||
}) => {
|
||||
*optional = true;
|
||||
}
|
||||
_ => syntax_error!(
|
||||
self.input.prev_span(),
|
||||
SyntaxError::TsBindingPatCannotBeOptional
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
match pat {
|
||||
Pat::Array(ArrayPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Assign(AssignPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Ident(Ident {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Object(ObjectPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Rest(RestPat {
|
||||
ref mut type_ann, ..
|
||||
}) => {
|
||||
*type_ann = self.try_parse_ts_type_ann()?;
|
||||
}
|
||||
Pat::Expr(expr) => unreachable!("invalid syntax: Pat(expr): {:?}", expr),
|
||||
}
|
||||
}
|
||||
if eat!('=') {
|
||||
let right = self.parse_expr()?;
|
||||
Ok(Pat::Assign(AssignPat {
|
||||
span: span!(start),
|
||||
left: box pat,
|
||||
type_ann: None,
|
||||
right,
|
||||
}))
|
||||
} else {
|
||||
Ok(pat)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// spec: 'FormalParameterList'
|
||||
pub(super) fn parse_formal_params(&mut self) -> PResult<'a, (Vec<Pat>)> {
|
||||
pub(super) fn parse_constructor_params(&mut self) -> PResult<'a, Vec<PatOrTsParamProp>> {
|
||||
let mut first = true;
|
||||
let mut params = vec![];
|
||||
|
||||
@ -139,22 +192,101 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let dot3_token = span!(start);
|
||||
|
||||
let pat = self.parse_binding_pat_or_ident()?;
|
||||
let type_ann = if self.input.syntax().typescript() && is!(':') {
|
||||
let cur_pos = cur_pos!();
|
||||
Some(self.parse_ts_type_ann(/* eat_colon */ true, cur_pos)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let pat = Pat::Rest(RestPat {
|
||||
dot3_token,
|
||||
arg: box pat,
|
||||
type_ann,
|
||||
});
|
||||
params.push(pat);
|
||||
params.push(PatOrTsParamProp::Pat(pat));
|
||||
break;
|
||||
} else {
|
||||
params.push(self.parse_binding_element()?);
|
||||
params.push(self.parse_constructor_param()?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
pub(super) fn parse_unique_formal_params(&mut self) -> PResult<'a, (Vec<Pat>)> {
|
||||
// FIXME: This is wrong.
|
||||
fn parse_constructor_param(&mut self) -> PResult<'a, PatOrTsParamProp> {
|
||||
let start = cur_pos!();
|
||||
let (accessibility, readonly) = if self.input.syntax().typescript() {
|
||||
let accessibility = self.parse_access_modifier()?;
|
||||
(
|
||||
accessibility,
|
||||
self.parse_ts_modifier(&["readonly"])?.is_some(),
|
||||
)
|
||||
} else {
|
||||
(None, false)
|
||||
};
|
||||
if accessibility == None && readonly == false {
|
||||
self.parse_formal_param().map(PatOrTsParamProp::from)
|
||||
} else {
|
||||
Ok(PatOrTsParamProp::TsParamProp(TsParamProp {
|
||||
span: span!(start),
|
||||
accessibility,
|
||||
readonly,
|
||||
decorators: vec![],
|
||||
param: match self.parse_formal_param()? {
|
||||
Pat::Ident(i) => TsParamPropParam::Ident(i),
|
||||
Pat::Assign(a) => TsParamPropParam::Assign(a),
|
||||
node => syntax_error!(node.span(), SyntaxError::TsInvalidParamPropPat),
|
||||
},
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn parse_formal_params(&mut self) -> PResult<'a, Vec<Pat>> {
|
||||
let mut first = true;
|
||||
let mut params = vec![];
|
||||
|
||||
while !eof!() && !is!(')') {
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
expect!(',');
|
||||
// Handle trailing comma.
|
||||
if is!(')') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let start = cur_pos!();
|
||||
|
||||
if eat!("...") {
|
||||
let dot3_token = span!(start);
|
||||
|
||||
let pat = self.parse_binding_pat_or_ident()?;
|
||||
let type_ann = if self.input.syntax().typescript() && is!(':') {
|
||||
let cur_pos = cur_pos!();
|
||||
Some(self.parse_ts_type_ann(/* eat_colon */ true, cur_pos)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let pat = Pat::Rest(RestPat {
|
||||
dot3_token,
|
||||
arg: box pat,
|
||||
type_ann,
|
||||
});
|
||||
params.push(pat);
|
||||
break;
|
||||
} else {
|
||||
params.push(self.parse_formal_param()?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
pub(super) fn parse_unique_formal_params(&mut self) -> PResult<'a, Vec<Pat>> {
|
||||
// FIXME: This is wrong
|
||||
self.parse_formal_params()
|
||||
}
|
||||
}
|
||||
@ -258,7 +390,12 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
match *expr {
|
||||
Expr::Paren(inner) => syntax_error!(span, SyntaxError::InvalidPat),
|
||||
Expr::Assign(assign_expr @ AssignExpr { op: Assign, .. }) => {
|
||||
Expr::Assign(
|
||||
assign_expr @ AssignExpr {
|
||||
op: AssignOpToken::Assign,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
let AssignExpr {
|
||||
span, left, right, ..
|
||||
} = assign_expr;
|
||||
@ -269,6 +406,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
PatOrExpr::Pat(left) => left,
|
||||
},
|
||||
right,
|
||||
type_ann: None,
|
||||
}));
|
||||
}
|
||||
Expr::Object(ObjectLit { span, props }) => {
|
||||
@ -307,6 +445,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// FIXME: is BindingPat correct?
|
||||
arg: box self
|
||||
.reparse_expr_as_pat(PatType::BindingPat, expr)?,
|
||||
type_ann: None,
|
||||
}))
|
||||
}
|
||||
|
||||
@ -314,6 +453,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
})
|
||||
.collect::<(PResult<'a, _>)>()?,
|
||||
type_ann: None,
|
||||
}));
|
||||
}
|
||||
Expr::Ident(ident) => return Ok(ident.into()),
|
||||
@ -324,6 +464,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
return Ok(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![],
|
||||
type_ann: None,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -370,6 +511,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
Pat::Rest(RestPat {
|
||||
dot3_token,
|
||||
arg: box pat,
|
||||
type_ann: None,
|
||||
})
|
||||
})
|
||||
.map(Some)?
|
||||
@ -386,6 +528,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
return Ok(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: params,
|
||||
type_ann: None,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -411,10 +554,10 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn parse_exprs_as_params(
|
||||
pub(super) fn parse_paren_items_as_params(
|
||||
&mut self,
|
||||
mut exprs: Vec<ExprOrSpread>,
|
||||
) -> PResult<'a, (Vec<Pat>)> {
|
||||
mut exprs: Vec<PatOrExprOrSpread>,
|
||||
) -> PResult<'a, Vec<Pat>> {
|
||||
let pat_ty = PatType::BindingPat;
|
||||
|
||||
let len = exprs.len();
|
||||
@ -426,10 +569,16 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
for expr in exprs.drain(..len - 1) {
|
||||
match expr {
|
||||
ExprOrSpread {
|
||||
PatOrExprOrSpread::ExprOrSpread(ExprOrSpread {
|
||||
spread: Some(..), ..
|
||||
} => syntax_error!(expr.span(), SyntaxError::NonLastRestParam),
|
||||
ExprOrSpread { expr, .. } => params.push(self.reparse_expr_as_pat(pat_ty, expr)?),
|
||||
})
|
||||
| PatOrExprOrSpread::Pat(Pat::Rest(..)) => {
|
||||
syntax_error!(expr.span(), SyntaxError::NonLastRestParam)
|
||||
}
|
||||
PatOrExprOrSpread::ExprOrSpread(ExprOrSpread {
|
||||
spread: None, expr, ..
|
||||
}) => params.push(self.reparse_expr_as_pat(pat_ty, expr)?),
|
||||
PatOrExprOrSpread::Pat(pat) => params.push(pat),
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,16 +586,20 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let expr = exprs.into_iter().next().unwrap();
|
||||
let last = match expr {
|
||||
// Rest
|
||||
ExprOrSpread {
|
||||
PatOrExprOrSpread::ExprOrSpread(ExprOrSpread {
|
||||
spread: Some(dot3_token),
|
||||
expr,
|
||||
} => self.reparse_expr_as_pat(pat_ty, expr).map(|pat| {
|
||||
}) => self.reparse_expr_as_pat(pat_ty, expr).map(|pat| {
|
||||
Pat::Rest(RestPat {
|
||||
dot3_token,
|
||||
arg: box pat,
|
||||
type_ann: None,
|
||||
})
|
||||
})?,
|
||||
ExprOrSpread { expr, .. } => self.reparse_expr_as_pat(pat_ty, expr)?,
|
||||
PatOrExprOrSpread::ExprOrSpread(ExprOrSpread { expr, .. }) => {
|
||||
self.reparse_expr_as_pat(pat_ty, expr)?
|
||||
}
|
||||
PatOrExprOrSpread::Pat(pat) => pat,
|
||||
};
|
||||
params.push(last);
|
||||
|
||||
@ -460,14 +613,16 @@ mod tests {
|
||||
use swc_common::DUMMY_SP as span;
|
||||
|
||||
fn array_pat(s: &'static str) -> Pat {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_array_binding_pat())
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_array_binding_pat().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn ident(s: &str) -> Ident {
|
||||
Ident {
|
||||
sym: s.into(),
|
||||
span,
|
||||
}
|
||||
Ident::new(s.into(), span)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -480,13 +635,16 @@ mod tests {
|
||||
Some(Pat::Ident(ident("a"))),
|
||||
Some(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![Some(Pat::Ident(ident("b")))]
|
||||
elems: vec![Some(Pat::Ident(ident("b")))],
|
||||
type_ann: None
|
||||
})),
|
||||
Some(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![Some(Pat::Ident(ident("c")))]
|
||||
elems: vec![Some(Pat::Ident(ident("c")))],
|
||||
type_ann: None
|
||||
}))
|
||||
]
|
||||
],
|
||||
type_ann: None
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -502,13 +660,16 @@ mod tests {
|
||||
Some(Pat::Ident(ident("a"))),
|
||||
Some(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![Some(Pat::Ident(ident("b")))]
|
||||
elems: vec![Some(Pat::Ident(ident("b")))],
|
||||
type_ann: None
|
||||
})),
|
||||
Some(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![Some(Pat::Ident(ident("c")))]
|
||||
elems: vec![Some(Pat::Ident(ident("c")))],
|
||||
type_ann: None
|
||||
}))
|
||||
]
|
||||
],
|
||||
type_ann: None
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -524,13 +685,16 @@ mod tests {
|
||||
None,
|
||||
Some(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![Some(Pat::Ident(ident("b")))]
|
||||
elems: vec![Some(Pat::Ident(ident("b")))],
|
||||
type_ann: None
|
||||
})),
|
||||
Some(Pat::Array(ArrayPat {
|
||||
span,
|
||||
elems: vec![Some(Pat::Ident(ident("c")))]
|
||||
elems: vec![Some(Pat::Ident(ident("c")))],
|
||||
type_ann: None
|
||||
}))
|
||||
]
|
||||
],
|
||||
type_ann: None
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
|
||||
pub fn parse_stmt(&mut self, top_level: bool) -> PResult<'a, Stmt> {
|
||||
self.parse_stmt_internal(false, top_level)
|
||||
self.parse_stmt_like(false, top_level)
|
||||
}
|
||||
|
||||
fn parse_stmt_list_item(&mut self, top_level: bool) -> PResult<'a, Stmt> {
|
||||
self.parse_stmt_internal(true, top_level)
|
||||
self.parse_stmt_like(true, top_level)
|
||||
}
|
||||
|
||||
/// Parse a statement, declaration or module item.
|
||||
@ -68,16 +68,34 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
Self: StmtLikeParser<'a, Type>,
|
||||
Type: IsDirective + From<Stmt>,
|
||||
{
|
||||
let decorators = self.parse_decorators(true)?;
|
||||
|
||||
if is_one_of!("import", "export") {
|
||||
return self.handle_import_export(top_level);
|
||||
return self.handle_import_export(top_level, decorators);
|
||||
}
|
||||
self.parse_stmt_internal(include_decl, top_level)
|
||||
|
||||
self.parse_stmt_internal(include_decl, top_level, decorators)
|
||||
.map(From::from)
|
||||
}
|
||||
|
||||
fn parse_stmt_internal(&mut self, include_decl: bool, top_level: bool) -> PResult<'a, Stmt> {
|
||||
/// `parseStatementContent`
|
||||
fn parse_stmt_internal(
|
||||
&mut self,
|
||||
include_decl: bool,
|
||||
top_level: bool,
|
||||
decorators: Vec<Decorator>,
|
||||
) -> PResult<'a, Stmt> {
|
||||
let start = cur_pos!();
|
||||
|
||||
if self.input.syntax().typescript() && is!("const") && peeked_is!("enum") {
|
||||
assert_and_bump!("const");
|
||||
assert_and_bump!("enum");
|
||||
return self
|
||||
.parse_ts_enum_decl(start, /* is_const */ true)
|
||||
.map(Decl::from)
|
||||
.map(Stmt::from);
|
||||
}
|
||||
|
||||
if is_one_of!("break", "continue") {
|
||||
let is_break = is!("break");
|
||||
bump!();
|
||||
@ -117,14 +135,14 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
unexpected!()
|
||||
}
|
||||
|
||||
return self.parse_fn_decl().map(Stmt::from);
|
||||
return self.parse_fn_decl(decorators).map(Stmt::from);
|
||||
}
|
||||
|
||||
if is!("class") {
|
||||
if !include_decl {
|
||||
unexpected!()
|
||||
}
|
||||
return self.parse_class_decl().map(Stmt::from);
|
||||
return self.parse_class_decl(decorators).map(Stmt::from);
|
||||
}
|
||||
|
||||
if is!("if") {
|
||||
@ -187,7 +205,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
&& peeked_is!("function")
|
||||
&& !self.input.has_linebreak_between_cur_and_peeked()
|
||||
{
|
||||
return self.parse_async_fn_decl().map(From::from);
|
||||
return self.parse_async_fn_decl(decorators).map(From::from);
|
||||
}
|
||||
|
||||
// If the statement does not start with a statement keyword or a
|
||||
@ -196,6 +214,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// next token is a colon and the expression was a simple
|
||||
// Identifier node, we switch to interpreting it as a label.
|
||||
let expr = self.include_in_expr(true).parse_expr()?;
|
||||
|
||||
let expr = match expr {
|
||||
box Expr::Ident(ident) => {
|
||||
if eat!(':') {
|
||||
@ -209,6 +228,16 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
expr
|
||||
}
|
||||
};
|
||||
match *expr {
|
||||
Expr::Ident(ref ident) => {
|
||||
if self.input.syntax().typescript() {
|
||||
if let Some(decl) = self.parse_ts_expr_stmt(decorators, ident.clone())? {
|
||||
return Ok(Stmt::Decl(decl));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if eat!(';') {
|
||||
Ok(Stmt::Expr(expr))
|
||||
@ -400,7 +429,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_var_stmt(&mut self, for_loop: bool) -> PResult<'a, VarDecl> {
|
||||
pub(super) fn parse_var_stmt(&mut self, for_loop: bool) -> PResult<'a, VarDecl> {
|
||||
let start = cur_pos!();
|
||||
let kind = match bump!() {
|
||||
tok!("const") => VarDeclKind::Const,
|
||||
@ -422,6 +451,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
Ok(VarDecl {
|
||||
span: span!(start),
|
||||
declare: self.ctx().in_declare,
|
||||
kind,
|
||||
decls,
|
||||
})
|
||||
@ -429,17 +459,57 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
fn parse_var_declarator(&mut self, for_loop: bool) -> PResult<'a, VarDeclarator> {
|
||||
let start = cur_pos!();
|
||||
let name = self.parse_binding_pat_or_ident()?;
|
||||
|
||||
let mut name = self.parse_binding_pat_or_ident()?;
|
||||
|
||||
let definite = if self.input.syntax().typescript() {
|
||||
match name {
|
||||
Pat::Ident(..) => eat!('!'),
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Typescript extension
|
||||
if self.input.syntax().typescript() && is!(':') {
|
||||
let type_annotation = self.try_parse_ts_type_ann()?;
|
||||
match name {
|
||||
Pat::Array(ArrayPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Assign(AssignPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Ident(Ident {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Object(ObjectPat {
|
||||
ref mut type_ann, ..
|
||||
})
|
||||
| Pat::Rest(RestPat {
|
||||
ref mut type_ann, ..
|
||||
}) => {
|
||||
*type_ann = type_annotation;
|
||||
}
|
||||
Pat::Expr(expr) => unreachable!("invalid syntax: Pat(expr): {:?}", expr),
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: This is wrong. Should check in/of only on first loop.
|
||||
let init = if !for_loop || !is_one_of!("in", "of") {
|
||||
if eat!('=') {
|
||||
Some(self.parse_assignment_expr()?)
|
||||
} else {
|
||||
// Destructuring bindings require initializers.
|
||||
match name {
|
||||
Pat::Ident(..) => None,
|
||||
_ => syntax_error!(span!(start), SyntaxError::PatVarWithoutInit),
|
||||
// Destructuring bindings require initializers, but
|
||||
// typescript allows `declare` vars not to have initializers.
|
||||
if self.ctx().in_declare {
|
||||
None
|
||||
} else {
|
||||
match name {
|
||||
Pat::Ident(..) => None,
|
||||
_ => syntax_error!(span!(start), SyntaxError::PatVarWithoutInit),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -451,6 +521,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
name,
|
||||
init,
|
||||
definite,
|
||||
});
|
||||
}
|
||||
|
||||
@ -510,7 +581,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
|
||||
expect!('{');
|
||||
|
||||
let stmts = self.parse_block_body(allow_directives, false, Some(&RBrace))?;
|
||||
let stmts = self.parse_block_body(allow_directives, false, Some(&tok!('}')))?;
|
||||
|
||||
let span = span!(start);
|
||||
Ok(BlockStmt { span, stmts })
|
||||
@ -525,7 +596,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
let body = box if is!("function") {
|
||||
let f = self.parse_fn_decl()?;
|
||||
let f = self.parse_fn_decl(vec![])?;
|
||||
match f {
|
||||
Decl::Fn(FnDecl {
|
||||
function:
|
||||
@ -710,12 +781,16 @@ impl IsDirective for Stmt {
|
||||
}
|
||||
|
||||
pub(super) trait StmtLikeParser<'a, Type: IsDirective> {
|
||||
fn handle_import_export(&mut self, top_level: bool) -> PResult<'a, Type>;
|
||||
fn handle_import_export(
|
||||
&mut self,
|
||||
top_level: bool,
|
||||
decorators: Vec<Decorator>,
|
||||
) -> PResult<'a, Type>;
|
||||
}
|
||||
|
||||
#[parser]
|
||||
impl<'a, I: Input> StmtLikeParser<'a, Stmt> for Parser<'a, I> {
|
||||
fn handle_import_export(&mut self, top_level: bool) -> PResult<'a, Stmt> {
|
||||
fn handle_import_export(&mut self, top_level: bool, _: Vec<Decorator>) -> PResult<'a, Stmt> {
|
||||
syntax_error!(SyntaxError::ImportExportInScript);
|
||||
}
|
||||
}
|
||||
@ -723,13 +798,24 @@ impl<'a, I: Input> StmtLikeParser<'a, Stmt> for Parser<'a, I> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::EsNextConfig;
|
||||
use swc_common::DUMMY_SP as span;
|
||||
|
||||
fn stmt(s: &'static str) -> Stmt {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_stmt(true))
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_stmt(true).map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
fn expr(s: &'static str) -> Box<Expr> {
|
||||
test_parser(s, Syntax::Es2019, |p| p.parse_expr())
|
||||
test_parser(s, Syntax::Es, |p| {
|
||||
p.parse_expr().map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -753,8 +839,10 @@ mod tests {
|
||||
span,
|
||||
props: vec![ObjectPatProp::Rest(RestPat {
|
||||
dot3_token: span,
|
||||
arg: box Pat::Ident(Ident::new("a34".into(), span))
|
||||
})]
|
||||
arg: box Pat::Ident(Ident::new("a34".into(), span)),
|
||||
type_ann: None
|
||||
})],
|
||||
type_ann: None,
|
||||
})
|
||||
.into(),
|
||||
body: BlockStmt {
|
||||
@ -791,16 +879,12 @@ mod tests {
|
||||
decls: vec![VarDeclarator {
|
||||
span,
|
||||
init: None,
|
||||
name: Pat::Ident(Ident {
|
||||
span,
|
||||
sym: "a".into()
|
||||
})
|
||||
name: Pat::Ident(Ident::new("a".into(), span)),
|
||||
definite: false,
|
||||
}],
|
||||
declare: false,
|
||||
}),
|
||||
right: box Expr::Ident(Ident {
|
||||
span,
|
||||
sym: "b".into()
|
||||
}),
|
||||
right: box Expr::Ident(Ident::new("b".into(), span)),
|
||||
|
||||
body: box Stmt::Empty(EmptyStmt { span })
|
||||
})
|
||||
@ -839,4 +923,48 @@ mod tests {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_decorator() {
|
||||
assert_eq_ignore_span!(
|
||||
test_parser(
|
||||
"
|
||||
@decorator
|
||||
@dec2
|
||||
class Foo {}
|
||||
",
|
||||
Syntax::EsNext(EsNextConfig {
|
||||
decorators: true,
|
||||
..Default::default()
|
||||
}),
|
||||
|p| p.parse_stmt_list_item(true).map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
}),
|
||||
),
|
||||
Stmt::Decl(Decl::Class(ClassDecl {
|
||||
ident: Ident::new("Foo".into(), span),
|
||||
class: Class {
|
||||
span,
|
||||
decorators: vec![
|
||||
Decorator {
|
||||
span,
|
||||
expr: expr("decorator")
|
||||
},
|
||||
Decorator {
|
||||
span,
|
||||
expr: expr("dec2")
|
||||
}
|
||||
],
|
||||
super_class: None,
|
||||
implements: vec![],
|
||||
body: vec![],
|
||||
is_abstract: false,
|
||||
super_type_params: None,
|
||||
type_params: None,
|
||||
},
|
||||
declare: false,
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,14 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!("import");
|
||||
|
||||
if self.input.syntax().typescript() {
|
||||
if is!(IdentRef) && peeked_is!('=') {
|
||||
return self
|
||||
.parse_ts_import_equals_decl(start, false)
|
||||
.map(From::from);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle import 'mod.js'
|
||||
let str_start = cur_pos!();
|
||||
match *cur!(false)? {
|
||||
@ -126,10 +134,64 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
self.with_ctx(ctx).parse_binding_ident()
|
||||
}
|
||||
|
||||
fn parse_export(&mut self) -> PResult<'a, ModuleDecl> {
|
||||
fn parse_export(&mut self, decorators: Vec<Decorator>) -> PResult<'a, ModuleDecl> {
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!("export");
|
||||
|
||||
// "export declare" is equivalent to just "export".
|
||||
let declare = self.input.syntax().typescript() && eat!("declare");
|
||||
|
||||
if declare {
|
||||
// TODO: Remove
|
||||
if let Some(decl) = self.try_parse_ts_declare(start, decorators.clone())? {
|
||||
return Ok(ModuleDecl::ExportDecl(decl));
|
||||
}
|
||||
}
|
||||
|
||||
if self.input.syntax().typescript() && is!(IdentName) {
|
||||
let sym = match *cur!(true)? {
|
||||
Token::Word(ref w) => w.clone().into(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
// TODO: remove clone
|
||||
if let Some(decl) = self.try_parse_ts_export_decl(decorators.clone(), sym)? {
|
||||
return Ok(ModuleDecl::ExportDecl(decl));
|
||||
}
|
||||
}
|
||||
|
||||
if self.input.syntax().typescript() {
|
||||
if eat!("import") {
|
||||
// export import A = B
|
||||
return self
|
||||
.parse_ts_import_equals_decl(start, /* is_export */ true)
|
||||
.map(From::from);
|
||||
}
|
||||
|
||||
if eat!('=') {
|
||||
// `export = x;`
|
||||
let expr = self.parse_expr()?;
|
||||
expect!(';');
|
||||
return Ok(TsExportAssignment {
|
||||
span: span!(start),
|
||||
expr,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
if eat!("as") {
|
||||
// `export as namespace A;`
|
||||
// See `parseNamespaceExportDeclaration` in TypeScript's own parser
|
||||
expect!("namespace");
|
||||
let id = self.parse_ident(false, false)?;
|
||||
expect!(';');
|
||||
return Ok(TsNamespaceExportDecl {
|
||||
span: span!(start),
|
||||
id,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
|
||||
if eat!('*') {
|
||||
let src = self.parse_from_clause_and_semi()?;
|
||||
return Ok(ModuleDecl::ExportAll(ExportAll {
|
||||
@ -139,15 +201,35 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
|
||||
if eat!("default") {
|
||||
if self.input.syntax().typescript() {
|
||||
if is!("abstract") && peeked_is!("class") {
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!("abstract");
|
||||
let mut class = self.parse_default_class(decorators)?;
|
||||
match class {
|
||||
ExportDefaultDecl::Class(ClassExpr { ref mut class, .. }) => {
|
||||
class.is_abstract = true
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
return Ok(class.into());
|
||||
}
|
||||
|
||||
if eat!("interface") {
|
||||
let decl = self.parse_ts_interface_decl().map(Decl::from)?;
|
||||
return Ok(decl.into());
|
||||
}
|
||||
}
|
||||
|
||||
let decl = if is!("class") {
|
||||
self.parse_default_class()?
|
||||
self.parse_default_class(decorators)?
|
||||
} else if is!("async")
|
||||
&& peeked_is!("function")
|
||||
&& !self.input.has_linebreak_between_cur_and_peeked()
|
||||
{
|
||||
self.parse_default_async_fn()?
|
||||
self.parse_default_async_fn(decorators)?
|
||||
} else if is!("function") {
|
||||
self.parse_default_fn()?
|
||||
self.parse_default_fn(decorators)?
|
||||
} else {
|
||||
let expr = self.include_in_expr(true).parse_assignment_expr()?;
|
||||
expect!(';');
|
||||
@ -158,14 +240,22 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
}
|
||||
|
||||
let decl = if is!("class") {
|
||||
self.parse_class_decl()?
|
||||
self.parse_class_decl(decorators)?
|
||||
} else if is!("async")
|
||||
&& peeked_is!("function")
|
||||
&& !self.input.has_linebreak_between_cur_and_peeked()
|
||||
{
|
||||
self.parse_async_fn_decl()?
|
||||
self.parse_async_fn_decl(decorators)?
|
||||
} else if is!("function") {
|
||||
self.parse_fn_decl()?
|
||||
self.parse_fn_decl(decorators)?
|
||||
} else if self.input.syntax().typescript() && is!("const") && peeked_is!("enum") {
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!("const");
|
||||
assert_and_bump!("enum");
|
||||
return self
|
||||
.parse_ts_enum_decl(start, /* is_const */ true)
|
||||
.map(Decl::from)
|
||||
.map(ModuleDecl::from);
|
||||
} else if is!("var")
|
||||
|| is!("const")
|
||||
|| (is!("let")
|
||||
@ -265,7 +355,11 @@ impl IsDirective for ModuleItem {
|
||||
|
||||
#[parser]
|
||||
impl<'a, I: Input> StmtLikeParser<'a, ModuleItem> for Parser<'a, I> {
|
||||
fn handle_import_export(&mut self, top_level: bool) -> PResult<'a, ModuleItem> {
|
||||
fn handle_import_export(
|
||||
&mut self,
|
||||
top_level: bool,
|
||||
decorators: Vec<Decorator>,
|
||||
) -> PResult<'a, ModuleItem> {
|
||||
if !top_level {
|
||||
syntax_error!(SyntaxError::NonTopLevelImportExport);
|
||||
}
|
||||
@ -274,7 +368,7 @@ impl<'a, I: Input> StmtLikeParser<'a, ModuleItem> for Parser<'a, I> {
|
||||
let decl = if is!("import") {
|
||||
self.parse_import()?
|
||||
} else if is!("export") {
|
||||
self.parse_export()?
|
||||
self.parse_export(decorators)?
|
||||
} else {
|
||||
unreachable!(
|
||||
"handle_import_export should not be called if current token isn't import nor \
|
||||
|
2035
ecmascript/parser/src/parser/typescript.rs
Normal file
2035
ecmascript/parser/src/parser/typescript.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -85,6 +85,15 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
self.with_ctx(ctx)
|
||||
}
|
||||
|
||||
/// Original context is restored when returned guard is dropped.
|
||||
pub(super) fn in_type<'w>(&'w mut self) -> WithCtx<'w, 'a, I> {
|
||||
let ctx = Context {
|
||||
in_type: true,
|
||||
..self.ctx()
|
||||
};
|
||||
self.with_ctx(ctx)
|
||||
}
|
||||
|
||||
/// Original context is restored when returned guard is dropped.
|
||||
pub(super) fn include_in_expr<'w>(&'w mut self, include_in_expr: bool) -> WithCtx<'w, 'a, I> {
|
||||
let ctx = Context {
|
||||
@ -170,7 +179,8 @@ pub(super) trait ExprExt {
|
||||
| Expr::Object(..)
|
||||
| Expr::Fn(..)
|
||||
| Expr::Class(..)
|
||||
| Expr::Tpl(..) => false,
|
||||
| Expr::Tpl(..)
|
||||
| Expr::TaggedTpl(..) => false,
|
||||
Expr::Paren(ParenExpr { ref expr, .. }) => {
|
||||
expr.is_valid_simple_assignment_target(strict)
|
||||
}
|
||||
@ -199,6 +209,14 @@ pub(super) trait ExprExt {
|
||||
| Expr::JSXEmpty(..)
|
||||
| Expr::JSXElement(..)
|
||||
| Expr::JSXFragment(..) => false,
|
||||
|
||||
// typescript
|
||||
Expr::TsNonNull(TsNonNullExpr { ref expr, .. })
|
||||
| Expr::TsTypeAssertion(TsTypeAssertion { ref expr, .. })
|
||||
| Expr::TsTypeCast(TsTypeCastExpr { ref expr, .. })
|
||||
| Expr::TsAs(TsAsExpr { ref expr, .. }) => {
|
||||
expr.is_valid_simple_assignment_target(strict)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Ported from [babel/bablyon][]
|
||||
//!
|
||||
//! [babel/bablyon]:https://github.com/babel/babel/blob/2d378d076eb0c5fe63234a8b509886005c01d7ee/packages/babylon/src/tokenizer/types.js
|
||||
pub(crate) use self::{AssignOpToken::*, BinOpToken::*, Keyword::*, Token::*, Word::*};
|
||||
pub(crate) use self::{AssignOpToken::*, BinOpToken::*, Keyword::*, Token::*};
|
||||
use crate::error::Error;
|
||||
pub(crate) use ast::AssignOp as AssignOpToken;
|
||||
use ast::{BinaryOp, Str};
|
||||
@ -23,6 +23,9 @@ pub(crate) enum Token {
|
||||
#[kind(before_expr)]
|
||||
Arrow,
|
||||
|
||||
/// '#'
|
||||
Hash,
|
||||
|
||||
/// '@'
|
||||
At,
|
||||
/// '.'
|
||||
@ -223,9 +226,9 @@ pub enum Word {
|
||||
impl From<JsWord> for Word {
|
||||
fn from(i: JsWord) -> Self {
|
||||
match i {
|
||||
js_word!("null") => Null,
|
||||
js_word!("true") => True,
|
||||
js_word!("false") => False,
|
||||
js_word!("null") => Word::Null,
|
||||
js_word!("true") => Word::True,
|
||||
js_word!("false") => Word::False,
|
||||
js_word!("await") => Await.into(),
|
||||
js_word!("break") => Break.into(),
|
||||
js_word!("case") => Case.into(),
|
||||
@ -261,20 +264,20 @@ impl From<JsWord> for Word {
|
||||
js_word!("typeof") => TypeOf.into(),
|
||||
js_word!("void") => Void.into(),
|
||||
js_word!("delete") => Delete.into(),
|
||||
_ => Ident(i),
|
||||
_ => Word::Ident(i),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<Keyword> for Word {
|
||||
fn from(kwd: Keyword) -> Self {
|
||||
Keyword(kwd)
|
||||
Word::Keyword(kwd)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Word> for JsWord {
|
||||
fn from(w: Word) -> Self {
|
||||
match w {
|
||||
Keyword(k) => match k {
|
||||
Word::Keyword(k) => match k {
|
||||
Await => js_word!("await"),
|
||||
Break => js_word!("break"),
|
||||
Case => js_word!("case"),
|
||||
@ -328,11 +331,11 @@ impl From<Word> for JsWord {
|
||||
Delete => js_word!("delete"),
|
||||
},
|
||||
|
||||
Null => js_word!("null"),
|
||||
True => js_word!("true"),
|
||||
False => js_word!("false"),
|
||||
Word::Null => js_word!("null"),
|
||||
Word::True => js_word!("true"),
|
||||
Word::False => js_word!("false"),
|
||||
|
||||
Ident(w) => w,
|
||||
Word::Ident(w) => w,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,7 +537,7 @@ impl Token {
|
||||
// This is required to recognize `let let` in strict mode.
|
||||
tok!("let") => true,
|
||||
|
||||
tok!('{') | tok!('[') | Word(Ident(..)) | tok!("yield") | tok!("await") => true,
|
||||
tok!('{') | tok!('[') | Word(Word::Ident(..)) | tok!("yield") | tok!("await") => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ use std::{
|
||||
io::{self, Read},
|
||||
path::Path,
|
||||
};
|
||||
use swc_common::{Fold, FoldWith, Span};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_parser::{PResult, Parser, Session, SourceFileInput, Syntax};
|
||||
use test::{test_main, Options, ShouldPanic::No, TestDesc, TestDescAndFn, TestFn, TestName};
|
||||
@ -163,19 +162,20 @@ fn with_parser<F, Ret>(file_name: &Path, f: F) -> Result<Ret, StdErr>
|
||||
where
|
||||
F: for<'a> FnOnce(&mut Parser<'a, SourceFileInput>) -> PResult<'a, Ret>,
|
||||
{
|
||||
let output = ::testing::run_test(|cm, handler| {
|
||||
let output = ::testing::run_test(false, |cm, handler| {
|
||||
let fm = cm
|
||||
.load_file(file_name)
|
||||
.unwrap_or_else(|e| panic!("failed to load {}: {}", file_name.display(), e));
|
||||
|
||||
let res = f(&mut Parser::new(
|
||||
Session {
|
||||
handler: &handler,
|
||||
cfg: Default::default(),
|
||||
},
|
||||
Session { handler: &handler },
|
||||
Syntax::Jsx,
|
||||
(&*fm).into(),
|
||||
));
|
||||
))
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
});
|
||||
|
||||
res
|
||||
});
|
||||
@ -198,84 +198,3 @@ fn error() {
|
||||
error_tests(&mut tests).unwrap();
|
||||
test_main(&args, tests, Options::new());
|
||||
}
|
||||
|
||||
pub fn normalize<T>(t: T) -> T
|
||||
where
|
||||
Normalizer: Fold<T>,
|
||||
{
|
||||
let mut n = Normalizer;
|
||||
n.fold(t)
|
||||
}
|
||||
|
||||
pub struct Normalizer;
|
||||
impl Fold<Span> for Normalizer {
|
||||
fn fold(&mut self, _: Span) -> Span {
|
||||
Span::default()
|
||||
}
|
||||
}
|
||||
impl Fold<Str> for Normalizer {
|
||||
fn fold(&mut self, s: Str) -> Str {
|
||||
Str {
|
||||
span: Default::default(),
|
||||
has_escape: false,
|
||||
..s
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Fold<Expr> for Normalizer {
|
||||
fn fold(&mut self, e: Expr) -> Expr {
|
||||
let e = e.fold_children(self);
|
||||
|
||||
match e {
|
||||
Expr::Paren(ParenExpr { expr, .. }) => *expr,
|
||||
Expr::New(NewExpr {
|
||||
callee,
|
||||
args: None,
|
||||
span,
|
||||
}) => Expr::New(NewExpr {
|
||||
span,
|
||||
callee,
|
||||
args: Some(vec![]),
|
||||
}),
|
||||
// Flatten comma expressions.
|
||||
Expr::Seq(SeqExpr { mut exprs, span }) => {
|
||||
let need_work = exprs.iter().any(|n| match **n {
|
||||
Expr::Seq(..) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
if need_work {
|
||||
exprs = exprs.into_iter().fold(vec![], |mut v, e| {
|
||||
match *e {
|
||||
Expr::Seq(SeqExpr { exprs, .. }) => v.extend(exprs),
|
||||
_ => v.push(e),
|
||||
}
|
||||
v
|
||||
});
|
||||
}
|
||||
Expr::Seq(SeqExpr { exprs, span })
|
||||
}
|
||||
_ => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<PropName> for Normalizer {
|
||||
fn fold(&mut self, n: PropName) -> PropName {
|
||||
let n = n.fold_children(self);
|
||||
|
||||
match n {
|
||||
PropName::Ident(Ident { sym, .. }) => PropName::Str(Str {
|
||||
span: Default::default(),
|
||||
value: sym,
|
||||
has_escape: false,
|
||||
}),
|
||||
PropName::Num(num) => PropName::Str(Str {
|
||||
span: Default::default(),
|
||||
value: num.to_string().into(),
|
||||
has_escape: false,
|
||||
}),
|
||||
_ => n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXExprContainer(
|
||||
@ -80,9 +83,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
30
|
||||
),
|
||||
@ -90,8 +93,10 @@ Module {
|
||||
31
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -78,9 +81,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
20
|
||||
),
|
||||
@ -88,8 +91,10 @@ Module {
|
||||
23
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXElement(
|
||||
@ -63,9 +66,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
br,
|
||||
Span {
|
||||
Ident {
|
||||
sym: br,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
6
|
||||
),
|
||||
@ -73,8 +76,10 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -86,7 +91,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -120,9 +126,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
37
|
||||
),
|
||||
@ -130,8 +136,10 @@ Module {
|
||||
40
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
LeftRight,
|
||||
Span {
|
||||
Ident {
|
||||
sym: LeftRight,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
left,
|
||||
Span {
|
||||
Ident {
|
||||
sym: left,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
11
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
15
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
JSXElement(
|
||||
@ -86,9 +90,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
17
|
||||
),
|
||||
@ -96,8 +100,10 @@ Module {
|
||||
18
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -109,7 +115,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -130,9 +137,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
right,
|
||||
Span {
|
||||
Ident {
|
||||
sym: right,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
22
|
||||
),
|
||||
@ -140,8 +147,10 @@ Module {
|
||||
27
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
JSXElement(
|
||||
@ -157,9 +166,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
29
|
||||
),
|
||||
@ -167,8 +176,10 @@ Module {
|
||||
30
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -180,7 +191,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -211,9 +223,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
52
|
||||
),
|
||||
@ -221,8 +233,10 @@ Module {
|
||||
53
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -232,7 +246,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -26,9 +26,9 @@ Module {
|
||||
name: JSXMemberExpr(
|
||||
JSXMemberExpr {
|
||||
obj: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -36,12 +36,14 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
prop: Ident(
|
||||
b,
|
||||
Span {
|
||||
prop: Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -49,8 +51,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
@ -63,7 +67,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -80,9 +85,9 @@ Module {
|
||||
name: JSXMemberExpr(
|
||||
JSXMemberExpr {
|
||||
obj: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
7
|
||||
),
|
||||
@ -90,12 +95,14 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
prop: Ident(
|
||||
b,
|
||||
Span {
|
||||
prop: Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -103,8 +110,10 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -28,9 +28,9 @@ Module {
|
||||
obj: JSXMemberExpr(
|
||||
JSXMemberExpr {
|
||||
obj: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -38,12 +38,14 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
prop: Ident(
|
||||
b,
|
||||
Span {
|
||||
prop: Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -51,13 +53,15 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
prop: Ident(
|
||||
c,
|
||||
Span {
|
||||
prop: Ident {
|
||||
sym: c,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
5
|
||||
),
|
||||
@ -65,8 +69,10 @@ Module {
|
||||
6
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
@ -79,7 +85,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -98,9 +105,9 @@ Module {
|
||||
obj: JSXMemberExpr(
|
||||
JSXMemberExpr {
|
||||
obj: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -108,12 +115,14 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
prop: Ident(
|
||||
b,
|
||||
Span {
|
||||
prop: Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
11
|
||||
),
|
||||
@ -121,13 +130,15 @@ Module {
|
||||
12
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
prop: Ident(
|
||||
c,
|
||||
Span {
|
||||
prop: Ident {
|
||||
sym: c,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
@ -135,8 +146,10 @@ Module {
|
||||
14
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -47,9 +47,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
2
|
||||
),
|
||||
@ -57,8 +57,10 @@ Module {
|
||||
5
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -70,7 +72,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -79,9 +82,9 @@ Module {
|
||||
}
|
||||
),
|
||||
right: Ident(
|
||||
Ident(
|
||||
x,
|
||||
Span {
|
||||
Ident {
|
||||
sym: x,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
12
|
||||
),
|
||||
@ -89,8 +92,10 @@ Module {
|
||||
13
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
expr: Ident(
|
||||
Ident(
|
||||
props,
|
||||
Span {
|
||||
Ident {
|
||||
sym: props,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -69,13 +71,16 @@ Module {
|
||||
14
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
expr: Ident(
|
||||
Ident(
|
||||
props,
|
||||
Span {
|
||||
Ident {
|
||||
sym: props,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
14
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
),
|
||||
@ -86,9 +90,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
post,
|
||||
Span {
|
||||
Ident {
|
||||
sym: post,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
16
|
||||
),
|
||||
@ -96,8 +100,10 @@ Module {
|
||||
20
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -121,7 +127,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
pre,
|
||||
Span {
|
||||
Ident {
|
||||
sym: pre,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
5
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -105,9 +109,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
pre2,
|
||||
Span {
|
||||
Ident {
|
||||
sym: pre2,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
19
|
||||
),
|
||||
@ -115,8 +119,10 @@ Module {
|
||||
23
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -151,9 +157,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
expr: Ident(
|
||||
Ident(
|
||||
props,
|
||||
Span {
|
||||
Ident {
|
||||
sym: props,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
40
|
||||
),
|
||||
@ -161,13 +167,16 @@ Module {
|
||||
45
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -182,9 +191,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
49
|
||||
),
|
||||
@ -192,8 +201,10 @@ Module {
|
||||
52
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -25,9 +25,9 @@ Module {
|
||||
opening: JSXOpeningElement {
|
||||
name: JSXNamespacedName(
|
||||
JSXNamespacedName {
|
||||
ns: Ident(
|
||||
n,
|
||||
Span {
|
||||
ns: Ident {
|
||||
sym: n,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -35,11 +35,13 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
name: Ident(
|
||||
a,
|
||||
Span {
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
name: Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -47,8 +49,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
@ -74,9 +78,9 @@ Module {
|
||||
},
|
||||
name: JSXNamespacedName(
|
||||
JSXNamespacedName {
|
||||
ns: Ident(
|
||||
n,
|
||||
Span {
|
||||
ns: Ident {
|
||||
sym: n,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
5
|
||||
),
|
||||
@ -84,11 +88,13 @@ Module {
|
||||
6
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
name: Ident(
|
||||
v,
|
||||
Span {
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
name: Ident {
|
||||
sym: v,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
7
|
||||
),
|
||||
@ -96,15 +102,18 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
value: None
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
aa,
|
||||
Span {
|
||||
Ident {
|
||||
sym: aa,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
5
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Member(
|
||||
@ -98,9 +102,9 @@ Module {
|
||||
},
|
||||
obj: Expr(
|
||||
Ident(
|
||||
Ident(
|
||||
aa,
|
||||
Span {
|
||||
Ident {
|
||||
sym: aa,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
7
|
||||
),
|
||||
@ -108,14 +112,16 @@ Module {
|
||||
9
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
),
|
||||
prop: Ident(
|
||||
Ident(
|
||||
bb,
|
||||
Span {
|
||||
Ident {
|
||||
sym: bb,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
10
|
||||
),
|
||||
@ -123,17 +129,19 @@ Module {
|
||||
12
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
computed: false
|
||||
}
|
||||
)
|
||||
),
|
||||
prop: Ident(
|
||||
Ident(
|
||||
cc,
|
||||
Span {
|
||||
Ident {
|
||||
sym: cc,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
@ -141,8 +149,10 @@ Module {
|
||||
15
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
computed: false
|
||||
}
|
||||
@ -162,9 +172,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
bb,
|
||||
Span {
|
||||
Ident {
|
||||
sym: bb,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
17
|
||||
),
|
||||
@ -172,8 +182,10 @@ Module {
|
||||
19
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Member(
|
||||
@ -201,9 +213,9 @@ Module {
|
||||
},
|
||||
obj: Expr(
|
||||
Ident(
|
||||
Ident(
|
||||
bb,
|
||||
Span {
|
||||
Ident {
|
||||
sym: bb,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
21
|
||||
),
|
||||
@ -211,14 +223,16 @@ Module {
|
||||
23
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
),
|
||||
prop: Ident(
|
||||
Ident(
|
||||
cc,
|
||||
Span {
|
||||
Ident {
|
||||
sym: cc,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
24
|
||||
),
|
||||
@ -226,17 +240,19 @@ Module {
|
||||
26
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
computed: false
|
||||
}
|
||||
)
|
||||
),
|
||||
prop: Ident(
|
||||
Ident(
|
||||
dd,
|
||||
Span {
|
||||
Ident {
|
||||
sym: dd,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
27
|
||||
),
|
||||
@ -244,8 +260,10 @@ Module {
|
||||
29
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
computed: false
|
||||
}
|
||||
@ -254,7 +272,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXElement(
|
||||
@ -270,9 +289,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
32
|
||||
),
|
||||
@ -280,8 +299,10 @@ Module {
|
||||
35
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -293,7 +314,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXExprContainer(
|
||||
@ -312,9 +334,9 @@ Module {
|
||||
},
|
||||
obj: Expr(
|
||||
Ident(
|
||||
Ident(
|
||||
aa,
|
||||
Span {
|
||||
Ident {
|
||||
sym: aa,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
37
|
||||
),
|
||||
@ -322,14 +344,16 @@ Module {
|
||||
39
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
),
|
||||
prop: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
40
|
||||
),
|
||||
@ -337,8 +361,10 @@ Module {
|
||||
41
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
computed: false
|
||||
}
|
||||
@ -359,9 +385,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
44
|
||||
),
|
||||
@ -369,8 +395,10 @@ Module {
|
||||
47
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -389,9 +417,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
50
|
||||
),
|
||||
@ -399,8 +427,10 @@ Module {
|
||||
51
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
expr: Ident(
|
||||
Ident(
|
||||
c,
|
||||
Span {
|
||||
Ident {
|
||||
sym: c,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -69,13 +71,16 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -96,9 +101,9 @@ Module {
|
||||
JSXSpreadChild(
|
||||
JSXSpreadChild {
|
||||
expr: Ident(
|
||||
Ident(
|
||||
children,
|
||||
Span {
|
||||
Ident {
|
||||
sym: children,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
17
|
||||
),
|
||||
@ -106,8 +111,10 @@ Module {
|
||||
25
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
),
|
||||
@ -115,9 +122,9 @@ Module {
|
||||
JSXExprContainer {
|
||||
expr: Expr(
|
||||
Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
27
|
||||
),
|
||||
@ -125,8 +132,10 @@ Module {
|
||||
28
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -134,9 +143,9 @@ Module {
|
||||
JSXSpreadChild(
|
||||
JSXSpreadChild {
|
||||
expr: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
33
|
||||
),
|
||||
@ -144,8 +153,10 @@ Module {
|
||||
34
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -162,9 +173,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
37
|
||||
),
|
||||
@ -172,8 +183,10 @@ Module {
|
||||
40
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -60,9 +62,9 @@ Module {
|
||||
},
|
||||
name: JSXNamespacedName(
|
||||
JSXNamespacedName {
|
||||
ns: Ident(
|
||||
n,
|
||||
Span {
|
||||
ns: Ident {
|
||||
sym: n,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -70,11 +72,13 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
name: Ident(
|
||||
foo,
|
||||
Span {
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
name: Ident {
|
||||
sym: foo,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
5
|
||||
),
|
||||
@ -82,8 +86,10 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
@ -108,7 +114,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -130,9 +137,9 @@ Module {
|
||||
JSXExprContainer {
|
||||
expr: Expr(
|
||||
Ident(
|
||||
Ident(
|
||||
value,
|
||||
Span {
|
||||
Ident {
|
||||
sym: value,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
17
|
||||
),
|
||||
@ -140,8 +147,10 @@ Module {
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -174,9 +183,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
25
|
||||
),
|
||||
@ -184,8 +193,10 @@ Module {
|
||||
26
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -197,7 +208,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXElement(
|
||||
@ -213,9 +225,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
c,
|
||||
Span {
|
||||
Ident {
|
||||
sym: c,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
28
|
||||
),
|
||||
@ -223,8 +235,10 @@ Module {
|
||||
29
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -236,7 +250,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -255,9 +270,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
34
|
||||
),
|
||||
@ -265,8 +280,10 @@ Module {
|
||||
35
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -285,9 +302,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
38
|
||||
),
|
||||
@ -295,8 +312,10 @@ Module {
|
||||
39
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -105,9 +109,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
c,
|
||||
Span {
|
||||
Ident {
|
||||
sym: c,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
11
|
||||
),
|
||||
@ -115,8 +119,10 @@ Module {
|
||||
12
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -151,9 +157,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
d,
|
||||
Span {
|
||||
Ident {
|
||||
sym: d,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
17
|
||||
),
|
||||
@ -161,8 +167,10 @@ Module {
|
||||
18
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -197,9 +205,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
e,
|
||||
Span {
|
||||
Ident {
|
||||
sym: e,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
27
|
||||
),
|
||||
@ -207,8 +215,10 @@ Module {
|
||||
28
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -232,7 +242,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
日本語,
|
||||
Span {
|
||||
Ident {
|
||||
sym: 日本語,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -62,9 +65,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
日本語,
|
||||
Span {
|
||||
Ident {
|
||||
sym: 日本語,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
@ -72,8 +75,10 @@ Module {
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
AbC-def,
|
||||
Span {
|
||||
Ident {
|
||||
sym: AbC-def,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
test,
|
||||
Span {
|
||||
Ident {
|
||||
sym: test,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
11
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
15
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Lit(
|
||||
@ -94,7 +98,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -137,9 +142,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
AbC-def,
|
||||
Span {
|
||||
Ident {
|
||||
sym: AbC-def,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
43
|
||||
),
|
||||
@ -147,8 +152,10 @@ Module {
|
||||
50
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -59,9 +61,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
b,
|
||||
Span {
|
||||
Ident {
|
||||
sym: b,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -69,8 +71,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
value: Some(
|
||||
Cond(
|
||||
@ -85,9 +89,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
test: Ident(
|
||||
Ident(
|
||||
x,
|
||||
Span {
|
||||
Ident {
|
||||
sym: x,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
6
|
||||
),
|
||||
@ -95,8 +99,10 @@ Module {
|
||||
7
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
cons: JSXElement(
|
||||
JSXElement {
|
||||
@ -111,9 +117,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
c,
|
||||
Span {
|
||||
Ident {
|
||||
sym: c,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
11
|
||||
),
|
||||
@ -121,8 +127,10 @@ Module {
|
||||
12
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -134,7 +142,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -153,9 +162,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
d,
|
||||
Span {
|
||||
Ident {
|
||||
sym: d,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
19
|
||||
),
|
||||
@ -163,8 +172,10 @@ Module {
|
||||
20
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -176,7 +187,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -188,7 +200,8 @@ Module {
|
||||
}
|
||||
)
|
||||
],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
|
@ -13,9 +13,9 @@ Module {
|
||||
Decl(
|
||||
Fn(
|
||||
FnDecl {
|
||||
ident: Ident(
|
||||
x,
|
||||
Span {
|
||||
ident: Ident {
|
||||
sym: x,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -23,10 +23,14 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
declare: false,
|
||||
function: Function {
|
||||
params: [],
|
||||
decorators: [],
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
0
|
||||
@ -36,109 +40,120 @@ Module {
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
body: BlockStmt {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
hi: BytePos(
|
||||
34
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
stmts: [
|
||||
Decl(
|
||||
Var(
|
||||
VarDecl {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
17
|
||||
),
|
||||
hi: BytePos(
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
kind: "let",
|
||||
decls: [
|
||||
VarDeclarator {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
21
|
||||
),
|
||||
hi: BytePos(
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
x,
|
||||
Span {
|
||||
lo: BytePos(
|
||||
21
|
||||
),
|
||||
hi: BytePos(
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
),
|
||||
init: None
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
),
|
||||
Expr(
|
||||
JSXElement(
|
||||
JSXElement {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
25
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
),
|
||||
hi: BytePos(
|
||||
29
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
),
|
||||
body: Some(
|
||||
BlockStmt {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
hi: BytePos(
|
||||
34
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
stmts: [
|
||||
Decl(
|
||||
Var(
|
||||
VarDecl {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
17
|
||||
),
|
||||
hi: BytePos(
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
kind: "let",
|
||||
declare: false,
|
||||
decls: [
|
||||
VarDeclarator {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
21
|
||||
),
|
||||
hi: BytePos(
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident {
|
||||
sym: x,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
21
|
||||
),
|
||||
hi: BytePos(
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
init: None,
|
||||
definite: false
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
),
|
||||
Expr(
|
||||
JSXElement(
|
||||
JSXElement {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
25
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
}
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
),
|
||||
hi: BytePos(
|
||||
29
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
),
|
||||
is_generator: false,
|
||||
is_async: false
|
||||
is_async: false,
|
||||
type_params: None,
|
||||
return_type: None
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXExprContainer(
|
||||
@ -80,9 +83,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
7
|
||||
),
|
||||
@ -90,8 +93,10 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -78,9 +81,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
14
|
||||
),
|
||||
@ -88,8 +91,10 @@ Module {
|
||||
15
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -66,9 +66,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
span,
|
||||
Span {
|
||||
Ident {
|
||||
sym: span,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
7
|
||||
),
|
||||
@ -76,8 +76,10 @@ Module {
|
||||
11
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -89,7 +91,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -128,9 +131,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
span,
|
||||
Span {
|
||||
Ident {
|
||||
sym: span,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
24
|
||||
),
|
||||
@ -138,8 +141,10 @@ Module {
|
||||
28
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -177,9 +182,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
33
|
||||
),
|
||||
@ -187,8 +192,10 @@ Module {
|
||||
36
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -200,7 +207,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -231,9 +239,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
42
|
||||
),
|
||||
@ -241,8 +249,10 @@ Module {
|
||||
45
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -66,9 +66,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
34
|
||||
),
|
||||
@ -76,8 +76,10 @@ Module {
|
||||
37
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -89,7 +91,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -104,9 +107,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
40
|
||||
),
|
||||
@ -114,8 +117,10 @@ Module {
|
||||
43
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -153,9 +158,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
48
|
||||
),
|
||||
@ -163,8 +168,10 @@ Module {
|
||||
51
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -176,7 +183,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -191,9 +199,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
54
|
||||
),
|
||||
@ -201,8 +209,10 @@ Module {
|
||||
57
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -47,9 +47,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
3
|
||||
),
|
||||
@ -57,8 +57,10 @@ Module {
|
||||
6
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -70,7 +72,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -101,9 +104,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
div,
|
||||
Span {
|
||||
Ident {
|
||||
sym: div,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
19
|
||||
),
|
||||
@ -111,8 +114,10 @@ Module {
|
||||
22
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
var,
|
||||
Span {
|
||||
Ident {
|
||||
sym: var,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -62,9 +65,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
var,
|
||||
Span {
|
||||
Ident {
|
||||
sym: var,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
7
|
||||
),
|
||||
@ -72,8 +75,10 @@ Module {
|
||||
10
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -25,9 +25,9 @@ Module {
|
||||
opening: JSXOpeningElement {
|
||||
name: JSXNamespacedName(
|
||||
JSXNamespacedName {
|
||||
ns: Ident(
|
||||
Foo,
|
||||
Span {
|
||||
ns: Ident {
|
||||
sym: Foo,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -35,11 +35,13 @@ Module {
|
||||
4
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
name: Ident(
|
||||
Bar,
|
||||
Span {
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
name: Ident {
|
||||
sym: Bar,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
5
|
||||
),
|
||||
@ -47,8 +49,10 @@ Module {
|
||||
8
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
@ -61,7 +65,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: true
|
||||
self_closing: true,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: None
|
||||
@ -85,9 +90,9 @@ Module {
|
||||
opening: JSXOpeningElement {
|
||||
name: JSXNamespacedName(
|
||||
JSXNamespacedName {
|
||||
ns: Ident(
|
||||
Foo,
|
||||
Span {
|
||||
ns: Ident {
|
||||
sym: Foo,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
14
|
||||
),
|
||||
@ -95,11 +100,13 @@ Module {
|
||||
17
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
name: Ident(
|
||||
Bar,
|
||||
Span {
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
name: Ident {
|
||||
sym: Bar,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
18
|
||||
),
|
||||
@ -107,8 +114,10 @@ Module {
|
||||
21
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
@ -121,7 +130,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
@ -137,9 +147,9 @@ Module {
|
||||
},
|
||||
name: JSXNamespacedName(
|
||||
JSXNamespacedName {
|
||||
ns: Ident(
|
||||
Foo,
|
||||
Span {
|
||||
ns: Ident {
|
||||
sym: Foo,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
24
|
||||
),
|
||||
@ -147,11 +157,13 @@ Module {
|
||||
27
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
name: Ident(
|
||||
Bar,
|
||||
Span {
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
name: Ident {
|
||||
sym: Bar,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
28
|
||||
),
|
||||
@ -159,8 +171,10 @@ Module {
|
||||
31
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -78,9 +81,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
@ -88,8 +91,10 @@ Module {
|
||||
14
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -24,9 +24,9 @@ Module {
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
1
|
||||
),
|
||||
@ -34,8 +34,10 @@ Module {
|
||||
2
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
@ -47,7 +49,8 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [
|
||||
JSXText(
|
||||
@ -78,9 +81,9 @@ Module {
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
A,
|
||||
Span {
|
||||
Ident {
|
||||
sym: A,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
14
|
||||
),
|
||||
@ -88,8 +91,10 @@ Module {
|
||||
15
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -13,9 +13,9 @@ Module {
|
||||
Decl(
|
||||
Fn(
|
||||
FnDecl {
|
||||
ident: Ident(
|
||||
it,
|
||||
Span {
|
||||
ident: Ident {
|
||||
sym: it,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
9
|
||||
),
|
||||
@ -23,10 +23,14 @@ Module {
|
||||
11
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
),
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
},
|
||||
declare: false,
|
||||
function: Function {
|
||||
params: [],
|
||||
decorators: [],
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
0
|
||||
@ -36,107 +40,116 @@ Module {
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
body: BlockStmt {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
hi: BytePos(
|
||||
35
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
stmts: [
|
||||
Expr(
|
||||
Yield(
|
||||
YieldExpr {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
19
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
arg: Some(
|
||||
JSXElement(
|
||||
JSXElement {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
25
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
),
|
||||
hi: BytePos(
|
||||
27
|
||||
),
|
||||
ctxt: #0
|
||||
}
|
||||
)
|
||||
),
|
||||
body: Some(
|
||||
BlockStmt {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
13
|
||||
),
|
||||
hi: BytePos(
|
||||
35
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
stmts: [
|
||||
Expr(
|
||||
Yield(
|
||||
YieldExpr {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
19
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
arg: Some(
|
||||
JSXElement(
|
||||
JSXElement {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
25
|
||||
),
|
||||
hi: BytePos(
|
||||
28
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
attrs: [],
|
||||
self_closing: false
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
JSXClosingElement {
|
||||
opening: JSXOpeningElement {
|
||||
name: Ident(
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
26
|
||||
),
|
||||
hi: BytePos(
|
||||
27
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
),
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
30
|
||||
26
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
28
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident(
|
||||
a,
|
||||
Span {
|
||||
lo: BytePos(
|
||||
30
|
||||
),
|
||||
hi: BytePos(
|
||||
31
|
||||
),
|
||||
ctxt: #0
|
||||
attrs: [],
|
||||
self_closing: false,
|
||||
type_args: None
|
||||
},
|
||||
children: [],
|
||||
closing: Some(
|
||||
JSXClosingElement {
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
30
|
||||
),
|
||||
hi: BytePos(
|
||||
32
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
name: Ident(
|
||||
Ident {
|
||||
sym: a,
|
||||
span: Span {
|
||||
lo: BytePos(
|
||||
30
|
||||
),
|
||||
hi: BytePos(
|
||||
31
|
||||
),
|
||||
ctxt: #0
|
||||
},
|
||||
type_ann: None,
|
||||
optional: false
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
delegate: false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
delegate: false
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
),
|
||||
is_generator: true,
|
||||
is_async: false
|
||||
is_async: false,
|
||||
type_params: None,
|
||||
return_type: None
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -4,9 +4,3 @@ error: Unexpected eof
|
||||
1 | class
|
||||
| ^
|
||||
|
||||
error: Expected ident
|
||||
--> $DIR/tests/test262-parser/fail/0889113e04d3203f.js:1:1
|
||||
|
|
||||
1 | class
|
||||
| ^^^^^
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user