Skip to content

Commit

Permalink
feature #219 Add phpstan (benji07, ogizanagi)
Browse files Browse the repository at this point in the history
This PR was merged into the 2.x-dev branch.

Discussion
----------

Add phpstan

Tests fail because of a deprecation inside of Doctrine ODM

Commits
-------

409e919 tweak CI & Makefile for PHPStan linting
bd22ffd Add phpstan
  • Loading branch information
ogizanagi committed Mar 24, 2023
2 parents 6d19071 + 409e919 commit d555de9
Show file tree
Hide file tree
Showing 20 changed files with 132 additions and 42 deletions.
34 changes: 29 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,36 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
coverage: none

- name: 'Require Doctrine MongoDB dependencies'
run: composer require --no-update --ignore-platform-reqs --dev --no-interaction --ansi "doctrine/mongodb-odm:^2.4" "doctrine/mongodb-odm-bundle:^4.5.1"

- name: 'Install dependencies'
run: make php-cs-fixer.phar
id: deps
run: |
echo "::group::Install project deps"
composer update --prefer-dist --ignore-platform-reqs --ansi
echo "::endgroup::"
echo "::group::Install PHPUnit"
vendor/bin/simple-phpunit install
echo "::endgroup::"
env:
SYMFONY_REQUIRE: "6.2*dev"

- name: 'Lint - PHP CS Fixer'
if: always() && steps.deps.outcome == 'success'
run: |
echo "::group::Install PHP CS Fixer"
make php-cs-fixer.phar
echo "::endgroup::"
./php-cs-fixer.phar fix --dry-run --no-interaction --diff
- name: 'Check style'
run: ./php-cs-fixer.phar fix --dry-run --no-interaction --diff
- name: 'Lint - PHPStan'
if: always() && steps.deps.outcome == 'success'
run: ./vendor/bin/phpstan

test:
name: ${{ matrix.name }}
Expand Down Expand Up @@ -139,7 +163,7 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: pdo_sqlite ${{ matrix.mongodb && ', mongodb' }} ${{ matrix.mysql && ', pdo_mysql' }}
coverage: pcov
coverage: none
tools: 'composer:v2,flex'

- name: 'Start MongoDB (Linux)'
Expand Down Expand Up @@ -211,4 +235,4 @@ jobs:
if: ${{ matrix.mysql && matrix.os == 'windows-latest' }}

- name: 'Run PHPUnit tests'
run: vendor/bin/simple-phpunit --testdox --verbose ${{ matrix.code-coverage && '--coverage-text --coverage-clover build/logs/clover.xml' }}
run: vendor/bin/simple-phpunit --testdox --verbose
21 changes: 13 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,42 @@ install: setup
install:
rm -f symfony composer.lock
symfony composer config minimum-stability --unset
symfony composer update --prefer-dist
symfony composer update --prefer-dist --ignore-platform-req=ext-mongodb

## Install - Install lowest deps
install.lowest: setup
install.lowest: export SYMFONY_REQUIRE = 5.4.*@dev
install.lowest:
symfony composer config minimum-stability --unset
symfony composer update --prefer-lowest
symfony composer update --prefer-lowest --ignore-platform-req=ext-mongodb

## Install - Install Symfony 5.4 deps
install.54: setup
install.54: export SYMFONY_REQUIRE = 5.4.*@dev
install.54:
symfony composer config minimum-stability dev
symfony composer update
symfony composer update --ignore-platform-req=ext-mongodb

## Install - Install Symfony 6.0 deps
install.60: setup
install.60: export SYMFONY_REQUIRE = 6.0.*@dev
install.60:
symfony composer config minimum-stability dev
symfony composer update
symfony composer update --ignore-platform-req=ext-mongodb

## Install - Install Symfony 6.1 deps
install.61: setup
install.61: export SYMFONY_REQUIRE = 6.1.*@dev
install.61:
symfony composer config minimum-stability dev
symfony composer update
symfony composer update --ignore-platform-req=ext-mongodb

## Install - Install Symfony 6.2 deps
install.62: setup
install.62: export SYMFONY_REQUIRE = 6.2.*@dev
install.62:
symfony composer config minimum-stability dev
symfony composer update
symfony composer update --ignore-platform-req=ext-mongodb

## Install - Add Doctrine ODM deps
deps.odm.add:
Expand Down Expand Up @@ -90,10 +90,10 @@ docker.stop:
########

## Lint - Lint
lint: lint.php-cs-fixer
lint: lint.php-cs-fixer lint.phpstan

## Lint - Fix Lint
lint.fix: lint.php-cs-fixer.fix
lint.fix: lint.php-cs-fixer.fix lint.phpstan

## Lint - Update tools
lint.update:
Expand All @@ -111,3 +111,8 @@ lint.php-cs-fixer:
php-cs-fixer.phar:
wget --no-verbose https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/${PHP_CS_FIXER_VERSION}/php-cs-fixer.phar
chmod +x php-cs-fixer.phar

lint.phpstan:
@make deps.odm.add install >> /dev/null 2>&1
./vendor/bin/phpstan
@make deps.odm.rm install >> /dev/null 2>&1
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"doctrine/dbal": "^3.2",
"doctrine/doctrine-bundle": "^2.5",
"doctrine/orm": "^2.10",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-symfony": "^1.2",
"symfony/browser-kit": "^5.4|^6.0",
"symfony/config": "^5.4|^6.0",
"symfony/dependency-injection": "^5.4.2|^6.0.1",
Expand Down
2 changes: 2 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
ignoreErrors:
11 changes: 11 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
includes:
- phpstan-baseline.neon
- vendor/phpstan/phpstan-symfony/extension.neon

parameters:
level: '6'
paths:
- src

checkMissingIterableValueType: false
treatPhpDocTypesAsCertain: false
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<env name="MONGODB_DB" value="enum-test" />
<env name="DOCTRINE_DBAL_URL" value="sqlite:///%kernel.cache_dir%/db.sqlite" />
<!--<env name="DOCTRINE_DBAL_URL" value="pdo-mysql://root@localhost:3306/doctrine_tests" />-->
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0&amp;max[self]=0&amp;max[total]=9999&amp;verbose=1"/>
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0&amp;max[self]=0&amp;max[total]=9999&amp;verbose=1&amp;baselineFile=./tests/allowed-deprecations.json&amp;generateBaseline=0"/>
<env name="SYMFONY_PHPUNIT_REQUIRE" value="phpspec/prophecy-phpunit"/>
<env name="SYMFONY_PHPUNIT_VERSION" value="9.5"/>
</php>
Expand Down
4 changes: 2 additions & 2 deletions src/Bridge/Doctrine/Common/AbstractTypesDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ public static function getTypeFullyQualifiedClassName(string $enumClass, string
public static function getPascalCase(string $string): string
{
return ucfirst(
preg_replace_callback(
(string) preg_replace_callback(
'/:([a-z])/i',
function (array $word): string {
return ucfirst(strtolower($word[1]));
},
preg_replace('/[^\da-z]+/i', ':', $string)
(string) preg_replace('/[^\da-z]+/i', ':', $string)
)
);
}
Expand Down
10 changes: 5 additions & 5 deletions src/Bridge/Doctrine/DBAL/Types/AbstractFlagBagType.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ abstract protected function getEnumClass(): string;

/**
* What should be returned on null value from the database.
*
* @return FlagBag<\BackedEnum>|null
*/
protected function onNullFromDatabase(): ?FlagBag
{
Expand All @@ -45,11 +47,9 @@ protected function onNullFromPhp(): int|null
/**
* {@inheritdoc}
*
* @param FlagBag|null $value
*
* @return mixed
* @param FlagBag<\BackedEnum>|null $value
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform): int
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?int
{
if ($value !== null && !$value instanceof FlagBag) {
throw new InvalidArgumentException(sprintf(
Expand All @@ -71,7 +71,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): int
*
* @param int|null $value The value to convert.
*
* @return FlagBag|null
* @return FlagBag<\BackedEnum>|null
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Bridge/Faker/Provider/EnumProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct(private array $aliases = [])
*/
public function randomEnum(string $enumClassOrAlias): \UnitEnum
{
/** @var \UnitEnum|string $class */
/** @var class-string<\UnitEnum> $class */
$class = $this->aliases[$enumClassOrAlias] ?? $enumClassOrAlias;

$this->ensureEnumClass($class);
Expand Down Expand Up @@ -59,7 +59,7 @@ public function randomEnums(string $enumClassOrAlias, int $count, bool $exact =
$count = mt_rand($min, $count);
}

/** @var \UnitEnum|string $class */
/** @var class-string<\UnitEnum> $class */
$class = $this->aliases[$enumClassOrAlias] ?? $enumClassOrAlias;

$this->ensureEnumClass($class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public function process(ContainerBuilder $container): void

$types = $container->getParameter('.elao_enum.doctrine_types');

if (!\is_array($types)) {
throw new \InvalidArgumentException('The .elao_enum.doctrine_types parameter must be an array');
}

(new TypesDumper())->dumpToFile($this->typesFilePath, $types);

$container->getDefinition('doctrine.dbal.connection_factory')->setFile($this->typesFilePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public function process(ContainerBuilder $container): void

$types = $container->getParameter('.elao_enum.doctrine_mongodb_types');

if (!\is_array($types)) {
throw new \InvalidArgumentException('The .elao_enum.doctrine_mongodb_types parameter must be an array');
}

(new TypesDumper())->dumpToFile($this->typesFilePath, $types);

if (!empty($types)) {
Expand Down
7 changes: 5 additions & 2 deletions src/Bridge/Symfony/Bundle/ElaoEnumBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ public function build(ContainerBuilder $container): void
{
parent::build($container);

/** @var string $kernelCacheDir */
$kernelCacheDir = $container->getParameter('kernel.cache_dir');

$container->addCompilerPass(
new DoctrineDBALTypesPass($container->getParameter('kernel.cache_dir') . '/elao_enum_doctrine_dbal_types.php')
new DoctrineDBALTypesPass($kernelCacheDir . '/elao_enum_doctrine_dbal_types.php')
);

$container->addCompilerPass(
new DoctrineODMTypesPass($container->getParameter('kernel.cache_dir') . '/elao_enum_doctrine_odm_types.php')
new DoctrineODMTypesPass($kernelCacheDir . '/elao_enum_doctrine_odm_types.php')
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\InvalidArgumentException;

/**
* @implements DataTransformerInterface<FlagBag<\BackedEnum>, \BackedEnum[]>
*/
abstract class AbstractFlagBagTransformer implements DataTransformerInterface
{
/** @var class-string<\BackedEnum> */
Expand Down Expand Up @@ -50,6 +53,8 @@ public function __construct(string $enumType)

/**
* @param int|\BackedEnum[] $value
*
* @return FlagBag<\BackedEnum>
*/
protected function createEnum(int|array $value): FlagBag
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class FlagBagToCollectionTransformer extends AbstractFlagBagTransformer
/**
* Transforms a FlagBag objects to an array of BackedEnum
*
* @param FlagBag $value A FlagBag instance
* @param FlagBag<\BackedEnum> $value A FlagBag instance
*
* @throws TransformationFailedException When the transformation fails
*
Expand Down Expand Up @@ -58,7 +58,7 @@ public function transform($value): ?array
*
* @throws TransformationFailedException When the transformation fails
*
* @return FlagBag|null A single FlagBag instance or null
* @return FlagBag<\BackedEnum>|null A single FlagBag instance or null
*/
public function reverseTransform($values): ?FlagBag
{
Expand Down
7 changes: 7 additions & 0 deletions src/Bridge/Symfony/Form/Type/FlagBagType.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
));
}

if (!\is_string($options['class']) || !is_subclass_of($options['class'], \BackedEnum::class)) {
throw new InvalidConfigurationException(sprintf(
'The "class" option of the "%s" form type must contains the FQCN of a BackedEnum.',
static::class
));
}

$builder->addModelTransformer(new FlagBagToCollectionTransformer($options['class']));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function resolveValues(Request $request, ArgumentMetadata $argument): array
$bag = match (true) {
$from instanceof BackedEnumFromQuery => $request->query,
$from instanceof BackedEnumFromBody => $request->request,
default => throw new \LogicException(sprintf('Unexpected attribute class "%s"', get_debug_type($from))),
};

if (!$bag->has($key)) {
Expand Down
5 changes: 4 additions & 1 deletion src/Bridge/Symfony/VarDumper/Caster/FlagBagCaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

final class FlagBagCaster
{
public static function cast(FlagBag $bag)
/**
* @param FlagBag<\BackedEnum> $bag
*/
public static function cast(FlagBag $bag): array
{
$a = [];

Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/VarDumper/Caster/ReadableEnumCaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

final class ReadableEnumCaster
{
public static function cast(ReadableEnumInterface $enum, $array)
public static function cast(ReadableEnumInterface $enum, array $array): array
{
return $array + [
// Append the readable value;
Expand Down
Loading

0 comments on commit d555de9

Please sign in to comment.