solidity-antlr4
Version:
Solidity Lang Lexer and Parser by official ANTLR4 grammar
104 lines (103 loc) • 3.07 kB
JavaScript
import { traverse } from "./traverse.js";
export var SelectorCombinator = /* @__PURE__ */ ((SelectorCombinator2) => {
SelectorCombinator2["Child"] = ">";
SelectorCombinator2["Inside"] = " ";
return SelectorCombinator2;
})(SelectorCombinator || {});
const getPathKey = (path) => `${path.path}#${JSON.stringify(path.node)}`;
export class Selector {
constructor(filter, _offset) {
this.filter = filter;
this._offset = _offset;
}
static create = (filter, _offset) => {
let target = {};
if (typeof filter !== "string") {
target = filter;
} else if (filter === "*") {
target = {};
} else {
target = { type: filter };
}
return new Selector(target, _offset);
};
next;
combinator;
_prev;
_getStartSelector = () => {
return this._prev ? this._prev._getStartSelector() : this;
};
chain = (combinator, f, _offset) => {
this.combinator = combinator;
const next = Selector.create(f, _offset || this._offset);
next._prev = this;
this.next = next;
return next;
};
child = (f, _offset) => {
return this.chain(">" /* Child */, f, _offset);
};
inside = (f, _offset) => {
return this.chain(" " /* Inside */, f, _offset);
};
/** @inner */
query = (node, options = {}) => {
if (!node)
return {};
const result = {};
traverse(node, (path) => {
if (path.matches(this.filter) && path.checkOffset(this._offset)) {
Object.assign(result, this.recursion(path, options));
}
});
return result;
};
/** @inner */
recursion = (path, options = {}) => {
if (!path.matches(this.filter))
return {};
if (!path.checkOffset(this._offset))
return {};
const result = {};
if (!this.next) {
result[getPathKey(path)] = path;
return result;
}
if (this.combinator === ">" /* Child */) {
traverse(path, (p) => {
if (p.depth - path.depth > 1)
p.stop();
Object.assign(result, this.next.recursion(p, options));
});
} else if (this.combinator === " " /* Inside */) {
traverse(path, (p) => {
Object.assign(result, this.next.recursion(p, options));
});
}
return result;
};
}
export const createSelector = Selector.create;
export const query = (ast, selector, options = {}) => {
if (!ast)
return [];
const result = {};
const selectors = Array.isArray(selector) ? selector : [selector];
for (let index = 0; index < selectors.length; index += 1) {
const current = selectors[index];
const startSelector = current._getStartSelector();
Object.assign(result, startSelector.query(ast, options));
}
return Object.values(result).sort((current, next) => {
if (options.order === "desc") {
return next.depth - current.depth;
}
return current.depth - next.depth;
});
};
export const querySelector = (ast, selector) => {
return query(ast, selector, { queryAll: false })?.[0] ?? null;
};
export const querySelectorAll = (ast, selector) => {
return query(ast, selector, { queryAll: true });
};