clarity-pattern-parser 11.4.2 → 11.5.1

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.
@@ -8,6 +8,7 @@ export declare class Expression implements Pattern {
8
8
  private _name;
9
9
  private _originalName;
10
10
  private _parent;
11
+ private _cachedParent;
11
12
  private _firstIndex;
12
13
  private _originalPatterns;
13
14
  private _patterns;
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.1",
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>) {
@@ -17,6 +17,7 @@ export class Expression implements Pattern {
17
17
  private _name: string;
18
18
  private _originalName: string;
19
19
  private _parent: Pattern | null;
20
+ private _cachedParent: Pattern | null;
20
21
  private _firstIndex: number;
21
22
  private _originalPatterns: Pattern[];
22
23
  private _patterns: Pattern[];
@@ -92,6 +93,7 @@ export class Expression implements Pattern {
92
93
  this._name = name;
93
94
  this._originalName = name;
94
95
  this._parent = null;
96
+ this._cachedParent = null;
95
97
  this._firstIndex = 0;
96
98
  this._atomPatterns = [];
97
99
  this._prefixPatterns = [];
@@ -278,7 +280,8 @@ export class Expression implements Pattern {
278
280
  }
279
281
 
280
282
  build() {
281
- if (!this._hasOrganized) {
283
+ if (!this._hasOrganized || this._cachedParent !== this.parent) {
284
+ this._cachedParent = this.parent;
282
285
  this._hasOrganized = true;
283
286
  this._organizePatterns(this._originalPatterns);
284
287
  this._cacheAncestors();
@@ -491,6 +494,7 @@ export class Expression implements Pattern {
491
494
  }
492
495
 
493
496
  getTokens(): string[] {
497
+ this.build();
494
498
  const atomTokens = this._atomPatterns.map(p => p.getTokens()).flat();
495
499
  const prefixTokens = this.prefixPatterns.map(p => p.getTokens()).flat();
496
500
 
@@ -498,6 +502,7 @@ export class Expression implements Pattern {
498
502
  }
499
503
 
500
504
  getTokensAfter(childReference: Pattern): string[] {
505
+ this.build();
501
506
  if (this._prefixPatterns.includes(childReference) || this._binaryPatterns.includes(childReference)) {
502
507
  const atomTokens = this._atomPatterns.map(p => p.getTokens()).flat();
503
508
  const prefixTokens = this.prefixPatterns.map(p => p.getTokens()).flat();
@@ -534,6 +539,7 @@ export class Expression implements Pattern {
534
539
  }
535
540
 
536
541
  getPatterns(): Pattern[] {
542
+ this.build();
537
543
  const atomPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
538
544
  const prefixPatterns = this.prefixPatterns.map(p => p.getPatterns()).flat();
539
545
 
@@ -541,6 +547,7 @@ export class Expression implements Pattern {
541
547
  }
542
548
 
543
549
  getPatternsAfter(childReference: Pattern): Pattern[] {
550
+ this.build();
544
551
  if (this._prefixPatterns.includes(childReference) || this._binaryPatterns.includes(childReference)) {
545
552
  const atomPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
546
553
  const prefixPatterns = this.prefixPatterns.map(p => p.getPatterns()).flat();