Skip to content

Commit

Permalink
Switch to a class
Browse files Browse the repository at this point in the history
  • Loading branch information
XhmikosR committed Apr 22, 2023
1 parent 66d5f28 commit 3ffaadf
Showing 1 changed file with 111 additions and 109 deletions.
220 changes: 111 additions & 109 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,135 +6,137 @@ function isObject(str) {
return typeof str === 'object' && !Array.isArray(str) && str !== null;
}

/**
* @param {Object} options - Options to configure parser
* @param {Object} options.parser - An object with a parse method that returns an AST
*/
module.exports = function(options = {}) {
this.parser = options.parser || parser;

if (options.parser) {
// We don't want to send that down to the actual parser
delete options.parser;
}
module.exports = class NodeSourceWalk {
/**
* @param {Object} options - Options to configure parser
* @param {Object} options.parser - An object with a parse method that returns an AST
*/
constructor(options = {}) {
this.parser = options.parser || parser;

if (options.parser) {
// We don't want to send that down to the actual parser
delete options.parser;
}

this.options = {
plugins: [
'jsx',
'flow',
'asyncGenerators',
'classProperties',
'doExpressions',
'dynamicImport',
'exportDefaultFrom',
'exportNamespaceFrom',
'functionBind',
'functionSent',
'nullishCoalescingOperator',
'objectRestSpread',
[
'decorators', {
decoratorsBeforeExport: true
}
this.options = {
plugins: [
'jsx',
'flow',
'asyncGenerators',
'classProperties',
'doExpressions',
'dynamicImport',
'exportDefaultFrom',
'exportNamespaceFrom',
'functionBind',
'functionSent',
'nullishCoalescingOperator',
'objectRestSpread',
[
'decorators', {
decoratorsBeforeExport: true
}
],
'optionalChaining'
],
'optionalChaining'
],
allowHashBang: true,
sourceType: 'module',
...options
};

// We use global state to stop the recursive traversal of the AST
this.shouldStop = false;
};
allowHashBang: true,
sourceType: 'module',
...options
};

/**
* @param {String} src
* @param {Object} [options] - Parser options
* @return {Object} The AST of the given src
*/
module.exports.prototype.parse = function(src, options) {
options = options || this.options;

// Keep around for consumers of parse that supply their own options
if (typeof options.allowHashBang === 'undefined') {
options.allowHashBang = true;
// We use global state to stop the recursive traversal of the AST
this.shouldStop = false;
}

return this.parser.parse(src, options);
};

/**
* Adapted from substack/node-detective
* Executes cb on a non-array AST node
*/
module.exports.prototype.traverse = function(node, cb) {
if (this.shouldStop) return;

if (Array.isArray(node)) {
for (const key of node) {
if (isObject(key)) {
// Mark that the node has been visited
key.parent = node;
this.traverse(key, cb);
}
/**
* @param {String} src
* @param {Object} [options] - Parser options
* @return {Object} The AST of the given src
*/
parse(src, options) {
options = options || this.options;

// Keep around for consumers of parse that supply their own options
if (typeof options.allowHashBang === 'undefined') {
options.allowHashBang = true;
}
} else if (node && isObject(node)) {
cb(node);

for (const [key, value] of Object.entries(node)) {
// Avoid visited nodes
if (key === 'parent' || !value) continue;
return this.parser.parse(src, options);
}

if (isObject(value)) {
value.parent = node;
/**
* Adapted from substack/node-detective
* Executes cb on a non-array AST node
*/
traverse(node, cb) {
if (this.shouldStop) return;

if (Array.isArray(node)) {
for (const key of node) {
if (isObject(key)) {
// Mark that the node has been visited
key.parent = node;
this.traverse(key, cb);
}
}
} else if (node && isObject(node)) {
cb(node);

for (const [key, value] of Object.entries(node)) {
// Avoid visited nodes
if (key === 'parent' || !value) continue;

this.traverse(value, cb);
if (isObject(value)) {
value.parent = node;
}

this.traverse(value, cb);
}
}
}
};

/**
* Executes the passed callback for every traversed node of
* the passed in src's ast
*
* @param {String|Object} src - The source code or AST to traverse
* @param {Function} cb - Called for every node
*/
module.exports.prototype.walk = function(src, cb) {
this.shouldStop = false;

const ast = isObject(src) ? src : this.parse(src);
/**
* Executes the passed callback for every traversed node of
* the passed in src's ast
*
* @param {String|Object} src - The source code or AST to traverse
* @param {Function} cb - Called for every node
*/
walk(src, cb) {
this.shouldStop = false;

this.traverse(ast, cb);
};
const ast = isObject(src) ? src : this.parse(src);

module.exports.prototype.moonwalk = function(node, cb) {
this.shouldStop = false;
this.traverse(ast, cb);
}

if (!isObject(node)) throw new Error('node must be an object');
moonwalk(node, cb) {
this.shouldStop = false;

reverseTraverse.call(this, node, cb);
};
if (!isObject(node)) throw new Error('node must be an object');

function reverseTraverse(node, cb) {
if (this.shouldStop || !node.parent) return;
this._reverseTraverse(node, cb);
}

if (Array.isArray(node.parent)) {
for (const parent of node.parent) {
cb(parent);
}
} else {
cb(node.parent);
/**
* Halts further traversal of the AST
*/
stopWalking() {
this.shouldStop = true;
}

reverseTraverse.call(this, node.parent, cb);
}
_reverseTraverse(node, cb) {
if (this.shouldStop || !node.parent) return;

if (Array.isArray(node.parent)) {
for (const parent of node.parent) {
cb(parent);
}
} else {
cb(node.parent);
}

/**
* Halts further traversal of the AST
*/
module.exports.prototype.stopWalking = function() {
this.shouldStop = true;
this._reverseTraverse(node.parent, cb);
}
};

0 comments on commit 3ffaadf

Please sign in to comment.