clarity-pattern-parser 11.4.2 → 11.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-pattern-parser",
3
- "version": "11.4.2",
3
+ "version": "11.5.0",
4
4
  "description": "Parsing Library for Typescript and Javascript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",
@@ -477,4 +477,42 @@ describe("Node", () => {
477
477
  expect(result.isEqual(expected)).toBeTruthy();
478
478
  });
479
479
 
480
+ test("Find All", () => {
481
+ const a = new Node("a", "a", 0, 0, [], "A");
482
+ const b = new Node("b", "b", 0, 0, [], "B");
483
+ const a2 = a.clone();
484
+ const parent = new Node("parent", "parent", 0, 0, [a, b, a2]);
485
+
486
+ const result = parent.findAll(n => n.name === "a");
487
+ expect(result).toEqual([a, a2]);
488
+ });
489
+
490
+ test("Breadth First Early Exit", () => {
491
+ const a = new Node("a", "a", 0, 0, [], "A");
492
+ const b = new Node("b", "b", 0, 0, [], "B");
493
+ const a2 = a.clone();
494
+ const parent = new Node("parent", "parent", 0, 0, [a, b, a2]);
495
+
496
+ let count = 0;
497
+ parent.walkBreadthFirst(n => {
498
+ count++;
499
+ if (n.name === "a") {
500
+ return false;
501
+ }
502
+ return true;
503
+ });
504
+
505
+ expect(count).toBe(2);
506
+ });
507
+
508
+ test("Find All (Breadth First)", () => {
509
+ const a = new Node("a", "a", 0, 0, [], "A");
510
+ const b = new Node("b", "b", 0, 0, [], "B");
511
+ const a2 = a.clone();
512
+ const parent = new Node("parent", "parent", 0, 0, [a, b, a2]);
513
+
514
+ const result = parent.findAll(n => n.name === "a", true);
515
+ expect(result).toEqual([a, a2]);
516
+ });
517
+
480
518
  });
package/src/ast/Node.ts CHANGED
@@ -190,16 +190,40 @@ export class Node {
190
190
  return null;
191
191
  }
192
192
 
193
- find(predicate: (node: Node) => boolean): Node | null {
194
- return this.findAll(predicate)[0] || null;
193
+ find(predicate: (node: Node) => boolean, breadthFirst = false): Node | null {
194
+ let match: Node | null = null;
195
+
196
+ if (breadthFirst) {
197
+ this.walkBreadthFirst(n => {
198
+ if (predicate(n)) {
199
+ match = n;
200
+ return false;
201
+ }
202
+ });
203
+ } else {
204
+ this.walkUp(n => {
205
+ if (predicate(n)) {
206
+ match = n;
207
+ return false;
208
+ }
209
+ });
210
+ }
211
+
212
+ return match;
195
213
  }
196
214
 
197
- findAll(predicate: (node: Node) => boolean): Node[] {
215
+ findAll(predicate: (node: Node) => boolean, breadthFirst = false): Node[] {
198
216
  const matches: Node[] = [];
199
217
 
200
- this.walkUp(n => {
201
- if (predicate(n)) { matches.push(n); }
202
- });
218
+ if (breadthFirst) {
219
+ this.walkBreadthFirst(n => {
220
+ if (predicate(n)) { matches.push(n); }
221
+ });
222
+ } else {
223
+ this.walkUp(n => {
224
+ if (predicate(n)) { matches.push(n);}
225
+ });
226
+ }
203
227
 
204
228
  return matches;
205
229
  }
@@ -229,28 +253,31 @@ export class Node {
229
253
  return null;
230
254
  }
231
255
 
232
- walkUp(callback: (node: Node) => void) {
256
+ walkUp(callback: (node: Node) => boolean | void): boolean {
233
257
  const childrenCopy = this._children.slice();
234
258
 
235
- childrenCopy.forEach(c => c.walkUp(callback));
236
- callback(this);
259
+ const result = childrenCopy.every(c => c.walkUp(callback));
260
+ return (callback(this) ?? true) && result;
237
261
  }
238
262
 
239
- walkDown(callback: (node: Node) => void) {
263
+ walkDown(callback: (node: Node) => boolean | void): boolean {
240
264
  const childrenCopy = this._children.slice();
241
265
 
242
- callback(this);
243
- childrenCopy.forEach(c => c.walkDown(callback));
266
+ return (callback(this) ?? true) && childrenCopy.every(c => c.walkDown(callback));
244
267
  }
245
268
 
246
- walkBreadthFirst(callback: (node: Node) => void): void {
269
+ walkBreadthFirst(callback: (node: Node) => boolean | void): boolean {
247
270
  const queue: Node[] = [this];
248
271
 
249
272
  while (queue.length > 0) {
250
273
  const current = queue.shift() as Node;
251
- callback(current);
274
+ if (callback(current) === false) {
275
+ return false;
276
+ }
252
277
  queue.push(...current.children);
253
278
  }
279
+
280
+ return true;
254
281
  }
255
282
 
256
283
  transform(visitors: Record<string, (node: Node) => Node>) {