Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Users may use the shareable [eslint-config-angular](https://github.com/dustinspe
| controller-name | All your controllers should have a name starting with the parameter you can define in your config object. The second parameter can be a Regexp wrapped in quotes. ("controller-name": [2, "ng"]) [Y123](https://github.com/johnpapa/angular-styleguide#style-y123), [Y124](https://github.com/johnpapa/angular-styleguide#style-y124)|
| deferred | When you want to create a new promise, you should not use the $q.deferred anymore. Prefer the new syntax : $q(function(resolve, reject){}) |
| definedundefined | You should use the angular.isUndefined or angular.isDefined methods instead of using the keyword undefined. We also check the use of !angular.isUndefined and !angular.isDefined (should prefer the reverse function)|
| di | All your DI should use the same syntax : the Array or function syntaxes ("di": [2, "function or array"])|
| di | All your DI should use the same syntax : the Array, function, or $inject syntaxes ("di": [2, "array, function, or $inject"])|
| di-order | Injected dependencies should be sorted alphabetically. If the second parameter is set to false, values which start and end with an underscore those underscores are stripped. This means for example that `_$httpBackend_` goes before `_$http_`. |
| directive-name | All your directives should have a name starting with the parameter you can define in your config object. The second parameter can be a Regexp wrapped in quotes. You can not prefix your directives by "ng" (reserved keyword for AngularJS directives) ("directive-name": [2, "ng"]) [Y073](https://github.com/johnpapa/angular-styleguide#style-y073), [Y126](https://github.com/johnpapa/angular-styleguide#style-y126) |
| directive-restrict | Not all directive restrictions may be desirable. Also it might be desirable to define default restrictions, or explicitly not. The default configuration limits the restrictions `AE` [Y074](https://github.com/johnpapa/angular-styleguide#style-y074) and disallows explicitly specifying a default. ("directive-restrict": [0, {"restrict": "AE", "explicit": "never"}]) |
Expand Down
44 changes: 39 additions & 5 deletions rules/di.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,46 @@ module.exports = function(context) {
});
}

var noninjectedFunctions = {};
var injectedFunctions = [];

function checkDi(syntax, node, param) {
if (syntax === 'function' && (!utils.isFunctionType(param) && !utils.isIdentifierType(param))) {
report(node, syntax);
}
if (syntax === 'array') {
if (!utils.isArrayType(param)) {
report(node, syntax);
} else {
} else if (syntax === 'array') {
if (utils.isArrayType(param)) {
var fn = param.elements[param.elements.length - 1];
if (utils.isFunctionType(fn) && fn.params.length !== param.elements.length - 1) {
context.report(fn, 'The signature of the method is incorrect', {});
}
} else {
report(node, syntax);
}
} else if (syntax === '$inject') {
if (utils.isIdentifierType(param)) {
noninjectedFunctions[param.name] = node;
} else {
report(node, syntax);
}
}
}

function maybeNoteInjection(syntax, node) {
if (syntax === '$inject' && node.left && node.left.property &&
((utils.isLiteralType(node.left.property) && node.left.property.value === '$inject') ||
(utils.isIdentifierType(node.left.property) && node.left.property.name === '$inject'))) {
injectedFunctions.push(node.left.object.name);
}
}

function verifyInjections(syntax) {
if (syntax === '$inject') {
injectedFunctions.forEach(function(f) {
delete noninjectedFunctions[f];
});

for (var func in noninjectedFunctions) {
report(noninjectedFunctions[func], syntax);
}
}
}
Expand All @@ -41,6 +69,12 @@ module.exports = function(context) {
*/
checkDi(context.options[0], node, node.arguments[0]);
}
},
AssignmentExpression: function(node) {
maybeNoteInjection(context.options[0], node);
},
'Program:exit': function() {
verifyInjections(context.options[0]);
}
};
};
Expand Down
59 changes: 59 additions & 0 deletions test/di.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ angularObjectList.forEach(function(object) {
}, {
code: 'angular.' + object + '(myFunction);function MyFunction() {}',
options: ['function']
}, {
code: 'angular.' + object + '(myFunction);myFunction.$inject=[];function myFunction() {}',
options: ['$inject']
}, {
code: 'angular.' + object + '(myFunction);myFunction["$inject"]=[];function myFunction() {}',
options: ['$inject']
}, {
code: 'myFunction.$inject=[];function myFunction() {} angular.' + object + '(myFunction);',
options: ['$inject']
}, {
code: 'function myFunction() {} myFunction.$inject=[];angular.' + object + '(myFunction);',
options: ['$inject']
}, {
code: 'var myFunction = function() {}; myFunction.$inject=[];angular.' + object + '(myFunction);',
options: ['$inject']
});

invalid.push({
Expand All @@ -46,6 +61,22 @@ angularObjectList.forEach(function(object) {
code: 'angular.' + object + '([function(Service1) {}]);',
options: ['array'],
errors: [{message: 'The signature of the method is incorrect'}]
}, {
code: 'angular.' + object + '(myFunction); function myFunction() {}',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
}, {
code: 'function myFunction() {} angular.' + object + '(myFunction);',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
}, {
code: 'var myFunction = function() {};angular.' + object + '(myFunction);',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
}, {
code: 'angular.' + object + '(function() {});',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
});
});

Expand All @@ -62,6 +93,18 @@ angularNamedObjectList.forEach(function(object) {
}, {
code: 'angular.' + object + '("name", myFunction);function MyFunction() {}',
options: ['function']
}, {
code: 'angular.' + object + '("name", myFunction);myFunction.$inject=[];function myFunction() {}',
options: ['$inject']
}, {
code: 'myFunction.$inject=[];function myFunction() {} angular.' + object + '("name", myFunction);',
options: ['$inject']
}, {
code: 'function myFunction() {} myFunction.$inject=[];angular.' + object + '("name", myFunction);',
options: ['$inject']
}, {
code: 'var myFunction = function() {}; myFunction.$inject=[];angular.' + object + '("name", myFunction);',
options: ['$inject']
});

invalid.push({
Expand All @@ -80,6 +123,22 @@ angularNamedObjectList.forEach(function(object) {
code: 'angular.' + object + '("name", [function(Service1) {}]);',
options: ['array'],
errors: [{message: 'The signature of the method is incorrect'}]
}, {
code: 'angular.' + object + '("name", myFunction); function myFunction() {}',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
}, {
code: 'function myFunction() {} angular.' + object + '("name", myFunction);',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
}, {
code: 'var myFunction = function () {};angular.' + object + '("name", myFunction);',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
}, {
code: 'angular.' + object + '("name", function() {});',
options: ['$inject'],
errors: [{message: 'You should use the $inject syntax for DI'}]
});
});

Expand Down