Skip to content

Commit 6a63a6c

Browse files
committed
Fix variable detection with babel-eslint (fixes #50)
1 parent 43ef52d commit 6a63a6c

File tree

4 files changed

+107
-32
lines changed

4 files changed

+107
-32
lines changed

lib/rules/jsx-uses-react.js

100644100755
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
'use strict';
66

7+
var variableUtil = require('../util/variable');
8+
79
// ------------------------------------------------------------------------------
810
// Rule Definition
911
// ------------------------------------------------------------------------------
@@ -21,7 +23,7 @@ module.exports = function(context) {
2123
return {
2224

2325
JSXOpeningElement: function() {
24-
context.markVariableAsUsed(id);
26+
variableUtil.markVariableAsUsed(context, id);
2527
},
2628

2729
BlockComment: function(node) {

lib/rules/jsx-uses-vars.js

100644100755
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
* @fileoverview Prevent variables used in JSX to be marked as unused
33
* @author Yannick Croissant
44
*/
5-
65
'use strict';
76

7+
var variableUtil = require('../util/variable');
8+
89
// ------------------------------------------------------------------------------
910
// Rule Definition
1011
// ------------------------------------------------------------------------------
@@ -13,13 +14,14 @@ module.exports = function(context) {
1314

1415
return {
1516
JSXExpressionContainer: function(node) {
16-
if (node.expression.type === 'Identifier') {
17-
context.markVariableAsUsed(node.expression.name);
17+
if (node.expression.type !== 'Identifier') {
18+
return;
1819
}
20+
variableUtil.markVariableAsUsed(context, node.expression.name);
1921
},
2022

2123
JSXIdentifier: function(node) {
22-
context.markVariableAsUsed(node.name);
24+
variableUtil.markVariableAsUsed(context, node.name);
2325
}
2426

2527
};

lib/rules/react-in-jsx-scope.js

100644100755
Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
'use strict';
66

7+
var variableUtil = require('../util/variable');
8+
79
// -----------------------------------------------------------------------------
810
// Rule Definition
911
// -----------------------------------------------------------------------------
@@ -15,36 +17,11 @@ module.exports = function(context) {
1517
var id = 'React';
1618
var NOT_DEFINED_MESSAGE = '\'{{name}}\' must be in scope when using JSX';
1719

18-
function findVariable(variables, name) {
19-
var i, len;
20-
for (i = 0, len = variables.length; i < len; i++) {
21-
if (variables[i].name === name) {
22-
return true;
23-
}
24-
}
25-
return false;
26-
}
27-
28-
function variablesInScope() {
29-
var scope = context.getScope(),
30-
variables = scope.variables;
31-
32-
while (scope.type !== 'global') {
33-
scope = scope.upper;
34-
variables = scope.variables.concat(variables);
35-
}
36-
if (scope.childScopes.length) {
37-
variables = scope.childScopes[0].variables.concat(variables);
38-
}
39-
40-
return variables;
41-
}
42-
4320
return {
4421

4522
JSXOpeningElement: function(node) {
46-
var variables = variablesInScope();
47-
if (findVariable(variables, id)) {
23+
var variables = variableUtil.variablesInScope(context);
24+
if (variableUtil.findVariable(variables, id)) {
4825
return;
4926
}
5027
context.report(node, NOT_DEFINED_MESSAGE, {

lib/util/variable.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* @fileoverview Utility functions for React components detection
3+
* @author Yannick Croissant
4+
*/
5+
'use strict';
6+
7+
/**
8+
* Record that a particular variable has been used in code
9+
*
10+
* Similar to the one coming from ESLint but with a patch for babel-eslint
11+
* to avoid https://github.com/babel/babel-eslint/issues/21
12+
*
13+
* @param {String} name The name of the variable to mark as used.
14+
* @returns {Boolean} True if the variable was found and marked as used, false if not.
15+
*/
16+
function markVariableAsUsed(context, name) {
17+
var scope = context.getScope();
18+
var variables;
19+
var i;
20+
var len;
21+
22+
// Special Node.js scope means we need to start one level deeper
23+
if (scope.type === 'global' && scope.childScopes.length) {
24+
scope = scope.childScopes[0];
25+
if (scope.childScopes.length) {
26+
scope = scope.childScopes[0];
27+
}
28+
}
29+
30+
do {
31+
variables = scope.variables;
32+
for (i = 0, len = variables.length; i < len; i++) {
33+
if (variables[i].name === name) {
34+
variables[i].eslintUsed = true;
35+
return true;
36+
}
37+
}
38+
scope = scope.upper;
39+
} while (scope);
40+
41+
return false;
42+
}
43+
44+
/**
45+
* Search a particular variable in a list
46+
* @param {Array} variables The variables list.
47+
* @param {Array} name The name of the variable to search.
48+
* @returns {Boolean} True if the variable was found, false if not.
49+
*/
50+
function findVariable(variables, name) {
51+
var i;
52+
var len;
53+
54+
for (i = 0, len = variables.length; i < len; i++) {
55+
if (variables[i].name === name) {
56+
return true;
57+
}
58+
}
59+
60+
return false;
61+
}
62+
63+
/**
64+
* List all variable in a given scope
65+
*
66+
* Contain a patch for babel-eslint to avoid https://github.com/babel/babel-eslint/issues/21
67+
*
68+
* @param {Object} context The current rule context.
69+
* @param {Array} name The name of the variable to search.
70+
* @returns {Boolean} True if the variable was found, false if not.
71+
*/
72+
function variablesInScope(context) {
73+
var scope = context.getScope();
74+
var variables = scope.variables;
75+
76+
while (scope.type !== 'global') {
77+
scope = scope.upper;
78+
variables = scope.variables.concat(variables);
79+
}
80+
if (scope.childScopes.length) {
81+
variables = scope.childScopes[0].variables.concat(variables);
82+
if (scope.childScopes[0].childScopes.length) {
83+
variables = scope.childScopes[0].childScopes[0].variables.concat(variables);
84+
}
85+
}
86+
87+
return variables;
88+
}
89+
90+
module.exports = {
91+
findVariable: findVariable,
92+
variablesInScope: variablesInScope,
93+
markVariableAsUsed: markVariableAsUsed
94+
};

0 commit comments

Comments
 (0)