From 8a999c028f19337e8241f706b2bb1c4e8975efac Mon Sep 17 00:00:00 2001 From: Adam Babcock Date: Wed, 18 Sep 2019 14:39:31 -0500 Subject: [PATCH] `consistent-function-scoping`: Ignore anything containing JSX (#382) --- docs/rules/consistent-function-scoping.md | 12 +++++++ rules/consistent-function-scoping.js | 44 ++++++++++++++++------- test/consistent-function-scoping.js | 32 +++++++++++++++++ 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/docs/rules/consistent-function-scoping.md b/docs/rules/consistent-function-scoping.md index dc0f5f6fa2..45ab23fabe 100644 --- a/docs/rules/consistent-function-scoping.md +++ b/docs/rules/consistent-function-scoping.md @@ -59,3 +59,15 @@ function doFoo(foo) { return foo; } ``` + +It also ignores functions that contain `JSXElement` references: + +```jsx +function doFoo(FooComponent) { + function Bar() { + return ; + } + + return Bar; +}; +``` diff --git a/rules/consistent-function-scoping.js b/rules/consistent-function-scoping.js index c3f9f3a02a..56318861aa 100644 --- a/rules/consistent-function-scoping.js +++ b/rules/consistent-function-scoping.js @@ -121,30 +121,48 @@ const create = context => { const sourceCode = context.getSourceCode(); const {scopeManager} = sourceCode; + const reports = []; + let hasJsx = false; + return { - ArrowFunctionExpression(node) { + ArrowFunctionExpression: node => { const valid = checkNode(node, scopeManager); if (valid) { - return; + reports.push(null); + } else { + reports.push({ + node, + messageId: MESSAGE_ID_ARROW + }); } - - context.report({ - node, - messageId: MESSAGE_ID_ARROW - }); }, - FunctionDeclaration(node) { + FunctionDeclaration: node => { const valid = checkNode(node, scopeManager); if (valid) { - return; + reports.push(null); + } else { + reports.push({ + node, + messageId: MESSAGE_ID_FUNCTION + }); + } + }, + JSXElement: () => { + // Turn off this rule if we see a JSX element because scope + // references does not include JSXElement nodes. + hasJsx = true; + }, + ':matches(ArrowFunctionExpression, FunctionDeclaration):exit': () => { + const report = reports.pop(); + if (report && !hasJsx) { + context.report(report); } - context.report({ - node, - messageId: MESSAGE_ID_FUNCTION - }); + if (reports.length === 0) { + hasJsx = false; + } } }; }; diff --git a/test/consistent-function-scoping.js b/test/consistent-function-scoping.js index 9783bdbb47..ad5eb3cb68 100644 --- a/test/consistent-function-scoping.js +++ b/test/consistent-function-scoping.js @@ -6,6 +6,12 @@ import rule from '../rules/consistent-function-scoping'; const ruleTester = avaRuleTester(test, { env: { es6: true + }, + parserOptions: { + ecmaVersion: 2018, + ecmaFeatures: { + jsx: true + } } }); @@ -156,6 +162,32 @@ ruleTester.run('consistent-function-scoping', rule, { doZaz('zaz'); }; + `, + outdent` + function doFoo() { + return function doBar() {}; + } + `, + outdent` + function doFoo(Foo) { + function doBar() { + return new Foo(); + } + return doBar; + }; + `, + outdent` + function doFoo(FooComponent) { + return ; + } + `, + outdent` + function doFoo(FooComponent) { + function Bar() { + return ; + } + return Bar; + }; ` ], invalid: [