Skip to content

add --rename option to rename declarations and references #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ Use the `--single_quotes` option to output `'$scope'` instead of `"$scope"`.
Use the `--regexp` option to restrict matching further or to expand matching.
See description further down.

Use the `--rename` option to rename providers (services, factories, controllers, etc.) with
a new name when declared and referenced through annotation.

Use the `--plugin` option to load a user plugin with the provided path (*experimental*,
0.9.x may change API). See [plugin-example.js](plugin-example.js) for more info.

Expand Down
68 changes: 45 additions & 23 deletions ng-annotate-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Copyright (c) 2013-2014 Olov Lassus <[email protected]>

"use strict";

const esprima_require_t0 = Date.now();
const esprima = require("esprima").parse;
const esprima_require_t1 = Date.now();
Expand Down Expand Up @@ -77,7 +78,7 @@ function matchNgRoute(node) {
if (args.length !== 2) {
return false;
}
const configArg = last(args)
const configArg = last(args);
if (configArg.type !== "ObjectExpression") {
return false;
}
Expand Down Expand Up @@ -160,7 +161,7 @@ function matchNgUi(node) {
matchProp("controllerProvider", props),
matchProp("templateProvider", props),
matchProp("onEnter", props),
matchProp("onExit", props),
matchProp("onExit", props)
];

// {resolve: ..}
Expand Down Expand Up @@ -218,7 +219,7 @@ function matchRegular(node, ctx) {
const args = node.arguments;
const target = (is.someof(method.name, ["config", "run"]) ?
args.length === 1 && args[0] :
args.length === 2 && args[0].type === "Literal" && is.string(args[0].value) && args[1]);
args.length === 2 && args[0].type === "Literal" && is.string(args[0].value) && [args[0], args[1]]);

if (target) {
target.$always = true;
Expand Down Expand Up @@ -264,41 +265,46 @@ function matchResolve(props) {
});
}
return [];
};
}

function stringify(arr, quot) {
function getReplaceString(ctx, originalString) {
return (ctx.rename[originalString] || originalString);
}

function stringify(ctx, arr, quot) {
return "[" + arr.map(function(arg) {
return quot + arg.name + quot;
return quot + getReplaceString(ctx, arg.name) + quot;
}).join(", ") + "]";
}

function insertArray(functionExpression, fragments, quot) {
function insertArray(ctx, functionExpression, fragments, quot) {
const range = functionExpression.range;

const args = stringify(functionExpression.params, quot);
const args = stringify(ctx, functionExpression.params, quot);
fragments.push({
start: range[0],
end: range[0],
str: args.slice(0, -1) + ", ",
str: args.slice(0, -1) + ", "
});
fragments.push({
start: range[1],
end: range[1],
str: "]",
str: "]"
});
}

function replaceArray(array, fragments, quot) {
function replaceArray(ctx, array, fragments, quot) {
const functionExpression = last(array.elements);

if (functionExpression.params.length === 0) {
return removeArray(array, fragments);
}
const args = stringify(functionExpression.params, quot);

const args = stringify(ctx, functionExpression.params, quot);
fragments.push({
start: array.range[0],
end: functionExpression.range[0],
str: args.slice(0, -1) + ", ",
str: args.slice(0, -1) + ", "
});
}

Expand All @@ -308,12 +314,21 @@ function removeArray(array, fragments) {
fragments.push({
start: array.range[0],
end: functionExpression.range[0],
str: "",
str: ""
});
fragments.push({
start: functionExpression.range[1],
end: array.range[1],
str: "",
str: ""
});
}

function replaceString(ctx, string, fragments, quot) {
var customReplace = getReplaceString(ctx, string.value);
fragments.push({
start: string.range[0],
end: string.range[1],
str: quot + customReplace + quot
});
}

Expand Down Expand Up @@ -341,11 +356,13 @@ function judgeSuspects(ctx) {
}

if (mode === "rebuild" && isAnnotatedArray(target)) {
replaceArray(target, fragments, quot);
replaceArray(ctx, target, fragments, quot);
} else if (mode === "remove" && isAnnotatedArray(target)) {
removeArray(target, fragments);
} else if (is.someof(mode, ["add", "rebuild"]) && isFunctionExpressionWithArgs(target)) {
insertArray(target, fragments, quot);
insertArray(ctx, target, fragments, quot);
} else if (isGenericProviderName(target)) {
replaceString(ctx, target, fragments, quot);
}
}
}
Expand All @@ -368,6 +385,9 @@ function isFunctionExpressionWithArgs(node) {
function isFunctionDeclarationWithArgs(node) {
return node.type === "FunctionDeclaration" && node.params.length >= 1;
}
function isGenericProviderName(node) {
return node.type === "Literal" && is.string(node.value);
}

module.exports = function ngAnnotate(src, options) {
const mode = (options.add && options.remove ? "rebuild" :
Expand All @@ -380,6 +400,7 @@ module.exports = function ngAnnotate(src, options) {

const quot = options.single_quotes ? "'" : '"';
const re = (options.regexp ? new RegExp(options.regexp) : /^[a-zA-Z0-9_\$\.\s]+$/);
const rename = options.rename || {};
let ast;
const stats = {};
try {
Expand All @@ -389,13 +410,13 @@ module.exports = function ngAnnotate(src, options) {

ast = esprima(src, {
range: true,
comment: true,
comment: true
});

stats.esprima_parse_t1 = Date.now();
} catch(e) {
return {
errors: ["error: couldn't process source due to parse error", e.message],
errors: ["error: couldn't process source due to parse error", e.message]
};
}

Expand All @@ -405,7 +426,7 @@ module.exports = function ngAnnotate(src, options) {
// append a dummy-node to ast to catch any remaining triggers
ast.body.push({
type: "DebuggerStatement",
range: [ast.range[1], ast.range[1]],
range: [ast.range[1], ast.range[1]]
});

// detach comments from ast
Expand Down Expand Up @@ -437,6 +458,7 @@ module.exports = function ngAnnotate(src, options) {
return src.slice(range[0], range[1]);
},
re: re,
rename: rename,
comments: comments,
fragments: fragments,
triggers: triggers,
Expand All @@ -446,7 +468,7 @@ module.exports = function ngAnnotate(src, options) {
isAnnotatedArray: isAnnotatedArray,
addModuleContextDependentSuspect: addModuleContextDependentSuspect,
addModuleContextIndependentSuspect: addModuleContextIndependentSuspect,
stringify: stringify,
stringify: stringify
};

const plugins = options.plugin || [];
Expand Down Expand Up @@ -505,6 +527,6 @@ module.exports = function ngAnnotate(src, options) {

return {
src: out,
_stats: stats,
_stats: stats
};
}
};
32 changes: 23 additions & 9 deletions ng-annotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,34 @@ const optimist = require("optimist")
.options("a", {
alias: "add",
boolean: true,
describe: "add dependency injection annotations where non-existing",
describe: "add dependency injection annotations where non-existing"
})
.options("r", {
alias: "remove",
boolean: true,
describe: "remove all existing dependency injection annotations",
describe: "remove all existing dependency injection annotations"
})
.options("o", {
describe: "write output to <file>. output is written to stdout by default",
describe: "write output to <file>. output is written to stdout by default"
})
.options("single_quotes", {
boolean: true,
describe: "use single quotes (') instead of double quotes (\")",
describe: "use single quotes (') instead of double quotes (\")"
})
.options("regexp", {
describe: "detect short form myMod.controller(...) iff myMod matches regexp",
describe: "detect short form myMod.controller(...) iff myMod matches regexp"
})
.options("rename", {
describe: "rename declarations and annotated refernces\n" +
"originalName newName anotherOriginalName anotherNewName ...",
default: ""
})
.options("plugin", {
describe: "use plugin with path (experimental)",
describe: "use plugin with path (experimental)"
})
.options("stats", {
boolean: true,
describe: "print statistics on stderr (experimental)",
describe: "print statistics on stderr (experimental)"
});

const argv = optimist.argv;
Expand Down Expand Up @@ -101,7 +106,7 @@ function runAnnotate(err, src) {
}, {});


["add", "remove", "o", "regexp", "single_quotes", "plugin", "stats"].forEach(function(opt) {
["add", "remove", "o", "regexp", "rename", "single_quotes", "plugin", "stats"].forEach(function(opt) {
if (opt in argv) {
config[opt] = argv[opt];
}
Expand All @@ -126,6 +131,15 @@ function runAnnotate(err, src) {
});
}

if (config.rename) {
var flattenRename = config.rename.split(" ");
var renameMap = {};
for (var i = 0; i < flattenRename.length; i = i + 2) {
renameMap[flattenRename[i]]= flattenRename[i+1];
}
config.rename = renameMap;
}

const run_t0 = Date.now();
const ret = ngAnnotate(src, config);
const run_t1 = Date.now();
Expand All @@ -145,7 +159,7 @@ function runAnnotate(err, src) {

const pct = function(n) {
return Math.round(100 * n / all);
}
};

process.stderr.write(fmt("[{0} ms] esprima: {1}, nga init: {2}, nga run: {3}\n", all, all_esprima, nga_init, nga_run));
process.stderr.write(fmt("[%] esprima: {0}, nga init: {1}, nga run: {2}\n", pct(all_esprima), pct(nga_init), pct(nga_run)));
Expand Down