UNPKG

solidity-antlr4

Version:

Solidity Lang Lexer and Parser by official ANTLR4 grammar

104 lines (103 loc) 3.07 kB
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 }); };