@@ -478,92 +478,138 @@ function walk(
478
478
function deleteEdgeIn ( node : NodeClass , edge : SafeEdge ) {
479
479
node . edgesIn . delete ( edge )
480
480
if ( edge . overrides ) {
481
- // updateNodeOverrideSetDueToEdgeRemoval(node, edge.overrides)
481
+ updateNodeOverrideSetDueToEdgeRemoval ( node , edge . overrides )
482
482
}
483
483
}
484
484
485
- // function recalculateOutEdgesOverrides (node: NodeClass) {
486
- // // For each edge out propogate the new overrides through.
487
- // for (const [, edge] of node.edgesOut) {
488
- // edge.reload(true)
489
- // if (edge.to) {
490
- // updateNodeOverrideSet(edge.to, edge.overrides)
491
- // }
492
- // }
493
- // }
494
-
495
- // function findSpecificOverrideSet (first, second) {
496
- // for (let OverrideSet = second; OverrideSet; OverrideSet = OverrideSet.parent) {
497
- // if (OverrideSet.isEqual(first)) {
498
- // return second
499
- // }
500
- // }
501
- // for (let OverrideSet = first; OverrideSet; OverrideSet = OverrideSet.parent) {
502
- // if (OverrideSet.isEqual(second)) {
503
- // return first
504
- // }
505
- // }
506
- // console.log('Conflicting override sets')
507
- // }
508
-
509
- // function updateNodeOverrideSetDueToEdgeRemoval (node: NodeClass, otherOverrideSet) {
510
- // // If this edge's overrides isn't equal to this node's overrides, then removing it won't change newOverrideSet later.
511
- // if (!node.overrides || !node.overrides.isEqual(otherOverrideSet)) {
512
- // return false
513
- // }
514
- // let newOverrideSet
515
- // for (const edge of node.edgesIn) {
516
- // if (newOverrideSet) {
517
- // newOverrideSet = findSpecificOverrideSet(node, edge.overrides, newOverrideSet)
518
- // } else {
519
- // newOverrideSet = edge.overrides
520
- // }
521
- // }
522
- // if (overrides.isEqual(newOverrideSet)) {
523
- // return false
524
- // }
525
- // this.overrides = newOverrideSet
526
- // if (this.overrides) {
527
- // // Optimization: if there's any override set at all, then no non-extraneous node has an empty override set. So if we temporarily have no
528
- // // override set (for example, we removed all the edges in), there's no use updating all the edges out right now. Let's just wait until
529
- // // we have an actual override set later.
530
- // recalculateOutEdgesOverrides(node)
531
- // }
532
- // return true
533
- // }
534
-
535
- // // This logic isn't perfect either. When we have two edges in that have different override sets, then we have to decide which set is correct.
536
- // // This function assumes the more specific override set is applicable, so if we have dependencies A->B->C and A->C
537
- // // and an override set that specifies what happens for C under A->B, this will work even if the new A->C edge comes along and tries to change
538
- // // the override set.
539
- // // The strictly correct logic is not to allow two edges with different overrides to point to the same node, because even if this node can satisfy
540
- // // both, one of its dependencies might need to be different depending on the edge leading to it.
541
- // // However, this might cause a lot of duplication, because the conflict in the dependencies might never actually happen.
542
- // function updateNodeOverrideSet (otherOverrideSet) {
543
- // if (!this.overrides) {
544
- // // Assuming there are any overrides at all, the overrides field is never undefined for any node at the end state of the tree.
545
- // // So if the new edge's overrides is undefined it will be updated later. So we can wait with updating the node's overrides field.
546
- // if (!otherOverrideSet) {
547
- // return false
548
- // }
549
- // this.overrides = otherOverrideSet
550
- // this.recalculateOutEdgesOverrides()
551
- // return true
552
- // }
553
- // if (this.overrides.isEqual(otherOverrideSet)) {
554
- // return false
555
- // }
556
- // const newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet)
557
- // if (newOverrideSet) {
558
- // if (!this.overrides.isEqual(newOverrideSet)) {
559
- // this.overrides = newOverrideSet
560
- // this.recalculateOutEdgesOverrides()
561
- // return true
562
- // }
563
- // return false
564
- // }
565
- // // This is an error condition. We can only get here if the new override set is in conflict with the existing.
566
- // }
485
+ function findSpecificOverrideSet ( first : OverrideSet | undefined , second : OverrideSet | undefined ) {
486
+ let overrideSet = second
487
+ while ( overrideSet ) {
488
+ if ( overrideSetsEqual ( overrideSet , first ) ) {
489
+ return second
490
+ }
491
+ overrideSet = overrideSet . parent
492
+ }
493
+ overrideSet = first
494
+ while ( overrideSet ) {
495
+ if ( overrideSetsEqual ( overrideSet , second ) ) {
496
+ return first
497
+ }
498
+ overrideSet = overrideSet . parent
499
+ }
500
+ console . error ( 'Conflicting override sets' )
501
+ }
502
+
503
+ function recalculateOutEdgesOverrides ( node : NodeClass ) {
504
+ // For each edge out propagate the new overrides through.
505
+ for ( const [ , edge ] of node . edgesOut ) {
506
+ edge . reload ( true )
507
+ if ( edge . to ) {
508
+ updateNodeOverrideSet ( edge . to , edge . overrides )
509
+ }
510
+ }
511
+ }
512
+
513
+ function updateNodeOverrideSetDueToEdgeRemoval ( node : NodeClass , other : OverrideSet ) {
514
+ // If this edge's overrides isn't equal to this node's overrides, then removing it won't change newOverrideSet later.
515
+ if ( ! node . overrides || ! overrideSetsEqual ( node . overrides , other ) ) {
516
+ return false
517
+ }
518
+ let newOverrideSet
519
+ for ( const edge of node . edgesIn ) {
520
+ if ( newOverrideSet ) {
521
+ newOverrideSet = findSpecificOverrideSet ( edge . overrides , newOverrideSet )
522
+ } else {
523
+ newOverrideSet = edge . overrides
524
+ }
525
+ }
526
+ if ( overrideSetsEqual ( node . overrides , newOverrideSet ) ) {
527
+ return false
528
+ }
529
+ node . overrides = newOverrideSet
530
+ if ( node . overrides ) {
531
+ // Optimization: if there's any override set at all, then no non-extraneous node has an empty override set. So if we temporarily have no
532
+ // override set (for example, we removed all the edges in), there's no use updating all the edges out right now. Let's just wait until
533
+ // we have an actual override set later.
534
+ recalculateOutEdgesOverrides ( node )
535
+ }
536
+ return true
537
+ }
538
+
539
+ // This logic isn't perfect either. When we have two edges in that have different override sets, then we have to decide which set is correct.
540
+ // This function assumes the more specific override set is applicable, so if we have dependencies A->B->C and A->C
541
+ // and an override set that specifies what happens for C under A->B, this will work even if the new A->C edge comes along and tries to change
542
+ // the override set.
543
+ // The strictly correct logic is not to allow two edges with different overrides to point to the same node, because even if this node can satisfy
544
+ // both, one of its dependencies might need to be different depending on the edge leading to it.
545
+ // However, this might cause a lot of duplication, because the conflict in the dependencies might never actually happen.
546
+ function updateNodeOverrideSet ( node : NodeClass , otherOverrideSet : OverrideSet | undefined ) {
547
+ if ( ! node . overrides ) {
548
+ // Assuming there are any overrides at all, the overrides field is never undefined for any node at the end state of the tree.
549
+ // So if the new edge's overrides is undefined it will be updated later. So we can wait with updating the node's overrides field.
550
+ if ( ! otherOverrideSet ) {
551
+ return false
552
+ }
553
+ node . overrides = otherOverrideSet
554
+ recalculateOutEdgesOverrides ( node )
555
+ return true
556
+ }
557
+ const { overrides } = node
558
+ if ( overrideSetsEqual ( overrides , otherOverrideSet ) ) {
559
+ return false
560
+ }
561
+ const newOverrideSet = findSpecificOverrideSet ( overrides , otherOverrideSet )
562
+ if ( newOverrideSet ) {
563
+ if ( ! overrideSetsEqual ( overrides , newOverrideSet ) ) {
564
+ node . overrides = newOverrideSet
565
+ recalculateOutEdgesOverrides ( node )
566
+ return true
567
+ }
568
+ return false
569
+ }
570
+ // This is an error condition. We can only get here if the new override set is in conflict with the existing.
571
+ }
572
+
573
+ function overrideSetsChildrenAreEqual ( overrideSet : OverrideSet , other : OverrideSet ) {
574
+ const { children } = overrideSet
575
+ const { children : otherChildren } = other
576
+ if ( children . size !== otherChildren . size ) {
577
+ return false
578
+ }
579
+ for ( const key of children . keys ( ) ) {
580
+ if ( ! otherChildren . has ( key ) ) {
581
+ return false
582
+ }
583
+ const child = < OverrideSet > children . get ( key )
584
+ const otherChild = < OverrideSet > otherChildren . get ( key )
585
+ if ( child ! . value !== otherChild ! . value ) {
586
+ return false
587
+ }
588
+ if ( ! overrideSetsChildrenAreEqual ( child , otherChild ) ) {
589
+ return false
590
+ }
591
+ }
592
+ return true
593
+ }
594
+
595
+ function overrideSetsEqual ( overrideSet : OverrideSet , other : OverrideSet | undefined ) {
596
+ if ( overrideSet === other ) {
597
+ return true
598
+ }
599
+ if ( ! other ) {
600
+ return false
601
+ }
602
+ if ( overrideSet . key !== other . key || overrideSet . value !== other . value ) {
603
+ return false
604
+ }
605
+ if ( ! overrideSetsChildrenAreEqual ( overrideSet , other ) ) {
606
+ return false
607
+ }
608
+ if ( ! overrideSet . parent ) {
609
+ return ! other . parent
610
+ }
611
+ return overrideSetsEqual ( overrideSet . parent , other . parent )
612
+ }
567
613
568
614
// An edge in the dependency graph
569
615
// Represents a dependency relationship of some kind
0 commit comments