diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 775c61c..d03e885 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -57,6 +57,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" dependencies: - "highest" @@ -69,6 +70,11 @@ jobs: exclude: - php-version: "8.1" symfony: "^7.0" + include: + - php-version: '8.4' + symfony: '^8.0' + - php-version: '8.5' + symfony: '^8.0' steps: - name: "Checkout" uses: "actions/checkout@v4" @@ -103,6 +109,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" dependencies: - "highest" @@ -115,6 +122,11 @@ jobs: exclude: - php-version: "8.1" symfony: "^7.0" + include: + - php-version: '8.4' + symfony: '^8.0' + - php-version: '8.5' + symfony: '^8.0' steps: - name: "Checkout" uses: "actions/checkout@v4" @@ -122,9 +134,9 @@ jobs: - name: "Setup PHP, with composer and extensions" uses: "shivammathur/setup-php@v2" with: - php-version: "${{ matrix.php-version }}" - extensions: "${{ env.PHP_EXTENSIONS }}" coverage: "none" + extensions: "${{ env.PHP_EXTENSIONS }}" + php-version: "${{ matrix.php-version }}" tools: "flex" - name: "Install composer dependencies" @@ -135,7 +147,7 @@ jobs: dependency-versions: "${{ matrix.dependencies }}" - name: "Static analysis" - run: "vendor/bin/psalm --php-version=${{ matrix.php-version }}" + run: "vendor/bin/phpstan --no-progress --memory-limit=1G analyse --error-format=github" unit-tests: name: "Unit tests" @@ -149,6 +161,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" dependencies: - "lowest" @@ -162,6 +175,11 @@ jobs: exclude: - php-version: "8.1" symfony: "^7.0" + include: + - php-version: '8.4' + symfony: '^8.0' + - php-version: '8.5' + symfony: '^8.0' steps: - name: "Checkout" @@ -171,8 +189,6 @@ jobs: uses: "shivammathur/setup-php@v2" with: php-version: "${{ matrix.php-version }}" - extensions: "${{ env.PHP_EXTENSIONS }}" - coverage: "none" tools: "flex" - name: "Install composer dependencies" @@ -193,7 +209,7 @@ jobs: strategy: matrix: php-version: - - "8.4" + - "8.5" dependencies: - "highest" diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php index a7801ad..803f15b 100644 --- a/composer-dependency-analyser.php +++ b/composer-dependency-analyser.php @@ -4,6 +4,7 @@ use ShipMonk\ComposerDependencyAnalyser\Config\Configuration; use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType; use Symfony\Component\TypeInfo\Type; +use Symfony\Component\PropertyInfo\Type as LegacyType; $config = new Configuration(); @@ -16,6 +17,9 @@ } else { $config->ignoreUnknownClasses([Type::class]); } +if (!class_exists(LegacyType::class)) { + $config->ignoreUnknownClasses([LegacyType::class]); +} // ignore polyfill if (version_compare(PHP_VERSION, '8.3.0', '>=')) { diff --git a/composer.json b/composer.json index d0d6bec..dd009aa 100644 --- a/composer.json +++ b/composer.json @@ -12,29 +12,33 @@ "require": { "php": ">=8.1", "doctrine/dbal": "^3.4 || ^4.0", - "doctrine/doctrine-bundle": "^1.9 || ^2.0 || ^3.0", + "doctrine/doctrine-bundle": "^1.9 || ^2.0 || ^3.0 || ^4.0", "dragonmantank/cron-expression": "^2.2 || ^3.0", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/form": "^5.4 || ^6.0 || ^7.0", - "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", - "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/config": "^5.4.22 || ^6.4 || ^7.0 || ^8.0", + "symfony/dependency-injection": "^5.4.22 || ^6.4 || ^7.0 || ^8.0", + "symfony/form": "^5.4.22 || ^6.4 || ^7.0 || ^8.0", + "symfony/http-kernel": "^5.4.22 || ^6.4 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.22 || ^6.4 || ^7.0 || ^8.0", "symfony/polyfill-php83": "^1.33", "symfony/polyfill-php84": "^1.33", - "symfony/property-info": "^5.4 || ^6.0 || ^7.0", - "symfony/validator": "^5.4 || ^6.0 || ^7.0" + "symfony/property-info": "^5.4.22 || ^6.4 || ^7.0 || ^8.0", + "symfony/validator": "^5.4.22 || ^6.4 || ^7.0 || ^8.0" }, "require-dev": { - "ergebnis/composer-normalize": "^2.42", + "ergebnis/composer-normalize": "^2.45", "matthiasnoback/symfony-dependency-injection-test": "^4.3 || ^5.0 || ^6.0", "phpdocumentor/reflection-docblock": "^5.3", - "phpunit/phpunit": "^9.5 || ^12.0", - "psalm/plugin-phpunit": "^0.19", + "phpstan/extension-installer": "^1.0", + "phpstan/phpdoc-parser": "^1.0 || ^2.0", + "phpstan/phpstan": "^1.0 || ^2.0", + "phpstan/phpstan-phpunit": "^1.0 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.0 || ^2.0", + "phpstan/phpstan-symfony": "^1.0 || ^2.0", + "phpunit/phpunit": "^10.5 || ^11.0.1 || ^12.0", "roave/security-advisories": "dev-latest", "shipmonk/composer-dependency-analyser": "^1.8", "sylius-labs/coding-standard": "^4.1.1", - "symplify/easy-coding-standard": "^12.3.6", - "vimeo/psalm": "^6.0" + "symplify/easy-coding-standard": "^12.3.6 || ^13.0.0" }, "prefer-stable": true, "autoload": { @@ -50,7 +54,8 @@ "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": false, - "ergebnis/composer-normalize": true + "ergebnis/composer-normalize": true, + "phpstan/extension-installer": true }, "sort-packages": true }, diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..0d4287d --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,2 @@ +parameters: + reportUnmatchedIgnoredErrors: false diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..239010f --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,23 @@ +includes: + - phpstan-baseline.neon + - vendor/phpstan/phpstan/conf/bleedingEdge.neon + +parameters: + level: 8 + paths: + - src + - tests + scanFiles: + - vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php + treatPhpDocTypesAsCertain: false + checkInternalClassCaseSensitivity: true + checkMissingVarTagTypehint: true + checkMissingTypehints: true + checkUninitializedProperties: true + featureToggles: + skipCheckGenericClasses: + - Symfony\Component\Form\AbstractType + - Symfony\Component\Form\FormBuilderInterface + - Symfony\Component\Form\FormInterface + - Symfony\Component\Form\FormTypeExtensionInterface + - Symfony\Component\Form\FormTypeInterface diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index 883f428..0000000 --- a/psalm.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/DependencyInjection/SetonoCronExpressionExtension.php b/src/DependencyInjection/SetonoCronExpressionExtension.php index c670ebb..e42b766 100644 --- a/src/DependencyInjection/SetonoCronExpressionExtension.php +++ b/src/DependencyInjection/SetonoCronExpressionExtension.php @@ -10,15 +10,15 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; final class SetonoCronExpressionExtension extends Extension implements PrependExtensionInterface { #[\Override] public function load(array $configs, ContainerBuilder $container): void { - $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); - $loader->load('services.xml'); + $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('services.php'); } #[\Override] diff --git a/src/Doctrine/DBAL/Types/CronExpressionType.php b/src/Doctrine/DBAL/Types/CronExpressionType.php index c5b5f17..3063a16 100644 --- a/src/Doctrine/DBAL/Types/CronExpressionType.php +++ b/src/Doctrine/DBAL/Types/CronExpressionType.php @@ -34,9 +34,7 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?CronExpr } if (!is_string($value)) { - /** - * @psalm-suppress UndefinedMethod - */ + /** @phpstan-ignore staticMethod.notFound */ throw class_exists(InvalidType::class) ? InvalidType::new($value, CronExpression::class, ['string']) : ConversionException::conversionFailedInvalidType($value, CronExpression::class, ['string']); } @@ -47,9 +45,7 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?CronExpr try { return CronExpression::factory($value); } catch (\Throwable $e) { - /** - * @psalm-suppress UndefinedMethod - */ + /** @phpstan-ignore staticMethod.notFound */ throw class_exists(ValueNotConvertible::class) ? ValueNotConvertible::new($value, CronExpression::class, null, $e) : ConversionException::conversionFailed($value, CronExpression::class, $e); } } @@ -72,7 +68,11 @@ public function getName(): string return self::CRON_EXPRESSION_TYPE; } - /** @noinspection PhpUnusedParameterInspection */ + /** + * @noinspection PhpUnusedParameterInspection + * + * @phpstan-ignore return.tooWideBool + */ public function requiresSQLCommentHint(AbstractPlatform $platform): bool { return true; diff --git a/src/Form/DataTransformer/CronExpressionToPartsTransformer.php b/src/Form/DataTransformer/CronExpressionToPartsTransformer.php index 9a87d29..ceb043a 100644 --- a/src/Form/DataTransformer/CronExpressionToPartsTransformer.php +++ b/src/Form/DataTransformer/CronExpressionToPartsTransformer.php @@ -10,8 +10,6 @@ /** * @template-implements DataTransformerInterface>> - * - * @psalm-suppress TooManyTemplateParams */ final class CronExpressionToPartsTransformer implements DataTransformerInterface { @@ -88,7 +86,9 @@ public function reverseTransform($value): CronExpression } /** - * @psalm-assert array> $value + * @phpstan-assert array> $value + * + * @phpstan-ignore missingType.iterableValue */ private static function allArrayScalar(array $value): bool { diff --git a/src/Form/DataTransformer/CronExpressionToStringPartsTransformer.php b/src/Form/DataTransformer/CronExpressionToStringPartsTransformer.php index 20605fe..79caf0e 100644 --- a/src/Form/DataTransformer/CronExpressionToStringPartsTransformer.php +++ b/src/Form/DataTransformer/CronExpressionToStringPartsTransformer.php @@ -10,8 +10,6 @@ /** * @template-implements DataTransformerInterface> - * - * @psalm-suppress TooManyTemplateParams */ final class CronExpressionToStringPartsTransformer implements DataTransformerInterface { @@ -88,7 +86,9 @@ public function reverseTransform($value): CronExpression } /** - * @psalm-assert iterable $value + * @phpstan-assert array $value + * + * @phpstan-ignore missingType.iterableValue */ private static function allString(array $value): bool { diff --git a/src/Form/DataTransformer/CronExpressionToStringTransformer.php b/src/Form/DataTransformer/CronExpressionToStringTransformer.php index fb0f954..4fdd10e 100644 --- a/src/Form/DataTransformer/CronExpressionToStringTransformer.php +++ b/src/Form/DataTransformer/CronExpressionToStringTransformer.php @@ -10,8 +10,6 @@ /** * @template-implements DataTransformerInterface - * - * @psalm-suppress TooManyTemplateParams */ final class CronExpressionToStringTransformer implements DataTransformerInterface { diff --git a/src/Form/Type/CronExpressionType.php b/src/Form/Type/CronExpressionType.php index 1e971d4..f04573b 100644 --- a/src/Form/Type/CronExpressionType.php +++ b/src/Form/Type/CronExpressionType.php @@ -136,6 +136,8 @@ public function getBlockPrefix(): string /** * Will create an array where the first key is 1 * oneIndexedRange(3) will return [1 => 1, 2 => 2, 3 => 3]. + * + * @return array */ private function oneIndexedRange(int $end, int $start = 0): array { @@ -147,11 +149,10 @@ private function oneIndexedRange(int $end, int $start = 0): array protected function buildCallback(int $payload): Callback { - // helper function for Symfony 4.4 - return new Callback([ - 'callback' => [$this, 'validateCronField'], - 'payload' => $payload, - ]); + return new Callback( + callback: $this->validateCronField(...), + payload: $payload, + ); } public function validateCronField(?string $value, ExecutionContextInterface $context, int $payload): void diff --git a/src/Form/TypeGuesser/CronExpressionTypeGuesser.php b/src/Form/TypeGuesser/CronExpressionTypeGuesser.php index 1ef2ab5..6c5caf4 100644 --- a/src/Form/TypeGuesser/CronExpressionTypeGuesser.php +++ b/src/Form/TypeGuesser/CronExpressionTypeGuesser.php @@ -90,12 +90,13 @@ private function createExtractor(): PropertyTypeExtractorInterface ], [], [], [$reflectionExtractor]); } + /** + * @param class-string $class + */ private function isCronExpression(string $class, string $property): bool { + /** @phpstan-ignore function.alreadyNarrowedType */ if (class_exists(Type::class) && method_exists($this->extractor, 'getType')) { - /** - * @psalm-suppress MixedAssignment - */ $type = $this->extractor->getType($class, $property); if (null === $type) { return false; @@ -104,18 +105,13 @@ private function isCronExpression(string $class, string $property): bool return true; } } else { - /** - * @psalm-suppress DeprecatedClass - * @psalm-suppress DeprecatedMethod - */ + /** @phpstan-ignore method.notFound */ $types = $this->extractor->getTypes($class, $property); if (null === $types) { return false; } foreach ($types as $lType) { - /** - * @psalm-suppress DeprecatedClass - */ + /** @phpstan-ignore class.notFound */ if (LegacyType::BUILTIN_TYPE_OBJECT === $lType->getBuiltinType() && CronExpression::class === $lType->getClassName()) { return true; diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php new file mode 100644 index 0000000..4e33810 --- /dev/null +++ b/src/Resources/config/services.php @@ -0,0 +1,17 @@ +services(); + + $services->set('setono_cron_expression.form.type_guesser.cron_expression', CronExpressionTypeGuesser::class) + ->args([ + service('property_info'), + ]) + ->tag('form.type_guesser'); +}; diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml deleted file mode 100644 index 41a9a93..0000000 --- a/src/Resources/config/services.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/src/Validator/CronExpression.php b/src/Validator/CronExpression.php index 54d0ecd..9588d62 100644 --- a/src/Validator/CronExpression.php +++ b/src/Validator/CronExpression.php @@ -23,12 +23,11 @@ class CronExpression extends Constraint * @param string[]|null $groups */ public function __construct( - string $message = null, + ?string $message = null, ?array $groups = null, mixed $payload = null, - array $options = [], ) { - parent::__construct($options, $groups, $payload); + parent::__construct(null, $groups, $payload); $this->message = $message ?? $this->message; } diff --git a/tests/Doctrine/DBAL/Types/CronExpressionTypeTest.php b/tests/Doctrine/DBAL/Types/CronExpressionTypeTest.php index 80d910e..7bd0449 100644 --- a/tests/Doctrine/DBAL/Types/CronExpressionTypeTest.php +++ b/tests/Doctrine/DBAL/Types/CronExpressionTypeTest.php @@ -18,7 +18,7 @@ final class CronExpressionTypeTest extends TestCase { public function testTypeName(): void { - self::assertEquals('cron_expression', $this->getType()->getName()); + self::assertSame('cron_expression', $this->getType()->getName()); } public function testTypeRequiresHint(): void @@ -60,9 +60,6 @@ public function testConvertFaultyTypeToPhpThrowsException(): void { self::expectException(ConversionException::class); if (class_exists(InvalidType::class)) { - /** - * @psalm-suppress InvalidArgument - */ self::expectException(InvalidType::class); } @@ -73,9 +70,6 @@ public function testConvertFaultyStringToPhpThrowsException(): void { self::expectException(ConversionException::class); if (class_exists(ValueNotConvertible::class)) { - /** - * @psalm-suppress InvalidArgument - */ self::expectException(ValueNotConvertible::class); } diff --git a/tests/Form/DataTransformer/ToPartsTest.php b/tests/Form/DataTransformer/ToPartsTest.php index 3087b39..f8321dd 100644 --- a/tests/Form/DataTransformer/ToPartsTest.php +++ b/tests/Form/DataTransformer/ToPartsTest.php @@ -71,6 +71,6 @@ protected function invalidReverseTransform(mixed $value): void protected function expectedReverseTransform(mixed $input, string $expected): void { $transformer = new CronExpressionToPartsTransformer(); - $this->assertSame($expected, $transformer->reverseTransform($input)->getExpression()); + self::assertSame($expected, $transformer->reverseTransform($input)->getExpression()); } } diff --git a/tests/Form/DataTransformer/ToStringPartsTest.php b/tests/Form/DataTransformer/ToStringPartsTest.php index 8310b5a..66c1baa 100644 --- a/tests/Form/DataTransformer/ToStringPartsTest.php +++ b/tests/Form/DataTransformer/ToStringPartsTest.php @@ -60,6 +60,6 @@ protected function invalidReverseTransform(mixed $value): void protected function expectedReverseTransform(mixed $input, string $expected): void { $transformer = new CronExpressionToStringPartsTransformer(); - $this->assertSame($expected, $transformer->reverseTransform($input)->getExpression()); + self::assertSame($expected, $transformer->reverseTransform($input)->getExpression()); } } diff --git a/tests/Form/DataTransformer/ToStringTest.php b/tests/Form/DataTransformer/ToStringTest.php index f78d473..d49864c 100644 --- a/tests/Form/DataTransformer/ToStringTest.php +++ b/tests/Form/DataTransformer/ToStringTest.php @@ -36,6 +36,6 @@ protected function invalidReverseTransform(mixed $value): void protected function expectedReverseTransform(mixed $input, string $expected): void { $transformer = new CronExpressionToStringTransformer(); - $this->assertSame($expected, $transformer->reverseTransform($input)->getExpression()); + self::assertSame($expected, $transformer->reverseTransform($input)->getExpression()); } } diff --git a/tests/Form/Type/CronExpressionTypeCallbackTest.php b/tests/Form/Type/CronExpressionTypeCallbackTest.php index 2ce3cdd..bd4c45a 100644 --- a/tests/Form/Type/CronExpressionTypeCallbackTest.php +++ b/tests/Form/Type/CronExpressionTypeCallbackTest.php @@ -5,7 +5,6 @@ namespace Setono\CronExpressionBundle\Tests\Form\Type; use Cron\CronExpression; -use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; use PHPUnit\Framework\TestCase; use Setono\CronExpressionBundle\Form\Type\CronExpressionType; use Symfony\Component\Validator\Context\ExecutionContextInterface; @@ -14,23 +13,29 @@ final class CronExpressionTypeCallbackTest extends TestCase { public function testNullNoViolation(): void { - $this->callValidateCronField(null, $this->never()); + $this->callValidateCronField(null, false); } public function testValidNoViolation(): void { - $this->callValidateCronField('59', $this->never()); + $this->callValidateCronField('59', false); } public function testViolationAdded(): void { - $this->callValidateCronField('61', $this->once()); + $this->callValidateCronField('61', true); } - protected function callValidateCronField(?string $value, InvokedCountMatcher $counter): void + protected function callValidateCronField(?string $value, bool $match): void { $mock = $this->createMock(ExecutionContextInterface::class); - $mock->expects($counter)->method('addViolation') + + $mock->expects( + $match ? +/** @phpstan-ignore staticMethod.dynamicCall */ $this->once() : +/** @phpstan-ignore staticMethod.dynamicCall */ $this->never(), + ) + ->method('addViolation') ->with('{{value}} is not a valid cron part', ['value' => $value]) ; diff --git a/tests/Form/Type/CronExpressionTypeStringTest.php b/tests/Form/Type/CronExpressionTypeStringTest.php index a06c770..c99bbf3 100644 --- a/tests/Form/Type/CronExpressionTypeStringTest.php +++ b/tests/Form/Type/CronExpressionTypeStringTest.php @@ -41,13 +41,13 @@ private function _submit(?string $formData, string $expected): void // submit the data to the form directly $form->submit($formData); - $this->assertTrue($form->isSynchronized()); + self::assertTrue($form->isSynchronized()); /** @var CronExpression $cronExpression */ $cronExpression = $form->getData(); - $this->assertInstanceOf(CronExpression::class, $cronExpression); - $this->assertSame($expected, $cronExpression->getExpression()); + self::assertInstanceOf(CronExpression::class, $cronExpression); + self::assertSame($expected, $cronExpression->getExpression()); } public function testSubmitFaultyEmpty(): void @@ -63,9 +63,9 @@ public function testSubmitFaultyArray(): void } /** - * @param string|array|null $formData + * @phpstan-ignore missingType.iterableValue */ - private function _submitFaultyData($formData): void + private function _submitFaultyData(array|string|null $formData): void { $form = $this->factory->create(CronExpressionType::class, null, [ 'widget' => 'single_text', @@ -74,7 +74,7 @@ private function _submitFaultyData($formData): void // submit the data to the form directly $form->submit($formData); - $this->assertFalse($form->isSynchronized()); + self::assertFalse($form->isSynchronized()); } public function testCreateWithFaultyData(): void diff --git a/tests/Form/Type/CronExpressionTypeTest.php b/tests/Form/Type/CronExpressionTypeTest.php index ca8f894..c7ea779 100644 --- a/tests/Form/Type/CronExpressionTypeTest.php +++ b/tests/Form/Type/CronExpressionTypeTest.php @@ -46,6 +46,9 @@ public function testSubmitEmpty(): void $this->_submit([], '* * * * *'); } + /** + * @param array> $formData + */ private function _submit(array $formData, string $expected): void { $form = $this->factory->create(CronExpressionType::class); @@ -53,20 +56,20 @@ private function _submit(array $formData, string $expected): void // submit the data to the form directly $form->submit($formData); - $this->assertTrue($form->isSynchronized()); + self::assertTrue($form->isSynchronized()); $view = $form->createView(); $children = $view->children; foreach (array_keys($formData) as $key) { - $this->assertArrayHasKey($key, $children); + self::assertArrayHasKey($key, $children); } /** @var CronExpression $cronExpression */ $cronExpression = $form->getData(); - $this->assertInstanceOf(CronExpression::class, $cronExpression); - $this->assertSame($expected, $cronExpression->getExpression()); + self::assertInstanceOf(CronExpression::class, $cronExpression); + self::assertSame($expected, $cronExpression->getExpression()); } public function testCreateWithFaultyData(): void diff --git a/tests/Form/Type/CronExpressionTypeTextTest.php b/tests/Form/Type/CronExpressionTypeTextTest.php index a3e47fc..c88a653 100644 --- a/tests/Form/Type/CronExpressionTypeTextTest.php +++ b/tests/Form/Type/CronExpressionTypeTextTest.php @@ -49,6 +49,9 @@ public function testSubmitEmpty(): void $this->_submit([], '* * * * *'); } + /** + * @param array $formData + */ private function _submit(array $formData, string $expected): void { $form = $this->factory->create(CronExpressionType::class, null, [ @@ -58,20 +61,20 @@ private function _submit(array $formData, string $expected): void // submit the data to the form directly $form->submit($formData); - $this->assertTrue($form->isSynchronized()); + self::assertTrue($form->isSynchronized()); $view = $form->createView(); $children = $view->children; foreach (array_keys($formData) as $key) { - $this->assertArrayHasKey($key, $children); + self::assertArrayHasKey($key, $children); } /** @var CronExpression $cronExpression */ $cronExpression = $form->getData(); - $this->assertInstanceOf(CronExpression::class, $cronExpression); - $this->assertSame($expected, $cronExpression->getExpression()); + self::assertInstanceOf(CronExpression::class, $cronExpression); + self::assertSame($expected, $cronExpression->getExpression()); } public function testSubmitFaultyMinutesOnly(): void @@ -82,9 +85,9 @@ public function testSubmitFaultyMinutesOnly(): void } /** - * @param string|array|null $formData + * @phpstan-ignore missingType.iterableValue */ - private function _submitFaultyData($formData): void + private function _submitFaultyData(array|string|null $formData): void { $form = $this->factory->create(CronExpressionType::class, null, [ 'widget' => 'text', @@ -93,7 +96,7 @@ private function _submitFaultyData($formData): void // submit the data to the form directly $form->submit($formData); - $this->assertFalse($form->isSynchronized()); + self::assertFalse($form->isSynchronized()); } public function testCreateWithFaultyData(): void @@ -130,12 +133,11 @@ public function _submitWithChild($formData, string $expected): void $form = $builder->getForm(); $form->submit(['cron' => $formData]); - /** @var array $data */ + /** @var array $data */ $data = $form->getData(); - /** @var CronExpression $cronExpression */ $cronExpression = $data['cron']; - $this->assertInstanceOf(CronExpression::class, $cronExpression); - $this->assertSame($expected, $cronExpression->getExpression()); + self::assertInstanceOf(CronExpression::class, $cronExpression); + self::assertSame($expected, $cronExpression->getExpression()); } } diff --git a/tests/Form/TypeGuesser/CronExpressionTypeGuesserTest.php b/tests/Form/TypeGuesser/CronExpressionTypeGuesserTest.php index c09d4ff..551eecd 100644 --- a/tests/Form/TypeGuesser/CronExpressionTypeGuesserTest.php +++ b/tests/Form/TypeGuesser/CronExpressionTypeGuesserTest.php @@ -22,22 +22,22 @@ public function setUp(): void public function testItReturnsNullIfClassDoesNotExist(): void { - $this->assertNull($this->typeGuesser->guessType('Class\\Does\\Not\\Exist', 'property')); + self::assertNull($this->typeGuesser->guessType('Class\\Does\\Not\\Exist', 'property')); } public function testItReturnsNullIfNoPhpdocIsPresent(): void { - $this->assertNull($this->typeGuesser->guessType(StubWithNoPhpDoc::class, 'property')); + self::assertNull($this->typeGuesser->guessType(StubWithNoPhpDoc::class, 'property')); } public function testItReturnsNullIfPropertyDoesntExist(): void { - $this->assertNull($this->typeGuesser->guessType(StubWithNoPhpDoc::class, 'property2')); + self::assertNull($this->typeGuesser->guessType(StubWithNoPhpDoc::class, 'property2')); } public function testItReturnsNullIfPropertyHasWrongType(): void { - $this->assertNull($this->typeGuesser->guessType(StubWithWrongType::class, 'property')); + self::assertNull($this->typeGuesser->guessType(StubWithWrongType::class, 'property')); } public function testItGuessesTypeWhenTypeIsAFqcn(): void @@ -62,16 +62,16 @@ public function testItGuessesTypeWhenTypeIsHinted(): void protected function guess_type(string $class): void { - $this->assertCorrectGuess($this->typeGuesser->guessType($class, 'property')); - $this->assertNull($this->typeGuesser->guessRequired($class, 'property')); - $this->assertNull($this->typeGuesser->guessMaxLength($class, 'property')); - $this->assertNull($this->typeGuesser->guessPattern($class, 'property')); + self::assertCorrectGuess($this->typeGuesser->guessType($class, 'property')); + self::assertNull($this->typeGuesser->guessRequired($class, 'property')); + self::assertNull($this->typeGuesser->guessMaxLength($class, 'property')); + self::assertNull($this->typeGuesser->guessPattern($class, 'property')); } - private function assertCorrectGuess(?TypeGuess $res): void + private static function assertCorrectGuess(?TypeGuess $res): void { - $this->assertNotNull($res); - $this->assertSame(CronExpressionType::class, $res->getType()); - $this->assertSame(Guess::VERY_HIGH_CONFIDENCE, $res->getConfidence()); + self::assertNotNull($res); + self::assertSame(CronExpressionType::class, $res->getType()); + self::assertSame(Guess::VERY_HIGH_CONFIDENCE, $res->getConfidence()); } } diff --git a/tests/Form/TypeGuesser/StubAliased.php b/tests/Form/TypeGuesser/StubAliased.php index e6724cd..2e43a6c 100644 --- a/tests/Form/TypeGuesser/StubAliased.php +++ b/tests/Form/TypeGuesser/StubAliased.php @@ -1,5 +1,7 @@ * - * @psalm-suppress TooManyTemplateParams + * @phpstan-ignore generics.notGeneric */ final class CronExpressionTest extends ConstraintValidatorTestCase { @@ -70,8 +70,6 @@ public function testExpectsStringCompatibleValue(): void * @dataProvider getInvalidValues * * @param mixed $value - * - * @psalm-suppress UndefinedAttributeClass */ #[DataProvider('getInvalidValues')] public function testInvalidValues($value, string $valueAsString): void @@ -80,13 +78,9 @@ public function testInvalidValues($value, string $valueAsString): void $this->validator->validate($value, $constraint); - /** @psalm-suppress InternalMethod,MixedMethodCall */ $this->buildViolation('myMessage')->setParameter('{{ value }}', $valueAsString)->assertRaised(); } - /** - * @psalm-return list - */ public static function getInvalidValues(): array { return [ diff --git a/tests/Validator/FormCallbackTest.php b/tests/Validator/FormCallbackTest.php index 017924c..0bce2ba 100644 --- a/tests/Validator/FormCallbackTest.php +++ b/tests/Validator/FormCallbackTest.php @@ -13,7 +13,7 @@ /** * @template-extends ConstraintValidatorTestCase * - * @psalm-suppress TooManyTemplateParams + * @phpstan-ignore generics.notGeneric */ final class FormCallbackTest extends ConstraintValidatorTestCase { @@ -39,16 +39,14 @@ public function testOutOfRangeIsNotValid(): void { $value = '61'; $this->validator->validate($value, $this->createConstraint(CronExpression::MINUTE)); - /** @psalm-suppress InternalMethod,MixedMethodCall */ $this->buildViolation('{{value}} is not a valid cron part')->setParameter('value', $value)->assertRaised(); } protected function createConstraint(int $payload): Callback { - // helper function for Symfony 4.4 - return new Callback([ - 'callback' => [new CronExpressionType(), 'validateCronField'], - 'payload' => $payload, - ]); + return new Callback( + callback: [new CronExpressionType(), 'validateCronField'], + payload: $payload, + ); } }