Repository: prettier/plugin-ruby (javascript)

Issue:
Array splat operator gets pushed before a leading comment
## Metadata

* Ruby version: 2.6.5
* `@prettier/plugin-ruby` or `prettier` gem version: 1.5.1
* Options:
  * [x] `rubyHashLabel`
  * [x] `rubyModifier`
  * [x] `rubySingleQuote`
  * [ ] `rubyToProc`
  * [ ] `trailingComma`

## Input

```ruby
[
  # a comment
  *anything
]
```

## Current output

```ruby
[
  *# a comment
  anything
]
```

## Expected output

```ruby
[
  # a comment
  *anything
]
```



Discussion:
Lol wat.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
 
 ## [Unreleased]
 
+### Changed
+
+- [#812](https://github.com/prettier/plugin-ruby/issues/812) - valscion, kddeisz - Splats and blocks within args that have comments attached should place their respective operators in the right place.
+
 ## [1.5.2] - 2021-02-03
 
 ### Changed
diff --git a/src/ruby/nodes/args.js b/src/ruby/nodes/args.js
--- a/src/ruby/nodes/args.js
+++ b/src/ruby/nodes/args.js
@@ -106,25 +106,66 @@ function printArgs(path, { rubyToProc }, print) {
   return args;
 }
 
+function printArgsAddBlock(path, opts, print) {
+  const node = path.getValue();
+  const parts = path.call(print, "body", 0);
+
+  if (node.body[1]) {
+    let blockDoc = path.call(print, "body", 1);
+
+    if (node.body[1].comments) {
+      // If we have a method call like:
+      //
+      //     foo(
+      //       # comment
+      //       &block
+      //     )
+      //
+      // then we need to make sure we don't accidentally prepend the operator
+      // before the comment.
+      blockDoc.parts[2] = concat(["&", blockDoc.parts[2]]);
+    } else {
+      // If we don't have any comments, we can just prepend the operator
+      blockDoc = concat(["&", blockDoc]);
+    }
+
+    parts.push(blockDoc);
+  }
+
+  return parts;
+}
+
+function printArgsAddStar(path, opts, print) {
+  const node = path.getValue();
+  const docs = path.map(print, "body");
+
+  if (node.body[1].comments) {
+    // If we have an array like:
+    //
+    //     [
+    //       # comment
+    //       *values
+    //     ]
+    //
+    // then we need to make sure we don't accidentally prepend the operator
+    // before the comment.
+    docs[1].parts[2] = concat(["*", docs[1].parts[2]]);
+  } else {
+    // If we don't have any comments, we can just prepend the operator
+    docs[1] = concat(["*", docs[1]]);
+  }
+
+  return docs[0].concat(docs[1]).concat(docs.slice(2));
+}
+
+function printBlockArg(path, opts, print) {
+  return concat(["&", path.call(print, "body", 0)]);
+}
+
 module.exports = {
   arg_paren: printArgParen,
   args: printArgs,
-  args_add_block: (path, opts, print) => {
-    const parts = path.call(print, "body", 0);
-
-    if (path.getValue().body[1]) {
-      parts.push(concat(["&", path.call(print, "body", 1)]));
-    }
-
-    return parts;
-  },
-  args_add_star: (path, opts, print) => {
-    const printed = path.map(print, "body");
-    const parts = printed[0]
-      .concat([concat(["*", printed[1]])])
-      .concat(printed.slice(2));
-
-    return parts;
-  },
-  blockarg: (path, opts, print) => concat(["&", path.call(print, "body", 0)])
+  args_add_block: printArgsAddBlock,
+  args_add_star: printArgsAddStar,
+  blockarg: printBlockArg
 };


Test patch:
diff --git a/test/js/ruby/nodes/method.test.js b/test/js/ruby/nodes/method.test.js
--- a/test/js/ruby/nodes/method.test.js
+++ b/test/js/ruby/nodes/method.test.js
@@ -245,7 +245,29 @@ describe("method", () => {
       test("between multi args", () =>
         expect("foo(1, 2, *abc, 3, 4)").toMatchFormat());
 
+      test("with comments", () => {
+        const content = ruby(`
+          foo(
+            # comment
+            *values
+          )
+        `);
+
+        return expect(content).toMatchFormat();
+      });
+
       test("with block", () => expect("foo(*bar, &block)").toMatchFormat());
+
+      test("with comments and block", () => {
+        const content = ruby(`
+          foo(
+            # comment
+            &block
+          )
+        `);
+
+        return expect(content).toMatchFormat();
+      });
     });
 
     describe("double splat", () => {
@@ -254,7 +276,7 @@ describe("method", () => {
       test("with block", () => expect("foo(**bar, &block)").toMatchFormat());
 
       test("with splat and block", () =>
-        expect("foo(*bar, **baz, &lock)").toMatchFormat());
+        expect("foo(*bar, **baz, &block)").toMatchFormat());
 
       test("after kwarg", () =>
         expect("foo(kwarg: 1, **splat)").toMatchFormat());