Skip to content

Commit 4df3bab

Browse files
authored
Merge pull request #1011 from jomasti/fix-996
Check for createElement being called from React
2 parents 3949b50 + 9b88474 commit 4df3bab

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

lib/util/Components.js

+14
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,23 @@ function componentRule(rule, context) {
256256
node[property] &&
257257
node[property].type === 'JSXElement'
258258
;
259+
var destructuredReactCreateElement = function () {
260+
var variables = variableUtil.variablesInScope(context);
261+
var variable = variableUtil.getVariable(variables, 'createElement');
262+
if (variable) {
263+
var map = variable.scope.set;
264+
if (map.has('React')) {
265+
return true;
266+
}
267+
}
268+
return false;
269+
};
259270
var returnsReactCreateElement =
271+
destructuredReactCreateElement() ||
260272
node[property] &&
261273
node[property].callee &&
274+
node[property].callee.object &&
275+
node[property].callee.object.name === 'React' &&
262276
node[property].callee.property &&
263277
node[property].callee.property.name === 'createElement'
264278
;

lib/util/variable.js

+15-9
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@
1111
* @returns {Boolean} True if the variable was found, false if not.
1212
*/
1313
function findVariable(variables, name) {
14-
var i;
15-
var len;
16-
17-
for (i = 0, len = variables.length; i < len; i++) {
18-
if (variables[i].name === name) {
19-
return true;
20-
}
21-
}
14+
return variables.some(function (variable) {
15+
return variable.name === name;
16+
});
17+
}
2218

23-
return false;
19+
/**
20+
* Find and return a particular variable in a list
21+
* @param {Array} variables The variables list.
22+
* @param {Array} name The name of the variable to search.
23+
* @returns {Object} Variable if the variable was found, null if not.
24+
*/
25+
function getVariable(variables, name) {
26+
return variables.find(function (variable) {
27+
return variable.name === name;
28+
});
2429
}
2530

2631
/**
@@ -52,5 +57,6 @@ function variablesInScope(context) {
5257

5358
module.exports = {
5459
findVariable: findVariable,
60+
getVariable: getVariable,
5561
variablesInScope: variablesInScope
5662
};

tests/lib/rules/display-name.js

+48
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,19 @@ ruleTester.run('display-name', rule, {
378378
')'
379379
].join('\n'),
380380
parser: 'babel-eslint'
381+
}, {
382+
code: [
383+
'module.exports = {',
384+
' createElement: tagName => document.createElement(tagName)',
385+
'};'
386+
].join('\n'),
387+
parser: 'babel-eslint'
388+
}, {
389+
code: [
390+
'const { createElement } = document;',
391+
'createElement("a");'
392+
].join('\n'),
393+
parser: 'babel-eslint'
381394
}],
382395

383396
invalid: [{
@@ -548,5 +561,40 @@ ruleTester.run('display-name', rule, {
548561
errors: [{
549562
message: 'Component definition is missing display name'
550563
}]
564+
}, {
565+
code: [
566+
'import React, { createElement } from "react";',
567+
'export default (props) => {',
568+
' return createElement("div", {}, "hello");',
569+
'};'
570+
].join('\n'),
571+
parser: 'babel-eslint',
572+
errors: [{
573+
message: 'Component definition is missing display name'
574+
}]
575+
}, {
576+
code: [
577+
'import React from "react";',
578+
'const { createElement } = React;',
579+
'export default (props) => {',
580+
' return createElement("div", {}, "hello");',
581+
'};'
582+
].join('\n'),
583+
parser: 'babel-eslint',
584+
errors: [{
585+
message: 'Component definition is missing display name'
586+
}]
587+
}, {
588+
code: [
589+
'import React from "react";',
590+
'const createElement = React.createElement;',
591+
'export default (props) => {',
592+
' return createElement("div", {}, "hello");',
593+
'};'
594+
].join('\n'),
595+
parser: 'babel-eslint',
596+
errors: [{
597+
message: 'Component definition is missing display name'
598+
}]
551599
}]
552600
});

0 commit comments

Comments
 (0)