Skip to content
Permalink
Browse files

OperatorLinebreakFixer - fix for reference (#156)

  • Loading branch information...
kubawerlos committed Oct 20, 2019
1 parent 2d5fad7 commit 38f15e94da750c1d7211297089ee90c371c426de
@@ -8,7 +8,7 @@

[![Build status](https://img.shields.io/travis/kubawerlos/php-cs-fixer-custom-fixers/master.svg)](https://travis-ci.org/kubawerlos/php-cs-fixer-custom-fixers)
[![Code coverage](https://img.shields.io/coveralls/github/kubawerlos/php-cs-fixer-custom-fixers/master.svg)](https://coveralls.io/github/kubawerlos/php-cs-fixer-custom-fixers?branch=master)
![Tests](https://img.shields.io/badge/tests-1299-brightgreen.svg)
![Tests](https://img.shields.io/badge/tests-1348-brightgreen.svg)
[![Mutation testing badge](https://badge.stryker-mutator.io/github.com/kubawerlos/php-cs-fixer-custom-fixers/master)](https://stryker-mutator.github.io)
[![Psalm type coverage](https://shepherd.dev/github/kubawerlos/php-cs-fixer-custom-fixers/coverage.svg)](https://shepherd.dev/github/kubawerlos/php-cs-fixer-custom-fixers)

@@ -0,0 +1,37 @@
<?php
declare(strict_types = 1);
namespace PhpCsFixerCustomFixers\Analyzer;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Tokens;
/**
* @internal
*/
final class ReferenceAnalyzer
{
public function isReference(Tokens $tokens, int $index): bool
{
if ($tokens[$index]->isGivenKind(CT::T_RETURN_REF)) {
return true;
}
if (!$tokens[$index]->equals('&')) {
return false;
}
/** @var int $index */
$index = $tokens->getPrevMeaningfulToken($index);
if ($tokens[$index]->equalsAny(['=', [T_AS], [T_CALLABLE], [T_DOUBLE_ARROW], [CT::T_ARRAY_TYPEHINT]])) {
return true;
}
if ($tokens[$index]->isGivenKind(T_STRING)) {
$index = $tokens->getPrevMeaningfulToken($index);
}
return $tokens[$index]->equalsAny(['(', ',', [T_NS_SEPARATOR], [CT::T_NULLABLE_TYPE]]);
}
}
@@ -14,6 +14,7 @@
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixerCustomFixers\Analyzer\Analysis\CaseAnalysis;
use PhpCsFixerCustomFixers\Analyzer\ReferenceAnalyzer;
use PhpCsFixerCustomFixers\Analyzer\SwitchAnalyzer;
final class OperatorLinebreakFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, DeprecatingFixerInterface
@@ -128,6 +129,8 @@ public function getPullRequestId(): int
public function fix(\SplFileInfo $file, Tokens $tokens): void
{
$referenceAnalyzer = new ReferenceAnalyzer();
$excludedIndices = $this->getExcludedIndices($tokens);
$index = $tokens->count();
@@ -138,6 +141,10 @@ public function fix(\SplFileInfo $file, Tokens $tokens): void
continue;
}
if ($referenceAnalyzer->isReference($tokens, $index)) {
continue;
}
if (\in_array($index, $excludedIndices, true)) {
continue;
}
@@ -0,0 +1,115 @@
<?php
declare(strict_types = 1);
namespace Tests\Analyzer;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixerCustomFixers\Analyzer\ReferenceAnalyzer;
use PHPUnit\Framework\TestCase;
/**
* @internal
*
* @covers \PhpCsFixerCustomFixers\Analyzer\ReferenceAnalyzer
*/
final class ReferenceAnalyzerTest extends TestCase
{
public function testNonAmpersand(): void
{
$analyzer = new ReferenceAnalyzer();
static::assertFalse($analyzer->isReference(Tokens::fromCode('<?php $foo;$bar;$baz;'), 3));
}
public function testReferenceAndNonReferenceTogether(): void
{
$analyzer = new ReferenceAnalyzer();
$tokens = Tokens::fromCode('<?php function foo(&$bar = BAZ & QUX) {};');
static::assertTrue($analyzer->isReference($tokens, 5));
static::assertFalse($analyzer->isReference($tokens, 12));
}
/**
* @dataProvider provideReferenceCases
*/
public function testReference(string $code): void
{
$this->doTestCode(true, $code);
}
/**
* @dataProvider provideNonReferenceCases
*/
public function testNonReference(string $code): void
{
$this->doTestCode(false, $code);
}
public function provideReferenceCases(): iterable
{
yield ['<?php $foo =& $bar;'];
yield ['<?php $foo =& find_var($bar);'];
yield ['<?php $foo["bar"] =& $baz;'];
yield ['<?php function foo(&$bar) {};'];
yield ['<?php function foo($bar, &$baz) {};'];
yield ['<?php function &() {};'];
yield ['<?php
class Foo {
public $value = 42;
public function &getValue() {
return $this->value;
}
}'];
yield ['<?php function foo(\Bar\Baz &$qux) {};'];
yield ['<?php function foo(array &$bar) {};'];
yield ['<?php function foo(callable &$bar) {};'];
yield ['<?php function foo(int &$bar) {};'];
yield ['<?php function foo(string &$bar) {};'];
yield ['<?php function foo(?int &$bar) {};'];
yield ['<?php foreach($foos as &$foo) {}'];
yield ['<?php foreach($foos as $key => &$foo) {}'];
}
public function provideNonReferenceCases(): iterable
{
yield ['<?php $foo & $bar;'];
yield ['<?php FOO & $bar;'];
yield ['<?php Foo::BAR & $baz;'];
yield ['<?php foo(1, 2) & $bar;'];
yield ['<?php foo($bar & $baz);'];
yield ['<?php foo($bar, $baz & $qux);'];
yield ['<?php foo($bar->baz & $qux);'];
yield ['<?php foo(Bar::BAZ & $qux);'];
yield ['<?php foo(Bar\Baz::qux & $quux);'];
yield ['<?php foo(\Bar\Baz::qux & $quux);'];
yield ['<?php foo($bar["mode"] & $baz);'];
yield ['<?php foo($bar{"mode"} & $baz);'];
yield ['<?php foo(0b11111111 & $bar);'];
yield ['<?php foo(127 & $bar);'];
yield ['<?php foo("bar" & $baz);'];
yield ['<?php foo($bar = BAZ & $qux);'];
yield ['<?php function foo($bar = BAZ & QUX) {};'];
yield ['<?php function foo($bar = BAZ::QUX & QUUX) {};'];
yield ['<?php function foo(array $bar = BAZ & QUX) {};'];
yield ['<?php function foo(callable $bar = BAZ & QUX) {};'];
yield ['<?php function foo(?int $bar = BAZ & QUX) {};'];
yield ['<?php foreach($foos as $foo) { $foo & $bar; }'];
yield ['<?php if ($foo instanceof Bar & 0b01010101) {}'];
}
private function doTestCode(bool $expected, string $code): void
{
$analyzer = new ReferenceAnalyzer();
$tokens = Tokens::fromCode($code);
foreach ($tokens as $index => $token) {
if ($token->getContent() === '&') {
static::assertSame($expected, $analyzer->isReference($tokens, $index));
}
}
}
}
@@ -161,6 +161,35 @@ function foo()
bool
{};',
];
yield 'assign by reference' => [
'<?php
$a
= $b;
$c =&
$d;
',
'<?php
$a =
$b;
$c =&
$d;
',
];
yield 'passing by reference' => [
'<?php
function foo(
&$a,
&$b,
int
&$c,
\Bar\Baz
&$d
) {};',
null,
['position' => 'end'],
];
}
private function pairs(): iterable
@@ -438,6 +467,17 @@ function () {
'<?php
[$foo =>
$bar];
',
];
yield 'handle & operator with constant' => [
'<?php
\Foo::bar
& $baz;
',
'<?php
\Foo::bar &
$baz;
',
];
}

0 comments on commit 38f15e9

Please sign in to comment.
You can’t perform that action at this time.