diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index c512a3d5..00000000 --- a/.coveralls.yml +++ /dev/null @@ -1,3 +0,0 @@ -service_name: travis-ci -coverage_clover: coverage.xml -json_path: coverage.json diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 00000000..31264fe5 --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,12 @@ +version: 1 +update_configs: + - package_manager: "php:composer" + directory: "/" + update_schedule: "weekly" + automerged_updates: + - match: + dependency_type: "development" + update_type: "all" + - match: + dependency_type: "production" + update_type: "semver:patch" diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 00000000..88e1b424 --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,178 @@ +on: push +name: Qa workflow +jobs: + setup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + - name: composer + uses: docker://composer + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: install --no-interaction --prefer-dist --optimize-autoloader + - name: composer-require-checker + uses: docker://phpga/composer-require-checker-ga + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + 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,D2CCAC42F6295E7D,E82B2FB314E9906E,8E730BA25823D8B5 --force-accept-unsigned + + phpunit-with-coverage: + runs-on: ubuntu-latest + name: Unit tests + needs: setup + steps: + - uses: actions/checkout@master + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + - name: Setup PHP + uses: shivammathur/setup-php@master + with: + php-version: 7.2 + extension-csv: mbstring, intl, iconv, libxml, dom, json, simplexml, zlib + ini-values-csv: memory_limit=2G, display_errors=On, error_reporting=-1 + coverage: xdebug + pecl: false + - name: Run PHPUnit + run: php tools/phpunit + + phpunit: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: + - ubuntu-latest + - windows-latest + - macOS-latest + php-versions: ['7.2', '7.3', '7.4'] + name: Unit tests for PHP version ${{ matrix.php-versions }} on ${{ matrix.operating-system }} + needs: + - setup + - phpunit-with-coverage + steps: + - uses: actions/checkout@master + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + - name: Setup PHP + uses: shivammathur/setup-php@master + with: + php-version: ${{ matrix.php-versions }} + extension-csv: mbstring, intl, iconv, libxml, dom, json, simplexml, zlib + ini-values-csv: memory_limit=2G, display_errors=On, error_reporting=-1 + pecl: false + - name: Run PHPUnit + continue-on-error: true + run: php tools/phpunit + + codestyle: + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@master + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Code style check + uses: phpDocumentor/coding-standard@v1.0.0 + with: + args: -s + + phpstan: + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@master + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: PHPStan + uses: phpDocumentor/phpstan-ga@0.12.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: analyse src --level max --configuration phpstan.neon + + psalm: + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@master + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + - name: Psalm + uses: docker://mickaelandrieu/psalm-ga + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index c368807d..4a0e4355 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,17 @@ +# IDE Shizzle; it is recommended to use a global .gitignore for this but since this is an OSS project we want to make +# it easy to contribute .idea -vendor -/build -/temp +/nbproject/private/ +.buildpath +.project +.settings + +# Build folder and vendor folder are generated code; no need to version this +build/ +temp/ +tools/ +vendor/ +*.phar + +# By default the phpunit.xml.dist is provided; you can override this using a local config file +phpunit.xml diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 00000000..4c5f9511 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,48 @@ +before_commands: + - "composer install --no-dev --prefer-source" + +checks: + php: + excluded_dependencies: + - phpstan/phpstan + +tools: + external_code_coverage: + enabled: true + timeout: 300 + filter: + excluded_paths: ["examples", "tests", "vendor"] + php_code_sniffer: + enabled: true + config: + standard: PSR2 + filter: + paths: ["src/*", "tests/*"] + excluded_paths: [] + php_cpd: + enabled: true + excluded_dirs: ["examples", "tests", "vendor"] + php_cs_fixer: + enabled: true + config: + level: all + filter: + paths: ["src/*", "tests/*"] + php_loc: + enabled: true + excluded_dirs: ["examples", "tests", "vendor"] + php_mess_detector: + enabled: true + config: + ruleset: phpmd.xml.dist + design_rules: { eval_expression: false } + filter: + paths: ["src/*"] + php_pdepend: + enabled: true + excluded_dirs: ["examples", "tests", "vendor"] + php_analyzer: + enabled: true + filter: + paths: ["src/*", "tests/*"] + sensiolabs_security_checker: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 87225891..00000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -language: php - -php: - - 7.0 - - 7.1 - - 7.2 - -matrix: - include: - - php: 7.1 - env: STATIC_ANALYSIS=true - -cache: - directories: - - $HOME/.composer/cache - -install: - - composer install --no-interaction - # coding style - - if [[ $STATIC_ANALYSIS != "" ]]; then composer create-project symplify/easy-coding-standard temp/ecs; fi - -script: - - vendor/bin/phpunit --coverage-clover=coverage.xml -v - # coding style - - if [[ $STATIC_ANALYSIS != "" ]]; then temp/ecs/bin/ecs check src tests; fi - -after_script: - - wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar; - - php coveralls.phar --verbose; - -notifications: - irc: "irc.freenode.org#phpdocumentor" - email: - - mike.vanriel@naenius.com - - ashnazg@php.net - - boen.robot@gmail.com diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..bdeae3d8 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +.PHONY: install-phive +install-phive: + mkdir tools; \ + wget -O tools/phive.phar https://phar.io/releases/phive.phar; \ + wget -O tools/phive.phar.asc https://phar.io/releases/phive.phar.asc; \ + gpg --keyserver pool.sks-keyservers.net --recv-keys 0x9D8A98B29B2D5D79; \ + gpg --verify tools/phive.phar.asc tools/phive.phar; \ + chmod +x tools/phive.phar + +.PHONY: setup +setup: install-phive + docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phar-ga:latest php tools/phive.phar install --force-accept-unsigned + +.PHONY: phpcs +phpcs: + docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpcs-ga:v1.0.0 -s + +.PHONY: phpcbf +phpcbf: + docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpcs-ga:v1.0.0 phpcbf + +.PHONY: phpstan +phpstan: + docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpstan-ga:latest analyse src --no-progress --level max --configuration phpstan.neon + +.PHONY: psaml +psalm: + docker run -it --rm -v${PWD}:/opt/project -w /opt/project mickaelandrieu/psalm-ga + +.PHONY: test +test: + docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:7.4-pcov tools/phpunit + +.PHONY: pre-commit-test +pre-commit-test: test phpcs phpstan psalm + diff --git a/README.md b/README.md index 5a7d326d..51f10883 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ -The ReflectionDocBlock Component [![Build Status](https://secure.travis-ci.org/phpDocumentor/ReflectionDocBlock.png)](https://travis-ci.org/phpDocumentor/ReflectionDocBlock) -================================ +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +![Qa workflow](https://github.com/phpDocumentor/ReflectionDocBlock/workflows/Qa%20workflow/badge.svg) +[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionDocBlock.svg)](https://coveralls.io/github/phpDocumentor/ReflectionDocBlock?branch=master) +[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master) +[![Stable Version](https://img.shields.io/packagist/v/phpdocumentor/reflection-docblock.svg)](https://packagist.org/packages/phpdocumentor/reflection-docblock) +[![Unstable Version](https://img.shields.io/packagist/vpre/phpdocumentor/reflection-docblock.svg)](https://packagist.org/packages/phpdocumentor/reflection-docblock) + +ReflectionDocBlock +================== Introduction ------------ @@ -27,8 +35,8 @@ instantiated using its `createInstance` factory method like this: $factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance(); ``` -Then we can use the `create` method of the factory to interpret the DocBlock. -Please note that it is also possible to provide a class that has the +Then we can use the `create` method of the factory to interpret the DocBlock. +Please note that it is also possible to provide a class that has the `getDocComment()` method, such as an object of type `ReflectionClass`, the create method will read that if it exists. diff --git a/composer-require-config.json b/composer-require-config.json new file mode 100644 index 00000000..19eee4ff --- /dev/null +++ b/composer-require-config.json @@ -0,0 +1,15 @@ +{ + "symbol-whitelist" : [ + "null", "true", "false", + "static", "self", "parent", + "array", "string", "int", "float", "bool", "iterable", "callable", "void", "object", "XSLTProcessor" + ], + "php-core-extensions" : [ + "Core", + "pcre", + "Reflection", + "tokenizer", + "SPL", + "standard" + ] +} diff --git a/composer.json b/composer.json index e3dc38a9..008f1d86 100644 --- a/composer.json +++ b/composer.json @@ -1,34 +1,42 @@ { - "name": "phpdocumentor/reflection-docblock", + "name": "phpdocumentor/reflection-docblock", "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "type": "library", + "type": "library", "license": "MIT", "authors": [ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "php": "^7.2", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1", + "phpdocumentor/reflection-common": "^2.0", + "ext-filter": "^7.1" + }, + "require-dev": { + "mockery/mockery": "^1", + "doctrine/instantiator": "^1" }, "autoload": { - "psr-4": {"phpDocumentor\\Reflection\\": ["src/"]} + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } }, "autoload-dev": { - "psr-4": {"phpDocumentor\\Reflection\\": ["tests/unit"]} - }, - "require-dev": { - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4", - "doctrine/instantiator": "~1.0.5" + "psr-4": { + "phpDocumentor\\Reflection\\": "tests/unit" + } }, "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } } } diff --git a/composer.lock b/composer.lock index 4589e702..14b2b0bb 100644 --- a/composer.lock +++ b/composer.lock @@ -1,42 +1,40 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f69122debe760b39f6a8eb6eb737b30a", + "content-hash": "2f0301d81fbb8c707a619b4e2bdb3a9c", "packages": [ { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "~6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -58,41 +56,40 @@ "reflection", "static analysis" ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2018-08-07T13:53:10+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -105,35 +102,92 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" }, { - "name": "webmozart/assert", - "version": "1.2.0", + "name": "symfony/polyfill-ctype", + "version": "v1.11.0", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "82ebae02209c21113908c229e9883c419720738a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=5.3.3" }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-02-06T07:57:58+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "vimeo/psalm": "<3.6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, + "type": "library", "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -155,38 +209,40 @@ "check", "validate" ], - "time": "2016-11-23T20:04:58+00:00" + "time": "2019-11-24T13:36:37+00:00" } ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -206,12 +262,12 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2019-10-21T16:45:58+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -263,16 +319,16 @@ }, { "name": "mockery/mockery", - "version": "1.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "1bac8c362b12f522fdd1f1fa3556284c91affa38" + "reference": "f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/1bac8c362b12f522fdd1f1fa3556284c91affa38", - "reference": "1bac8c362b12f522fdd1f1fa3556284c91affa38", + "url": "https://api.github.com/repos/mockery/mockery/zipball/f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be", + "reference": "f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be", "shasum": "" }, "require": { @@ -281,12 +337,12 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "~5.7|~6.1" + "phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -310,8 +366,8 @@ "homepage": "http://davedevelopment.co.uk" } ], - "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", - "homepage": "http://github.com/mockery/mockery", + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", "keywords": [ "BDD", "TDD", @@ -324,1209 +380,7 @@ "test double", "testing" ], - "time": "2017-10-06T16:20:43+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.7.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2017-10-19T19:58:43+00:00" - }, - { - "name": "phar-io/manifest", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^1.0.1", - "php": "^5.6 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" - }, - { - "name": "phar-io/version", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.7.2", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2017-09-04T11:05:03+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "5.2.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d", - "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^7.0", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" - }, - "require-dev": { - "ext-xdebug": "^2.5", - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-xdebug": "^2.5.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2017-11-03T13:47:33+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2016-10-03T07:40:28+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.2.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2017-08-20T05:47:52+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "6.4.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/562f7dc75d46510a4ed5d16189ae57fbe45a9932", - "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", - "php": "^7.0", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.2.2", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^4.0.3", - "sebastian/comparator": "^2.0.2", - "sebastian/diff": "^2.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" - }, - "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-11-08T11:26:09+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.0", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.0" - }, - "conflict": { - "phpunit/phpunit": "<6.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2017-08-03T14:08:16+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" - }, - { - "name": "sebastian/comparator", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1174d9018191e93cb9d719edec01257fc05f8158" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1174d9018191e93cb9d719edec01257fc05f8158", - "reference": "1174d9018191e93cb9d719edec01257fc05f8158", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/diff": "^2.0", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-11-03T07:16:52+00:00" - }, - { - "name": "sebastian/diff", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2017-08-03T08:09:46+00:00" - }, - { - "name": "sebastian/environment", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2017-07-01T08:51:00+00:00" - }, - { - "name": "sebastian/exporter", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2017-04-03T13:19:02+00:00" - }, - { - "name": "sebastian/global-state", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2017-04-27T15:39:26+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "shasum": "" - }, - "require": { - "php": ">=5.6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" + "time": "2019-12-26T09:49:15+00:00" } ], "aliases": [], @@ -1535,7 +389,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.0" + "php": "^7.2", + "ext-filter": "^7.1" }, "platform-dev": [] } diff --git a/easy-coding-standard.neon b/easy-coding-standard.neon deleted file mode 100644 index 7c2ba6e2..00000000 --- a/easy-coding-standard.neon +++ /dev/null @@ -1,31 +0,0 @@ -includes: - - temp/ecs/config/clean-code.neon - - temp/ecs/config/psr2-checkers.neon - - temp/ecs/config/spaces.neon - - temp/ecs/config/common.neon - -checkers: - PhpCsFixer\Fixer\Operator\ConcatSpaceFixer: - spacing: one - -parameters: - exclude_checkers: - # from temp/ecs/config/common.neon - - PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer - - PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer - - PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer - # from temp/ecs/config/spaces.neon - - PhpCsFixer\Fixer\Operator\NotOperatorWithSuccessorSpaceFixer - - skip: - SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff: - # WIP code - - src/DocBlock/StandardTagFactory.php - PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\EmptyStatementSniff: - # WIP code - - src/DocBlock/StandardTagFactory.php - PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff: - - src/DocBlock/Tags/Return_.php - - src/DocBlock/Tags/Var_.php - PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff: - - */tests/** diff --git a/examples/04-adding-your-own-tag.php b/examples/04-adding-your-own-tag.php index 026d6069..e3c5ee6f 100644 --- a/examples/04-adding-your-own-tag.php +++ b/examples/04-adding-your-own-tag.php @@ -83,12 +83,9 @@ public function __construct(Description $description = null) * * @see Tag for the interface declaration of the `create` method. * @see Tag::create() for more information on this method's workings. - * - * @return MyTag */ - public static function create($body, DescriptionFactory $descriptionFactory = null, Context $context = null) + public static function create(string $body, DescriptionFactory $descriptionFactory = null, Context $context = null): MyTag { - Assert::string($body); Assert::notNull($descriptionFactory); return new static($descriptionFactory->create($body, $context)); @@ -99,10 +96,8 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu * * This method is used to reconstitute a DocBlock into its original form by the {@see Serializer}. It should * feature all parts of the tag so that the serializer can put it back together. - * - * @return string */ - public function __toString() + public function __toString(): string { return (string)$this->description; } diff --git a/phive.xml b/phive.xml new file mode 100644 index 00000000..76a2c6a1 --- /dev/null +++ b/phive.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 00000000..1cb3002e --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,16 @@ + + + The coding standard for phpDocumentor. + + src + tests/unit + */tests/unit/Types/ContextFactoryTest.php + + + + + + + */src/*/Abstract*.php + + diff --git a/phpmd.xml.dist b/phpmd.xml.dist new file mode 100644 index 00000000..9abf85cf --- /dev/null +++ b/phpmd.xml.dist @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + 40 + + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..272dd744 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,8 @@ +includes: + - /composer/vendor/phpstan/phpstan-mockery/extension.neon + - /composer/vendor/phpstan/phpstan-webmozart-assert/extension.neon + +parameters: + ignoreErrors: + # false positive + - '#Method phpDocumentor\Reflection\DocBlock\Tags\Method::filterArguments() should return array but returns array#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1460f9a5..81f914c2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,8 +1,9 @@ ./src/ - - ./vendor/ - diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 00000000..9fedb8ab --- /dev/null +++ b/psalm.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/src/DocBlock.php b/src/DocBlock.php index 46605b78..a5b9f5ce 100644 --- a/src/DocBlock.php +++ b/src/DocBlock.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -21,16 +22,16 @@ final class DocBlock private $summary = ''; /** @var DocBlock\Description The actual description for this docblock. */ - private $description = null; + private $description; /** @var Tag[] An array containing all the tags in this docblock; except inline. */ private $tags = []; - /** @var Types\Context Information about the context of this DocBlock. */ - private $context = null; + /** @var Types\Context|null Information about the context of this DocBlock. */ + private $context; - /** @var Location Information about the location of this DocBlock. */ - private $location = null; + /** @var Location|null Information about the location of this DocBlock. */ + private $location; /** @var bool Is this DocBlock (the start of) a template? */ private $isTemplateStart = false; @@ -39,73 +40,56 @@ final class DocBlock private $isTemplateEnd = false; /** - * @param string $summary - * @param DocBlock\Description $description * @param DocBlock\Tag[] $tags - * @param Types\Context $context The context in which the DocBlock occurs. - * @param Location $location The location within the file that this DocBlock occurs in. - * @param bool $isTemplateStart - * @param bool $isTemplateEnd + * @param Types\Context $context The context in which the DocBlock occurs. + * @param Location $location The location within the file that this DocBlock occurs in. */ public function __construct( - $summary = '', - DocBlock\Description $description = null, + string $summary = '', + ?DocBlock\Description $description = null, array $tags = [], - Types\Context $context = null, - Location $location = null, - $isTemplateStart = false, - $isTemplateEnd = false + ?Types\Context $context = null, + ?Location $location = null, + bool $isTemplateStart = false, + bool $isTemplateEnd = false ) { - Assert::string($summary); - Assert::boolean($isTemplateStart); - Assert::boolean($isTemplateEnd); Assert::allIsInstanceOf($tags, Tag::class); - $this->summary = $summary; + $this->summary = $summary; $this->description = $description ?: new DocBlock\Description(''); foreach ($tags as $tag) { $this->addTag($tag); } - $this->context = $context; + $this->context = $context; $this->location = $location; - $this->isTemplateEnd = $isTemplateEnd; + $this->isTemplateEnd = $isTemplateEnd; $this->isTemplateStart = $isTemplateStart; } - /** - * @return string - */ - public function getSummary() + public function getSummary() : string { return $this->summary; } - /** - * @return DocBlock\Description - */ - public function getDescription() + public function getDescription() : DocBlock\Description { return $this->description; } /** * Returns the current context. - * - * @return Types\Context */ - public function getContext() + public function getContext() : ?Types\Context { return $this->context; } /** * Returns the current location. - * - * @return Location */ - public function getLocation() + public function getLocation() : ?Location { return $this->location; } @@ -128,10 +112,8 @@ public function getLocation() * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). * * @see self::isTemplateEnd() for the check whether a closing marker was provided. - * - * @return boolean */ - public function isTemplateStart() + public function isTemplateStart() : bool { return $this->isTemplateStart; } @@ -140,10 +122,8 @@ public function isTemplateStart() * Returns whether this DocBlock is the end of a Template section. * * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. - * - * @return boolean */ - public function isTemplateEnd() + public function isTemplateEnd() : bool { return $this->isTemplateEnd; } @@ -153,7 +133,7 @@ public function isTemplateEnd() * * @return Tag[] */ - public function getTags() + public function getTags() : array { return $this->tags; } @@ -166,10 +146,8 @@ public function getTags() * * @return Tag[] */ - public function getTagsByName($name) + public function getTagsByName(string $name) : array { - Assert::string($name); - $result = []; /** @var Tag $tag */ @@ -188,13 +166,9 @@ public function getTagsByName($name) * Checks if a tag of a certain type is present in this DocBlock. * * @param string $name Tag name to check for. - * - * @return bool */ - public function hasTag($name) + public function hasTag(string $name) : bool { - Assert::string($name); - /** @var Tag $tag */ foreach ($this->getTags() as $tag) { if ($tag->getName() === $name) { @@ -208,11 +182,9 @@ public function hasTag($name) /** * Remove a tag from this DocBlock. * - * @param Tag $tag The tag to remove. - * - * @return void + * @param Tag $tagToRemove The tag to remove. */ - public function removeTag(Tag $tagToRemove) + public function removeTag(Tag $tagToRemove) : void { foreach ($this->tags as $key => $tag) { if ($tag === $tagToRemove) { @@ -226,10 +198,8 @@ public function removeTag(Tag $tagToRemove) * Adds a tag to this DocBlock. * * @param Tag $tag The tag to add. - * - * @return void */ - private function addTag(Tag $tag) + private function addTag(Tag $tag) : void { $this->tags[] = $tag; } diff --git a/src/DocBlock/Description.php b/src/DocBlock/Description.php index 25a79e00..40299fc3 100644 --- a/src/DocBlock/Description.php +++ b/src/DocBlock/Description.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,7 +15,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\Formatter; use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; -use Webmozart\Assert\Assert; +use function vsprintf; /** * Object representing to description for a DocBlock. @@ -59,15 +60,12 @@ class Description /** * Initializes a Description with its body (template) and a listing of the tags used in the body template. * - * @param string $bodyTemplate * @param Tag[] $tags */ - public function __construct($bodyTemplate, array $tags = []) + public function __construct(string $bodyTemplate, array $tags = []) { - Assert::string($bodyTemplate); - $this->bodyTemplate = $bodyTemplate; - $this->tags = $tags; + $this->tags = $tags; } /** @@ -75,7 +73,7 @@ public function __construct($bodyTemplate, array $tags = []) * * @return Tag[] */ - public function getTags() + public function getTags() : array { return $this->tags; } @@ -83,12 +81,8 @@ public function getTags() /** * Renders this description as a string where the provided formatter will format the tags in the expected string * format. - * - * @param Formatter|null $formatter - * - * @return string */ - public function render(Formatter $formatter = null) + public function render(?Formatter $formatter = null) : string { if ($formatter === null) { $formatter = new PassthroughFormatter(); @@ -104,10 +98,8 @@ public function render(Formatter $formatter = null) /** * Returns a plain string representation of this description. - * - * @return string */ - public function __toString() + public function __toString() : string { return $this->render(); } diff --git a/src/DocBlock/DescriptionFactory.php b/src/DocBlock/DescriptionFactory.php index 48f9c219..267e5af4 100644 --- a/src/DocBlock/DescriptionFactory.php +++ b/src/DocBlock/DescriptionFactory.php @@ -1,18 +1,32 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; +use const PREG_SPLIT_DELIM_CAPTURE; +use function count; +use function explode; +use function implode; +use function ltrim; +use function min; +use function preg_split; +use function str_replace; +use function strlen; +use function strpos; +use function substr; +use function trim; /** * Creates a new Description object given a body of text. @@ -38,8 +52,6 @@ class DescriptionFactory /** * Initializes this factory with the means to construct (inline) tags. - * - * @param TagFactory $tagFactory */ public function __construct(TagFactory $tagFactory) { @@ -48,27 +60,36 @@ public function __construct(TagFactory $tagFactory) /** * Returns the parsed text of this description. - * - * @param string $contents - * @param TypeContext $context - * - * @return Description */ - public function create($contents, TypeContext $context = null) + public function create(string $contents, ?TypeContext $context = null) : Description { - list($text, $tags) = $this->parse($this->lex($contents), $context); + $tokens = $this->lex($contents); + $count = count($tokens); + $tagCount = 0; + $tags = []; - return new Description($text, $tags); + for ($i = 1; $i < $count; $i += 2) { + $tags[] = $this->tagFactory->create($tokens[$i], $context); + $tokens[$i] = '%' . ++$tagCount . '$s'; + } + + //In order to allow "literal" inline tags, the otherwise invalid + //sequence "{@}" is changed to "@", and "{}" is changed to "}". + //"%" is escaped to "%%" because of vsprintf. + //See unit tests for examples. + for ($i = 0; $i < $count; $i += 2) { + $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); + } + + return new Description(implode('', $tokens), $tags); } /** * Strips the contents from superfluous whitespace and splits the description into a series of tokens. * - * @param string $contents - * * @return string[] A series of tokens of which the description text is composed. */ - private function lex($contents) + private function lex(string $contents) : array { $contents = $this->removeSuperfluousStartingWhitespace($contents); @@ -77,7 +98,7 @@ private function lex($contents) return [$contents]; } - return preg_split( + $parts = preg_split( '/\{ # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally. (?!@\}) @@ -103,39 +124,11 @@ private function lex($contents) ) \}/Sux', $contents, - null, + 0, PREG_SPLIT_DELIM_CAPTURE ); - } - - /** - * Parses the stream of tokens in to a new set of tokens containing Tags. - * - * @param string[] $tokens - * @param TypeContext $context - * - * @return string[]|Tag[] - */ - private function parse($tokens, TypeContext $context) - { - $count = count($tokens); - $tagCount = 0; - $tags = []; - - for ($i = 1; $i < $count; $i += 2) { - $tags[] = $this->tagFactory->create($tokens[$i], $context); - $tokens[$i] = '%' . ++$tagCount . '$s'; - } - - //In order to allow "literal" inline tags, the otherwise invalid - //sequence "{@}" is changed to "@", and "{}" is changed to "}". - //"%" is escaped to "%%" because of vsprintf. - //See unit tests for examples. - for ($i = 0; $i < $count; $i += 2) { - $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); - } - - return [implode('', $tokens), $tags]; + Assert::isArray($parts); + return $parts; } /** @@ -151,12 +144,8 @@ private function parse($tokens, TypeContext $context) * * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent * lines and this may cause rendering issues when, for example, using a Markdown converter. - * - * @param string $contents - * - * @return string */ - private function removeSuperfluousStartingWhitespace($contents) + private function removeSuperfluousStartingWhitespace(string $contents) : string { $lines = explode("\n", $contents); @@ -168,7 +157,7 @@ private function removeSuperfluousStartingWhitespace($contents) // determine how many whitespace characters need to be stripped $startingSpaceCount = 9999999; - for ($i = 1; $i < count($lines); $i++) { + for ($i = 1; $i < count($lines); ++$i) { // lines with a no length do not count as they are not indented at all if (strlen(trim($lines[$i])) === 0) { continue; @@ -181,7 +170,7 @@ private function removeSuperfluousStartingWhitespace($contents) // strip the number of spaces from each line if ($startingSpaceCount > 0) { - for ($i = 1; $i < count($lines); $i++) { + for ($i = 1; $i < count($lines); ++$i) { $lines[$i] = substr($lines[$i], $startingSpaceCount); } } diff --git a/src/DocBlock/ExampleFinder.php b/src/DocBlock/ExampleFinder.php index 571ed749..db42be71 100644 --- a/src/DocBlock/ExampleFinder.php +++ b/src/DocBlock/ExampleFinder.php @@ -1,18 +1,28 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlock\Tags\Example; +use const DIRECTORY_SEPARATOR; +use function array_slice; +use function file; +use function getcwd; +use function implode; +use function is_readable; +use function rtrim; +use function sprintf; +use function trim; /** * Class used to find an example file's location based on a given ExampleDescriptor. @@ -27,18 +37,14 @@ class ExampleFinder /** * Attempts to find the example contents for the given descriptor. - * - * @param Example $example - * - * @return string */ - public function find(Example $example) + public function find(Example $example) : string { $filename = $example->getFilePath(); $file = $this->getExampleFileContents($filename); if (!$file) { - return "** File not found : {$filename} **"; + return sprintf('** File not found : %s **', $filename); } return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount())); @@ -46,22 +52,16 @@ public function find(Example $example) /** * Registers the project's root directory where an 'examples' folder can be expected. - * - * @param string $directory - * - * @return void */ - public function setSourceDirectory($directory = '') + public function setSourceDirectory(string $directory = '') : void { $this->sourceDirectory = $directory; } /** * Returns the project's root directory where an 'examples' folder can be expected. - * - * @return string */ - public function getSourceDirectory() + public function getSourceDirectory() : string { return $this->sourceDirectory; } @@ -71,7 +71,7 @@ public function getSourceDirectory() * * @param string[] $directories */ - public function setExampleDirectories(array $directories) + public function setExampleDirectories(array $directories) : void { $this->exampleDirectories = $directories; } @@ -81,7 +81,7 @@ public function setExampleDirectories(array $directories) * * @return string[] */ - public function getExampleDirectories() + public function getExampleDirectories() : array { return $this->exampleDirectories; } @@ -97,11 +97,9 @@ public function getExampleDirectories() * 3. Checks the 'examples' folder in the current working directory for examples * 4. Checks the path relative to the current working directory for the given filename * - * @param string $filename - * - * @return string|null + * @return string[] all lines of the example file */ - private function getExampleFileContents($filename) + private function getExampleFileContents(string $filename) : ?array { $normalizedPath = null; @@ -123,42 +121,30 @@ private function getExampleFileContents($filename) } } - return $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : null; + $lines = $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : false; + return $lines !== false ? $lines : null; } /** * Get example filepath based on the example directory inside your project. - * - * @param string $file - * - * @return string */ - private function getExamplePathFromExampleDirectory($file) + private function getExamplePathFromExampleDirectory(string $file) : string { return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file; } /** * Returns a path to the example file in the given directory.. - * - * @param string $directory - * @param string $file - * - * @return string */ - private function constructExamplePath($directory, $file) + private function constructExamplePath(string $directory, string $file) : string { return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file; } /** * Get example filepath based on sourcecode. - * - * @param string $file - * - * @return string */ - private function getExamplePathFromSource($file) + private function getExamplePathFromSource(string $file) : string { return sprintf( '%s%s%s', diff --git a/src/DocBlock/Serializer.php b/src/DocBlock/Serializer.php index 0f355f58..e8a5c647 100644 --- a/src/DocBlock/Serializer.php +++ b/src/DocBlock/Serializer.php @@ -1,19 +1,26 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlock; -use Webmozart\Assert\Assert; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; +use function sprintf; +use function str_repeat; +use function str_replace; +use function strlen; +use function wordwrap; /** * Converts a DocBlock back from an object to a complete DocComment including Asterisks. @@ -30,33 +37,32 @@ class Serializer protected $isFirstLineIndented = true; /** @var int|null The max length of a line. */ - protected $lineLength = null; + protected $lineLength; - /** @var DocBlock\Tags\Formatter A custom tag formatter. */ - protected $tagFormatter = null; + /** @var Formatter A custom tag formatter. */ + protected $tagFormatter; /** * Create a Serializer instance. * - * @param int $indent The number of times the indent string is repeated. - * @param string $indentString The string to indent the comment with. - * @param bool $indentFirstLine Whether to indent the first line. - * @param int|null $lineLength The max length of a line or NULL to disable line wrapping. - * @param DocBlock\Tags\Formatter $tagFormatter A custom tag formatter, defaults to PassthroughFormatter. + * @param int $indent The number of times the indent string is repeated. + * @param string $indentString The string to indent the comment with. + * @param bool $indentFirstLine Whether to indent the first line. + * @param int|null $lineLength The max length of a line or NULL to disable line wrapping. + * @param Formatter $tagFormatter A custom tag formatter, defaults to PassthroughFormatter. */ - public function __construct($indent = 0, $indentString = ' ', $indentFirstLine = true, $lineLength = null, $tagFormatter = null) - { - Assert::integer($indent); - Assert::string($indentString); - Assert::boolean($indentFirstLine); - Assert::nullOrInteger($lineLength); - Assert::nullOrIsInstanceOf($tagFormatter, 'phpDocumentor\Reflection\DocBlock\Tags\Formatter'); - - $this->indent = $indent; - $this->indentString = $indentString; + public function __construct( + int $indent = 0, + string $indentString = ' ', + bool $indentFirstLine = true, + ?int $lineLength = null, + ?Formatter $tagFormatter = null + ) { + $this->indent = $indent; + $this->indentString = $indentString; $this->isFirstLineIndented = $indentFirstLine; - $this->lineLength = $lineLength; - $this->tagFormatter = $tagFormatter ?: new DocBlock\Tags\Formatter\PassthroughFormatter(); + $this->lineLength = $lineLength; + $this->tagFormatter = $tagFormatter ?: new PassthroughFormatter(); } /** @@ -66,9 +72,9 @@ public function __construct($indent = 0, $indentString = ' ', $indentFirstLine = * * @return string The serialized doc block. */ - public function getDocComment(DocBlock $docblock) + public function getDocComment(DocBlock $docblock) : string { - $indent = str_repeat($this->indentString, $this->indent); + $indent = str_repeat($this->indentString, $this->indent); $firstIndent = $this->isFirstLineIndented ? $indent : ''; // 3 === strlen(' * ') $wrapLength = $this->lineLength ? $this->lineLength - strlen($indent) - 3 : null; @@ -81,46 +87,43 @@ public function getDocComment(DocBlock $docblock) ) ); - $comment = "{$firstIndent}/**\n"; + $comment = $firstIndent . "/**\n"; if ($text) { - $comment .= "{$indent} * {$text}\n"; - $comment .= "{$indent} *\n"; + $comment .= $indent . ' * ' . $text . "\n"; + $comment .= $indent . " *\n"; } $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment); - $comment .= $indent . ' */'; - - return $comment; + return $comment . $indent . ' */'; } /** - * @param $indent - * @param $text * @return mixed */ - private function removeTrailingSpaces($indent, $text) + private function removeTrailingSpaces(string $indent, string $text) { - return str_replace("\n{$indent} * \n", "\n{$indent} *\n", $text); + return str_replace( + sprintf("\n%s * \n", $indent), + sprintf("\n%s *\n", $indent), + $text + ); } /** - * @param $indent - * @param $text * @return mixed */ - private function addAsterisksForEachLine($indent, $text) + private function addAsterisksForEachLine(string $indent, string $text) { - return str_replace("\n", "\n{$indent} * ", $text); + return str_replace( + "\n", + sprintf("\n%s * ", $indent), + $text + ); } - /** - * @param DocBlock $docblock - * @param $wrapLength - * @return string - */ - private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, $wrapLength) + private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, ?int $wrapLength) : string { - $text = $docblock->getSummary() . ((string)$docblock->getDescription() ? "\n\n" . $docblock->getDescription() + $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() : ''); if ($wrapLength !== null) { $text = wordwrap($text, $wrapLength); @@ -130,14 +133,7 @@ private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, $wrapLeng return $text; } - /** - * @param DocBlock $docblock - * @param $wrapLength - * @param $indent - * @param $comment - * @return string - */ - private function addTagBlock(DocBlock $docblock, $wrapLength, $indent, $comment) + private function addTagBlock(DocBlock $docblock, ?int $wrapLength, string $indent, string $comment) : string { foreach ($docblock->getTags() as $tag) { $tagText = $this->tagFormatter->format($tag); @@ -145,9 +141,13 @@ private function addTagBlock(DocBlock $docblock, $wrapLength, $indent, $comment) $tagText = wordwrap($tagText, $wrapLength); } - $tagText = str_replace("\n", "\n{$indent} * ", $tagText); + $tagText = str_replace( + "\n", + sprintf("\n%s * ", $indent), + $tagText + ); - $comment .= "{$indent} * {$tagText}\n"; + $comment .= sprintf("%s * %s\n", $indent, $tagText); } return $comment; diff --git a/src/DocBlock/StandardTagFactory.php b/src/DocBlock/StandardTagFactory.php index 5a8143cf..7b348c7f 100644 --- a/src/DocBlock/StandardTagFactory.php +++ b/src/DocBlock/StandardTagFactory.php @@ -1,22 +1,52 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; +use InvalidArgumentException; +use phpDocumentor\Reflection\DocBlock\Tags\Author; +use phpDocumentor\Reflection\DocBlock\Tags\Covers; +use phpDocumentor\Reflection\DocBlock\Tags\Deprecated; use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod; use phpDocumentor\Reflection\DocBlock\Tags\Generic; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; +use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag; +use phpDocumentor\Reflection\DocBlock\Tags\Method; +use phpDocumentor\Reflection\DocBlock\Tags\Param; +use phpDocumentor\Reflection\DocBlock\Tags\Property; +use phpDocumentor\Reflection\DocBlock\Tags\PropertyRead; +use phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite; +use phpDocumentor\Reflection\DocBlock\Tags\Return_; +use phpDocumentor\Reflection\DocBlock\Tags\See as SeeTag; +use phpDocumentor\Reflection\DocBlock\Tags\Since; +use phpDocumentor\Reflection\DocBlock\Tags\Source; +use phpDocumentor\Reflection\DocBlock\Tags\Throws; +use phpDocumentor\Reflection\DocBlock\Tags\Uses; +use phpDocumentor\Reflection\DocBlock\Tags\Var_; +use phpDocumentor\Reflection\DocBlock\Tags\Version; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use ReflectionMethod; +use ReflectionParameter; use Webmozart\Assert\Assert; +use function array_merge; +use function array_slice; +use function call_user_func_array; +use function count; +use function get_class; +use function preg_match; +use function strpos; +use function trim; /** * Creates a Tag object given the contents of a tag. @@ -38,41 +68,47 @@ final class StandardTagFactory implements TagFactory { /** PCRE regular expression matching a tag name. */ - const REGEX_TAGNAME = '[\w\-\_\\\\]+'; + public const REGEX_TAGNAME = '[\w\-\_\\\\:]+'; /** - * @var string[] An array with a tag as a key, and an FQCN to a class that handles it as an array value. + * @var string[] An array with a tag as a key, and an + * FQCN to a class that handles it as an array value. */ private $tagHandlerMappings = [ - 'author' => '\phpDocumentor\Reflection\DocBlock\Tags\Author', - 'covers' => '\phpDocumentor\Reflection\DocBlock\Tags\Covers', - 'deprecated' => '\phpDocumentor\Reflection\DocBlock\Tags\Deprecated', + 'author' => Author::class, + 'covers' => Covers::class, + 'deprecated' => Deprecated::class, // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example', - 'link' => '\phpDocumentor\Reflection\DocBlock\Tags\Link', - 'method' => '\phpDocumentor\Reflection\DocBlock\Tags\Method', - 'param' => '\phpDocumentor\Reflection\DocBlock\Tags\Param', - 'property-read' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead', - 'property' => '\phpDocumentor\Reflection\DocBlock\Tags\Property', - 'property-write' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite', - 'return' => '\phpDocumentor\Reflection\DocBlock\Tags\Return_', - 'see' => '\phpDocumentor\Reflection\DocBlock\Tags\See', - 'since' => '\phpDocumentor\Reflection\DocBlock\Tags\Since', - 'source' => '\phpDocumentor\Reflection\DocBlock\Tags\Source', - 'throw' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', - 'throws' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', - 'uses' => '\phpDocumentor\Reflection\DocBlock\Tags\Uses', - 'var' => '\phpDocumentor\Reflection\DocBlock\Tags\Var_', - 'version' => '\phpDocumentor\Reflection\DocBlock\Tags\Version' + 'link' => LinkTag::class, + 'method' => Method::class, + 'param' => Param::class, + 'property-read' => PropertyRead::class, + 'property' => Property::class, + 'property-write' => PropertyWrite::class, + 'return' => Return_::class, + 'see' => SeeTag::class, + 'since' => Since::class, + 'source' => Source::class, + 'throw' => Throws::class, + 'throws' => Throws::class, + 'uses' => Uses::class, + 'var' => Var_::class, + 'version' => Version::class, ]; /** - * @var \ReflectionParameter[][] a lazy-loading cache containing parameters for each tagHandler that has been used. + * @var string[] An array with a anotation s a key, and an + * FQCN to a class that handles it as an array value. */ - private $tagHandlerParameterCache = []; + private $annotationMappings = []; /** - * @var FqsenResolver + * @var ReflectionParameter[][] a lazy-loading cache containing parameters + * for each tagHandler that has been used. */ + private $tagHandlerParameterCache = []; + + /** @var FqsenResolver */ private $fqsenResolver; /** @@ -87,12 +123,11 @@ final class StandardTagFactory implements TagFactory * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property * is used. * - * @param FqsenResolver $fqsenResolver - * @param string[] $tagHandlers - * * @see self::registerTagHandler() to add a new tag handler to the existing default list. + * + * @param string[] $tagHandlers */ - public function __construct(FqsenResolver $fqsenResolver, array $tagHandlers = null) + public function __construct(FqsenResolver $fqsenResolver, ?array $tagHandlers = null) { $this->fqsenResolver = $fqsenResolver; if ($tagHandlers !== null) { @@ -105,27 +140,21 @@ public function __construct(FqsenResolver $fqsenResolver, array $tagHandlers = n /** * {@inheritDoc} */ - public function create($tagLine, TypeContext $context = null) + public function create(string $tagLine, ?TypeContext $context = null) : Tag { - if (! $context) { + if (!$context) { $context = new TypeContext(''); } - list($tagName, $tagBody) = $this->extractTagParts($tagLine); + [$tagName, $tagBody] = $this->extractTagParts($tagLine); - if ($tagBody !== '' && $tagBody[0] === '[') { - throw new \InvalidArgumentException( - 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' - ); - } - - return $this->createTag($tagBody, $tagName, $context); + return $this->createTag(trim($tagBody), $tagName, $context); } /** * {@inheritDoc} */ - public function addParameter($name, $value) + public function addParameter(string $name, $value) : void { $this->serviceLocator[$name] = $value; } @@ -133,7 +162,7 @@ public function addParameter($name, $value) /** * {@inheritDoc} */ - public function addService($service, $alias = null) + public function addService(object $service, ?string $alias = null) : void { $this->serviceLocator[$alias ?: get_class($service)] = $service; } @@ -141,15 +170,15 @@ public function addService($service, $alias = null) /** * {@inheritDoc} */ - public function registerTagHandler($tagName, $handler) + public function registerTagHandler(string $tagName, string $handler) : void { Assert::stringNotEmpty($tagName); - Assert::stringNotEmpty($handler); Assert::classExists($handler); + /** @var object $handler stupid hack to make phpstan happy. */ Assert::implementsInterface($handler, StaticMethod::class); if (strpos($tagName, '\\') && $tagName[0] !== '\\') { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'A namespaced tag must have a leading backslash as it must be fully qualified' ); } @@ -160,15 +189,13 @@ public function registerTagHandler($tagName, $handler) /** * Extracts all components for a tag. * - * @param string $tagLine - * * @return string[] */ - private function extractTagParts($tagLine) + private function extractTagParts(string $tagLine) : array { $matches = []; - if (! preg_match('/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)/us', $tagLine, $matches)) { - throw new \InvalidArgumentException( + if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\s\(\{])\s*([^\s].*)|$)/us', $tagLine, $matches)) { + throw new InvalidArgumentException( 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' ); } @@ -183,14 +210,8 @@ private function extractTagParts($tagLine) /** * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the * body was invalid. - * - * @param string $body - * @param string $name - * @param TypeContext $context - * - * @return Tag|null */ - private function createTag($body, $name, TypeContext $context) + private function createTag(string $body, string $name, TypeContext $context) : Tag { $handlerClassName = $this->findHandlerClassName($name, $context); $arguments = $this->getArgumentsForParametersFromWiring( @@ -198,28 +219,30 @@ private function createTag($body, $name, TypeContext $context) $this->getServiceLocatorWithDynamicParameters($context, $name, $body) ); - return call_user_func_array([$handlerClassName, 'create'], $arguments); + try { + /** @var callable $callable */ + $callable = [$handlerClassName, 'create']; + $tag = call_user_func_array($callable, $arguments); + return $tag ?? InvalidTag::create($body, $name); + } catch (InvalidArgumentException $e) { + return InvalidTag::create($body, $name)->withError($e); + } } /** * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). - * - * @param string $tagName - * @param TypeContext $context - * - * @return string */ - private function findHandlerClassName($tagName, TypeContext $context) + private function findHandlerClassName(string $tagName, TypeContext $context) : string { $handlerClassName = Generic::class; if (isset($this->tagHandlerMappings[$tagName])) { $handlerClassName = $this->tagHandlerMappings[$tagName]; } elseif ($this->isAnnotation($tagName)) { // TODO: Annotation support is planned for a later stage and as such is disabled for now - // $tagName = (string)$this->fqsenResolver->resolve($tagName, $context); - // if (isset($this->annotationMappings[$tagName])) { - // $handlerClassName = $this->annotationMappings[$tagName]; - // } + $tagName = (string) $this->fqsenResolver->resolve($tagName, $context); + if (isset($this->annotationMappings[$tagName])) { + $handlerClassName = $this->annotationMappings[$tagName]; + } } return $handlerClassName; @@ -228,17 +251,22 @@ private function findHandlerClassName($tagName, TypeContext $context) /** * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters. * - * @param \ReflectionParameter[] $parameters - * @param mixed[] $locator + * @param ReflectionParameter[] $parameters + * @param mixed[] $locator * * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters * is provided with this method. */ - private function getArgumentsForParametersFromWiring($parameters, $locator) + private function getArgumentsForParametersFromWiring(array $parameters, array $locator) : array { $arguments = []; - foreach ($parameters as $index => $parameter) { - $typeHint = $parameter->getClass() ? $parameter->getClass()->getName() : null; + foreach ($parameters as $parameter) { + $class = $parameter->getClass(); + $typeHint = null; + if ($class !== null) { + $typeHint = $class->getName(); + } + if (isset($locator[$typeHint])) { $arguments[] = $locator[$typeHint]; continue; @@ -260,14 +288,12 @@ private function getArgumentsForParametersFromWiring($parameters, $locator) * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given * tag handler class name. * - * @param string $handlerClassName - * - * @return \ReflectionParameter[] + * @return ReflectionParameter[] */ - private function fetchParametersForHandlerFactoryMethod($handlerClassName) + private function fetchParametersForHandlerFactoryMethod(string $handlerClassName) : array { - if (! isset($this->tagHandlerParameterCache[$handlerClassName])) { - $methodReflection = new \ReflectionMethod($handlerClassName, 'create'); + if (!isset($this->tagHandlerParameterCache[$handlerClassName])) { + $methodReflection = new ReflectionMethod($handlerClassName, 'create'); $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters(); } @@ -275,39 +301,39 @@ private function fetchParametersForHandlerFactoryMethod($handlerClassName) } /** - * Returns a copy of this class' Service Locator with added dynamic parameters, such as the tag's name, body and - * Context. + * Returns a copy of this class' Service Locator with added dynamic parameters, + * such as the tag's name, body and Context. * - * @param TypeContext $context The Context (namespace and aliasses) that may be passed and is used to resolve FQSENs. - * @param string $tagName The name of the tag that may be passed onto the factory method of the Tag class. - * @param string $tagBody The body of the tag that may be passed onto the factory method of the Tag class. + * @param TypeContext $context The Context (namespace and aliasses) that may be + * passed and is used to resolve FQSENs. + * @param string $tagName The name of the tag that may be + * passed onto the factory method of the Tag class. + * @param string $tagBody The body of the tag that may be + * passed onto the factory method of the Tag class. * * @return mixed[] */ - private function getServiceLocatorWithDynamicParameters(TypeContext $context, $tagName, $tagBody) - { - $locator = array_merge( + private function getServiceLocatorWithDynamicParameters( + TypeContext $context, + string $tagName, + string $tagBody + ) : array { + return array_merge( $this->serviceLocator, [ - 'name' => $tagName, - 'body' => $tagBody, - TypeContext::class => $context + 'name' => $tagName, + 'body' => $tagBody, + TypeContext::class => $context, ] ); - - return $locator; } /** * Returns whether the given tag belongs to an annotation. * - * @param string $tagContent - * * @todo this method should be populated once we implement Annotation notation support. - * - * @return bool */ - private function isAnnotation($tagContent) + private function isAnnotation(string $tagContent) : bool { // 1. Contains a namespace separator // 2. Contains parenthesis diff --git a/src/DocBlock/Tag.php b/src/DocBlock/Tag.php index e7653678..647f018f 100644 --- a/src/DocBlock/Tag.php +++ b/src/DocBlock/Tag.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,11 +17,14 @@ interface Tag { - public function getName(); + public function getName() : string; - public static function create($body); + /** + * @return Tag|mixed Class that implements Tag + */ + public static function create(string $body); - public function render(Formatter $formatter = null); + public function render(?Formatter $formatter = null) : string; - public function __toString(); + public function __toString() : string; } diff --git a/src/DocBlock/TagFactory.php b/src/DocBlock/TagFactory.php index 3c1d1132..1a2dc893 100644 --- a/src/DocBlock/TagFactory.php +++ b/src/DocBlock/TagFactory.php @@ -1,17 +1,19 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; +use InvalidArgumentException; use phpDocumentor\Reflection\Types\Context as TypeContext; interface TagFactory @@ -34,60 +36,49 @@ interface TagFactory * * These parameters are injected at the last moment and will override any existing parameter with those names. * - * @param string $name - * @param mixed $value - * - * @return void + * @param mixed $value */ - public function addParameter($name, $value); + public function addParameter(string $name, $value) : void; /** - * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided. - * - * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter - * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint. + * Factory method responsible for instantiating the correct sub type. * - * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the - * interface is passed as alias then every time that interface is requested the provided service will be returned. + * @param string $tagLine The text for this tag, including description. * - * @param object $service - * @param string $alias + * @return Tag A new tag object. * - * @return void + * @throws InvalidArgumentException If an invalid tag line was presented. */ - public function addService($service); + public function create(string $tagLine, ?TypeContext $context = null) : Tag; /** - * Factory method responsible for instantiating the correct sub type. - * - * @param string $tagLine The text for this tag, including description. - * @param TypeContext $context + * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided. * - * @throws \InvalidArgumentException if an invalid tag line was presented. + * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter + * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint. * - * @return Tag A new tag object. + * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the + * interface is passed as alias then every time that interface is requested the provided service will be returned. */ - public function create($tagLine, TypeContext $context = null); + public function addService(object $service) : void; /** * Registers a handler for tags. * - * If you want to use your own tags then you can use this method to instruct the TagFactory to register the name - * of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement the {@see Tag} interface (and thus - * the create method). + * If you want to use your own tags then you can use this method to instruct the TagFactory + * to register the name of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement + * the {@see Tag} interface (and thus the create method). * - * @param string $tagName Name of tag to register a handler for. When registering a namespaced tag, the full - * name, along with a prefixing slash MUST be provided. + * @param string $tagName Name of tag to register a handler for. When registering a namespaced tag, + * the full name, along with a prefixing slash MUST be provided. * @param string $handler FQCN of handler. * - * @throws \InvalidArgumentException if the tag name is not a string - * @throws \InvalidArgumentException if the tag name is namespaced (contains backslashes) but does not start with - * a backslash - * @throws \InvalidArgumentException if the handler is not a string - * @throws \InvalidArgumentException if the handler is not an existing class - * @throws \InvalidArgumentException if the handler does not implement the {@see Tag} interface - * - * @return void + * @throws InvalidArgumentException If the tag name is not a string. + * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but + * does not start with a backslash. + * @throws InvalidArgumentException If the handler is not a string. + * @throws InvalidArgumentException If the handler is not an existing class. + * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface. */ - public function registerTagHandler($tagName, $handler); + public function registerTagHandler(string $tagName, string $handler) : void; } diff --git a/src/DocBlock/Tags/Author.php b/src/DocBlock/Tags/Author.php index 29d7f1de..4bebe494 100644 --- a/src/DocBlock/Tags/Author.php +++ b/src/DocBlock/Tags/Author.php @@ -1,18 +1,24 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; -use Webmozart\Assert\Assert; +use InvalidArgumentException; +use const FILTER_VALIDATE_EMAIL; +use function filter_var; +use function preg_match; +use function strlen; +use function trim; /** * Reflection class for an {@}author tag in a Docblock. @@ -30,16 +36,11 @@ final class Author extends BaseTag implements Factory\StaticMethod /** * Initializes this tag with the author name and e-mail. - * - * @param string $authorName - * @param string $authorEmail */ - public function __construct($authorName, $authorEmail) + public function __construct(string $authorName, string $authorEmail) { - Assert::string($authorName); - Assert::string($authorEmail); if ($authorEmail && !filter_var($authorEmail, FILTER_VALIDATE_EMAIL)) { - throw new \InvalidArgumentException('The author tag does not have a valid e-mail address'); + throw new InvalidArgumentException('The author tag does not have a valid e-mail address'); } $this->authorName = $authorName; @@ -51,7 +52,7 @@ public function __construct($authorName, $authorEmail) * * @return string The author's name. */ - public function getAuthorName() + public function getAuthorName() : string { return $this->authorName; } @@ -61,39 +62,31 @@ public function getAuthorName() * * @return string The author's email. */ - public function getEmail() + public function getEmail() : string { return $this->authorEmail; } /** * Returns this tag in string form. - * - * @return string */ - public function __toString() + public function __toString() : string { return $this->authorName . (strlen($this->authorEmail) ? ' <' . $this->authorEmail . '>' : ''); } /** * Attempts to create a new Author object based on †he tag body. - * - * @param string $body - * - * @return static */ - public static function create($body) + public static function create(string $body) : ?self { - Assert::string($body); - $splitTagContent = preg_match('/^([^\<]*)(?:\<([^\>]*)\>)?$/u', $body, $matches); if (!$splitTagContent) { return null; } $authorName = trim($matches[1]); - $email = isset($matches[2]) ? trim($matches[2]) : ''; + $email = isset($matches[2]) ? trim($matches[2]) : ''; return new static($authorName, $email); } diff --git a/src/DocBlock/Tags/BaseTag.php b/src/DocBlock/Tags/BaseTag.php index 14bb7177..fbcd4022 100644 --- a/src/DocBlock/Tags/BaseTag.php +++ b/src/DocBlock/Tags/BaseTag.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -31,17 +32,17 @@ abstract class BaseTag implements DocBlock\Tag * * @return string The name of this tag. */ - public function getName() + public function getName() : string { return $this->name; } - public function getDescription() + public function getDescription() : ?Description { return $this->description; } - public function render(Formatter $formatter = null) + public function render(?Formatter $formatter = null) : string { if ($formatter === null) { $formatter = new Formatter\PassthroughFormatter(); diff --git a/src/DocBlock/Tags/Covers.php b/src/DocBlock/Tags/Covers.php index 8d65403f..5d165f80 100644 --- a/src/DocBlock/Tags/Covers.php +++ b/src/DocBlock/Tags/Covers.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -18,26 +19,25 @@ use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_split; /** * Reflection class for a @covers tag in a Docblock. */ final class Covers extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'covers'; /** @var Fqsen */ - private $refers = null; + private $refers; /** * Initializes this tag. - * - * @param Fqsen $refers - * @param Description $description */ - public function __construct(Fqsen $refers, Description $description = null) + public function __construct(Fqsen $refers, ?Description $description = null) { - $this->refers = $refers; + $this->refers = $refers; $this->description = $description; } @@ -45,38 +45,36 @@ public function __construct(Fqsen $refers, Description $description = null) * {@inheritdoc} */ public static function create( - $body, - DescriptionFactory $descriptionFactory = null, - FqsenResolver $resolver = null, - TypeContext $context = null - ) { - Assert::string($body); + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?FqsenResolver $resolver = null, + ?TypeContext $context = null + ) : self { Assert::notEmpty($body); + Assert::notNull($descriptionFactory); + Assert::notNull($resolver); $parts = preg_split('/\s+/Su', $body, 2); + Assert::isArray($parts); return new static( $resolver->resolve($parts[0], $context), - $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context) + $descriptionFactory->create($parts[1] ?? '', $context) ); } /** * Returns the structural element this tag refers to. - * - * @return Fqsen */ - public function getReference() + public function getReference() : Fqsen { return $this->refers; } /** * Returns a string representation of this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return $this->refers . ($this->description ? ' ' . $this->description->render() : ''); } diff --git a/src/DocBlock/Tags/Deprecated.php b/src/DocBlock/Tags/Deprecated.php index 822c3050..130d8449 100644 --- a/src/DocBlock/Tags/Deprecated.php +++ b/src/DocBlock/Tags/Deprecated.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,19 +17,21 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; /** * Reflection class for a {@}deprecated tag in a Docblock. */ final class Deprecated extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'deprecated'; /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ - const REGEX_VECTOR = '(?: + public const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | @@ -40,23 +43,25 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod [^\s\:]+\:\s*\$[^\$]+\$ )'; - /** @var string The version vector. */ + /** @var string|null The version vector. */ private $version = ''; - public function __construct($version = null, Description $description = null) + public function __construct(?string $version = null, ?Description $description = null) { Assert::nullOrStringNotEmpty($version); - $this->version = $version; + $this->version = $version; $this->description = $description; } /** * @return static */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::nullOrString($body); + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { if (empty($body)) { return new static(); } @@ -65,33 +70,30 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { return new static( null, - null !== $descriptionFactory ? $descriptionFactory->create($body, $context) : null + $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null ); } + Assert::notNull($descriptionFactory); return new static( $matches[1], - $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + $descriptionFactory->create($matches[2] ?? '', $context) ); } /** * Gets the version section of the tag. - * - * @return string */ - public function getVersion() + public function getVersion() : ?string { return $this->version; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { - return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + return ($this->version ?? '') . ($this->description ? ' ' . $this->description->render() : ''); } } diff --git a/src/DocBlock/Tags/Example.php b/src/DocBlock/Tags/Example.php index ecb199b4..d27ed477 100644 --- a/src/DocBlock/Tags/Example.php +++ b/src/DocBlock/Tags/Example.php @@ -1,29 +1,33 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; -use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\Tag; use Webmozart\Assert\Assert; +use function array_key_exists; +use function preg_match; +use function rawurlencode; +use function str_replace; +use function strpos; +use function trim; /** * Reflection class for a {@}example tag in a Docblock. */ -final class Example extends BaseTag +final class Example implements Tag, Factory\StaticMethod { - /** - * @var string Path to a file to use as an example. May also be an absolute URI. - */ + /** @var string Path to a file to use as an example. May also be an absolute URI. */ private $filePath; /** @@ -32,72 +36,72 @@ final class Example extends BaseTag */ private $isURI = false; - /** - * @var int - */ + /** @var int */ private $startingLine; - /** - * @var int - */ + /** @var int */ private $lineCount; - public function __construct($filePath, $isURI, $startingLine, $lineCount, $description) + /** @var string|null */ + private $content; + + public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content) { Assert::notEmpty($filePath); - Assert::integer($startingLine); Assert::greaterThanEq($startingLine, 0); + Assert::greaterThanEq($lineCount, 0); - $this->filePath = $filePath; + $this->filePath = $filePath; $this->startingLine = $startingLine; - $this->lineCount = $lineCount; - $this->name = 'example'; - if ($description !== null) { - $this->description = trim($description); + $this->lineCount = $lineCount; + if ($content !== null) { + $this->content = trim((string) $content); } $this->isURI = $isURI; } - /** - * {@inheritdoc} - */ - public function getContent() + public function getContent() : string { - if (null === $this->description) { + if ($this->content === null) { $filePath = '"' . $this->filePath . '"'; if ($this->isURI) { $filePath = $this->isUriRelative($this->filePath) ? str_replace('%2F', '/', rawurlencode($this->filePath)) - :$this->filePath; + : $this->filePath; } - return trim($filePath . ' ' . parent::getDescription()); + return trim($filePath); } - return $this->description; + return $this->content; + } + + public function getDescription() : ?string + { + return $this->content; } /** * {@inheritdoc} */ - public static function create($body) + public static function create(string $body) : ?Tag { // File component: File path in quotes or File URI / Source information - if (! preg_match('/^(?:\"([^\"]+)\"|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) { + if (!preg_match('/^(?:\"([^\"]+)\"|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) { return null; } $filePath = null; $fileUri = null; - if ('' !== $matches[1]) { + if ($matches[1] !== '') { $filePath = $matches[1]; } else { $fileUri = $matches[2]; } $startingLine = 1; - $lineCount = null; + $lineCount = 0; $description = null; if (array_key_exists(3, $matches)) { @@ -105,9 +109,9 @@ public static function create($body) // Starting line / Number of lines / Description if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) { - $startingLine = (int)$contentMatches[1]; + $startingLine = (int) $contentMatches[1]; if (isset($contentMatches[2]) && $contentMatches[2] !== '') { - $lineCount = (int)$contentMatches[2]; + $lineCount = (int) $contentMatches[2]; } if (array_key_exists(3, $contentMatches)) { @@ -117,7 +121,7 @@ public static function create($body) } return new static( - $filePath !== null?$filePath:$fileUri, + $filePath ?? ($fileUri ?? ''), $fileUri !== null, $startingLine, $lineCount, @@ -131,46 +135,48 @@ public static function create($body) * @return string Path to a file to use as an example. * May also be an absolute URI. */ - public function getFilePath() + public function getFilePath() : string { return $this->filePath; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { - return $this->filePath . ($this->description ? ' ' . $this->description : ''); + return $this->filePath . ($this->content ? ' ' . $this->content : ''); } /** * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute). - * - * @param string $uri - * - * @return bool */ - private function isUriRelative($uri) + private function isUriRelative(string $uri) : bool { - return false === strpos($uri, ':'); + return strpos($uri, ':') === false; } - /** - * @return int - */ - public function getStartingLine() + public function getStartingLine() : int { return $this->startingLine; } - /** - * @return int - */ - public function getLineCount() + public function getLineCount() : int { return $this->lineCount; } + + public function getName() : string + { + return 'example'; + } + + public function render(?Formatter $formatter = null) : string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } } diff --git a/src/DocBlock/Tags/Factory/StaticMethod.php b/src/DocBlock/Tags/Factory/StaticMethod.php index 98aea455..b21a3f02 100644 --- a/src/DocBlock/Tags/Factory/StaticMethod.php +++ b/src/DocBlock/Tags/Factory/StaticMethod.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,5 +15,8 @@ interface StaticMethod { - public static function create($body); + /** + * @return mixed + */ + public static function create(string $body); } diff --git a/src/DocBlock/Tags/Factory/Strategy.php b/src/DocBlock/Tags/Factory/Strategy.php deleted file mode 100644 index b9ca0b8a..00000000 --- a/src/DocBlock/Tags/Factory/Strategy.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org - */ - -namespace phpDocumentor\Reflection\DocBlock\Tags\Factory; - -interface Strategy -{ - public function create($body); -} diff --git a/src/DocBlock/Tags/Formatter.php b/src/DocBlock/Tags/Formatter.php index 64b2c603..92fb9e6c 100644 --- a/src/DocBlock/Tags/Formatter.php +++ b/src/DocBlock/Tags/Formatter.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,10 +19,6 @@ interface Formatter { /** * Formats a tag into a string representation according to a specific format, such as Markdown. - * - * @param Tag $tag - * - * @return string */ - public function format(Tag $tag); + public function format(Tag $tag) : string; } diff --git a/src/DocBlock/Tags/Formatter/AlignFormatter.php b/src/DocBlock/Tags/Formatter/AlignFormatter.php index ceb40cc3..b1a406c0 100644 --- a/src/DocBlock/Tags/Formatter/AlignFormatter.php +++ b/src/DocBlock/Tags/Formatter/AlignFormatter.php @@ -1,13 +1,13 @@ - * @copyright 2017 Mike van Riel - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -15,6 +15,9 @@ use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use function max; +use function str_repeat; +use function strlen; class AlignFormatter implements Formatter { @@ -22,8 +25,6 @@ class AlignFormatter implements Formatter protected $maxLen = 0; /** - * Constructor. - * * @param Tag[] $tags All tags that should later be aligned with the formatter. */ public function __construct(array $tags) @@ -35,13 +36,14 @@ public function __construct(array $tags) /** * Formats the given tag to return a simple plain text version. - * - * @param Tag $tag - * - * @return string */ - public function format(Tag $tag) + public function format(Tag $tag) : string { - return '@' . $tag->getName() . str_repeat(' ', $this->maxLen - strlen($tag->getName()) + 1) . (string)$tag; + return '@' . $tag->getName() . + str_repeat( + ' ', + $this->maxLen - strlen($tag->getName()) + 1 + ) . + $tag; } } diff --git a/src/DocBlock/Tags/Formatter/PassthroughFormatter.php b/src/DocBlock/Tags/Formatter/PassthroughFormatter.php index 4e2c5762..f26d22fb 100644 --- a/src/DocBlock/Tags/Formatter/PassthroughFormatter.php +++ b/src/DocBlock/Tags/Formatter/PassthroughFormatter.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,18 +15,15 @@ use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use function trim; class PassthroughFormatter implements Formatter { /** * Formats the given tag to return a simple plain text version. - * - * @param Tag $tag - * - * @return string */ - public function format(Tag $tag) + public function format(Tag $tag) : string { - return trim('@' . $tag->getName() . ' ' . (string)$tag); + return trim('@' . $tag->getName() . ' ' . $tag); } } diff --git a/src/DocBlock/Tags/Generic.php b/src/DocBlock/Tags/Generic.php index e4c53e00..7509ff1a 100644 --- a/src/DocBlock/Tags/Generic.php +++ b/src/DocBlock/Tags/Generic.php @@ -1,88 +1,79 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; +use InvalidArgumentException; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\DocBlock\StandardTagFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; /** * Parses a tag definition for a DocBlock. */ -class Generic extends BaseTag implements Factory\StaticMethod +final class Generic extends BaseTag implements Factory\StaticMethod { /** * Parses a tag and populates the member variables. * - * @param string $name Name of the tag. + * @param string $name Name of the tag. * @param Description $description The contents of the given tag. */ - public function __construct($name, Description $description = null) + public function __construct(string $name, ?Description $description = null) { $this->validateTagName($name); - $this->name = $name; + $this->name = $name; $this->description = $description; } /** * Creates a new tag that represents any unknown tag type. * - * @param string $body - * @param string $name - * @param DescriptionFactory $descriptionFactory - * @param TypeContext $context - * * @return static */ public static function create( - $body, - $name = '', - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); + string $body, + string $name = '', + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($name); Assert::notNull($descriptionFactory); - $description = $descriptionFactory && $body ? $descriptionFactory->create($body, $context) : null; + $description = $body !== '' ? $descriptionFactory->create($body, $context) : null; return new static($name, $description); } /** * Returns the tag as a serialized string - * - * @return string */ - public function __toString() + public function __toString() : string { - return ($this->description ? $this->description->render() : ''); + return $this->description ? $this->description->render() : ''; } /** * Validates if the tag name matches the expected format, otherwise throws an exception. - * - * @param string $name - * - * @return void */ - private function validateTagName($name) + private function validateTagName(string $name) : void { - if (! preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { - throw new \InvalidArgumentException( + if (!preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { + throw new InvalidArgumentException( 'The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' . 'hyphens and backslashes.' ); diff --git a/src/DocBlock/Tags/InvalidTag.php b/src/DocBlock/Tags/InvalidTag.php new file mode 100644 index 00000000..a531c036 --- /dev/null +++ b/src/DocBlock/Tags/InvalidTag.php @@ -0,0 +1,133 @@ +name = $name; + $this->body = $body; + } + + public function getException() : ?Throwable + { + return $this->throwable; + } + + public function getName() : string + { + return $this->name; + } + + /** + * @return self + * + * @inheritDoc + */ + public static function create(string $body, string $name = '') + { + return new self($name, $body); + } + + public function withError(Throwable $exception) : self + { + $this->flattenExceptionBacktrace($exception); + $tag = new self($this->name, $this->body); + $tag->throwable = $exception; + + return $tag; + } + + /** + * Removes all complex types from backtrace + * + * Not all objects are serializable. So we need to remove them from the + * stored exception to be sure that we do not break existing library usage. + */ + private function flattenExceptionBacktrace(Throwable $exception) : void + { + $traceProperty = (new ReflectionClass('Exception'))->getProperty('trace'); + $traceProperty->setAccessible(true); + + $flatten = + /** @param mixed $value */ + static function (&$value) : void { + if ($value instanceof Closure) { + $closureReflection = new ReflectionFunction($value); + $value = sprintf( + '(Closure at %s:%s)', + $closureReflection->getFileName(), + $closureReflection->getStartLine() + ); + } elseif (is_object($value)) { + $value = sprintf('object(%s)', get_class($value)); + } elseif (is_resource($value)) { + $value = sprintf('resource(%s)', get_resource_type($value)); + } + }; + + do { + $trace = array_map( + static function (array $call) use ($flatten) : array { + array_walk_recursive($call['args'], $flatten); + + return $call; + }, + $exception->getTrace() + ); + $traceProperty->setValue($exception, $trace); + $exception = $exception->getPrevious(); + } while ($exception !== null); + + $traceProperty->setAccessible(false); + } + + public function render(?Formatter $formatter = null) : string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } + + public function __toString() : string + { + return $this->body; + } +} diff --git a/src/DocBlock/Tags/Link.php b/src/DocBlock/Tags/Link.php index 9c0e367e..a50c813a 100644 --- a/src/DocBlock/Tags/Link.php +++ b/src/DocBlock/Tags/Link.php @@ -1,13 +1,14 @@ - * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -16,61 +17,57 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_split; /** * Reflection class for a @link tag in a Docblock. */ final class Link extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'link'; /** @var string */ - private $link = ''; + private $link; /** * Initializes a link to a URL. - * - * @param string $link - * @param Description $description */ - public function __construct($link, Description $description = null) + public function __construct(string $link, ?Description $description = null) { - Assert::string($link); - - $this->link = $link; + $this->link = $link; $this->description = $description; } /** * {@inheritdoc} */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::string($body); + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::notNull($descriptionFactory); $parts = preg_split('/\s+/Su', $body, 2); + Assert::isArray($parts); $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; return new static($parts[0], $description); } /** - * Gets the link - * - * @return string - */ - public function getLink() + * Gets the link + */ + public function getLink() : string { return $this->link; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return $this->link . ($this->description ? ' ' . $this->description->render() : ''); } diff --git a/src/DocBlock/Tags/Method.php b/src/DocBlock/Tags/Method.php index 75225299..c7a00e4d 100644 --- a/src/DocBlock/Tags/Method.php +++ b/src/DocBlock/Tags/Method.php @@ -1,36 +1,50 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; +use InvalidArgumentException; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Types\Mixed_; use phpDocumentor\Reflection\Types\Void_; use Webmozart\Assert\Assert; +use function array_keys; +use function explode; +use function implode; +use function is_string; +use function preg_match; +use function sort; +use function strpos; +use function substr; +use function trim; +use function var_export; /** * Reflection class for an {@}method in a Docblock. */ final class Method extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'method'; /** @var string */ private $methodName = ''; - /** @var string[] */ + /** @var string[][] */ private $arguments = []; /** @var bool */ @@ -39,15 +53,19 @@ final class Method extends BaseTag implements Factory\StaticMethod /** @var Type */ private $returnType; + /** + * @param mixed[][] $arguments + * + * @psalm-param array|string> $arguments + */ public function __construct( - $methodName, + string $methodName, array $arguments = [], - Type $returnType = null, - $static = false, - Description $description = null + ?Type $returnType = null, + bool $static = false, + ?Description $description = null ) { Assert::stringNotEmpty($methodName); - Assert::boolean($static); if ($returnType === null) { $returnType = new Void_(); @@ -64,13 +82,14 @@ public function __construct( * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : ?self { Assert::stringNotEmpty($body); - Assert::allNotNull([ $typeResolver, $descriptionFactory ]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); // 1. none or more whitespace // 2. optionally the keyword "static" followed by whitespace @@ -91,23 +110,19 @@ public static function create( )? # Return type (?: - ( + ( (?:[\w\|_\\\\]*\$this[\w\|_\\\\]*) | (?: (?:[\w\|_\\\\]+) - # array notation + # array notation (?:\[\])* )* ) \s+ )? - # Legacy method name (not captured) - (?: - [\w_]+\(\)\s+ - )? # Method name - ([\w\|_\\\\]+) + ([\w_]+) # Arguments (?: \(([^\)]*)\) @@ -122,9 +137,9 @@ public static function create( return null; } - list(, $static, $returnType, $methodName, $arguments, $description) = $matches; + [, $static, $returnType, $methodName, $arguments, $description] = $matches; - $static = $static === 'static'; + $static = $static === 'static'; if ($returnType === '') { $returnType = 'void'; @@ -133,23 +148,23 @@ public static function create( $returnType = $typeResolver->resolve($returnType, $context); $description = $descriptionFactory->create($description, $context); - if (is_string($arguments) && strlen($arguments) > 0) { + if ($arguments !== '') { $arguments = explode(',', $arguments); foreach ($arguments as &$argument) { $argument = explode(' ', self::stripRestArg(trim($argument)), 2); if ($argument[0][0] === '$') { $argumentName = substr($argument[0], 1); - $argumentType = new Void_(); + $argumentType = new Mixed_(); } else { $argumentType = $typeResolver->resolve($argument[0], $context); $argumentName = ''; if (isset($argument[1])) { - $argument[1] = self::stripRestArg($argument[1]); + $argument[1] = self::stripRestArg($argument[1]); $argumentName = substr($argument[1], 1); } } - $argument = [ 'name' => $argumentName, 'type' => $argumentType]; + $argument = ['name' => $argumentName, 'type' => $argumentType]; } } else { $arguments = []; @@ -160,18 +175,16 @@ public static function create( /** * Retrieves the method name. - * - * @return string */ - public function getMethodName() + public function getMethodName() : string { return $this->methodName; } /** - * @return string[] + * @return string[][] */ - public function getArguments() + public function getArguments() : array { return $this->arguments; } @@ -181,20 +194,17 @@ public function getArguments() * * @return bool TRUE if the method declaration is for a static method, FALSE otherwise. */ - public function isStatic() + public function isStatic() : bool { return $this->isStatic; } - /** - * @return Type - */ - public function getReturnType() + public function getReturnType() : Type { return $this->returnType; } - public function __toString() + public function __toString() : string { $arguments = []; foreach ($this->arguments as $argument) { @@ -202,36 +212,47 @@ public function __toString() } return trim(($this->isStatic() ? 'static ' : '') - . (string)$this->returnType . ' ' + . (string) $this->returnType . ' ' . $this->methodName . '(' . implode(', ', $arguments) . ')' . ($this->description ? ' ' . $this->description->render() : '')); } - private function filterArguments($arguments) + /** + * @param mixed[][]|string[] $arguments + * + * @return mixed[][] + * + * @psalm-param array|string> $arguments + * @psalm-return array> $arguments + */ + private function filterArguments(array $arguments = []) : array { - foreach ($arguments as &$argument) { + $result = []; + foreach ($arguments as $argument) { if (is_string($argument)) { - $argument = [ 'name' => $argument ]; + $argument = ['name' => $argument]; } - if (! isset($argument['type'])) { - $argument['type'] = new Void_(); + if (!isset($argument['type'])) { + $argument['type'] = new Mixed_(); } $keys = array_keys($argument); sort($keys); - if ($keys !== [ 'name', 'type' ]) { - throw new \InvalidArgumentException( + if ($keys !== ['name', 'type']) { + throw new InvalidArgumentException( 'Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, true) ); } + + $result[] = $argument; } - return $arguments; + return $result; } - private static function stripRestArg($argument) + private static function stripRestArg(string $argument) : string { if (strpos($argument, '...') === 0) { $argument = trim(substr($argument, 3)); diff --git a/src/DocBlock/Tags/Param.php b/src/DocBlock/Tags/Param.php index 7d699d88..658ea973 100644 --- a/src/DocBlock/Tags/Param.php +++ b/src/DocBlock/Tags/Param.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,75 +19,81 @@ use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use const PREG_SPLIT_DELIM_CAPTURE; +use function array_shift; +use function array_unshift; +use function implode; +use function preg_split; +use function strlen; +use function strpos; +use function substr; /** * Reflection class for the {@}param tag in a Docblock. */ -final class Param extends BaseTag implements Factory\StaticMethod +final class Param extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'param'; - - /** @var Type */ - private $type; - - /** @var string */ - private $variableName = ''; + /** @var string|null */ + private $variableName; /** @var bool determines whether this is a variadic argument */ - private $isVariadic = false; - - /** - * @param string $variableName - * @param Type $type - * @param bool $isVariadic - * @param Description $description - */ - public function __construct($variableName, Type $type = null, $isVariadic = false, Description $description = null) - { - Assert::string($variableName); - Assert::boolean($isVariadic); + private $isVariadic; + public function __construct( + ?string $variableName, + ?Type $type = null, + bool $isVariadic = false, + ?Description $description = null + ) { + $this->name = 'param'; $this->variableName = $variableName; - $this->type = $type; - $this->isVariadic = $isVariadic; - $this->description = $description; + $this->type = $type; + $this->isVariadic = $isVariadic; + $this->description = $description; } /** * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + + [$firstPart, $body] = self::extractTypeFromBody($body); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; + $type = null; + $parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; - $isVariadic = false; + $isVariadic = false; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && (strlen($firstPart) > 0) && ($firstPart[0] !== '$')) { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$' || substr($parts[0], 0, 4) === '...$')) { + if (isset($parts[0]) + && (strlen($parts[0]) > 0) + && ($parts[0][0] === '$' || substr($parts[0], 0, 4) === '...$') + ) { $variableName = array_shift($parts); array_shift($parts); - if (substr($variableName, 0, 3) === '...') { - $isVariadic = true; + if ($variableName !== null && strpos($variableName, '...') === 0) { + $isVariadic = true; $variableName = substr($variableName, 3); } - if (substr($variableName, 0, 1) === '$') { + if ($variableName !== null && strpos($variableName, '$') === 0) { $variableName = substr($variableName, 1); } } @@ -98,44 +105,28 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName() : ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns whether this tag is variadic. - * - * @return boolean */ - public function isVariadic() + public function isVariadic() : bool { return $this->isVariadic; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return ($this->type ? $this->type . ' ' : '') - . ($this->isVariadic() ? '...' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . ($this->isVariadic() ? '...' : '') + . ($this->variableName !== null ? '$' . $this->variableName : '') + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/Property.php b/src/DocBlock/Tags/Property.php index f0ef7c07..81bff40c 100644 --- a/src/DocBlock/Tags/Property.php +++ b/src/DocBlock/Tags/Property.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,63 +19,65 @@ use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use const PREG_SPLIT_DELIM_CAPTURE; +use function array_shift; +use function array_unshift; +use function implode; +use function preg_split; +use function strlen; +use function strpos; +use function substr; /** * Reflection class for a {@}property tag in a Docblock. */ -class Property extends BaseTag implements Factory\StaticMethod +final class Property extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property'; - - /** @var Type */ - private $type; - - /** @var string */ + /** @var string|null */ protected $variableName = ''; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'property'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } /** * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; - $variableName = ''; + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); + $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && (strlen($firstPart) > 0) && ($firstPart[0] !== '$')) { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + if (isset($parts[0]) && ($parts[0] !== '') && (strpos($parts[0], '$') === 0)) { $variableName = array_shift($parts); array_shift($parts); - if (substr($variableName, 0, 1) === '$') { + if ($variableName !== null && strpos($variableName, '$') === 0) { $variableName = substr($variableName, 1); } } @@ -86,33 +89,19 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName() : ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . ($this->variableName ? '$' . $this->variableName : '') + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/PropertyRead.php b/src/DocBlock/Tags/PropertyRead.php index e41c0c1c..a1f8c8a5 100644 --- a/src/DocBlock/Tags/PropertyRead.php +++ b/src/DocBlock/Tags/PropertyRead.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,63 +19,65 @@ use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use const PREG_SPLIT_DELIM_CAPTURE; +use function array_shift; +use function array_unshift; +use function implode; +use function preg_split; +use function strlen; +use function strpos; +use function substr; /** * Reflection class for a {@}property-read tag in a Docblock. */ -class PropertyRead extends BaseTag implements Factory\StaticMethod +final class PropertyRead extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property-read'; - - /** @var Type */ - private $type; - - /** @var string */ + /** @var string|null */ protected $variableName = ''; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'property-read'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } /** * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; - $variableName = ''; + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); + $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && (strlen($firstPart) > 0) && ($firstPart[0] !== '$')) { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + if (isset($parts[0]) && ($parts[0] !== '') && (strpos($parts[0], '$') === 0)) { $variableName = array_shift($parts); array_shift($parts); - if (substr($variableName, 0, 1) === '$') { + if ($variableName !== null && strpos($variableName, '$') === 0) { $variableName = substr($variableName, 1); } } @@ -86,33 +89,19 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName() : ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . ($this->variableName ? '$' . $this->variableName : '') + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/PropertyWrite.php b/src/DocBlock/Tags/PropertyWrite.php index cfdb0ed0..ae57fdc3 100644 --- a/src/DocBlock/Tags/PropertyWrite.php +++ b/src/DocBlock/Tags/PropertyWrite.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,55 +19,57 @@ use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use const PREG_SPLIT_DELIM_CAPTURE; +use function array_shift; +use function array_unshift; +use function implode; +use function preg_split; +use function strlen; +use function strpos; +use function substr; /** * Reflection class for a {@}property-write tag in a Docblock. */ -class PropertyWrite extends BaseTag implements Factory\StaticMethod +final class PropertyWrite extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property-write'; - - /** @var Type */ - private $type; - /** @var string */ protected $variableName = ''; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'property-write'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } /** * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; - $variableName = ''; + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); + $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && (strlen($firstPart) > 0) && ($firstPart[0] !== '$')) { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } // if the next item starts with a $ or ...$ it must be the variable name @@ -74,7 +77,7 @@ public static function create( $variableName = array_shift($parts); array_shift($parts); - if (substr($variableName, 0, 1) === '$') { + if ($variableName !== null && strpos($variableName, '$') === 0) { $variableName = substr($variableName, 1); } } @@ -86,33 +89,19 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName() : ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . ($this->variableName ? '$' . $this->variableName : '') + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/Reference/Fqsen.php b/src/DocBlock/Tags/Reference/Fqsen.php index dc7b8b6d..cede74c1 100644 --- a/src/DocBlock/Tags/Reference/Fqsen.php +++ b/src/DocBlock/Tags/Reference/Fqsen.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; @@ -15,18 +16,13 @@ use phpDocumentor\Reflection\Fqsen as RealFqsen; /** - * Fqsen reference used by {@see phpDocumentor\Reflection\DocBlock\Tags\See} + * Fqsen reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See} */ final class Fqsen implements Reference { - /** - * @var RealFqsen - */ + /** @var RealFqsen */ private $fqsen; - /** - * Fqsen constructor. - */ public function __construct(RealFqsen $fqsen) { $this->fqsen = $fqsen; @@ -35,8 +31,8 @@ public function __construct(RealFqsen $fqsen) /** * @return string string representation of the referenced fqsen */ - public function __toString() + public function __toString() : string { - return (string)$this->fqsen; + return (string) $this->fqsen; } } diff --git a/src/DocBlock/Tags/Reference/Reference.php b/src/DocBlock/Tags/Reference/Reference.php index a3ffd24c..5eedcbc3 100644 --- a/src/DocBlock/Tags/Reference/Reference.php +++ b/src/DocBlock/Tags/Reference/Reference.php @@ -1,21 +1,22 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; /** - * Interface for references in {@see phpDocumentor\Reflection\DocBlock\Tags\See} + * Interface for references in {@see \phpDocumentor\Reflection\DocBlock\Tags\See} */ interface Reference { - public function __toString(); + public function __toString() : string; } diff --git a/src/DocBlock/Tags/Reference/Url.php b/src/DocBlock/Tags/Reference/Url.php index 2671d5e1..1b2374b9 100644 --- a/src/DocBlock/Tags/Reference/Url.php +++ b/src/DocBlock/Tags/Reference/Url.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; @@ -15,25 +16,20 @@ use Webmozart\Assert\Assert; /** - * Url reference used by {@see phpDocumentor\Reflection\DocBlock\Tags\See} + * Url reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See} */ final class Url implements Reference { - /** - * @var string - */ + /** @var string */ private $uri; - /** - * Url constructor. - */ - public function __construct($uri) + public function __construct(string $uri) { Assert::stringNotEmpty($uri); $this->uri = $uri; } - public function __toString() + public function __toString() : string { return $this->uri; } diff --git a/src/DocBlock/Tags/Return_.php b/src/DocBlock/Tags/Return_.php index ca5bda70..96808757 100644 --- a/src/DocBlock/Tags/Return_.php +++ b/src/DocBlock/Tags/Return_.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -22,16 +23,12 @@ /** * Reflection class for a {@}return tag in a Docblock. */ -final class Return_ extends BaseTag implements Factory\StaticMethod +final class Return_ extends TagWithType implements Factory\StaticMethod { - protected $name = 'return'; - - /** @var Type */ - private $type; - - public function __construct(Type $type, Description $description = null) + public function __construct(Type $type, ?Description $description = null) { - $this->type = $type; + $this->name = 'return'; + $this->type = $type; $this->description = $description; } @@ -39,34 +36,24 @@ public function __construct(Type $type, Description $description = null) * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + [$type, $description] = self::extractTypeFromBody($body); - $type = $typeResolver->resolve(isset($parts[0]) ? $parts[0] : '', $context); - $description = $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); return new static($type, $description); } - /** - * Returns the type section of the variable. - * - * @return Type - */ - public function getType() - { - return $this->type; - } - - public function __toString() + public function __toString() : string { - return $this->type . ' ' . $this->description; + return ($this->type ?: 'mixed') . ' ' . (string) $this->description; } } diff --git a/src/DocBlock/Tags/See.php b/src/DocBlock/Tags/See.php index 9e9e723b..21d85910 100644 --- a/src/DocBlock/Tags/See.php +++ b/src/DocBlock/Tags/See.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -20,26 +21,26 @@ use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; +use function preg_split; /** * Reflection class for an {@}see tag in a Docblock. */ -class See extends BaseTag implements Factory\StaticMethod +final class See extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'see'; /** @var Reference */ - protected $refers = null; + protected $refers; /** * Initializes this tag. - * - * @param Reference $refers - * @param Description $description */ - public function __construct(Reference $refers, Description $description = null) + public function __construct(Reference $refers, ?Description $description = null) { - $this->refers = $refers; + $this->refers = $refers; $this->description = $description; } @@ -47,15 +48,16 @@ public function __construct(Reference $refers, Description $description = null) * {@inheritdoc} */ public static function create( - $body, - FqsenResolver $resolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$resolver, $descriptionFactory]); + string $body, + ?FqsenResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + $parts = preg_split('/\s+/Su', $body, 2); + Assert::isArray($parts); $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; // https://tools.ietf.org/html/rfc2396#section-3 @@ -63,25 +65,21 @@ public static function create( return new static(new Url($parts[0]), $description); } - return new static(new FqsenRef($resolver->resolve($parts[0], $context)), $description); + return new static(new FqsenRef($typeResolver->resolve($parts[0], $context)), $description); } /** * Returns the ref of this tag. - * - * @return Reference */ - public function getReference() + public function getReference() : Reference { return $this->refers; } /** * Returns a string representation of this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return $this->refers . ($this->description ? ' ' . $this->description->render() : ''); } diff --git a/src/DocBlock/Tags/Since.php b/src/DocBlock/Tags/Since.php index 835fb0dc..31ce54c9 100644 --- a/src/DocBlock/Tags/Since.php +++ b/src/DocBlock/Tags/Since.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,19 +17,21 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; /** * Reflection class for a {@}since tag in a Docblock. */ final class Since extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'since'; /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ - const REGEX_VECTOR = '(?: + public const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | @@ -40,10 +43,10 @@ final class Since extends BaseTag implements Factory\StaticMethod [^\s\:]+\:\s*\$[^\$]+\$ )'; - /** @var string The version vector. */ + /** @var string|null The version vector. */ private $version = ''; - public function __construct($version = null, Description $description = null) + public function __construct(?string $version = null, ?Description $description = null) { Assert::nullOrStringNotEmpty($version); @@ -51,44 +54,40 @@ public function __construct($version = null, Description $description = null) $this->description = $description; } - /** - * @return static - */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::nullOrString($body); + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : ?self { if (empty($body)) { return new static(); } $matches = []; - if (! preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { return null; } + Assert::notNull($descriptionFactory); return new static( $matches[1], - $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + $descriptionFactory->create($matches[2] ?? '', $context) ); } /** * Gets the version section of the tag. - * - * @return string */ - public function getVersion() + public function getVersion() : ?string { return $this->version; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { - return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + return (string) $this->version . ($this->description ? ' ' . (string) $this->description : ''); } } diff --git a/src/DocBlock/Tags/Source.php b/src/DocBlock/Tags/Source.php index 247b1b3b..b678806e 100644 --- a/src/DocBlock/Tags/Source.php +++ b/src/DocBlock/Tags/Source.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,6 +17,7 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; /** * Reflection class for a {@}source tag in a Docblock. @@ -29,23 +31,30 @@ final class Source extends BaseTag implements Factory\StaticMethod private $startingLine = 1; /** @var int|null The number of lines, relative to the starting line. NULL means "to the end". */ - private $lineCount = null; + private $lineCount; - public function __construct($startingLine, $lineCount = null, Description $description = null) + /** + * @param int|string $startingLine should be a to int convertible value + * @param int|string|null $lineCount should be a to int convertible value + */ + public function __construct($startingLine, $lineCount = null, ?Description $description = null) { Assert::integerish($startingLine); Assert::nullOrIntegerish($lineCount); - $this->startingLine = (int)$startingLine; - $this->lineCount = $lineCount !== null ? (int)$lineCount : null; + $this->startingLine = (int) $startingLine; + $this->lineCount = $lineCount !== null ? (int) $lineCount : null; $this->description = $description; } /** * {@inheritdoc} */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($body); Assert::notNull($descriptionFactory); @@ -55,15 +64,15 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu // Starting line / Number of lines / Description if (preg_match('/^([1-9]\d*)\s*(?:((?1))\s+)?(.*)$/sux', $body, $matches)) { - $startingLine = (int)$matches[1]; + $startingLine = (int) $matches[1]; if (isset($matches[2]) && $matches[2] !== '') { - $lineCount = (int)$matches[2]; + $lineCount = (int) $matches[2]; } $description = $matches[3]; } - return new static($startingLine, $lineCount, $descriptionFactory->create($description, $context)); + return new static($startingLine, $lineCount, $descriptionFactory->create($description??'', $context)); } /** @@ -72,7 +81,7 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu * @return int The starting line, relative to the structural element's * location. */ - public function getStartingLine() + public function getStartingLine() : int { return $this->startingLine; } @@ -83,15 +92,15 @@ public function getStartingLine() * @return int|null The number of lines, relative to the starting line. NULL * means "to the end". */ - public function getLineCount() + public function getLineCount() : ?int { return $this->lineCount; } - public function __toString() + public function __toString() : string { return $this->startingLine - . ($this->lineCount !== null ? ' ' . $this->lineCount : '') - . ($this->description ? ' ' . $this->description->render() : ''); + . ($this->lineCount !== null ? ' ' . $this->lineCount : '') + . ($this->description ? ' ' . (string) $this->description : ''); } } diff --git a/src/DocBlock/Tags/TagWithType.php b/src/DocBlock/Tags/TagWithType.php new file mode 100644 index 00000000..9cd485cb --- /dev/null +++ b/src/DocBlock/Tags/TagWithType.php @@ -0,0 +1,65 @@ +type; + } + + /** + * @return string[] + */ + protected static function extractTypeFromBody(string $body) : array + { + $type = ''; + $nestingLevel = 0; + for ($i = 0; $i < strlen($body); $i++) { + $character = $body[$i]; + + if (trim($character) === '' && $nestingLevel === 0) { + break; + } + + $type .= $character; + if (in_array($character, ['<', '(', '[', '{'])) { + $nestingLevel++; + continue; + } + + if (in_array($character, ['>', ')', ']', '}'])) { + $nestingLevel--; + continue; + } + } + + $description = trim(substr($body, strlen($type))); + + return [$type, $description]; + } +} diff --git a/src/DocBlock/Tags/Throws.php b/src/DocBlock/Tags/Throws.php index 349e773b..549883aa 100644 --- a/src/DocBlock/Tags/Throws.php +++ b/src/DocBlock/Tags/Throws.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -22,15 +23,11 @@ /** * Reflection class for a {@}throws tag in a Docblock. */ -final class Throws extends BaseTag implements Factory\StaticMethod +final class Throws extends TagWithType implements Factory\StaticMethod { - protected $name = 'throws'; - - /** @var Type */ - private $type; - - public function __construct(Type $type, Description $description = null) + public function __construct(Type $type, ?Description $description = null) { + $this->name = 'throws'; $this->type = $type; $this->description = $description; } @@ -39,34 +36,24 @@ public function __construct(Type $type, Description $description = null) * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + [$type, $description] = self::extractTypeFromBody($body); - $type = $typeResolver->resolve(isset($parts[0]) ? $parts[0] : '', $context); - $description = $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); return new static($type, $description); } - /** - * Returns the type section of the variable. - * - * @return Type - */ - public function getType() - { - return $this->type; - } - - public function __toString() + public function __toString() : string { - return $this->type . ' ' . $this->description; + return (string) $this->type . ' ' . (string) $this->description; } } diff --git a/src/DocBlock/Tags/Uses.php b/src/DocBlock/Tags/Uses.php index 00dc3e3b..7a69642d 100644 --- a/src/DocBlock/Tags/Uses.php +++ b/src/DocBlock/Tags/Uses.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -18,24 +19,23 @@ use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_split; /** * Reflection class for a {@}uses tag in a Docblock. */ final class Uses extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'uses'; /** @var Fqsen */ - protected $refers = null; + protected $refers; /** * Initializes this tag. - * - * @param Fqsen $refers - * @param Description $description */ - public function __construct(Fqsen $refers, Description $description = null) + public function __construct(Fqsen $refers, ?Description $description = null) { $this->refers = $refers; $this->description = $description; @@ -45,39 +45,37 @@ public function __construct(Fqsen $refers, Description $description = null) * {@inheritdoc} */ public static function create( - $body, - FqsenResolver $resolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$resolver, $descriptionFactory]); + string $body, + ?FqsenResolver $resolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { + Assert::notNull($resolver); + Assert::notNull($descriptionFactory); $parts = preg_split('/\s+/Su', $body, 2); + Assert::isArray($parts); + Assert::allString($parts); return new static( $resolver->resolve($parts[0], $context), - $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context) + $descriptionFactory->create($parts[1] ?? '', $context) ); } /** * Returns the structural element this tag refers to. - * - * @return Fqsen */ - public function getReference() + public function getReference() : Fqsen { return $this->refers; } /** * Returns a string representation of this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { - return $this->refers . ' ' . $this->description->render(); + return $this->refers . ' ' . (string) $this->description; } } diff --git a/src/DocBlock/Tags/Var_.php b/src/DocBlock/Tags/Var_.php index 8907c951..8f1ae426 100644 --- a/src/DocBlock/Tags/Var_.php +++ b/src/DocBlock/Tags/Var_.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,30 +19,28 @@ use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use const PREG_SPLIT_DELIM_CAPTURE; +use function array_shift; +use function array_unshift; +use function implode; +use function preg_split; +use function strlen; +use function strpos; +use function substr; /** * Reflection class for a {@}var tag in a Docblock. */ -class Var_ extends BaseTag implements Factory\StaticMethod +final class Var_ extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'var'; - - /** @var Type */ - private $type; - - /** @var string */ + /** @var string|null */ protected $variableName = ''; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'var'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; @@ -51,30 +50,35 @@ public function __construct($variableName, Type $type = null, Description $descr * {@inheritdoc} */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + + [$firstPart, $body] = self::extractTypeFromBody($body); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $type = null; $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && (strlen($firstPart) > 0) && ($firstPart[0] !== '$')) { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + if (isset($parts[0]) && ($parts[0] !== '') && (strpos($parts[0], '$') === 0)) { $variableName = array_shift($parts); array_shift($parts); - if (substr($variableName, 0, 1) === '$') { + if ($variableName !== null && strpos($variableName, '$') === 0) { $variableName = substr($variableName, 1); } } @@ -86,33 +90,19 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName() : ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { return ($this->type ? $this->type . ' ' : '') - . (empty($this->variableName) ? null : ('$' . $this->variableName)) + . (empty($this->variableName) ? '' : ('$' . $this->variableName)) . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/Version.php b/src/DocBlock/Tags/Version.php index 7bb04207..7fdb590b 100644 --- a/src/DocBlock/Tags/Version.php +++ b/src/DocBlock/Tags/Version.php @@ -1,13 +1,14 @@ - * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -16,19 +17,21 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; /** * Reflection class for a {@}version tag in a Docblock. */ final class Version extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'version'; /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ - const REGEX_VECTOR = '(?: + public const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | @@ -40,23 +43,22 @@ final class Version extends BaseTag implements Factory\StaticMethod [^\s\:]+\:\s*\$[^\$]+\$ )'; - /** @var string The version vector. */ + /** @var string|null The version vector. */ private $version = ''; - public function __construct($version = null, Description $description = null) + public function __construct(?string $version = null, ?Description $description = null) { Assert::nullOrStringNotEmpty($version); - $this->version = $version; + $this->version = $version; $this->description = $description; } - /** - * @return static - */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::nullOrString($body); + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ) : ?self { if (empty($body)) { return new static(); } @@ -66,29 +68,31 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu return null; } + $description = null; + if ($descriptionFactory !== null) { + $description = $descriptionFactory->create($matches[2] ?? '', $context); + } + return new static( $matches[1], - $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + $description ); } /** * Gets the version section of the tag. - * - * @return string */ - public function getVersion() + public function getVersion() : ?string { return $this->version; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString() : string { - return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + return ((string) $this->version) . + ($this->description instanceof Description ? ' ' . $this->description->render() : ''); } } diff --git a/src/DocBlockFactory.php b/src/DocBlockFactory.php index 1bdb8f4d..1e669b5e 100644 --- a/src/DocBlockFactory.php +++ b/src/DocBlockFactory.php @@ -1,22 +1,35 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; +use InvalidArgumentException; +use LogicException; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\DocBlock\StandardTagFactory; -use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\TagFactory; use Webmozart\Assert\Assert; +use function array_shift; +use function count; +use function explode; +use function is_object; +use function method_exists; +use function preg_match; +use function preg_replace; +use function str_replace; +use function strpos; +use function substr; +use function trim; final class DocBlockFactory implements DocBlockFactoryInterface { @@ -28,27 +41,22 @@ final class DocBlockFactory implements DocBlockFactoryInterface /** * Initializes this factory with the required subcontractors. - * - * @param DescriptionFactory $descriptionFactory - * @param TagFactory $tagFactory */ public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory) { $this->descriptionFactory = $descriptionFactory; - $this->tagFactory = $tagFactory; + $this->tagFactory = $tagFactory; } /** * Factory method for easy instantiation. * * @param string[] $additionalTags - * - * @return DocBlockFactory */ - public static function createInstance(array $additionalTags = []) + public static function createInstance(array $additionalTags = []) : self { - $fqsenResolver = new FqsenResolver(); - $tagFactory = new StandardTagFactory($fqsenResolver); + $fqsenResolver = new FqsenResolver(); + $tagFactory = new StandardTagFactory($fqsenResolver); $descriptionFactory = new DescriptionFactory($tagFactory); $tagFactory->addService($descriptionFactory); @@ -65,17 +73,13 @@ public static function createInstance(array $additionalTags = []) /** * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the * getDocComment method (such as a ReflectionClass object). - * @param Types\Context $context - * @param Location $location - * - * @return DocBlock */ - public function create($docblock, Types\Context $context = null, Location $location = null) + public function create($docblock, ?Types\Context $context = null, ?Location $location = null) : DocBlock { if (is_object($docblock)) { if (!method_exists($docblock, 'getDocComment')) { $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; - throw new \InvalidArgumentException($exceptionMessage); + throw new InvalidArgumentException($exceptionMessage); } $docblock = $docblock->getDocComment(); @@ -88,14 +92,13 @@ public function create($docblock, Types\Context $context = null, Location $locat } $parts = $this->splitDocBlock($this->stripDocComment($docblock)); - list($templateMarker, $summary, $description, $tags) = $parts; + + [$templateMarker, $summary, $description, $tags] = $parts; return new DocBlock( $summary, $description ? $this->descriptionFactory->create($description, $context) : null, - array_filter($this->parseTagBlock($tags, $context), function ($tag) { - return $tag instanceof Tag; - }), + $this->parseTagBlock($tags, $context), $context, $location, $templateMarker === '#@+', @@ -103,7 +106,7 @@ public function create($docblock, Types\Context $context = null, Location $locat ); } - public function registerTagHandler($tagName, $handler) + public function registerTagHandler(string $tagName, string $handler) : void { $this->tagFactory->registerTagHandler($tagName, $handler); } @@ -112,12 +115,12 @@ public function registerTagHandler($tagName, $handler) * Strips the asterisks from the DocBlock comment. * * @param string $comment String containing the comment text. - * - * @return string */ - private function stripDocComment($comment) + private function stripDocComment(string $comment) : string { - $comment = trim(preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment)); + /** @var string $comment */ + $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment); + $comment = trim($comment); // reg ex above is not able to remove */ from a single line docblock if (substr($comment, -2) === '*/') { @@ -127,17 +130,19 @@ private function stripDocComment($comment) return str_replace(["\r\n", "\r"], "\n", $comment); } + // phpcs:disable SlevomatCodingStandard.Commenting.ForbiddenAnnotations.AnnotationForbidden /** * Splits the DocBlock into a template marker, summary, description and block of tags. * * @param string $comment Comment to split into the sub-parts. * - * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. + * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + * * @author Mike van Riel for extending the regex with template marker support. * - * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. */ - private function splitDocBlock($comment) + private function splitDocBlock(string $comment) : array { // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the @@ -147,6 +152,7 @@ private function splitDocBlock($comment) } // clears all extra horizontal whitespace from the line endings to prevent parsing issues + /** @var string $comment */ $comment = preg_replace('/\h*$/Sum', '', $comment); /* @@ -176,7 +182,7 @@ private function splitDocBlock($comment) [^\n.]+ (?: (?! \. \n | \n{2} ) # End summary upon a dot followed by newline or two newlines - [\n.] (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line + [\n.]* (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line [^\n.]+ # Include anything else )* \.? @@ -214,20 +220,21 @@ private function splitDocBlock($comment) /** * Creates the tag objects. * - * @param string $tags Tag block to parse. + * @param string $tags Tag block to parse. * @param Types\Context $context Context of the parsed Tag * * @return DocBlock\Tag[] */ - private function parseTagBlock($tags, Types\Context $context) + private function parseTagBlock(string $tags, Types\Context $context) : array { $tags = $this->filterTagBlock($tags); - if (!$tags) { + if ($tags === null) { return []; } - $result = $this->splitTagBlockIntoTagLines($tags); - foreach ($result as $key => $tagLine) { + $result = []; + $lines = $this->splitTagBlockIntoTagLines($tags); + foreach ($lines as $key => $tagLine) { $result[$key] = $this->tagFactory->create(trim($tagLine), $context); } @@ -235,11 +242,9 @@ private function parseTagBlock($tags, Types\Context $context) } /** - * @param string $tags - * * @return string[] */ - private function splitTagBlockIntoTagLines($tags) + private function splitTagBlockIntoTagLines(string $tags) : array { $result = []; foreach (explode("\n", $tags) as $tag_line) { @@ -253,22 +258,18 @@ private function splitTagBlockIntoTagLines($tags) return $result; } - /** - * @param $tags - * @return string - */ - private function filterTagBlock($tags) + private function filterTagBlock(string $tags) : ?string { $tags = trim($tags); if (!$tags) { return null; } - if ('@' !== $tags[0]) { + if ($tags[0] !== '@') { // @codeCoverageIgnoreStart // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that // we didn't foresee. - throw new \LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); + throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); // @codeCoverageIgnoreEnd } diff --git a/src/DocBlockFactoryInterface.php b/src/DocBlockFactoryInterface.php index b3533429..c1619569 100644 --- a/src/DocBlockFactoryInterface.php +++ b/src/DocBlockFactoryInterface.php @@ -1,23 +1,21 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -23,12 +24,12 @@ final class DocblocksWithAnnotationsTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown(): void { m::close(); } - public function testDocblockWithAnnotations() + public function testDocblockWithAnnotations(): void { $docComment = <<create($docComment); $this->assertCount(3, $docblock->getTags()); } + + public function testDocblockWithAnnotationHavingZeroValue(): void + { + $docComment = <<create($docComment); + + $this->assertSame(0, printf('%i', $docblock->getTagsByName('my-tag'))); + } } diff --git a/tests/integration/InterpretingDocBlocksTest.php b/tests/integration/InterpretingDocBlocksTest.php index ce91d382..7ef37ba2 100644 --- a/tests/integration/InterpretingDocBlocksTest.php +++ b/tests/integration/InterpretingDocBlocksTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -27,18 +28,45 @@ class InterpretingDocBlocksTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown(): void { m::close(); } - public function testInterpretingASimpleDocBlock() + public function testInterpretingSummaryWithEllipsis(): void { - /** - * @var DocBlock $docblock - * @var string $summary - * @var Description $description - */ + $docblock = <<create($docblock); + + $summary = 'This is a short (...) description.'; + $description = 'This is a long description.'; + + $this->assertInstanceOf(DocBlock::class, $phpdoc); + $this->assertSame($summary, $phpdoc->getSummary()); + $this->assertSame($description, $phpdoc->getDescription()->render()); + $this->assertCount(1, $phpdoc->getTags()); + $this->assertTrue($phpdoc->hasTag('return')); + } + + public function testInterpretingASimpleDocBlock(): void + { + /** @var DocBlock $docblock */ + $docblock; + /** @var string $summary */ + $summary; + /** @var Description $description */ + $description; + include(__DIR__ . '/../../examples/01-interpreting-a-simple-docblock.php'); $descriptionText = <<assertEmpty($docblock->getTags()); } - public function testInterpretingTags() + public function testInterpretingTags(): void { - /** - * @var DocBlock $docblock - * @var boolean $hasSeeTag - * @var Tag[] $tags - * @var See[] $seeTags - */ + /** @var DocBlock $docblock */ + $docblock; + /** @var boolean $hasSeeTag */ + $hasSeeTag; + /** @var Tag[] $tags */ + $tags; + /** @var See[] $seeTags */ + $seeTags; + include(__DIR__ . '/../../examples/02-interpreting-tags.php'); $this->assertTrue($hasSeeTag); @@ -73,21 +104,25 @@ public function testInterpretingTags() $this->assertInstanceOf(See::class, $seeTags[0]); $seeTag = $seeTags[0]; - $this->assertSame('\\' . StandardTagFactory::class, (string)$seeTag->getReference()); - $this->assertSame('', (string)$seeTag->getDescription()); + $this->assertSame('\\' . StandardTagFactory::class, (string) $seeTag->getReference()); + $this->assertSame('', (string) $seeTag->getDescription()); } - public function testDescriptionsCanEscapeAtSignsAndClosingBraces() + public function testDescriptionsCanEscapeAtSignsAndClosingBraces(): void { - /** - * @var string $docComment - * @var DocBlock $docblock - * @var Description $description - * @var string $receivedDocComment - * @var string $foundDescription - */ + /** @var string $docComment */ + $docComment; + /** @var DocBlock $docblock */ + $docblock; + /** @var Description $description */ + $description; + /** @var string $receivedDocComment */ + $receivedDocComment; + /** @var string $foundDescription */ + $foundDescription; include(__DIR__ . '/../../examples/playing-with-descriptions/02-escaping.php'); + $this->assertSame( <<<'DESCRIPTION' You can escape the @-sign by surrounding it with braces, for example: @. And escape a closing brace within an diff --git a/tests/integration/ReconstitutingADocBlockTest.php b/tests/integration/ReconstitutingADocBlockTest.php index d411bb40..02da4def 100644 --- a/tests/integration/ReconstitutingADocBlockTest.php +++ b/tests/integration/ReconstitutingADocBlockTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -23,17 +24,18 @@ class ReconstitutingADocBlockTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown(): void { m::close(); } - public function testReconstituteADocBlock() + public function testReconstituteADocBlock(): void { - /** - * @var string $docComment - * @var string $reconstitutedDocComment - */ + /** @var string $docComment */ + $docComment; + /** @var string $reconstitutedDocComment */ + $reconstitutedDocComment; + include(__DIR__ . '/../../examples/03-reconstituting-a-docblock.php'); $this->assertSame($docComment, $reconstitutedDocComment); diff --git a/tests/integration/UsingTagsTest.php b/tests/integration/UsingTagsTest.php index a6b9467d..eb463d8d 100644 --- a/tests/integration/UsingTagsTest.php +++ b/tests/integration/UsingTagsTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -25,23 +26,25 @@ class UsingTagsTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown(): void { m::close(); } - public function testAddingYourOwnTagUsingAStaticMethodAsFactory() + public function testAddingYourOwnTagUsingAStaticMethodAsFactory(): void { - /** - * @var object[] $customTagObjects - * @var string $docComment - * @var string $reconstitutedDocComment - */ + /** @var object[] $customTagObjects */ + $customTagObjects; + /** @var string $docComment */ + $docComment; + /** @var string $reconstitutedDocComment */ + $reconstitutedDocComment; + include(__DIR__ . '/../../examples/04-adding-your-own-tag.php'); $this->assertInstanceOf(\MyTag::class, $customTagObjects[0]); $this->assertSame('my-tag', $customTagObjects[0]->getName()); - $this->assertSame('I have a description', (string)$customTagObjects[0]->getDescription()); + $this->assertSame('I have a description', (string) $customTagObjects[0]->getDescription()); $this->assertSame($docComment, $reconstitutedDocComment); } } diff --git a/tests/unit/DocBlock/DescriptionFactoryTest.php b/tests/unit/DocBlock/DescriptionFactoryTest.php index ca927016..3c4647f3 100644 --- a/tests/unit/DocBlock/DescriptionFactoryTest.php +++ b/tests/unit/DocBlock/DescriptionFactoryTest.php @@ -1,19 +1,22 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; +use Exception; use Mockery as m; -use phpDocumentor\Reflection\DocBlock\Tags\Link; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; +use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag; use phpDocumentor\Reflection\Types\Context; use PHPUnit\Framework\TestCase; @@ -26,18 +29,19 @@ class DescriptionFactoryTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description * @dataProvider provideSimpleExampleDescriptions */ - public function testDescriptionCanParseASimpleString($contents) + public function testDescriptionCanParseASimpleString(string $contents) : void { $tagFactory = m::mock(TagFactory::class); $tagFactory->shouldReceive('create')->never(); @@ -49,12 +53,13 @@ public function testDescriptionCanParseASimpleString($contents) } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description * @dataProvider provideEscapeSequences */ - public function testEscapeSequences($contents, $expected) + public function testEscapeSequences(string $contents, string $expected) : void { $tagFactory = m::mock(TagFactory::class); $tagFactory->shouldReceive('create')->never(); @@ -66,15 +71,16 @@ public function testEscapeSequences($contents, $expected) } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\Types\Context + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description - * @uses phpDocumentor\Reflection\DocBlock\Tags\Link - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * @uses phpDocumentor\Reflection\Types\Context */ - public function testDescriptionCanParseAStringWithInlineTag() + public function testDescriptionCanParseAStringWithInlineTag() : void { $contents = 'This is text for a {@link http://phpdoc.org/ description} that uses an inline tag.'; $context = new Context(''); @@ -82,7 +88,7 @@ public function testDescriptionCanParseAStringWithInlineTag() $tagFactory->shouldReceive('create') ->once() ->with('@link http://phpdoc.org/ description', $context) - ->andReturn(new Link('http://phpdoc.org/', new Description('description'))); + ->andReturn(new LinkTag('http://phpdoc.org/', new Description('description'))); $factory = new DescriptionFactory($tagFactory); $description = $factory->create($contents, $context); @@ -91,15 +97,16 @@ public function testDescriptionCanParseAStringWithInlineTag() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\Types\Context + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description - * @uses phpDocumentor\Reflection\DocBlock\Tags\Link - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * @uses phpDocumentor\Reflection\Types\Context */ - public function testDescriptionCanParseAStringStartingWithInlineTag() + public function testDescriptionCanParseAStringStartingWithInlineTag() : void { $contents = '{@link http://phpdoc.org/ This} is text for a description that starts with an inline tag.'; $context = new Context(''); @@ -107,7 +114,7 @@ public function testDescriptionCanParseAStringStartingWithInlineTag() $tagFactory->shouldReceive('create') ->once() ->with('@link http://phpdoc.org/ This', $context) - ->andReturn(new Link('http://phpdoc.org/', new Description('This'))); + ->andReturn(new LinkTag('http://phpdoc.org/', new Description('This'))); $factory = new DescriptionFactory($tagFactory); $description = $factory->create($contents, $context); @@ -116,11 +123,12 @@ public function testDescriptionCanParseAStringStartingWithInlineTag() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testIfSuperfluousStartingSpacesAreRemoved() + public function testIfSuperfluousStartingSpacesAreRemoved() : void { $factory = new DescriptionFactory(m::mock(TagFactory::class)); $descriptionText = <<assertSame($expectedDescription, $description->render()); } + /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\InvalidTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::__construct + * @covers ::create + */ + public function testDescriptionWithBrokenInlineTags() : void + { + $contents = 'This {@see $name} is a broken use case, but used in real life.'; + $context = new Context(''); + $tagFactory = m::mock(TagFactory::class); + $tagFactory->shouldReceive('create') + ->once() + ->with('@see $name', $context) + ->andReturn(InvalidTag::create('$name', 'see', new Exception())); + + $factory = new DescriptionFactory($tagFactory); + $description = $factory->create($contents, $context); + + $this->assertSame($contents, $description->render()); + } + /** * Provides a series of example strings that the parser should correctly interpret and return. * * @return string[][] */ - public function provideSimpleExampleDescriptions() + public function provideSimpleExampleDescriptions() : array { return [ ['This is text for a description.'], @@ -171,7 +204,10 @@ public function provideSimpleExampleDescriptions() ]; } - public function provideEscapeSequences() + /** + * @return string[][] + */ + public function provideEscapeSequences() : array { return [ ['This is text for a description with a {@}.', 'This is text for a description with a @.'], diff --git a/tests/unit/DocBlock/DescriptionTest.php b/tests/unit/DocBlock/DescriptionTest.php index 30fd0a8c..1cb34812 100644 --- a/tests/unit/DocBlock/DescriptionTest.php +++ b/tests/unit/DocBlock/DescriptionTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -25,23 +26,24 @@ class DescriptionTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** - * @covers ::__construct - * @covers ::render * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * + * @covers ::__construct + * @covers ::render */ - public function testDescriptionCanRenderUsingABodyWithPlaceholdersAndTags() + public function testDescriptionCanRenderUsingABodyWithPlaceholdersAndTags() : void { - $body = 'This is a %1$s body.'; + $body = 'This is a %1$s body.'; $expected = 'This is a {@internal significant} body.'; - $tags = [new Generic('internal', new Description('significant '))]; + $tags = [new Generic('internal', new Description('significant '))]; $fixture = new Description($body, $tags); @@ -55,30 +57,32 @@ public function testDescriptionCanRenderUsingABodyWithPlaceholdersAndTags() } /** - * @covers ::__construct - * @covers ::render - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * + * @covers ::__construct + * @covers ::render + * @covers ::__toString */ - public function testDescriptionCanBeCastToString() + public function testDescriptionCanBeCastToString() : void { - $body = 'This is a %1$s body.'; + $body = 'This is a %1$s body.'; $expected = 'This is a {@internal significant} body.'; - $tags = [new Generic('internal', new Description('significant '))]; + $tags = [new Generic('internal', new Description('significant '))]; $fixture = new Description($body, $tags); - $this->assertSame($expected, (string)$fixture); + $this->assertSame($expected, (string) $fixture); } /** - * @covers ::getTags * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * + * @covers ::getTags */ - public function testDescriptionTagsGetter() + public function testDescriptionTagsGetter() : void { $body = '@JoinTable(name="table", joinColumns=%1$s, inverseJoinColumns=%2$s)'; @@ -92,7 +96,7 @@ public function testDescriptionTagsGetter() $fixture = new Description($body, $tags); - $this->assertEquals(2, count($fixture->getTags())); + $this->assertCount(2, $fixture->getTags()); $actualTags = $fixture->getTags(); $this->assertSame($tags, $actualTags); @@ -101,14 +105,15 @@ public function testDescriptionTagsGetter() } /** - * @covers ::__construct - * @covers ::render - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * + * @covers ::__construct + * @covers ::render + * @covers ::__toString */ - public function testDescriptionMultipleTagsCanBeCastToString() + public function testDescriptionMultipleTagsCanBeCastToString() : void { $body = '@JoinTable(name="table", joinColumns=%1$s, inverseJoinColumns=%2$s)'; @@ -120,17 +125,9 @@ public function testDescriptionMultipleTagsCanBeCastToString() $tag2, ]; - $fixture = new Description($body, $tags); - $expected = '@JoinTable(name="table", joinColumns={@JoinColumn (name="column_id", referencedColumnName="id")}, inverseJoinColumns={@JoinColumn (name="column_id_2", referencedColumnName="id")})'; - $this->assertSame($expected, (string)$fixture); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testBodyTemplateMustBeAString() - { - new Description([]); + $fixture = new Description($body, $tags); + $expected = '@JoinTable(name="table", joinColumns={@JoinColumn (name="column_id", referencedColumnName="id")}, ' + . 'inverseJoinColumns={@JoinColumn (name="column_id_2", referencedColumnName="id")})'; + $this->assertSame($expected, (string) $fixture); } } diff --git a/tests/unit/DocBlock/ExampleFinderTest.php b/tests/unit/DocBlock/ExampleFinderTest.php index 7c306fa8..d135892b 100644 --- a/tests/unit/DocBlock/ExampleFinderTest.php +++ b/tests/unit/DocBlock/ExampleFinderTest.php @@ -1,5 +1,7 @@ */ class ExampleFinderTest extends TestCase @@ -18,25 +20,26 @@ class ExampleFinderTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } - public function setUp() + public function setUp() : void { $this->fixture = new ExampleFinder(); } /** - * @covers ::find - * @covers ::getSourceDirectory * @uses \phpDocumentor\Reflection\DocBlock\Tags\Example * @uses \phpDocumentor\Reflection\DocBlock\Description + * + * @covers ::find + * @covers ::getSourceDirectory */ - public function testFileNotFound() + public function testFileNotFound() : void { - $example = new Example('./example.php', false, 1, 0, new Description('Test')); + $example = new Example('./example.php', false, 1, 0, 'Test'); $this->assertSame('** File not found : ./example.php **', $this->fixture->find($example)); } } diff --git a/tests/unit/DocBlock/SerializerTest.php b/tests/unit/DocBlock/SerializerTest.php index 69a164a7..967dace9 100644 --- a/tests/unit/DocBlock/SerializerTest.php +++ b/tests/unit/DocBlock/SerializerTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -25,21 +26,22 @@ class SerializerTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\DocBlock + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * * @covers ::__construct * @covers ::getDocComment - * @uses phpDocumentor\Reflection\DocBlock\Description - * @uses phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * @uses phpDocumentor\Reflection\DocBlock - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Tags\Generic */ - public function testReconstructsADocCommentFromADocBlock() + public function testReconstructsADocCommentFromADocBlock() : void { $expected = <<<'DOCCOMMENT' /** @@ -57,7 +59,7 @@ public function testReconstructsADocCommentFromADocBlock() 'This is a summary', new Description('This is a description'), [ - new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')) + new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')), ] ); @@ -65,15 +67,16 @@ public function testReconstructsADocCommentFromADocBlock() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\DocBlock + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * * @covers ::__construct * @covers ::getDocComment - * @uses phpDocumentor\Reflection\DocBlock\Description - * @uses phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * @uses phpDocumentor\Reflection\DocBlock - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Tags\Generic */ - public function testAddPrefixToDocBlock() + public function testAddPrefixToDocBlock() : void { $expected = <<<'DOCCOMMENT' aa/** @@ -91,7 +94,7 @@ public function testAddPrefixToDocBlock() 'This is a summary', new Description('This is a description'), [ - new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')) + new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')), ] ); @@ -99,15 +102,16 @@ public function testAddPrefixToDocBlock() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\DocBlock + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * * @covers ::__construct * @covers ::getDocComment - * @uses phpDocumentor\Reflection\DocBlock\Description - * @uses phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * @uses phpDocumentor\Reflection\DocBlock - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Tags\Generic */ - public function testAddPrefixToDocBlockExceptFirstLine() + public function testAddPrefixToDocBlockExceptFirstLine() : void { $expected = <<<'DOCCOMMENT' /** @@ -125,7 +129,7 @@ public function testAddPrefixToDocBlockExceptFirstLine() 'This is a summary', new Description('This is a description'), [ - new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')) + new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')), ] ); @@ -133,15 +137,16 @@ public function testAddPrefixToDocBlockExceptFirstLine() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * @uses \phpDocumentor\Reflection\DocBlock + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * * @covers ::__construct * @covers ::getDocComment - * @uses phpDocumentor\Reflection\DocBlock\Description - * @uses phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * @uses phpDocumentor\Reflection\DocBlock - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Tags\Generic */ - public function testWordwrapsAroundTheGivenAmountOfCharacters() + public function testWordwrapsAroundTheGivenAmountOfCharacters() : void { $expected = <<<'DOCCOMMENT' /** @@ -165,7 +170,7 @@ public function testWordwrapsAroundTheGivenAmountOfCharacters() 'This is a summary', new Description('This is a description'), [ - new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')) + new DocBlock\Tags\Generic('unknown-tag', new Description('Test description for the unknown tag')), ] ); @@ -176,7 +181,7 @@ public function testWordwrapsAroundTheGivenAmountOfCharacters() * @covers ::__construct * @covers ::getDocComment */ - public function testNoExtraSpacesAfterTagRemoval() + public function testNoExtraSpacesAfterTagRemoval() : void { $expected = <<<'DOCCOMMENT' /** @@ -189,7 +194,7 @@ public function testNoExtraSpacesAfterTagRemoval() */ DOCCOMMENT_AFTER_REMOVE; - $fixture = new Serializer(0, '', true, 15); + $fixture = new Serializer(0, '', true, 15); $genericTag = new DocBlock\Tags\Generic('unknown-tag'); $docBlock = new DocBlock('', null, [$genericTag]); @@ -198,40 +203,4 @@ public function testNoExtraSpacesAfterTagRemoval() $docBlock->removeTag($genericTag); $this->assertSame($expectedAfterRemove, $fixture->getDocComment($docBlock)); } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testInitializationFailsIfIndentIsNotAnInteger() - { - new Serializer([]); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testInitializationFailsIfIndentStringIsNotAString() - { - new Serializer(0, []); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testInitializationFailsIfIndentFirstLineIsNotABoolean() - { - new Serializer(0, '', []); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testInitializationFailsIfLineLengthIsNotNullNorAnInteger() - { - new Serializer(0, '', false, []); - } } diff --git a/tests/unit/DocBlock/StandardTagFactoryTest.php b/tests/unit/DocBlock/StandardTagFactoryTest.php index 13d60e97..33372045 100644 --- a/tests/unit/DocBlock/StandardTagFactoryTest.php +++ b/tests/unit/DocBlock/StandardTagFactoryTest.php @@ -1,22 +1,25 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; +use InvalidArgumentException; use Mockery as m; use phpDocumentor\Reflection\DocBlock\Tags\Author; use phpDocumentor\Reflection\DocBlock\Tags\Formatter; use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; use phpDocumentor\Reflection\DocBlock\Tags\Generic; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; use phpDocumentor\Reflection\DocBlock\Tags\Return_; use phpDocumentor\Reflection\DocBlock\Tags\See; use phpDocumentor\Reflection\Fqsen; @@ -26,29 +29,29 @@ use PHPUnit\Framework\TestCase; /** - * @coversDefaultClass phpDocumentor\Reflection\DocBlock\StandardTagFactory + * @coversDefaultClass \phpDocumentor\Reflection\DocBlock\StandardTagFactory * @covers :: */ class StandardTagFactoryTest extends TestCase { - /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @uses phpDocumentor\Reflection\DocBlock\Tags\Generic - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testCreatingAGenericTag() + public function testCreatingAGenericTag() : void { $expectedTagName = 'unknown-tag'; $expectedDescriptionText = 'This is a description'; @@ -74,13 +77,14 @@ public function testCreatingAGenericTag() } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @uses phpDocumentor\Reflection\DocBlock\Tags\Author - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testCreatingASpecificTag() + public function testCreatingASpecificTag() : void { $context = new Context(''); $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class)); @@ -93,15 +97,16 @@ public function testCreatingASpecificTag() } /** - * @covers ::__construct - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService * @uses \phpDocumentor\Reflection\DocBlock\Tags\See * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen + * + * @covers ::__construct + * @covers ::create */ - public function testAnEmptyContextIsCreatedIfNoneIsProvided() + public function testAnEmptyContextIsCreatedIfNoneIsProvided() : void { $fqsen = '\Tag'; $resolver = m::mock(FqsenResolver::class) @@ -119,17 +124,18 @@ public function testAnEmptyContextIsCreatedIfNoneIsProvided() $tag = $tagFactory->create('@see Tag'); $this->assertInstanceOf(See::class, $tag); - $this->assertSame($fqsen, (string)$tag->getReference()); + $this->assertSame($fqsen, (string) $tag->getReference()); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @uses phpDocumentor\Reflection\DocBlock\Tags\Author - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testPassingYourOwnSetOfTagHandlers() + public function testPassingYourOwnSetOfTagHandlers() : void { $context = new Context(''); $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class), ['user' => Author::class]); @@ -142,24 +148,28 @@ public function testPassingYourOwnSetOfTagHandlers() } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The tag "@user[myuser" does not seem to be wellformed, please check it for errors */ - public function testExceptionIsThrownIfProvidedTagIsNotWellformed() + public function testExceptionIsThrownIfProvidedTagIsNotWellformed() : void { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage( + 'The tag "@user[myuser" does not seem to be wellformed, please check it for errors' + ); $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class)); $tagFactory->create('@user[myuser'); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * * @covers ::__construct * @covers ::addParameter - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService */ - public function testAddParameterToServiceLocator() + public function testAddParameterToServiceLocator() : void { $resolver = m::mock(FqsenResolver::class); $tagFactory = new StandardTagFactory($resolver); @@ -173,10 +183,11 @@ public function testAddParameterToServiceLocator() } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * * @covers ::addService - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct */ - public function testAddServiceToServiceLocator() + public function testAddServiceToServiceLocator() : void { $service = new PassthroughFormatter(); @@ -192,10 +203,11 @@ public function testAddServiceToServiceLocator() } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * * @covers ::addService - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct */ - public function testInjectConcreteServiceForInterfaceToServiceLocator() + public function testInjectConcreteServiceForInterfaceToServiceLocator() : void { $interfaceName = Formatter::class; $service = new PassthroughFormatter(); @@ -212,13 +224,14 @@ public function testInjectConcreteServiceForInterfaceToServiceLocator() } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::create + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author + * * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::create - * @uses phpDocumentor\Reflection\DocBlock\Tags\Author */ - public function testRegisteringAHandlerForANewTag() + public function testRegisteringAHandlerForANewTag() : void { $resolver = m::mock(FqsenResolver::class); $tagFactory = new StandardTagFactory($resolver); @@ -231,114 +244,74 @@ public function testRegisteringAHandlerForANewTag() } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException - */ - public function testHandlerRegistrationFailsIfProvidedTagNameIsNotAString() - { - $resolver = m::mock(FqsenResolver::class); - $tagFactory = new StandardTagFactory($resolver); - - $tagFactory->registerTagHandler([], Author::class); - } - - /** - * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException - */ - public function testHandlerRegistrationFailsIfProvidedTagNameIsEmpty() - { - $resolver = m::mock(FqsenResolver::class); - $tagFactory = new StandardTagFactory($resolver); - - $tagFactory->registerTagHandler('', Author::class); - } - - /** - * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException - */ - public function testHandlerRegistrationFailsIfProvidedTagNameIsNamespaceButNotFullyQualified() - { - $resolver = m::mock(FqsenResolver::class); - $tagFactory = new StandardTagFactory($resolver); - - $tagFactory->registerTagHandler('Name\Spaced\Tag', Author::class); - } - - /** - * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException */ - public function testHandlerRegistrationFailsIfProvidedHandlerIsNotAString() + public function testHandlerRegistrationFailsIfProvidedTagNameIsNamespaceButNotFullyQualified() : void { + $this->expectException('InvalidArgumentException'); $resolver = m::mock(FqsenResolver::class); $tagFactory = new StandardTagFactory($resolver); - - $tagFactory->registerTagHandler('my-tag', []); + // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName + $tagFactory->registerTagHandler(\Name\Spaced\Tag::class, Author::class); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException */ - public function testHandlerRegistrationFailsIfProvidedHandlerIsEmpty() + public function testHandlerRegistrationFailsIfProvidedHandlerIsEmpty() : void { + $this->expectException('InvalidArgumentException'); $resolver = m::mock(FqsenResolver::class); $tagFactory = new StandardTagFactory($resolver); - $tagFactory->registerTagHandler('my-tag', ''); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException */ - public function testHandlerRegistrationFailsIfProvidedHandlerIsNotAnExistingClassName() + public function testHandlerRegistrationFailsIfProvidedHandlerIsNotAnExistingClassName() : void { + $this->expectException('InvalidArgumentException'); $resolver = m::mock(FqsenResolver::class); $tagFactory = new StandardTagFactory($resolver); - $tagFactory->registerTagHandler('my-tag', 'IDoNotExist'); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * * @covers ::registerTagHandler - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @expectedException \InvalidArgumentException */ - public function testHandlerRegistrationFailsIfProvidedHandlerDoesNotImplementTheTagInterface() + public function testHandlerRegistrationFailsIfProvidedHandlerDoesNotImplementTheTagInterface() : void { + $this->expectException('InvalidArgumentException'); $resolver = m::mock(FqsenResolver::class); $tagFactory = new StandardTagFactory($resolver); - $tagFactory->registerTagHandler('my-tag', 'stdClass'); } /** + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct + * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService + * @uses \phpDocumentor\Reflection\Docblock\Description + * @uses \phpDocumentor\Reflection\Docblock\Tags\Return_ + * @uses \phpDocumentor\Reflection\Docblock\Tags\BaseTag + * * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::__construct - * @uses phpDocumentor\Reflection\DocBlock\StandardTagFactory::addService - * @uses phpDocumentor\Reflection\Docblock\Description - * @uses phpDocumentor\Reflection\Docblock\Tags\Return_ - * @uses phpDocumentor\Reflection\Docblock\Tags\BaseTag */ - public function testReturntagIsMappedCorrectly() + public function testReturnTagIsMappedCorrectly() : void { - $context = new Context(''); + $context = new Context(''); $descriptionFactory = m::mock(DescriptionFactory::class); $descriptionFactory @@ -359,4 +332,105 @@ public function testReturntagIsMappedCorrectly() $this->assertInstanceOf(Return_::class, $tag); $this->assertSame('return', $tag->getName()); } + + public function testInvalidTagIsReturnedOnFailure() : void + { + $tagFactory = new StandardTagFactory(m::mock(FqsenResolver::class)); + + /** @var InvalidTag $tag */ + $tag = $tagFactory->create('@see $name some invalid tag'); + + $this->assertInstanceOf(InvalidTag::class, $tag); + } + + /** + * @dataProvider validTagProvider + */ + public function testValidFormattedTags(string $input, string $tagName, string $render) : void + { + $fqsenResolver = $this->prophesize(FqsenResolver::class); + $tagFactory = new StandardTagFactory($fqsenResolver->reveal()); + $tagFactory->registerTagHandler('tag', Generic::class); + $tag = $tagFactory->create($input); + + self::assertSame($tagName, $tag->getName()); + self::assertSame($render, $tag->render()); + } + + /** + * @return string[][] + * + * @phpstan-return array> + */ + public function validTagProvider() : array + { + //rendered result is adding a space, because the tags are not rendered properly. + return [ + 'tag without body' => [ + '@tag', + 'tag', + '@tag', + ], + 'tag specialization' => [ + '@tag:some-spec body', + 'tag:some-spec', + '@tag:some-spec body', + ], + 'tag specialization followed by parenthesis' => [ + '@tag:some-spec(body)', + 'tag:some-spec', + '@tag:some-spec (body)', + ], + 'tag with textual description' => [ + '@tag some text', + 'tag', + '@tag some text', + ], + 'tag body starting with sqare brackets is allowed' => [ + '@tag [is valid]', + 'tag', + '@tag [is valid]', + ], + 'tag body starting with curly brackets is allowed' => [ + '@tag {is valid}', + 'tag', + '@tag {is valid}', + ], + 'tag name followed by curly brackets directly is allowed' => [ + '@tag{is valid}', + 'tag', + '@tag {is valid}', + ], + 'parenthesis directly following a tag name is valid' => [ + '@tag(is valid)', + 'tag', + '@tag (is valid)', + ], + ]; + } + + /** + * @dataProvider invalidTagProvider + */ + public function testInValidFormattedTags(string $input) : void + { + $this->expectException(InvalidArgumentException::class); + $fqsenResolver = $this->prophesize(FqsenResolver::class); + $tagFactory = new StandardTagFactory($fqsenResolver->reveal()); + $tagFactory->registerTagHandler('tag', Generic::class); + $tagFactory->create($input); + } + + /** + * @return string[][] + * + * @phpstan-return list> + */ + public function invalidTagProvider() : array + { + return [ + ['@tag[invalid]'], + ['@tag@invalid'], + ]; + } } diff --git a/tests/unit/DocBlock/Tags/AuthorTest.php b/tests/unit/DocBlock/Tags/AuthorTest.php index ea0d099d..59e4cdad 100644 --- a/tests/unit/DocBlock/Tags/AuthorTest.php +++ b/tests/unit/DocBlock/Tags/AuthorTest.php @@ -1,14 +1,16 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ + namespace phpDocumentor\Reflection\DocBlock\Tags; use Mockery as m; @@ -23,16 +25,17 @@ class AuthorTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Author('Mike van Riel', 'mike@phpdoc.org'); @@ -43,10 +46,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::__construct * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Author('Mike van Riel', 'mike@phpdoc.org'); @@ -55,9 +59,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Author('Mike van Riel', 'mike@phpdoc.org'); @@ -71,7 +76,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getAuthorName */ - public function testHasTheAuthorName() + public function testHasTheAuthorName() : void { $expected = 'Mike van Riel'; @@ -80,21 +85,11 @@ public function testHasTheAuthorName() $this->assertSame($expected, $fixture->getAuthorName()); } - /** - * @covers ::__construct - * @covers ::getAuthorName - * @expectedException \InvalidArgumentException - */ - public function testInitializationFailsIfAuthorNameIsNotAString() - { - new Author([], 'mike@phpdoc.org'); - } - /** * @covers ::__construct * @covers ::getEmail */ - public function testHasTheAuthorMailAddress() + public function testHasTheAuthorMailAddress() : void { $expected = 'mike@phpdoc.org'; @@ -105,19 +100,10 @@ public function testHasTheAuthorMailAddress() /** * @covers ::__construct - * @expectedException \InvalidArgumentException */ - public function testInitializationFailsIfEmailIsNotAString() - { - new Author('Mike van Riel', []); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testInitializationFailsIfEmailIsNotValid() + public function testInitializationFailsIfEmailIsNotValid() : void { + $this->expectException('InvalidArgumentException'); new Author('Mike van Riel', 'mike'); } @@ -125,7 +111,7 @@ public function testInitializationFailsIfEmailIsNotValid() * @covers ::__construct * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Author('Mike van Riel', 'mike@phpdoc.org'); @@ -136,7 +122,7 @@ public function testStringRepresentationIsReturned() * @covers ::__construct * @covers ::__toString */ - public function testStringRepresentationWithEmtpyEmail() + public function testStringRepresentationWithEmtpyEmail() : void { $fixture = new Author('Mike van Riel', ''); @@ -144,10 +130,11 @@ public function testStringRepresentationWithEmtpyEmail() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author:: + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $fixture = Author::create('Mike van Riel '); @@ -157,10 +144,11 @@ public function testFactoryMethod() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author:: + * + * @covers ::create */ - public function testFactoryMethodReturnsNullIfItCouldNotReadBody() + public function testFactoryMethodReturnsNullIfItCouldNotReadBody() : void { $this->assertNull(Author::create('dfgr<')); } diff --git a/tests/unit/DocBlock/Tags/CoversTest.php b/tests/unit/DocBlock/Tags/CoversTest.php index 2750420a..f4319a91 100644 --- a/tests/unit/DocBlock/Tags/CoversTest.php +++ b/tests/unit/DocBlock/Tags/CoversTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -26,11 +27,10 @@ */ class CoversTest extends TestCase { - /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -38,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Covers::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Covers(new Fqsen('\DateTime'), new Description('Description')); @@ -52,10 +53,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Covers::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Covers(new Fqsen('\DateTime'), new Description('Description')); @@ -65,9 +67,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Covers::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Covers(new Fqsen('\DateTime'), new Description('Description')); @@ -81,7 +84,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getReference */ - public function testHasReferenceToFqsen() + public function testHasReferenceToFqsen() : void { $expected = new Fqsen('\DateTime'); @@ -91,11 +94,12 @@ public function testHasReferenceToFqsen() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -105,33 +109,35 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Covers(new Fqsen('\DateTime'), new Description('Description')); - $this->assertSame('\DateTime Description', (string)$fixture); + $this->assertSame('\DateTime Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Covers:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\FqsenResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $resolver = m::mock(FqsenResolver::class); - $context = new Context(''); + $resolver = m::mock(FqsenResolver::class); + $context = new Context(''); - $fqsen = new Fqsen('\DateTime'); + $fqsen = new Fqsen('\DateTime'); $description = new Description('My Description'); $descriptionFactory @@ -140,26 +146,17 @@ public function testFactoryMethod() $fixture = Covers::create('DateTime My Description', $descriptionFactory, $resolver, $context); - $this->assertSame('\DateTime My Description', (string)$fixture); + $this->assertSame('\DateTime My Description', (string) $fixture); $this->assertSame($fqsen, $fixture->getReference()); $this->assertSame($description, $fixture->getDescription()); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - $this->assertNull(Covers::create([])); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotEmpty() + public function testFactoryMethodFailsIfBodyIsNotEmpty() : void { + $this->expectException('InvalidArgumentException'); $this->assertNull(Covers::create('')); } } diff --git a/tests/unit/DocBlock/Tags/DeprecatedTest.php b/tests/unit/DocBlock/Tags/DeprecatedTest.php index 3fc3df22..9df9a7f7 100644 --- a/tests/unit/DocBlock/Tags/DeprecatedTest.php +++ b/tests/unit/DocBlock/Tags/DeprecatedTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -27,7 +28,7 @@ class DeprecatedTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -35,9 +36,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Deprecated('1.0', new Description('Description')); @@ -49,10 +51,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Deprecated('1.0', new Description('Description')); @@ -62,9 +65,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Deprecated('1.0', new Description('Description')); @@ -78,7 +82,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVersion */ - public function testHasVersionNumber() + public function testHasVersionNumber() : void { $expected = '1.0'; @@ -88,11 +92,12 @@ public function testHasVersionNumber() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -102,74 +107,69 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Deprecated('1.0', new Description('Description')); - $this->assertSame('1.0 Description', (string)$fixture); + $this->assertSame('1.0 Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); - $version = '1.0'; + $version = '1.0'; $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); $fixture = Deprecated::create('1.0 My Description', $descriptionFactory, $context); - $this->assertSame('1.0 My Description', (string)$fixture); + $this->assertSame('1.0 My Description', (string) $fixture); $this->assertSame($version, $fixture->getVersion()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethodCreatesEmptyDeprecatedTag() + public function testFactoryMethodCreatesEmptyDeprecatedTag() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $descriptionFactory->shouldReceive('create')->never(); $fixture = Deprecated::create('', $descriptionFactory, new Context('')); - $this->assertSame('', (string)$fixture); - $this->assertSame(null, $fixture->getVersion()); - $this->assertSame(null, $fixture->getDescription()); + $this->assertSame('', (string) $fixture); + $this->assertNull($fixture->getVersion()); + $this->assertNull($fixture->getDescription()); } /** - * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfVersionIsNotString() - { - $this->assertNull(Deprecated::create([])); - } - - /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated::__construct + * + * @covers ::create */ - public function testFactoryMethodReturnsNullIfBodyDoesNotMatchRegex() + public function testFactoryMethodReturnsNullIfBodyDoesNotMatchRegex() : void { $this->assertEquals(new Deprecated(), Deprecated::create('dkhf<')); } diff --git a/tests/unit/DocBlock/Tags/ExampleTest.php b/tests/unit/DocBlock/Tags/ExampleTest.php index 1d9207fa..77809d49 100644 --- a/tests/unit/DocBlock/Tags/ExampleTest.php +++ b/tests/unit/DocBlock/Tags/ExampleTest.php @@ -1,5 +1,7 @@ assertEquals('"example1.php"', $tag->getContent()); @@ -35,13 +37,14 @@ public function testExampleWithoutContent() } /** + * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::create * @covers ::__construct * @covers ::getFilePath * @covers ::getDescription - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testWithDescription() + public function testWithDescription() : void { $tag = Example::create('"example1.php" some text'); $this->assertEquals('example1.php', $tag->getFilePath()); @@ -49,13 +52,14 @@ public function testWithDescription() } /** + * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::create * @covers ::__construct * @covers ::getFilePath * @covers ::getStartingLine - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testStartlineIsParsed() + public function testStartlineIsParsed() : void { $tag = Example::create('"example1.php" 10'); $this->assertEquals('example1.php', $tag->getFilePath()); @@ -63,14 +67,15 @@ public function testStartlineIsParsed() } /** + * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::create * @covers ::__construct * @covers ::getFilePath * @covers ::getStartingLine * @covers ::getDescription - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testAllowOmitingLineCount() + public function testAllowOmitingLineCount() : void { $tag = Example::create('"example1.php" 10 some text'); $this->assertEquals('example1.php', $tag->getFilePath()); @@ -79,14 +84,15 @@ public function testAllowOmitingLineCount() } /** + * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::create * @covers ::__construct * @covers ::getFilePath * @covers ::getStartingLine * @covers ::getLineCount - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testLengthIsParsed() + public function testLengthIsParsed() : void { $tag = Example::create('"example1.php" 10 5'); $this->assertEquals('example1.php', $tag->getFilePath()); @@ -95,15 +101,16 @@ public function testLengthIsParsed() } /** + * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * * @covers ::create * @covers ::__construct * @covers ::getFilePath * @covers ::getStartingLine * @covers ::getLineCount * @covers ::getDescription - * @uses phpDocumentor\Reflection\DocBlock\Tags\BaseTag */ - public function testFullExample() + public function testFullExample() : void { $tag = Example::create('"example1.php" 10 5 test text'); $this->assertEquals('example1.php', $tag->getFilePath()); diff --git a/tests/unit/DocBlock/Tags/Formatter/AlignFormatterTest.php b/tests/unit/DocBlock/Tags/Formatter/AlignFormatterTest.php index 1a4fbb3b..ce0c286a 100644 --- a/tests/unit/DocBlock/Tags/Formatter/AlignFormatterTest.php +++ b/tests/unit/DocBlock/Tags/Formatter/AlignFormatterTest.php @@ -1,21 +1,21 @@ - * @copyright 2017 Mike van Riel - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Formatter; use Mockery as m; use phpDocumentor\Reflection\DocBlock\Description; -use phpDocumentor\Reflection\DocBlock\Tags\Link; +use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag; use phpDocumentor\Reflection\DocBlock\Tags\Param; use phpDocumentor\Reflection\DocBlock\Tags\Version; use phpDocumentor\Reflection\Types\String_; @@ -29,34 +29,35 @@ class AlignFormatterTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version + * @uses \phpDocumentor\Reflection\Types\String_ + * * @covers ::format * @covers \phpDocumentor\Reflection\DocBlock\Tags\Formatter\AlignFormatter::__construct - * @uses \phpDocumentor\Reflection\DocBlock\Description - * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag - * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link - * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param - * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version - * @uses \phpDocumentor\Reflection\Types\String_ */ - public function testFormatterCallsToStringAndReturnsAStandardRepresentation() + public function testFormatterCallsToStringAndReturnsAStandardRepresentation() : void { - $tags = [ + $tags = [ new Param('foobar', new String_()), new Version('1.2.0'), - new Link('http://www.example.com', new Description('Examples')) + new LinkTag('http://www.example.com', new Description('Examples')), ]; $fixture = new AlignFormatter($tags); $expected = [ '@param string $foobar', '@version 1.2.0', - '@link http://www.example.com Examples' + '@link http://www.example.com Examples', ]; foreach ($tags as $key => $tag) { diff --git a/tests/unit/DocBlock/Tags/Formatter/PassthroughFormatterTest.php b/tests/unit/DocBlock/Tags/Formatter/PassthroughFormatterTest.php index cb2009e7..8f0f021f 100644 --- a/tests/unit/DocBlock/Tags/Formatter/PassthroughFormatterTest.php +++ b/tests/unit/DocBlock/Tags/Formatter/PassthroughFormatterTest.php @@ -1,13 +1,14 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Formatter; @@ -25,18 +26,19 @@ class PassthroughFormatterTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** - * @covers ::format * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * + * @covers ::format */ - public function testFormatterCallsToStringAndReturnsAStandardRepresentation() + public function testFormatterCallsToStringAndReturnsAStandardRepresentation() : void { $expected = '@unknown-tag This is a description'; @@ -49,15 +51,16 @@ public function testFormatterCallsToStringAndReturnsAStandardRepresentation() } /** - * @covers ::format * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic + * + * @covers ::format */ - public function testFormatterToStringWitoutDescription() + public function testFormatterToStringWitoutDescription() : void { $expected = '@unknown-tag'; - $fixture = new PassthroughFormatter(); + $fixture = new PassthroughFormatter(); $this->assertSame( $expected, diff --git a/tests/unit/DocBlock/Tags/GenericTest.php b/tests/unit/DocBlock/Tags/GenericTest.php index 62d37c01..a3c82488 100644 --- a/tests/unit/DocBlock/Tags/GenericTest.php +++ b/tests/unit/DocBlock/Tags/GenericTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @generic http://phpdoc.org */ @@ -27,16 +28,18 @@ class GenericTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } + /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Generic('generic', new Description('Description')); @@ -49,9 +52,10 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Generic('generic', new Description('Description')); @@ -61,9 +65,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Generic('generic', new Description('Description')); @@ -74,11 +79,12 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -88,67 +94,60 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Generic('generic', new Description('Description')); - $this->assertSame('Description', (string)$fixture); + $this->assertSame('Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Generic:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); - $generics = 'generic'; + $generics = 'generic'; $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); $fixture = Generic::create('My Description', 'generic', $descriptionFactory, $context); - $this->assertSame('My Description', (string)$fixture); + $this->assertSame('My Description', (string) $fixture); $this->assertSame($generics, $fixture->getName()); $this->assertSame($description, $fixture->getDescription()); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfNameIsNotString() - { - Generic::create('', []); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfNameIsNotEmpty() + public function testFactoryMethodFailsIfNameIsNotEmpty() : void { + $this->expectException('InvalidArgumentException'); Generic::create('', ''); } /** * @covers ::create * @covers ::__construct - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfNameContainsIllegalCharacters() + public function testFactoryMethodFailsIfNameContainsIllegalCharacters() : void { + $this->expectException('InvalidArgumentException'); Generic::create('', 'name/myname'); } } diff --git a/tests/unit/DocBlock/Tags/InvalidTagTest.php b/tests/unit/DocBlock/Tags/InvalidTagTest.php new file mode 100644 index 00000000..49d79a61 --- /dev/null +++ b/tests/unit/DocBlock/Tags/InvalidTagTest.php @@ -0,0 +1,100 @@ + + * @covers ::getName + * @covers ::render + * @covers ::getException + * @covers ::create + */ +final class InvalidTagTest extends TestCase +{ + public function testCreationWithoutError() : void + { + $tag = InvalidTag::create('Body', 'name'); + + self::assertSame('name', $tag->getName()); + self::assertSame('@name Body', $tag->render()); + self::assertNull($tag->getException()); + } + + /** + * @covers ::withError + * @covers ::__toString + */ + public function testCreationWithError() : void + { + $exception = new Exception(); + $tag = InvalidTag::create('Body', 'name')->withError($exception); + + self::assertSame('name', $tag->getName()); + self::assertSame('@name Body', $tag->render()); + self::assertSame('Body', (string) $tag); + self::assertSame($exception, $tag->getException()); + } + + public function testCreationWithErrorContainingClosure() : void + { + try { + $this->throwExceptionFromClosureWithClosureArgument(); + } catch (Throwable $e) { + $parentException = new Exception('test', 0, $e); + $tag = InvalidTag::create('Body', 'name')->withError($parentException); + self::assertSame('name', $tag->getName()); + self::assertSame('@name Body', $tag->render()); + self::assertSame($parentException, $tag->getException()); + self::assertStringStartsWith('(Closure at', $tag->getException()->getPrevious()->getTrace()[0]['args'][0]); + self::assertStringContainsString(__FILE__, $tag->getException()->getPrevious()->getTrace()[0]['args'][0]); + self::assertEquals($parentException, unserialize(serialize($parentException))); + } + } + + private function throwExceptionFromClosureWithClosureArgument() : void + { + $function = static function () : void { + throw new InvalidArgumentException(); + }; + + $function($function); + } + + public function testCreationWithErrorContainingResource() : void + { + try { + $this->throwExceptionWithResourceArgument(); + } catch (Throwable $e) { + $parentException = new Exception('test', 0, $e); + $tag = InvalidTag::create('Body', 'name')->withError($parentException); + self::assertSame('name', $tag->getName()); + self::assertSame('@name Body', $tag->render()); + self::assertSame($parentException, $tag->getException()); + self::assertStringStartsWith( + 'resource(stream)', + $tag->getException()->getPrevious()->getTrace()[0]['args'][0] + ); + self::assertEquals($parentException, unserialize(serialize($parentException))); + } + } + + private function throwExceptionWithResourceArgument() : void + { + $function = static function () : void { + throw new InvalidArgumentException(); + }; + + $function(fopen(__FILE__, 'r')); + } +} diff --git a/tests/unit/DocBlock/Tags/LinkTest.php b/tests/unit/DocBlock/Tags/LinkTest.php index 8e267583..00c8fe5c 100644 --- a/tests/unit/DocBlock/Tags/LinkTest.php +++ b/tests/unit/DocBlock/Tags/LinkTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -27,7 +28,7 @@ class LinkTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -35,9 +36,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Link('http://this.is.my/link', new Description('Description')); @@ -49,10 +51,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Link('http://this.is.my/link', new Description('Description')); @@ -62,9 +65,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Link('http://this.is.my/link', new Description('Description')); @@ -78,7 +82,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getLink */ - public function testHasLinkUrl() + public function testHasLinkUrl() : void { $expected = 'http://this.is.my/link'; @@ -88,11 +92,12 @@ public function testHasLinkUrl() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -102,66 +107,60 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Link('http://this.is.my/link', new Description('Description')); - $this->assertSame('http://this.is.my/link Description', (string)$fixture); + $this->assertSame('http://this.is.my/link Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); - $links = 'http://this.is.my/link'; + $links = 'http://this.is.my/link'; $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); $fixture = Link::create('http://this.is.my/link My Description', $descriptionFactory, $context); - $this->assertSame('http://this.is.my/link My Description', (string)$fixture); + $this->assertSame('http://this.is.my/link My Description', (string) $fixture); $this->assertSame($links, $fixture->getLink()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Link:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethodCreatesEmptyLinkTag() + public function testFactoryMethodCreatesEmptyLinkTag() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $descriptionFactory->shouldReceive('create')->never(); $fixture = Link::create('', $descriptionFactory, new Context('')); - $this->assertSame('', (string)$fixture); + $this->assertSame('', (string) $fixture); $this->assertSame('', $fixture->getLink()); $this->assertSame(null, $fixture->getDescription()); } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfVersionIsNotString() - { - $this->assertNull(Link::create([])); - } } diff --git a/tests/unit/DocBlock/Tags/MethodTest.php b/tests/unit/DocBlock/Tags/MethodTest.php index c7e67003..03bd1b61 100644 --- a/tests/unit/DocBlock/Tags/MethodTest.php +++ b/tests/unit/DocBlock/Tags/MethodTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -21,6 +22,7 @@ use phpDocumentor\Reflection\Types\Compound; use phpDocumentor\Reflection\Types\Context; use phpDocumentor\Reflection\Types\Integer; +use phpDocumentor\Reflection\Types\Mixed_; use phpDocumentor\Reflection\Types\Object_; use phpDocumentor\Reflection\Types\String_; use phpDocumentor\Reflection\Types\This; @@ -36,16 +38,17 @@ class MethodTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Method('myMethod'); @@ -58,16 +61,24 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $arguments = [ ['name' => 'argument1', 'type' => new String_()], - ['name' => 'argument2', 'type' => new Object_()] + ['name' => 'argument2', 'type' => new Object_()], ]; - $fixture = new Method('myMethod', $arguments, new Void_(), true, new Description('My Description')); + + $fixture = new Method( + 'myMethod', + $arguments, + new Void_(), + true, + new Description('My Description') + ); $this->assertSame( '@method static void myMethod(string $argument1, object $argument2) My Description', @@ -78,9 +89,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Method('myMethod'); @@ -94,7 +106,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getMethodName */ - public function testHasMethodName() + public function testHasMethodName() : void { $expected = 'myMethod'; @@ -107,10 +119,10 @@ public function testHasMethodName() * @covers ::__construct * @covers ::getArguments */ - public function testHasArguments() + public function testHasArguments() : void { $arguments = [ - [ 'name' => 'argument1', 'type' => new String_() ] + ['name' => 'argument1', 'type' => new String_()], ]; $fixture = new Method('myMethod', $arguments); @@ -122,11 +134,11 @@ public function testHasArguments() * @covers ::__construct * @covers ::getArguments */ - public function testArgumentsMayBePassedAsString() + public function testArgumentsMayBePassedAsString() : void { $arguments = ['argument1']; - $expected = [ - [ 'name' => $arguments[0], 'type' => new Void_() ] + $expected = [ + ['name' => $arguments[0], 'type' => new Mixed_()], ]; $fixture = new Method('myMethod', $arguments); @@ -138,11 +150,11 @@ public function testArgumentsMayBePassedAsString() * @covers ::__construct * @covers ::getArguments */ - public function testArgumentTypeCanBeInferredAsVoid() + public function testArgumentTypeCanBeInferredAsMixed() : void { - $arguments = [ [ 'name' => 'argument1' ] ]; - $expected = [ - [ 'name' => $arguments[0]['name'], 'type' => new Void_() ] + $arguments = [['name' => 'argument1']]; + $expected = [ + ['name' => $arguments[0]['name'], 'type' => new Mixed_()], ]; $fixture = new Method('myMethod', $arguments); @@ -151,23 +163,24 @@ public function testArgumentTypeCanBeInferredAsVoid() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__construct * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::getArguments * @uses \phpDocumentor\Reflection\DocBlock\Description + * + * @covers ::create */ - public function testRestArgumentIsParsedAsRegularArg() + public function testRestArgumentIsParsedAsRegularArg() : void { $expected = [ - [ 'name' => 'arg1', 'type' => new Void_() ], - [ 'name' => 'rest', 'type' => new Void_() ], - [ 'name' => 'rest2', 'type' => new Array_() ], + ['name' => 'arg1', 'type' => new Mixed_()], + ['name' => 'rest', 'type' => new Mixed_()], + ['name' => 'rest2', 'type' => new Array_()], ]; $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); $context = new Context(''); - $description = new Description(''); + $description = new Description(''); $descriptionFactory->shouldReceive('create')->with('', $context)->andReturn($description); $fixture = Method::create( @@ -184,7 +197,7 @@ public function testRestArgumentIsParsedAsRegularArg() * @covers ::__construct * @covers ::getReturnType */ - public function testHasReturnType() + public function testHasReturnType() : void { $expected = new String_(); @@ -197,7 +210,7 @@ public function testHasReturnType() * @covers ::__construct * @covers ::getReturnType */ - public function testReturnTypeCanBeInferredAsVoid() + public function testReturnTypeCanBeInferredAsVoid() : void { $fixture = new Method('myMethod', []); @@ -208,23 +221,24 @@ public function testReturnTypeCanBeInferredAsVoid() * @covers ::__construct * @covers ::isStatic */ - public function testMethodCanBeStatic() + public function testMethodCanBeStatic() : void { $expected = false; - $fixture = new Method('myMethod', [], null, $expected); + $fixture = new Method('myMethod', [], null, $expected); $this->assertSame($expected, $fixture->isStatic()); $expected = true; - $fixture = new Method('myMethod', [], null, $expected); + $fixture = new Method('myMethod', [], null, $expected); $this->assertSame($expected, $fixture->isStatic()); } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -234,47 +248,51 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::isStatic + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $arguments = [ ['name' => 'argument1', 'type' => new String_()], - ['name' => 'argument2', 'type' => new Object_()] + ['name' => 'argument2', 'type' => new Object_()], ]; - $fixture = new Method('myMethod', $arguments, new Void_(), true, new Description('My Description')); + $fixture = new Method('myMethod', $arguments, new Void_(), true, new Description('My Description')); $this->assertSame( 'static void myMethod(string $argument1, object $argument2) My Description', - (string)$fixture + (string) $fixture ); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); $context = new Context(''); - $description = new Description('My Description'); + $description = new Description('My Description'); $expectedArguments = [ - [ 'name' => 'argument1', 'type' => new String_() ], - [ 'name' => 'argument2', 'type' => new Void_() ] + ['name' => 'argument1', 'type' => new String_()], + ['name' => 'argument2', 'type' => new Mixed_()], ]; - $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); $fixture = Method::create( 'static void myMethod(string $argument1, $argument2) My Description', @@ -283,7 +301,10 @@ public function testFactoryMethod() $context ); - $this->assertSame('static void myMethod(string $argument1, void $argument2) My Description', (string)$fixture); + $this->assertSame( + 'static void myMethod(string $argument1, mixed $argument2) My Description', + (string) $fixture + ); $this->assertSame('myMethod', $fixture->getMethodName()); $this->assertEquals($expectedArguments, $fixture->getArguments()); $this->assertInstanceOf(Void_::class, $fixture->getReturnType()); @@ -291,19 +312,20 @@ public function testFactoryMethod() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testReturnTypeThis() + public function testReturnTypeThis() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); $context = new Context(''); - $description = new Description(''); + $description = new Description(''); $descriptionFactory->shouldReceive('create')->with('', $context)->andReturn($description); @@ -315,165 +337,182 @@ public function testReturnTypeThis() ); $this->assertTrue($fixture->isStatic()); - $this->assertSame('static $this myMethod()', (string)$fixture); + $this->assertSame('static $this myMethod()', (string) $fixture); $this->assertSame('myMethod', $fixture->getMethodName()); $this->assertInstanceOf(This::class, $fixture->getReturnType()); } - public function collectionReturnTypesProvider() + /** + * @return string[][] + */ + public function collectionReturnTypesProvider() : array { return [ - ['int[]', Array_::class, Integer::class, Compound::class], - ['int[][]', Array_::class, Array_::class, Compound::class], + ['int[]', Array_::class, Integer::class, Compound::class], + ['int[][]', Array_::class, Array_::class, Compound::class], ['Object[]', Array_::class, Object_::class, Compound::class], - ['array[]', Array_::class, Array_::class, Compound::class], + ['array[]', Array_::class, Array_::class, Compound::class], ]; } /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\Types\Array_ + * @uses \phpDocumentor\Reflection\Types\Compound + * @uses \phpDocumentor\Reflection\Types\Integer + * @uses \phpDocumentor\Reflection\Types\Object_ + * * @dataProvider collectionReturnTypesProvider * @covers ::create - * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: - * @uses \phpDocumentor\Reflection\DocBlock\Description - * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @uses \phpDocumentor\Reflection\TypeResolver - * @uses \phpDocumentor\Reflection\Types\Array_ - * @uses \phpDocumentor\Reflection\Types\Compound - * @uses \phpDocumentor\Reflection\Types\Integer - * @uses \phpDocumentor\Reflection\Types\Object_ - * @param string $returnType - * @param string $expectedType - * @param string $expectedValueType - * @param string null $expectedKeyType */ public function testCollectionReturnTypes( - $returnType, - $expectedType, - $expectedValueType = null, - $expectedKeyType = null - ) { + string $returnType, + string $expectedType, + ?string $expectedValueType = null, + ?string $expectedKeyType = null + ) : void { $resolver = new TypeResolver(); $descriptionFactory = m::mock(DescriptionFactory::class); - $descriptionFactory->shouldReceive('create')->with('', null)->andReturn(new Description('')); + $descriptionFactory->shouldReceive('create') + ->with('', null) + ->andReturn(new Description('')); - $fixture = Method::create("$returnType myMethod(\$arg)", $resolver, $descriptionFactory); + $fixture = Method::create("${returnType} myMethod(\$arg)", $resolver, $descriptionFactory); $returnType = $fixture->getReturnType(); $this->assertInstanceOf($expectedType, $returnType); - if ($returnType instanceof Array_) { - $this->assertInstanceOf($expectedValueType, $returnType->getValueType()); - $this->assertInstanceOf($expectedKeyType, $returnType->getKeyType()); + if (!($returnType instanceof Array_)) { + return; } - } - /** - * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - Method::create([]); + $this->assertInstanceOf($expectedValueType, $returnType->getValueType()); + $this->assertInstanceOf($expectedKeyType, $returnType->getKeyType()); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsEmpty() + public function testFactoryMethodFailsIfBodyIsEmpty() : void { + $this->expectException('InvalidArgumentException'); Method::create(''); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodReturnsNullIfBodyIsIncorrect() + public function testFactoryMethodReturnsNullIfBodyIsIncorrect() : void { + $this->expectException('InvalidArgumentException'); $this->assertNull(Method::create('body(')); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Method::create('body'); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Method::create('body', new TypeResolver()); } /** * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testCreationFailsIfBodyIsNotString() - { - new Method([]); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException */ - public function testCreationFailsIfBodyIsEmpty() + public function testCreationFailsIfBodyIsEmpty() : void { + $this->expectException('InvalidArgumentException'); new Method(''); } /** * @covers ::__construct - * @expectedException \InvalidArgumentException */ - public function testCreationFailsIfStaticIsNotBoolean() + public function testCreationFailsIfArgumentRecordContainsInvalidEntry() : void { - new Method('body', [], null, []); + $this->expectException('InvalidArgumentException'); + new Method('body', [['name' => 'myName', 'unknown' => 'nah']]); } /** - * @covers ::__construct - * @expectedException \InvalidArgumentException + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Fqsen + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testCreationFailsIfArgumentRecordContainsInvalidEntry() + public function testCreateMethodParenthesisMissing() : void { - new Method('body', [ [ 'name' => 'myName', 'unknown' => 'nah' ] ]); + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + + $descriptionFactory->shouldReceive('create')->with( + 'My Description', + $context + )->andReturn($description); + + $fixture = Method::create( + 'static void myMethod My Description', + $resolver, + $descriptionFactory, + $context + ); + + $this->assertSame('static void myMethod() My Description', (string) $fixture); + $this->assertSame('myMethod', $fixture->getMethodName()); + $this->assertEquals([], $fixture->getArguments()); + $this->assertInstanceOf(Void_::class, $fixture->getReturnType()); + $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testCreateMethodParenthesisMissing() + public function testCreateMethodEmptyArguments() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); $context = new Context(''); - $description = new Description('My Description'); + $description = new Description('My Description'); - $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); $fixture = Method::create( - 'static void myMethod My Description', + 'static void myMethod() My Description', $resolver, $descriptionFactory, $context ); - $this->assertSame('static void myMethod() My Description', (string)$fixture); + $this->assertSame('static void myMethod() My Description', (string) $fixture); $this->assertSame('myMethod', $fixture->getMethodName()); $this->assertEquals([], $fixture->getArguments()); $this->assertInstanceOf(Void_::class, $fixture->getReturnType()); @@ -481,7 +520,6 @@ public function testCreateMethodParenthesisMissing() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver @@ -489,14 +527,16 @@ public function testCreateMethodParenthesisMissing() * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\Types\Context * @uses \phpDocumentor\Reflection\Types\Void_ + * + * @covers ::create */ - public function testCreateWithoutReturnType() + public function testCreateWithoutReturnType() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); $context = new Context(''); - $description = new Description(''); + $description = new Description(''); $descriptionFactory->shouldReceive('create')->with('', $context)->andReturn($description); @@ -507,7 +547,7 @@ public function testCreateWithoutReturnType() $context ); - $this->assertSame('void myMethod()', (string)$fixture); + $this->assertSame('void myMethod()', (string) $fixture); $this->assertSame('myMethod', $fixture->getMethodName()); $this->assertEquals([], $fixture->getArguments()); $this->assertInstanceOf(Void_::class, $fixture->getReturnType()); @@ -515,7 +555,6 @@ public function testCreateWithoutReturnType() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver @@ -526,8 +565,10 @@ public function testCreateWithoutReturnType() * @uses \phpDocumentor\Reflection\Types\Compound * @uses \phpDocumentor\Reflection\Types\Integer * @uses \phpDocumentor\Reflection\Types\Object_ + * + * @covers ::create */ - public function testCreateWithMixedReturnTypes() + public function testCreateWithMixedReturnTypes() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); @@ -542,7 +583,7 @@ public function testCreateWithMixedReturnTypes() $context ); - $this->assertSame('\MyClass[]|int[] myMethod()', (string)$fixture); + $this->assertSame('\MyClass[]|int[] myMethod()', (string) $fixture); $this->assertSame('myMethod', $fixture->getMethodName()); $this->assertEquals([], $fixture->getArguments()); diff --git a/tests/unit/DocBlock/Tags/ParamTest.php b/tests/unit/DocBlock/Tags/ParamTest.php index 17737ab7..9e4513ab 100644 --- a/tests/unit/DocBlock/Tags/ParamTest.php +++ b/tests/unit/DocBlock/Tags/ParamTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -29,7 +30,7 @@ class ParamTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Param('myParameter', null, false, new Description('Description')); @@ -52,10 +54,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Param('myParameter', new String_(), true, new Description('Description')); $this->assertSame('@param string ...$myParameter Description', $fixture->render()); @@ -72,9 +75,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Param('myParameter'); @@ -88,7 +92,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVariableName */ - public function testHasVariableName() + public function testHasVariableName() : void { $expected = 'myParameter'; @@ -101,7 +105,7 @@ public function testHasVariableName() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -114,7 +118,7 @@ public function testHasType() * @covers ::__construct * @covers ::isVariadic */ - public function testIfParameterIsVariadic() + public function testIfParameterIsVariadic() : void { $fixture = new Param('myParameter', new String_(), false); $this->assertFalse($fixture->isVariadic()); @@ -124,11 +128,12 @@ public function testIfParameterIsVariadic() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -138,38 +143,40 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * * @covers ::__construct * @covers ::isVariadic * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description - * @uses \phpDocumentor\Reflection\Types\String_ */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Param('myParameter', new String_(), true, new Description('Description')); - $this->assertSame('string ...$myParameter Description', (string)$fixture); + $this->assertSame('string ...$myParameter Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { - $typeResolver = new TypeResolver(); + $typeResolver = new TypeResolver(); $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); $fixture = Param::create('string ...$myParameter My Description', $typeResolver, $descriptionFactory, $context); - $this->assertSame('string ...$myParameter My Description', (string)$fixture); + $this->assertSame('string ...$myParameter My Description', (string) $fixture); $this->assertSame('myParameter', $fixture->getVariableName()); $this->assertInstanceOf(String_::class, $fixture->getType()); $this->assertTrue($fixture->isVariadic()); @@ -177,61 +184,36 @@ public function testFactoryMethod() } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Param:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfEmptyBodyIsGiven() + public function testFactoryMethodFailsIfEmptyBodyIsGiven() : void { + $this->expectException('InvalidArgumentException'); $descriptionFactory = m::mock(DescriptionFactory::class); Param::create('', new TypeResolver(), $descriptionFactory); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - Param::create([]); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Param::create('body'); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\TypeResolver - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Param::create('body', new TypeResolver()); } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfVariableNameIsNotString() - { - new Param([]); - } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfVariadicIsNotBoolean() - { - new Param('', null, []); - } } diff --git a/tests/unit/DocBlock/Tags/PropertyReadTest.php b/tests/unit/DocBlock/Tags/PropertyReadTest.php index 003bb4c2..901b0907 100644 --- a/tests/unit/DocBlock/Tags/PropertyReadTest.php +++ b/tests/unit/DocBlock/Tags/PropertyReadTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -29,7 +30,7 @@ class PropertyReadTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyRead::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new PropertyRead('myProperty', null, new Description('Description')); @@ -51,10 +53,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyRead::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new PropertyRead('myProperty', new String_(), new Description('Description')); $this->assertSame('@property-read string $myProperty Description', $fixture->render()); @@ -68,9 +71,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyRead::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new PropertyRead('myProperty'); @@ -84,7 +88,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVariableName */ - public function testHasVariableName() + public function testHasVariableName() : void { $expected = 'myProperty'; @@ -97,7 +101,7 @@ public function testHasVariableName() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -107,11 +111,12 @@ public function testHasType() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -121,30 +126,32 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new PropertyRead('myProperty', new String_(), new Description('Description')); - $this->assertSame('string $myProperty Description', (string)$fixture); + $this->assertSame('string $myProperty Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyRead:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { - $typeResolver = new TypeResolver(); + $typeResolver = new TypeResolver(); $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); @@ -156,59 +163,43 @@ public function testFactoryMethod() $context ); - $this->assertSame('string $myProperty My Description', (string)$fixture); + $this->assertSame('string $myProperty My Description', (string) $fixture); $this->assertSame('myProperty', $fixture->getVariableName()); $this->assertInstanceOf(String_::class, $fixture->getType()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyRead:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfEmptyBodyIsGiven() + public function testFactoryMethodFailsIfEmptyBodyIsGiven() : void { + $this->expectException('InvalidArgumentException'); $descriptionFactory = m::mock(DescriptionFactory::class); PropertyRead::create('', new TypeResolver(), $descriptionFactory); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - PropertyRead::create([]); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); PropertyRead::create('body'); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\TypeResolver - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); PropertyRead::create('body', new TypeResolver()); } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfVariableNameIsNotString() - { - new PropertyRead([]); - } } diff --git a/tests/unit/DocBlock/Tags/PropertyTest.php b/tests/unit/DocBlock/Tags/PropertyTest.php index 90f69d85..ec0e7fc3 100644 --- a/tests/unit/DocBlock/Tags/PropertyTest.php +++ b/tests/unit/DocBlock/Tags/PropertyTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -29,7 +30,7 @@ class PropertyTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Property::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Property('myProperty', null, new Description('Description')); @@ -51,10 +53,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Property::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Property('myProperty', new String_(), new Description('Description')); $this->assertSame('@property string $myProperty Description', $fixture->render()); @@ -68,9 +71,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Property::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Property('myProperty'); @@ -84,7 +88,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVariableName */ - public function testHasVariableName() + public function testHasVariableName() : void { $expected = 'myProperty'; @@ -97,7 +101,7 @@ public function testHasVariableName() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -107,11 +111,12 @@ public function testHasType() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -121,89 +126,75 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Property('myProperty', new String_(), new Description('Description')); - $this->assertSame('string $myProperty Description', (string)$fixture); + $this->assertSame('string $myProperty Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Property:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { - $typeResolver = new TypeResolver(); + $typeResolver = new TypeResolver(); $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); $fixture = Property::create('string $myProperty My Description', $typeResolver, $descriptionFactory, $context); - $this->assertSame('string $myProperty My Description', (string)$fixture); + $this->assertSame('string $myProperty My Description', (string) $fixture); $this->assertSame('myProperty', $fixture->getVariableName()); $this->assertInstanceOf(String_::class, $fixture->getType()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Property:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfEmptyBodyIsGiven() + public function testFactoryMethodFailsIfEmptyBodyIsGiven() : void { + $this->expectException('InvalidArgumentException'); $descriptionFactory = m::mock(DescriptionFactory::class); Property::create('', new TypeResolver(), $descriptionFactory); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - Property::create([]); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Property::create('body'); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\TypeResolver - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Property::create('body', new TypeResolver()); } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfVariableNameIsNotString() - { - new Property([]); - } } diff --git a/tests/unit/DocBlock/Tags/PropertyWriteTest.php b/tests/unit/DocBlock/Tags/PropertyWriteTest.php index 96fbfef6..1c6124c2 100644 --- a/tests/unit/DocBlock/Tags/PropertyWriteTest.php +++ b/tests/unit/DocBlock/Tags/PropertyWriteTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -29,7 +30,7 @@ class PropertyWriteTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new PropertyWrite('myProperty', null, new Description('Description')); @@ -51,10 +53,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new PropertyWrite('myProperty', new String_(), new Description('Description')); $this->assertSame('@property-write string $myProperty Description', $fixture->render()); @@ -68,9 +71,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new PropertyWrite('myProperty'); @@ -84,7 +88,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVariableName */ - public function testHasVariableName() + public function testHasVariableName() : void { $expected = 'myProperty'; @@ -97,7 +101,7 @@ public function testHasVariableName() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -107,11 +111,12 @@ public function testHasType() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -121,30 +126,32 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new PropertyWrite('myProperty', new String_(), new Description('Description')); - $this->assertSame('string $myProperty Description', (string)$fixture); + $this->assertSame('string $myProperty Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { - $typeResolver = new TypeResolver(); + $typeResolver = new TypeResolver(); $descriptionFactory = m::mock(DescriptionFactory::class); - $context = new Context(''); + $context = new Context(''); $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); @@ -156,59 +163,43 @@ public function testFactoryMethod() $context ); - $this->assertSame('string $myProperty My Description', (string)$fixture); + $this->assertSame('string $myProperty My Description', (string) $fixture); $this->assertSame('myProperty', $fixture->getVariableName()); $this->assertInstanceOf(String_::class, $fixture->getType()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfEmptyBodyIsGiven() + public function testFactoryMethodFailsIfEmptyBodyIsGiven() : void { + $this->expectException('InvalidArgumentException'); $descriptionFactory = m::mock(DescriptionFactory::class); PropertyWrite::create('', new TypeResolver(), $descriptionFactory); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - PropertyWrite::create([]); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); PropertyWrite::create('body'); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\TypeResolver - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); PropertyWrite::create('body', new TypeResolver()); } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfVariableNameIsNotString() - { - new PropertyWrite([]); - } } diff --git a/tests/unit/DocBlock/Tags/ReturnTest.php b/tests/unit/DocBlock/Tags/ReturnTest.php index 335cd5e9..aad958ce 100644 --- a/tests/unit/DocBlock/Tags/ReturnTest.php +++ b/tests/unit/DocBlock/Tags/ReturnTest.php @@ -1,17 +1,19 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; +use InvalidArgumentException; use Mockery as m; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; @@ -29,7 +31,7 @@ class ReturnTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +39,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Return_(new String_(), new Description('Description')); @@ -51,10 +54,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Return_(new String_(), new Description('Description')); @@ -64,9 +68,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Return_(new String_(), new Description('Description')); @@ -80,7 +85,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -90,11 +95,12 @@ public function testHasType() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -104,76 +110,163 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Return_(new String_(), new Description('Description')); - $this->assertSame('string Description', (string)$fixture); + $this->assertSame('string Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $resolver = new TypeResolver(); - $context = new Context(''); + $resolver = new TypeResolver(); + $context = new Context(''); - $type = new String_(); + $type = new String_(); $description = new Description('My Description'); $descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description); $fixture = Return_::create('string My Description', $resolver, $descriptionFactory, $context); - $this->assertSame('string My Description', (string)$fixture); + $this->assertSame('string My Description', (string) $fixture); $this->assertEquals($type, $fixture->getType()); $this->assertSame($description, $fixture->getDescription()); } /** + * This test checks whether a braces in a Type are allowed. + * + * The advent of generics poses a few issues, one of them is that spaces can now be part of a type. In the past we + * could purely rely on spaces to split the individual parts of the body of a tag; but when there is a type in play + * we now need to check for braces. + * + * This test tests whether an error occurs demonstrating that the braces were taken into account; this test is still + * expected to produce an exception because the TypeResolver does not support generics. + * + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * @uses \phpDocumentor\Reflection\Types\Context + * * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotString() + public function testFactoryMethodWithGenericWithSpace() : void { - $this->assertNull(Return_::create([])); + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); + + $fixture = Return_::create('array My Description', $resolver, $descriptionFactory, $context); + + $this->assertSame('array My Description', (string) $fixture); + $this->assertEquals('array', $fixture->getType()); + $this->assertSame($description, $fixture->getDescription()); + } + + /** + * @see self::testFactoryMethodWithGenericWithSpace() + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create + */ + public function testFactoryMethodWithGenericWithSpaceAndAddedEmojisToVerifyMultiByteBehaviour() : void + { + $this->markTestSkipped('A bug in the TypeResolver breaks this test'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('"\array😁" is not a valid Fqsen.'); + + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); + + Return_::create('array😁 My Description', $resolver, $descriptionFactory, $context); + } + + /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Return_:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create + */ + public function testFactoryMethodWithEmojisToVerifyMultiByteBehaviour() : void + { + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); + + $fixture = Return_::create('\My😁Class My Description', $resolver, $descriptionFactory, $context); + + $this->assertSame('\My😁Class My Description', (string) $fixture); + $this->assertEquals('\My😁Class', $fixture->getType()); + $this->assertSame($description, $fixture->getDescription()); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotEmpty() + public function testFactoryMethodFailsIfBodyIsNotEmpty() : void { + $this->expectException('InvalidArgumentException'); $this->assertNull(Return_::create('')); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Return_::create('body'); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Return_::create('body', new TypeResolver()); } } diff --git a/tests/unit/DocBlock/Tags/SeeTest.php b/tests/unit/DocBlock/Tags/SeeTest.php index ae4fa53c..f9ed04c0 100644 --- a/tests/unit/DocBlock/Tags/SeeTest.php +++ b/tests/unit/DocBlock/Tags/SeeTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -31,7 +32,7 @@ class SeeTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -41,9 +42,10 @@ public function tearDown() * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen * @uses \phpDocumentor\Reflection\Fqsen + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new See(new FqsenRef(new Fqsen('\DateTime')), new Description('Description')); @@ -56,10 +58,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new See(new FqsenRef(new Fqsen('\DateTime')), new Description('Description')); @@ -71,9 +74,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen * @uses \phpDocumentor\Reflection\Fqsen + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new See(new FqsenRef(new Fqsen('\DateTime')), new Description('Description')); @@ -86,10 +90,11 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen * @uses \phpDocumentor\Reflection\Fqsen + * * @covers ::__construct * @covers ::getReference */ - public function testHasReferenceToFqsen() + public function testHasReferenceToFqsen() : void { $expected = new FqsenRef(new Fqsen('\DateTime')); @@ -99,13 +104,14 @@ public function testHasReferenceToFqsen() } /** - * @covers ::__construct - * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen * @uses \phpDocumentor\Reflection\Fqsen + * + * @covers ::__construct + * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -115,21 +121,21 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen * @uses \phpDocumentor\Reflection\Fqsen + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new See(new FqsenRef(new Fqsen('\DateTime::format()')), new Description('Description')); - $this->assertSame('\DateTime::format() Description', (string)$fixture); + $this->assertSame('\DateTime::format() Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\See:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\FqsenResolver @@ -137,14 +143,16 @@ public function testStringRepresentationIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $resolver = m::mock(FqsenResolver::class); - $context = new Context(''); + $resolver = m::mock(FqsenResolver::class); + $context = new Context(''); - $fqsen = new Fqsen('\DateTime'); + $fqsen = new Fqsen('\DateTime'); $description = new Description('My Description'); $descriptionFactory @@ -153,26 +161,27 @@ public function testFactoryMethod() $fixture = See::create('DateTime My Description', $resolver, $descriptionFactory, $context); - $this->assertSame('\DateTime My Description', (string)$fixture); + $this->assertSame('\DateTime My Description', (string) $fixture); $this->assertInstanceOf(FqsenRef::class, $fixture->getReference()); - $this->assertSame((string)$fqsen, (string)$fixture->getReference()); + $this->assertSame((string) $fqsen, (string) $fixture->getReference()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\See:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\FqsenResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Url * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethodWithUrl() + public function testFactoryMethodWithUrl() : void { $descriptionFactory = m::mock(DescriptionFactory::class); - $resolver = m::mock(FqsenResolver::class); - $context = new Context(''); + $resolver = m::mock(FqsenResolver::class); + $context = new Context(''); $description = new Description('My Description'); @@ -183,45 +192,36 @@ public function testFactoryMethodWithUrl() $fixture = See::create('https://test.org My Description', $resolver, $descriptionFactory, $context); - $this->assertSame('https://test.org My Description', (string)$fixture); + $this->assertSame('https://test.org My Description', (string) $fixture); $this->assertInstanceOf(UrlRef::class, $fixture->getReference()); - $this->assertSame('https://test.org', (string)$fixture->getReference()); + $this->assertSame('https://test.org', (string) $fixture->getReference()); $this->assertSame($description, $fixture->getDescription()); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - $this->assertNull(See::create([])); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotEmpty() + public function testFactoryMethodFailsIfBodyIsNotEmpty() : void { + $this->expectException('InvalidArgumentException'); $this->assertNull(See::create('')); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); See::create('body'); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); See::create('body', new FqsenResolver()); } } diff --git a/tests/unit/DocBlock/Tags/SinceTest.php b/tests/unit/DocBlock/Tags/SinceTest.php index 778c0d75..ff926d2c 100644 --- a/tests/unit/DocBlock/Tags/SinceTest.php +++ b/tests/unit/DocBlock/Tags/SinceTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -24,11 +25,10 @@ */ class SinceTest extends TestCase { - /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -36,9 +36,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Since::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Since('1.0', new Description('Description')); @@ -50,10 +51,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Since::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Since('1.0', new Description('Description')); @@ -63,9 +65,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Since::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Since('1.0', new Description('Description')); @@ -79,7 +82,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVersion */ - public function testHasVersionNumber() + public function testHasVersionNumber() : void { $expected = '1.0'; @@ -89,11 +92,12 @@ public function testHasVersionNumber() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -103,25 +107,27 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Since('1.0', new Description('Description')); - $this->assertSame('1.0 Description', (string)$fixture); + $this->assertSame('1.0 Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Since:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $context = new Context(''); @@ -133,43 +139,35 @@ public function testFactoryMethod() $fixture = Since::create('1.0 My Description', $descriptionFactory, $context); - $this->assertSame('1.0 My Description', (string)$fixture); + $this->assertSame('1.0 My Description', (string) $fixture); $this->assertSame($version, $fixture->getVersion()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Since:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethodCreatesEmptySinceTag() + public function testFactoryMethodCreatesEmptySinceTag() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $descriptionFactory->shouldReceive('create')->never(); $fixture = Since::create('', $descriptionFactory, new Context('')); - $this->assertSame('', (string)$fixture); + $this->assertSame('', (string) $fixture); $this->assertSame(null, $fixture->getVersion()); $this->assertSame(null, $fixture->getDescription()); } - /** - * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfSinceIsNotString() - { - $this->assertNull(Since::create([])); - } - /** * @covers ::create */ - public function testFactoryMethodReturnsNullIfBodyDoesNotMatchRegex() + public function testFactoryMethodReturnsNullIfBodyDoesNotMatchRegex() : void { $this->assertNull(Since::create('dkhf<')); } diff --git a/tests/unit/DocBlock/Tags/SourceTest.php b/tests/unit/DocBlock/Tags/SourceTest.php index 810607dc..178d16e0 100644 --- a/tests/unit/DocBlock/Tags/SourceTest.php +++ b/tests/unit/DocBlock/Tags/SourceTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -27,7 +28,7 @@ class SourceTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -35,9 +36,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Source::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Source(1, null, new Description('Description')); @@ -49,10 +51,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Source::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Source(1, 10, new Description('Description')); $this->assertSame('@source 1 10 Description', $fixture->render()); @@ -66,9 +69,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Source::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Source(1); @@ -82,7 +86,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getStartingLine */ - public function testHasStartingLine() + public function testHasStartingLine() : void { $expected = 1; @@ -95,7 +99,7 @@ public function testHasStartingLine() * @covers ::__construct * @covers ::getLineCount */ - public function testHasLineCount() + public function testHasLineCount() : void { $expected = 2; @@ -105,11 +109,12 @@ public function testHasLineCount() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -119,26 +124,28 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Source(1, 10, new Description('Description')); - $this->assertSame('1 10 Description', (string)$fixture); + $this->assertSame('1 10 Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Source:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $context = new Context(''); @@ -148,59 +155,52 @@ public function testFactoryMethod() $fixture = Source::create('1 10 My Description', $descriptionFactory, $context); - $this->assertSame('1 10 My Description', (string)$fixture); + $this->assertSame('1 10 My Description', (string) $fixture); $this->assertSame(1, $fixture->getStartingLine()); $this->assertSame(10, $fixture->getLineCount()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Source:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfEmptyBodyIsGiven() + public function testFactoryMethodFailsIfEmptyBodyIsGiven() : void { + $this->expectException('InvalidArgumentException'); $descriptionFactory = m::mock(DescriptionFactory::class); Source::create('', $descriptionFactory); } /** - * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - Source::create([]); - } - - /** - * @covers ::create * @uses \phpDocumentor\Reflection\TypeResolver - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Source::create('1'); } /** * @covers ::__construct - * @expectedException \InvalidArgumentException */ - public function testExceptionIsThrownIfStartingLineIsNotInteger() + public function testExceptionIsThrownIfStartingLineIsNotInteger() : void { + $this->expectException('InvalidArgumentException'); new Source('blabla'); } /** * @covers ::__construct - * @expectedException \InvalidArgumentException */ - public function testExceptionIsThrownIfLineCountIsNotIntegerOrNull() + public function testExceptionIsThrownIfLineCountIsNotIntegerOrNull() : void { + $this->expectException('InvalidArgumentException'); new Source('1', []); } } diff --git a/tests/unit/DocBlock/Tags/ThrowsTest.php b/tests/unit/DocBlock/Tags/ThrowsTest.php index 5747e8f5..ab1f759a 100644 --- a/tests/unit/DocBlock/Tags/ThrowsTest.php +++ b/tests/unit/DocBlock/Tags/ThrowsTest.php @@ -1,17 +1,19 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; +use InvalidArgumentException; use Mockery as m; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; @@ -29,7 +31,7 @@ class ThrowsTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +39,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Throws(new String_(), new Description('Description')); @@ -51,10 +54,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Throws(new String_(), new Description('Description')); @@ -64,9 +68,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Throws(new String_(), new Description('Description')); @@ -80,7 +85,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -90,11 +95,12 @@ public function testHasType() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -104,27 +110,29 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Throws(new String_(), new Description('Description')); - $this->assertSame('string Description', (string)$fixture); + $this->assertSame('string Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = new TypeResolver(); @@ -136,44 +144,129 @@ public function testFactoryMethod() $fixture = Throws::create('string My Description', $resolver, $descriptionFactory, $context); - $this->assertSame('string My Description', (string)$fixture); + $this->assertSame('string My Description', (string) $fixture); $this->assertEquals($type, $fixture->getType()); $this->assertSame($description, $fixture->getDescription()); } /** + * This test checks whether a braces in a Type are allowed. + * + * The advent of generics poses a few issues, one of them is that spaces can now be part of a type. In the past we + * could purely rely on spaces to split the individual parts of the body of a tag; but when there is a type in play + * we now need to check for braces. + * + * This test tests whether an error occurs demonstrating that the braces were taken into account; this test is still + * expected to produce an exception because the TypeResolver does not support generics. + * + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * @uses \phpDocumentor\Reflection\Types\Context + * * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotString() + public function testFactoryMethodWithGenericWithSpace() : void { - $this->assertNull(Throws::create([])); + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); + + $fixture = Throws::create('array My Description', $resolver, $descriptionFactory, $context); + + $this->assertSame('array My Description', (string) $fixture); + $this->assertEquals('array', $fixture->getType()); + $this->assertSame($description, $fixture->getDescription()); + } + + /** + * @see self::testFactoryMethodWithGenericWithSpace() + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create + */ + public function testFactoryMethodWithGenericWithSpaceAndAddedEmojisToVerifyMultiByteBehaviour() : void + { + $this->markTestSkipped('A bug in the TypeResolver breaks this test'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('"\array😁" is not a valid Fqsen.'); + + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); + + Throws::create('array😁 My Description', $resolver, $descriptionFactory, $context); + } + + /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Throws:: + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\TypeResolver + * @uses \phpDocumentor\Reflection\DocBlock\Description + * @uses \phpDocumentor\Reflection\Types\String_ + * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create + */ + public function testFactoryMethodWithEmojisToVerifyMultiByteBehaviour() : void + { + $descriptionFactory = m::mock(DescriptionFactory::class); + $resolver = new TypeResolver(); + $context = new Context(''); + + $description = new Description('My Description'); + $descriptionFactory->shouldReceive('create') + ->with('My Description', $context) + ->andReturn($description); + + $fixture = Throws::create('\My😁Class My Description', $resolver, $descriptionFactory, $context); + + $this->assertSame('\My😁Class My Description', (string) $fixture); + $this->assertEquals('\My😁Class', $fixture->getType()); + $this->assertSame($description, $fixture->getDescription()); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotEmpty() + public function testFactoryMethodFailsIfBodyIsNotEmpty() : void { + $this->expectException('InvalidArgumentException'); $this->assertNull(Throws::create('')); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Throws::create('body'); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Throws::create('body', new TypeResolver()); } } diff --git a/tests/unit/DocBlock/Tags/UsesTest.php b/tests/unit/DocBlock/Tags/UsesTest.php index 02ec7637..979a6751 100644 --- a/tests/unit/DocBlock/Tags/UsesTest.php +++ b/tests/unit/DocBlock/Tags/UsesTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -29,7 +30,7 @@ class UsesTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Uses::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Uses(new Fqsen('\DateTime'), new Description('Description')); @@ -51,10 +53,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Uses::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Uses(new Fqsen('\DateTime'), new Description('Description')); @@ -64,9 +67,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Uses::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Uses(new Fqsen('\DateTime'), new Description('Description')); @@ -80,7 +84,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getReference */ - public function testHasReferenceToFqsen() + public function testHasReferenceToFqsen() : void { $expected = new Fqsen('\DateTime'); @@ -90,11 +94,12 @@ public function testHasReferenceToFqsen() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -104,27 +109,29 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Uses(new Fqsen('\DateTime'), new Description('Description')); - $this->assertSame('\DateTime Description', (string)$fixture); + $this->assertSame('\DateTime Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Uses:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\FqsenResolver * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Fqsen * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $resolver = m::mock(FqsenResolver::class); @@ -139,44 +146,35 @@ public function testFactoryMethod() $fixture = Uses::create('DateTime My Description', $resolver, $descriptionFactory, $context); - $this->assertSame('\DateTime My Description', (string)$fixture); + $this->assertSame('\DateTime My Description', (string) $fixture); $this->assertSame($fqsen, $fixture->getReference()); $this->assertSame($description, $fixture->getDescription()); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - $this->assertNull(Uses::create([])); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfBodyIsNotEmpty() + public function testFactoryMethodFailsIfBodyIsNotEmpty() : void { + $this->expectException('InvalidArgumentException'); $this->assertNull(Uses::create('')); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Uses::create('body'); } /** * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Uses::create('body', new FqsenResolver()); } } diff --git a/tests/unit/DocBlock/Tags/VarTest.php b/tests/unit/DocBlock/Tags/VarTest.php index 49a72ef7..409263ed 100644 --- a/tests/unit/DocBlock/Tags/VarTest.php +++ b/tests/unit/DocBlock/Tags/VarTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -29,7 +30,7 @@ class VarTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -37,9 +38,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Var_::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Var_('myVariable', null, new Description('Description')); @@ -48,9 +50,10 @@ public function testIfCorrectTagNameIsReturned() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Var_::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfVariableNameIsOmmitedIfEmpty() + public function testIfVariableNameIsOmmitedIfEmpty() : void { $fixture = new Var_('', null, null); @@ -62,10 +65,11 @@ public function testIfVariableNameIsOmmitedIfEmpty() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Var_::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Var_('myVariable', new String_(), new Description('Description')); $this->assertSame('@var string $myVariable Description', $fixture->render()); @@ -79,9 +83,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Var_::__construct + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Var_('myVariable'); @@ -95,7 +100,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVariableName */ - public function testHasVariableName() + public function testHasVariableName() : void { $expected = 'myVariable'; @@ -108,7 +113,7 @@ public function testHasVariableName() * @covers ::__construct * @covers ::getType */ - public function testHasType() + public function testHasType() : void { $expected = new String_(); @@ -118,11 +123,12 @@ public function testHasType() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -132,26 +138,28 @@ public function testHasDescription() } /** - * @covers ::__construct - * @covers ::__toString * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\String_ + * + * @covers ::__construct + * @covers ::__toString */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Var_('myVariable', new String_(), new Description('Description')); - $this->assertSame('string $myVariable Description', (string)$fixture); + $this->assertSame('string $myVariable Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Var_:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $typeResolver = new TypeResolver(); $descriptionFactory = m::mock(DescriptionFactory::class); @@ -162,59 +170,43 @@ public function testFactoryMethod() $fixture = Var_::create('string $myVariable My Description', $typeResolver, $descriptionFactory, $context); - $this->assertSame('string $myVariable My Description', (string)$fixture); + $this->assertSame('string $myVariable My Description', (string) $fixture); $this->assertSame('myVariable', $fixture->getVariableName()); $this->assertInstanceOf(String_::class, $fixture->getType()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Var_:: * @uses \phpDocumentor\Reflection\TypeResolver * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfEmptyBodyIsGiven() + public function testFactoryMethodFailsIfEmptyBodyIsGiven() : void { + $this->expectException('InvalidArgumentException'); $descriptionFactory = m::mock(DescriptionFactory::class); Var_::create('', new TypeResolver(), $descriptionFactory); } /** * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfBodyIsNotString() - { - Var_::create([]); - } - - /** - * @covers ::create - * @expectedException \InvalidArgumentException */ - public function testFactoryMethodFailsIfResolverIsNull() + public function testFactoryMethodFailsIfResolverIsNull() : void { + $this->expectException('InvalidArgumentException'); Var_::create('body'); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\TypeResolver - * @expectedException \InvalidArgumentException + * + * @covers ::create */ - public function testFactoryMethodFailsIfDescriptionFactoryIsNull() + public function testFactoryMethodFailsIfDescriptionFactoryIsNull() : void { + $this->expectException('InvalidArgumentException'); Var_::create('body', new TypeResolver()); } - - /** - * @covers ::__construct - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfVariableNameIsNotString() - { - new Var_([]); - } } diff --git a/tests/unit/DocBlock/Tags/VersionTest.php b/tests/unit/DocBlock/Tags/VersionTest.php index 4ccc1592..04ce027e 100644 --- a/tests/unit/DocBlock/Tags/VersionTest.php +++ b/tests/unit/DocBlock/Tags/VersionTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -27,7 +28,7 @@ class VersionTest extends TestCase /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } @@ -35,9 +36,10 @@ public function tearDown() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfCorrectTagNameIsReturned() + public function testIfCorrectTagNameIsReturned() : void { $fixture = new Version('1.0', new Description('Description')); @@ -49,10 +51,11 @@ public function testIfCorrectTagNameIsReturned() * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version::__toString * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName */ - public function testIfTagCanBeRenderedUsingDefaultFormatter() + public function testIfTagCanBeRenderedUsingDefaultFormatter() : void { $fixture = new Version('1.0', new Description('Description')); @@ -62,9 +65,10 @@ public function testIfTagCanBeRenderedUsingDefaultFormatter() /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version::__construct * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render */ - public function testIfTagCanBeRenderedUsingSpecificFormatter() + public function testIfTagCanBeRenderedUsingSpecificFormatter() : void { $fixture = new Version('1.0', new Description('Description')); @@ -78,7 +82,7 @@ public function testIfTagCanBeRenderedUsingSpecificFormatter() * @covers ::__construct * @covers ::getVersion */ - public function testHasVersionNumber() + public function testHasVersionNumber() : void { $expected = '1.0'; @@ -88,11 +92,12 @@ public function testHasVersionNumber() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testHasDescription() + public function testHasDescription() : void { $expected = new Description('Description'); @@ -102,25 +107,27 @@ public function testHasDescription() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testStringRepresentationIsReturned() + public function testStringRepresentationIsReturned() : void { $fixture = new Version('1.0', new Description('Description')); - $this->assertSame('1.0 Description', (string)$fixture); + $this->assertSame('1.0 Description', (string) $fixture); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethod() + public function testFactoryMethod() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $context = new Context(''); @@ -132,43 +139,35 @@ public function testFactoryMethod() $fixture = Version::create('1.0 My Description', $descriptionFactory, $context); - $this->assertSame('1.0 My Description', (string)$fixture); + $this->assertSame('1.0 My Description', (string) $fixture); $this->assertSame($version, $fixture->getVersion()); $this->assertSame($description, $fixture->getDescription()); } /** - * @covers ::create * @uses \phpDocumentor\Reflection\DocBlock\Tags\Version:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Types\Context + * + * @covers ::create */ - public function testFactoryMethodCreatesEmptyVersionTag() + public function testFactoryMethodCreatesEmptyVersionTag() : void { $descriptionFactory = m::mock(DescriptionFactory::class); $descriptionFactory->shouldReceive('create')->never(); $fixture = Version::create('', $descriptionFactory, new Context('')); - $this->assertSame('', (string)$fixture); + $this->assertSame('', (string) $fixture); $this->assertSame(null, $fixture->getVersion()); $this->assertSame(null, $fixture->getDescription()); } - /** - * @covers ::create - * @expectedException \InvalidArgumentException - */ - public function testFactoryMethodFailsIfVersionIsNotString() - { - $this->assertNull(Version::create([])); - } - /** * @covers ::create */ - public function testFactoryMethodReturnsNullIfBodyDoesNotMatchRegex() + public function testFactoryMethodReturnsNullIfBodyDoesNotMatchRegex() : void { $this->assertNull(Version::create('dkhf<')); } diff --git a/tests/unit/DocBlockFactoryTest.php b/tests/unit/DocBlockFactoryTest.php index 4bb91ad9..2298a01a 100644 --- a/tests/unit/DocBlockFactoryTest.php +++ b/tests/unit/DocBlockFactoryTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -20,30 +21,33 @@ use phpDocumentor\Reflection\DocBlock\Tags\Param; use phpDocumentor\Reflection\Types\Context; use PHPUnit\Framework\TestCase; +use ReflectionClass; /** - * @coversDefaultClass phpDocumentor\Reflection\DocBlockFactory - * @covers :: * @uses \Webmozart\Assert\Assert - * @uses phpDocumentor\Reflection\DocBlock + * @uses \phpDocumentor\Reflection\DocBlock + * + * @coversDefaultClass \phpDocumentor\Reflection\DocBlockFactory + * @covers :: */ class DocBlockFactoryTest extends TestCase { /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** - * @covers ::__construct - * @covers ::createInstance * @uses \phpDocumentor\Reflection\DocBlock\StandardTagFactory * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * + * @covers ::__construct + * @covers ::createInstance */ - public function testCreateFactoryUsingFactoryMethod() + public function testCreateFactoryUsingFactoryMethod() : void { $fixture = DocBlockFactory::createInstance(); @@ -51,16 +55,17 @@ public function testCreateFactoryUsingFactoryMethod() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testCreateDocBlockFromReflection() + public function testCreateDocBlockFromReflection() : void { $fixture = new DocBlockFactory(m::mock(DescriptionFactory::class), m::mock(TagFactory::class)); $docBlock = '/** This is a DocBlock */'; - $classReflector = m::mock(\ReflectionClass::class); + $classReflector = m::mock(ReflectionClass::class); $classReflector->shouldReceive('getDocComment')->andReturn($docBlock); $docblock = $fixture->create($classReflector); @@ -73,11 +78,12 @@ public function testCreateDocBlockFromReflection() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testCreateDocBlockFromStringWithDocComment() + public function testCreateDocBlockFromStringWithDocComment() : void { $fixture = new DocBlockFactory(m::mock(DescriptionFactory::class), m::mock(TagFactory::class)); @@ -92,11 +98,12 @@ public function testCreateDocBlockFromStringWithDocComment() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::create * @covers ::__construct - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testCreateDocBlockFromStringWithoutDocComment() + public function testCreateDocBlockFromStringWithoutDocComment() : void { $fixture = new DocBlockFactory(m::mock(DescriptionFactory::class), m::mock(TagFactory::class)); @@ -111,13 +118,15 @@ public function testCreateDocBlockFromStringWithoutDocComment() } /** + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @uses phpDocumentor\Reflection\DocBlock\Description + * * @dataProvider provideSummaryAndDescriptions */ - public function testSummaryAndDescriptionAreSeparated($given, $summary, $description) + public function testSummaryAndDescriptionAreSeparated(string $given, string $summary, string $description) : void { $tagFactory = m::mock(TagFactory::class); $fixture = new DocBlockFactory(new DescriptionFactory($tagFactory), $tagFactory); @@ -129,12 +138,13 @@ public function testSummaryAndDescriptionAreSeparated($given, $summary, $descrip } /** + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testDescriptionsRetainFormatting() + public function testDescriptionsRetainFormatting() : void { $tagFactory = m::mock(TagFactory::class); $fixture = new DocBlockFactory(new DescriptionFactory($tagFactory), $tagFactory); @@ -162,12 +172,13 @@ public function testDescriptionsRetainFormatting() } /** + * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::create - * @uses phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @uses phpDocumentor\Reflection\DocBlock\Description */ - public function testTagsAreInterpretedUsingFactory() + public function testTagsAreInterpretedUsingFactory() : void { $tagString = << This is with @@ -194,23 +205,26 @@ public function testTagsAreInterpretedUsingFactory() $this->assertEquals([$tag], $docblock->getTags()); } - public function provideSummaryAndDescriptions() + /** + * @return string[] + */ + public function provideSummaryAndDescriptions() : array { return [ ['This is a DocBlock', 'This is a DocBlock', ''], [ 'This is a DocBlock. This should still be summary.', 'This is a DocBlock. This should still be summary.', - '' + '', ], [ <<shouldReceive('create')->with(m::any(), $context)->andReturn(new Param('param')); $docblock = $fixture->create('/** @param MyType $param */', $context); - } - - /** - * @covers ::__construct - * @covers ::create - * - * @uses phpDocumentor\Reflection\DocBlock\DescriptionFactory - * @uses phpDocumentor\Reflection\DocBlock\Description - */ - public function testTagsAreFilteredForNullValues() - { - $tagString = << This is with - multiline description. -TAG; - - $tagFactory = m::mock(TagFactory::class); - $tagFactory->shouldReceive('create')->with($tagString, m::any())->andReturn(null); - - $fixture = new DocBlockFactory(new DescriptionFactory($tagFactory), $tagFactory); - $given = << This is with - * multiline description. - */ -DOCBLOCK; - - $docblock = $fixture->create($given, new Context('')); - - $this->assertEquals([], $docblock->getTags()); + $this->assertInstanceOf(DocBlock::class, $docblock); } } diff --git a/tests/unit/DocBlockTest.php b/tests/unit/DocBlockTest.php index ca1edc56..e6cbfe37 100644 --- a/tests/unit/DocBlockTest.php +++ b/tests/unit/DocBlockTest.php @@ -1,12 +1,13 @@ - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,27 +19,28 @@ use PHPUnit\Framework\TestCase; /** + * @uses \Webmozart\Assert\Assert + * * @coversDefaultClass phpDocumentor\Reflection\DocBlock * @covers :: - * @uses \Webmozart\Assert\Assert */ class DocBlockTest extends TestCase { /** * Call Mockery::close after each test. */ - public function tearDown() + public function tearDown() : void { m::close(); } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::getSummary - * - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testDocBlockCanHaveASummary() + public function testDocBlockCanHaveASummary() : void { $summary = 'This is a summary'; @@ -48,42 +50,27 @@ public function testDocBlockCanHaveASummary() } /** - * @covers ::__construct + * @uses \phpDocumentor\Reflection\DocBlock\Description * - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfSummaryIsNotAString() - { - new DocBlock([]); - } - - /** * @covers ::__construct - * - * @expectedException \InvalidArgumentException + * @covers ::getSummary */ - public function testExceptionIsThrownIfTemplateStartIsNotABoolean() + public function testDocBlockCanHaveEllipsisInSummary() : void { - new DocBlock('', null, [], null, null, ['is not boolean']); - } + $summary = 'This is a short (...) description.'; - /** - * @covers ::__construct - * - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfTemplateEndIsNotABoolean() - { - new DocBlock('', null, [], null, null, false, ['is not boolean']); + $fixture = new DocBlock($summary); + + $this->assertSame($summary, $fixture->getSummary()); } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::getDescription - * - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testDocBlockCanHaveADescription() + public function testDocBlockCanHaveADescription() : void { $description = new DocBlock\Description(''); @@ -93,16 +80,16 @@ public function testDocBlockCanHaveADescription() } /** - * @covers ::__construct - * @covers ::getTags - * * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tag + * + * @covers ::__construct + * @covers ::getTags */ - public function testDocBlockCanHaveTags() + public function testDocBlockCanHaveTags() : void { $tags = [ - m::mock(DocBlock\Tag::class) + m::mock(DocBlock\Tag::class), ]; $fixture = new DocBlock('', null, $tags); @@ -111,32 +98,28 @@ public function testDocBlockCanHaveTags() } /** - * @covers ::__construct - * @covers ::getTags - * * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tag * - * @expectedException \InvalidArgumentException + * @covers ::__construct + * @covers ::getTags */ - public function testDocBlockAllowsOnlyTags() + public function testDocBlockAllowsOnlyTags() : void { - $tags = [ - null - ]; - + $this->expectException('InvalidArgumentException'); + $tags = [null]; $fixture = new DocBlock('', null, $tags); } /** - * @covers ::__construct - * @covers ::getTagsByName - * * @uses \phpDocumentor\Reflection\DocBlock::getTags * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tag + * + * @covers ::__construct + * @covers ::getTagsByName */ - public function testFindTagsInDocBlockByName() + public function testFindTagsInDocBlockByName() : void { $tag1 = m::mock(DocBlock\Tag::class); $tag2 = m::mock(DocBlock\Tag::class); @@ -154,26 +137,14 @@ public function testFindTagsInDocBlockByName() } /** - * @covers ::__construct - * @covers ::getTagsByName - * @uses \phpDocumentor\Reflection\DocBlock\Description - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfNameForTagsIsNotString() - { - $fixture = new DocBlock(); - $fixture->getTagsByName([]); - } - - /** - * @covers ::__construct - * @covers ::hasTag - * * @uses \phpDocumentor\Reflection\DocBlock::getTags * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\DocBlock\Tag + * + * @covers ::__construct + * @covers ::hasTag */ - public function testCheckIfThereAreTagsWithAGivenName() + public function testCheckIfThereAreTagsWithAGivenName() : void { $tag1 = m::mock(DocBlock\Tag::class); $tag2 = m::mock(DocBlock\Tag::class); @@ -191,25 +162,13 @@ public function testCheckIfThereAreTagsWithAGivenName() } /** - * @covers ::__construct - * @covers ::hasTag * @uses \phpDocumentor\Reflection\DocBlock\Description - * @expectedException \InvalidArgumentException - */ - public function testExceptionIsThrownIfNameForCheckingTagsIsNotString() - { - $fixture = new DocBlock(); - $fixture->hasTag([]); - } - - /** + * @uses \phpDocumentor\Reflection\Types\Context + * * @covers ::__construct * @covers ::getContext - * - * @uses \phpDocumentor\Reflection\DocBlock\Description - * @uses \phpDocumentor\Reflection\Types\Context */ - public function testDocBlockKnowsInWhichNamespaceItIsAndWhichAliasesThereAre() + public function testDocBlockKnowsInWhichNamespaceItIsAndWhichAliasesThereAre() : void { $context = new Context(''); @@ -219,13 +178,13 @@ public function testDocBlockKnowsInWhichNamespaceItIsAndWhichAliasesThereAre() } /** - * @covers ::__construct - * @covers ::getLocation - * * @uses \phpDocumentor\Reflection\DocBlock\Description * @uses \phpDocumentor\Reflection\Location + * + * @covers ::__construct + * @covers ::getLocation */ - public function testDocBlockKnowsAtWhichLineItIs() + public function testDocBlockKnowsAtWhichLineItIs() : void { $location = new Location(10); @@ -235,12 +194,12 @@ public function testDocBlockKnowsAtWhichLineItIs() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::isTemplateStart - * - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testDocBlockKnowsIfItIsTheStartOfADocBlockTemplate() + public function testDocBlockKnowsIfItIsTheStartOfADocBlockTemplate() : void { $fixture = new DocBlock('', null, [], null, null, true); @@ -248,12 +207,12 @@ public function testDocBlockKnowsIfItIsTheStartOfADocBlockTemplate() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Description + * * @covers ::__construct * @covers ::isTemplateEnd - * - * @uses \phpDocumentor\Reflection\DocBlock\Description */ - public function testDocBlockKnowsIfItIsTheEndOfADocBlockTemplate() + public function testDocBlockKnowsIfItIsTheEndOfADocBlockTemplate() : void { $fixture = new DocBlock('', null, [], null, null, false, true); @@ -261,14 +220,14 @@ public function testDocBlockKnowsIfItIsTheEndOfADocBlockTemplate() } /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated + * * @covers ::__construct * @covers ::removeTag - * - * @uses \phpDocumentor\Reflection\DocBlock\Tags\Deprecated */ - public function testRemoveTag() + public function testRemoveTag() : void { - $someTag = new Deprecated(); + $someTag = new Deprecated(); $anotherTag = new Deprecated(); $fixture = new DocBlock('', null, [$someTag]);