diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index cba02f2..69a1933 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -4,21 +4,14 @@ on: - 1.x pull_request: name: Qa workflow +env: + phiveGPGKeys: 4AA394086372C20A,D2CCAC42F6295E7D,E82B2FB314E9906E,8A03EA3B385DBAA1 jobs: - setup: + composer-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Restore/cache tools folder - uses: actions/cache@v2 - with: - path: tools - key: all-tools-${{ github.sha }} - restore-keys: | - all-tools-${{ github.sha }}- - all-tools- - - name: composer uses: docker://composer env: @@ -33,16 +26,9 @@ jobs: with: args: check --config-file ./composer-require-config.json composer.json - - name: Install phive - run: make install-phive - - - name: Install PHAR dependencies - run: tools/phive.phar --no-progress install --copy --trust-gpg-keys 4AA394086372C20A,8A03EA3B385DBAA1 --force-accept-unsigned - phpunit-with-coverage: runs-on: ubuntu-latest name: Unit tests - needs: setup steps: - uses: actions/checkout@v2 @@ -52,27 +38,17 @@ jobs: php-version: 7.2 ini-values: memory_limit=2G, display_errors=On, error_reporting=-1 coverage: pcov + tools: phive - - name: Restore/cache tools folder - uses: actions/cache@v2 - with: - path: tools - key: all-tools-${{ github.sha }} - restore-keys: | - all-tools-${{ github.sha }}- - all-tools- + - name: Install PHAR dependencies + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: phive --no-progress install --copy --trust-gpg-keys ${{ env.phiveGPGKeys }} --force-accept-unsigned - name: Get composer cache directory id: composer-cache run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache composer dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ubuntu-latest-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ubuntu-latest-composer- - - name: Install Composer dependencies run: | composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader @@ -81,60 +57,72 @@ jobs: run: php tools/phpunit phpunit: + name: Unit tests for PHP version ${{ matrix.php-versions }} on ${{ matrix.operating-system }} runs-on: ${{ matrix.operating-system }} + continue-on-error: ${{ matrix.php-versions == '8.1' }} strategy: matrix: operating-system: - ubuntu-latest - windows-latest - macOS-latest - php-versions: ['7.2', '7.3', '7.4', '8.0'] - name: Unit tests for PHP version ${{ matrix.php-versions }} on ${{ matrix.operating-system }} + php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1'] + env: + extensions: mbstring + key: cache-v1 # can be any string, change to clear the extension cache. + needs: - - setup - phpunit-with-coverage + steps: - uses: actions/checkout@v2 - - name: Restore/cache vendor folder - uses: actions/cache@v2 + - name: Setup cache environment + id: cache-env + uses: shivammathur/cache-extensions@v1 with: - path: vendor - key: all-build-${{ hashFiles('**/composer.lock') }} - restore-keys: | - all-build-${{ hashFiles('**/composer.lock') }} - all-build- + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} - - name: Restore/cache tools folder + - name: Cache extensions uses: actions/cache@v2 with: - path: tools - key: all-tools-${{ github.sha }} - restore-keys: | - all-tools-${{ github.sha }}- - all-tools- + path: ${{ steps.cache-env.outputs.dir }} + key: ${{ steps.cache-env.outputs.key }} - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} ini-values: memory_limit=2G, display_errors=On, error_reporting=-1 - coverage: none + tools: phive + + - name: Install PHAR dependencies + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: phive --no-progress install --copy --trust-gpg-keys ${{ env.phiveGPGKeys }} --force-accept-unsigned + + - name: Install phpunit 8 for php 7.2 + if: matrix.php-versions == '7.2' + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: phive --no-progress install --copy --trust-gpg-keys ${{ env.phiveGPGKeys }} phpunit:^8.5 - name: Get composer cache directory id: composer-cache run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache composer dependencies + - name: Cache dependencies uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Install Composer dependencies - run: | - composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + - name: Install dependencies + run: composer install --no-interaction --prefer-dist --optimize-autoloader - name: Run PHPUnit continue-on-error: true @@ -142,9 +130,15 @@ jobs: codestyle: runs-on: ubuntu-latest - needs: [setup, phpunit] + needs: [phpunit] steps: - uses: actions/checkout@v2 + - name: composer + uses: docker://composer + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: install --no-interaction --prefer-dist --optimize-autoloader - name: Restore/cache vendor folder uses: actions/cache@v2 with: @@ -160,64 +154,93 @@ jobs: phpstan: runs-on: ubuntu-latest - needs: [setup, phpunit] + needs: [phpunit] steps: - uses: actions/checkout@v2 - - name: Restore/cache vendor folder - uses: actions/cache@v2 + - name: composer + uses: docker://composer + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - path: vendor - key: all-build-${{ hashFiles('**/composer.lock') }} - restore-keys: | - all-build-${{ hashFiles('**/composer.lock') }} - all-build- + args: install --no-interaction --prefer-dist --optimize-autoloader + - name: PHPStan - uses: phpDocumentor/phpstan-ga@master + uses: phpDocumentor/phpstan-ga@0.12.9 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: args: analyse src --configuration phpstan.neon psalm: - runs-on: ubuntu-latest - needs: [setup, phpunit] + name: Psalm + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: + - ubuntu-latest + php-versions: ['7.3'] + env: + extensions: mbstring + key: cache-v1 # can be any string, change to clear the extension cache. + + needs: + - phpunit + steps: - uses: actions/checkout@v2 + - name: Setup cache environment + id: cache-env + uses: shivammathur/cache-extensions@v1 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} + + - name: Cache extensions + uses: actions/cache@v2 + with: + path: ${{ steps.cache-env.outputs.dir }} + key: ${{ steps.cache-env.outputs.key }} + - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} ini-values: memory_limit=2G, display_errors=On, error_reporting=-1 - tools: psalm - coverage: none - name: Get composer cache directory id: composer-cache run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Cache composer dependencies + - name: Cache dependencies uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Install Composer dependencies - run: | - composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + - name: Install dependencies + run: composer install --no-interaction --prefer-dist --optimize-autoloader - - name: Psalm - run: psalm --output-format=github + - name: Run psalm + run: vendor/bin/psalm.phar bc_check: name: BC Check runs-on: ubuntu-latest - needs: [setup, phpunit] + needs: [phpunit] steps: - uses: actions/checkout@v2 - name: fetch tags run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* + - name: composer + uses: docker://composer + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: install --no-interaction --prefer-dist --optimize-autoloader - name: Restore/cache vendor folder uses: actions/cache@v2 with: @@ -232,7 +255,7 @@ jobs: profile: runs-on: ubuntu-latest name: profile - needs: [setup, phpunit] + needs: [phpunit] services: blackfire: image: blackfire/blackfire diff --git a/Makefile b/Makefile index f3e88f2..6dcdf22 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ phpstan: .PHONY: psalm psalm: - docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:7.2 tools/psalm + docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:7.3 vendor/bin/psalm.phar .PHONY: test test: diff --git a/composer.json b/composer.json index 242ecbe..4dbf623 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "*" + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 8fa8b87..63af4fa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ee8aea1f755e1772266bc7e041d8ee5b", + "content-hash": "b9c80334bad7bfa0dec2ff7c530ca3ab", "packages": [ { "name": "phpdocumentor/reflection-common", @@ -56,7 +56,43 @@ "time": "2020-06-27T09:03:43+00:00" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "psalm/phar", + "version": "4.8.1", + "source": { + "type": "git", + "url": "https://github.com/psalm/phar.git", + "reference": "ce0856e5c28a78382d1fa4e1a11cf9aac6292231" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/psalm/phar/zipball/ce0856e5c28a78382d1fa4e1a11cf9aac6292231", + "reference": "ce0856e5c28a78382d1fa4e1a11cf9aac6292231", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "vimeo/psalm": "*" + }, + "bin": [ + "psalm.phar" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer-based Psalm Phar", + "support": { + "issues": "https://github.com/psalm/phar/issues", + "source": "https://github.com/psalm/phar/tree/4.8.1" + }, + "time": "2021-06-21T02:02:58+00:00" + } + ], "aliases": [], "minimum-stability": "stable", "stability-flags": [], @@ -67,5 +103,6 @@ }, "platform-dev": { "ext-tokenizer": "*" - } + }, + "plugin-api-version": "2.1.0" } diff --git a/phive.xml b/phive.xml index de6e4bb..290682a 100644 --- a/phive.xml +++ b/phive.xml @@ -1,5 +1,4 @@ - diff --git a/phpstan.neon b/phpstan.neon index 995090a..22254bc 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,7 +1,2 @@ parameters: level: max - - ignoreErrors: - # Bug in PHPStan? The error is "expects A, A given" - - '#Parameter \#1 \$tokens of method phpDocumentor\\Reflection\\Types\\ContextFactory::parse#' - # ArrayIterator::current can return null if iterated even if ArrayIterator::valid isn't checked before diff --git a/psalm.xml b/psalm.xml index 3cd5541..6723159 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,6 +13,16 @@ + + + + + + + + + + diff --git a/src/TypeResolver.php b/src/TypeResolver.php index 07e1b83..3955f02 100644 --- a/src/TypeResolver.php +++ b/src/TypeResolver.php @@ -348,7 +348,15 @@ public function addKeyword(string $keyword, string $typeClassName) : void ); } - if (!in_array(Type::class, class_implements($typeClassName), true)) { + $interfaces = class_implements($typeClassName); + if ($interfaces === false) { + throw new InvalidArgumentException( + 'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' + . ' but we could not find the class ' . $typeClassName + ); + } + + if (!in_array(Type::class, $interfaces, true)) { throw new InvalidArgumentException( 'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"' ); diff --git a/src/Types/ContextFactory.php b/src/Types/ContextFactory.php index 5d09d56..9430641 100644 --- a/src/Types/ContextFactory.php +++ b/src/Types/ContextFactory.php @@ -108,16 +108,11 @@ private function createFromReflectionParameter(ReflectionParameter $parameter) : throw new InvalidArgumentException('Unable to get class of ' . $parameter->getName()); } - //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable - /** @var ReflectionClass $class */ - return $this->createFromReflectionClass($class); } private function createFromReflectionMethod(ReflectionMethod $method) : Context { - //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable - /** @var ReflectionClass $class */ $class = $method->getDeclaringClass(); return $this->createFromReflectionClass($class); @@ -125,8 +120,6 @@ private function createFromReflectionMethod(ReflectionMethod $method) : Context private function createFromReflectionProperty(ReflectionProperty $property) : Context { - //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable - /** @var ReflectionClass $class */ $class = $property->getDeclaringClass(); return $this->createFromReflectionClass($class); @@ -135,14 +128,14 @@ private function createFromReflectionProperty(ReflectionProperty $property) : Co private function createFromReflectionClassConstant(ReflectionClassConstant $constant) : Context { //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable - /** @var ReflectionClass $class */ + /** @phpstan-var ReflectionClass $class */ $class = $constant->getDeclaringClass(); return $this->createFromReflectionClass($class); } /** - * @param ReflectionClass $class + * @phpstan-param ReflectionClass $class */ private function createFromReflectionClass(ReflectionClass $class) : Context {