Skip to content

Commit

Permalink
ReadonlyPromotedPropertiesFixer - do not make poperty readonly if it …
Browse files Browse the repository at this point in the history
…has an assignment in class (#914)
  • Loading branch information
kubawerlos authored Aug 6, 2023
1 parent 1d9ba55 commit d3f2590
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Latest stable version](https://img.shields.io/packagist/v/kubawerlos/php-cs-fixer-custom-fixers.svg?label=current%20version)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers)
[![PHP version](https://img.shields.io/packagist/php-v/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://php.net)
[![License](https://img.shields.io/github/license/kubawerlos/php-cs-fixer-custom-fixers.svg)](LICENSE)
![Tests](https://img.shields.io/badge/tests-3451-brightgreen.svg)
![Tests](https://img.shields.io/badge/tests-3454-brightgreen.svg)
[![Downloads](https://img.shields.io/packagist/dt/kubawerlos/php-cs-fixer-custom-fixers.svg)](https://packagist.org/packages/kubawerlos/php-cs-fixer-custom-fixers)

[![CI Status](https://github.com/kubawerlos/php-cs-fixer-custom-fixers/workflows/CI/badge.svg?branch=main)](https://github.com/kubawerlos/php-cs-fixer-custom-fixers/actions)
Expand Down
47 changes: 39 additions & 8 deletions src/Fixer/ReadonlyPromotedPropertiesFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,21 @@ public function fix(\SplFileInfo $file, Tokens $tokens): void
continue;
}

$openParenthesis = $tokens->getNextTokenOfKind($constructorAnalysis->getConstructorIndex(), ['(']);
\assert(\is_int($openParenthesis));
$closeParenthesis = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis);

$this->fixParameters($tokens, $openParenthesis, $closeParenthesis);
$classOpenBraceIndex = $tokens->getNextTokenOfKind($index, ['{']);
\assert(\is_int($classOpenBraceIndex));
$classCloseBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpenBraceIndex);

$constructorOpenParenthesisIndex = $tokens->getNextTokenOfKind($constructorAnalysis->getConstructorIndex(), ['(']);
\assert(\is_int($constructorOpenParenthesisIndex));
$constructorCloseParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $constructorOpenParenthesisIndex);

$this->fixParameters(
$tokens,
$classOpenBraceIndex,
$classCloseBraceIndex,
$constructorOpenParenthesisIndex,
$constructorCloseParenthesisIndex,
);
}
}

Expand All @@ -101,9 +111,14 @@ private function isClassReadonly(Tokens $tokens, int $index): bool
return $tokens[$index]->isGivenKind(\T_READONLY);
}

private function fixParameters(Tokens $tokens, int $openParenthesis, int $closeParenthesis): void
{
for ($index = $closeParenthesis; $index > $openParenthesis; $index--) {
private function fixParameters(
Tokens $tokens,
int $classOpenBraceIndex,
int $classCloseBraceIndex,
int $constructorOpenParenthesisIndex,
int $constructorCloseParenthesisIndex
): void {
for ($index = $constructorCloseParenthesisIndex; $index > $constructorOpenParenthesisIndex; $index--) {
if (
!$tokens[$index]->isGivenKind([
CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE,
Expand All @@ -124,6 +139,22 @@ private function fixParameters(Tokens $tokens, int $openParenthesis, int $closeP
continue;
}

$propertyIndex = $tokens->getNextTokenOfKind($index, [[\T_VARIABLE]]);
\assert(\is_int($propertyIndex));

$propertyAssignment = $tokens->findSequence(
[
[\T_VARIABLE, '$this'],
[\T_OBJECT_OPERATOR],
[\T_STRING, \substr($tokens[$propertyIndex]->getContent(), 1)],
],
$classOpenBraceIndex,
$classCloseBraceIndex,
);
if ($propertyAssignment !== null) {
continue;
}

$tokens->insertAt(
$index + 1,
[
Expand Down
29 changes: 29 additions & 0 deletions tests/Fixer/ReadonlyPromotedPropertiesFixerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,35 @@ class Bar { public function notConstruct(int $x) {} }
class Baz { public function __construct(public int $x) {} }
',
];

yield [
'<?php class Foo {
public function __construct(public int $x) {}
public function doSomething() { $this->x = 42; }
}',
];

yield [
'<?php class Foo {
public function __construct(public readonly int $x) {}
public function doSomething() { $object->x = 42; }
}',
'<?php class Foo {
public function __construct(public int $x) {}
public function doSomething() { $object->x = 42; }
}',
];

yield [
'<?php class Foo {
public function __construct(public int $x, public readonly int $y, public int $z) {}
public function doSomething() { $this->x = 42; $this->z = 10; }
}',
'<?php class Foo {
public function __construct(public int $x, public int $y, public int $z) {}
public function doSomething() { $this->x = 42; $this->z = 10; }
}',
];
}

/**
Expand Down

0 comments on commit d3f2590

Please sign in to comment.