Skip to content

Commit

Permalink
feat(rome_js_parser): EcmaScript @decorators rome#4252
Browse files Browse the repository at this point in the history
class member
  • Loading branch information
denbezrukov committed Apr 16, 2023
1 parent e431795 commit f6c4dc0
Show file tree
Hide file tree
Showing 52 changed files with 11,430 additions and 2,963 deletions.
68 changes: 34 additions & 34 deletions crates/rome_js_formatter/src/generated.rs
Expand Up @@ -4700,6 +4700,40 @@ impl IntoFormat<JsFormatContext> for rome_js_syntax::JsInitializerClause {
)
}
}
impl FormatRule<rome_js_syntax::JsDecorator>
for crate::js::auxiliary::decorator::FormatJsDecorator
{
type Context = JsFormatContext;
#[inline(always)]
fn fmt(&self, node: &rome_js_syntax::JsDecorator, f: &mut JsFormatter) -> FormatResult<()> {
FormatNodeRule::<rome_js_syntax::JsDecorator>::fmt(self, node, f)
}
}
impl AsFormat<JsFormatContext> for rome_js_syntax::JsDecorator {
type Format<'a> = FormatRefWithRule<
'a,
rome_js_syntax::JsDecorator,
crate::js::auxiliary::decorator::FormatJsDecorator,
>;
fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(
self,
crate::js::auxiliary::decorator::FormatJsDecorator::default(),
)
}
}
impl IntoFormat<JsFormatContext> for rome_js_syntax::JsDecorator {
type Format = FormatOwnedWithRule<
rome_js_syntax::JsDecorator,
crate::js::auxiliary::decorator::FormatJsDecorator,
>;
fn into_format(self) -> Self::Format {
FormatOwnedWithRule::new(
self,
crate::js::auxiliary::decorator::FormatJsDecorator::default(),
)
}
}
impl FormatRule<rome_js_syntax::TsOptionalPropertyAnnotation>
for crate::ts::auxiliary::optional_property_annotation::FormatTsOptionalPropertyAnnotation
{
Expand Down Expand Up @@ -6807,40 +6841,6 @@ impl IntoFormat<JsFormatContext> for rome_js_syntax::TsThisParameter {
)
}
}
impl FormatRule<rome_js_syntax::JsDecorator>
for crate::js::auxiliary::decorator::FormatJsDecorator
{
type Context = JsFormatContext;
#[inline(always)]
fn fmt(&self, node: &rome_js_syntax::JsDecorator, f: &mut JsFormatter) -> FormatResult<()> {
FormatNodeRule::<rome_js_syntax::JsDecorator>::fmt(self, node, f)
}
}
impl AsFormat<JsFormatContext> for rome_js_syntax::JsDecorator {
type Format<'a> = FormatRefWithRule<
'a,
rome_js_syntax::JsDecorator,
crate::js::auxiliary::decorator::FormatJsDecorator,
>;
fn format(&self) -> Self::Format<'_> {
FormatRefWithRule::new(
self,
crate::js::auxiliary::decorator::FormatJsDecorator::default(),
)
}
}
impl IntoFormat<JsFormatContext> for rome_js_syntax::JsDecorator {
type Format = FormatOwnedWithRule<
rome_js_syntax::JsDecorator,
crate::js::auxiliary::decorator::FormatJsDecorator,
>;
fn into_format(self) -> Self::Format {
FormatOwnedWithRule::new(
self,
crate::js::auxiliary::decorator::FormatJsDecorator::default(),
)
}
}
impl FormatRule<rome_js_syntax::TsAnyType> for crate::ts::types::any_type::FormatTsAnyType {
type Context = JsFormatContext;
#[inline(always)]
Expand Down
1 change: 1 addition & 0 deletions crates/rome_js_formatter/src/js/any/method_modifier.rs
Expand Up @@ -10,6 +10,7 @@ impl FormatRule<AnyJsMethodModifier> for FormatAnyJsMethodModifier {
match node {
AnyJsMethodModifier::TsAccessibilityModifier(node) => node.format().fmt(f),
AnyJsMethodModifier::JsStaticModifier(node) => node.format().fmt(f),
AnyJsMethodModifier::JsDecorator(node) => node.format().fmt(f),
AnyJsMethodModifier::TsOverrideModifier(node) => node.format().fmt(f),
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/rome_js_formatter/src/js/any/property_modifier.rs
Expand Up @@ -11,6 +11,7 @@ impl FormatRule<AnyJsPropertyModifier> for FormatAnyJsPropertyModifier {
AnyJsPropertyModifier::TsAccessibilityModifier(node) => node.format().fmt(f),
AnyJsPropertyModifier::JsStaticModifier(node) => node.format().fmt(f),
AnyJsPropertyModifier::JsAccessorModifier(node) => node.format().fmt(f),
AnyJsPropertyModifier::JsDecorator(node) => node.format().fmt(f),
AnyJsPropertyModifier::TsReadonlyModifier(node) => node.format().fmt(f),
AnyJsPropertyModifier::TsOverrideModifier(node) => node.format().fmt(f),
}
Expand Down
104 changes: 103 additions & 1 deletion crates/rome_js_formatter/tests/quick_test.rs
Expand Up @@ -13,7 +13,109 @@ mod language {
// use this test check if your snippet prints as you wish, without using a snapshot
fn quick_test() {
let src = r#"
const foo = @deco class {}
import { LitElement, html } from '@polymer/lit-element';
class MyElement extends LitElement {
static get properties() {
return {
mood: { type: String }
};
}
constructor() {
super();
this.mood = 'happy';
}
render() {
return html`
<style
>
.mood { color: green; }
</style
>
Web Components are <span
class="mood" >${
this.mood
}</span
>!
`;
}
}
customElements.define('my-element', MyElement);
const someHtml1 = html`<div > hello ${world} </div >`;
const someHtml2 = /* HTML */ `<div > hello ${world} </div >`;
html``
html`<my-element obj=${obj}></my-element>`;
html` <${Footer} >footer content<// > `
html` <div /> `
html`
<div />
`
html`<span>one</span><span>two</span><span>three</span>`;
function HelloWorld() {
return html`
<h3>Bar List</h3>
${bars.map(bar => html`
<p>${bar}</p>
`)}
`;
}
const trickyParens = html`<script> f((${expr}) / 2); </script>`;
const nestedFun = /* HTML */ `${outerExpr( 1 )} <script>const tpl = html\`<div>\${innerExpr( 1 )} ${outerExpr( 2 )}</div>\`</script>`;
const closingScriptTagShouldBeEscapedProperly = /* HTML */ `
<script>
const html = /* HTML */ \`<script><\\/script>\`;
</script>
`;
const closingScriptTag2 = /* HTML */ `<script>const scriptTag='<\\/script>'; <\/script>`;
html`
<div style="
${ foo}
"></div>
`
html`
<div style=${
foo
}></div>
`
html`<div style=" color : red;
display :inline ">
</div>`
html`<div style=" color : red;
${ foo}
display :inline ">
</div>`
html`<div style=" color : red;
${ foo}:${bar};
display :inline ">
</div>`
"#;
let syntax = SourceType::tsx();
let tree = parse(src, syntax);
Expand Down
@@ -0,0 +1,92 @@
---
source: crates/rome_formatter_test/src/snapshot_builder.rs
info: js/babel-plugins/decorators.js
---

# Input

```js
// https://babeljs.io/docs/en/babel-plugin-proposal-decorators

@annotation
class MyClass { }

function annotation(target) {
target.annotated = true;
}

@isTestable(true)
class MyClass { }

function isTestable(value) {
return function decorator(target) {
target.isTestable = value;
}
}

class C {
@enumerable(false)
method() { }
}

function enumerable(value) {
return function (target, key, descriptor) {
descriptor.enumerable = value;
return descriptor;
}
}

```


# Prettier differences

```diff
--- Prettier
+++ Rome
@@ -17,8 +17,7 @@
}

class C {
- @enumerable(false)
- method() {}
+ @enumerable(false) method() {}
}

function enumerable(value) {
```

# Output

```js
// https://babeljs.io/docs/en/babel-plugin-proposal-decorators

@annotation
class MyClass {}

function annotation(target) {
target.annotated = true;
}

@isTestable(true)
class MyClass {}

function isTestable(value) {
return function decorator(target) {
target.isTestable = value;
};
}

class C {
@enumerable(false) method() {}
}

function enumerable(value) {
return function (target, key, descriptor) {
descriptor.enumerable = value;
return descriptor;
};
}
```


@@ -1,7 +1,6 @@
---
source: crates/rome_formatter_test/src/snapshot_builder.rs
info:
test_file: js/decorator-comments/comments.js
info: js/decorator-comments/comments.js
---

# Input
Expand Down
Expand Up @@ -86,7 +86,7 @@ class {
```
classes.js:3:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Decorators are not valid here.
× Decorators are not valid here
1 │ @deco class Foo {}
2 │
Expand All @@ -97,7 +97,7 @@ classes.js:3:1 parse ━━━━━━━━━━━━━━━━━━━
classes.js:5:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Decorators are not valid here.
× Decorators are not valid here
3 │ @deco export class Bar {}
4 │
Expand Down
Expand Up @@ -97,7 +97,7 @@ export class Bar {}
```
comments.js:13:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Decorators are not valid here.
× Decorators are not valid here
> 13 │ @NgModule({
│ ^^^^^^^^^^^
Expand All @@ -111,7 +111,7 @@ comments.js:13:1 parse ━━━━━━━━━━━━━━━━━━━
comments.js:27:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Decorators are not valid here.
× Decorators are not valid here
26 │ // A
> 27 │ @Foo()
Expand Down
@@ -1,7 +1,6 @@
---
source: crates/rome_formatter_test/src/snapshot_builder.rs
info:
test_file: js/decorators/methods.js
info: js/decorators/methods.js
---

# Input
Expand All @@ -26,9 +25,15 @@ class Yo {
```diff
--- Prettier
+++ Rome
@@ -5,6 +5,5 @@
@anotherDecoratorWithALongName("and a very long string as a first argument")
async plip() {}
@@ -1,10 +1,7 @@
class Yo {
- @foo("hello")
- async plop() {}
+ @foo("hello") async plop() {}

- @anotherDecoratorWithALongName("and a very long string as a first argument")
- async plip() {}
+ @anotherDecoratorWithALongName("and a very long string as a first argument") async plip() {}

- @anotherDecoratorWithALongName("another very long string, but now inline")
- async plip() {}
Expand All @@ -40,19 +45,18 @@ class Yo {

```js
class Yo {
@foo("hello")
async plop() {}
@foo("hello") async plop() {}

@anotherDecoratorWithALongName("and a very long string as a first argument")
async plip() {}
@anotherDecoratorWithALongName("and a very long string as a first argument") async plip() {}

@anotherDecoratorWithALongName("another very long string, but now inline") async plip() {}
}
```

# Lines exceeding max width of 80 characters
```
8: @anotherDecoratorWithALongName("another very long string, but now inline") async plip() {}
4: @anotherDecoratorWithALongName("and a very long string as a first argument") async plip() {}
6: @anotherDecoratorWithALongName("another very long string, but now inline") async plip() {}
```


0 comments on commit f6c4dc0

Please sign in to comment.