mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
swc_ecma_ast:
- Split class member / property into separate types
This commit is contained in:
parent
6275831b30
commit
a46804ab48
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_ast"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
authors = ["강동윤 <kdy1@outlook.kr>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
|
@ -47,7 +47,7 @@ pub struct Class {
|
||||
pub enum ClassMember {
|
||||
Constructor(Constructor),
|
||||
/// `es2015`
|
||||
Method(Method),
|
||||
Method(ClassMethod),
|
||||
PrivateMethod(PrivateMethod),
|
||||
/// stage 0 / Typescript
|
||||
ClassProp(ClassProp),
|
||||
@ -55,57 +55,90 @@ pub enum ClassMember {
|
||||
TsIndexSignature(TsIndexSignature),
|
||||
}
|
||||
|
||||
pub type ClassProp = ClassProperty<Box<Expr>>;
|
||||
pub type PrivateProp = ClassProperty<PrivateName>;
|
||||
macro_rules! property {
|
||||
($name:ident, $ty:literal, $KEY:ty) => {
|
||||
#[ast_node($ty)]
|
||||
pub struct $name {
|
||||
#[serde(default)]
|
||||
pub span: Span,
|
||||
|
||||
#[ast_node]
|
||||
#[derive(Deserialize)]
|
||||
pub struct ClassProperty<K> {
|
||||
#[serde(default)]
|
||||
pub span: Span,
|
||||
pub key: $KEY,
|
||||
|
||||
#[cfg_attr(feature = "fold", fold(bound))]
|
||||
pub key: K,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub value: Option<Box<Expr>>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub value: Option<Box<Expr>>,
|
||||
#[serde(
|
||||
default,
|
||||
rename = "typeAnnotation",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
|
||||
#[serde(
|
||||
default,
|
||||
rename = "typeAnnotation",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub type_ann: Option<TsTypeAnn>,
|
||||
#[serde(default)]
|
||||
pub is_static: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub is_static: bool,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub decorators: Vec<Decorator>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub decorators: Vec<Decorator>,
|
||||
#[serde(default)]
|
||||
pub computed: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub computed: bool,
|
||||
/// Typescript extension.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub accessibility: Option<Accessibility>,
|
||||
|
||||
/// Typescript extension.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub accessibility: Option<Accessibility>,
|
||||
/// Typescript extension.
|
||||
#[serde(default)]
|
||||
pub is_abstract: bool,
|
||||
|
||||
/// Typescript extension.
|
||||
#[serde(default)]
|
||||
pub is_abstract: bool,
|
||||
#[serde(default)]
|
||||
pub is_optional: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub is_optional: bool,
|
||||
#[serde(default)]
|
||||
pub readonly: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub readonly: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub definite: bool,
|
||||
#[serde(default)]
|
||||
pub definite: bool,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub type Method = ClassMethod<PropName>;
|
||||
pub type PrivateMethod = ClassMethod<PrivateName>;
|
||||
property!(ClassProp, "ClassProperty", Box<Expr>);
|
||||
property!(PrivateProp, "PrivateProperty", PrivateName);
|
||||
|
||||
macro_rules! method {
|
||||
($name:ident, $ty:literal, $KEY:ty) => {
|
||||
#[ast_node($ty)]
|
||||
pub struct $name {
|
||||
#[serde(default)]
|
||||
pub span: Span,
|
||||
|
||||
pub key: $KEY,
|
||||
|
||||
pub function: Function,
|
||||
|
||||
#[cfg_attr(feature = "fold", fold(ignore))]
|
||||
pub kind: MethodKind,
|
||||
|
||||
#[serde(default)]
|
||||
pub is_static: bool,
|
||||
|
||||
/// Typescript extension.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub accessibility: Option<Accessibility>,
|
||||
|
||||
/// Typescript extension.
|
||||
#[serde(default)]
|
||||
pub is_abstract: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub is_optional: bool,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
method!(ClassMethod, "ClassMethod", PropName);
|
||||
method!(PrivateMethod, "PrivateMethod", PrivateName);
|
||||
|
||||
#[ast_node("Constructor")]
|
||||
pub struct Constructor {
|
||||
@ -126,34 +159,6 @@ pub struct Constructor {
|
||||
pub is_optional: bool,
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
#[derive(Deserialize)]
|
||||
pub struct ClassMethod<K> {
|
||||
#[serde(default)]
|
||||
pub span: Span,
|
||||
#[cfg_attr(feature = "fold", fold(bound))]
|
||||
pub key: K,
|
||||
|
||||
pub function: Function,
|
||||
|
||||
#[cfg_attr(feature = "fold", fold(ignore))]
|
||||
pub kind: MethodKind,
|
||||
|
||||
#[serde(default)]
|
||||
pub is_static: bool,
|
||||
|
||||
/// Typescript extension.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub accessibility: Option<Accessibility>,
|
||||
|
||||
/// Typescript extension.
|
||||
#[serde(default)]
|
||||
pub is_abstract: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub is_optional: bool,
|
||||
}
|
||||
|
||||
#[ast_node("Decorator")]
|
||||
pub struct Decorator {
|
||||
#[serde(default)]
|
||||
|
@ -17,8 +17,8 @@ extern crate swc_common;
|
||||
|
||||
pub use self::{
|
||||
class::{
|
||||
Class, ClassMember, ClassMethod, ClassProp, ClassProperty, Constructor, Decorator, Method,
|
||||
MethodKind, PrivateMethod, PrivateProp,
|
||||
Class, ClassMember, ClassMethod, ClassProp, Constructor, Decorator, MethodKind,
|
||||
PrivateMethod, PrivateProp,
|
||||
},
|
||||
decl::{ClassDecl, Decl, FnDecl, VarDecl, VarDeclKind, VarDeclarator},
|
||||
expr::{
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_codegen"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
authors = ["강동윤 <kdy1@outlook.kr>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
@ -12,10 +12,10 @@ bitflags = "1"
|
||||
fxhash = "0.2.1"
|
||||
swc_atoms = { version = "0.1", path ="../../atoms" }
|
||||
swc_common = { version = "0.3", path ="../../common" }
|
||||
swc_ecma_ast = { version = "0.8", path ="../ast" }
|
||||
swc_ecma_ast = { version = "0.9", path ="../ast" }
|
||||
swc_ecma_codegen_macros = { version = "0.3", path ="./macros" }
|
||||
sourcemap = "2.2"
|
||||
|
||||
[dev-dependencies]
|
||||
testing = { version = "0.3", path ="../../testing" }
|
||||
swc_ecma_parser = { version = "0.9", path ="../parser" }
|
||||
swc_ecma_parser = { version = "0.10", path ="../parser" }
|
@ -689,53 +689,82 @@ impl<'a> Emitter<'a> {
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_private_method(&mut self, n: &PrivateMethod) -> Result {
|
||||
self.emit_class_method(n)?;
|
||||
self.emit_leading_comments_of_pos(n.span().lo())?;
|
||||
|
||||
if n.is_static {
|
||||
keyword!("static");
|
||||
space!();
|
||||
}
|
||||
match n.kind {
|
||||
MethodKind::Method => {
|
||||
if n.function.is_async {
|
||||
keyword!("async");
|
||||
}
|
||||
space!();
|
||||
if n.function.is_generator {
|
||||
punct!("*");
|
||||
}
|
||||
|
||||
emit!(n.key);
|
||||
}
|
||||
MethodKind::Getter => {
|
||||
keyword!("get");
|
||||
space!();
|
||||
|
||||
emit!(n.key);
|
||||
}
|
||||
MethodKind::Setter => {
|
||||
keyword!("set");
|
||||
space!();
|
||||
|
||||
emit!(n.key);
|
||||
}
|
||||
}
|
||||
|
||||
self.emit_fn_trailing(&n.function)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_method(&mut self, n: &Method) -> Result {
|
||||
self.emit_class_method(n)?;
|
||||
}
|
||||
pub fn emit_class_method(&mut self, n: &ClassMethod) -> Result {
|
||||
self.emit_leading_comments_of_pos(n.span().lo())?;
|
||||
|
||||
fn emit_class_method<K: Node>(&mut self, node: &ClassMethod<K>) -> Result {
|
||||
self.emit_leading_comments_of_pos(node.span().lo())?;
|
||||
|
||||
if node.is_static {
|
||||
keyword!(self, "static");
|
||||
space!(self);
|
||||
if n.is_static {
|
||||
keyword!("static");
|
||||
space!();
|
||||
}
|
||||
match node.kind {
|
||||
match n.kind {
|
||||
MethodKind::Method => {
|
||||
if node.function.is_async {
|
||||
keyword!(self, "async");
|
||||
if n.function.is_async {
|
||||
keyword!("async");
|
||||
}
|
||||
space!(self);
|
||||
if node.function.is_generator {
|
||||
punct!(self, "*");
|
||||
space!();
|
||||
if n.function.is_generator {
|
||||
punct!("*");
|
||||
}
|
||||
|
||||
emit!(self, node.key);
|
||||
emit!(n.key);
|
||||
}
|
||||
MethodKind::Getter => {
|
||||
keyword!(self, "get");
|
||||
space!(self);
|
||||
keyword!("get");
|
||||
space!();
|
||||
|
||||
emit!(self, node.key);
|
||||
emit!(n.key);
|
||||
}
|
||||
MethodKind::Setter => {
|
||||
keyword!(self, "set");
|
||||
space!(self);
|
||||
keyword!("set");
|
||||
space!();
|
||||
|
||||
emit!(self, node.key);
|
||||
emit!(n.key);
|
||||
}
|
||||
}
|
||||
|
||||
self.emit_fn_trailing(&node.function)?;
|
||||
Ok(())
|
||||
self.emit_fn_trailing(&n.function)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_private_prop(&mut self, n: &PrivateProp) -> Result {
|
||||
self.emit_leading_comments_of_pos(n.span().lo())?;
|
||||
|
||||
unimplemented!("emit_private_prop")
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
authors = ["강동윤 <kdy1@outlook.kr>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
@ -17,7 +17,7 @@ verify = ["fold"]
|
||||
[dependencies]
|
||||
swc_atoms = { version = "0.1", path ="../../atoms" }
|
||||
swc_common = { version = "0.3", path ="../../common" }
|
||||
swc_ecma_ast = { version = "0.8", path ="../ast" }
|
||||
swc_ecma_ast = { version = "0.9", path ="../ast" }
|
||||
swc_ecma_parser_macros = { version = "0.3", path ="./macros" }
|
||||
enum_kind = { version = "0.1", path ="../../macros/enum_kind" }
|
||||
unicode-xid = "0.1"
|
||||
|
@ -543,7 +543,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
expect!(';');
|
||||
|
||||
Ok(match key {
|
||||
Either::Left(key) => ClassProperty {
|
||||
Either::Left(key) => PrivateProp {
|
||||
span: span!(start),
|
||||
key,
|
||||
value,
|
||||
@ -558,7 +558,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
computed: false,
|
||||
}
|
||||
.into(),
|
||||
Either::Right(key) => ClassProperty {
|
||||
Either::Right(key) => ClassProp {
|
||||
span: span!(start),
|
||||
computed: match key {
|
||||
PropName::Computed(..) => true,
|
||||
@ -747,7 +747,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
self.parse_fn_args_body(decorators, start, parse_args, is_async, is_generator)?;
|
||||
|
||||
match key {
|
||||
Either::Left(key) => Ok(ClassMethod {
|
||||
Either::Left(key) => Ok(PrivateMethod {
|
||||
span: span!(start),
|
||||
|
||||
accessibility,
|
||||
|
@ -3,7 +3,7 @@ macro_rules! fold_only_key {
|
||||
impl<'a> Fold<ClassMember> for $T<'a> {
|
||||
fn fold(&mut self, m: ClassMember) -> ClassMember {
|
||||
match m {
|
||||
ClassMember::Method(m) => ClassMember::Method(Method {
|
||||
ClassMember::Method(m) => ClassMember::Method(ClassMethod {
|
||||
key: m.key.fold_with(self),
|
||||
..m
|
||||
}),
|
||||
|
@ -564,11 +564,7 @@ impl Classes {
|
||||
body
|
||||
}
|
||||
|
||||
fn fold_class_methods(
|
||||
&mut self,
|
||||
class_name: Ident,
|
||||
methods: Vec<ClassMethod<PropName>>,
|
||||
) -> Vec<Stmt> {
|
||||
fn fold_class_methods(&mut self, class_name: Ident, methods: Vec<ClassMethod>) -> Vec<Stmt> {
|
||||
if methods.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
@ -2,50 +2,50 @@ use super::*;
|
||||
use crate::compat::es2015::{block_scoping, resolver};
|
||||
|
||||
fn tr() -> impl Fold<Module> {
|
||||
chain!(resolver(), function_name(), block_scoping())
|
||||
chain!(resolver(), function_name(), block_scoping())
|
||||
}
|
||||
|
||||
macro_rules! identical {
|
||||
($name:ident, $src:literal) => {
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
$name,
|
||||
$src,
|
||||
$src
|
||||
);
|
||||
};
|
||||
($name:ident, $src:literal) => {
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
$name,
|
||||
$src,
|
||||
$src
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
basic,
|
||||
r#"var number = function (x) {
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
basic,
|
||||
r#"var number = function (x) {
|
||||
return x;
|
||||
};"#,
|
||||
r#"var number = function number(x) {
|
||||
r#"var number = function number(x) {
|
||||
return x;
|
||||
};"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
assign,
|
||||
r#"number = function (x) {
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
assign,
|
||||
r#"number = function (x) {
|
||||
return x;
|
||||
};"#,
|
||||
r#"number = function number(x) {
|
||||
r#"number = function number(x) {
|
||||
return x;
|
||||
};"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
let_complex,
|
||||
r#"
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
let_complex,
|
||||
r#"
|
||||
let TestClass = {
|
||||
name: "John Doe",
|
||||
|
||||
@ -57,7 +57,7 @@ let TestClass = {
|
||||
}
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
r#"
|
||||
var TestClass = {
|
||||
name: "John Doe",
|
||||
|
||||
@ -72,10 +72,10 @@ var TestClass = {
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
class_simple,
|
||||
r#"
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
class_simple,
|
||||
r#"
|
||||
var Foo = function() {
|
||||
var Foo = function () {
|
||||
_classCallCheck(this, Foo);
|
||||
@ -87,7 +87,7 @@ expect(Foo.num).toBe(0);
|
||||
expect(Foo.num = 1).toBe(1);
|
||||
expect(Foo.name).toBe('Foo');
|
||||
"#,
|
||||
r#"
|
||||
r#"
|
||||
var Foo = function() {
|
||||
var Foo = function() {
|
||||
_classCallCheck(this, Foo);
|
||||
@ -102,10 +102,10 @@ expect(Foo.name).toBe('Foo');
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
issue_288_01,
|
||||
"var extendStatics = function (d, b) {
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
issue_288_01,
|
||||
"var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf || {
|
||||
__proto__: []
|
||||
} instanceof Array && function (d, b) {
|
||||
@ -116,7 +116,7 @@ test!(
|
||||
|
||||
return extendStatics(d, b);
|
||||
};",
|
||||
"var extendStatics = function (d, b) {
|
||||
"var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf || {
|
||||
__proto__: []
|
||||
} instanceof Array && function (d1, b1) {
|
||||
@ -130,11 +130,11 @@ test!(
|
||||
);
|
||||
|
||||
identical!(
|
||||
issue_288_02,
|
||||
"function components_Link_extends() {
|
||||
issue_288_02,
|
||||
"function components_Link_extends() {
|
||||
components_Link_extends = Object.assign || function (target) { for (var i = 1; i < \
|
||||
arguments.length; i++) { var source = arguments[i]; for (var key in source) { if \
|
||||
(Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return \
|
||||
target; };
|
||||
arguments.length; i++) { var source = arguments[i]; for (var key in source) { if \
|
||||
(Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } \
|
||||
return target; };
|
||||
return components_Link_extends.apply(this, arguments); }"
|
||||
);
|
||||
|
@ -328,8 +328,8 @@ impl Fold<Expr> for MethodFolder {
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Method> for Actual {
|
||||
fn fold(&mut self, m: Method) -> Method {
|
||||
impl Fold<ClassMethod> for Actual {
|
||||
fn fold(&mut self, m: ClassMethod) -> ClassMethod {
|
||||
if m.function.body.is_none() {
|
||||
return m;
|
||||
}
|
||||
@ -356,7 +356,7 @@ impl Fold<Method> for Actual {
|
||||
})))
|
||||
};
|
||||
|
||||
Method {
|
||||
ClassMethod {
|
||||
function: Function {
|
||||
span: m.span,
|
||||
is_async: false,
|
||||
|
@ -290,7 +290,7 @@ impl ClassProperties {
|
||||
}
|
||||
_ => method.key,
|
||||
};
|
||||
members.push(ClassMember::Method(Method { key, ..method }))
|
||||
members.push(ClassMember::Method(ClassMethod { key, ..method }))
|
||||
}
|
||||
|
||||
ClassMember::ClassProp(mut prop) => {
|
||||
|
@ -163,7 +163,7 @@ impl Fold<Vec<ClassMember>> for Strip {
|
||||
|
||||
members.move_flat_map(|member| match member {
|
||||
ClassMember::Constructor(Constructor { body: None, .. }) => None,
|
||||
ClassMember::Method(Method {
|
||||
ClassMember::Method(ClassMethod {
|
||||
is_abstract: true, ..
|
||||
}) => None,
|
||||
_ => Some(member),
|
||||
|
Loading…
Reference in New Issue
Block a user