duster icon indicating copy to clipboard operation
duster copied to clipboard

`CustomPhpUnitOrderFixer.php` incompatible with PHP-CS-Fixer >= v.3.77.0

Open johnbacon opened this issue 7 months ago • 2 comments

We're piggybacking on Tighten's ruleset in our PHP-CS-Fixer config:

<?php

// Adopt Laravel and PHP-CS-Fixer defaults from Tighten's ruleset.
$tightenConfig = require 'vendor/tightenco/duster/standards/.php-cs-fixer.dist.php';

$finder = PhpCsFixer\Finder::create()
	->in(__DIR__ . '/app')
	->in(__DIR__ . '/config')
	->in(__DIR__ . '/database')
	->in(__DIR__ . '/resources')
	->in(__DIR__ . '/routes')
	->in(__DIR__ . '/tests')
    ->notName([
		'_ide_helper*',
		'.phpstorm.meta.php',
	])
;

// We can now extend or modify the $config if we wish, or simply return it.
// Note that other PHP-CS-Fixer rules are being set and run via Stout and PHP Insights.
$config = (new PhpCsFixer\Config())
    ->registerCustomFixers($tightenConfig->getCustomFixers())
	->setRules(array_merge(
		$tightenConfig->getRules(),
		[
			'Tighten/custom_ordered_class_elements' => false, // Disable Tighten's ordering and set our own in stout.json
		]
	))
    ->setFinder($finder)
    ->setRiskyAllowed($tightenConfig->getRiskyAllowed())
	->setUsingCache(true)
	->setCacheFile(__DIR__ . '/storage/cache/.php-cs-fixer.cache');

return $config;

Unfortunately, in PHP-CS-Fixer v.3.77.0, PhpUnitTestCaseIndicator was moved from PhpCsFixer\Indicator\PhpUnitTestCaseIndicator to PhpCsFixer\Tokenizer\Analyzer\PhpUnitTestCaseAnalyzer (see here).

However, Duster's CustomPhpUnitOrderFixer.php is still using the old path: https://github.com/tighten/duster/blob/86894caf68c449b7f83c753da7da6ff1dbee0f83/app/Fixer/ClassNotation/CustomPhpUnitOrderFixer.php#L7C26-L7C50

This isn't really an issue with Duster, which still works (until updating PHP-CS-Fixer), but it does cause an issue with our integration. 😅

Updating Duster to the latest PHP-CS-Fixer would solve our problems. But... I'm also aware that this is due to our unusual use of Duster's rules.

johnbacon avatar Jul 07 '25 19:07 johnbacon

I'm having the same issue with the latest PHP-CS-Fixer (v3.86.0).
Also, PhpUnitTestCaseAnalyzer was marked as @internal, and the isPhpUnitClass() is now private...

As I'm using a fork of Duster to add GD75\DoubleQuoteFixer, I was able to fix it with some reflection magic:


use PhpCsFixer\Tokenizer\Analyzer\PhpUnitTestCaseAnalyzer;


protected function applyFix(SplFileInfo $file, Tokens $tokens): void
{
    $phpUnitTestCaseAnalyzer = new PhpUnitTestCaseAnalyzer();
    $isPhpUnitClass = new ReflectionMethod(PhpUnitTestCaseAnalyzer::class, "isPhpUnitClass");
    for ($index = $tokens->count() - 1; $index > 0; $index--) {
          if ($tokens[$index]->isGivenKind(T_CLASS) && $isPhpUnitClass->invokeArgs($phpUnitTestCaseAnalyzer, [$tokens, $index])) {
              parent::applyFix($file, $tokens);
              break;
          }
      }
}

Dirty but works. The other solution would be to copy/paste the code from PhpUnitTestCaseAnalyzer.

superbiche avatar Aug 27 '25 11:08 superbiche

Woof, sorry we left this sitting so long. Taking a look!

mattstauffer avatar Oct 06 '25 15:10 mattstauffer