diff --git a/CHANGELOG.md b/CHANGELOG.md index 5255f87e..7f69624e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,8 @@ Please also have a look at our ### Fixed +- Insert `Rule` before sibling even with different property name + (in `RuleSet::addRule()`) (#1270) - Ensure `RuleSet::addRule()` sets non-negative column number when sibling provided (#1268) - Set line number when `RuleSet::addRule()` called with only column number set diff --git a/src/RuleSet/RuleSet.php b/src/RuleSet/RuleSet.php index b24eefab..8e0e8ae5 100644 --- a/src/RuleSet/RuleSet.php +++ b/src/RuleSet/RuleSet.php @@ -104,9 +104,25 @@ public function addRule(Rule $ruleToAdd, ?Rule $sibling = null): void $position = \count($this->rules[$propertyName]); if ($sibling !== null) { + $siblingIsInSet = false; $siblingPosition = \array_search($sibling, $this->rules[$propertyName], true); if ($siblingPosition !== false) { + $siblingIsInSet = true; $position = $siblingPosition; + } else { + $siblingIsInSet = $this->hasRule($sibling); + if ($siblingIsInSet) { + // Maintain ordering within `$this->rules[$propertyName]` + // by inserting before first `Rule` with a same-or-later position than the sibling. + foreach ($this->rules[$propertyName] as $index => $rule) { + if (self::comparePositionable($rule, $sibling) >= 0) { + $position = $index; + break; + } + } + } + } + if ($siblingIsInSet) { // Increment column number of all existing rules on same line, starting at sibling $siblingLineNumber = $sibling->getLineNumber(); $siblingColumnNumber = $sibling->getColumnNumber(); @@ -123,6 +139,7 @@ public function addRule(Rule $ruleToAdd, ?Rule $sibling = null): void $ruleToAdd->setPosition($siblingLineNumber, $siblingColumnNumber); } } + if ($ruleToAdd->getLineNumber() === null) { //this node is added manually, give it the next best line $columnNumber = $ruleToAdd->getColumnNumber() ?? 0; @@ -305,4 +322,15 @@ private static function comparePositionable(Positionable $first, Positionable $s } return $first->getLineNo() - $second->getLineNo(); } + + private function hasRule(Rule $rule): bool + { + foreach ($this->rules as $rulesForAProperty) { + if (\in_array($rule, $rulesForAProperty, true)) { + return true; + } + } + + return false; + } } diff --git a/tests/Unit/RuleSet/RuleSetTest.php b/tests/Unit/RuleSet/RuleSetTest.php index 5b2bfa7a..03cacd85 100644 --- a/tests/Unit/RuleSet/RuleSetTest.php +++ b/tests/Unit/RuleSet/RuleSetTest.php @@ -221,8 +221,6 @@ public function addRuleWithSiblingInsertsRuleBeforeSibling( int $siblingIndex, string $propertyNameToAdd ): void { - self::markTestSkipped('tofix: if property names don\'t match, sibling is ignored'); - $ruleToAdd = new Rule($propertyNameToAdd); $this->setRulesFromPropertyNames($initialPropertyNames); $sibling = $this->subject->getRules()[$siblingIndex];