add TraversalPath#replaceInline, fix traversal path not updating sibling keys correctly
This commit is contained in:
parent
7a44576c26
commit
06a58f228c
@ -14,29 +14,47 @@ export default class TraversalContext {
|
|||||||
return TraversalPath.get(this.parentPath, this, node, obj, key);
|
return TraversalPath.get(this.parentPath, this, node, obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit(node, key) {
|
visitMultiple(nodes, node, key) {
|
||||||
var nodes = node[key];
|
|
||||||
if (!nodes) return;
|
|
||||||
|
|
||||||
if (!Array.isArray(nodes)) {
|
|
||||||
return this.create(node, node, key).visit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// nothing to traverse!
|
// nothing to traverse!
|
||||||
if (nodes.length === 0) {
|
if (nodes.length === 0) return false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var queue = [];
|
var queue = this.queue = [];
|
||||||
|
var stop = false;
|
||||||
|
var done = [];
|
||||||
|
|
||||||
|
// build up initial queue
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
if (nodes[i]) queue.push(this.create(node, nodes, i));
|
if (nodes[i]) queue.push(this.create(node, nodes, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// visit the queue
|
||||||
for (let i = 0; i < queue.length; i++) {
|
for (let i = 0; i < queue.length; i++) {
|
||||||
if (queue[i].visit()) {
|
if (queue[i].visit()) {
|
||||||
return true;
|
stop = true;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear context from queued paths
|
||||||
|
for (let i = 0; i < queue.length; i++) {
|
||||||
|
//queue[i].clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
return stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitSingle(node, key) {
|
||||||
|
return this.create(node, node, key).visit();
|
||||||
|
}
|
||||||
|
|
||||||
|
visit(node, key) {
|
||||||
|
var nodes = node[key];
|
||||||
|
if (!nodes) return;
|
||||||
|
|
||||||
|
if (Array.isArray(nodes)) {
|
||||||
|
return this.visitMultiple(nodes, node, key);
|
||||||
|
} else {
|
||||||
|
return this.visitSingle(node, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,6 +78,12 @@ export default class TraversalPath {
|
|||||||
return ourScope;
|
return ourScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queueNode(path) {
|
||||||
|
if (this.context) {
|
||||||
|
this.context.queue.push(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
insertBefore(nodes) {
|
insertBefore(nodes) {
|
||||||
this.checkNodes(nodes);
|
this.checkNodes(nodes);
|
||||||
|
|
||||||
@ -89,15 +95,24 @@ export default class TraversalPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_containerInsertAfter(nodes) {
|
||||||
|
this.updateSiblingKeys(this.key + 1, nodes.length);
|
||||||
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
|
var to = this.key + 1 + i;
|
||||||
|
this.container.splice(to, 0, nodes[i]);
|
||||||
|
|
||||||
|
if (this.context) {
|
||||||
|
this.queueNode(this.context.create(this.parent, this.container, to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
insertAfter(nodes) {
|
insertAfter(nodes) {
|
||||||
this.checkNodes(nodes);
|
this.checkNodes(nodes);
|
||||||
|
|
||||||
if (this.isPreviousType("Statement")) {
|
if (this.isPreviousType("Statement")) {
|
||||||
if (Array.isArray(this.container)) {
|
if (Array.isArray(this.container)) {
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
this._containerInsertAfter(nodes);
|
||||||
this.container.splice(this.key + 1 + i, 0, nodes[i]);
|
|
||||||
}
|
|
||||||
this.updateSiblingKeys(this.key + nodes.length, nodes.length);
|
|
||||||
} else if (includes(t.STATEMENT_OR_BLOCK_KEYS, this.key) && !t.isBlockStatement(this.container)) {
|
} else if (includes(t.STATEMENT_OR_BLOCK_KEYS, this.key) && !t.isBlockStatement(this.container)) {
|
||||||
this.container[this.key] = t.blockStatement(nodes);
|
this.container[this.key] = t.blockStatement(nodes);
|
||||||
} else {
|
} else {
|
||||||
@ -139,6 +154,10 @@ export default class TraversalPath {
|
|||||||
this.scope = TraversalPath.getScope(this, this.context && this.context.scope, file);
|
this.scope = TraversalPath.getScope(this, this.context && this.context.scope, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearContext() {
|
||||||
|
this.context = null;
|
||||||
|
}
|
||||||
|
|
||||||
setContext(parentPath, context, key, file?) {
|
setContext(parentPath, context, key, file?) {
|
||||||
this.shouldSkip = false;
|
this.shouldSkip = false;
|
||||||
this.shouldStop = false;
|
this.shouldStop = false;
|
||||||
@ -200,18 +219,34 @@ export default class TraversalPath {
|
|||||||
throw new Error("Don't use `path.node = newNode;`, use `path.replaceWith(newNode)` or `path.replaceWithMultiple([newNode])`");
|
throw new Error("Don't use `path.node = newNode;`, use `path.replaceWith(newNode)` or `path.replaceWithMultiple([newNode])`");
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceWithMultiple(nodes: Array<Object>) {
|
replaceInline(nodes) {
|
||||||
|
if (Array.isArray(nodes)) {
|
||||||
|
if (Array.isArray(this.container)) {
|
||||||
|
this._verifyNodeList("replaceInline", nodes);
|
||||||
|
this._containerInsertAfter(nodes);
|
||||||
|
return this.remove();
|
||||||
|
} else {
|
||||||
|
return this.replaceWithMultiple(nodes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.replaceWith(nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_verifyNodeList(key, nodes) {
|
||||||
if (nodes.indexOf(this.node) >= 0) {
|
if (nodes.indexOf(this.node) >= 0) {
|
||||||
// todo: check for inclusion of current node in `nodes` and yell at the user if it's in there and tell them to use `insertBefore` or `insertAfter`
|
// todo: possibly check for inclusion of current node and yell at the user as it's an anti-pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
if (!node) throw new Error(`Falsy node passed to \`path.replaceWithMultiple()\` with the index of ${i}`);
|
if (!node) throw new Error(`Falsy node passed to \`path.${key}()\` with the index of ${i}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.inherits(nodes[0], this.node);
|
replaceWithMultiple(nodes: Array<Object>) {
|
||||||
|
this._verifyNodeList("replaceWithMultiple", nodes);
|
||||||
|
t.inheritsComments(nodes[0], this.node);
|
||||||
this.container[this.key] = null;
|
this.container[this.key] = null;
|
||||||
this.insertAfter(nodes);
|
this.insertAfter(nodes);
|
||||||
if (!this.node) this.remove();
|
if (!this.node) this.remove();
|
||||||
|
|||||||
@ -76,7 +76,7 @@ var templateVisitor = {
|
|||||||
}
|
}
|
||||||
if (t.isIdentifier(node) && has(nodes, node.name)) {
|
if (t.isIdentifier(node) && has(nodes, node.name)) {
|
||||||
this.skip();
|
this.skip();
|
||||||
return nodes[node.name];
|
this.replaceInline(nodes[node.name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user