Skip to content
This repository was archived by the owner on Mar 23, 2024. It is now read-only.

Commit df355fa

Browse files
schempymarkelog
authored andcommitted
New rule: disallowUnusedVariables
Fixes #2076 Closes gh-2199
1 parent c5f4aa2 commit df355fa

File tree

2 files changed

+470
-0
lines changed

2 files changed

+470
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* Disallows unused variables defined with var, let or const.
3+
*
4+
* Types: `Boolean`
5+
*
6+
* Values: `true`
7+
*
8+
* #### Example
9+
*
10+
* ```js
11+
* "disallowUnusedVariables": true
12+
* ```
13+
*
14+
* ##### Valid
15+
*
16+
* ```js
17+
* var x=1;
18+
*
19+
* function getX() {
20+
* return x;
21+
* }
22+
*
23+
* ```
24+
*
25+
* ##### Invalid
26+
*
27+
* ```js
28+
* var x=1;
29+
*
30+
* function getX() {
31+
* return true;
32+
* }
33+
*
34+
* ```
35+
*/
36+
37+
var assert = require('assert');
38+
39+
module.exports = function() {};
40+
41+
module.exports.prototype = {
42+
configure: function(options) {
43+
assert(
44+
options === true,
45+
this.getOptionName() + ' option requires a true value or should be removed'
46+
);
47+
},
48+
49+
getOptionName: function() {
50+
return 'disallowUnusedVariables';
51+
},
52+
53+
check: function(file, errors) {
54+
var program = file.getProgram();
55+
var variableList = [];
56+
var nodesToCheck = [];
57+
var unusedNodes = [];
58+
59+
function reportError(node) {
60+
errors.add('Variable `' + node.name + '` is not used', node);
61+
}
62+
63+
function isVariableGood(variable) {
64+
var parentCheck = function(node) {
65+
if (node.parentElement) {
66+
if (node.parentElement.type === 'VariableDeclaration') {
67+
var grandparentElement = node.parentElement.parentElement;
68+
69+
return grandparentElement.type !== 'ExportNamedDeclaration';
70+
} else {
71+
return parentCheck(node.parentElement);
72+
}
73+
} else {
74+
return false;
75+
}
76+
}
77+
78+
var useVariable = variable.definitions.some(function checkVariableDefinition(definition) {
79+
return parentCheck(definition.node);
80+
});
81+
82+
83+
return useVariable;
84+
}
85+
86+
function getVariablesInAllScopes(scope) {
87+
var variableList = [];
88+
89+
var iterateChildScopes = function(scope) {
90+
scope.variables.forEach(function(variable) {
91+
variableList.push(variable);
92+
});
93+
94+
scope.childScopes.forEach(function(childScope){
95+
return iterateChildScopes(childScope);
96+
});
97+
};
98+
99+
iterateChildScopes(scope);
100+
101+
return variableList;
102+
}
103+
104+
// Get all variables in all scopes.
105+
variableList = getVariablesInAllScopes(file.getScopes().acquire(program));
106+
107+
// Check if variables are what we want to check..
108+
variableList.reduce(function(acc, variable) {
109+
if (isVariableGood(variable)) {
110+
acc.push(variable);
111+
}
112+
113+
return acc;
114+
}, nodesToCheck);
115+
116+
// Check if variables are used.
117+
nodesToCheck.reduce(function checkVariableReferences(acc, variable) {
118+
if (variable.references.length === 1) {
119+
variable.definitions.forEach(function addUnusedVariable(definition) {
120+
acc.push(definition.node);
121+
});
122+
}
123+
124+
return acc;
125+
}, unusedNodes);
126+
127+
unusedNodes.forEach(reportError);
128+
},
129+
130+
_fix: function(file, error) {
131+
var node = error.element;
132+
133+
while(node.type !== 'VariableDeclaration') {
134+
node = node.parentElement;
135+
}
136+
137+
node.parentElement.removeChild(node);
138+
error.fixed = true;
139+
}
140+
};

0 commit comments

Comments
 (0)