Repository: prettier/prettier (JavaScript)

Issue:
Misplaced parameter comment in abstract method
**Prettier 2.3.0**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEBDARgZxgJ1WGAAjABtVNNCAxCCQ4AHSkMI2zwMPVRwAomWLAPQAqEcQgBbSQiJwAHgAcyASyhqA5oQCumODgCSAE0KKeqSYRFCBg3fuMAaWwEomAXxCOQERTBXQmMigPDgQAO4ACjwIQSioJOGoAJ5B3ugcANZwMADKZmCayLjacN5wkuhwRkbVADKoUBraqBpwNDiSqDD+Tcho2jAQXiAAFjCSJADqoyrwmAVwubFzKgBuc8n9YBQjano4MJF4Gl3IAGYJet4AVpjyAEJZObkWcHVqcBdXZSB38rlNCQ4ABFbQQeDfEjXEBmHAHfrcKokAC0MDSsJwahgUxURhgo2QAA4AAzeRRhPRTPCKfoUuAHNZfbwAR3B8GOvjiaEwKKgcGq1RGODgbJUIuOrTOSEu0N+ekkKmKOFK3kwQNB7K+Mp+3hgGFx+MJSAATHq8CoSJoAMJSaUgBkAVhG9gAKmwoTC1qUDFBarBcmAsX4AIJ+3IwZLAz1wdzuIA)
<!-- prettier-ignore -->
```sh
--parser babel-ts
```

**Input:**
<!-- prettier-ignore -->
```tsx
abstract class Foo {
  abstract bar(
    /** comment explaining userId param */
    userId,
  )
}
```

**Output:**
<!-- prettier-ignore -->
```tsx
abstract class Foo {
  abstract bar(userId);
  /** comment explaining userId param */
}

```

**Expected behavior:**
<!-- prettier-ignore -->
```tsx
abstract class Foo {
  abstract bar(
    /** comment explaining userId param */
    userId
  )
}
```

I expect the comment to remain directly above the `userId` argument. It only seems to repro when the method is abstract and has exactly one argument.


Hints:
Also it happens for a method that has no body.

**Prettier 2.3.2**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAucAbAhgZ0wAgGIQQ7AA6UOOARugE4AUZFFA9AFSs6QC2XCMOcAB4AHDAEsoEgOY4Arpjg0AkgBMcw2ui45WzRk3mLVAGn0BKMgF8QxkBGEwx0TMlC0aEAO4AFWghco6Kie6ACeLraUNOhgANZwMADKGmDSyDA0snC2cFyUcCoqBQAy6FBSsuhScAQ0XOgwjuXIIOiyMBA2IAAWMFyoAOrdYvCYKXCJ-iNiAG4joS1g2F0SCjQw3tFS9cgAZkEKtgBWmIIAQtFxCYlacMUScHsH2SAngonSqHAAirIQ8E9UIcQBoaGsWtR8qgALQwCIgmgSGADMQqGDdZAADgADLZhB4FANosIWvi4GsZo9bABHP7wTb2AKtTDQqBwAoFLo0OC0sTczZVHZIfZAl4KLhidKZMWfH50x7C562GDoSgotEYpAAJmV0TEqGkAGEIDx0C1yQBWLqGAAqqoCIuBMyySigRVgiTAiIcAEE3YkYKEvoCFJZLEA)
<!-- prettier-ignore -->
```sh
--parser babel-ts
```

**Input:**
<!-- prettier-ignore -->
```tsx
class Foo {
  bar(
    /** comment explaining userId param */
    userId,
  )
}
```

**Output:**
<!-- prettier-ignore -->
```tsx
class Foo {
  bar(userId);
  /** comment explaining userId param */
}

```
This is blocking us from adopting prettier 2.3. Would love to see some traction on this diff. 
I investigated this issue a little.

```typescript
abstract class Foo {
  abstract bar(
    /** comment explaining userId param */
    userId,
  )
}
```

In the `babel-ts` parser, the above comment has become the trailing comment for `bar`.
This might be the reason why the comment is misplaced.
Thanks @t-mangoe . If you can get us unblocked we'd be extremely grateful. I've never worked on a tool like prettier before, so I've procrastinated biting the bullet and diving in. This one is really blocking us and we can't leverage new features like support for the override keyword.
After bisecting, I found that this issue was introduced in #9872
@fisker is this something you can take a look at?
Looks like the change in canAttachComment is to blame, but the fix may be more complicated.
May be we can fix this in attachComment? 
Forgive me, but I've never contributed to this project before. I don't see an attachComment API. Is it maybe referring to this PR? https://github.com/prettier/prettier/pull/11525

Patch:
diff --git a/src/language-js/comments.js b/src/language-js/comments.js
--- a/src/language-js/comments.js
+++ b/src/language-js/comments.js
@@ -459,6 +459,7 @@ function handleMethodNameComments({
   if (
     enclosingNode &&
     precedingNode &&
+    getNextNonSpaceNonCommentCharacter(text, comment, locEnd) === "(" &&
     // "MethodDefinition" is handled in getCommentChildNodes
     (enclosingNode.type === "Property" ||
       enclosingNode.type === "TSDeclareMethod" ||


Test patch:
diff --git a/tests/format/typescript/comments/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/comments/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/typescript/comments/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/typescript/comments/__snapshots__/jsfmt.spec.js.snap
@@ -28,6 +28,40 @@ abstract class AbstractRule {
 ================================================================================
 `;
 
+exports[`abstract_methods.ts format 1`] = `
+====================================options=====================================
+parsers: ["typescript"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+abstract class AbstractFoo {
+  abstract method1(/* comment */ arg: string);
+  abstract method2(
+    /* comment */
+    arg: string
+  );
+  abstract method3(
+    // comment
+    arg: string
+  );
+}
+
+=====================================output=====================================
+abstract class AbstractFoo {
+  abstract method1(/* comment */ arg: string);
+  abstract method2(
+    /* comment */
+    arg: string
+  );
+  abstract method3(
+    // comment
+    arg: string
+  );
+}
+
+================================================================================
+`;
+
 exports[`after_jsx_generic.ts format 1`] = `
 ====================================options=====================================
 parsers: ["typescript"]
@@ -602,6 +636,8 @@ export class Point {
   mismatchedIndentation() {}
 
   inline /* foo*/ (/* bar */) /* baz */ {}
+
+  noBody(/* comment */ arg);
 }
 
 =====================================output=====================================
@@ -651,6 +687,8 @@ export class Point {
   mismatchedIndentation() {}
 
   inline /* foo*/(/* bar */) /* baz */ {}
+
+  noBody(/* comment */ arg);
 }
 
 ================================================================================
diff --git a/tests/format/typescript/comments/abstract_methods.ts b/tests/format/typescript/comments/abstract_methods.ts
new file mode 100644
--- /dev/null
+++ b/tests/format/typescript/comments/abstract_methods.ts
@@ -0,0 +1,11 @@
+abstract class AbstractFoo {
+  abstract method1(/* comment */ arg: string);
+  abstract method2(
+    /* comment */
+    arg: string
+  );
+  abstract method3(
+    // comment
+    arg: string
+  );
+}
diff --git a/tests/format/typescript/comments/methods.ts b/tests/format/typescript/comments/methods.ts
--- a/tests/format/typescript/comments/methods.ts
+++ b/tests/format/typescript/comments/methods.ts
@@ -44,4 +44,6 @@ export class Point {
   mismatchedIndentation() {}
 
   inline /* foo*/ (/* bar */) /* baz */ {}
+
+  noBody(/* comment */ arg);
 }