mirror of
https://github.com/shivammathur/setup-php.git
synced 2025-10-12 22:41:30 +07:00
Improve code quality and write tests
This commit is contained in:
313
node_modules/regexp-tree/dist/traverse/index.js
generated
vendored
Normal file
313
node_modules/regexp-tree/dist/traverse/index.js
generated
vendored
Normal file
@ -0,0 +1,313 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var NodePath = require('./node-path');
|
||||
|
||||
/**
|
||||
* Does an actual AST traversal, using visitor pattern,
|
||||
* and calling set of callbacks.
|
||||
*
|
||||
* Based on https://github.com/olov/ast-traverse
|
||||
*
|
||||
* Expects AST in Mozilla Parser API: nodes which are supposed to be
|
||||
* handled should have `type` property.
|
||||
*
|
||||
* @param Object root - a root node to start traversal from.
|
||||
*
|
||||
* @param Object options - an object with set of callbacks:
|
||||
*
|
||||
* - `pre(node, parent, prop, index)` - a hook called on node enter
|
||||
* - `post`(node, parent, prop, index) - a hook called on node exit
|
||||
* - `skipProperty(prop)` - a predicated whether a property should be skipped
|
||||
*/
|
||||
function astTraverse(root) {
|
||||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
|
||||
var pre = options.pre;
|
||||
var post = options.post;
|
||||
var skipProperty = options.skipProperty;
|
||||
|
||||
function visit(node, parent, prop, idx) {
|
||||
if (!node || typeof node.type !== 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
var res = undefined;
|
||||
if (pre) {
|
||||
res = pre(node, parent, prop, idx);
|
||||
}
|
||||
|
||||
if (res !== false) {
|
||||
|
||||
// A node can be replaced during traversal, so we have to
|
||||
// recalculate it from the parent, to avoid traversing "dead" nodes.
|
||||
if (parent && parent[prop]) {
|
||||
if (!isNaN(idx)) {
|
||||
node = parent[prop][idx];
|
||||
} else {
|
||||
node = parent[prop];
|
||||
}
|
||||
}
|
||||
|
||||
for (var _prop in node) {
|
||||
if (node.hasOwnProperty(_prop)) {
|
||||
if (skipProperty ? skipProperty(_prop, node) : _prop[0] === '$') {
|
||||
continue;
|
||||
}
|
||||
|
||||
var child = node[_prop];
|
||||
|
||||
// Collection node.
|
||||
//
|
||||
// NOTE: a node (or several nodes) can be removed or inserted
|
||||
// during traversal.
|
||||
//
|
||||
// Current traversing index is stored on top of the
|
||||
// `NodePath.traversingIndexStack`. The stack is used to support
|
||||
// recursive nature of the traversal.
|
||||
//
|
||||
// In this case `NodePath.traversingIndex` (which we use here) is
|
||||
// updated in the NodePath remove/insert methods.
|
||||
//
|
||||
if (Array.isArray(child)) {
|
||||
var index = 0;
|
||||
NodePath.traversingIndexStack.push(index);
|
||||
while (index < child.length) {
|
||||
visit(child[index], node, _prop, index);
|
||||
index = NodePath.updateTraversingIndex(+1);
|
||||
}
|
||||
NodePath.traversingIndexStack.pop();
|
||||
}
|
||||
|
||||
// Simple node.
|
||||
else {
|
||||
visit(child, node, _prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (post) {
|
||||
post(node, parent, prop, idx);
|
||||
}
|
||||
}
|
||||
|
||||
visit(root, null);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Traverses an AST.
|
||||
*
|
||||
* @param Object ast - an AST node
|
||||
*
|
||||
* @param Object | Array<Object> handlers:
|
||||
*
|
||||
* an object (or an array of objects)
|
||||
*
|
||||
* Each such object contains a handler function per node.
|
||||
* In case of an array of handlers, they are applied in order.
|
||||
* A handler may return a transformed node (or a different type).
|
||||
*
|
||||
* The per-node function may instead be an object with functions pre and post.
|
||||
* pre is called before visiting the node, post after.
|
||||
* If a handler is a function, it is treated as the pre function, with an empty post.
|
||||
*
|
||||
* @param Object options:
|
||||
*
|
||||
* a config object, specifying traversal options:
|
||||
*
|
||||
* `asNodes`: boolean - whether handlers should receives raw AST nodes
|
||||
* (false by default), instead of a `NodePath` wrapper. Note, by default
|
||||
* `NodePath` wrapper provides a set of convenient method to manipulate
|
||||
* a traversing AST, and also has access to all parents list. A raw
|
||||
* nodes traversal should be used in rare cases, when no `NodePath`
|
||||
* features are needed.
|
||||
*
|
||||
* Special hooks:
|
||||
*
|
||||
* - `shouldRun(ast)` - a predicate determining whether the handler
|
||||
* should be applied.
|
||||
*
|
||||
* NOTE: Multiple handlers are used as an optimization of applying all of
|
||||
* them in one AST traversal pass.
|
||||
*/
|
||||
traverse: function traverse(ast, handlers) {
|
||||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { asNodes: false };
|
||||
|
||||
|
||||
if (!Array.isArray(handlers)) {
|
||||
handlers = [handlers];
|
||||
}
|
||||
|
||||
// Filter out handlers by result of `shouldRun`, if the method is present.
|
||||
handlers = handlers.filter(function (handler) {
|
||||
if (typeof handler.shouldRun !== 'function') {
|
||||
return true;
|
||||
}
|
||||
return handler.shouldRun(ast);
|
||||
});
|
||||
|
||||
NodePath.initRegistry();
|
||||
|
||||
// Allow handlers to initializer themselves.
|
||||
handlers.forEach(function (handler) {
|
||||
if (typeof handler.init === 'function') {
|
||||
handler.init(ast);
|
||||
}
|
||||
});
|
||||
|
||||
function getPathFor(node, parent, prop, index) {
|
||||
var parentPath = NodePath.getForNode(parent);
|
||||
var nodePath = NodePath.getForNode(node, parentPath, prop, index);
|
||||
|
||||
return nodePath;
|
||||
}
|
||||
|
||||
// Handle actual nodes.
|
||||
astTraverse(ast, {
|
||||
/**
|
||||
* Handler on node enter.
|
||||
*/
|
||||
pre: function pre(node, parent, prop, index) {
|
||||
var nodePath = void 0;
|
||||
if (!options.asNodes) {
|
||||
nodePath = getPathFor(node, parent, prop, index);
|
||||
}
|
||||
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = handlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var handler = _step.value;
|
||||
|
||||
// "Catch-all" `*` handler.
|
||||
if (typeof handler['*'] === 'function') {
|
||||
if (nodePath) {
|
||||
// A path/node can be removed by some previous handler.
|
||||
if (!nodePath.isRemoved()) {
|
||||
var handlerResult = handler['*'](nodePath);
|
||||
// Explicitly stop traversal.
|
||||
if (handlerResult === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handler['*'](node, parent, prop, index);
|
||||
}
|
||||
}
|
||||
|
||||
// Per-node handler.
|
||||
var handlerFuncPre = void 0;
|
||||
if (typeof handler[node.type] === 'function') {
|
||||
handlerFuncPre = handler[node.type];
|
||||
} else if (typeof handler[node.type] === 'object' && typeof handler[node.type].pre === 'function') {
|
||||
handlerFuncPre = handler[node.type].pre;
|
||||
}
|
||||
|
||||
if (handlerFuncPre) {
|
||||
if (nodePath) {
|
||||
// A path/node can be removed by some previous handler.
|
||||
if (!nodePath.isRemoved()) {
|
||||
var _handlerResult = handlerFuncPre.call(handler, nodePath);
|
||||
// Explicitly stop traversal.
|
||||
if (_handlerResult === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handlerFuncPre.call(handler, node, parent, prop, index);
|
||||
}
|
||||
}
|
||||
} // Loop over handlers
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// pre func
|
||||
|
||||
/**
|
||||
* Handler on node exit.
|
||||
*/
|
||||
post: function post(node, parent, prop, index) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
var nodePath = void 0;
|
||||
if (!options.asNodes) {
|
||||
nodePath = getPathFor(node, parent, prop, index);
|
||||
}
|
||||
|
||||
var _iteratorNormalCompletion2 = true;
|
||||
var _didIteratorError2 = false;
|
||||
var _iteratorError2 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator2 = handlers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||||
var handler = _step2.value;
|
||||
|
||||
// Per-node handler.
|
||||
var handlerFuncPost = void 0;
|
||||
if (typeof handler[node.type] === 'object' && typeof handler[node.type].post === 'function') {
|
||||
handlerFuncPost = handler[node.type].post;
|
||||
}
|
||||
|
||||
if (handlerFuncPost) {
|
||||
if (nodePath) {
|
||||
// A path/node can be removed by some previous handler.
|
||||
if (!nodePath.isRemoved()) {
|
||||
var handlerResult = handlerFuncPost.call(handler, nodePath);
|
||||
// Explicitly stop traversal.
|
||||
if (handlerResult === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handlerFuncPost.call(handler, node, parent, prop, index);
|
||||
}
|
||||
}
|
||||
} // Loop over handlers
|
||||
} catch (err) {
|
||||
_didIteratorError2 = true;
|
||||
_iteratorError2 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||||
_iterator2.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError2) {
|
||||
throw _iteratorError2;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// post func
|
||||
|
||||
/**
|
||||
* Skip locations by default.
|
||||
*/
|
||||
skipProperty: function skipProperty(prop) {
|
||||
return prop === 'loc';
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
426
node_modules/regexp-tree/dist/traverse/node-path.js
generated
vendored
Normal file
426
node_modules/regexp-tree/dist/traverse/node-path.js
generated
vendored
Normal file
@ -0,0 +1,426 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var DEFAULT_COLLECTION_PROP = 'expressions';
|
||||
var DEFAULT_SINGLE_PROP = 'expression';
|
||||
|
||||
/**
|
||||
* NodePath class encapsulates a traversing node,
|
||||
* its parent node, property name in the parent node, and
|
||||
* an index (in case if a node is part of a collection).
|
||||
* It also provides set of methods for AST manipulation.
|
||||
*/
|
||||
|
||||
var NodePath = function () {
|
||||
/**
|
||||
* NodePath constructor.
|
||||
*
|
||||
* @param Object node - an AST node
|
||||
* @param NodePath parentPath - a nullable parent path
|
||||
* @param string property - property name of the node in the parent
|
||||
* @param number index - index of the node in a collection.
|
||||
*/
|
||||
function NodePath(node) {
|
||||
var parentPath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
var property = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||||
var index = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
||||
|
||||
_classCallCheck(this, NodePath);
|
||||
|
||||
this.node = node;
|
||||
this.parentPath = parentPath;
|
||||
this.parent = parentPath ? parentPath.node : null;
|
||||
this.property = property;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
_createClass(NodePath, [{
|
||||
key: '_enforceProp',
|
||||
value: function _enforceProp(property) {
|
||||
if (!this.node.hasOwnProperty(property)) {
|
||||
throw new Error('Node of type ' + this.node.type + ' doesn\'t have "' + property + '" collection.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a node into a children collection or the single child.
|
||||
* By default child nodes are supposed to be under `expressions` property.
|
||||
* An explicit property can be passed.
|
||||
*
|
||||
* @param Object node - a node to set into a collection or as single child
|
||||
* @param number index - index at which to set
|
||||
* @param string property - name of the collection or single property
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'setChild',
|
||||
value: function setChild(node) {
|
||||
var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
var property = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||||
|
||||
|
||||
var childPath = void 0;
|
||||
if (index != null) {
|
||||
if (!property) {
|
||||
property = DEFAULT_COLLECTION_PROP;
|
||||
}
|
||||
this._enforceProp(property);
|
||||
this.node[property][index] = node;
|
||||
childPath = NodePath.getForNode(node, this, property, index);
|
||||
} else {
|
||||
if (!property) {
|
||||
property = DEFAULT_SINGLE_PROP;
|
||||
}
|
||||
this._enforceProp(property);
|
||||
this.node[property] = node;
|
||||
childPath = NodePath.getForNode(node, this, property, null);
|
||||
}
|
||||
return childPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a node to a children collection.
|
||||
* By default child nodes are supposed to be under `expressions` property.
|
||||
* An explicit property can be passed.
|
||||
*
|
||||
* @param Object node - a node to set into a collection or as single child
|
||||
* @param string property - name of the collection or single property
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'appendChild',
|
||||
value: function appendChild(node) {
|
||||
var property = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
|
||||
|
||||
if (!property) {
|
||||
property = DEFAULT_COLLECTION_PROP;
|
||||
}
|
||||
this._enforceProp(property);
|
||||
var end = this.node[property].length;
|
||||
return this.setChild(node, end, property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a node into a collection.
|
||||
* By default child nodes are supposed to be under `expressions` property.
|
||||
* An explicit property can be passed.
|
||||
*
|
||||
* @param Object node - a node to insert into a collection
|
||||
* @param number index - index at which to insert
|
||||
* @param string property - name of the collection property
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'insertChildAt',
|
||||
value: function insertChildAt(node, index) {
|
||||
var property = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_COLLECTION_PROP;
|
||||
|
||||
this._enforceProp(property);
|
||||
|
||||
this.node[property].splice(index, 0, node);
|
||||
|
||||
// If we inserted a node before the traversing index,
|
||||
// we should increase the later.
|
||||
if (index <= NodePath.getTraversingIndex()) {
|
||||
NodePath.updateTraversingIndex(+1);
|
||||
}
|
||||
|
||||
this._rebuildIndex(this.node, property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a node.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'remove',
|
||||
value: function remove() {
|
||||
if (this.isRemoved()) {
|
||||
return;
|
||||
}
|
||||
NodePath.registry.delete(this.node);
|
||||
|
||||
this.node = null;
|
||||
|
||||
if (!this.parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// A node is in a collection.
|
||||
if (this.index !== null) {
|
||||
this.parent[this.property].splice(this.index, 1);
|
||||
|
||||
// If we remove a node before the traversing index,
|
||||
// we should increase the later.
|
||||
if (this.index <= NodePath.getTraversingIndex()) {
|
||||
NodePath.updateTraversingIndex(-1);
|
||||
}
|
||||
|
||||
// Rebuild index.
|
||||
this._rebuildIndex(this.parent, this.property);
|
||||
|
||||
this.index = null;
|
||||
this.property = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// A simple node.
|
||||
delete this.parent[this.property];
|
||||
this.property = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds child nodes index (used on remove/insert).
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_rebuildIndex',
|
||||
value: function _rebuildIndex(parent, property) {
|
||||
var parentPath = NodePath.getForNode(parent);
|
||||
|
||||
for (var i = 0; i < parent[property].length; i++) {
|
||||
var path = NodePath.getForNode(parent[property][i], parentPath, property, i);
|
||||
path.index = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the path was removed.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'isRemoved',
|
||||
value: function isRemoved() {
|
||||
return this.node === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a node with the passed one.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'replace',
|
||||
value: function replace(newNode) {
|
||||
NodePath.registry.delete(this.node);
|
||||
|
||||
this.node = newNode;
|
||||
|
||||
if (!this.parent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// A node is in a collection.
|
||||
if (this.index !== null) {
|
||||
this.parent[this.property][this.index] = newNode;
|
||||
}
|
||||
|
||||
// A simple node.
|
||||
else {
|
||||
this.parent[this.property] = newNode;
|
||||
}
|
||||
|
||||
// Rebuild the node path for the new node.
|
||||
return NodePath.getForNode(newNode, this.parentPath, this.property, this.index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a node inline.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'update',
|
||||
value: function update(nodeProps) {
|
||||
Object.assign(this.node, nodeProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns parent.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'getParent',
|
||||
value: function getParent() {
|
||||
return this.parentPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns nth child.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'getChild',
|
||||
value: function getChild() {
|
||||
var n = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||
|
||||
if (this.node.expressions) {
|
||||
return NodePath.getForNode(this.node.expressions[n], this, DEFAULT_COLLECTION_PROP, n);
|
||||
} else if (this.node.expression && n == 0) {
|
||||
return NodePath.getForNode(this.node.expression, this, DEFAULT_SINGLE_PROP);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a path node is syntactically equal to the passed one.
|
||||
*
|
||||
* NOTE: we don't rely on `source` property from the `loc` data
|
||||
* (which would be the fastest comparison), since it might be unsync
|
||||
* after several modifications. We use here simple `JSON.stringify`
|
||||
* excluding the `loc` data.
|
||||
*
|
||||
* @param NodePath other - path to compare to.
|
||||
* @return boolean
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'hasEqualSource',
|
||||
value: function hasEqualSource(path) {
|
||||
return JSON.stringify(this.node, jsonSkipLoc) === JSON.stringify(path.node, jsonSkipLoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON-encodes a node skipping location.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'jsonEncode',
|
||||
value: function jsonEncode() {
|
||||
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
||||
format = _ref.format,
|
||||
useLoc = _ref.useLoc;
|
||||
|
||||
return JSON.stringify(this.node, useLoc ? null : jsonSkipLoc, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns previous sibling.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'getPreviousSibling',
|
||||
value: function getPreviousSibling() {
|
||||
if (!this.parent || this.index == null) {
|
||||
return null;
|
||||
}
|
||||
return NodePath.getForNode(this.parent[this.property][this.index - 1], NodePath.getForNode(this.parent), this.property, this.index - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next sibling.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'getNextSibling',
|
||||
value: function getNextSibling() {
|
||||
if (!this.parent || this.index == null) {
|
||||
return null;
|
||||
}
|
||||
return NodePath.getForNode(this.parent[this.property][this.index + 1], NodePath.getForNode(this.parent), this.property, this.index + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a NodePath instance for a node.
|
||||
*
|
||||
* The same NodePath can be reused in several places, e.g.
|
||||
* a parent node passed for all its children.
|
||||
*/
|
||||
|
||||
}], [{
|
||||
key: 'getForNode',
|
||||
value: function getForNode(node) {
|
||||
var parentPath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
var prop = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||||
var index = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : -1;
|
||||
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!NodePath.registry.has(node)) {
|
||||
NodePath.registry.set(node, new NodePath(node, parentPath, prop, index == -1 ? null : index));
|
||||
}
|
||||
|
||||
var path = NodePath.registry.get(node);
|
||||
|
||||
if (parentPath !== null) {
|
||||
path.parentPath = parentPath;
|
||||
path.parent = path.parentPath.node;
|
||||
}
|
||||
|
||||
if (prop !== null) {
|
||||
path.property = prop;
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
path.index = index;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the NodePath registry. The registry is a map from
|
||||
* a node to its NodePath instance.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'initRegistry',
|
||||
value: function initRegistry() {
|
||||
if (!NodePath.registry) {
|
||||
NodePath.registry = new Map();
|
||||
}
|
||||
NodePath.registry.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates index of a currently traversing collection.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'updateTraversingIndex',
|
||||
value: function updateTraversingIndex(dx) {
|
||||
return NodePath.traversingIndexStack[NodePath.traversingIndexStack.length - 1] += dx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current traversing index.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'getTraversingIndex',
|
||||
value: function getTraversingIndex() {
|
||||
return NodePath.traversingIndexStack[NodePath.traversingIndexStack.length - 1];
|
||||
}
|
||||
}]);
|
||||
|
||||
return NodePath;
|
||||
}();
|
||||
|
||||
NodePath.initRegistry();
|
||||
|
||||
/**
|
||||
* Index of a currently traversing collection is stored on top of the
|
||||
* `NodePath.traversingIndexStack`. Remove/insert methods can adjust
|
||||
* this index.
|
||||
*/
|
||||
NodePath.traversingIndexStack = [];
|
||||
|
||||
// Helper function used to skip `loc` in JSON operations.
|
||||
function jsonSkipLoc(prop, value) {
|
||||
if (prop === 'loc') {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
module.exports = NodePath;
|
Reference in New Issue
Block a user