diff --git a/composer.json b/composer.json index ed41b0d..3a0bc82 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,9 @@ "require-dev": { "phpmd/phpmd": "@stable", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "roave/security-advisories": "dev-latest", "squizlabs/php_codesniffer": "^3.6" }, @@ -37,6 +37,9 @@ } }, "scripts": { + "baseline": ["@baseline:phpstan", "@baseline:phpmd"], + "baseline:phpstan": "phpstan --generate-baseline", + "baseline:phpmd": "phpmd src,tests xml phpmd.xml.dist --generate-baseline", "check": ["@check:phpstan", "@check:phpmd", "@check:phpcs"], "check:phpstan": "phpstan analyse", "check:phpmd": "phpmd src,tests text phpmd.xml.dist --suffixes php --exclude /tests/*/data/*", diff --git a/phpmd.baseline.xml b/phpmd.baseline.xml new file mode 100644 index 0000000..6a01256 --- /dev/null +++ b/phpmd.baseline.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index dc5b1aa..ebee1ef 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,46 +1,91 @@ parameters: ignoreErrors: - - message: "#^Call to function method_exists\\(\\) with 'PHPUnit\\\\\\\\Runner\\\\\\\\Version' and 'majorVersionNumber' will always evaluate to true\\.$#" + message: '#^Call to an undefined method PHPUnit\\Framework\\MockObject\\Generator\\Generator\:\:getMock\(\)\.$#' + identifier: method.notFound count: 1 path: src/Constraint/ValueProvider/Compound/InstanceProvider.php - - message: "#^Call to method getMock\\(\\) on an unknown class PHPUnit\\\\Framework\\\\MockObject\\\\Generator\\.$#" - count: 2 + message: '#^Call to function method_exists\(\) with ''PHPUnit\\\\Runner\\\\Version'' and ''majorVersionNumber'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 path: src/Constraint/ValueProvider/Compound/InstanceProvider.php - - message: "#^Call to method testDouble\\(\\) on an unknown class PHPUnit\\\\Framework\\\\MockObject\\\\Generator\\.$#" - count: 2 + message: '#^Call to function method_exists\(\) with PHPUnit\\Framework\\MockObject\\Generator\\Generator and ''testDouble'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 path: src/Constraint/ValueProvider/Compound/InstanceProvider.php - - message: "#^Instantiated class PHPUnit\\\\Framework\\\\MockObject\\\\Generator not found\\.$#" + message: '#^Call to method getMock\(\) on an unknown class PHPUnit\\Framework\\MockObject\\Generator\.$#' + identifier: class.notFound count: 1 path: src/Constraint/ValueProvider/Compound/InstanceProvider.php - - message: "#^PHPDoc tag @var for variable \\$mockGenerator contains unknown class PHPUnit\\\\Framework\\\\MockObject\\\\Generator\\.$#" + message: '#^Instantiated class PHPUnit\\Framework\\MockObject\\Generator not found\.$#' + identifier: class.notFound count: 1 path: src/Constraint/ValueProvider/Compound/InstanceProvider.php - - message: "#^Call to method getMockForAbstractClass\\(\\) on an unknown class PHPUnit\\\\Framework\\\\MockObject\\\\Generator\\.$#" - count: 2 + message: '#^Method DigitalRevolution\\AccessorPairConstraint\\Constraint\\ValueProvider\\Compound\\InstanceProvider\:\:getMockObject\(\) should return object but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Constraint/ValueProvider/Compound/InstanceProvider.php + + - + message: '#^Parameter \#3 \$methods of method PHPUnit\\Framework\\MockObject\\Generator\\Generator\:\:testDouble\(\) expects array\|null, true given\.$#' + identifier: argument.type + count: 1 + path: src/Constraint/ValueProvider/Compound/InstanceProvider.php + + - + message: '#^Parameter \#5 \$mockClassName of method PHPUnit\\Framework\\MockObject\\Generator\\Generator\:\:testDouble\(\) expects string, array given\.$#' + identifier: argument.type + count: 1 + path: src/Constraint/ValueProvider/Compound/InstanceProvider.php + + - + message: '#^Parameter \#6 \$callOriginalConstructor of method PHPUnit\\Framework\\MockObject\\Generator\\Generator\:\:testDouble\(\) expects bool, string given\.$#' + identifier: argument.type + count: 1 + path: src/Constraint/ValueProvider/Compound/InstanceProvider.php + + - + message: '#^Call to an undefined method PHPUnit\\Framework\\MockObject\\Generator\\Generator\:\:getMockForAbstractClass\(\)\.$#' + identifier: method.notFound + count: 1 path: src/Constraint/ValueProvider/Compound/IntersectionProvider.php - - message: "#^Call to method mockObjectForAbstractClass\\(\\) on an unknown class PHPUnit\\\\Framework\\\\MockObject\\\\Generator\\.$#" + message: '#^Call to function method_exists\(\) with PHPUnit\\Framework\\MockObject\\Generator\\Generator and ''mockObjectForAbstra…'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType count: 1 path: src/Constraint/ValueProvider/Compound/IntersectionProvider.php - - message: "#^Instantiated class PHPUnit\\\\Framework\\\\MockObject\\\\Generator not found\\.$#" + message: '#^Call to method getMockForAbstractClass\(\) on an unknown class PHPUnit\\Framework\\MockObject\\Generator\.$#' + identifier: class.notFound count: 1 path: src/Constraint/ValueProvider/Compound/IntersectionProvider.php - - message: "#^PHPDoc tag @var for variable \\$mockGenerator contains unknown class PHPUnit\\\\Framework\\\\MockObject\\\\Generator\\.$#" + message: '#^Instantiated class PHPUnit\\Framework\\MockObject\\Generator not found\.$#' + identifier: class.notFound count: 1 path: src/Constraint/ValueProvider/Compound/IntersectionProvider.php + + - + message: '#^Call to function array_filter\(\) requires parameter \#2 to be passed to avoid loose comparison semantics\.$#' + identifier: arrayFilter.strict + count: 1 + path: src/Constraint/ValueProvider/Pseudo/NonEmptyValueProvider.php + + - + message: '#^Parameter \#1 \$typehint of class DigitalRevolution\\AccessorPairConstraint\\Constraint\\ValueProvider\\Compound\\InstanceProvider constructor expects class\-string, string given\.$#' + identifier: argument.type + count: 1 + path: tests/Unit/Constraint/ValueProvider/Compound/InstanceProviderTest.php diff --git a/phpstan.neon b/phpstan.neon index 5ae13e4..3a48cd0 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -17,3 +17,7 @@ parameters: html-escaped-string: 'string' lowercase-string: 'string' non-empty-string: 'string' + + ignoreErrors: + - + identifier: phpunit.coversMethod diff --git a/src/Constraint/ConstraintConfig.php b/src/Constraint/ConstraintConfig.php index 5663db4..da30426 100644 --- a/src/Constraint/ConstraintConfig.php +++ b/src/Constraint/ConstraintConfig.php @@ -113,6 +113,9 @@ public function setExcludedMethods(array $excludedMethods): self return $this; } + /** + * @return callable(): mixed[]|null + */ public function getConstructorCallback(): ?callable { return $this->constructorCallback; diff --git a/src/Constraint/ValueProvider/Compound/ArrayProvider.php b/src/Constraint/ValueProvider/Compound/ArrayProvider.php index af9ecae..6e28ef5 100644 --- a/src/Constraint/ValueProvider/Compound/ArrayProvider.php +++ b/src/Constraint/ValueProvider/Compound/ArrayProvider.php @@ -25,7 +25,7 @@ public function getValues(): array { $keys = []; if ($this->keyProvider !== null) { - $keys = array_filter($this->keyProvider->getValues()); + $keys = array_filter($this->keyProvider->getValues(), static fn($key): bool => $key !== ''); } $testArray = []; @@ -38,7 +38,7 @@ public function getValues(): array } /** - * @return array + * @return mixed[] * @throws Exception */ protected function getArrayValues(): array diff --git a/src/Constraint/ValueProvider/Compound/InstanceProvider.php b/src/Constraint/ValueProvider/Compound/InstanceProvider.php index b03a452..551f653 100644 --- a/src/Constraint/ValueProvider/Compound/InstanceProvider.php +++ b/src/Constraint/ValueProvider/Compound/InstanceProvider.php @@ -14,9 +14,12 @@ class InstanceProvider implements ValueProvider { - /** @var string */ + /** @var class-string */ protected $typehint; + /** + * @param class-string $typehint + */ public function __construct(string $typehint) { $this->typehint = ltrim($typehint, '\\'); @@ -32,7 +35,7 @@ public function __construct(string $typehint) public function getValues(): array { if (enum_exists($this->typehint)) { - /** @var UnitEnum $enum */ + /** @var class-string $enum */ $enum = $this->typehint; return $enum::cases(); @@ -49,7 +52,6 @@ public function getValues(): array private function getMockObject(string $typehint): object { if (class_exists('PHPUnit\Framework\MockObject\Generator\Generator')) { - /** @var \PHPUnit\Framework\MockObject\Generator $mockGenerator */ $mockGenerator = new Generator(); if (method_exists($mockGenerator, 'testDouble')) { if (method_exists(Version::class, 'majorVersionNumber') && Version::majorVersionNumber() >= 11) { diff --git a/src/Constraint/ValueProvider/Compound/IntersectionProvider.php b/src/Constraint/ValueProvider/Compound/IntersectionProvider.php index fc70a52..07dd24a 100644 --- a/src/Constraint/ValueProvider/Compound/IntersectionProvider.php +++ b/src/Constraint/ValueProvider/Compound/IntersectionProvider.php @@ -7,9 +7,6 @@ use phpDocumentor\Reflection\Type; use PHPUnit\Framework\MockObject\Generator\Generator; -/** - * @SuppressWarnings(PHPMD.EvalExpression) - */ class IntersectionProvider implements ValueProvider { /** @var Type[] */ @@ -57,7 +54,6 @@ public function getValues(): array } if (class_exists('PHPUnit\Framework\MockObject\Generator\Generator')) { - /** @var \PHPUnit\Framework\MockObject\Generator $mockGenerator */ $mockGenerator = new Generator(); if (method_exists($mockGenerator, 'mockObjectForAbstractClass')) { $instance = $mockGenerator->mockObjectForAbstractClass($className, [], '', false, false); diff --git a/src/Constraint/ValueProvider/NativeValueProviderFactory.php b/src/Constraint/ValueProvider/NativeValueProviderFactory.php index 2165b00..8586904 100644 --- a/src/Constraint/ValueProvider/NativeValueProviderFactory.php +++ b/src/Constraint/ValueProvider/NativeValueProviderFactory.php @@ -34,9 +34,6 @@ use phpDocumentor\Reflection\PseudoTypes\True_; use ReflectionMethod; -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ class NativeValueProviderFactory { private ValueProviderFactory $valueProviderFactory; diff --git a/src/Constraint/ValueProvider/PseudoValueProviderFactory.php b/src/Constraint/ValueProvider/PseudoValueProviderFactory.php index c059151..26e97c8 100644 --- a/src/Constraint/ValueProvider/PseudoValueProviderFactory.php +++ b/src/Constraint/ValueProvider/PseudoValueProviderFactory.php @@ -41,9 +41,6 @@ use phpDocumentor\Reflection\Types\ClassString; use ReflectionMethod; -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ class PseudoValueProviderFactory { private ValueProviderFactory $valueProviderFactory; @@ -80,16 +77,13 @@ public function getProvider(Type $typehint, ?ReflectionMethod $method = null): ? return $this->getPseudoStringProvider($typehint); } - /** - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ protected function getPseudoStringProvider(Type $typehint): ?ValueProvider { switch (get_class($typehint)) { case ClassString::class: $fqsen = null; if ($typehint->getFqsen() !== null) { - /** @var class-string|null $fqsen */ + /** @var class-string $fqsen */ $fqsen = (string)$typehint->getFqsen(); } diff --git a/src/Constraint/ValueProvider/Special/ResourceProvider.php b/src/Constraint/ValueProvider/Special/ResourceProvider.php index e5cb4f1..b750117 100644 --- a/src/Constraint/ValueProvider/Special/ResourceProvider.php +++ b/src/Constraint/ValueProvider/Special/ResourceProvider.php @@ -10,7 +10,6 @@ class ResourceProvider implements ValueProvider { /** * @return resource[] - * @throws Exception */ public function getValues(): array { diff --git a/src/Constraint/ValueProvider/ValueProviderFactory.php b/src/Constraint/ValueProvider/ValueProviderFactory.php index 54c4596..1bd37c9 100644 --- a/src/Constraint/ValueProvider/ValueProviderFactory.php +++ b/src/Constraint/ValueProvider/ValueProviderFactory.php @@ -15,9 +15,6 @@ use phpDocumentor\Reflection\Types\Object_; use ReflectionMethod; -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ class ValueProviderFactory { private NativeValueProviderFactory $nativeProviderFactory; @@ -53,7 +50,10 @@ public function getProvider(Type $typehint, ?ReflectionMethod $method = null): V // Support for fully namespaced class name if (($typehint instanceof Object_ || $typehint instanceof Collection) && $typehint->getFqsen() !== null) { - return new InstanceProvider((string)$typehint->getFqsen()); + /** @var class-string $fqsen */ + $fqsen = (string)$typehint->getFqsen(); + + return new InstanceProvider($fqsen); } // Check if the provider typehint is a PHP scalar type diff --git a/src/Test/AbstractDtoTestCase.php b/src/Test/AbstractDtoTestCase.php index e907373..301614b 100644 --- a/src/Test/AbstractDtoTestCase.php +++ b/src/Test/AbstractDtoTestCase.php @@ -24,7 +24,10 @@ public function testModel(): void if ($attribute->getName() === 'PHPUnit\Framework\Attributes\CoversClass') { $testedAttributes = true; $config = $this->getAccessorPairConfig(); - static::assertAccessorPairs($attribute->getArguments()[0], $config); + + /** @var array{0: class-string} $arguments */ + $arguments = $attribute->getArguments(); + static::assertAccessorPairs($arguments[0], $config); } } static::assertTrue($testedAttributes, 'Missing CoversClass attribute'); diff --git a/tests/Unit/Constraint/MethodPair/AbstractDataClass.php b/tests/Unit/Constraint/MethodPair/AbstractDataClass.php index faeb956..38d5895 100644 --- a/tests/Unit/Constraint/MethodPair/AbstractDataClass.php +++ b/tests/Unit/Constraint/MethodPair/AbstractDataClass.php @@ -5,9 +5,6 @@ use DigitalRevolution\AccessorPairConstraint\Constraint\ConstraintConfig; -/** - * @suppressWarnings(PHPMD.NumberOfChildren) - */ abstract class AbstractDataClass { /** diff --git a/tests/Unit/Constraint/ValueProvider/AbstractValueProviderTestCase.php b/tests/Unit/Constraint/ValueProvider/AbstractValueProviderTestCase.php index 39b1577..1946914 100644 --- a/tests/Unit/Constraint/ValueProvider/AbstractValueProviderTestCase.php +++ b/tests/Unit/Constraint/ValueProvider/AbstractValueProviderTestCase.php @@ -5,9 +5,6 @@ use DigitalRevolution\AccessorPairConstraint\Tests\TestCase; -/** - * @suppressWarnings(PHPMD.NumberOfChildren) - */ abstract class AbstractValueProviderTestCase extends TestCase { abstract public function testGetValues(): void; diff --git a/tests/Unit/Constraint/ValueProvider/Compound/ArrayProviderTest.php b/tests/Unit/Constraint/ValueProvider/Compound/ArrayProviderTest.php index 4565b28..11d5cc5 100644 --- a/tests/Unit/Constraint/ValueProvider/Compound/ArrayProviderTest.php +++ b/tests/Unit/Constraint/ValueProvider/Compound/ArrayProviderTest.php @@ -23,7 +23,7 @@ class ArrayProviderTest extends AbstractValueProviderTestCase public function testGetValues(): void { $valueProvider = new ArrayProvider(); - $values = $valueProvider->getValues(); + $values = $valueProvider->getValues(); static::assertValueTypes($values, ['iterable']); static::assertValueTypes(array_merge(...$values), ['integer', 'double', 'string', 'NULL']); @@ -41,7 +41,7 @@ public function testGetValues(): void public function testGetValuesTyped(): void { $valueProvider = new ArrayProvider(new IntProvider(), new StringProvider()); - $values = $valueProvider->getValues(); + $values = $valueProvider->getValues(); static::assertValueTypes($values, ['iterable']); static::assertValueTypes(array_merge(...$values), ['integer']); diff --git a/tests/Unit/Constraint/ValueProvider/NativeValueProviderFactoryTest.php b/tests/Unit/Constraint/ValueProvider/NativeValueProviderFactoryTest.php index c810e49..be504d1 100644 --- a/tests/Unit/Constraint/ValueProvider/NativeValueProviderFactoryTest.php +++ b/tests/Unit/Constraint/ValueProvider/NativeValueProviderFactoryTest.php @@ -65,7 +65,6 @@ * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\ValueProviderList * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\PseudoValueProviderFactory * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\ValueProviderFactory - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class NativeValueProviderFactoryTest extends TestCase { diff --git a/tests/Unit/Constraint/ValueProvider/Pseudo/ListProviderTest.php b/tests/Unit/Constraint/ValueProvider/Pseudo/ListProviderTest.php index 918c5a9..19da5e2 100644 --- a/tests/Unit/Constraint/ValueProvider/Pseudo/ListProviderTest.php +++ b/tests/Unit/Constraint/ValueProvider/Pseudo/ListProviderTest.php @@ -29,7 +29,6 @@ public function testGetValues(): void } /** - * @covers ::__construct * @covers ::getValues * @throws Exception * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\Scalar\IntProvider diff --git a/tests/Unit/Constraint/ValueProvider/PseudoValueProviderFactoryTest.php b/tests/Unit/Constraint/ValueProvider/PseudoValueProviderFactoryTest.php index a39ed6e..7a00df0 100644 --- a/tests/Unit/Constraint/ValueProvider/PseudoValueProviderFactoryTest.php +++ b/tests/Unit/Constraint/ValueProvider/PseudoValueProviderFactoryTest.php @@ -78,7 +78,6 @@ * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\ValueProviderList * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\NativeValueProviderFactory * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\ValueProviderFactory - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PseudoValueProviderFactoryTest extends TestCase { diff --git a/tests/Unit/Constraint/ValueProvider/ValueProviderFactoryTest.php b/tests/Unit/Constraint/ValueProvider/ValueProviderFactoryTest.php index 982fe01..d74b654 100644 --- a/tests/Unit/Constraint/ValueProvider/ValueProviderFactoryTest.php +++ b/tests/Unit/Constraint/ValueProvider/ValueProviderFactoryTest.php @@ -66,7 +66,6 @@ * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\ValueProviderList * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\PseudoValueProviderFactory * @uses \DigitalRevolution\AccessorPairConstraint\Constraint\ValueProvider\NativeValueProviderFactory - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ValueProviderFactoryTest extends TestCase {