Skip to content

Commit

Permalink
Only chek if error starts with a text to avoid issues when the last p…
Browse files Browse the repository at this point in the history
…art change based on cakephp version.
  • Loading branch information
rochamarcelo committed Oct 15, 2024
1 parent 54c2a17 commit 83b3879
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 16 deletions.
86 changes: 86 additions & 0 deletions src/Constraint/ArrayOfStringStartsWith.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
declare(strict_types=1);

namespace CakeDC\PHPStan\Constraint;

use PHPUnit\Framework\Constraint\Constraint;

class ArrayOfStringStartsWith extends Constraint
{
/**
* @var array<string>
*/
private readonly array $actual;
/**
* @var array<array{expected: string, type: string, actual: string|null}>
*/
private array $result = [];
/**
* @var array<string>
*/
private array $notExpected = [];

/**
* @param array<string> $actual
*/
public function __construct(array $actual)
{
$this->actual = $actual;
}

/**
* @return string
*/
public function toString(): string
{
return 'a list of errors';
}

/**
* @param mixed $other
* @return bool
*/
protected function matches(mixed $other): bool
{
$result = true;
$this->notExpected = $this->actual;
assert(is_array($other));
foreach ($other as $key => $error) {
if (!isset($this->actual[$key])) {
$this->result[$key] = ['expected' => $error, 'type' => 'missing', 'actual' => null];
$result = false;
continue;
}
unset($this->notExpected[$key]);
if (!str_starts_with($this->actual[$key], $error)) {
$this->result[$key] = ['expected' => $error, 'type' => 'not-equal', 'actual' => $this->actual[$key]];
$result = false;
}
}

return $result && empty($this->notExpected);
}

/**
* @param mixed $other
* @return string
*/
protected function failureDescription(mixed $other): string
{
$text = "\n";
foreach ($this->result as $item) {
if ($item['type'] === 'not-equal') {
$text .= sprintf(" -%s \n +%s \n", $item['expected'], $item['actual']);
}
if ($item['type'] === 'missing') {
$text .= sprintf(" -%s \n", $item['expected']);
}
}

foreach ($this->notExpected as $item) {
$text .= sprintf(" \n +%s", $item);
}

return $text;
}
}
39 changes: 39 additions & 0 deletions src/Rule/Traits/AnalyseCheckLineStartsWithTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);

namespace CakeDC\PHPStan\Rule\Traits;

use CakeDC\PHPStan\Constraint\ArrayOfStringStartsWith;
use PHPStan\Analyser\Error;

/**
* @mixin \PHPStan\Testing\RuleTestCase;
*/
trait AnalyseCheckLineStartsWithTrait
{
/**
* @param array $files
* @param array $expected
* @return void
*/
public function analyseCheckLineStartsWith(array $files, array $expected): void
{
$actualErrors = $this->gatherAnalyserErrors($files);
$messageText = static function (int $line, string $message): string {
return sprintf('%02d: %s', $line, $message);
};
$actualErrors = array_map(static function (Error $error) use ($messageText): string {
$line = $error->getLine();
if ($line === null) {
return $messageText(-1, $error->getMessage());
}

return $messageText($line, $error->getMessage());
}, $actualErrors);

$expected = array_map(static function (array $item) use ($messageText): string {
return $messageText($item[1], $item[0]);
}, $expected);
$this->assertThat($expected, new ArrayOfStringStartsWith($actualErrors));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@

namespace CakeDC\PHPStan\Test\TestCase\Rule\Model;

use Cake\Core\Configure;
use CakeDC\PHPStan\Rule\Model\AddAssociationMatchOptionsTypesRule;
use CakeDC\PHPStan\Rule\Traits\AnalyseCheckLineStartsWithTrait;
use PHPStan\Rules\Properties\PropertyReflectionFinder;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Testing\RuleTestCase;

class AddAssociationMatchOptionsTypesRuleTest extends RuleTestCase
{
use AnalyseCheckLineStartsWithTrait;

/**
* @return \PHPStan\Rules\Rule
*/
Expand All @@ -38,14 +40,7 @@ protected function getRule(): Rule
*/
public function testRule(): void
{
$messageThrough = 'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsToMany with option "through" (Cake\ORM\Table|string|null) does not accept stdClass.';
if (version_compare(Configure::version(), '5.0.5', '<')) {
$messageThrough = 'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsToMany with option "through" (Cake\ORM\Table|string) does not accept stdClass.';
}
// first argument: path to the example file that contains some errors that should be reported by MyRule
// second argument: an array of expected errors,
// each error consists of the asserted error message, and the asserted error file line
$this->analyse([__DIR__ . '/Fake/FailingRuleItemsTable.php'], [
$this->analyseCheckLineStartsWith([__DIR__ . '/Fake/FailingRuleItemsTable.php'], [
[
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "className" (string) does not accept false.',
66,
Expand All @@ -67,12 +62,12 @@ public function testRule(): void
66,
],
[
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "bindingKey" (list<string>|string) does not accept 10.',
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "bindingKey" ',
66,
'Type #1 from the union: 10 is not a list.',
],
[
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "foreignKey" (list<string>|string|false) does not accept 11.',
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsTo with option "foreignKey" ',
66,
'Type #1 from the union: 11 is not a list.',
],
Expand Down Expand Up @@ -114,7 +109,7 @@ public function testRule(): void
'Type #1 from the union: Closure(): 10 is not a list.',
],
[
$messageThrough,
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::belongsToMany with option "through"',
98,
],
[
Expand Down Expand Up @@ -150,12 +145,12 @@ public function testRule(): void
120,
],
[
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "bindingKey" (list<string>|string) does not accept 10.',
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "bindingKey" ',
120,
'Type #1 from the union: 10 is not a list.',
],
[
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "foreignKey" (list<string>|string|false) does not accept 11.',
'Call to CakeDC\PHPStan\Test\TestCase\Rule\Model\Fake\FailingRuleItemsTable::hasOne with option "foreignKey" ',
120,
'Type #1 from the union: 11 is not a list.',
],
Expand Down Expand Up @@ -220,12 +215,12 @@ public function testRule(): void
148,
],
[
'Call to Cake\ORM\AssociationCollection::load with option "bindingKey" (list<string>|string) does not accept 10.',
'Call to Cake\ORM\AssociationCollection::load with option "bindingKey" ',
148,
'Type #1 from the union: 10 is not a list.',
],
[
'Call to Cake\ORM\AssociationCollection::load with option "foreignKey" (list<string>|string|false) does not accept 11.',
'Call to Cake\ORM\AssociationCollection::load with option "foreignKey" ',
148,
'Type #1 from the union: 11 is not a list.',
],
Expand Down

0 comments on commit 83b3879

Please sign in to comment.