Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UseTransformer - Trait import in enum fix (PHP8.1) #6181

Merged
merged 1 commit into from Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/Tokenizer/Transformer/UseTransformer.php
Expand Up @@ -61,11 +61,17 @@ public function process(Tokens $tokens, Token $token, int $index): void
// Only search inside class/trait body for `T_USE` for traits.
// Cannot import traits inside interfaces or anywhere else

if (!$token->isGivenKind([T_CLASS, T_TRAIT])) {
return;
$classTypes = [T_TRAIT];

if (\defined('T_ENUM')) { // @TODO: drop condition when PHP 8.1+ is required
$classTypes[] = T_ENUM;
}

if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_DOUBLE_COLON)) {
if ($token->isGivenKind(T_CLASS)) {
if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_DOUBLE_COLON)) {
return;
}
} elseif (!$token->isGivenKind($classTypes)) {
return;
}

Expand Down
23 changes: 23 additions & 0 deletions tests/Fixer/Import/NoUnusedImportsFixerTest.php
Expand Up @@ -1482,4 +1482,27 @@ function test2($param = (new Foo6)) {}
',
];
}

/**
* @requires PHP 8.1
* @dataProvider provideFixPhp81Cases
*/
public function testFixPhp81(string $expected): void
{
$this->doTest($expected);
}

public function provideFixPhp81Cases(): iterable
{
yield [
'<?php
enum Foo: string
{
use Bar;

case Test1 = "a";
}
',
];
}
}
160 changes: 96 additions & 64 deletions tests/Tokenizer/Transformer/UseTransformerTest.php
Expand Up @@ -44,98 +44,130 @@ public function testProcess(string $source, array $expectedTokens = []): void
);
}

public function provideProcessCases(): array
public function provideProcessCases(): iterable
{
return [
yield [
'<?php use Foo;',
[
'<?php use Foo;',
[
1 => T_USE,
],
1 => T_USE,
],
];

yield [
'<?php $foo = function() use ($bar) {};',
[
'<?php $foo = function() use ($bar) {};',
[
9 => CT::T_USE_LAMBDA,
],
9 => CT::T_USE_LAMBDA,
],
];

yield [
'<?php class Foo { use Bar; }',
[
'<?php class Foo { use Bar; }',
[
7 => CT::T_USE_TRAIT,
],
7 => CT::T_USE_TRAIT,
],
];

yield [
'<?php namespace Aaa; use Bbb; class Foo { use Bar; function baz() { $a=1; return function () use ($a) {}; } }',
[
'<?php namespace Aaa; use Bbb; class Foo { use Bar; function baz() { $a=1; return function () use ($a) {}; } }',
[
6 => T_USE,
17 => CT::T_USE_TRAIT,
42 => CT::T_USE_LAMBDA,
],
6 => T_USE,
17 => CT::T_USE_TRAIT,
42 => CT::T_USE_LAMBDA,
],
];

yield [
'<?php
namespace A {
class Foo {}
echo Foo::class;
}

namespace B {
use \stdClass;

echo 123;
}',
[
'<?php
namespace A {
class Foo {}
echo Foo::class;
}

namespace B {
use \stdClass;

echo 123;
}',
[
30 => T_USE,
],
30 => T_USE,
],
];

yield [
'<?php use Foo; $a = Bar::class;',
[
'<?php use Foo; $a = Bar::class;',
[
1 => T_USE,
],
1 => T_USE,
],
'nested anonymous classes' => [
'<?php
];

yield 'nested anonymous classes' => [
'<?php

namespace SomeWhereOverTheRainbow;

trait Foo {
public function test()
{
$a = time();
return function() use ($a) { echo $a; };
}
public function test()
{
$a = time();
return function() use ($a) { echo $a; };
}
};

$a = new class(
new class() {
use Foo;
}
new class() {
use Foo;
}
) {
public function __construct($bar)
{
$a = $bar->test();
$a();
}
public function __construct($bar)
{
$a = $bar->test();
$a();
}
};
',
[
38 => CT::T_USE_LAMBDA,
76 => CT::T_USE_TRAIT,
],
],
[
'<?php
38 => CT::T_USE_LAMBDA,
76 => CT::T_USE_TRAIT,
],
];

yield [
'<?php
use A\{B,};
use function D;
use C\{D,E,};
',
[
1 => T_USE,
11 => T_USE,
18 => T_USE,
],
[
1 => T_USE,
11 => T_USE,
18 => T_USE,
],
];
}

/**
* @param array<int, int> $expectedTokens index => kind
*
* @requires PHP 8.1
* @dataProvider provideProcessPhp81Cases
*/
public function testProcessPhp81(string $source, array $expectedTokens = []): void
{
$this->doTest($source, $expectedTokens, [CT::T_USE_TRAIT]);
}

public function provideProcessPhp81Cases(): iterable
{
yield [
'<?php enum Foo: string
{
use Bar;

case Test1 = "a";
}
',
[
10 => CT::T_USE_TRAIT,
],
];
}
Expand Down