Skip to content

Commit

Permalink
fix: make BinaryOperatorSpacesFixer work as pre-v3.47 (#7751)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wirone committed Jan 16, 2024
1 parent bf48c81 commit 66d2e15
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 94 deletions.
94 changes: 18 additions & 76 deletions src/Fixer/Operator/BinaryOperatorSpacesFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -552,19 +552,19 @@ private function fixAlignment(Tokens $tokens, array $toAlign): void
$this->deepestLevel = 0;
$this->currentLevel = 0;

// This fixer works partially on Tokens and partially on string representation of code.
// During the process of fixing internal state of single Token may be affected by injecting ALIGN_PLACEHOLDER to its content.
// The placeholder will be resolved by `replacePlaceholders` method by removing placeholder or changing it into spaces.
// That way of fixing the code causes disturbances in marking Token as changed - if code is perfectly valid then placeholder
// still be injected and removed, which will cause the `changed` flag to be set.
// To handle that unwanted behavior we work on clone of Tokens collection and then override original collection with fixed collection.
$tokensClone = clone $tokens;

foreach ($toAlign as $tokenContent => $alignStrategy) {
// This fixer works partially on Tokens and partially on string representation of code.
// During the process of fixing internal state of single Token may be affected by injecting ALIGN_PLACEHOLDER to its content.
// The placeholder will be resolved by `replacePlaceholders` method by removing placeholder or changing it into spaces.
// That way of fixing the code causes disturbances in marking Token as changed - if code is perfectly valid then placeholder
// still be injected and removed, which will cause the `changed` flag to be set.
// To handle that unwanted behavior we work on clone of Tokens collection and then override original collection with fixed collection.
$tokensClone = clone $tokens;

if ('=>' === $tokenContent) {
$this->injectAlignmentPlaceholdersForArrow($tokensClone, 0, \count($tokensClone));
$this->injectAlignmentPlaceholdersForArrow($tokensClone, 0, \count($tokens));
} else {
$this->injectAlignmentPlaceholdersDefault($tokensClone, 0, \count($tokensClone), $tokenContent);
$this->injectAlignmentPlaceholdersDefault($tokensClone, 0, \count($tokens), $tokenContent);
}

// for all tokens that should be aligned but do not have anything to align with, fix spacing if needed
Expand All @@ -575,32 +575,28 @@ private function fixAlignment(Tokens $tokens, array $toAlign): void
|| self::ALIGN_SINGLE_SPACE_MINIMAL_BY_SCOPE === $alignStrategy
) {
if ('=>' === $tokenContent) {
for ($index = $tokensClone->count() - 2; $index > 0; --$index) {
if ($tokensClone[$index]->isGivenKind(T_DOUBLE_ARROW)) { // always binary operator, never part of declare statement
for ($index = $tokens->count() - 2; $index > 0; --$index) {
if ($tokens[$index]->isGivenKind(T_DOUBLE_ARROW)) { // always binary operator, never part of declare statement
$this->fixWhiteSpaceBeforeOperator($tokensClone, $index, $alignStrategy);
}
}
} elseif ('=' === $tokenContent) {
for ($index = $tokensClone->count() - 2; $index > 0; --$index) {
if ('=' === $tokensClone[$index]->getContent() && !$this->isEqualPartOfDeclareStatement($tokensClone, $index) && $this->tokensAnalyzer->isBinaryOperator($index)) {
for ($index = $tokens->count() - 2; $index > 0; --$index) {
if ('=' === $tokens[$index]->getContent() && !$this->isEqualPartOfDeclareStatement($tokens, $index) && $this->tokensAnalyzer->isBinaryOperator($index)) {
$this->fixWhiteSpaceBeforeOperator($tokensClone, $index, $alignStrategy);
}
}
} else {
for ($index = $tokensClone->count() - 2; $index > 0; --$index) {
$content = $tokensClone[$index]->getContent();
for ($index = $tokens->count() - 2; $index > 0; --$index) {
$content = $tokens[$index]->getContent();
if (strtolower($content) === $tokenContent && $this->tokensAnalyzer->isBinaryOperator($index)) { // never part of declare statement
$this->fixWhiteSpaceBeforeOperator($tokensClone, $index, $alignStrategy);
}
}
}
}

$tokensClone->setCode($this->replacePlaceholders($tokensClone, $alignStrategy, $tokenContent));
}

if ($tokensClone->generateCode() !== $tokens->generateCode()) {
$tokens->setCode($tokensClone->generateCode());
$tokens->setCode($this->replacePlaceholders($tokensClone, $alignStrategy, $tokenContent));
}
}

Expand Down Expand Up @@ -929,7 +925,7 @@ private function replacePlaceholders(Tokens $tokens, string $alignStrategy, stri

if ($delta > 0) {
$line = str_replace($placeholder, str_repeat(' ', $delta).$placeholder, $line);
$lines[$index] = $this->getReAlignedLineWithMultipleShiftsInSingleLine($line, $alignStrategy, $placeholder, $tokenContent, $delta);
$lines[$index] = $line;
}
}
}
Expand All @@ -939,58 +935,4 @@ private function replacePlaceholders(Tokens $tokens, string $alignStrategy, stri

return $tmpCode;
}

private function getReAlignedLineWithMultipleShiftsInSingleLine(
string $line,
string $alignStrategy,
string $placeholder,
string $tokenContent,
int $delta
): string {
if (
self::ALIGN === $alignStrategy
|| self::ALIGN_BY_SCOPE === $alignStrategy
) {
return $line;
}

$strAlreadyAligned = str_replace(
$placeholder.$tokenContent,
'',
mb_strstr($line, $placeholder.$tokenContent)
);

$quotedOperators = [];
foreach (array_keys($this->alignOperatorTokens) as $alignOperatorToken) {
$quotedOperators[] = preg_quote($alignOperatorToken, '/');
}

$count = 0;
$replacedStr = Preg::replaceCallback(
'/\s*?('.implode('|', $quotedOperators).')/',
static function ($matches) use (&$count, $delta) {
$tokenWithEmptyStr = $matches[0];
$token = $matches[1];
$emptyStrCount = mb_substr_count($tokenWithEmptyStr, ' ');
$reAlignedStr = $tokenWithEmptyStr;
if (0 === $count) {
if ($emptyStrCount - $delta > 0) {
$reAlignedStr = str_repeat(' ', $emptyStrCount - $delta).$token;
}
} else {
$reAlignedStr = str_repeat(' ', $delta).$tokenWithEmptyStr;
}
++$count;

return $reAlignedStr;
},
$strAlreadyAligned,
);

return mb_strstr(
$line,
$placeholder.$tokenContent,
true
).$placeholder.$tokenContent.$replacedStr;
}
}
18 changes: 0 additions & 18 deletions tests/Fixer/Operator/BinaryOperatorSpacesFixerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -556,24 +556,6 @@ function A(){}[$a] = $a[$c];
null,
['operators' => ['|' => BinaryOperatorSpacesFixer::NO_SPACE]],
];

yield 'multiple shifts in single line' => [
'<?php
$testA = $testB["abc"] / $testC * 100;
$testD = $testE["abcdef"] / $testF * 100;
$testA = $testB["abc"] / $testC * 10000000 * 100;
$testD = $testE["abcdef"] / $testF * 10000000000 * 100;
',
'<?php
$testA = $testB["abc"]/$testC * 100;
$testD = $testE["abcdef"]/$testF * 100;
$testA = $testB["abc"]/$testC * 10000000 * 100;
$testD = $testE["abcdef"]/$testF * 10000000000 * 100;
',
['default' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL],
];
}

/**
Expand Down

0 comments on commit 66d2e15

Please sign in to comment.