Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add support for replacing nodes with expression source strings
  • Loading branch information
sebmck committed May 3, 2015
1 parent f24b516 commit 0fc02f2
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 65 deletions.
17 changes: 1 addition & 16 deletions src/babel/api/node.js
Expand Up @@ -14,6 +14,7 @@ export { default as TransformerPipeline } from "../transformation/transformer-pi
export { default as traverse } from "../traversal";
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
export { version } from "../../../package";
export { all as parse } from "../helpers/parse";

import * as t from "../types";
export { t as types };
Expand Down Expand Up @@ -55,19 +56,3 @@ export function transformFileSync(filename: string, opts?: Object = {}) {
opts.filename = filename;
return transform(fs.readFileSync(filename), opts);
}

export function parse(code, opts = {}) {
opts.sourceType = "module";
opts.ecmaVersion = Infinity;
opts.plugins = {
flow: true,
jsx: true
};
opts.features = {};

for (var key in transform.pipeline.transformers) {
opts.features[key] = true;
}

return acorn.parse(code, opts);
}
117 changes: 70 additions & 47 deletions src/babel/helpers/parse.js
Expand Up @@ -3,63 +3,86 @@ import estraverse from "estraverse";
import codeFrame from "./code-frame";
import * as acorn from "../../acorn";

export default function (opts, code, callback) {
function parseCatch(code, opts) {
var comments = opts.onComment = [];
var tokens = opts.onToken = [];

try {
var comments = [];
var tokens = [];
return acorn.parse(code, opts);
} catch (err) {
if (err._babel) {
throw err;
} else {
err._babel = true;
}

var parseOpts = {
allowImportExportEverywhere: opts.looseModules,
allowReturnOutsideFunction: opts.looseModules,
ecmaVersion: 6,
strictMode: opts.strictMode,
sourceType: opts.sourceType,
onComment: comments,
locations: true,
features: opts.features || {},
plugins: opts.plugins || {},
onToken: tokens,
ranges: true
};
if (opts.errorMessage) {
err.message += ` - ${opts.errorMessage}`;
}

if (opts.nonStandard) {
parseOpts.plugins.jsx = true;
parseOpts.plugins.flow = true;
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;
}

var ast = acorn.parse(code, parseOpts);
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
}
}

estraverse.attachComments(ast, comments, tokens);
throw err;
}
}

ast = normalizeAst(ast, comments, tokens);
export default function (opts, code, callback) {
var parseOpts = {
allowImportExportEverywhere: opts.looseModules,
allowReturnOutsideFunction: opts.looseModules,
ecmaVersion: 6,
strictMode: opts.strictMode,
sourceType: opts.sourceType,
locations: true,
features: opts.features || {},
plugins: opts.plugins || {},
ranges: true
};

if (callback) {
return callback(ast);
} else {
return ast;
}
} catch (err) {
if (!err._babel) {
err._babel = true;
if (opts.nonStandard) {
parseOpts.plugins.jsx = true;
parseOpts.plugins.flow = true;
}

var message = err.message = `${opts.filename}: ${err.message}`;
var ast = parseCatch(code, parseOpts);

var loc = err.loc;
if (loc) {
err.codeFrame = codeFrame(code, loc.line, loc.column + 1, opts);
message += "\n" + err.codeFrame;
}
estraverse.attachComments(ast, parseOpts.onComment, parseOpts.onToken);
ast = normalizeAst(ast, parseOpts.onComment, parseOpts.onToken);

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
}
}
}
if (callback) {
return callback(ast);
} else {
return ast;
}
}

throw err;
export function all(code, opts = {}) {
opts.sourceType = "module";
opts.ecmaVersion = Infinity;
opts.plugins = {
flow: true,
jsx: true
};
opts.features = {};

for (var key in transform.pipeline.transformers) {
opts.features[key] = true;
}
};

return parseCatch(code, opts);
}
33 changes: 31 additions & 2 deletions src/babel/traversal/path/index.js
Expand Up @@ -3,6 +3,7 @@ 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 traverse from "../index";
import includes from "lodash/collection/includes";
import assign from "lodash/object/assign";
Expand Down Expand Up @@ -476,7 +477,21 @@ export default class TraversalPath {
* Description
*/

replaceWith(replacement, arraysAllowed) {
replaceWithSourceString(replacement) {
replacement = parse.all(`(${replacement})`, {
filename: "custom string",
errorMessage: "make sure this is an expression"
}).body[0].expression;

traverse.removeProperties(replacement);
return this.replaceWith(replacement);
}

/**
* Description
*/

replaceWith(replacement, whateverAllowed) {
if (this.removed) {
throw new Error("You can't replace this node, we've already removed it");
}
Expand All @@ -486,13 +501,27 @@ export default class TraversalPath {
}

if (Array.isArray(replacement)) {
if (arraysAllowed) {
if (whateverAllowed) {
return this.replaceWithMultiple(replacement);
} else {
throw new Error("Don't use `path.replaceWith()` with an array of nodes, use `path.replaceWithMultiple()`");
}
}

if (typeof replacement === "string") {
if (whateverAllowed) {
return this.replaceWithSourceString(replacement);
} else {
throw new Error("Don't use `path.replaceWith()` with a string, use `path.replaceWithSourceString()`");
}
}

// replacing a statement with an expression so wrap it in an expression statement
if (this.isPreviousType("Statement") && t.isExpression(replacement)) {
replacement = t.expressionStatement(replacement);
}

// replacing an expression with a statement so let's explode it
if (this.isPreviousType("Expression") && t.isStatement(replacement)) {
return this.replaceExpressionWithStatements([replacement]);
}
Expand Down

0 comments on commit 0fc02f2

Please sign in to comment.