Repository: lo1tuma/eslint-plugin-mocha (ts)

Issue:
no-mocha-arrows drops comments in the function head when fixing
All of these comments are dropped when fixing:
```js
it( ( foo /* one */ ) /* two */ => /* three */ { body(); } );
```

This was noticed while porting this rule to eslint-plugin-qunit: https://github.com/platinumazure/eslint-plugin-qunit/pull/88

The fixes there can be easily backported to this plugin.

Pull request description:
Support comments in arrow functions when fixing
Fixes #251

Patch:
diff --git a/lib/rules/no-mocha-arrows.js b/lib/rules/no-mocha-arrows.js
index 89f5dd5..30a7977 100644
--- a/lib/rules/no-mocha-arrows.js
+++ b/lib/rules/no-mocha-arrows.js
@@ -5,7 +5,6 @@
  * @author Paul Melnikow
  */
 
-const last = require('ramda/src/last');
 const astUtils = require('../util/ast');
 
 module.exports = {
@@ -16,21 +15,35 @@ module.exports = {
     create(context) {
         const sourceCode = context.getSourceCode();
 
+        function extractSourceTextByRange(start, end) {
+            return sourceCode.text.slice(start, end).trim();
+        }
+
+        // eslint-disable-next-line max-statements
         function formatFunctionHead(fn) {
-            const paramsLeftParen = sourceCode.getFirstToken(fn);
-            const paramsRightParen = sourceCode.getTokenBefore(sourceCode.getTokenBefore(fn.body));
-            let paramsFullText = sourceCode.text.slice(paramsLeftParen.range[0], paramsRightParen.range[1]);
-            let functionKeyword = 'function';
+            const arrow = sourceCode.getTokenBefore(fn.body);
+            const beforeArrowToken = sourceCode.getTokenBefore(arrow);
+            let firstToken = sourceCode.getFirstToken(fn);
 
+            let functionKeyword = 'function';
+            let params = extractSourceTextByRange(firstToken.range[0], beforeArrowToken.range[1]);
             if (fn.async) {
-                // When 'async' specified, take care about the keyword.
+                // When 'async' specified strip the token from the params text
+                // and prepend it to the function keyword
+                params = params.slice(firstToken.range[1] - firstToken.range[0]).trim();
                 functionKeyword = 'async function';
-                // Strip 'async (...)' to ' (...)'
-                paramsFullText = paramsFullText.slice(5);
+
+                // Advance firstToken pointer
+                firstToken = sourceCode.getTokenAfter(firstToken);
             }
 
-            if (fn.params.length > 0) {
-                paramsFullText = `(${ sourceCode.text.slice(fn.params[0].range[0], last(fn.params).range[1]) })`;
+            const beforeArrowComment = extractSourceTextByRange(beforeArrowToken.range[1], arrow.range[0]);
+            const afterArrowComment = extractSourceTextByRange(arrow.range[1], fn.body.range[0]);
+            let paramsFullText;
+            if (firstToken.type !== 'Punctuator') {
+                paramsFullText = `(${params}${beforeArrowComment})${afterArrowComment}`;
+            } else {
+                paramsFullText = `${params}${beforeArrowComment}${afterArrowComment}`;
             }
 
             return `${functionKeyword}${paramsFullText} `;


Test patch:
diff --git a/test/rules/no-mocha-arrows.js b/test/rules/no-mocha-arrows.js
index 94f32d6..a388a7f 100644
--- a/test/rules/no-mocha-arrows.js
+++ b/test/rules/no-mocha-arrows.js
@@ -74,12 +74,12 @@ ruleTester.run('no-mocha-arrows', rules['no-mocha-arrows'], {
         {
             code: 'it(async () => { assert(something, false) })',
             errors,
-            output: 'it(async function () { assert(something, false) })'
+            output: 'it(async function() { assert(something, false) })'
         },
         {
             code: 'it(async () => assert(something, false))',
             errors,
-            output: 'it(async function () { return assert(something, false); })'
+            output: 'it(async function() { return assert(something, false); })'
         },
         {
             code: 'it(async done => assert(something, false))',
@@ -95,6 +95,11 @@ ruleTester.run('no-mocha-arrows', rules['no-mocha-arrows'], {
             code: 'it(async() => assert(something, false))',
             errors,
             output: 'it(async function() { return assert(something, false); })'
+        },
+        {
+            code: 'it(/*one*/async/*two*/(done)/*three*/=>/*four*/assert(something, false))',
+            errors,
+            output: 'it(/*one*/async function/*two*/(done)/*three*//*four*/ { return assert(something, false); })'
         }
     ]