clean up file transform pipeline
This commit is contained in:
parent
0fc02f2cf0
commit
d981b30194
@ -1,56 +1,23 @@
|
||||
import normalizeAst from "./normalize-ast";
|
||||
import estraverse from "estraverse";
|
||||
import codeFrame from "./code-frame";
|
||||
import * as acorn from "../../acorn";
|
||||
|
||||
function parseCatch(code, opts) {
|
||||
var comments = opts.onComment = [];
|
||||
var tokens = opts.onToken = [];
|
||||
|
||||
try {
|
||||
return acorn.parse(code, opts);
|
||||
} catch (err) {
|
||||
if (err._babel) {
|
||||
throw err;
|
||||
} else {
|
||||
err._babel = true;
|
||||
}
|
||||
|
||||
if (opts.errorMessage) {
|
||||
err.message += ` - ${opts.errorMessage}`;
|
||||
}
|
||||
|
||||
var message = err.message = `${opts.filename || "unknown"}: ${err.message}`;
|
||||
|
||||
var loc = err.loc;
|
||||
if (loc) {
|
||||
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, opts);
|
||||
message += "\n" + err.codeFrame;
|
||||
}
|
||||
|
||||
if (err.stack) {
|
||||
var newStack = err.stack.replace(err.message, message);
|
||||
try {
|
||||
err.stack = newStack;
|
||||
} catch (e) {
|
||||
// `err.stack` may be a readonly property in some environments
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export default function (opts, code, callback) {
|
||||
var comments = [];
|
||||
var tokens = [];
|
||||
|
||||
var parseOpts = {
|
||||
allowImportExportEverywhere: opts.looseModules,
|
||||
allowReturnOutsideFunction: opts.looseModules,
|
||||
allowHashBang: true,
|
||||
ecmaVersion: 6,
|
||||
strictMode: opts.strictMode,
|
||||
sourceType: opts.sourceType,
|
||||
locations: true,
|
||||
onComment: comments,
|
||||
features: opts.features || {},
|
||||
plugins: opts.plugins || {},
|
||||
onToken: tokens,
|
||||
ranges: true
|
||||
};
|
||||
|
||||
@ -59,19 +26,15 @@ export default function (opts, code, callback) {
|
||||
parseOpts.plugins.flow = true;
|
||||
}
|
||||
|
||||
var ast = parseCatch(code, parseOpts);
|
||||
var ast = acorn.parse(code, parseOpts);
|
||||
|
||||
estraverse.attachComments(ast, parseOpts.onComment, parseOpts.onToken);
|
||||
ast = normalizeAst(ast, parseOpts.onComment, parseOpts.onToken);
|
||||
|
||||
if (callback) {
|
||||
return callback(ast);
|
||||
} else {
|
||||
return ast;
|
||||
}
|
||||
estraverse.attachComments(ast, comments, tokens);
|
||||
ast = normalizeAst(ast, comments, tokens);
|
||||
return ast;
|
||||
}
|
||||
|
||||
export function all(code, opts = {}) {
|
||||
opts.allowHashBang = true;
|
||||
opts.sourceType = "module";
|
||||
opts.ecmaVersion = Infinity;
|
||||
opts.plugins = {
|
||||
@ -84,5 +47,5 @@ export function all(code, opts = {}) {
|
||||
opts.features[key] = true;
|
||||
}
|
||||
|
||||
return parseCatch(code, opts);
|
||||
return acorn.parse(code, opts);
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import resolveRc from "../../tools/resolve-rc";
|
||||
import sourceMap from "source-map";
|
||||
import transform from "./../index";
|
||||
import generate from "../../generation";
|
||||
import codeFrame from "../../helpers/code-frame";
|
||||
import defaults from "lodash/object/defaults";
|
||||
import includes from "lodash/collection/includes";
|
||||
import traverse from "../../traversal";
|
||||
@ -236,48 +237,6 @@ export default class File {
|
||||
this.transformerStack = stack.concat(secondaryStack);
|
||||
}
|
||||
|
||||
getModuleFormatter(type: string) {
|
||||
var ModuleFormatter = isFunction(type) ? type : moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolveRelative(type);
|
||||
if (loc) ModuleFormatter = require(loc);
|
||||
}
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
throw new ReferenceError(`Unknown module formatter type ${JSON.stringify(type)}`);
|
||||
}
|
||||
|
||||
return new ModuleFormatter(this);
|
||||
}
|
||||
|
||||
parseInputSourceMap(code: string) {
|
||||
var opts = this.opts;
|
||||
|
||||
if (opts.inputSourceMap !== false) {
|
||||
var inputMap = convertSourceMap.fromSource(code);
|
||||
if (inputMap) {
|
||||
opts.inputSourceMap = inputMap.toObject();
|
||||
code = convertSourceMap.removeComments(code);
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
parseShebang(code: string) {
|
||||
var shebangMatch = shebangRegex.exec(code);
|
||||
|
||||
if (shebangMatch) {
|
||||
this.shebang = shebangMatch[0];
|
||||
|
||||
// remove shebang
|
||||
code = code.replace(shebangRegex, "");
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
set(key: string, val): any {
|
||||
return this.data[key] = val;
|
||||
};
|
||||
@ -398,110 +357,6 @@ export default class File {
|
||||
return err;
|
||||
}
|
||||
|
||||
addCode(code: string) {
|
||||
code = (code || "") + "";
|
||||
code = this.parseInputSourceMap(code);
|
||||
this.code = code;
|
||||
return this.parseShebang(code);
|
||||
}
|
||||
|
||||
shouldIgnore() {
|
||||
var opts = this.opts;
|
||||
return util.shouldIgnore(opts.filename, opts.ignore, opts.only);
|
||||
}
|
||||
|
||||
parse(code: string) {
|
||||
if (this.shouldIgnore()) {
|
||||
return {
|
||||
metadata: {},
|
||||
code: code,
|
||||
map: null,
|
||||
ast: null
|
||||
};
|
||||
}
|
||||
|
||||
code = this.addCode(code);
|
||||
|
||||
var opts = this.opts;
|
||||
|
||||
//
|
||||
|
||||
var parseOpts = {
|
||||
highlightCode: opts.highlightCode,
|
||||
nonStandard: opts.nonStandard,
|
||||
filename: opts.filename,
|
||||
plugins: {}
|
||||
};
|
||||
|
||||
var features = parseOpts.features = {};
|
||||
for (var key in this.transformers) {
|
||||
var transformer = this.transformers[key];
|
||||
features[key] = transformer.canTransform();
|
||||
}
|
||||
|
||||
parseOpts.looseModules = this.isLoose("es6.modules");
|
||||
parseOpts.strictMode = features.strict;
|
||||
parseOpts.sourceType = "module";
|
||||
|
||||
this.log.debug("Parse start");
|
||||
|
||||
//
|
||||
|
||||
return parse(parseOpts, code, (tree) => {
|
||||
this.log.debug("Parse stop");
|
||||
this.transform(tree);
|
||||
return this.generate();
|
||||
});
|
||||
}
|
||||
|
||||
setAst(ast) {
|
||||
this.path = TraversalPath.get(null, null, ast, ast, "program", this);
|
||||
this.scope = this.path.scope;
|
||||
this.ast = ast;
|
||||
|
||||
this.path.traverse({
|
||||
enter(node, parent, scope) {
|
||||
if (this.isScope()) {
|
||||
for (var key in scope.bindings) {
|
||||
scope.bindings[key].setTypeAnnotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
transform(ast) {
|
||||
this.log.debug("Start set AST");
|
||||
this.setAst(ast);
|
||||
this.log.debug("End set AST");
|
||||
|
||||
this.log.debug("Start prepass");
|
||||
this.checkPath(this.path);
|
||||
this.log.debug("End prepass");
|
||||
|
||||
this.log.debug("Start module formatter init");
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canTransform()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
this.log.debug("End module formatter init");
|
||||
|
||||
this.call("pre");
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
this.call("post");
|
||||
}
|
||||
|
||||
call(key: string) {
|
||||
var stack = this.transformerStack;
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var transformer = stack[i].transformer;
|
||||
var fn = transformer[key];
|
||||
if (fn) fn(this);
|
||||
}
|
||||
}
|
||||
|
||||
checkPath(path) {
|
||||
if (Array.isArray(path)) {
|
||||
for (var i = 0; i < path.length; i++) {
|
||||
@ -541,6 +396,178 @@ export default class File {
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
getModuleFormatter(type: string) {
|
||||
var ModuleFormatter = isFunction(type) ? type : moduleFormatters[type];
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
var loc = util.resolveRelative(type);
|
||||
if (loc) ModuleFormatter = require(loc);
|
||||
}
|
||||
|
||||
if (!ModuleFormatter) {
|
||||
throw new ReferenceError(`Unknown module formatter type ${JSON.stringify(type)}`);
|
||||
}
|
||||
|
||||
return new ModuleFormatter(this);
|
||||
}
|
||||
|
||||
parse(code: string) {
|
||||
var opts = this.opts;
|
||||
|
||||
//
|
||||
|
||||
var parseOpts = {
|
||||
highlightCode: opts.highlightCode,
|
||||
nonStandard: opts.nonStandard,
|
||||
filename: opts.filename,
|
||||
plugins: {}
|
||||
};
|
||||
|
||||
var features = parseOpts.features = {};
|
||||
for (var key in this.transformers) {
|
||||
var transformer = this.transformers[key];
|
||||
features[key] = transformer.canTransform();
|
||||
}
|
||||
|
||||
parseOpts.looseModules = this.isLoose("es6.modules");
|
||||
parseOpts.strictMode = features.strict;
|
||||
parseOpts.sourceType = "module";
|
||||
|
||||
this.log.debug("Parse start");
|
||||
var tree = parse(parseOpts, code);
|
||||
this.log.debug("Parse stop");
|
||||
return tree;
|
||||
}
|
||||
|
||||
_addAst(ast) {
|
||||
this.path = TraversalPath.get(null, null, ast, ast, "program", this);
|
||||
this.scope = this.path.scope;
|
||||
this.ast = ast;
|
||||
|
||||
this.path.traverse({
|
||||
enter(node, parent, scope) {
|
||||
if (this.isScope()) {
|
||||
for (var key in scope.bindings) {
|
||||
scope.bindings[key].setTypeAnnotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addAst(ast) {
|
||||
this.log.debug("Start set AST");
|
||||
this._addAst(ast);
|
||||
this.log.debug("End set AST");
|
||||
|
||||
this.log.debug("Start prepass");
|
||||
this.checkPath(this.path);
|
||||
this.log.debug("End prepass");
|
||||
|
||||
this.log.debug("Start module formatter init");
|
||||
var modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
|
||||
if (modFormatter.init && this.transformers["es6.modules"].canTransform()) {
|
||||
modFormatter.init();
|
||||
}
|
||||
this.log.debug("End module formatter init");
|
||||
|
||||
this.call("pre");
|
||||
each(this.transformerStack, function (pass) {
|
||||
pass.transform();
|
||||
});
|
||||
this.call("post");
|
||||
}
|
||||
|
||||
wrap(code, callback) {
|
||||
try {
|
||||
if (this.shouldIgnore()) {
|
||||
return {
|
||||
metadata: {},
|
||||
code: code,
|
||||
map: null,
|
||||
ast: null
|
||||
};
|
||||
}
|
||||
|
||||
callback();
|
||||
|
||||
return this.generate();
|
||||
} catch (err) {
|
||||
if (err._babel) {
|
||||
throw err;
|
||||
} else {
|
||||
err._babel = true;
|
||||
}
|
||||
|
||||
var message = err.message = `${this.opts.filename}: ${err.message}`;
|
||||
|
||||
var loc = err.loc;
|
||||
if (loc) {
|
||||
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, this.opts);
|
||||
message += "\n" + err.codeFrame;
|
||||
}
|
||||
|
||||
if (err.stack) {
|
||||
var newStack = err.stack.replace(err.message, message);
|
||||
try {
|
||||
err.stack = newStack;
|
||||
} catch (e) {
|
||||
// `err.stack` may be a readonly property in some environments
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
addCode(code: string, parseCode?) {
|
||||
code = (code || "") + "";
|
||||
code = this.parseInputSourceMap(code);
|
||||
this.code = code;
|
||||
|
||||
if (parseCode) {
|
||||
this.parseShebang();
|
||||
this.addAst(this.parse(this.code));
|
||||
}
|
||||
}
|
||||
|
||||
shouldIgnore() {
|
||||
var opts = this.opts;
|
||||
return util.shouldIgnore(opts.filename, opts.ignore, opts.only);
|
||||
}
|
||||
|
||||
call(key: string) {
|
||||
var stack = this.transformerStack;
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var transformer = stack[i].transformer;
|
||||
var fn = transformer[key];
|
||||
if (fn) fn(this);
|
||||
}
|
||||
}
|
||||
|
||||
parseInputSourceMap(code: string) {
|
||||
var opts = this.opts;
|
||||
|
||||
if (opts.inputSourceMap !== false) {
|
||||
var inputMap = convertSourceMap.fromSource(code);
|
||||
if (inputMap) {
|
||||
opts.inputSourceMap = inputMap.toObject();
|
||||
code = convertSourceMap.removeComments(code);
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
parseShebang() {
|
||||
var shebangMatch = shebangRegex.exec(this.code);
|
||||
if (shebangMatch) {
|
||||
this.shebang = shebangMatch[0];
|
||||
this.code = this.code.replace(shebangRegex, "");
|
||||
}
|
||||
}
|
||||
|
||||
generate(): {
|
||||
usedHelpers?: Array<string>;
|
||||
code: string;
|
||||
|
||||
@ -57,16 +57,19 @@ export default class TransformerPipeline {
|
||||
|
||||
transform(code: string, opts?: Object) {
|
||||
var file = new File(opts, this);
|
||||
return file.parse(code);
|
||||
return file.wrap(code, function () {
|
||||
file.addCode(code, true);
|
||||
});
|
||||
}
|
||||
|
||||
transformFromAst(ast, code, opts) {
|
||||
ast = normalizeAst(ast);
|
||||
|
||||
var file = new File(opts, this);
|
||||
file.addCode(code);
|
||||
file.transform(ast);
|
||||
return file.generate();
|
||||
return file.wrap(code, function () {
|
||||
file.addCode(code);
|
||||
file.addAst(ast);
|
||||
});
|
||||
}
|
||||
|
||||
_ensureTransformerNames(type: string, rawKeys: Array<string>) {
|
||||
|
||||
@ -3,7 +3,8 @@ import isBoolean from "lodash/lang/isBoolean";
|
||||
import isNumber from "lodash/lang/isNumber";
|
||||
import isRegExp from "lodash/lang/isRegExp";
|
||||
import isString from "lodash/lang/isString";
|
||||
import * as parse from "../../helpers/parse";
|
||||
import codeFrame from "../../helpers/code-frame";
|
||||
import { all as parse } from "../../helpers/parse";
|
||||
import traverse from "../index";
|
||||
import includes from "lodash/collection/includes";
|
||||
import assign from "lodash/object/assign";
|
||||
@ -478,11 +479,19 @@ export default class TraversalPath {
|
||||
*/
|
||||
|
||||
replaceWithSourceString(replacement) {
|
||||
replacement = parse.all(`(${replacement})`, {
|
||||
filename: "custom string",
|
||||
errorMessage: "make sure this is an expression"
|
||||
}).body[0].expression;
|
||||
try {
|
||||
replacement = `(${replacement})`;
|
||||
replacement = parse(code);
|
||||
} catch (err) {
|
||||
var loc = err.loc;
|
||||
if (loc) {
|
||||
err.message += " - make sure this is an expression.";
|
||||
err.message += "\n" + codeFrame(replacement, loc.line, loc.column + 1);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
replacement = replacement.body[0].expression;
|
||||
traverse.removeProperties(replacement);
|
||||
return this.replaceWith(replacement);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user