diff --git a/.travis.yml b/.travis.yml index 87225891..73451f99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,30 @@ language: php -php: - - 7.0 - - 7.1 - - 7.2 - matrix: include: + - php: 7.0 + env: + # Test commited lock file + - COMPOSER_LOCK=true - php: 7.1 - env: STATIC_ANALYSIS=true - -cache: - directories: - - $HOME/.composer/cache + env: + # Test code standard + - STATIC_ANALYSIS=true + # Test with updated dependencies + - php: 7.2 + - php: 7.3 + - php: 7.4 + fast_finish: true install: - - composer install --no-interaction + - | + if [[ $COMPOSER_LOCK = true ]]; then + COMPOSER_ROOT_VERSION=4.x-dev composer install + else + COMPOSER_ROOT_VERSION=4.x-dev composer update + fi # coding style - - if [[ $STATIC_ANALYSIS != "" ]]; then composer create-project symplify/easy-coding-standard temp/ecs; fi + - if [[ $STATIC_ANALYSIS != "" ]]; then composer create-project symplify/easy-coding-standard:v2.5.12 temp/ecs; fi script: - vendor/bin/phpunit --coverage-clover=coverage.xml -v @@ -25,7 +32,7 @@ script: - 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; + - wget https://github.com/satooshi/php-coveralls/releases/download/v1.1.0/coveralls.phar; - php coveralls.phar --verbose; notifications: diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..2a650d99 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,54 @@ +build: false +clone_folder: c:\reflectiondocblock +max_jobs: 3 +platform: x86 +pull_requests: + do_not_increment_build_number: true +version: '{build}.{branch}' +skip_tags: true +branches: + only: + - master + +environment: + matrix: + - php_ver_target: 7.1 + - php_ver_target: 7.2 +matrix: + fast_finish: false + +cache: + - c:\php -> appveyor.yml + - '%LOCALAPPDATA%\Composer\files' + +init: + - SET PATH=C:\Program Files\OpenSSL;c:\tools\php;%PATH% + - SET COMPOSER_NO_INTERACTION=1 + - SET PHP=1 + - SET ANSICON=121x90 (121x90) + + +install: + - IF EXIST c:\tools\php (SET PHP=0) + - ps: appveyor-retry cinst --params '""/InstallDir:C:\tools\php""' --ignore-checksums -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $env:php_ver_target | sort { [version]($_ -split '\|' | select -last 1) } -Descending | Select-Object -first 1) -replace '[php|]','') + - cd c:\tools\php + - IF %PHP%==1 copy /Y php.ini-development php.ini + - IF %PHP%==1 echo max_execution_time=1200 >> php.ini + - IF %PHP%==1 echo date.timezone="UTC" >> php.ini + - IF %PHP%==1 echo extension_dir=ext >> php.ini + - IF %PHP%==1 echo extension=php_curl.dll >> php.ini + - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini + - IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini + - IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini + - IF %PHP%==1 echo zend.assertions=1 >> php.ini + - IF %PHP%==1 echo assert.exception=On >> php.ini + - IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat + - appveyor-retry appveyor DownloadFile https://getcomposer.org/composer.phar + - cd c:\reflectiondocblock + - composer install --no-interaction --prefer-dist --no-progress + - composer global require phpunit/phpunit ^6 + - composer global config bin-dir --absolute + +test_script: + - cd c:\reflectiondocblock + - c:\Users\appveyor\AppData\Roaming\Composer\vendor\bin\phpunit --no-coverage diff --git a/composer.json b/composer.json index e3dc38a9..9bbf8eb6 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,8 @@ ], "require": { "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", "webmozart/assert": "^1.0" }, "autoload": { @@ -23,8 +23,9 @@ }, "require-dev": { "mockery/mockery": "^1.0", + "phpdocumentor/type-resolver": "0.4.*", "phpunit/phpunit": "^6.4", - "doctrine/instantiator": "~1.0.5" + "doctrine/instantiator": "^1.0.5" }, "extra": { "branch-alias": { diff --git a/composer.lock b/composer.lock index 4589e702..4d2a2605 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_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": "1ff5ca2db919ac08da3d0089a2cf990e", "packages": [ { "name": "phpdocumentor/reflection-common", @@ -108,32 +108,88 @@ "time": "2017-07-14T14:27:02+00:00" }, { - "name": "webmozart/assert", - "version": "1.2.0", + "name": "symfony/polyfill-ctype", + "version": "v1.13.1", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" }, "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/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", "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.13-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-11-27T13:56:44+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,7 +211,7 @@ "check", "validate" ], - "time": "2016-11-23T20:04:58+00:00" + "time": "2019-11-24T13:36:37+00:00" } ], "packages-dev": [ @@ -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,7 +380,7 @@ "test double", "testing" ], - "time": "2017-10-06T16:20:43+00:00" + "time": "2019-12-26T09:49:15+00:00" }, { "name": "myclabs/deep-copy", @@ -475,38 +531,38 @@ }, { "name": "phpspec/prophecy", - "version": "v1.7.2", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6" + "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/cbe1df668b3fe136bcc909126a0f529a78d4cbbc", + "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc", "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", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.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" + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -534,20 +590,20 @@ "spy", "stub" ], - "time": "2017-09-04T11:05:03+00:00" + "time": "2019-12-22T21:05:45+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.2.3", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d" + "reference": "c89677919c5dd6d3b3852f230a663118762218ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d", - "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac", "shasum": "" }, "require": { @@ -556,14 +612,13 @@ "php": "^7.0", "phpunit/php-file-iterator": "^1.4.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0", + "phpunit/php-token-stream": "^2.0.1", "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": { @@ -572,7 +627,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.2.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -587,7 +642,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -598,20 +653,20 @@ "testing", "xunit" ], - "time": "2017-11-03T13:47:33+00:00" + "time": "2018-04-06T15:36:58+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -645,7 +700,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -739,16 +794,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { @@ -784,20 +839,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-08-20T05:47:52+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", - "version": "6.4.4", + "version": "6.5.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932" + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/562f7dc75d46510a4ed5d16189ae57fbe45a9932", - "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bac23fe7ff13dbdb461481f706f0e9fe746334b7", + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7", "shasum": "" }, "require": { @@ -811,12 +866,12 @@ "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-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", "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", + "phpunit/phpunit-mock-objects": "^5.0.9", + "sebastian/comparator": "^2.1", "sebastian/diff": "^2.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", @@ -842,7 +897,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.4.x-dev" + "dev-master": "6.5.x-dev" } }, "autoload": { @@ -868,33 +923,33 @@ "testing", "xunit" ], - "time": "2017-11-08T11:26:09+00:00" + "time": "2019-02-01T05:22:47+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "4.0.4", + "version": "5.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.5", "php": "^7.0", "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.0" + "sebastian/exporter": "^3.1" }, "conflict": { "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.5.11" }, "suggest": { "ext-soap": "*" @@ -902,7 +957,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -917,7 +972,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -927,7 +982,8 @@ "mock", "xunit" ], - "time": "2017-08-03T14:08:16+00:00" + "abandoned": true, + "time": "2018-08-09T05:50:03+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -976,21 +1032,21 @@ }, { "name": "sebastian/comparator", - "version": "2.1.0", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1174d9018191e93cb9d719edec01257fc05f8158" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1174d9018191e93cb9d719edec01257fc05f8158", - "reference": "1174d9018191e93cb9d719edec01257fc05f8158", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { "php": "^7.0", - "sebastian/diff": "^2.0", + "sebastian/diff": "^2.0 || ^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { @@ -1036,7 +1092,7 @@ "compare", "equality" ], - "time": "2017-11-03T07:16:52+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", @@ -1142,16 +1198,16 @@ }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", "shasum": "" }, "require": { @@ -1178,6 +1234,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1186,17 +1246,13 @@ "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" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -1205,7 +1261,7 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2019-09-14T09:02:43+00:00" }, { "name": "sebastian/global-state", @@ -1490,16 +1546,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.1.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", "shasum": "" }, "require": { @@ -1526,7 +1582,7 @@ } ], "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-06-13T22:48:21+00:00" } ], "aliases": [], diff --git a/src/DocBlock/Tags/BaseTag.php b/src/DocBlock/Tags/BaseTag.php index 14bb7177..b549214a 100644 --- a/src/DocBlock/Tags/BaseTag.php +++ b/src/DocBlock/Tags/BaseTag.php @@ -1,4 +1,7 @@ create($body, $context) : null; + $description = $descriptionFactory && $body !== "" ? $descriptionFactory->create($body, $context) : null; return new static($name, $description); } diff --git a/src/DocBlock/Tags/Method.php b/src/DocBlock/Tags/Method.php index 75225299..78bc3e20 100644 --- a/src/DocBlock/Tags/Method.php +++ b/src/DocBlock/Tags/Method.php @@ -102,12 +102,8 @@ public static function create( ) \s+ )? - # Legacy method name (not captured) - (?: - [\w_]+\(\)\s+ - )? # Method name - ([\w\|_\\\\]+) + ([\w_]+) # Arguments (?: \(([^\)]*)\) diff --git a/src/DocBlock/Tags/Param.php b/src/DocBlock/Tags/Param.php index 7d699d88..cfa32250 100644 --- a/src/DocBlock/Tags/Param.php +++ b/src/DocBlock/Tags/Param.php @@ -22,14 +22,8 @@ /** * 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 = ''; @@ -47,6 +41,7 @@ public function __construct($variableName, Type $type = null, $isVariadic = fals Assert::string($variableName); Assert::boolean($isVariadic); + $this->name = 'param'; $this->variableName = $variableName; $this->type = $type; $this->isVariadic = $isVariadic; @@ -65,19 +60,25 @@ public static function create( Assert::stringNotEmpty($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + list($firstPart, $body) = self::extractTypeFromBody($body); $type = null; + $parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; $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); @@ -106,16 +107,6 @@ public function getVariableName() 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. * @@ -134,8 +125,8 @@ public function isVariadic() public function __toString() { return ($this->type ? $this->type . ' ' : '') - . ($this->isVariadic() ? '...' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . ($this->isVariadic() ? '...' : '') + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/Property.php b/src/DocBlock/Tags/Property.php index f0ef7c07..96688b9d 100644 --- a/src/DocBlock/Tags/Property.php +++ b/src/DocBlock/Tags/Property.php @@ -22,26 +22,21 @@ /** * Reflection class for a {@}property tag in a Docblock. */ -class Property extends BaseTag implements Factory\StaticMethod +class Property extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property'; - - /** @var Type */ - private $type; - /** @var string */ protected $variableName = ''; /** - * @param string $variableName - * @param Type $type + * @param string $variableName + * @param Type $type * @param Description $description */ public function __construct($variableName, Type $type = null, Description $description = null) { Assert::string($variableName); + $this->name = 'property'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; @@ -59,14 +54,17 @@ public static function create( Assert::stringNotEmpty($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + list($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 @@ -94,16 +92,6 @@ public function getVariableName() 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. * @@ -112,7 +100,7 @@ public function getType() public function __toString() { return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/PropertyRead.php b/src/DocBlock/Tags/PropertyRead.php index e41c0c1c..935c79d3 100644 --- a/src/DocBlock/Tags/PropertyRead.php +++ b/src/DocBlock/Tags/PropertyRead.php @@ -22,26 +22,21 @@ /** * Reflection class for a {@}property-read tag in a Docblock. */ -class PropertyRead extends BaseTag implements Factory\StaticMethod +class PropertyRead extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property-read'; - - /** @var Type */ - private $type; - /** @var string */ protected $variableName = ''; /** - * @param string $variableName - * @param Type $type + * @param string $variableName + * @param Type $type * @param Description $description */ public function __construct($variableName, Type $type = null, Description $description = null) { Assert::string($variableName); + $this->name = 'property-read'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; @@ -59,14 +54,17 @@ public static function create( Assert::stringNotEmpty($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + list($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 @@ -94,16 +92,6 @@ public function getVariableName() 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. * @@ -112,7 +100,7 @@ public function getType() public function __toString() { return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/PropertyWrite.php b/src/DocBlock/Tags/PropertyWrite.php index cfdb0ed0..6ccb2277 100644 --- a/src/DocBlock/Tags/PropertyWrite.php +++ b/src/DocBlock/Tags/PropertyWrite.php @@ -22,26 +22,21 @@ /** * Reflection class for a {@}property-write tag in a Docblock. */ -class PropertyWrite extends BaseTag implements Factory\StaticMethod +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 string $variableName + * @param Type $type * @param Description $description */ public function __construct($variableName, Type $type = null, Description $description = null) { Assert::string($variableName); + $this->name = 'property-write'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; @@ -59,14 +54,17 @@ public static function create( Assert::stringNotEmpty($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + list($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 @@ -94,16 +92,6 @@ public function getVariableName() 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. * @@ -112,7 +100,7 @@ public function getType() public function __toString() { return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); } } diff --git a/src/DocBlock/Tags/Return_.php b/src/DocBlock/Tags/Return_.php index ca5bda70..f3c97ce8 100644 --- a/src/DocBlock/Tags/Return_.php +++ b/src/DocBlock/Tags/Return_.php @@ -22,15 +22,11 @@ /** * 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) { + $this->name = 'return'; $this->type = $type; $this->description = $description; } @@ -47,24 +43,14 @@ public static function create( Assert::string($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/\s+/Su', $body, 2); + list($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() { return $this->type . ' ' . $this->description; diff --git a/src/DocBlock/Tags/TagWithType.php b/src/DocBlock/Tags/TagWithType.php new file mode 100644 index 00000000..7781caf5 --- /dev/null +++ b/src/DocBlock/Tags/TagWithType.php @@ -0,0 +1,60 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\Type; + +abstract class TagWithType extends BaseTag +{ + /** @var Type */ + protected $type; + + /** + * Returns the type section of the variable. + * + * @return Type + */ + public function getType() + { + return $this->type; + } + + 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++; + } + + if (in_array($character, ['>', ')', ']', '}'])) { + $nestingLevel--; + } + } + + $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..cf93cd09 100644 --- a/src/DocBlock/Tags/Throws.php +++ b/src/DocBlock/Tags/Throws.php @@ -22,16 +22,12 @@ /** * 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) { - $this->type = $type; + $this->name = 'throws'; + $this->type = $type; $this->description = $description; } @@ -47,24 +43,14 @@ public static function create( Assert::string($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/\s+/Su', $body, 2); + list($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() { return $this->type . ' ' . $this->description; diff --git a/src/DocBlock/Tags/Var_.php b/src/DocBlock/Tags/Var_.php index 8907c951..a0b40460 100644 --- a/src/DocBlock/Tags/Var_.php +++ b/src/DocBlock/Tags/Var_.php @@ -22,29 +22,24 @@ /** * Reflection class for a {@}var tag in a Docblock. */ -class Var_ extends BaseTag implements Factory\StaticMethod +class Var_ extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'var'; - - /** @var Type */ - private $type; - /** @var string */ protected $variableName = ''; /** - * @param string $variableName - * @param Type $type + * @param string $variableName + * @param Type $type * @param Description $description */ public function __construct($variableName, Type $type = null, Description $description = null) { Assert::string($variableName); + $this->name = 'var'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } /** @@ -59,14 +54,17 @@ public static function create( Assert::stringNotEmpty($body); Assert::allNotNull([$typeResolver, $descriptionFactory]); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; + list($firstPart, $body) = self::extractTypeFromBody($body); + $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 @@ -94,16 +92,6 @@ public function getVariableName() 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. * diff --git a/src/DocBlockFactoryInterface.php b/src/DocBlockFactoryInterface.php index b3533429..6c6edbf8 100644 --- a/src/DocBlockFactoryInterface.php +++ b/src/DocBlockFactoryInterface.php @@ -13,7 +13,7 @@ interface DocBlockFactoryInterface public static function createInstance(array $additionalTags = []); /** - * @param string $docblock + * @param object|string $docblock * @param Types\Context $context * @param Location $location * diff --git a/tests/integration/DocblocksWithAnnotationsTest.php b/tests/integration/DocblocksWithAnnotationsTest.php index 98646438..ed076a4b 100644 --- a/tests/integration/DocblocksWithAnnotationsTest.php +++ b/tests/integration/DocblocksWithAnnotationsTest.php @@ -43,4 +43,18 @@ public function testDocblockWithAnnotations() $this->assertCount(3, $docblock->getTags()); } + + public function testDocblockWithAnnotationHavingZeroValue() + { + $docComment = <<create($docComment); + + $this->assertSame(0, printf('%i', $docblock->getTagsByName('my-tag'))); + } } diff --git a/tests/unit/DocBlock/Tags/MethodTest.php b/tests/unit/DocBlock/Tags/MethodTest.php index c7e67003..98c2be34 100644 --- a/tests/unit/DocBlock/Tags/MethodTest.php +++ b/tests/unit/DocBlock/Tags/MethodTest.php @@ -482,6 +482,40 @@ public function testCreateMethodParenthesisMissing() /** * @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 testCreateMethodEmptyArguments() + { + $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()); + } + + /** * @uses \phpDocumentor\Reflection\DocBlock\Tags\Method:: * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\TypeResolver diff --git a/tests/unit/DocBlock/Tags/ReturnTest.php b/tests/unit/DocBlock/Tags/ReturnTest.php index 335cd5e9..2e126075 100644 --- a/tests/unit/DocBlock/Tags/ReturnTest.php +++ b/tests/unit/DocBlock/Tags/ReturnTest.php @@ -112,7 +112,7 @@ public function testStringRepresentationIsReturned() { $fixture = new Return_(new String_(), new Description('Description')); - $this->assertSame('string Description', (string)$fixture); + $this->assertSame('string Description', (string) $fixture); } /** @@ -136,11 +136,101 @@ public function testFactoryMethod() $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. + * + * @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 + */ + public function testFactoryMethodWithGenericWithSpace() + { + $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); + } + + /** + * @see self::testFactoryMethodWithGenericWithSpace() + * + * @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 + */ + public function testFactoryMethodWithGenericWithSpaceAndAddedEmojisToVerifyMultiByteBehaviour() + { + $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); + } + + /** + * @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 + */ + public function testFactoryMethodWithEmojisToVerifyMultiByteBehaviour() + { + $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 diff --git a/tests/unit/DocBlock/Tags/ThrowsTest.php b/tests/unit/DocBlock/Tags/ThrowsTest.php index 5747e8f5..31d8d528 100644 --- a/tests/unit/DocBlock/Tags/ThrowsTest.php +++ b/tests/unit/DocBlock/Tags/ThrowsTest.php @@ -112,7 +112,7 @@ public function testStringRepresentationIsReturned() { $fixture = new Throws(new String_(), new Description('Description')); - $this->assertSame('string Description', (string)$fixture); + $this->assertSame('string Description', (string) $fixture); } /** @@ -127,20 +127,110 @@ public function testStringRepresentationIsReturned() public function testFactoryMethod() { $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 = 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. + * + * @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 + */ + public function testFactoryMethodWithGenericWithSpace() + { + $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); + } + + /** + * @see self::testFactoryMethodWithGenericWithSpace() + * + * @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 + */ + public function testFactoryMethodWithGenericWithSpaceAndAddedEmojisToVerifyMultiByteBehaviour() + { + $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); + } + + /** + * @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 + */ + public function testFactoryMethodWithEmojisToVerifyMultiByteBehaviour() + { + $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