Cleanup fast-path (#1743)

- I want to get to a place where we don't use ast-types in order to do the traversal. This almost removes it from fast-path.
- Remove FastPath.from and copy
- Use .prototype instead of the weird Fpp
- Remove unused TODO
- Remove unused needsParen condition with a bunch of associated code
master
Christopher Chedeau 2017-05-26 10:59:12 -07:00 committed by GitHub
parent 06806068f6
commit 7bd951652c
2 changed files with 11 additions and 90 deletions

View File

@ -4,8 +4,6 @@ const assert = require("assert");
const types = require("./ast-types");
const util = require("./util");
const n = types.namedTypes;
const isArray = types.builtInTypes.array;
const isNumber = types.builtInTypes.number;
const startsWithNoLookaheadToken = util.startsWithNoLookaheadToken;
function FastPath(value) {
@ -13,40 +11,9 @@ function FastPath(value) {
this.stack = [value];
}
const FPp = FastPath.prototype;
// Static convenience function for coercing a value to a FastPath.
FastPath.from = function(obj) {
if (obj instanceof FastPath) {
// Return a defensive copy of any existing FastPath instances.
return obj.copy();
}
if (obj instanceof types.NodePath) {
// For backwards compatibility, unroll NodePath instances into
// lightweight FastPath [..., name, value] stacks.
const copy = Object.create(FastPath.prototype);
const stack = [obj.value];
for (let pp; (pp = obj.parentPath); obj = pp) {
stack.push(obj.name, pp.value);
}
copy.stack = stack.reverse();
return copy;
}
// Otherwise use obj as the value of the new FastPath instance.
return new FastPath(obj);
};
FPp.copy = function copy() {
const copy = Object.create(FastPath.prototype);
copy.stack = this.stack.slice(0);
return copy;
};
// The name of the current property is always the penultimate element of
// this.stack, and always a String.
FPp.getName = function getName() {
FastPath.prototype.getName = function getName() {
const s = this.stack;
const len = s.length;
if (len > 1) {
@ -59,7 +26,7 @@ FPp.getName = function getName() {
// The value of the current property is always the final element of
// this.stack.
FPp.getValue = function getValue() {
FastPath.prototype.getValue = function getValue() {
const s = this.stack;
return s[s.length - 1];
};
@ -70,7 +37,7 @@ function getNodeHelper(path, count) {
for (let i = s.length - 1; i >= 0; i -= 2) {
const value = s[i];
if (n.Node.check(value) && --count < 0) {
if (value && !Array.isArray(value) && --count < 0) {
return value;
}
}
@ -78,36 +45,20 @@ function getNodeHelper(path, count) {
return null;
}
FPp.getNode = function getNode(count) {
FastPath.prototype.getNode = function getNode(count) {
return getNodeHelper(this, ~~count);
};
FPp.getParentNode = function getParentNode(count) {
FastPath.prototype.getParentNode = function getParentNode(count) {
return getNodeHelper(this, ~~count + 1);
};
FPp.isLast = function isLast() {
const s = this.stack;
if (this.getParentNode()) {
const idx = s[s.length - 2];
// The name of this node should be an index
assert.ok(typeof idx === "number");
const arr = s[s.length - 3];
// We should have an array as a parent node
assert.ok(Array.isArray(arr));
return idx === arr.length - 1;
}
return false;
};
// Temporarily push properties named by string arguments given after the
// callback function onto this.stack, then call the callback with a
// reference to this (modified) FastPath object. Note that the stack will
// be restored to its original state after the callback is finished, so it
// is probably a mistake to retain a reference to the path.
FPp.call = function call(callback /*, name1, name2, ... */) {
FastPath.prototype.call = function call(callback /*, name1, name2, ... */) {
const s = this.stack;
const origLen = s.length;
let value = s[origLen - 1];
@ -126,7 +77,7 @@ FPp.call = function call(callback /*, name1, name2, ... */) {
// accessing this.getValue()[name1][name2]... should be array-like. The
// callback will be called with a reference to this path object for each
// element of the array.
FPp.each = function each(callback /*, name1, name2, ... */) {
FastPath.prototype.each = function each(callback /*, name1, name2, ... */) {
const s = this.stack;
const origLen = s.length;
let value = s[origLen - 1];
@ -154,7 +105,7 @@ FPp.each = function each(callback /*, name1, name2, ... */) {
// Similar to FastPath.prototype.each, except that the results of the
// callback function invocations are stored in an array and returned at
// the end of the iteration.
FPp.map = function map(callback /*, name1, name2, ... */) {
FastPath.prototype.map = function map(callback /*, name1, name2, ... */) {
const s = this.stack;
const origLen = s.length;
let value = s[origLen - 1];
@ -183,7 +134,7 @@ FPp.map = function map(callback /*, name1, name2, ... */) {
// Inspired by require("ast-types").NodePath.prototype.needsParens, but
// more efficient because we're iterating backwards through a stack.
FPp.needsParens = function() {
FastPath.prototype.needsParens = function() {
const parent = this.getParentNode();
if (!parent) {
return false;
@ -459,7 +410,7 @@ FPp.needsParens = function() {
case "Literal":
return (
parent.type === "MemberExpression" &&
isNumber.check(node.value) &&
typeof node.value === "number" &&
name === "object" &&
parent.object === node
);
@ -575,33 +526,7 @@ FPp.needsParens = function() {
return parent.type === "ExpressionStatement"; // To avoid becoming a directive
}
if (
parent.type === "NewExpression" &&
name === "callee" &&
parent.callee === node
) {
return containsCallExpression(node);
}
return false;
};
function containsCallExpression(node) {
if (n.CallExpression.check(node)) {
return true;
}
if (isArray.check(node)) {
return node.some(containsCallExpression);
}
if (n.Node.check(node)) {
return types.someField(node, (name, child) => {
return containsCallExpression(child);
});
}
return false;
}
module.exports = FastPath;

View File

@ -164,10 +164,6 @@ function genericPrintNoParens(path, options, print, args) {
return n;
}
// TODO: Investigate types that return not printable.
// This assert isn't very useful though.
// namedTypes.Printable.assert(n);
let parts = [];
switch (n.type) {
case "File":
@ -4618,7 +4614,7 @@ function printAstToDoc(ast, options, addAlignmentSize) {
);
}
let doc = printGenerically(FastPath.from(ast));
let doc = printGenerically(new FastPath(ast));
if (addAlignmentSize > 0) {
// Add a hardline to make the indents take effect
// It should be removed in index.js format()