swc_ecma_ast:

- Split class member / property into separate types
This commit is contained in:
강동윤 2019-02-28 19:25:38 +09:00
parent 6275831b30
commit a46804ab48
13 changed files with 184 additions and 154 deletions

View File

@ -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"

View File

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

View File

@ -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::{

View File

@ -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" }

View File

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

View File

@ -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"

View File

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

View File

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

View File

@ -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![];
}

View File

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

View File

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

View File

@ -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) => {

View File

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