From 39e475353955a530b07f8c113d3c2ee13564dd7d Mon Sep 17 00:00:00 2001 From: Anix Date: Sat, 16 May 2020 12:05:02 +0000 Subject: [PATCH 1/8] Fix: no reportin for comments inside (fixes #12995) --- lib/rules/arrow-parens.js | 8 +++++ tests/lib/rules/arrow-parens.js | 58 ++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js index dc3c3825791..a3f5bfc6666 100644 --- a/lib/rules/arrow-parens.js +++ b/lib/rules/arrow-parens.js @@ -105,6 +105,14 @@ module.exports = { ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`); } + if ( + node.params.length === 1 && + (sourceCode.getCommentsBefore(node.params[0]).length > 0 || + sourceCode.getCommentsAfter(node.params[0]).length > 0) + ) { + return; + } + // "as-needed", { "requireForBlockBody": true }: x => x if ( requireForBlockBody && diff --git a/tests/lib/rules/arrow-parens.js b/tests/lib/rules/arrow-parens.js index 3e796c1ec3c..51cd22776d6 100644 --- a/tests/lib/rules/arrow-parens.js +++ b/tests/lib/rules/arrow-parens.js @@ -29,6 +29,12 @@ const valid = [ "(a) => {\n}", "a.then((foo) => {});", "a.then((foo) => { if (true) {}; });", + "const f = (/* */a) => a + a;", + "const f = (a/** */) => a + a;", + "const f = (a//\n) => a + a;", + "const f = (//\na) => a + a;", + "const f = (/*\n */a//\n) => a + a;", + "const f = (/** @type {number} */a/**hello*/) => a + a;", { code: "a.then(async (foo) => { if (true) {}; });", parserOptions: { ecmaVersion: 8 } }, // "always" (explicit) @@ -68,7 +74,31 @@ const valid = [ { code: "async a => ({})", options: ["as-needed", { requireForBlockBody: true }], parserOptions: { ecmaVersion: 8 } }, { code: "async a => a", options: ["as-needed", { requireForBlockBody: true }], parserOptions: { ecmaVersion: 8 } }, { code: "(a: T) => a", options: ["as-needed", { requireForBlockBody: true }], parser: parser("identifer-type") }, - { code: "(a): T => a", options: ["as-needed", { requireForBlockBody: true }], parser: parser("return-type") } + { code: "(a): T => a", options: ["as-needed", { requireForBlockBody: true }], parser: parser("return-type") }, + { + code: "const f = (/** @type {number} */a/**hello*/) => a + a;", + options: ["as-needed"] + }, + { + code: "const f = (/* */a) => a + a;", + options: ["as-needed"] + }, + { + code: "const f = (a/** */) => a + a;", + options: ["as-needed"] + }, + { + code: "const f = (a//\n) => a + a;", + options: ["as-needed"] + }, + { + code: "const f = (//\na) => a + a;", + options: ["as-needed"] + }, + { + code: "const f = (/*\n */a//\n) => a + a;", + options: ["as-needed"] + } ]; const type = "ArrowFunctionExpression"; @@ -271,6 +301,32 @@ const invalid = [ messageId: "unexpectedParensInline", type }] + }, + { + code: "const f = /** @type {number} */(a)/**hello*/ => a + a;", + options: ["as-needed"], + output: "const f = /** @type {number} */a/**hello*/ => a + a;", + errors: [{ + line: 1, + column: 33, + type, + messageId: "unexpectedParens", + endLine: 1, + endColumn: 34 + }] + }, + { + code: "const f = //\n(a) => a + a;", + output: "const f = //\na => a + a;", + options: ["as-needed"], + errors: [{ + line: 2, + column: 2, + type, + messageId: "unexpectedParens", + endLine: 2, + endColumn: 3 + }] } ]; From 20834f3e5458eb00e52f2f5d060b402a28de0bff Mon Sep 17 00:00:00 2001 From: Anix Date: Sun, 17 May 2020 14:02:04 +0000 Subject: [PATCH 2/8] Update: handled some cases for comments in parens --- lib/rules/arrow-parens.js | 42 +++++++++++++++++++++++++++++---- tests/lib/rules/arrow-parens.js | 40 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js index a3f5bfc6666..88892783a8c 100644 --- a/lib/rules/arrow-parens.js +++ b/lib/rules/arrow-parens.js @@ -105,11 +105,43 @@ module.exports = { ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`); } - if ( - node.params.length === 1 && - (sourceCode.getCommentsBefore(node.params[0]).length > 0 || - sourceCode.getCommentsAfter(node.params[0]).length > 0) - ) { + /** + * Checks whether there are comments inside the params or not. + * @param {ASTNode} paramNode node to check + * @returns {boolean} `true` if there are comments inside of braces, else `false` + */ + function isCommentsInParens(paramNode) { + + if (paramNode.params.length !== 1) { + return false; + } + + if (!astUtils.isOpeningParenToken(firstTokenOfParam)) { + return false; + } + + if (sourceCode.getCommentsBefore(paramNode.params[0]).length > 0) { + return true; + } + + if (sourceCode.getCommentsAfter(paramNode.params[0]).length > 0) { + return true; + } + + const commaToken = sourceCode.getTokenAfter(paramNode.params[0]); + + if (commaToken.type === "Punctuator" && commaToken.value === ",") { + if (sourceCode.getCommentsAfter(commaToken).length > 0) { + return true; + } + } + + + return false; + } + + + if (isCommentsInParens(node)) { return; } diff --git a/tests/lib/rules/arrow-parens.js b/tests/lib/rules/arrow-parens.js index 51cd22776d6..2633193e3ab 100644 --- a/tests/lib/rules/arrow-parens.js +++ b/tests/lib/rules/arrow-parens.js @@ -98,6 +98,21 @@ const valid = [ { code: "const f = (/*\n */a//\n) => a + a;", options: ["as-needed"] + }, + { + code: "var foo = (a,/**/) => b;", + parserOptions: { ecmaVersion: 2017 }, + options: ["as-needed"] + }, + { + code: "var foo = (a,//\n) => b;", + parserOptions: { ecmaVersion: 2017 }, + options: ["as-needed"] + }, + { + code: "const i = (a/**/,) => a + a;", + parserOptions: { ecmaVersion: 2017 }, + options: ["as-needed"] } ]; @@ -327,7 +342,32 @@ const invalid = [ endLine: 2, endColumn: 3 }] + }, + { + code: "var foo = /**/ a => b;", + output: "var foo = /**/ (a) => b;", + errors: [{ + line: 1, + column: 16, + type: "ArrowFunctionExpression", + messageId: "expectedParens", + endLine: 1, + endColumn: 17 + }] + }, + { + code: "var bar = a /**/ => b;", + output: "var bar = (a) /**/ => b;", + errors: [{ + line: 1, + column: 11, + type: "ArrowFunctionExpression", + messageId: "expectedParens", + endLine: 1, + endColumn: 12 + }] } + ]; ruleTester.run("arrow-parens", rule, { From 4a3305b351dccdf8392dfd5a19d3a96a68415c32 Mon Sep 17 00:00:00 2001 From: Anix Date: Sun, 17 May 2020 14:10:30 +0000 Subject: [PATCH 3/8] Chore: added some more tests --- tests/lib/rules/arrow-parens.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/lib/rules/arrow-parens.js b/tests/lib/rules/arrow-parens.js index 2633193e3ab..bb69c222c87 100644 --- a/tests/lib/rules/arrow-parens.js +++ b/tests/lib/rules/arrow-parens.js @@ -104,6 +104,16 @@ const valid = [ parserOptions: { ecmaVersion: 2017 }, options: ["as-needed"] }, + { + code: "var foo = (a , /**/) => b;", + parserOptions: { ecmaVersion: 2017 }, + options: ["as-needed"] + }, + { + code: "var foo = (a\n,\n/**/) => b;", + parserOptions: { ecmaVersion: 2017 }, + options: ["as-needed"] + }, { code: "var foo = (a,//\n) => b;", parserOptions: { ecmaVersion: 2017 }, @@ -113,6 +123,11 @@ const valid = [ code: "const i = (a/**/,) => a + a;", parserOptions: { ecmaVersion: 2017 }, options: ["as-needed"] + }, + { + code: "const i = (a \n /**/,) => a + a;", + parserOptions: { ecmaVersion: 2017 }, + options: ["as-needed"] } ]; From 587c14a2ad156bf8ea7ecd1f3a9f61e3584b0058 Mon Sep 17 00:00:00 2001 From: Anix Date: Sun, 17 May 2020 14:20:52 +0000 Subject: [PATCH 4/8] Chore: removed unnecessary blanklines --- lib/rules/arrow-parens.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js index 88892783a8c..7102408180c 100644 --- a/lib/rules/arrow-parens.js +++ b/lib/rules/arrow-parens.js @@ -136,11 +136,9 @@ module.exports = { } } - return false; } - if (isCommentsInParens(node)) { return; } From c762724144447752d935299de2728e4b1cce5d81 Mon Sep 17 00:00:00 2001 From: Anix Date: Tue, 19 May 2020 10:50:25 +0000 Subject: [PATCH 5/8] Update: added docs example and function refactor --- docs/rules/arrow-parens.md | 2 ++ lib/rules/arrow-parens.js | 38 ++++++-------------------------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/docs/rules/arrow-parens.md b/docs/rules/arrow-parens.md index fbcdbaeff93..0f878c4fd0a 100644 --- a/docs/rules/arrow-parens.md +++ b/docs/rules/arrow-parens.md @@ -159,6 +159,7 @@ Examples of **incorrect** code for this rule with the `"as-needed"` option: a.then((foo) => {}); a.then((foo) => a); a((foo) => { if (true) {} }); +const f = /** @type {number} */(a) => a + a; ``` Examples of **correct** code for this rule with the `"as-needed"` option: @@ -177,6 +178,7 @@ a.then(foo => { if (true) {} }); (a = 10) => a; ([a, b]) => a; ({a, b}) => a; +const f = /** @type {number} */a => a + a; ``` ### requireForBlockBody diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js index 7102408180c..e4ef5985685 100644 --- a/lib/rules/arrow-parens.js +++ b/lib/rules/arrow-parens.js @@ -107,46 +107,21 @@ module.exports = { /** * Checks whether there are comments inside the params or not. - * @param {ASTNode} paramNode node to check - * @returns {boolean} `true` if there are comments inside of braces, else `false` + * @returns {boolean} `true` if there are comments inside of parens, else `false` */ - function isCommentsInParens(paramNode) { + function hasCommentsInParens() { + const closingParenToken = sourceCode.getTokenAfter(firstTokenOfParam, astUtils.isClosingParenToken); - if (paramNode.params.length !== 1) { - return false; - } - - if (!astUtils.isOpeningParenToken(firstTokenOfParam)) { - return false; - } - - if (sourceCode.getCommentsBefore(paramNode.params[0]).length > 0) { - return true; - } - - if (sourceCode.getCommentsAfter(paramNode.params[0]).length > 0) { - return true; - } - - const commaToken = sourceCode.getTokenAfter(paramNode.params[0]); - - if (commaToken.type === "Punctuator" && commaToken.value === ",") { - if (sourceCode.getCommentsAfter(commaToken).length > 0) { - return true; - } - } - - return false; + return closingParenToken && sourceCode.commentsExistBetween(firstTokenOfParam, closingParenToken); } - if (isCommentsInParens(node)) { + if (hasCommentsInParens()) { return; } // "as-needed", { "requireForBlockBody": true }: x => x if ( requireForBlockBody && - node.params.length === 1 && node.params[0].type === "Identifier" && !node.params[0].typeAnnotation && node.body.type !== "BlockStatement" && @@ -182,7 +157,6 @@ module.exports = { // "as-needed": x => x if (asNeeded && - node.params.length === 1 && node.params[0].type === "Identifier" && !node.params[0].typeAnnotation && !node.returnType @@ -216,7 +190,7 @@ module.exports = { } return { - ArrowFunctionExpression: parens + "ArrowFunctionExpression[params.length=1]": parens }; } }; From 80d44bbac0f1c7b2ad21a74ec9be0ec709c3dafd Mon Sep 17 00:00:00 2001 From: Anix Date: Thu, 21 May 2020 07:08:44 +0000 Subject: [PATCH 6/8] Update: changed hasComment checks --- docs/rules/arrow-parens.md | 2 +- lib/rules/arrow-parens.js | 8 ++++++-- tests/lib/rules/arrow-parens.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/docs/rules/arrow-parens.md b/docs/rules/arrow-parens.md index 0f878c4fd0a..36a24f43702 100644 --- a/docs/rules/arrow-parens.md +++ b/docs/rules/arrow-parens.md @@ -178,7 +178,7 @@ a.then(foo => { if (true) {} }); (a = 10) => a; ([a, b]) => a; ({a, b}) => a; -const f = /** @type {number} */a => a + a; +const f = (/** @type {number} */a) => a + a; ``` ### requireForBlockBody diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js index e4ef5985685..99e9381723f 100644 --- a/lib/rules/arrow-parens.js +++ b/lib/rules/arrow-parens.js @@ -110,9 +110,13 @@ module.exports = { * @returns {boolean} `true` if there are comments inside of parens, else `false` */ function hasCommentsInParens() { - const closingParenToken = sourceCode.getTokenAfter(firstTokenOfParam, astUtils.isClosingParenToken); + if (firstTokenOfParam.type === "Punctuator" && firstTokenOfParam.value === "(") { + const closingParenToken = sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken); + + return closingParenToken && sourceCode.commentsExistBetween(firstTokenOfParam, closingParenToken); + } + return false; - return closingParenToken && sourceCode.commentsExistBetween(firstTokenOfParam, closingParenToken); } if (hasCommentsInParens()) { diff --git a/tests/lib/rules/arrow-parens.js b/tests/lib/rules/arrow-parens.js index bb69c222c87..edd1ae6da8a 100644 --- a/tests/lib/rules/arrow-parens.js +++ b/tests/lib/rules/arrow-parens.js @@ -128,6 +128,14 @@ const valid = [ code: "const i = (a \n /**/,) => a + a;", parserOptions: { ecmaVersion: 2017 }, options: ["as-needed"] + }, + { + code: "var bar = ({/*comment here*/a}) => a", + options: ["as-needed"] + }, + { + code: "var bar = (/*comment here*/{a}) => a", + options: ["as-needed"] } ]; @@ -381,6 +389,26 @@ const invalid = [ endLine: 1, endColumn: 12 }] + }, + { + code: `const foo = a => {}; + +// comment between 'a' and an unrelated closing paren + +bar();`, + output: `const foo = (a) => {}; + +// comment between 'a' and an unrelated closing paren + +bar();`, + errors: [{ + line: 1, + column: 13, + type: "ArrowFunctionExpression", + messageId: "expectedParens", + endLine: 1, + endColumn: 14 + }] } ]; From 3ecdd32d5ab83c743879f56d020fc268dfa617a0 Mon Sep 17 00:00:00 2001 From: Anix Date: Thu, 21 May 2020 08:49:04 +0000 Subject: [PATCH 7/8] Update: refactore and docs update --- docs/rules/arrow-parens.md | 2 ++ lib/rules/arrow-parens.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/rules/arrow-parens.md b/docs/rules/arrow-parens.md index 36a24f43702..e537d434fdc 100644 --- a/docs/rules/arrow-parens.md +++ b/docs/rules/arrow-parens.md @@ -160,6 +160,8 @@ a.then((foo) => {}); a.then((foo) => a); a((foo) => { if (true) {} }); const f = /** @type {number} */(a) => a + a; +const g = (/* comment */ a) => a + a; +const h = (a /* comment */) => a + a; ``` Examples of **correct** code for this rule with the `"as-needed"` option: diff --git a/lib/rules/arrow-parens.js b/lib/rules/arrow-parens.js index 99e9381723f..bfd32447ac6 100644 --- a/lib/rules/arrow-parens.js +++ b/lib/rules/arrow-parens.js @@ -110,7 +110,7 @@ module.exports = { * @returns {boolean} `true` if there are comments inside of parens, else `false` */ function hasCommentsInParens() { - if (firstTokenOfParam.type === "Punctuator" && firstTokenOfParam.value === "(") { + if (astUtils.isOpeningParenToken(firstTokenOfParam)) { const closingParenToken = sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken); return closingParenToken && sourceCode.commentsExistBetween(firstTokenOfParam, closingParenToken); From 05e83625816b2a4a09e73b74cd1bf03cb03480d0 Mon Sep 17 00:00:00 2001 From: Anix Date: Thu, 21 May 2020 09:50:53 +0000 Subject: [PATCH 8/8] Docs: added docs example --- docs/rules/arrow-parens.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/rules/arrow-parens.md b/docs/rules/arrow-parens.md index e537d434fdc..e4fc5845af2 100644 --- a/docs/rules/arrow-parens.md +++ b/docs/rules/arrow-parens.md @@ -160,8 +160,8 @@ a.then((foo) => {}); a.then((foo) => a); a((foo) => { if (true) {} }); const f = /** @type {number} */(a) => a + a; -const g = (/* comment */ a) => a + a; -const h = (a /* comment */) => a + a; +const g = /* comment */ (a) => a + a; +const h = (a) /* comment */ => a + a; ``` Examples of **correct** code for this rule with the `"as-needed"` option: @@ -181,6 +181,8 @@ a.then(foo => { if (true) {} }); ([a, b]) => a; ({a, b}) => a; const f = (/** @type {number} */a) => a + a; +const g = (/* comment */ a) => a + a; +const h = (a /* comment */) => a + a; ``` ### requireForBlockBody