From ff5317e93425f93cfdf808609551ee67b2032543 Mon Sep 17 00:00:00 2001 From: "Philip (flip) Kromer" Date: Fri, 3 Jul 2020 14:43:54 -0500 Subject: [PATCH] Update: Improve array-callback-return report message (#13395) * Update: Improve array-callback-return report (explains why) The array-callback-return rule should explain that a return value is required because the surrounding method requires it. This makes it clear that eg. .filter() expects the passed function to return something, rather than a general expectation of that function. The error messages for expectedAtEnd/Inside now read 'Method .{{arrayMethodName}}() expected a value to be returned at the end of {{name}}.' and 'Method .{{arrayMethodName}}() expected a return value from {{name}}.' * Update lib/rules/array-callback-return.js Co-authored-by: Kai Cataldo * Update lib/rules/array-callback-return.js Co-authored-by: Kai Cataldo * Update: Improve array-callback-return report (explains why) patch * Made tests match proposed new message. * fix: forEach message, .from Owner * forEach has a message, and describes why no return value is expected. * present tense ('Array.from expects no' vs 'Array.from expected no') * Added explicit check of the forEach message * fix: cleaner production of full-qyalified method name Co-authored-by: Kai Cataldo --- lib/rules/array-callback-return.js | 31 ++-- tests/lib/rules/array-callback-return.js | 199 ++++++++++++----------- 2 files changed, 121 insertions(+), 109 deletions(-) diff --git a/lib/rules/array-callback-return.js b/lib/rules/array-callback-return.js index 62ba7b72d87..02a96e311e5 100644 --- a/lib/rules/array-callback-return.js +++ b/lib/rules/array-callback-return.js @@ -9,8 +9,6 @@ // Requirements //------------------------------------------------------------------------------ -const lodash = require("lodash"); - const astUtils = require("./utils/ast-utils"); //------------------------------------------------------------------------------ @@ -43,6 +41,19 @@ function isTargetMethod(node) { ); } +/** + * Returns a human-legible description of an array method + * @param {string} arrayMethodName A method name to fully qualify + * @returns {string} the method name prefixed with `Array.` if it is a class method, + * or else `Array.prototype.` if it is an instance method. + */ +function fullMethodName(arrayMethodName) { + if (["from", "of", "isArray"].includes(arrayMethodName)) { + return "Array.".concat(arrayMethodName); + } + return "Array.prototype.".concat(arrayMethodName); +} + /** * Checks whether or not a given node is a function expression which is the * callback of an array method, returning the method name. @@ -153,10 +164,10 @@ module.exports = { ], messages: { - expectedAtEnd: "Expected to return a value at the end of {{name}}.", - expectedInside: "Expected to return a value in {{name}}.", - expectedReturnValue: "{{name}} expected a return value.", - expectedNoReturnValue: "{{name}} did not expect a return value." + expectedAtEnd: "{{arrayMethodName}}() expects a value to be returned at the end of {{name}}.", + expectedInside: "{{arrayMethodName}}() expects a return value from {{name}}.", + expectedReturnValue: "{{arrayMethodName}}() expects a return value from {{name}}.", + expectedNoReturnValue: "{{arrayMethodName}}() expects no useless return value from {{name}}." } }, @@ -202,14 +213,13 @@ module.exports = { } if (messageId) { - let name = astUtils.getFunctionNameWithKind(node); + const name = astUtils.getFunctionNameWithKind(node); - name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name; context.report({ node, loc: astUtils.getFunctionHeadLoc(node, sourceCode), messageId, - data: { name } + data: { name, arrayMethodName: fullMethodName(funcInfo.arrayMethodName) } }); } } @@ -273,7 +283,8 @@ module.exports = { node, messageId, data: { - name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node)) + name: astUtils.getFunctionNameWithKind(funcInfo.node), + arrayMethodName: fullMethodName(funcInfo.arrayMethodName) } }); } diff --git a/tests/lib/rules/array-callback-return.js b/tests/lib/rules/array-callback-return.js index 24b40cb5204..61aabaeb32c 100644 --- a/tests/lib/rules/array-callback-return.js +++ b/tests/lib/rules/array-callback-return.js @@ -115,90 +115,91 @@ ruleTester.run("array-callback-return", rule, { ], invalid: [ - { code: "Array.from(x, function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "Array.from(x, function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "Int32Array.from(x, function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "Int32Array.from(x, function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.every(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.every(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.filter(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.filter(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.find(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.find(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.findIndex(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.findIndex(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.flatMap(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.flatMap(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.map(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.map(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.reduce(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.reduce(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.reduceRight(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.reduceRight(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.some(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.some(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.sort(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.sort(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.bar.baz.every(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.bar.baz.every(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo[\"every\"](function() {})", errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo[\"every\"](function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo[`every`](function() {})", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo[`every`](function foo() {})", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.every(() => {})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected to return a value in arrow function.", column: 14 }] }, - { code: "foo.every(function() { if (a) return true; })", errors: [{ message: "Expected to return a value at the end of function.", column: 11 }] }, - { code: "foo.every(function cb() { if (a) return true; })", errors: [{ message: "Expected to return a value at the end of function 'cb'.", column: 11 }] }, - { code: "foo.every(function() { switch (a) { case 0: break; default: return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function" } }] }, - { code: "foo.every(function foo() { switch (a) { case 0: break; default: return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function 'foo'" } }] }, - { code: "foo.every(function() { try { bar(); } catch (err) { return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function" } }] }, - { code: "foo.every(function foo() { try { bar(); } catch (err) { return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function 'foo'" } }] }, - { code: "foo.every(function() { return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "Function" } }] }, - { code: "foo.every(function foo() { return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "Function 'foo'" } }] }, - { code: "foo.every(function() { if (a) return; })", errors: ["Expected to return a value at the end of function.", { messageId: "expectedReturnValue", data: { name: "Function" } }] }, - { code: "foo.every(function foo() { if (a) return; })", errors: ["Expected to return a value at the end of function 'foo'.", { messageId: "expectedReturnValue", data: { name: "Function 'foo'" } }] }, - { code: "foo.every(function() { if (a) return; else return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "Function" } }, { messageId: "expectedReturnValue", data: { name: "Function" } }] }, - { code: "foo.every(function foo() { if (a) return; else return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "Function 'foo'" } }, { messageId: "expectedReturnValue", data: { name: "Function 'foo'" } }] }, - { code: "foo.every(cb || function() {})", errors: ["Expected to return a value in function."] }, - { code: "foo.every(cb || function foo() {})", errors: ["Expected to return a value in function 'foo'."] }, - { code: "foo.every(a ? function() {} : function() {})", errors: ["Expected to return a value in function.", "Expected to return a value in function."] }, - { code: "foo.every(a ? function foo() {} : function bar() {})", errors: ["Expected to return a value in function 'foo'.", "Expected to return a value in function 'bar'."] }, - { code: "foo.every(function(){ return function() {}; }())", errors: [{ message: "Expected to return a value in function.", column: 30 }] }, - { code: "foo.every(function(){ return function foo() {}; }())", errors: [{ message: "Expected to return a value in function 'foo'.", column: 30 }] }, - { code: "foo.every(() => {})", options: [{ allowImplicit: false }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected to return a value in arrow function." }] }, - { code: "foo.every(() => {})", options: [{ allowImplicit: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected to return a value in arrow function." }] }, + { code: "Array.from(x, function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.from" } }] }, + { code: "Array.from(x, function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.from" } }] }, + { code: "Int32Array.from(x, function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.from" } }] }, + { code: "Int32Array.from(x, function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.from" } }] }, + { code: "foo.every(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.filter(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.filter" } }] }, + { code: "foo.filter(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.filter" } }] }, + { code: "foo.find(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.find" } }] }, + { code: "foo.find(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.find" } }] }, + { code: "foo.findIndex(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.findIndex" } }] }, + { code: "foo.findIndex(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.findIndex" } }] }, + { code: "foo.flatMap(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.flatMap" } }] }, + { code: "foo.flatMap(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.flatMap" } }] }, + { code: "foo.map(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.map" } }] }, + { code: "foo.map(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.map" } }] }, + { code: "foo.reduce(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.reduce" } }] }, + { code: "foo.reduce(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.reduce" } }] }, + { code: "foo.reduceRight(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.reduceRight" } }] }, + { code: "foo.reduceRight(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.reduceRight" } }] }, + { code: "foo.some(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.some" } }] }, + { code: "foo.some(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.some" } }] }, + { code: "foo.sort(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.sort" } }] }, + { code: "foo.sort(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.sort" } }] }, + { code: "foo.bar.baz.every(function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.bar.baz.every(function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo[\"every\"](function() {})", errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo[\"every\"](function foo() {})", errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo[`every`](function() {})", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo[`every`](function foo() {})", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(() => {})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Array.prototype.every() expects a return value from arrow function.", column: 14 }] }, + { code: "foo.every(function() { if (a) return true; })", errors: [{ message: "Array.prototype.every() expects a value to be returned at the end of function.", column: 11 }] }, + { code: "foo.every(function cb() { if (a) return true; })", errors: [{ message: "Array.prototype.every() expects a value to be returned at the end of function 'cb'.", column: 11 }] }, + { code: "foo.every(function() { switch (a) { case 0: break; default: return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function foo() { switch (a) { case 0: break; default: return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function() { try { bar(); } catch (err) { return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function foo() { try { bar(); } catch (err) { return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function() { return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function foo() { return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function() { if (a) return; })", errors: ["Array.prototype.every() expects a value to be returned at the end of function.", { messageId: "expectedReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function foo() { if (a) return; })", errors: ["Array.prototype.every() expects a value to be returned at the end of function 'foo'.", { messageId: "expectedReturnValue", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function() { if (a) return; else return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.every" } }, { messageId: "expectedReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(function foo() { if (a) return; else return; })", errors: [{ messageId: "expectedReturnValue", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }, { messageId: "expectedReturnValue", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(cb || function() {})", errors: ["Array.prototype.every() expects a return value from function."] }, + { code: "foo.every(cb || function foo() {})", errors: ["Array.prototype.every() expects a return value from function 'foo'."] }, + { code: "foo.every(a ? function() {} : function() {})", errors: ["Array.prototype.every() expects a return value from function.", "Array.prototype.every() expects a return value from function."] }, + { code: "foo.every(a ? function foo() {} : function bar() {})", errors: ["Array.prototype.every() expects a return value from function 'foo'.", "Array.prototype.every() expects a return value from function 'bar'."] }, + { code: "foo.every(function(){ return function() {}; }())", errors: [{ message: "Array.prototype.every() expects a return value from function.", column: 30 }] }, + { code: "foo.every(function(){ return function foo() {}; }())", errors: [{ message: "Array.prototype.every() expects a return value from function 'foo'.", column: 30 }] }, + { code: "foo.every(() => {})", options: [{ allowImplicit: false }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Array.prototype.every() expects a return value from arrow function." }] }, + { code: "foo.every(() => {})", options: [{ allowImplicit: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Array.prototype.every() expects a return value from arrow function." }] }, // options: { allowImplicit: true } - { code: "Array.from(x, function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.every(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.filter(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.find(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.map(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.reduce(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.reduceRight(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.bar.baz.every(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.every(cb || function() {})", options: allowImplicitOptions, errors: ["Expected to return a value in function."] }, - { code: "[\"foo\",\"bar\"].sort(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.forEach(x => x)", options: allowImplicitCheckForEach, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Arrow function" } }] }, - { code: "foo.forEach(function(x) { if (a == b) {return x;}})", options: allowImplicitCheckForEach, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function" } }] }, - { code: "foo.forEach(function bar(x) { return x;})", options: allowImplicitCheckForEach, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function 'bar'" } }] }, + { code: "Array.from(x, function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.from" } }] }, + { code: "foo.every(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.filter(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.filter" } }] }, + { code: "foo.find(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.find" } }] }, + { code: "foo.map(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.map" } }] }, + { code: "foo.reduce(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.reduce" } }] }, + { code: "foo.reduceRight(function() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.reduceRight" } }] }, + { code: "foo.bar.baz.every(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.every(cb || function() {})", options: allowImplicitOptions, errors: ["Array.prototype.every() expects a return value from function."] }, + { code: "[\"foo\",\"bar\"].sort(function foo() {})", options: allowImplicitOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.sort" } }] }, + { code: "foo.forEach(x => x)", options: allowImplicitCheckForEach, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function(x) { if (a == b) {return x;}})", options: allowImplicitCheckForEach, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function bar(x) { return x;})", options: allowImplicitCheckForEach, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function 'bar'", arrayMethodName: "Array.prototype.forEach" } }] }, // // options: { checkForEach: true } - { code: "foo.forEach(x => x)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Arrow function" } }] }, - { code: "foo.forEach(val => y += val)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Arrow function" } }] }, - { code: "[\"foo\",\"bar\"].forEach(x => ++x)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Arrow function" } }] }, - { code: "foo.bar().forEach(x => x === y)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Arrow function" } }] }, - { code: "foo.forEach(function() {return function() { if (a == b) { return a; }}}())", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function" } }] }, - { code: "foo.forEach(function(x) { if (a == b) {return x;}})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function" } }] }, - { code: "foo.forEach(function(x) { if (a == b) {return undefined;}})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function" } }] }, - { code: "foo.forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function 'bar'" } }] }, - { code: "foo.bar().forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function 'bar'" } }] }, - { code: "[\"foo\",\"bar\"].forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Function 'bar'" } }] }, - { code: "foo.forEach((x) => { return x;})", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "Arrow function" } }] }, - { code: "Array.from(x, function() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.every(function() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] }, - { code: "foo.filter(function foo() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] }, - { code: "foo.filter(function foo() { return; })", options: checkForEachOptions, errors: [{ messageId: "expectedReturnValue", data: { name: "Function 'foo'" } }] }, - { code: "foo.every(cb || function() {})", options: checkForEachOptions, errors: ["Expected to return a value in function."] }, + { code: "foo.forEach(x => x)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(val => y += val)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "[\"foo\",\"bar\"].forEach(x => ++x)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.bar().forEach(x => x === y)", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function() {return function() { if (a == b) { return a; }}}())", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function(x) { if (a == b) {return x;}})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function(x) { if (a == b) {return undefined;}})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function 'bar'", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: ["Array.prototype.forEach() expects no useless return value from function 'bar'."] }, + { code: "foo.bar().forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function 'bar'", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "[\"foo\",\"bar\"].forEach(function bar(x) { return x;})", options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", data: { name: "function 'bar'", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "foo.forEach((x) => { return x;})", options: checkForEachOptions, parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" } }] }, + { code: "Array.from(x, function() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.from" } }] }, + { code: "foo.every(function() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function", arrayMethodName: "Array.prototype.every" } }] }, + { code: "foo.filter(function foo() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.filter" } }] }, + { code: "foo.filter(function foo() { return; })", options: checkForEachOptions, errors: [{ messageId: "expectedReturnValue", data: { name: "function 'foo'", arrayMethodName: "Array.prototype.filter" } }] }, + { code: "foo.every(cb || function() {})", options: checkForEachOptions, errors: ["Array.prototype.every() expects a return value from function."] }, // full location tests { @@ -206,7 +207,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", - data: { name: "arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.filter" }, type: "ArrowFunctionExpression", line: 1, column: 16, @@ -219,7 +220,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", - data: { name: "arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.filter" }, type: "ArrowFunctionExpression", line: 2, column: 4, @@ -232,7 +233,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", - data: { name: "arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.filter" }, type: "ArrowFunctionExpression", line: 1, column: 26, @@ -245,7 +246,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedReturnValue", - data: { name: "Arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.filter" }, type: "ReturnStatement", line: 1, column: 21, @@ -258,7 +259,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", - data: { name: "arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.from" }, type: "ArrowFunctionExpression", line: 1, column: 21, @@ -272,7 +273,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", - data: { name: "Arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" }, type: "ArrowFunctionExpression", line: 1, column: 17, @@ -286,7 +287,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", - data: { name: "Arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" }, type: "ArrowFunctionExpression", line: 1, column: 41, @@ -300,7 +301,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", - data: { name: "Arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" }, type: "ArrowFunctionExpression", line: 2, column: 13, @@ -314,7 +315,7 @@ ruleTester.run("array-callback-return", rule, { parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedNoReturnValue", - data: { name: "Arrow function" }, + data: { name: "arrow function", arrayMethodName: "Array.prototype.forEach" }, type: "ReturnStatement", line: 1, column: 52, @@ -326,7 +327,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function(){})", errors: [{ messageId: "expectedInside", - data: { name: "function" }, + data: { name: "function", arrayMethodName: "Array.prototype.filter" }, type: "FunctionExpression", line: 1, column: 12, @@ -338,7 +339,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function (){})", errors: [{ messageId: "expectedInside", - data: { name: "function" }, + data: { name: "function", arrayMethodName: "Array.prototype.filter" }, type: "FunctionExpression", line: 1, column: 12, @@ -350,7 +351,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function\n(){})", errors: [{ messageId: "expectedInside", - data: { name: "function" }, + data: { name: "function", arrayMethodName: "Array.prototype.filter" }, type: "FunctionExpression", line: 1, column: 12, @@ -362,7 +363,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function bar(){})", errors: [{ messageId: "expectedInside", - data: { name: "function 'bar'" }, + data: { name: "function 'bar'", arrayMethodName: "Array.prototype.filter" }, type: "FunctionExpression", line: 1, column: 12, @@ -374,7 +375,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function bar (){})", errors: [{ messageId: "expectedInside", - data: { name: "function 'bar'" }, + data: { name: "function 'bar'", arrayMethodName: "Array.prototype.filter" }, type: "FunctionExpression", line: 1, column: 12, @@ -386,7 +387,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function\n bar() {})", errors: [{ messageId: "expectedInside", - data: { name: "function 'bar'" }, + data: { name: "function 'bar'", arrayMethodName: "Array.prototype.filter" }, type: "FunctionExpression", line: 1, column: 12, @@ -398,7 +399,7 @@ ruleTester.run("array-callback-return", rule, { code: "Array.from(foo, function bar(){})", errors: [{ messageId: "expectedInside", - data: { name: "function 'bar'" }, + data: { name: "function 'bar'", arrayMethodName: "Array.from" }, type: "FunctionExpression", line: 1, column: 17, @@ -410,7 +411,7 @@ ruleTester.run("array-callback-return", rule, { code: "Array.from(foo, bar ? function (){} : baz)", errors: [{ messageId: "expectedInside", - data: { name: "function" }, + data: { name: "function", arrayMethodName: "Array.from" }, type: "FunctionExpression", line: 1, column: 23, @@ -422,7 +423,7 @@ ruleTester.run("array-callback-return", rule, { code: "foo.filter(function bar() { return \n })", errors: [{ messageId: "expectedReturnValue", - data: { name: "Function 'bar'" }, + data: { name: "function 'bar'", arrayMethodName: "Array.prototype.filter" }, type: "ReturnStatement", line: 1, column: 29, @@ -435,7 +436,7 @@ ruleTester.run("array-callback-return", rule, { options: checkForEachOptions, errors: [{ messageId: "expectedNoReturnValue", - data: { name: "Function" }, + data: { name: "function", arrayMethodName: "Array.prototype.forEach" }, type: "ReturnStatement", line: 2, column: 10,