ng-annotate
Advanced tools
Comparing version 0.1.2 to 0.2.0
@@ -7,18 +7,42 @@ "use strict"; | ||
// Short form: | ||
// *.controller("MyCtrl", function($scope, $timeout) {}); | ||
function isShortDef(node, re) { | ||
return is.string(node.name) && (!re || re.test(node.name)); | ||
function match(node, re) { | ||
return matchRegular(node, re) || | ||
matchDirectiveReturnObject(node) || | ||
matchProviderGet(node); | ||
} | ||
// Long form: | ||
// angular.module(*).controller("MyCtrl", function($scope, $timeout) {}); | ||
function isLongDef(node) { | ||
return node.type === "CallExpression" && | ||
node.callee && | ||
node.callee.object && node.callee.object.name === "angular" && | ||
node.callee.property && node.callee.property.name === "module"; | ||
function matchDirectiveReturnObject(node) { | ||
// return { .. controller: function($scope, $timeout), ...} | ||
return node.type === "ReturnStatement" && | ||
node.argument && node.argument.type === "ObjectExpression" && | ||
matchProp("controller", node.argument.properties); | ||
} | ||
function matchCallee(node, re) { | ||
function matchProviderGet(node) { | ||
// this.$get = function($scope, $timeout) | ||
// { ... $get: function($scope, $timeout), ...} | ||
return (node.type === "AssignmentExpression" && node.left.type === "MemberExpression" && | ||
node.left.object.type === "ThisExpression" && node.left.property.name === "$get" && node.right) || | ||
(node.type === "ObjectExpression" && matchProp("$get", node.properties)); | ||
} | ||
function matchRegular(node, re) { | ||
// Short form: *.controller("MyCtrl", function($scope, $timeout) {}); | ||
function isShortDef(node, re) { | ||
return is.string(node.name) && (!re || re.test(node.name)); | ||
} | ||
// Long form: angular.module(*).controller("MyCtrl", function($scope, $timeout) {}); | ||
function isLongDef(node) { | ||
return node.callee && | ||
node.callee.object && node.callee.object.name === "angular" && | ||
node.callee.property && node.callee.property.name === "module"; | ||
} | ||
if (node.type !== "CallExpression") { | ||
return; | ||
} | ||
const callee = node.callee; | ||
@@ -33,19 +57,17 @@ if (callee.type !== "MemberExpression") { | ||
} | ||
return (obj.$chained || isShortDef(obj, re) || isLongDef(obj)) && is.someof(prop.name, ["config", "factory", "directive", "filter", "run", "controller", "service"]); | ||
} | ||
const matchAngularModule = (obj.$chained || isShortDef(obj, re) || isLongDef(obj)) && | ||
is.someof(prop.name, ["provider", "config", "factory", "directive", "filter", "run", "controller", "service"]); | ||
if (!matchAngularModule) { | ||
return false; | ||
} | ||
node.$chained = true; | ||
function matchFunctionSignature(node) { | ||
const args = node.arguments; | ||
return (is.someof(node.callee.property.name, ["config", "run"]) ? | ||
args.length === 1 : | ||
args.length === 2 && args[0].type === "Literal") && | ||
last(args).type === "FunctionExpression" && last(args).params.length > 0; | ||
} | ||
if (prop.name === "provider") { | ||
return false; // affects matchAngularModule because of chaining | ||
} | ||
function matchArraySignature(node) { | ||
const args = node.arguments; | ||
return (is.someof(node.callee.property.name, ["config", "run"]) ? | ||
args.length === 1 : | ||
args.length === 2 && args[0].type === "Literal") && | ||
last(args).type === "ArrayExpression" && last(args).elements.length >= 1 && last(last(args).elements).type === "FunctionExpression"; | ||
return (is.someof(prop.name, ["config", "run"]) ? | ||
args.length === 1 && args[0] : | ||
args.length === 2 && args[0].type === "Literal" && is.string(args[0].value) && args[1]); | ||
} | ||
@@ -57,4 +79,13 @@ | ||
function insertArray(node, fragments) { | ||
const functionExpression = last(node.arguments); | ||
function matchProp(name, props) { | ||
for (let i = 0; i < props.length; i++) { | ||
const prop = props[i]; | ||
if (prop.key.type === "Identifier" && prop.key.name === name) { | ||
return prop.value; // FunctionExpression or ArrayExpression | ||
} | ||
} | ||
return null; | ||
} | ||
function insertArray(functionExpression, fragments) { | ||
const range = functionExpression.range; | ||
@@ -77,8 +108,7 @@ | ||
function replaceArray(node, fragments) { | ||
const array = last(node.arguments); | ||
function replaceArray(array, fragments) { | ||
const functionExpression = last(array.elements); | ||
if (functionExpression.params.length === 0) { | ||
return removeArray(node, fragments); | ||
return removeArray(array, fragments); | ||
} | ||
@@ -95,4 +125,3 @@ const args = JSON.stringify(functionExpression.params.map(function(arg) { | ||
function removeArray(node, fragments) { | ||
const array = last(node.arguments); | ||
function removeArray(array, fragments) { | ||
const functionExpression = last(array.elements); | ||
@@ -112,2 +141,9 @@ | ||
function isAnnotatedArray(node) { | ||
return node.type === "ArrayExpression" && node.elements.length >= 1 && last(node.elements).type === "FunctionExpression"; | ||
} | ||
function isFunctionWithArgs(node) { | ||
return node.type === "FunctionExpression" && node.params.length >= 1; | ||
} | ||
module.exports = function ngAnnotate(src, options) { | ||
@@ -128,17 +164,15 @@ const mode = (options.add && options.remove ? "rebuild" : | ||
const fragments = []; | ||
traverse(ast, {post: function(node, parent) { | ||
if (node.type !== "CallExpression") { | ||
traverse(ast, {post: function(node) { | ||
const target = match(node, re); | ||
if (!target) { | ||
return; | ||
} | ||
if (!matchCallee(node, re)) { | ||
return; | ||
} | ||
node.$chained = true; | ||
if (mode === "rebuild" && matchArraySignature(node)) { | ||
replaceArray(node, fragments); | ||
} else if (mode === "remove" && matchArraySignature(node)) { | ||
removeArray(node, fragments); | ||
} else if (is.someof(mode, ["add", "rebuild"]) && matchFunctionSignature(node)) { | ||
insertArray(node, fragments); | ||
if (mode === "rebuild" && isAnnotatedArray(target)) { | ||
replaceArray(target, fragments); | ||
} else if (mode === "remove" && isAnnotatedArray(target)) { | ||
removeArray(target, fragments); | ||
} else if (is.someof(mode, ["add", "rebuild"]) && isFunctionWithArgs(target)) { | ||
insertArray(target, fragments); | ||
} | ||
@@ -145,0 +179,0 @@ }}); |
{ | ||
"name": "ng-annotate", | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"description": "add, remove and rebuild angularjs dependency injection annotations", | ||
@@ -19,2 +19,5 @@ "main": "ng-annotate-main.js", | ||
}, | ||
"devDependencies": { | ||
"diff": "~1.0.6" | ||
}, | ||
"keywords": [ | ||
@@ -32,2 +35,5 @@ "angular", | ||
], | ||
"scripts": { | ||
"test": "node --harmony run-tests" | ||
}, | ||
"bin": "./ng-annotate", | ||
@@ -34,0 +40,0 @@ "author": "Olov Lassus <olov.lassus@gmail.com>", |
@@ -63,2 +63,8 @@ # ng-annotate | ||
ng-annotate understands `this.$get = function($scope)` and | ||
`{.., $get: function($scope), ..}` inside a `provider`. | ||
ng-annotate understands `return {.., controller: function($scope), ..}` inside a | ||
`directive`. | ||
ng-annotate understands chaining. | ||
@@ -65,0 +71,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18764
10
460
91
1
2
1