* A tree structure of `Logic` corresponding to a tree of fields. * This implementation represents a leaf in the sense that its logic is derived * from a single builder.
| 344 | * from a single builder. |
| 345 | */ |
| 346 | class LeafLogicNode implements LogicNode { |
| 347 | /** The computed logic for this node. */ |
| 348 | readonly logic: LogicContainer; |
| 349 | |
| 350 | /** |
| 351 | * Constructs a `LeafLogicNode`. |
| 352 | * @param builder The `AbstractLogicNodeBuilder` from which to derive the logic. |
| 353 | * If undefined, an empty `Logic` instance is created. |
| 354 | * @param predicates An array of predicates that gate the logic from the builder. |
| 355 | */ |
| 356 | constructor( |
| 357 | private builder: AbstractLogicNodeBuilder | undefined, |
| 358 | private predicates: BoundPredicate[], |
| 359 | /** The depth of this node in the field tree. */ |
| 360 | private depth: number, |
| 361 | ) { |
| 362 | this.logic = builder ? createLogic(builder, predicates, depth) : new LogicContainer([]); |
| 363 | } |
| 364 | |
| 365 | // TODO: cache here, or just rely on the user of this API to do caching? |
| 366 | /** |
| 367 | * Retrieves the `LogicNode` for a child identified by the given property key. |
| 368 | * @param key The property key of the child. |
| 369 | * @returns The `LogicNode` for the specified child. |
| 370 | */ |
| 371 | getChild(key: PropertyKey): LogicNode { |
| 372 | // The logic for a particular child may be spread across multiple builders. We lazily combine |
| 373 | // this logic at the time the child logic node is requested to be created. |
| 374 | const childBuilders = this.builder ? getAllChildBuilders(this.builder, key) : []; |
| 375 | if (childBuilders.length === 0) { |
| 376 | return new LeafLogicNode(undefined, [], this.depth + 1); |
| 377 | } else if (childBuilders.length === 1) { |
| 378 | const {builder, predicates} = childBuilders[0]; |
| 379 | return new LeafLogicNode( |
| 380 | builder, |
| 381 | [...this.predicates, ...predicates.map((p) => bindLevel(p, this.depth))], |
| 382 | this.depth + 1, |
| 383 | ); |
| 384 | } else { |
| 385 | const builtNodes = childBuilders.map( |
| 386 | ({builder, predicates}) => |
| 387 | new LeafLogicNode( |
| 388 | builder, |
| 389 | [...this.predicates, ...predicates.map((p) => bindLevel(p, this.depth))], |
| 390 | this.depth + 1, |
| 391 | ), |
| 392 | ); |
| 393 | return new CompositeLogicNode(builtNodes); |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | hasLogic(builder: AbstractLogicNodeBuilder): boolean { |
| 398 | if (!this.builder) { |
| 399 | return false; |
| 400 | } |
| 401 | return this.builder.hasLogic(builder); |
| 402 | } |
| 403 |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…