Skip to content

Commit b77be96

Browse files
authored
Merge pull request #1995 from sergei-startsev/fix-1960-no-this-in-sfc
Fix `no-this-in-sfc` for class properties
2 parents aef3ee9 + e779b00 commit b77be96

File tree

3 files changed

+60
-16
lines changed

3 files changed

+60
-16
lines changed

lib/util/Components.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -457,15 +457,12 @@ function componentRule(rule, context) {
457457
let scope = context.getScope();
458458
while (scope) {
459459
const node = scope.block;
460-
const isClass = node.type === 'ClassExpression';
461460
const isFunction = /Function/.test(node.type); // Functions
462-
const isArrowFunction = node.type === 'ArrowFunctionExpression';
463-
let functionScope = scope;
464-
if (isArrowFunction) {
465-
functionScope = utils.getParentFunctionScope(scope);
466-
}
467-
const methodNode = functionScope && functionScope.block.parent;
468-
const isMethod = methodNode && methodNode.type === 'MethodDefinition'; // Classes methods
461+
const isArrowFunction = astUtil.isArrowFunction(node);
462+
const enclosingScope = isArrowFunction ? utils.getArrowFunctionScope(scope) : scope;
463+
const enclosingScopeParent = enclosingScope && enclosingScope.block.parent;
464+
const isClass = enclosingScope && astUtil.isClass(enclosingScope.block);
465+
const isMethod = enclosingScopeParent && enclosingScopeParent.type === 'MethodDefinition'; // Classes methods
469466
const isArgument = node.parent && node.parent.type === 'CallExpression'; // Arguments (callback, etc.)
470467
// Attribute Expressions inside JSX Elements (<button onClick={() => props.handleClick()}></button>)
471468
const isJSXExpressionContainer = node.parent && node.parent.type === 'JSXExpressionContainer';
@@ -483,15 +480,14 @@ function componentRule(rule, context) {
483480
},
484481

485482
/**
486-
* Get a parent scope created by a FunctionExpression or FunctionDeclaration
487-
* @param {Scope} scope The child scope
488-
* @returns {Scope} A parent function scope
483+
* Get an enclosing scope used to find `this` value by an arrow function
484+
* @param {Scope} scope Current scope
485+
* @returns {Scope} An enclosing scope used by an arrow function
489486
*/
490-
getParentFunctionScope(scope) {
487+
getArrowFunctionScope(scope) {
491488
scope = scope.upper;
492489
while (scope) {
493-
const type = scope.block.type;
494-
if (type === 'FunctionExpression' || type === 'FunctionDeclaration') {
490+
if (astUtil.isFunction(scope.block) || astUtil.isClass(scope.block)) {
495491
return scope;
496492
}
497493
scope = scope.upper;

lib/util/ast.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,41 @@ function isFunctionLikeExpression(node) {
102102
return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';
103103
}
104104

105+
/**
106+
* Checks if the node is a function.
107+
* @param {Object} context The node to check
108+
* @return {Boolean} true if it's a function
109+
*/
110+
function isFunction(node) {
111+
return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration';
112+
}
113+
114+
/**
115+
* Checks if the node is an arrow function.
116+
* @param {Object} context The node to check
117+
* @return {Boolean} true if it's an arrow function
118+
*/
119+
function isArrowFunction(node) {
120+
return node.type === 'ArrowFunctionExpression';
121+
}
122+
123+
/**
124+
* Checks if the node is a class.
125+
* @param {Object} context The node to check
126+
* @return {Boolean} true if it's a class
127+
*/
128+
function isClass(node) {
129+
return node.type === 'ClassDeclaration' || node.type === 'ClassExpression';
130+
}
131+
105132
module.exports = {
106133
findReturnStatement: findReturnStatement,
107134
getPropertyName: getPropertyName,
108135
getPropertyNameNode: getPropertyNameNode,
109136
getComponentProperties: getComponentProperties,
110-
isNodeFirstInLine: isNodeFirstInLine,
111-
isFunctionLikeExpression: isFunctionLikeExpression
137+
isArrowFunction: isArrowFunction,
138+
isClass: isClass,
139+
isFunction: isFunction,
140+
isFunctionLikeExpression: isFunctionLikeExpression,
141+
isNodeFirstInLine: isNodeFirstInLine
112142
};

tests/lib/rules/no-this-in-sfc.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,24 @@ ruleTester.run('no-this-in-sfc', rule, {
119119
};
120120
}
121121
}`
122+
}, {
123+
code: `
124+
class Foo {
125+
bar = () => {
126+
this.something();
127+
return null;
128+
};
129+
}`,
130+
parser: 'babel-eslint'
131+
}, {
132+
code: `
133+
class Foo {
134+
bar = () => () => {
135+
this.something();
136+
return null;
137+
};
138+
}`,
139+
parser: 'babel-eslint'
122140
}],
123141
invalid: [{
124142
code: `

0 commit comments

Comments
 (0)