Skip to content
Permalink
Browse files

Add DataProviderStaticFixer (#191)

  • Loading branch information
kubawerlos committed Nov 23, 2019
1 parent 6012c1c commit ec894ccebc73f7518241657481f281c7c8e9e66d
Showing with 284 additions and 57 deletions.
  1. +1 −0 CHANGELOG.md
  2. +15 −1 README.md
  3. +1 −1 src/Fixer/DataProviderNameFixer.php
  4. +1 −1 src/Fixer/DataProviderReturnTypeFixer.php
  5. +95 −0 src/Fixer/DataProviderStaticFixer.php
  6. +1 −1 src/Fixer/PhpUnitNoUselessReturnFixer.php
  7. +2 −2 tests/Analyzer/ReferenceAnalyzerTest.php
  8. +1 −1 tests/Analyzer/SwitchAnalyzerTest.php
  9. +2 −2 tests/AutoReview/SrcCodeTest.php
  10. +13 −3 tests/AutoReview/TestsCodeTest.php
  11. +1 −1 tests/Fixer/CommentSurroundedBySpacesFixerTest.php
  12. +1 −1 tests/Fixer/DataProviderNameFixerTest.php
  13. +1 −1 tests/Fixer/DataProviderReturnTypeFixerTest.php
  14. +109 −0 tests/Fixer/DataProviderStaticFixerTest.php
  15. +1 −1 tests/Fixer/ImplodeCallFixerTest.php
  16. +1 −1 tests/Fixer/InternalClassCasingFixerTest.php
  17. +1 −1 tests/Fixer/MultilineCommentOpeningClosingAloneFixerTest.php
  18. +1 −1 tests/Fixer/NoCommentedOutCodeFixerTest.php
  19. +1 −1 tests/Fixer/NoDoctrineMigrationsGeneratedCommentFixerTest.php
  20. +1 −1 tests/Fixer/NoDuplicatedImportsFixerTest.php
  21. +1 −1 tests/Fixer/NoImportFromGlobalNamespaceFixerTest.php
  22. +1 −1 tests/Fixer/NoLeadingSlashInGlobalNamespaceFixerTest.php
  23. +1 −1 tests/Fixer/NoNullableBooleanTypeFixerTest.php
  24. +1 −1 tests/Fixer/NoPhpStormGeneratedCommentFixerTest.php
  25. +1 −1 tests/Fixer/NoReferenceInFunctionDefinitionFixerTest.php
  26. +1 −1 tests/Fixer/NoTwoConsecutiveEmptyLinesFixerTest.php
  27. +1 −1 tests/Fixer/NoUnneededConcatenationFixerTest.php
  28. +1 −1 tests/Fixer/NoUselessClassCommentFixerTest.php
  29. +1 −1 tests/Fixer/NoUselessCommentFixerTest.php
  30. +1 −1 tests/Fixer/NoUselessConstructorCommentFixerTest.php
  31. +1 −1 tests/Fixer/NoUselessDoctrineRepositoryCommentFixerTest.php
  32. +1 −1 tests/Fixer/NoUselessSprintfFixerTest.php
  33. +1 −1 tests/Fixer/NullableParamStyleFixerTest.php
  34. +3 −5 tests/Fixer/OperatorLinebreakFixerTest.php
  35. +3 −3 tests/Fixer/PhpUnitNoUselessReturnFixerTest.php
  36. +1 −1 tests/Fixer/PhpdocNoIncorrectVarAnnotationFixerTest.php
  37. +1 −1 tests/Fixer/PhpdocNoSuperfluousParamFixerTest.php
  38. +1 −1 tests/Fixer/PhpdocOnlyAllowedAnnotationsFixerTest.php
  39. +1 −1 tests/Fixer/PhpdocParamOrderFixerTest.php
  40. +1 −1 tests/Fixer/PhpdocParamTypeFixerTest.php
  41. +1 −1 tests/Fixer/PhpdocSelfAccessorFixerTest.php
  42. +1 −1 tests/Fixer/PhpdocSingleLineVarFixerTest.php
  43. +1 −1 tests/Fixer/PhpdocVarAnnotationCorrectOrderFixerTest.php
  44. +1 −1 tests/Fixer/SingleLineThrowFixerTest.php
  45. +2 −2 tests/Fixer/SingleSpaceAfterStatementFixerTest.php
  46. +1 −1 tests/Fixer/SingleSpaceBeforeStatementFixerTest.php
  47. +1 −1 tests/FixersTest.php
  48. +1 −1 tests/PriorityTest.php
  49. +1 −1 tests/TokenRemoverTest.php
@@ -2,6 +2,7 @@

## [Unreleased]
- Update PHP CS Fixer to v2.16
- Add DataProviderStaticFixer
- Deprecate SingleLineThrowFixer

## v1.16.0 - *2019-10-24*
@@ -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-1480-brightgreen.svg)
![Tests](https://img.shields.io/badge/tests-1548-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)

@@ -76,6 +76,20 @@ Return type of data provider must be `iterable`.
}
```

#### DataProviderStaticFixer
Data provider must be static.
```diff
<?php
class FooTest extends TestCase {
/**
* @dataProvider provideHappyPathCases
*/
public function testHappyPath() {}
- public function provideHappyPathCases() {}
+ public static function provideHappyPathCases() {}
}
```

#### ImplodeCallFixer
Function `implode` must be called with 2 arguments in the documented order.
DEPRECATED: use `implode_call` instead.
@@ -47,7 +47,7 @@ public function getPriority(): int

public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_DOC_COMMENT);
return $tokens->isAllTokenKindsFound([T_CLASS, T_DOC_COMMENT, T_EXTENDS, T_FUNCTION, T_STRING]);
}

public function isRisky(): bool
@@ -49,7 +49,7 @@ public function getPriority(): int

public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_DOC_COMMENT);
return $tokens->isAllTokenKindsFound([T_CLASS, T_DOC_COMMENT, T_EXTENDS, T_FUNCTION, T_STRING]);
}

public function isRisky(): bool
@@ -0,0 +1,95 @@
<?php

declare(strict_types = 1);

namespace PhpCsFixerCustomFixers\Fixer;

use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Indicator\PhpUnitTestCaseIndicator;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixer\Tokenizer\TokensAnalyzer;
use PhpCsFixerCustomFixers\Analyzer\DataProviderAnalyzer;

final class DataProviderStaticFixer extends AbstractFixer
{
/**
* {@inheritdoc}
*/
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Data provider must be static.',
[
new CodeSample(
'<?php
class FooTest extends TestCase {
/**
* @dataProvider provideHappyPathCases
*/
public function testHappyPath() {}
public function provideHappyPathCases() {}
}
'
),
]
);
}

public function getPriority(): int
{
return 0;
}

public function isCandidate(Tokens $tokens): bool
{
return $tokens->isAllTokenKindsFound([T_CLASS, T_DOC_COMMENT, T_EXTENDS, T_FUNCTION, T_STRING]);
}

public function isRisky(): bool
{
return false;
}

public function fix(\SplFileInfo $file, Tokens $tokens): void
{
$phpUnitTestCaseIndicator = new PhpUnitTestCaseIndicator();

/** @var int[] $indices */
foreach ($phpUnitTestCaseIndicator->findPhpUnitClasses($tokens) as $indices) {
$this->fixStatic($tokens, $indices[0], $indices[1]);
}
}

private function fixStatic(Tokens $tokens, int $startIndex, int $endIndex): void
{
$dataProviderAnalyzer = new DataProviderAnalyzer();
$tokensAnalyzer = new TokensAnalyzer($tokens);

foreach (\array_reverse($dataProviderAnalyzer->getDataProviders($tokens, $startIndex, $endIndex)) as $dataProviderAnalysis) {
/** @var int $methodStartIndex */
$methodStartIndex = $tokens->getNextTokenOfKind($dataProviderAnalysis->getNameIndex(), ['{']);

$methodEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $methodStartIndex);

if ($tokens->findSequence([[T_VARIABLE, '$this']], $methodStartIndex, $methodEndIndex) !== null) {
continue;
}

/** @var int $functionIndex */
$functionIndex = $tokens->getPrevTokenOfKind($dataProviderAnalysis->getNameIndex(), [[T_FUNCTION]]);

$methodAttributes = $tokensAnalyzer->getMethodAttributes($functionIndex);
if ($methodAttributes['static'] !== false) {
continue;
}

$tokens->insertAt(
$functionIndex,
[new Token([T_STATIC, 'static']), new Token([T_WHITESPACE, ' '])]
);
}
}
}
@@ -49,7 +49,7 @@ public function getPriority(): int

public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_STRING);
return $tokens->isAllTokenKindsFound([T_CLASS, T_EXTENDS, T_FUNCTION, T_STRING, T_RETURN]);
}

public function isRisky(): bool
@@ -48,7 +48,7 @@ public function testNonReference(string $code): void
$this->doTestCode(false, $code);
}

public function provideReferenceCases(): iterable
public static function provideReferenceCases(): iterable
{
yield ['<?php $foo =& $bar;'];
yield ['<?php $foo =& find_var($bar);'];
@@ -73,7 +73,7 @@ public function &getValue() {
yield ['<?php foreach($foos as $key => &$foo) {}'];
}

public function provideNonReferenceCases(): iterable
public static function provideNonReferenceCases(): iterable
{
yield ['<?php $foo & $bar;'];
yield ['<?php FOO & $bar;'];
@@ -38,7 +38,7 @@ public function testGettingSwitchAnalysis(SwitchAnalysis $expected, string $code
static::assertSame(\serialize($expected), \serialize(($analyzer->getSwitchAnalysis($tokens, $index))));
}

public function provideGettingSwitchAnalysisCases(): iterable
public static function provideGettingSwitchAnalysisCases(): iterable
{
yield 'two cases' => [
new SwitchAnalysis(7, 29, [new CaseAnalysis(12), new CaseAnalysis(22)]),
@@ -72,7 +72,7 @@ public function testDeprecatedFixerHasAnnotation(FixerInterface $fixer): void
);
}

public function provideFixerCases(): iterable
public static function provideFixerCases(): iterable
{
return \array_map(
static function (FixerInterface $fixer): array {
@@ -120,7 +120,7 @@ static function (Token $token): string {
static::assertNotContains('preg_split', $strings, $message);
}

public function provideThereIsNoPregFunctionUsedDirectlyCases(): iterable
public static function provideThereIsNoPregFunctionUsedDirectlyCases(): iterable
{
$finder = Finder::create()
->files()
@@ -38,7 +38,17 @@ public function testDataProviderReturnType(string $dataProviderName, string $cla
static::assertSame('iterable', $reflectionMethod->getReturnType()->getName());
}

public function provideDataProviderCases(): iterable
/**
* @dataProvider provideDataProviderCases
*/
public function testDataProviderIsStatic(string $dataProviderName, string $className): void
{
$reflectionMethod = new \ReflectionMethod($className, $dataProviderName);

static::assertTrue($reflectionMethod->isStatic());
}

public static function provideDataProviderCases(): iterable
{
static $dataProviders;

@@ -57,7 +67,7 @@ public function provideDataProviderCases(): iterable
$className .= '\\' . \str_replace('/', '\\', $file->getRelativePath());
}
$className .= '\\' . $file->getBasename('.php');
foreach ($this->getDataProviderMethodNames($className) as $dataProviderName) {
foreach (static::getDataProviderMethodNames($className) as $dataProviderName) {
$dataProviders[\sprintf('%s::%s', $className, $dataProviderName)] = [$dataProviderName, $className];
}
}
@@ -71,7 +81,7 @@ public function provideDataProviderCases(): iterable
/**
* @return string[]
*/
private function getDataProviderMethodNames(string $className): array
private static function getDataProviderMethodNames(string $className): array
{
$reflection = new \ReflectionClass($className);

@@ -24,7 +24,7 @@ public function testFix(string $expected, ?string $input = null): void
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable
public static function provideFixCases(): iterable
{
yield ['<?php $a; //'];
yield ['<?php $a; ////'];
@@ -24,7 +24,7 @@ public function testFix(string $expected, ?string $input = null): void
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable
public static function provideFixCases(): iterable
{
yield 'data provider correctly named' => [
'<?php
@@ -24,7 +24,7 @@ public function testFix(string $expected, ?string $input = null): void
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable
public static function provideFixCases(): iterable
{
yield 'data provider with iterable return type' => [
'<?php
@@ -0,0 +1,109 @@
<?php

declare(strict_types = 1);

namespace Tests\Fixer;

/**
* @internal
*
* @covers \PhpCsFixerCustomFixers\Fixer\DataProviderStaticFixer
*/
final class DataProviderStaticFixerTest extends AbstractFixerTestCase
{
public function testIsRisky(): void
{
static::assertFalse($this->fixer->isRisky());
}

/**
* @dataProvider provideFixCases
*/
public function testFix(string $expected, ?string $input = null): void
{
$this->doTest($expected, $input);
}

public static function provideFixCases(): iterable
{
yield 'do not fix when containing dynamic calls' => [
'<?php
class FooTest extends TestCase {
/**
* @dataProvider provideFoo1Cases
*/
public function testFoo1() {}
public function provideFoo1Cases() { $this->init(); }
}',
];

yield 'fix single' => [
'<?php
class FooTest extends TestCase {
/**
* @dataProvider provideFooCases
*/
public function testFoo() {}
public static function provideFooCases() { $x->getData(); }
}',
'<?php
class FooTest extends TestCase {
/**
* @dataProvider provideFooCases
*/
public function testFoo() {}
public function provideFooCases() { $x->getData(); }
}',
];

yield 'fix multiple' => [
'<?php
class FooTest extends TestCase {
/** @dataProvider provider1 */
public function testFoo1() {}
/** @dataProvider provider2 */
public function testFoo2() {}
/** @dataProvider provider3 */
public function testFoo13() {}
public static function provider1() {}
public function provider2() { $this->init(); }
public static function provider3() {}
}',
'<?php
class FooTest extends TestCase {
/** @dataProvider provider1 */
public function testFoo1() {}
/** @dataProvider provider2 */
public function testFoo2() {}
/** @dataProvider provider3 */
public function testFoo13() {}
public function provider1() {}
public function provider2() { $this->init(); }
public static function provider3() {}
}',
];

yield 'fix with multilines' => [
'<?php
class FooTest extends TestCase {
/**
* @dataProvider provideFooCases
*/
public function testFoo() {}
public
static function
provideFooCases() { $x->getData(); }
}',
'<?php
class FooTest extends TestCase {
/**
* @dataProvider provideFooCases
*/
public function testFoo() {}
public
function
provideFooCases() { $x->getData(); }
}',
];
}
}
@@ -29,7 +29,7 @@ public function testFix(string $expected, ?string $input = null): void
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable
public static function provideFixCases(): iterable
{
yield ["<?php implode('', [1,2,3]);"];
yield ['<?php implode("", $foo);'];
@@ -24,7 +24,7 @@ public function testFix(string $expected, ?string $input = null): void
$this->doTest($expected, $input);
}

public function provideFixCases(): iterable
public static function provideFixCases(): iterable
{
yield ['<?php class STDCLASS {};'];
yield ['<?php class STDCLASS { use EXCEPTION; };'];

0 comments on commit ec894cc

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