all files / eslint-plugin-angular/rules/ controller-as.js

100% Statements 24/24
100% Branches 30/30
100% Functions 8/8
100% Lines 24/24
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                            20× 20×       20× 20×       51×           20× 12× 10× 51× 10×             20×     36×         34×       29×             20×              
/**
 * 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
 */
'use strict';
 
var utils = require('./utils/utils');
 
module.exports = 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();
        }
    };
};
 
module.exports.schema = [{
    type: ['object', 'string']
}];