-
Notifications
You must be signed in to change notification settings - Fork 130
/
Copy pathcontroller-as.js
83 lines (77 loc) · 3.58 KB
/
controller-as.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
/**
* disallow assignments to `$scope` in controllers
*
* You should not set properties on $scope in controllers.
* Use controllerAs syntax and add data to 'this'.
* The second parameter can be a Regexp for identifying controller functions (when using something like Browserify)
*
* @styleguideReference {johnpapa} `y031` controllerAs Controller Syntax
* @version 0.1.0
* @category bestPractice
* @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/controller-as.md'
},
schema: [{
type: ['object', 'string']
}]
},
create: function(context) {
var badStatements = [];
var controllerFunctions = [];
// If your Angular code is written so that controller functions are in
// separate files from your .controller() calls, you can specify a regex for your controller function names
var controllerNameMatcher = context.options[0];
if (controllerNameMatcher && utils.isStringRegexp(controllerNameMatcher)) {
controllerNameMatcher = utils.convertStringToRegex(controllerNameMatcher);
}
// check node against known controller functions or pattern if specified
function isControllerFunction(node) {
return controllerFunctions.indexOf(node) >= 0 ||
(controllerNameMatcher && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration') &&
node.id && controllerNameMatcher.test(node.id.name));
}
// for each of the bad uses, find any parent nodes that are controller functions
function reportBadUses() {
if (controllerFunctions.length > 0 || controllerNameMatcher) {
badStatements.forEach(function(item) {
item.parents.forEach(function(parent) {
if (isControllerFunction(parent)) {
context.report(item.stmt, 'You should not set properties on $scope in controllers. Use controllerAs syntax and add data to "this"');
}
});
});
}
}
return {
// Looking for .controller() calls here and getting the associated controller function
'CallExpression:exit': function(node) {
if (utils.isAngularControllerDeclaration(node)) {
controllerFunctions.push(utils.getControllerDefinition(context, node));
}
},
// statements are checked here for bad uses of $scope
ExpressionStatement: function(stmt) {
if (stmt.expression.type === 'AssignmentExpression' &&
stmt.expression.left.object &&
stmt.expression.left.object.name === '$scope' &&
utils.scopeProperties.indexOf(stmt.expression.left.property.name) < 0) {
badStatements.push({parents: context.getAncestors(), stmt: stmt});
} else if (stmt.expression.type === 'CallExpression' &&
stmt.expression.callee.object &&
stmt.expression.callee.object.name === '$scope' &&
utils.scopeProperties.indexOf(stmt.expression.callee.property.name) < 0) {
badStatements.push({parents: context.getAncestors(), stmt: stmt});
}
},
'Program:exit': function() {
reportBadUses();
}
};
}
};