'use strict';
var MODULE_NAME = 'Controllers',
CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/,
CATEGORY_CONTROLLER_NAME = 'Name controllers according to best practices',
CATEGORY_GLOBAL_CONTROLLER = 'Using global functions as controllers is against Angular best practices and depricated in Angular 1.3 and up',
SEVERITY_ERROR = 1,
SEVERITY_WARNING = 2;
// local state
var nameToControllerMap = {};
/**
* Decorates $controller with a patching function to
* log a message if the controller is instantiated on the window
*/
angular.module('ngHintControllers', []).
config(['$provide', '$controllerProvider', function ($provide, $controllerProvider) {
$provide.decorator('$controller', ['$delegate', controllerDecorator]);
var originalRegister = $controllerProvider.register;
$controllerProvider.register = function(name, constructor) {
stringOrObjectRegister(name);
originalRegister.apply($controllerProvider, arguments);
}
}]);
function controllerDecorator($delegate) {
return function(ctrl) {
if (typeof ctrl === 'string') {
var match = ctrl.match(CNTRL_REG);
var ctrlName = (match && match[1]) || ctrl;
if (!nameToControllerMap[ctrlName]) {
sendMessageForControllerName(ctrlName);
}
if (!nameToControllerMap[ctrlName] && typeof window[ctrlName] === 'function') {
sendMessageForGlobalController(ctrlName);
}
}
return $delegate.apply(this, arguments);
};
}
/**
* Save details of the controllers as they are instantiated
* for use in decoration.
* Hint about the best practices for naming controllers.
*/
var originalModule = angular.module;
function stringOrObjectRegister(controllerName) {
if ((controllerName !== null) && (typeof controllerName === 'object')) {
Object.keys(controllerName).forEach(processController);
} else {
processController(controllerName);
}
}
function processController(ctrlName) {
nameToControllerMap[ctrlName] = true;
sendMessageForControllerName(ctrlName);
}
function sendMessageForGlobalController(name) {
angular.hint.emit(MODULE_NAME + ':global',
'add `' + name + '` to a module',
angular.version.minor