Skip to content

Commit

Permalink
[PHP 8.0] Add Stringable
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Apr 24, 2020
1 parent b1143d5 commit c622589
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 1 deletion.
1 change: 1 addition & 0 deletions config/set/php/php80.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ services:
Rector\Php80\Rector\NotIdentical\StrContainsRector: null
Rector\Php80\Rector\Identical\StrStartsWithRector: null
Rector\Php80\Rector\Identical\StrEndsWithRector: null
Rector\Php80\Rector\Class_\StringableForToStringRector: null
23 changes: 22 additions & 1 deletion docs/AllRectorsOverview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# All 501 Rectors Overview
# All 502 Rectors Overview

- [Projects](#projects)
- [General](#general)
Expand Down Expand Up @@ -7915,6 +7915,27 @@ Change helper functions to str_starts_with()

<br>

### `StringableForToStringRector`

- class: [`Rector\Php80\Rector\Class_\StringableForToStringRector`](/../master/rules/php80/src/Rector/Class_/StringableForToStringRector.php)
- [test fixtures](/../master/rules/php80/tests/Rector/Class_/StringableForToStringRector/Fixture)

Add `Stringable` interface to classes with `__toString()` method

```diff
-class SomeClass
+class SomeClass implements Stringable
{
- public function __toString()
+ public function __toString(): string
{
return 'I can stringz';
}
}
```

<br>

### `UnionTypesRector`

- class: [`Rector\Php80\Rector\FunctionLike\UnionTypesRector`](/../master/rules/php80/src/Rector/FunctionLike/UnionTypesRector.php)
Expand Down
99 changes: 99 additions & 0 deletions rules/php80/src/Rector/Class_/StringableForToStringRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);

namespace Rector\Php80\Rector\Class_;

use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;

/**
* @see https://wiki.php.net/rfc/stringable
*
* @see \Rector\Php80\Tests\Rector\Class_\StringableForToStringRector\StringableForToStringRectorTest
*/
final class StringableForToStringRector extends AbstractRector
{
/**
* @var string
*/
private const STRINGABLE = 'Stringable';

/**
* @var ClassManipulator
*/
private $classManipulator;

public function __construct(ClassManipulator $classManipulator)
{
$this->classManipulator = $classManipulator;
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add `Stringable` interface to classes with `__toString()` method', [
new CodeSample(
<<<'PHP'
class SomeClass
{
public function __toString()
{
return 'I can stringz';
}
}
PHP
,
<<<'PHP'
class SomeClass implements Stringable
{
public function __toString(): string
{
return 'I can stringz';
}
}
PHP

),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
$toStringClassMethod = $node->getMethod('__toString');
if ($toStringClassMethod === null) {
return null;
}

if ($this->classManipulator->hasInterface($node, self::STRINGABLE)) {
return null;
}

// add interface
$node->implements[] = new FullyQualified(self::STRINGABLE);

// add return type

if ($toStringClassMethod->returnType === null) {
$toStringClassMethod->returnType = new Name('string');
}

return $node;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Rector\Php80\Tests\Rector\Class_\StringableForToStringRector\Fixture;

class SomeClass
{
public function __toString()
{
return 'I can stringz';
}
}

?>
-----
<?php

namespace Rector\Php80\Tests\Rector\Class_\StringableForToStringRector\Fixture;

class SomeClass implements \Stringable
{
public function __toString(): string
{
return 'I can stringz';
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Rector\Php80\Tests\Rector\Class_\StringableForToStringRector;

use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Php80\Rector\Class_\StringableForToStringRector;

final class StringableForToStringRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}

public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

protected function getRectorClass(): string
{
return StringableForToStringRector::class;
}
}

0 comments on commit c622589

Please sign in to comment.