precise matching on $provide.decorator, .service, .factory and .provider. Remove general .decorator matching on long and short forms. closes #82

This commit is contained in:
Olov Lassus
2014-11-18 13:52:39 +01:00
parent 1ca5fdee92
commit 1f5bf3cf5f
5 changed files with 121 additions and 32 deletions
+2 -2
View File
@@ -151,8 +151,8 @@ aliases for `this`.
ng-annotate understands `return {.., controller: function($scope) ..}` inside a
`directive`.
ng-annotate understands `$provide.decorator("bar", function($scope) ..)` and other methods
on `provide` such as `factory`.
ng-annotate understands `$provide.decorator("bar", function($scope) ..)`, `$provide.service`,
`$provide.factory` and `$provide.provider`.
ng-annotate understands `$routeProvider.when("path", { .. })`.
+31 -2
View File
@@ -30,8 +30,10 @@ function match(node, ctx, matchPlugins) {
// matchInjectorInvoke must happen before matchRegular
// to prevent false positive ($injector.invoke() outside module)
// matchProvide must happen before matchRegular
// to prevent regular from matching it as a short-form
const matchMethodCalls = (isMethodCall &&
(matchInjectorInvoke(node) || matchRegular(node, ctx) || matchNgRoute(node) || matchNgUi(node) || matchHttpProvider(node)));
(matchInjectorInvoke(node) || matchProvide(node, ctx) || matchRegular(node, ctx) || matchNgRoute(node) || matchNgUi(node) || matchHttpProvider(node)));
return matchMethodCalls ||
(matchPlugins && matchPlugins(node)) ||
@@ -252,6 +254,33 @@ function matchHttpProvider(node) {
node.arguments.length >= 1 && node.arguments);
}
function matchProvide(node, ctx) {
// $provide.decorator("foo", function($scope) {});
// $provide.service("foo", function($scope) {});
// $provide.factory("foo", function($scope) {});
// $provide.provider("foo", function($scope) {});
// we already know that node is a (non-computed) method call
const callee = node.callee;
const obj = callee.object; // identifier or expression
const method = callee.property; // identifier
const args = node.arguments;
const target = obj.type === "Identifier" && obj.name === "$provide" &&
is.someof(method.name, ["decorator", "service", "factory", "provider"]) &&
args.length === 2 && args[1];
if (target) {
target.$methodName = method.name;
if (ctx.rename) {
// for eventual rename purposes
return args;
}
}
return target;
}
function matchRegular(node, ctx) {
// we already know that node is a (non-computed) method call
const callee = node.callee;
@@ -269,7 +298,7 @@ function matchRegular(node, ctx) {
}
const matchAngularModule = (obj.$chained === chainedRegular || isReDef(obj, ctx) || isLongDef(obj)) &&
is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "decorator", "animation", "invoke"]);
is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "animation", "invoke"]);
if (!matchAngularModule) {
return false;
}
+28 -8
View File
@@ -180,17 +180,32 @@ angular.module("MyMod").directive("foo", function($a, $b) {
});
// $provide
angular.module("MyMod").directive("foo", function($a, $b) {
$provide.decorator("foo", function($scope, $timeout) {
a;
angular.module("myMod").controller("foo", function() {
$provide.decorator("foo", function($scope) {});
$provide.service("foo", function($scope) {});
$provide.factory("foo", function($scope) {});
//$provide.provider
$provide.provider("foo", function($scope) {
this.$get = function($scope) {};
return { $get: function($scope, $timeout) {}};
});
$provide.factory("bar", function($timeout, $scope) {
b;
});
$provide.animation("baz", function($scope, $timeout) {
c;
$provide.provider("foo", {
$get: function($scope, $timeout) {}
});
});
// negative $provide
function notInContext() {
$provide.decorator("foo", function($scope) {});
$provide.service("foo", function($scope) {});
$provide.factory("foo", function($scope) {});
$provide.provider("foo", function($scope) {
this.$get = function($scope) {};
return { $get: function($scope, $timeout) {}};
});
$provide.provider("foo", {
$get: function($scope, $timeout) {}
});
}
// all the patterns below matches only when we're inside a detected angular module
@@ -591,6 +606,11 @@ myMod.service("donttouch", function() {
}
});
myMod.directive("donttouch", function() {
foo.decorator("me", function($scope) {
});
});
// IIFE-jumping (primarily for compile-to-JS langs)
angular.module("MyMod").directive("foo", function($a, $b) {
$modal.open({
+30 -10
View File
@@ -184,17 +184,32 @@ angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) {
}]);
// $provide
angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) {
$provide.decorator("foo", ["$scope", "$timeout", function($scope, $timeout) {
a;
angular.module("myMod").controller("foo", function() {
$provide.decorator("foo", ["$scope", function($scope) {}]);
$provide.service("foo", ["$scope", function($scope) {}]);
$provide.factory("foo", ["$scope", function($scope) {}]);
//$provide.provider
$provide.provider("foo", ["$scope", function($scope) {
this.$get = ["$scope", function($scope) {}];
return { $get: ["$scope", "$timeout", function($scope, $timeout) {}]};
}]);
$provide.factory("bar", ["$timeout", "$scope", function($timeout, $scope) {
b;
}]);
$provide.animation("baz", ["$scope", "$timeout", function($scope, $timeout) {
c;
}]);
}]);
$provide.provider("foo", {
$get: ["$scope", "$timeout", function($scope, $timeout) {}]
});
});
// negative $provide
function notInContext() {
$provide.decorator("foo", function($scope) {});
$provide.service("foo", function($scope) {});
$provide.factory("foo", function($scope) {});
$provide.provider("foo", function($scope) {
this.$get = function($scope) {};
return { $get: function($scope, $timeout) {}};
});
$provide.provider("foo", {
$get: function($scope, $timeout) {}
});
}
// all the patterns below matches only when we're inside a detected angular module
@@ -614,6 +629,11 @@ myMod.service("donttouch", function() {
}
});
myMod.directive("donttouch", function() {
foo.decorator("me", function($scope) {
});
});
// IIFE-jumping (primarily for compile-to-JS langs)
angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) {
$modal.open({
+30 -10
View File
@@ -184,17 +184,32 @@ angular.module("MyMod").directive("foo", ['$a', '$b', function($a, $b) {
}]);
// $provide
angular.module("MyMod").directive("foo", ['$a', '$b', function($a, $b) {
$provide.decorator("foo", ['$scope', '$timeout', function($scope, $timeout) {
a;
angular.module("myMod").controller("foo", function() {
$provide.decorator("foo", ['$scope', function($scope) {}]);
$provide.service("foo", ['$scope', function($scope) {}]);
$provide.factory("foo", ['$scope', function($scope) {}]);
//$provide.provider
$provide.provider("foo", ['$scope', function($scope) {
this.$get = ['$scope', function($scope) {}];
return { $get: ['$scope', '$timeout', function($scope, $timeout) {}]};
}]);
$provide.factory("bar", ['$timeout', '$scope', function($timeout, $scope) {
b;
}]);
$provide.animation("baz", ['$scope', '$timeout', function($scope, $timeout) {
c;
}]);
}]);
$provide.provider("foo", {
$get: ['$scope', '$timeout', function($scope, $timeout) {}]
});
});
// negative $provide
function notInContext() {
$provide.decorator("foo", function($scope) {});
$provide.service("foo", function($scope) {});
$provide.factory("foo", function($scope) {});
$provide.provider("foo", function($scope) {
this.$get = function($scope) {};
return { $get: function($scope, $timeout) {}};
});
$provide.provider("foo", {
$get: function($scope, $timeout) {}
});
}
// all the patterns below matches only when we're inside a detected angular module
@@ -614,6 +629,11 @@ myMod.service("donttouch", function() {
}
});
myMod.directive("donttouch", function() {
foo.decorator("me", function($scope) {
});
});
// IIFE-jumping (primarily for compile-to-JS langs)
angular.module("MyMod").directive("foo", ['$a', '$b', function($a, $b) {
$modal.open({