Skip to content

Commit 80ed1a0

Browse files
committed
Merge pull request #181 from Gillespie59/development
0.8.0
2 parents 8a7683a + c224914 commit 80ed1a0

File tree

4 files changed

+166
-1
lines changed

4 files changed

+166
-1
lines changed

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'ng_definedundefined': require('./rules/ng_definedundefined'),
1313
'ng_di': require('./rules/ng_di'),
1414
'ng_di_order': require('./rules/ng_di_order'),
15+
'ng_di_unused': require('./rules/ng_di_unused'),
1516
'ng_directive_name': require('./rules/ng_directive_name'),
1617
'ng_document_service': require('./rules/ng_document_service'),
1718
'ng_empty_controller': require('./rules/ng_empty_controller'),
@@ -55,6 +56,7 @@
5556
'ng_definedundefined': 2,
5657
'ng_di': [2, 'function'],
5758
'ng_di_order': 0,
59+
'ng_di_unused': 0,
5860
'ng_directive_name': 0,
5961
'ng_document_service': 2,
6062
'ng_empty_controller': 0,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eslint-plugin-angular",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"description": "ESLint rules for AngularJS projects",
55
"main": "index.js",
66
"repository": {

rules/ng_di_unused.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
module.exports = function(context) {
2+
3+
'use strict';
4+
5+
var utils = require('./utils/utils');
6+
7+
var angularNamedObjectList = [
8+
'controller',
9+
'directive',
10+
'factory',
11+
'filter',
12+
'provider',
13+
'service'
14+
];
15+
var setupCalls = [
16+
'config',
17+
'run'
18+
];
19+
20+
var injectFunctions = [];
21+
22+
// Keeps track of visited scopes in the collectAngularScopes function to prevent infinite recursion on circular references.
23+
var visitedScopes = [];
24+
25+
// This collects the variable scopes for the injectible functions which have been collected.
26+
function collectAngularScopes(scope) {
27+
if(visitedScopes.indexOf(scope) === -1) {
28+
visitedScopes.push(scope);
29+
injectFunctions.forEach(function(value) {
30+
if(scope.block === value.node) {
31+
value.scope = scope;
32+
}
33+
});
34+
scope.childScopes.forEach(function(child) {
35+
collectAngularScopes(child);
36+
});
37+
}
38+
}
39+
40+
return {
41+
42+
'AssignmentExpression': function(node) {
43+
// Colllect the $get function of a providers.
44+
if(node.left.type === 'MemberExpression' && node.left.property.name === '$get') {
45+
injectFunctions.push({
46+
node: node.right
47+
});
48+
}
49+
},
50+
51+
'CallExpression': function(node) {
52+
// An Angular component definition.
53+
if(utils.isAngularComponent(node) && node.callee.type === 'MemberExpression' && node.arguments[1].type === 'FunctionExpression' && angularNamedObjectList.indexOf(node.callee.property.name) >= 0){
54+
return injectFunctions.push({
55+
node: node.arguments[1]
56+
});
57+
}
58+
// Config and run functions.
59+
if(node.callee.type === 'MemberExpression' && node.arguments.length > 0 && setupCalls.indexOf(node.callee.property.name) !== -1 && node.arguments[0].type === 'FunctionExpression') {
60+
return injectFunctions.push({
61+
node: node.arguments[0]
62+
});
63+
}
64+
// Injected values in unittests.
65+
if(node.callee.type === 'Identifier' && node.callee.name === 'inject') {
66+
return injectFunctions.push({
67+
node: node.arguments[0]
68+
});
69+
}
70+
},
71+
72+
// Actually find and report unused injected variables.
73+
'Program:exit': function(node) {
74+
var globalScope = context.getScope();
75+
collectAngularScopes(globalScope);
76+
injectFunctions.forEach(function(value) {
77+
if(value.scope) {
78+
value.scope.variables.forEach(function(variable) {
79+
if(variable.name === 'arguments') {
80+
return;
81+
}
82+
if(value.node.params.indexOf(variable.identifiers[0]) === -1) {
83+
return;
84+
}
85+
if(variable.references.length === 0) {
86+
context.report(value.node, 'Unused injected value {{name}}', variable);
87+
}
88+
});
89+
}
90+
})
91+
}
92+
};
93+
};

test/ng_di_unused.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//------------------------------------------------------------------------------
2+
// Requirements
3+
//------------------------------------------------------------------------------
4+
5+
var rule = require('../rules/ng_di_unused'),
6+
RuleTester = require("eslint").RuleTester;
7+
8+
//------------------------------------------------------------------------------
9+
// Tests
10+
//------------------------------------------------------------------------------
11+
12+
var eslintTester = new RuleTester();
13+
eslintTester.run('ng_di_unused', rule, {
14+
valid: [
15+
'app.controller("", function($q){return $q;});',
16+
'app.directive("", function($q){return $q;});',
17+
'app.factory("", function($q){return $q;});',
18+
'app.factory("", function($q){return function(){return $q;};});',
19+
'app.factory("", function(){var myVar;});',
20+
'app.filter("", function($q){return $q;});',
21+
'app.provider("", function($httpProvider){return $httpProvider;});',
22+
'app.service("", function($q){return $q;});',
23+
'app.config(function($httpProvider) {$httpProvider.defaults.headers.post.answer="42"})',
24+
'app.run(function($q) {$q()})',
25+
'inject(function($q){_$q_ = $q;});',
26+
'this.$get = function($q){return $q;};',
27+
],
28+
invalid: [{
29+
code: 'app.controller("", function($q){});',
30+
errors: [{message: 'Unused injected value $q'}]
31+
}, {
32+
code: 'app.directive("", function($q){});',
33+
errors: [{message: 'Unused injected value $q'}]
34+
}, {
35+
code: 'app.factory("", function($q){});',
36+
errors: [{message: 'Unused injected value $q'}]
37+
}, {
38+
code: 'app.factory("", function($http, $q){});',
39+
errors: [
40+
{message: 'Unused injected value $http'},
41+
{message: 'Unused injected value $q'}
42+
]
43+
}, {
44+
code: 'app.factory("", function($http, $q){return $q.resolve()});',
45+
errors: [
46+
{message: 'Unused injected value $http'}
47+
]
48+
}, {
49+
code: 'app.filter("", function($q){});',
50+
errors: [{message: 'Unused injected value $q'}]
51+
}, {
52+
code: 'app.provider("", function($httpProvider){});',
53+
errors: [{message: 'Unused injected value $httpProvider'}]
54+
}, {
55+
code: 'app.service("", function($q){});',
56+
errors: [{message: 'Unused injected value $q'}]
57+
}, {
58+
code: 'app.config(function($httpProvider) {})',
59+
errors: [{message: 'Unused injected value $httpProvider'}]
60+
}, {
61+
code: 'app.run(function($q){});',
62+
errors: [{message: 'Unused injected value $q'}]
63+
}, {
64+
code: 'inject(function($q){});',
65+
errors: [{message: 'Unused injected value $q'}]
66+
}, {
67+
code: 'this.$get = function($q){};',
68+
errors: [{message: 'Unused injected value $q'}]
69+
}]
70+
});

0 commit comments

Comments
 (0)