UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

181 lines (180 loc) 5.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GenericTree = void 0; exports.filterTree = filterTree; const defaultRemoveOptions = { keepChildren: true, }; class GenericTree { _tree = []; constructor(tree) { this._tree = tree; } copy() { return new GenericTree(Array.from(this._tree)); } forEach(callback) { for (const n of this.iter()) { callback(n); } } iter() { function* iterNode(...nodes) { for (const n of nodes) { yield n; yield* iterNode(...n.children); } } return iterNode(...Array.from(this._tree)); } filter(callback) { function innerFilter(nodes, callback) { const result = []; for (const n of nodes) { const children = innerFilter(n.children, callback); if (callback(n)) { const newNode = { ...n, children }; result.push(newNode); continue; } if (children.length > 0) { result.push(...children); } } return result; } return innerFilter(this._tree, callback); } filterToTree(callback) { return new GenericTree(this.filter(callback)); } includes(callback) { for (const n of this.iter()) { if (callback(n)) { return true; } } return false; } map(callback) { const result = []; for (const n of this.iter()) { result.push(callback(n)); } return result; } find(callback) { for (const n of this.iter()) { if (callback(n)) { return n; } } return undefined; } findAll(callback) { const result = []; for (const n of this.iter()) { if (callback(n)) { result.push(n); } } return result; } toArray() { return Array.from(this._tree); } toFlatArray() { const result = []; for (const n of this.iter()) { result.push(n); } return result; } get flatLength() { return this.toFlatArray().length; } findParents(toFind, equalsCallback) { function hasChild(node, toFind) { if (equalsCallback(node, toFind)) { return true; } for (const n of node.children) { if (hasChild(n, toFind)) { return true; } } return false; } return this.filterToTree((node) => hasChild(node, toFind)).toFlatArray(); } remove(toRemove, equalsCallback, options = defaultRemoveOptions) { function innerRemove(nodes) { const result = []; for (const n of nodes) { const children = innerRemove(n.children); if (!equalsCallback(n, toRemove)) { const newNode = { ...n, children }; result.push(newNode); continue; } if (options.keepChildren && children.length > 0) { result.push(...children); } } return result; } this._tree = innerRemove(this._tree); } removeAll(toRemove, equalsCallback, options = defaultRemoveOptions) { for (const rmv of toRemove) { this.remove(rmv, equalsCallback, options); } } toString(callback = (node) => node.toString()) { function toStringHelper(indent = 0, ...nodes) { let result = ''; for (const n of nodes) { result += ' '.repeat(indent) + callback(n) + '\n'; result += toStringHelper(indent + 2, ...n.children); } return result; } return toStringHelper(0, ...Array.from(this._tree)); } } exports.GenericTree = GenericTree; //// Example usage with SyntaxNode //const rootNode: SyntaxNode = [> ... <]; //const abstractSyntaxTree = new AbstractTree<SyntaxNode>([rootNode]); // //const allNodes = abstractSyntaxTree.flattenAllChildren(); //const filteredNodes = abstractSyntaxTree.filter((node) => node.type === 'Identifier'); //abstractSyntaxTree.removeChild(rootNode); // //// Example usage with DocumentSymbol //const rootSymbol: DocumentSymbol = [> ... <]; //const abstractSymbolTree = new AbstractTree<DocumentSymbol>([rootSymbol]); // //const allSymbols = abstractSymbolTree.flattenAllChildren(); //const filteredSymbols = abstractSymbolTree.filter((symbol) => symbol.kind === 'Class'); //abstractSymbolTree.removeChild(rootSymbol); function filterTree(nodes, callbackfn) { function inner(nodes, callbackfn) { const result = []; for (const n of nodes) { let children = []; if ('children' in n) { children = inner(n.children, callbackfn); } if (callbackfn(n)) { result.push(n); continue; } if (children.length > 0) { result.push(...children); } } return result; } return inner(nodes, callbackfn); }