Skip to content

Commit

Permalink
Fix no-this-in-sfc for class properties
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-startsev committed Sep 24, 2018
1 parent bd083bf commit 68d6384
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
22 changes: 12 additions & 10 deletions lib/util/Components.js
Expand Up @@ -456,15 +456,16 @@ function componentRule(rule, context) {
let scope = context.getScope();
while (scope) {
const node = scope.block;
const isClass = node.type === 'ClassExpression';
const isFunction = /Function/.test(node.type); // Functions
const isArrowFunction = node.type === 'ArrowFunctionExpression';
let functionScope = scope;
let enclosingScope = scope;
if (isArrowFunction) {
functionScope = utils.getParentFunctionScope(scope);
enclosingScope = utils.getArrowFunctionScope(scope);
}
const methodNode = functionScope && functionScope.block.parent;
const isMethod = methodNode && methodNode.type === 'MethodDefinition'; // Classes methods
const enclosingScopeType = enclosingScope && enclosingScope.block.type;
const enclosingScopeParent = enclosingScope && enclosingScope.block.parent;
const isClass = enclosingScopeType === 'ClassDeclaration' || enclosingScopeType === 'ClassExpression';
const isMethod = enclosingScopeParent && enclosingScopeParent.type === 'MethodDefinition'; // Classes methods
const isArgument = node.parent && node.parent.type === 'CallExpression'; // Arguments (callback, etc.)
// Attribute Expressions inside JSX Elements (<button onClick={() => props.handleClick()}></button>)
const isJSXExpressionContainer = node.parent && node.parent.type === 'JSXExpressionContainer';
Expand All @@ -482,15 +483,16 @@ function componentRule(rule, context) {
},

/**
* Get a parent scope created by a FunctionExpression or FunctionDeclaration
* @param {Scope} scope The child scope
* @returns {Scope} A parent function scope
* Get an enclosing scope used to find `this` value by an arrow function
* @param {Scope} scope Current scope
* @returns {Scope} An enclosing scope used by an arrow function
*/
getParentFunctionScope(scope) {
getArrowFunctionScope(scope) {
scope = scope.upper;
while (scope) {
const type = scope.block.type;
if (type === 'FunctionExpression' || type === 'FunctionDeclaration') {
if (type === 'FunctionExpression' || type === 'FunctionDeclaration'
|| type === 'ClassDeclaration' || type === 'ClassExpression') {
return scope;
}
scope = scope.upper;
Expand Down
20 changes: 20 additions & 0 deletions tests/lib/rules/no-this-in-sfc.js
Expand Up @@ -16,6 +16,8 @@ const ERROR_MESSAGE = 'Stateless functional components should not use this';
const rule = require('../../../lib/rules/no-this-in-sfc');
const RuleTester = require('eslint').RuleTester;

require('babel-eslint');

const parserOptions = {
ecmaVersion: 2018,
sourceType: 'module',
Expand Down Expand Up @@ -119,6 +121,24 @@ ruleTester.run('no-this-in-sfc', rule, {
};
}
}`
}, {
code: `
class Foo {
bar = () => {
this.something();
return null;
};
}`,
parser: 'babel-eslint'
}, {
code: `
class Foo {
bar = () => () => {
this.something();
return null;
};
}`,
parser: 'babel-eslint'
}],
invalid: [{
code: `
Expand Down

0 comments on commit 68d6384

Please sign in to comment.