From 4ed2adf17665994530509195330e54c47e43ee29 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Sat, 20 Jun 2020 15:10:29 +0800 Subject: [PATCH] Improve `consistent-function-scoping` message (#773) --- package.json | 2 +- rules/consistent-function-scoping.js | 25 ++------- test/consistent-function-scoping.js | 82 ++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index f8f1b8944c..dbd82ad792 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "clean-regexp": "^1.0.0", "eslint-ast-utils": "^1.1.0", "eslint-template-visitor": "^2.0.0", - "eslint-utils": "^2.0.0", + "eslint-utils": "^2.1.0", "import-modules": "^2.0.0", "lodash": "^4.17.15", "pluralize": "^8.0.0", diff --git a/rules/consistent-function-scoping.js b/rules/consistent-function-scoping.js index 864a430888..33f92102cb 100644 --- a/rules/consistent-function-scoping.js +++ b/rules/consistent-function-scoping.js @@ -1,9 +1,9 @@ 'use strict'; +const {getFunctionNameWithKind} = require('eslint-utils'); const getDocumentationUrl = require('./utils/get-documentation-url'); const getReferences = require('./utils/get-references'); -const MESSAGE_ID_NAMED = 'named'; -const MESSAGE_ID_ANONYMOUS = 'anonymous'; +const MESSAGE_ID = 'consistent-function-scoping'; const isSameScope = (scope1, scope2) => scope1 && scope2 && (scope1 === scope2 || scope1.block === scope2.block); @@ -163,25 +163,11 @@ const create = context => { }, ':matches(ArrowFunctionExpression, FunctionDeclaration):exit': node => { if (!hasJsx && !checkNode(node, scopeManager)) { - const functionType = node.type === 'ArrowFunctionExpression' ? 'arrow function' : 'function'; - let functionName = ''; - if (node.id) { - functionName = node.id.name; - } else if ( - node.parent && - node.parent.type === 'VariableDeclarator' && - node.parent.id && - node.parent.id.type === 'Identifier' - ) { - functionName = node.parent.id.name; - } - context.report({ node, - messageId: functionName ? MESSAGE_ID_NAMED : MESSAGE_ID_ANONYMOUS, + messageId: MESSAGE_ID, data: { - functionType, - functionName + functionNameWithKind: getFunctionNameWithKind(node) } }); } @@ -202,8 +188,7 @@ module.exports = { url: getDocumentationUrl(__filename) }, messages: { - [MESSAGE_ID_NAMED]: 'Move {{functionType}} `{{functionName}}` to the outer scope.', - [MESSAGE_ID_ANONYMOUS]: 'Move {{functionType}} to the outer scope.' + [MESSAGE_ID]: 'Move {{functionNameWithKind}} to the outer scope.' } } }; diff --git a/test/consistent-function-scoping.js b/test/consistent-function-scoping.js index a72317339e..6754dee928 100644 --- a/test/consistent-function-scoping.js +++ b/test/consistent-function-scoping.js @@ -17,14 +17,12 @@ const typescriptRuleTester = avaRuleTester(test, { parser: require.resolve('@typescript-eslint/parser') }); -const MESSAGE_ID_NAMED = 'named'; -const MESSAGE_ID_ANONYMOUS = 'anonymous'; +const MESSAGE_ID = 'consistent-function-scoping'; -const createError = ({name, arrow}) => ({ - messageId: name ? MESSAGE_ID_NAMED : MESSAGE_ID_ANONYMOUS, +const createError = functionNameWithKind => ({ + messageId: MESSAGE_ID, data: { - functionType: arrow ? 'arrow function' : 'function', - functionName: name + functionNameWithKind } }); @@ -332,7 +330,7 @@ ruleTester.run('consistent-function-scoping', rule, { return foo; } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -344,7 +342,7 @@ ruleTester.run('consistent-function-scoping', rule, { return foo; } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -354,7 +352,7 @@ ruleTester.run('consistent-function-scoping', rule, { } } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -364,13 +362,13 @@ ruleTester.run('consistent-function-scoping', rule, { } } `, - errors: [createError({name: 'doBar', arrow: true})] + errors: [createError('arrow function \'doBar\'')] }, { code: outdent` const doFoo = () => bar => bar; `, - errors: [createError({arrow: true})] + errors: [createError('arrow function')] }, // `this` { @@ -382,7 +380,7 @@ ruleTester.run('consistent-function-scoping', rule, { return doBar(); }; `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -391,7 +389,7 @@ ruleTester.run('consistent-function-scoping', rule, { return doBar(); }; `, - errors: [createError({name: 'doBar', arrow: true})] + errors: [createError('arrow function \'doBar\'')] }, { code: outdent` @@ -400,7 +398,7 @@ ruleTester.run('consistent-function-scoping', rule, { return doBar(); }; `, - errors: [createError({name: 'doBar', arrow: true})] + errors: [createError('arrow function \'doBar\'')] }, // `arguments` { @@ -412,7 +410,7 @@ ruleTester.run('consistent-function-scoping', rule, { return doBar(); }; `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -421,7 +419,7 @@ ruleTester.run('consistent-function-scoping', rule, { return doBar(); }; `, - errors: [createError({name: 'doBar', arrow: true})] + errors: [createError('arrow function \'doBar\'')] }, { code: outdent` @@ -432,7 +430,7 @@ ruleTester.run('consistent-function-scoping', rule, { return foo; } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -443,7 +441,7 @@ ruleTester.run('consistent-function-scoping', rule, { return doBar; } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -451,7 +449,7 @@ ruleTester.run('consistent-function-scoping', rule, { function doBar() {} } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -466,7 +464,7 @@ ruleTester.run('consistent-function-scoping', rule, { return foo; } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -478,7 +476,7 @@ ruleTester.run('consistent-function-scoping', rule, { } } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] }, { code: outdent` @@ -488,7 +486,43 @@ ruleTester.run('consistent-function-scoping', rule, { } } `, - errors: [createError({name: 'doBar'})] + errors: [createError('function \'doBar\'')] + }, + // Function kinds and names + { + code: 'function foo() { function bar() {} }', + errors: [createError('function \'bar\'')] + }, + { + code: 'function foo() { async function bar() {} }', + errors: [createError('async function \'bar\'')] + }, + { + code: 'function foo() { function* bar() {} }', + errors: [createError('generator function \'bar\'')] + }, + { + code: 'function foo() { async function* bar() {} }', + errors: [createError('async generator function \'bar\'')] + }, + { + code: 'function foo() { const bar = () => {} }', + errors: [createError('arrow function \'bar\'')] + }, + { + code: 'const doFoo = () => bar => bar;', + errors: [createError('arrow function')] + }, + { + code: 'function foo() { const bar = async () => {} }', + errors: [createError('async arrow function \'bar\'')] + }, + // Actual message + { + code: 'function foo() { async function* bar() {} }', + errors: [{ + message: 'Move async generator function \'bar\' to the outer scope.' + }] }, // React Hooks { @@ -500,7 +534,7 @@ ruleTester.run('consistent-function-scoping', rule, { } }, []) `, - errors: [createError({name: 'bar'})] + errors: [createError('function \'bar\'')] }, // IIFE { @@ -512,7 +546,7 @@ ruleTester.run('consistent-function-scoping', rule, { } })(); `, - errors: [createError({name: 'bar'})] + errors: [createError('function \'bar\'')] } ] });