UNPKG

4.82 kBJavaScriptView Raw
1/**
2 * require a consistent DI syntax
3 *
4 * All your DI should use the same syntax : the Array, function, or $inject syntaxes ("di": [2, "array, function, or $inject"])
5 *
6 * @version 0.1.0
7 * @category conventions
8 * @sinceAngularVersion 1.x
9 */
10'use strict';
11
12var utils = require('./utils/utils');
13
14var angularRule = require('./utils/angular-rule');
15
16
17module.exports = {
18 meta: {
19 schema: [{
20 enum: [
21 'function',
22 'array',
23 '$inject'
24 ]
25 }, {
26 type: 'object',
27 properties: {
28 matchNames: {
29 type: 'boolean'
30 }
31 }
32 }]
33 },
34 create: angularRule(function(context) {
35 var syntax = context.options[0] || 'function';
36
37 var extra = context.options[1] || {};
38 var matchNames = extra.matchNames !== false;
39
40 function report(node) {
41 context.report(node, 'You should use the {{syntax}} syntax for DI', {
42 syntax: syntax
43 });
44 }
45
46 var $injectProperties = {};
47
48 function maybeNoteInjection(node) {
49 if (syntax === '$inject' && node.left && node.left.property &&
50 ((utils.isLiteralType(node.left.property) && node.left.property.value === '$inject') ||
51 (utils.isIdentifierType(node.left.property) && node.left.property.name === '$inject'))) {
52 $injectProperties[node.left.object.name] = node.right;
53 }
54 }
55
56 function checkDi(callee, fn) {
57 if (!fn) {
58 return;
59 }
60
61 if (syntax === 'array') {
62 if (utils.isArrayType(fn.parent)) {
63 if (fn.parent.elements.length - 1 !== fn.params.length) {
64 context.report(fn, 'The signature of the method is incorrect', {});
65 return;
66 }
67
68 if (matchNames) {
69 var invalidArray = fn.params.filter(function(e, i) {
70 return e.name !== fn.parent.elements[i].value;
71 });
72 if (invalidArray.length > 0) {
73 context.report(fn, 'You have an error in your DI configuration. Each items of the array should match exactly one function parameter', {});
74 return;
75 }
76 }
77 } else {
78 if (fn.params.length === 0) {
79 return;
80 }
81 report(fn);
82 }
83 }
84
85 if (syntax === 'function') {
86 if (utils.isArrayType(fn.parent)) {
87 report(fn);
88 }
89 }
90
91 if (syntax === '$inject') {
92 if (fn && fn.id && utils.isIdentifierType(fn.id)) {
93 var $injectArray = $injectProperties[fn.id.name];
94
95 if ($injectArray && utils.isArrayType($injectArray)) {
96 if ($injectArray.elements.length !== fn.params.length) {
97 context.report(fn, 'The signature of the method is incorrect', {});
98 return;
99 }
100
101 if (matchNames) {
102 var invalidInjectArray = fn.params.filter(function(e, i) {
103 return e.name !== $injectArray.elements[i].value;
104 });
105 if (invalidInjectArray.length > 0) {
106 context.report(fn, 'You have an error in your DI configuration. Each items of the array should match exactly one function parameter', {});
107 return;
108 }
109 }
110 } else if (fn.params.length > 0) {
111 report(fn);
112 }
113 } else if (fn.params && fn.params.length !== 0) {
114 report(fn);
115 }
116 }
117 }
118
119 return {
120 'angular?animation': checkDi,
121 'angular?config': checkDi,
122 'angular?controller': checkDi,
123 'angular?directive': checkDi,
124 'angular?factory': checkDi,
125 'angular?filter': checkDi,
126 'angular?inject': checkDi,
127 'angular?run': checkDi,
128 'angular?service': checkDi,
129 'angular?provider': function(callee, providerFn, $get) {
130 checkDi(null, providerFn);
131 checkDi(null, $get);
132 },
133 AssignmentExpression: function(node) {
134 maybeNoteInjection(node);
135 }
136 };
137 })
138};