Repository: prettier/prettier (JavaScript)
Date: 2017-12-03 02:50:15+00:00
Task type: Bug Fix

Issue:
Typescript: decorator + readonly + comment leads to un-compilable code
<!-- BUGGY OR UGLY? Please use this template.

Tip! Don't write this stuff manually.

1. Go to https://prettier.io/playground
2. Paste your code and set options
3. Press the "Report issue" button in the lower right

-->

**Prettier 1.8.2**
```sh
# Options (if any):
```

**Input:**
```ts
class Something {                 
  @Annotateme()                   
  //TODO will it break            
  readonly property: Array<string>
}                                 
```

**Output:**
```ts
class Something {
  @Annotateme()
  readonly //TODO will it break
  property: Array<string>;
}
```

**Expected behavior:**
Unchanged code. Current version leads to code that Typescript 2.4.1 refuses to compile.


Issue discussion:
Same thing for flow, too.

**Prettier 1.8.2**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAucAbAhgZ0wAgMoQC2cMAFgJZQDmOwO9DjT9AOlPQAICCUUEM6eMQAUASmYTmbegHoZAFQDyAEUU4A7uVSoc5GDgBGAJzjoA1pMbScmATHJgcAByMQncIzACeSHFyNG6F4APLZGlFQAfGwAvtZsIAA0IG720JjIoFgwyABm6KiYcMnG6GBmJHhOZRHIMEYArsUgACYQYHkFRcmURZ4ACoFUhOidhc0AVpgAHgBCgeWV6MQAMpRwY90pDTBOOwBMm83VRn3IIAboBl6o0EkgLpQwAOrkLWTIABwADMkuEEVnoEnHVGs0TABHBrkEyDdDDUZIfLjZJFQjkUFNVERVBwACKDX4GyRXWaAgMr3epGQ+2S9XQWgiAGEiCNznwoBtkg0ivIrhkSeMYjEgA)

**Input:**
```jsx
class Something {                 
  @Annotateme()                   
  //TODO will it break            
  static property: Array<string>
}
  

```

**Output:**
```jsx
class Something {
  @Annotateme()
  static //TODO will it break
  property: Array<string>;
}

```

Solution patch:
diff --git a/src/comments.js b/src/comments.js
index bd1cbf83a5cc..260b0a17de08 100644
--- a/src/comments.js
+++ b/src/comments.js
@@ -638,6 +638,9 @@ function handleMethodNameComments(text, enclosingNode, precedingNode, comment) {
     enclosingNode &&
     precedingNode.type === "Decorator" &&
     (enclosingNode.type === "ClassMethod" ||
+      enclosingNode.type === "ClassProperty" ||
+      enclosingNode.type === "TSAbstractClassProperty" ||
+      enclosingNode.type === "TSAbstractMethodDefinition" ||
       enclosingNode.type === "MethodDefinition")
   ) {
     addTrailingComment(precedingNode, comment);


Test patch:
diff --git a/tests/decorator_comments/__snapshots__/jsfmt.spec.js.snap b/tests/decorator_comments/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..de47bc62fbac
--- /dev/null
+++ b/tests/decorator_comments/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`comments.js 1`] = `
+class Something {
+    @Annotateme()
+    // comment
+    static property: Array<string>;
+}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class Something {
+  @Annotateme()
+  // comment
+  static property: Array<string>;
+}
+
+`;
diff --git a/tests/decorator_comments/comments.js b/tests/decorator_comments/comments.js
new file mode 100644
index 000000000000..f28b803b77ec
--- /dev/null
+++ b/tests/decorator_comments/comments.js
@@ -0,0 +1,5 @@
+class Something {
+    @Annotateme()
+    // comment
+    static property: Array<string>;
+}
diff --git a/tests/decorator_comments/jsfmt.spec.js b/tests/decorator_comments/jsfmt.spec.js
new file mode 100644
index 000000000000..4ef9b45f0f5e
--- /dev/null
+++ b/tests/decorator_comments/jsfmt.spec.js
@@ -0,0 +1,1 @@
+run_spec(__dirname, ["babylon", "typescript"]);
diff --git a/tests/typescript_decorators/__snapshots__/jsfmt.spec.js.snap b/tests/typescript_decorators/__snapshots__/jsfmt.spec.js.snap
index c715c5055a5c..77e1fb6d8877 100644
--- a/tests/typescript_decorators/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/typescript_decorators/__snapshots__/jsfmt.spec.js.snap
@@ -80,6 +80,23 @@ class Foo4 {
     async *method() {}
 }
 
+class Something {
+    @foo()
+    // comment
+    readonly property: Array<string>
+}
+
+class Something {
+    @foo()
+    // comment
+    abstract property: Array<string>
+}
+
+class Something {
+    @foo()
+    // comment
+    abstract method(): Array<string>
+}
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 class Foo1 {
   @foo
@@ -105,6 +122,24 @@ class Foo4 {
   async *method() {}
 }
 
+class Something {
+  @foo()
+  // comment
+  readonly property: Array<string>;
+}
+
+class Something {
+  @foo()
+  // comment
+  abstract property: Array<string>;
+}
+
+class Something {
+  @foo()
+  // comment
+  abstract method(): Array<string>;
+}
+
 `;
 
 exports[`inline-decorators.ts 1`] = `
diff --git a/tests/typescript_decorators/decorators-comments.js b/tests/typescript_decorators/decorators-comments.js
index 8516944028a1..e67b1534100f 100644
--- a/tests/typescript_decorators/decorators-comments.js
+++ b/tests/typescript_decorators/decorators-comments.js
@@ -23,3 +23,20 @@ class Foo4 {
     async *method() {}
 }
 
+class Something {
+    @foo()
+    // comment
+    readonly property: Array<string>
+}
+
+class Something {
+    @foo()
+    // comment
+    abstract property: Array<string>
+}
+
+class Something {
+    @foo()
+    // comment
+    abstract method(): Array<string>
+}