Skip to content

Commit 14d23b8

Browse files
authored
Allow TraverseCallback to bail out early (#1034)
* Allow TraverseCallback to bail out early It is used in getChildByName to search children, which led to *always* searching all children, which is especially problematic for any deeply nested structures. Improves convert time by 25% on the monaco.d.ts file in #975 * Fix coverage report
1 parent 185ca2f commit 14d23b8

File tree

7 files changed

+63
-44
lines changed

7 files changed

+63
-44
lines changed

package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,14 @@
8080
"documentation",
8181
"generator",
8282
"gruntplugin"
83-
]
83+
],
84+
"nyc": {
85+
"extension": [
86+
".ts",
87+
".tsx"
88+
],
89+
"exclude": [
90+
"**/*.d.ts"
91+
]
92+
}
8493
}

src/lib/models/reflections/abstract.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,11 @@ export enum TraverseProperty {
258258
}
259259

260260
export interface TraverseCallback {
261-
(reflection: Reflection, property: TraverseProperty): void;
261+
/**
262+
* May return false to bail out of any further iteration. To preserve backwards compatibility, if
263+
* a function returns undefined, iteration must continue.
264+
*/
265+
(reflection: Reflection, property: TraverseProperty): boolean | void;
262266
}
263267

264268
/**
@@ -468,20 +472,11 @@ export abstract class Reflection {
468472
return false;
469473
}
470474

471-
/**
472-
* @param name The name of the child to look for. Might contain a hierarchy.
473-
*/
474-
getChildByName(name: string): Reflection;
475-
476-
/**
477-
* @param names The name hierarchy of the child to look for.
478-
*/
479-
getChildByName(names: string[]): Reflection;
480-
481475
/**
482476
* Return a child by its name.
483477
*
484-
* @returns The found child or NULL.
478+
* @param names The name hierarchy of the child to look for.
479+
* @returns The found child or undefined.
485480
*/
486481
getChildByName(arg: string | string[]): Reflection | undefined {
487482
const names: string[] = Array.isArray(arg) ? arg : arg.split('.');
@@ -492,9 +487,10 @@ export abstract class Reflection {
492487
if (child.name === name) {
493488
if (names.length <= 1) {
494489
result = child;
495-
} else if (child) {
490+
} else {
496491
result = child.getChildByName(names.slice(1));
497492
}
493+
return false;
498494
}
499495
});
500496

@@ -610,7 +606,7 @@ export abstract class Reflection {
610606
const lines = [indent + this.toString()];
611607

612608
indent += ' ';
613-
this.traverse((child, property) => {
609+
this.traverse((child) => {
614610
lines.push(child.toStringHierarchy(indent));
615611
});
616612

src/lib/models/reflections/container.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Reflection, ReflectionKind, TraverseCallback, TraverseProperty } from '
22
import { ReflectionCategory } from '../ReflectionCategory';
33
import { ReflectionGroup } from '../ReflectionGroup';
44
import { DeclarationReflection } from './declaration';
5+
import { toArray } from 'lodash';
56

67
export class ContainerReflection extends Reflection {
78
/**
@@ -38,10 +39,10 @@ export class ContainerReflection extends Reflection {
3839
* @param callback The callback function that should be applied for each child reflection.
3940
*/
4041
traverse(callback: TraverseCallback) {
41-
if (this.children) {
42-
this.children.slice().forEach((child: DeclarationReflection) => {
43-
callback(child, TraverseProperty.Children);
44-
});
42+
for (const child of toArray(this.children)) {
43+
if (callback(child, TraverseProperty.Children) === false) {
44+
return;
45+
}
4546
}
4647
}
4748

src/lib/models/reflections/declaration.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Type, ReflectionType } from '../types/index';
33
import { ContainerReflection } from './container';
44
import { SignatureReflection } from './signature';
55
import { TypeParameterReflection } from './type-parameter';
6+
import { toArray } from 'lodash';
67

78
/**
89
* Stores hierarchical type data.
@@ -152,28 +153,40 @@ export class DeclarationReflection extends ContainerReflection implements Defaul
152153
* @param callback The callback function that should be applied for each child reflection.
153154
*/
154155
traverse(callback: TraverseCallback) {
155-
if (this.typeParameters) {
156-
this.typeParameters.slice().forEach((parameter) => callback(parameter, TraverseProperty.TypeParameter));
156+
for (const parameter of toArray(this.typeParameters)) {
157+
if (callback(parameter, TraverseProperty.TypeParameter) === false) {
158+
return;
159+
}
157160
}
158161

159162
if (this.type instanceof ReflectionType) {
160-
callback(this.type.declaration, TraverseProperty.TypeLiteral);
163+
if (callback(this.type.declaration, TraverseProperty.TypeLiteral) === false) {
164+
return;
165+
}
161166
}
162167

163-
if (this.signatures) {
164-
this.signatures.slice().forEach((signature) => callback(signature, TraverseProperty.Signatures));
168+
for (const signature of toArray(this.signatures)) {
169+
if (callback(signature, TraverseProperty.Signatures) === false) {
170+
return;
171+
}
165172
}
166173

167174
if (this.indexSignature) {
168-
callback(this.indexSignature, TraverseProperty.IndexSignature);
175+
if (callback(this.indexSignature, TraverseProperty.IndexSignature) === false) {
176+
return;
177+
}
169178
}
170179

171180
if (this.getSignature) {
172-
callback(this.getSignature, TraverseProperty.GetSignature);
181+
if (callback(this.getSignature, TraverseProperty.GetSignature) === false) {
182+
return;
183+
}
173184
}
174185

175186
if (this.setSignature) {
176-
callback(this.setSignature, TraverseProperty.SetSignature);
187+
if (callback(this.setSignature, TraverseProperty.SetSignature) === false) {
188+
return;
189+
}
177190
}
178191

179192
super.traverse(callback);

src/lib/models/reflections/parameter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ export class ParameterReflection extends Reflection implements DefaultValueConta
1919
*/
2020
traverse(callback: TraverseCallback) {
2121
if (this.type instanceof ReflectionType) {
22-
callback(this.type.declaration, TraverseProperty.TypeLiteral);
22+
if (callback(this.type.declaration, TraverseProperty.TypeLiteral) === false) {
23+
return;
24+
}
2325
}
2426

2527
super.traverse(callback);

src/lib/models/reflections/project.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,13 @@ export class ProjectReflection extends ContainerReflection {
7878
return values;
7979
}
8080

81-
/**
82-
* @param name The name to look for. Might contain a hierarchy.
83-
*/
84-
findReflectionByName(name: string): Reflection;
85-
86-
/**
87-
* @param names The name hierarchy to look for.
88-
*/
89-
findReflectionByName(names: string[]): Reflection;
90-
9181
/**
9282
* Try to find a reflection by its name.
9383
*
84+
* @param names The name hierarchy to look for, if a string, the name will be split on "."
9485
* @return The found reflection or undefined.
9586
*/
96-
findReflectionByName(arg: any): Reflection | undefined {
87+
findReflectionByName(arg: string | string[]): Reflection | undefined {
9788
const names: string[] = Array.isArray(arg) ? arg : arg.split('.');
9889
const name = names.pop();
9990

src/lib/models/reflections/signature.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Reflection, TypeContainer, TypeParameterContainer, TraverseProperty, Tr
33
import { ContainerReflection } from './container';
44
import { ParameterReflection } from './parameter';
55
import { TypeParameterReflection } from './type-parameter';
6+
import { toArray } from 'lodash';
67

78
export class SignatureReflection extends Reflection implements TypeContainer, TypeParameterContainer {
89
parent?: ContainerReflection;
@@ -57,15 +58,21 @@ export class SignatureReflection extends Reflection implements TypeContainer, Ty
5758
*/
5859
traverse(callback: TraverseCallback) {
5960
if (this.type instanceof ReflectionType) {
60-
callback(this.type.declaration, TraverseProperty.TypeLiteral);
61+
if (callback(this.type.declaration, TraverseProperty.TypeLiteral) === false) {
62+
return;
63+
}
6164
}
6265

63-
if (this.typeParameters) {
64-
this.typeParameters.slice().forEach((parameter) => callback(parameter, TraverseProperty.TypeParameter));
66+
for (const parameter of toArray(this.typeParameters)) {
67+
if (callback(parameter, TraverseProperty.TypeParameter) === false) {
68+
return;
69+
}
6570
}
6671

67-
if (this.parameters) {
68-
this.parameters.slice().forEach((parameter) => callback(parameter, TraverseProperty.Parameters));
72+
for (const parameter of toArray(this.parameters)) {
73+
if (callback(parameter, TraverseProperty.Parameters) === false) {
74+
return;
75+
}
6976
}
7077

7178
super.traverse(callback);

0 commit comments

Comments
 (0)