123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- // ng-annotate.js
- // MIT licensed, see LICENSE file
- // Copyright (c) 2013-2015 Olov Lassus <olov.lassus@gmail.com>
- "use strict";
- const t0 = Date.now();
- const fs = require("fs");
- const fmt = require("simple-fmt");
- const tryor = require("tryor");
- const ngAnnotate = require("./ng-annotate-main");
- const version = require("./package.json").version;
- const optimist = require("optimist")
- .usage("ng-annotate v" + version + "\n\nUsage: ng-annotate OPTIONS <file>\n\n" +
- "provide - instead of <file> to read from stdin\n" +
- "use -a and -r together to remove and add (rebuild) annotations in one go")
- .options("a", {
- alias: "add",
- boolean: true,
- describe: "add dependency injection annotations where non-existing",
- })
- .options("r", {
- alias: "remove",
- boolean: true,
- describe: "remove all existing dependency injection annotations",
- })
- .options("o", {
- describe: "write output to <file>. output is written to stdout by default",
- })
- .options("sourcemap", {
- boolean: true,
- describe: "generate an inline sourcemap"
- })
- .options("sourceroot", {
- describe: "set the sourceRoot property of the generated sourcemap"
- })
- .options("single_quotes", {
- boolean: true,
- describe: "use single quotes (') instead of double quotes (\")",
- })
- .options("regexp", {
- describe: "detect short form myMod.controller(...) iff myMod matches regexp",
- })
- .options("rename", {
- describe: "rename declarations and annotated references\n" +
- "oldname1 newname1 oldname2 newname2 ...",
- default: ""
- })
- .options("plugin", {
- describe: "use plugin with path (experimental)",
- })
- .options("stats", {
- boolean: true,
- describe: "print statistics on stderr (experimental)",
- });
- const argv = optimist.argv;
- function exit(msg) {
- if (msg) {
- process.stderr.write(msg);
- process.stderr.write("\n");
- }
- process.exit(-1);
- }
- // validate options
- if (argv._.length !== 1) {
- optimist.showHelp();
- exit("error: no input file provided");
- }
- if (!argv.add && !argv.remove) {
- optimist.showHelp();
- exit("error: missing option --add and/or --remove");
- }
- const filename = argv._.shift();
- (filename === "-" ? slurpStdin : slurpFile)(runAnnotate);
- function slurpStdin(cb) {
- let buf = "";
- process.stdin.setEncoding("utf8");
- process.stdin.on("data", function(d) {
- buf += d;
- });
- process.stdin.on("end", function() {
- cb(null, buf);
- });
- process.stdin.resume();
- }
- function slurpFile(cb) {
- if (!fs.existsSync(filename)) {
- cb(new Error(fmt('error: file not found {0}', filename)));
- }
- fs.readFile(filename, cb);
- }
- function runAnnotate(err, src) {
- if (err) {
- exit(err.message);
- }
- src = String(src);
- const config = tryor(function() {
- return JSON.parse(String(fs.readFileSync("ng-annotate-config.json")));
- }, {});
- if (filename !== "-") {
- config.inFile = filename;
- }
- ["add", "remove", "o", "regexp", "rename", "single_quotes", "plugin", "stats"].forEach(function(opt) {
- if (opt in argv) {
- config[opt] = argv[opt];
- }
- });
- if (argv.sourcemap) {
- config.map = { inline: true, sourceRoot: argv.sourceroot };
- if (filename !== "-") {
- config.map.inFile = filename;
- }
- };
- if (config.plugin) {
- if (!Array.isArray(config.plugin)) {
- config.plugin = [config.plugin];
- }
- config.plugin = config.plugin.map(function(path) {
- const absPath = tryor(fs.realpathSync.bind(fs, path), null);
- if (!absPath) {
- exit(fmt('error: plugin file not found {0}', path));
- }
- // the require below may throw an exception on parse-error
- try {
- return require(absPath);
- } catch (e) {
- // node will already print file:line and offending line to stderr
- exit(fmt("error: couldn't require(\"{0}\")", absPath));
- }
- });
- }
- const trimmedRename = config.rename && config.rename.trim();
- if (trimmedRename) {
- const flattenRename = trimmedRename.split(" ");
- const renameArray = [];
- for (let i = 0; i < flattenRename.length; i = i + 2) {
- renameArray.push({
- "from": flattenRename[i],
- "to": flattenRename[i + 1],
- });
- }
- config.rename = renameArray;
- } else {
- config.rename = null;
- }
- const run_t0 = Date.now();
- const ret = ngAnnotate(src, config);
- const run_t1 = Date.now();
- if (ret.errors) {
- exit(ret.errors.join("\n"));
- }
- const stats = ret._stats;
- if (config.stats && stats) {
- const t1 = Date.now();
- const all = t1 - t0;
- const run_parser = stats.parser_parse_t1 - stats.parser_parse_t0;
- const all_parser = run_parser + (stats.parser_require_t1 - stats.parser_require_t0);
- const nga_run = (run_t1 - run_t0) - run_parser;
- const nga_init = all - all_parser - nga_run;
- const pct = function(n) {
- return Math.round(100 * n / all);
- }
- process.stderr.write(fmt("[{0} ms] parser: {1}, nga init: {2}, nga run: {3}\n", all, all_parser, nga_init, nga_run));
- process.stderr.write(fmt("[%] parser: {0}, nga init: {1}, nga run: {2}\n", pct(all_parser), pct(nga_init), pct(nga_run)));
- }
- if (ret.src && config.o) {
- try {
- fs.writeFileSync(config.o, ret.src);
- } catch (e) {
- exit(e.message);
- }
- } else if (ret.src) {
- process.stdout.write(ret.src);
- }
- }
|