switch from escodegen to recast which is slower but far superior

This commit is contained in:
Sebastian McKenzie
2014-10-10 00:47:39 +11:00
parent d04216457d
commit 98ab869af8
7 changed files with 85 additions and 90 deletions

View File

@@ -151,11 +151,7 @@ to5.transformFile("filename.js", options, function (err, result) {
sourceMap: false,
// Filename for use in errors etc.
filename: "unknown",
// Format options
// See https://github.com/Constellation/escodegen/wiki/API for options.
format: {}
filename: "unknown"
}
```

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env node
var helper = require("../test/_helper");
var util = require("../test/_helper");
console.log("(" + helper.run + ")(" + JSON.stringify(helper.getTests(), null, " ") + ", to5, proclaim)");
console.log("(" + helper.run + ")(" + util.formatJSON(helper.getTests()) + ", to5, proclaim)");

View File

@@ -1,5 +1,6 @@
var traverse = require("./traverse");
var assert = require("assert");
var recast = require("recast");
var path = require("path");
var util = require("./util");
var _ = require("lodash");
@@ -51,28 +52,13 @@ transform._run = function (code, tree, opts) {
transform._runTransformer(transformer, tree, opts, generateUid);
});
var genOpts = {
file: path.basename(opts.filename),
format: opts.format
};
var result = util.generate(tree, opts);
if (opts.sourceMap) {
genOpts.sourceMap = genOpts.file;
genOpts.sourceContent = code;
genOpts.sourceMapWithCode = true;
if (opts.sourceMap === "inline") {
result.code += "\n" + util.sourceMapToComment(result.map);
}
var result = util.generate(tree, genOpts);
if (opts.sourceMap) {
if (opts.sourceMap === "inline") {
result.code += "\n" + util.sourceMapToComment(result.map);
}
return result;
} else {
return { code: result, map: null };
}
return result;
};
transform._runTransformer = function (transformer, tree, opts, generateUid) {
@@ -86,20 +72,32 @@ transform._runTransformer = function (transformer, tree, opts, generateUid) {
});
};
transform.test = function (actual, expect, opts) {
opts = opts || {};
_.defaults(opts, { filename: "test" });
transform.test = function (task, assert) {
var actual = task.actual;
var expect = task.expect;
var opts = task.options;
opts.filename = actual.filename;
var actualCode = actual.code.trim();
var transformedCode = transform(actualCode, opts).code;
var transformedResult = transform(actualCode, opts);
var transformedCode = transformedResult.code;
var actualAst = util.parse(actual.filename, transformedCode);
actualCode = util.generate(actualAst);
var actualResult = recast.prettyPrint(actualAst);
actualCode = actualResult.code;
var expectCode = expect.code.trim();
var expectAst = util.parse(expect.filename, expectCode);
expectCode = util.generate(expectAst);
var expectResult = recast.prettyPrint(expectAst);
expectCode = expectResult.code;
assert.equal(actualCode, expectCode);
if (opts.sourceMap && task.sourceMap) {
assert.deepEqual(util.formatJSON(transformedResult.map), util.formatJSON(task.sourceMap));
}
};
transform.transformers = {

View File

@@ -3,6 +3,7 @@
"ArrayPattern": ["elements"],
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
"AssignmentExpression": ["left", "right"],
"AwaitExpression": ["argument"],
"BinaryExpression": ["left", "right"],
"BlockStatement": ["body"],
"BreakStatement": ["label"],
@@ -23,6 +24,7 @@
"ExportBatchSpecifier": [],
"ExportSpecifier": ["id", "name"],
"ExpressionStatement": ["expression"],
"File": ["program"],
"ForInStatement": ["left", "right", "body"],
"ForOfStatement": ["left", "right", "body"],
"ForStatement": ["init", "test", "update", "body"],
@@ -70,6 +72,5 @@
"VoidTypeAnnotation": [],
"WhileStatement": ["test", "body"],
"WithStatement": ["object", "body"],
"YieldExpression": ["argument"],
"AwaitExpression": ["argument"]
"YieldExpression": ["argument"]
}

View File

@@ -1,46 +1,12 @@
var estraverse = require("estraverse");
var escodegen = require("escodegen");
var traverse = require("./traverse");
var esprima = require("esprima-fb");
var recast = require("recast");
var path = require("path");
var fs = require("fs");
var _ = require("lodash");
var b = require("ast-types").builders;
_.each(esprima.Syntax, function (name) {
estraverse.VisitorKeys[name] = estraverse.VisitorKeys[name] || [];
});
exports.parse = function (filename, code, callback, opts) {
try {
var ast = esprima.parse(code, _.extend(opts || {}, {
comment: true,
source: filename,
tokens: true,
range: true,
loc: true
}));
estraverse.attachComments(ast, ast.comments, ast.tokens);
if (callback) {
return callback(ast);
} else {
return ast;
}
} catch (err) {
if (!err._6to5) {
err._6to5 = true;
err.message = filename + ": " + err.message;
if (err.lineNumber) {
var frame = exports.codeFrame(code, err.lineNumber, err.column);
err.message = err.message + frame;
}
}
throw err;
}
};
exports.ensureBlock = function (node) {
var block = node.body;
if (block.type === "BlockStatement") return;
@@ -52,19 +18,8 @@ exports.isPattern = function (node) {
return node.type === "ArrayPattern" || node.type === "ObjectPattern";
};
exports.generate = function (ast, opts) {
opts = opts || {};
opts = _.merge({
comment: true,
format: {
indent: {
style: " "
}
}
}, opts);
return escodegen.generate(ast, opts);
exports.formatJSON = function (obj) {
return JSON.stringify(obj, null, " ");
};
exports.removeProperties = function (tree) {
@@ -138,6 +93,7 @@ exports.buildDefineProperties = function (mutatorMap, keyNode) {
var propNode = b.property("init", b.identifier(key), mapNode);
_.each(map, function (methodNode, type) {
methodNode = _.clone(methodNode);
if (methodNode.type === "MethodDefinition") methodNode = methodNode.value;
mapNode.properties.push(b.property("init", b.identifier(type), methodNode));
});
@@ -212,6 +168,39 @@ exports.repeat = function (width, cha) {
return new Array(width + 1).join(cha);
};
exports.generate = function (ast, opts) {
var printOpts = {};
if (opts.sourceMap) {
printOpts.sourceMapName = path.basename(opts.filename);
}
return recast.print(ast, printOpts);
};
exports.parse = function (filename, code, callback, opts) {
try {
var ast = recast.parse(code, {
sourceFileName: path.basename(filename)
});
if (callback) {
return callback(ast);
} else {
return ast;
}
} catch (err) {
if (!err._6to5) {
err._6to5 = true;
err.message = filename + ": " + err.message;
if (err.lineNumber) {
var frame = exports.codeFrame(code, err.lineNumber, err.column);
err.message = err.message + frame;
}
}
throw err;
}
};
try {
exports.templates = require("../../templates.json");
} catch (err) {
@@ -221,7 +210,9 @@ try {
var templatesLoc = __dirname + "/templates";
if (!fs.existsSync(templatesLoc)) {
throw new Error("no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/sebmck/6to5/issues");
throw new Error("no templates directory - this is most likely the result" +
" of a broken `npm publish`. Please report to " +
"https://github.com/sebmck/6to5/issues");
}
_.each(fs.readdirSync(templatesLoc), function (name) {
@@ -231,6 +222,6 @@ try {
exports.templates[key] = exports.removeProperties(exports.parse(loc, code, null, {
tolerant: true
}));
}).program);
});
}

View File

@@ -39,15 +39,13 @@
"dependencies": {
"ast-types": "0.5.0",
"commander": "2.3.0",
"escodegen": "https://github.com/Constellation/escodegen/archive/624550d0d6edf812a661902c6908dedff66005a7.tar.gz",
"esprima-fb": "7001.1.0-dev-harmony-fb",
"estraverse": "1.5.1",
"fs-readdir-recursive": "0.0.2",
"lodash": "2.4.1",
"mkdirp": "0.5.0",
"es6-shim": "^0.18.0",
"es6-symbol": "^0.1.1",
"regexpu": "^0.2.2"
"regexpu": "^0.2.2",
"recast": "^0.8.0"
},
"devDependencies": {
"es6-transpiler": "0.7.17",

View File

@@ -20,8 +20,9 @@ exports.run = function (suites, transform, assert) {
suite(testSuite.title, function () {
_.each(testSuite.tests, function (task) {
test(task.title, function () {
var run = function () {
transform.test(task.actual, task.expect, task.options);
transform.test(task, assert);
};
var throwMsg = task.options.throws;
@@ -70,7 +71,8 @@ exports.getTests = function () {
var taskOpts = _.merge({ filename: actualLoc }, _.cloneDeep(suite.options));
if (fs.existsSync(taskOptsLoc)) _.merge(taskOpts, require(taskOptsLoc));
suite.tests.push({
var test = {
title: humanise(taskName),
options: taskOpts,
actual: {
@@ -81,7 +83,15 @@ exports.getTests = function () {
code: readFile(expectLoc),
filename: expectLoc
}
});
};
suite.tests.push(test);
var sourceMapLoc = taskDir + "/source-map.json";
if (fs.existsSync(sourceMapLoc)) {
test.options.sourceMap = true;
test.sourceMap = require(sourceMapLoc);
}
});
});