-
Notifications
You must be signed in to change notification settings - Fork 130
/
Copy pathmodule-dependency-order.js
190 lines (180 loc) · 6.72 KB
/
module-dependency-order.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/**
* require a consistent order of module dependencies
*
* Module dependencies should be sorted in a logical manner.
* This rule provides two ways to sort modules, grouped or ungrouped.
* In grouped mode the modules should be grouped in the order: standard modules - third party modules - custom modules.
* The modules should be sorted alphabetically within its group.
* A prefix can be specified to determine which prefix the custom modules have.
* Without grouped set to `false` all dependencies combined should be sorted alphabetically.
* ('module-dependency-order', [2, {grouped: true, prefix: "app"}])
*
* @version 0.12.0
* @category conventions
* @sinceAngularVersion 1.x
*/
'use strict';
var utils = require('./utils/utils');
module.exports = {
meta: {
docs: {
url: 'https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/module-dependency-order.md'
},
schema: [{
type: 'object',
properties: {
grouped: {
type: 'boolean'
},
prefix: {
type: ['string', 'null']
}
}
}]
},
create: function(context) {
var options = context.options[0] || {};
var groupedMode = options.grouped !== false;
var moduleRegex;
if (groupedMode) {
moduleRegex = utils.convertPrefixToRegex(options.prefix);
}
var standard = [
// Libraries in the angular.js repository
'ng',
'ngAnimate',
'ngAria',
'ngCookies',
'ngLocale',
'ngMessageFormat',
'ngMessages',
'ngMock',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
// Libraries maintained by the angular team, but in another repository
'ngMaterial',
'ngNewRouter'
];
function checkLiteral(node) {
if (node && node.type !== 'Literal' && node.type !== 'Identifier') {
context.report(node, 'Unexpected non-literal or identifier value' + node.type);
return false;
}
if (!node) {
return false;
}
return true;
}
function checkCombined(deps) {
var lastCorrect;
deps.elements.forEach(function(node) {
if (!checkLiteral(node)) {
return;
}
var value = node.value || node.name;
if (lastCorrect === undefined || lastCorrect.localeCompare(value) < 0) {
lastCorrect = value;
} else {
context.report(node, '{{current}} should be sorted before {{last}}', {
current: value,
last: lastCorrect
});
}
});
}
function isStandardModule(value) {
return standard.indexOf(value) !== -1;
}
function isCustomModule(value) {
return moduleRegex && moduleRegex.test(value);
}
function checkGrouped(deps) {
var lastCorrect;
var group = 'standard';
deps.elements.forEach(function loop(node) {
if (!checkLiteral(node)) {
return;
}
var value = node.value || node.name;
if (lastCorrect === undefined) {
lastCorrect = value;
if (isCustomModule(value)) {
group = 'custom';
} else if (standard.indexOf(value) === -1) {
group = 'third party';
}
return;
}
if (group === 'standard') {
if (isStandardModule(value)) {
if (lastCorrect.localeCompare(value) > 0) {
context.report(node, '{{current}} should be sorted before {{last}}', {
current: value,
last: lastCorrect
});
} else {
lastCorrect = value;
}
} else {
if (isCustomModule(value)) {
group = 'custom';
} else {
group = 'third party';
}
lastCorrect = value;
}
}
if (group === 'third party') {
if (isStandardModule(value)) {
context.report(node, '{{current}} is a standard module and should be sorted before {{last}}', {
current: value,
last: lastCorrect
});
} else if (isCustomModule(value)) {
group = 'custom';
lastCorrect = value;
} else if (lastCorrect.localeCompare(value) > 0) {
context.report(node, '{{current}} should be sorted before {{last}}', {
current: value,
last: lastCorrect
});
} else {
lastCorrect = value;
}
}
if (group === 'custom') {
if (isStandardModule(value)) {
context.report(node, '{{current}} is a standard module and should be sorted before {{last}}', {
current: value,
last: lastCorrect
});
} else if (!isCustomModule(value)) {
context.report(node, '{{current}} is a third party module and should be sorted before {{last}}', {
current: value,
last: lastCorrect
});
}
}
});
}
return {
CallExpression: function(node) {
if (!utils.isAngularModuleDeclaration(node)) {
return;
}
var deps = node.arguments[1];
if (deps.type !== 'ArrayExpression') {
context.report(deps, 'Dependencies should be a literal array');
return;
}
if (groupedMode) {
checkGrouped(deps);
} else {
checkCombined(deps);
}
}
};
}
};