composer update

This commit is contained in:
2019-12-01 06:37:45 +00:00
parent fa199eef05
commit 3115ab75a5
3650 changed files with 72361 additions and 147137 deletions

View File

@@ -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: ["tests", "vendor"]
php_code_sniffer:
enabled: true
config:
standard: PSR2
filter:
paths: ["src/*", "tests/*"]
excluded_paths: []
php_cpd:
enabled: true
excluded_dirs: ["tests", "vendor"]
php_cs_fixer:
enabled: true
config:
level: all
filter:
paths: ["src/*", "tests/*"]
php_loc:
enabled: true
excluded_dirs: ["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: ["tests", "vendor"]
php_analyzer:
enabled: true
filter:
paths: ["src/*", "tests/*"]
sensiolabs_security_checker: true

View File

@@ -1,35 +1,53 @@
language: php
php:
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm
- nightly
php: [ 7.1, 7.2, nightly ]
sudo: false
env:
matrix:
fast_finish: true
allow_failures:
- php:
- hhvm
- nightly
- php: nightly
install:
- travis_retry composer install --no-interaction --prefer-dist --optimize-autoloader
script:
- ./vendor/bin/phpunit --no-coverage
jobs:
include:
- stage: analysis
php: 7.1
script:
- ./vendor/bin/phpunit
after_script:
- travis_retry wget --no-verbose https://phar.io/releases/phive.phar
- travis_retry php phive.phar --no-progress install --trust-gpg-keys E82B2FB314E9906E php-coveralls/php-coveralls && ./tools/php-coveralls --verbose
- travis_retry wget --no-verbose https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml
- stage: analysis
php: 7.1
before_script:
- travis_retry wget --no-verbose https://phar.io/releases/phive.phar
- travis_retry php phive.phar --no-progress install --trust-gpg-keys 8E730BA25823D8B5 phpstan
script:
- ./tools/phpstan analyse src --level max --configuration phpstan.neon
- stage: analysis
php: 7.1
script:
- composer create-project symplify/easy-coding-standard temp/ecs ^3 && temp/ecs/bin/ecs check src tests
cache:
directories:
- $HOME/.composer/cache
script:
- vendor/bin/phpunit --coverage-clover=coverage.clover -v
- composer update --no-interaction --prefer-source
- vendor/bin/phpunit -v
before_script:
- composer install --no-interaction
after_script:
- if [ $TRAVIS_PHP_VERSION = '5.6' ]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi
- $HOME/.composer
- $HOME/.phive
notifications:
irc: "irc.freenode.org#phpdocumentor"
slack:
secure: "fjumM0h+4w3EYM4dpgqvpiCug7m4sSIC5+HATgwga/Nrc6IjlbWvGOv3JPgD3kQUhi18VmZfUYPmCv916SIbMnv8JWcrSaJXnPCgmxidvYkuzQDIw1HDJbVppGnkmwQA/qjIrM3sIEMfnu/arLRJQLI363aStZzGPxwIa4PDKcg="
email:
- me@mikevanriel.com
- ashnazg@php.net
- me@mikevanriel.com
- ashnazg@php.net

View File

@@ -1,2 +1,12 @@
# ReflectionCommon
[![Build Status](https://travis-ci.org/phpDocumentor/ReflectionCommon.svg?branch=master)](https://travis-ci.org/phpDocumentor/ReflectionCommon)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Travis Status](https://img.shields.io/travis/phpDocumentor/ReflectionCommon.svg?label=Linux)](https://travis-ci.org/phpDocumentor/ReflectionCommon)
[![Appveyor Status](https://img.shields.io/appveyor/ci/phpDocumentor/ReflectionCommon.svg?label=Windows)](https://ci.appveyor.com/project/phpDocumentor/ReflectionCommon/branch/master)
[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionCommon.svg)](https://coveralls.io/github/phpDocumentor/ReflectionCommon?branch=master)
[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master)
[![Stable Version](https://img.shields.io/packagist/v/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common)
[![Unstable Version](https://img.shields.io/packagist/vpre/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common)
ReflectionCommon
================

View File

@@ -0,0 +1,52 @@
build: false
clone_folder: c:\reflectioncommon
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:\reflectioncommon
- composer install --no-interaction --prefer-dist --no-progress
test_script:
- cd c:\reflectioncommon
- vendor\bin\phpunit --no-coverage

View File

@@ -11,19 +11,19 @@
}
],
"require": {
"php": ">=5.5"
"php": ">=7.1"
},
"autoload" : {
"psr-4" : {
"phpDocumentor\\Reflection\\": ["src"]
"phpDocumentor\\Reflection\\": "src/"
}
},
"require-dev": {
"phpunit/phpunit": "^4.6"
"phpunit/phpunit": "~6"
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "2.x-dev"
}
}
}

View File

@@ -0,0 +1,17 @@
includes:
- temp/ecs/config/clean-code.neon
- temp/ecs/config/psr2.neon
- temp/ecs/config/common.neon
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:
PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff:
- */tests/**

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^6.5.5" installed="6.5.5" location="./tools/phpunit"/>
<phar name="phpstan" version="^0.9.1" installed="0.9.1" location="./tools/phpstan"/>
</phive>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<ruleset
name="ProxyManager rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
>
<rule ref="rulesets/codesize.xml"/>
<rule ref="rulesets/unusedcode.xml"/>
<rule ref="rulesets/design.xml">
<!-- eval is needed to generate runtime classes -->
<exclude name="EvalExpression"/>
</rule>
<rule ref="rulesets/naming.xml">
<exclude name="LongVariable"/>
</rule>
<rule ref="rulesets/naming.xml/LongVariable">
<properties>
<property name="minimum">40</property>
</properties>
</rule>
</ruleset>

View File

View File

@@ -1,10 +1,13 @@
<?php
declare(strict_types=1);
/**
* phpDocumentor
*
* PHP Version 5.5
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com)
* @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -18,15 +21,11 @@ interface Element
{
/**
* Returns the Fqsen of the element.
*
* @return Fqsen
*/
public function getFqsen();
public function getFqsen(): Fqsen;
/**
* Returns the name of the element.
*
* @return string
*/
public function getName();
}
public function getName(): string;
}

View File

@@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @copyright 2010-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -19,22 +21,16 @@ interface File
{
/**
* Returns the content of the file as a string.
*
* @return string
*/
public function getContents();
public function getContents(): string;
/**
* Returns md5 hash of the file.
*
* @return string
*/
public function md5();
public function md5(): string;
/**
* Returns an relative path to the file.
*
* @return string
*/
public function path();
public function path(): string;
}

View File

@@ -1,16 +1,21 @@
<?php
declare(strict_types=1);
/**
* phpDocumentor
*
* PHP Version 5.5
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com)
* @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use InvalidArgumentException;
/**
* Value Object for Fqsen.
*
@@ -31,21 +36,19 @@ final class Fqsen
/**
* Initializes the object.
*
* @param string $fqsen
*
* @throws \InvalidArgumentException when $fqsen is not matching the format.
* @throws InvalidArgumentException when $fqsen is not matching the format.
*/
public function __construct($fqsen)
public function __construct(string $fqsen)
{
$matches = array();
$matches = [];
$result = preg_match(
'/^\\\\([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\\\]*)?(?:[:]{2}\\$?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*))?(?:\\(\\))?$/',
$fqsen,
$matches
$fqsen,
$matches
);
if ($result === 0) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
sprintf('"%s" is not a valid Fqsen.', $fqsen)
);
}
@@ -62,20 +65,16 @@ final class Fqsen
/**
* converts this class to string.
*
* @return string
*/
public function __toString()
public function __toString(): string
{
return $this->fqsen;
}
/**
* Returns the name of the element without path.
*
* @return string
*/
public function getName()
public function getName(): string
{
return $this->name;
}

View File

@@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @copyright 2010-2018 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -17,7 +19,7 @@ namespace phpDocumentor\Reflection;
*/
final class Location
{
/** @var int */
/** @var int */
private $lineNumber = 0;
/** @var int */
@@ -25,32 +27,25 @@ final class Location
/**
* Initializes the location for an element using its line number in the file and optionally the column number.
*
* @param int $lineNumber
* @param int $columnNumber
*/
public function __construct($lineNumber, $columnNumber = 0)
public function __construct(int $lineNumber, int $columnNumber = 0)
{
$this->lineNumber = $lineNumber;
$this->lineNumber = $lineNumber;
$this->columnNumber = $columnNumber;
}
/**
* Returns the line number that is covered by this location.
*
* @return integer
*/
public function getLineNumber()
public function getLineNumber(): int
{
return $this->lineNumber;
}
/**
* Returns the column number (character position on a line) for this location object.
*
* @return integer
*/
public function getColumnNumber()
public function getColumnNumber(): int
{
return $this->columnNumber;
}

View File

@@ -1,10 +1,13 @@
<?php
declare(strict_types=1);
/**
* phpDocumentor
*
* PHP Version 5.5
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com)
* @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -18,8 +21,6 @@ interface Project
{
/**
* Returns the name of the project.
*
* @return string
*/
public function getName();
public function getName(): string;
}

View File

@@ -1,13 +1,17 @@
<?php
declare(strict_types=1);
/**
* phpDocumentor
*
* PHP Version 5.5
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com)
* @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
/**
@@ -23,5 +27,5 @@ interface ProjectFactory
* @param File[] $files
* @return Project
*/
public function create($name, array $files);
public function create($name, array $files): Project;
}

View File

@@ -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

View File

@@ -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": {
@@ -24,7 +24,7 @@
"require-dev": {
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^6.4",
"doctrine/instantiator": "~1.0.5"
"doctrine/instantiator": "^1.0.5"
},
"extra": {
"branch-alias": {

View File

@@ -0,0 +1,35 @@
on: push
name: Qa workflow
jobs:
composer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: composer
uses: docker://composer
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
args: install --no-interaction --prefer-dist --optimize-autoloader
- name: Code style check
uses: docker://phpdoc/phpcs-ga:master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
args: -d memory_limit=1024M -s
- 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: Psalm
uses: docker://mickaelandrieu/psalm-ga
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: PHPStan
uses: docker://oskarstark/phpstan-ga
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
args: analyse src tests --level max --configuration phpstan.neon

View File

@@ -1,3 +1,13 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Travis Status](https://img.shields.io/travis/phpDocumentor/TypeResolver.svg?label=Linux)](https://travis-ci.org/phpDocumentor/TypeResolver)
[![Appveyor Status](https://img.shields.io/appveyor/ci/phpDocumentor/TypeResolver.svg?label=Windows)](https://ci.appveyor.com/project/phpDocumentor/TypeResolver/branch/master)
[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/TypeResolver.svg)](https://coveralls.io/github/phpDocumentor/TypeResolver?branch=master)
[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=master)
[![Stable Version](https://img.shields.io/packagist/v/phpDocumentor/Type-Resolver.svg)](https://packagist.org/packages/phpDocumentor/TypeResolver)
[![Unstable Version](https://img.shields.io/packagist/vpre/phpDocumentor/Type-Resolver.svg)](https://packagist.org/packages/phpDocumentor/TypeResolver)
TypeResolver and FqsenResolver
==============================
@@ -22,8 +32,7 @@ The easiest way to install this library is with [Composer](https://getcomposer.o
## Examples
Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and
check which type of action that your want to accomplish.
Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and check which type of action that your want to accomplish.
## On Types and Element Names
@@ -39,6 +48,7 @@ The TypeResolver can resolve:
- a php primitive or pseudo-primitive such as a string or void (`@var string` or `@return void`).
- a composite such as an array of string (`@var string[]`).
- a compound such as a string or integer (`@var string|integer`).
- an array expression (`@var (string|TypeResolver)[]`)
- an object or interface such as the TypeResolver class (`@var TypeResolver`
or `@var \phpDocumentor\Reflection\TypeResolver`)
@@ -58,8 +68,7 @@ Where the FqsenResolver can resolve:
## Resolving a type
In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver`
and call its `resolve` method like this:
In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` and call its `resolve` method like this:
```php
$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
@@ -70,31 +79,30 @@ In this example you will receive a Value Object of class `\phpDocumentor\Reflect
elements, one of type `\phpDocumentor\Reflection\Types\String_` and one of type
`\phpDocumentor\Reflection\Types\Integer`.
The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but
in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver
in which namespace the given expression occurs and which namespace aliases (or imports) apply.
The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.
### Resolving nullable types
Php 7.1 introduced nullable types e.g. `?string`. Type resolver will resolve the original type without the nullable notation `?`
just like it would do without the `?`. After that the type is wrapped in a `\phpDocumentor\Reflection\Types\Nullable` object.
The `Nullable` type has a method to fetch the actual type.
## Resolving an FQSEN
A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using
the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this:
A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this:
```php
$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
$fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()');
```
In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class
name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`.
In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`.
The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural
Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will
inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.
The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply.
## Resolving partial Classes and Structural Element Names
Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class
names.
Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class names.
For example, you have this file:
@@ -116,9 +124,8 @@ class Classy
```
Suppose that you would want to resolve (and expand) the type in the `@var` tag and the element name in the `@see` tag.
For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating
a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in
play.
For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in play.
### Creating a Context
@@ -131,9 +138,7 @@ $context = new \phpDocumentor\Reflection\Types\Context(
);
```
Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector
object or by providing the namespace that you'd like to extract and the source code of the file in which the given
type expression occurs.
Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector object or by providing the namespace that you'd like to extract and the source code of the file in which the given type expression occurs.
```php
$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory();
@@ -149,8 +154,7 @@ $context = $contextFactory->createForNamespace('\My\Example', file_get_contents(
### Using the Context
After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver
class as second argument and the Resolvers will take this into account when resolving partial names.
After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver class as second argument and the Resolvers will take this into account when resolving partial names.
To obtain the resolved class name for the `@var` tag in the example above you can do:
@@ -159,24 +163,17 @@ $typeResolver = new \phpDocumentor\Reflection\TypeResolver();
$type = $typeResolver->resolve('Types\Context', $context);
```
When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call
the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be
`phpDocumentor\Reflection\Types\Context`.
When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be `phpDocumentor\Reflection\Types\Context`.
> Why is the FQSEN wrapped in another object `Object_`?
>
> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common
> type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it
> is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN.
> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN.
Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To
resolve that you can do the following:
Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To resolve that you can do the following:
```php
$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver();
$type = $fqsenResolver->resolve('Classy::otherFunction()', $context);
```
Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the
`resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to
`\My\Example\Classy::otherFunction()`.
Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the `resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to `\My\Example\Classy::otherFunction()`.

View File

@@ -0,0 +1,52 @@
build: false
clone_folder: c:\typeresolver
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:\typeresolver
- composer install --no-interaction --prefer-dist --no-progress
test_script:
- cd c:\typeresolver
- vendor\bin\phpunit --no-coverage

View File

@@ -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"
]
}

View File

@@ -1,27 +1,36 @@
{
"name": "phpdocumentor/type-resolver",
"type": "library",
"name": "phpdocumentor/type-resolver",
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"type": "library",
"license": "MIT",
"authors": [
{"name": "Mike van Riel", "email": "me@mikevanriel.com"}
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"require": {
"php": "^5.5 || ^7.0",
"phpdocumentor/reflection-common": "^1.0"
},
"autoload": {
"psr-4": {"phpDocumentor\\Reflection\\": ["src/"]}
},
"autoload-dev": {
"psr-4": {"phpDocumentor\\Reflection\\": ["tests/unit"]}
"php": "^7.1",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"phpunit/phpunit": "^5.2||^4.8.24",
"mockery/mockery": "^0.9.4"
"mockery/mockery": "~1",
"ext-tokenizer": "^7.1",
"phpunit/phpunit": "^7.0"
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"phpDocumentor\\Reflection\\": "tests/unit"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.x-dev"
}
}
}

1448
vendor/phpdocumentor/type-resolver/composer.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^6.5.5" installed="6.5.11" location="./tools/phpunit"/>
<phar name="phpstan" version="^0.9.1" installed="0.10.2" location="./tools/phpstan"/>
</phive>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<ruleset name="phpDocumentor">
<description>The coding standard for phpDocumentor.</description>
<file>src</file>
<file>tests/unit</file>
<exclude-pattern>*/tests/unit/Types/ContextFactoryTest.php</exclude-pattern>
<arg value="p"/>
<rule ref="PSR2">
<include-pattern>*\.php</include-pattern>
</rule>
<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.TypeHints.UselessConstantTypeHint.UselessDocComment" />
</rule>
<rule ref="Squiz.Classes.ValidClassName.NotCamelCaps">
<exclude-pattern>*/src/*_.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix">
<exclude-pattern>*/src/*/Abstract*.php</exclude-pattern>
</rule>
<rule ref="Generic.Formatting.SpaceAfterNot">
<properties>
<property name="spacing" value="0" />
</properties>
</rule>
</ruleset>

View File

@@ -0,0 +1,7 @@
parameters:
ignoreErrors:
-
message: '#Parameter \#1 \$types of class phpDocumentor\\Reflection\\Types\\Compound constructor expects array<phpDocumentor\\Reflection\\Type>, array<int, string> given\.#'
path: %currentWorkingDirectory%/tests/unit/Types/CompoundTest.php
- message: '#Parameter \#2 \$fileContents of method phpDocumentor\\Reflection\\Types\\ContextFactory::createForNamespace\(\) expects string, string|false given\.#'
path: %currentWorkingDirectory%/tests/unit/Types/ContextFactoryTest.php

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<psalm
totallyTyped="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config file:///composer/vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<LessSpecificReturnType errorLevel="info" />
</issueHandlers>
</psalm>

View File

@@ -1,25 +1,30 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use InvalidArgumentException;
use phpDocumentor\Reflection\Types\Context;
use function explode;
use function implode;
use function strpos;
class FqsenResolver
{
/** @var string Definition of the NAMESPACE operator in PHP */
const OPERATOR_NAMESPACE = '\\';
private const OPERATOR_NAMESPACE = '\\';
public function resolve($fqsen, Context $context = null)
public function resolve(string $fqsen, ?Context $context = null) : Fqsen
{
if ($context === null) {
$context = new Context('');
@@ -34,12 +39,8 @@ class FqsenResolver
/**
* Tests whether the given type is a Fully Qualified Structural Element Name.
*
* @param string $type
*
* @return bool
*/
private function isFqsen($type)
private function isFqsen(string $type) : bool
{
return strpos($type, self::OPERATOR_NAMESPACE) === 0;
}
@@ -48,13 +49,9 @@ class FqsenResolver
* Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation
* (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context.
*
* @param string $type
* @param Context $context
*
* @return Fqsen
* @throws \InvalidArgumentException when type is not a valid FQSEN.
* @throws InvalidArgumentException When type is not a valid FQSEN.
*/
private function resolvePartialStructuralElementName($type, Context $context)
private function resolvePartialStructuralElementName(string $type, Context $context) : Fqsen
{
$typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2);
@@ -63,7 +60,7 @@ class FqsenResolver
// if the first segment is not an alias; prepend namespace name and return
if (!isset($namespaceAliases[$typeParts[0]])) {
$namespace = $context->getNamespace();
if ('' !== $namespace) {
if ($namespace !== '') {
$namespace .= self::OPERATOR_NAMESPACE;
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -14,5 +15,8 @@ namespace phpDocumentor\Reflection;
interface Type
{
public function __toString();
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*/
public function __toString() : string;
}

View File

@@ -1,39 +1,76 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection;
use ArrayIterator;
use InvalidArgumentException;
use phpDocumentor\Reflection\Types\Array_;
use phpDocumentor\Reflection\Types\Collection;
use phpDocumentor\Reflection\Types\Compound;
use phpDocumentor\Reflection\Types\Context;
use phpDocumentor\Reflection\Types\Integer;
use phpDocumentor\Reflection\Types\Iterable_;
use phpDocumentor\Reflection\Types\Nullable;
use phpDocumentor\Reflection\Types\Object_;
use phpDocumentor\Reflection\Types\String_;
use RuntimeException;
use const PREG_SPLIT_DELIM_CAPTURE;
use const PREG_SPLIT_NO_EMPTY;
use function array_keys;
use function array_pop;
use function class_exists;
use function class_implements;
use function count;
use function in_array;
use function preg_split;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
use function trim;
final class TypeResolver
{
/** @var string Definition of the ARRAY operator for types */
const OPERATOR_ARRAY = '[]';
private const OPERATOR_ARRAY = '[]';
/** @var string Definition of the NAMESPACE operator in PHP */
const OPERATOR_NAMESPACE = '\\';
private const OPERATOR_NAMESPACE = '\\';
/** @var string[] List of recognized keywords and unto which Value Object they map */
private $keywords = array(
/** @var int the iterator parser is inside a compound context */
private const PARSER_IN_COMPOUND = 0;
/** @var int the iterator parser is inside a nullable expression context */
private const PARSER_IN_NULLABLE = 1;
/** @var int the iterator parser is inside an array expression context */
private const PARSER_IN_ARRAY_EXPRESSION = 2;
/** @var int the iterator parser is inside a collection expression context */
private const PARSER_IN_COLLECTION_EXPRESSION = 3;
/**
* @var array<string, string> List of recognized keywords and unto which Value Object they map
* @psalm-var array<string, class-string<Type>>
*/
private $keywords = [
'string' => Types\String_::class,
'int' => Types\Integer::class,
'integer' => Types\Integer::class,
'bool' => Types\Boolean::class,
'boolean' => Types\Boolean::class,
'real' => Types\Float_::class,
'float' => Types\Float_::class,
'double' => Types\Float_::class,
'object' => Object_::class,
@@ -52,17 +89,15 @@ final class TypeResolver
'static' => Types\Static_::class,
'parent' => Types\Parent_::class,
'iterable' => Iterable_::class,
);
];
/** @var FqsenResolver */
private $fqsenResolver;
/**
* Initializes this TypeResolver with the means to create and resolve Fqsen objects.
*
* @param FqsenResolver $fqsenResolver
*/
public function __construct(FqsenResolver $fqsenResolver = null)
public function __construct(?FqsenResolver $fqsenResolver = null)
{
$this->fqsenResolver = $fqsenResolver ?: new FqsenResolver();
}
@@ -77,39 +112,177 @@ final class TypeResolver
* This method only works as expected if the namespace and aliases are set;
* no dynamic reflection is being performed here.
*
* @param string $type The relative or absolute type.
* @param Context $context
*
* @uses Context::getNamespace() to determine with what to prefix the type name.
* @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be
* replaced with another namespace.
* replaced with another namespace.
* @uses Context::getNamespace() to determine with what to prefix the type name.
*
* @return Type|null
* @param string $type The relative or absolute type.
*/
public function resolve($type, Context $context = null)
public function resolve(string $type, ?Context $context = null) : Type
{
if (!is_string($type)) {
throw new \InvalidArgumentException(
'Attempted to resolve type but it appeared not to be a string, received: ' . var_export($type, true)
);
}
$type = trim($type);
if (!$type) {
throw new \InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
throw new InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty');
}
if ($context === null) {
$context = new Context('');
}
// split the type string into tokens `|`, `?`, `<`, `>`, `,`, `(`, `)[]`, '<', '>' and type names
$tokens = preg_split(
'/(\\||\\?|<|>|, ?|\\(|\\)(?:\\[\\])+)/',
$type,
-1,
PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
);
if ($tokens === false) {
throw new InvalidArgumentException('Unable to split the type string "' . $type . '" into tokens');
}
$tokenIterator = new ArrayIterator($tokens);
return $this->parseTypes($tokenIterator, $context, self::PARSER_IN_COMPOUND);
}
/**
* Analyse each tokens and creates types
*
* @param ArrayIterator $tokens the iterator on tokens
* @param int $parserContext on of self::PARSER_* constants, indicating
* the context where we are in the parsing
*/
private function parseTypes(ArrayIterator $tokens, Context $context, int $parserContext) : Type
{
$types = [];
$token = '';
while ($tokens->valid()) {
$token = $tokens->current();
if ($token === '|') {
if (count($types) === 0) {
throw new RuntimeException(
'A type is missing before a type separator'
);
}
if ($parserContext !== self::PARSER_IN_COMPOUND
&& $parserContext !== self::PARSER_IN_ARRAY_EXPRESSION
&& $parserContext !== self::PARSER_IN_COLLECTION_EXPRESSION
) {
throw new RuntimeException(
'Unexpected type separator'
);
}
$tokens->next();
} elseif ($token === '?') {
if ($parserContext !== self::PARSER_IN_COMPOUND
&& $parserContext !== self::PARSER_IN_ARRAY_EXPRESSION
&& $parserContext !== self::PARSER_IN_COLLECTION_EXPRESSION
) {
throw new RuntimeException(
'Unexpected nullable character'
);
}
$tokens->next();
$type = $this->parseTypes($tokens, $context, self::PARSER_IN_NULLABLE);
$types[] = new Nullable($type);
} elseif ($token === '(') {
$tokens->next();
$type = $this->parseTypes($tokens, $context, self::PARSER_IN_ARRAY_EXPRESSION);
$resolvedType = new Array_($type);
$token = $tokens->current();
// Someone did not properly close their array expression ..
if ($token === null) {
break;
}
// we generate arrays corresponding to the number of '[]' after the ')'
$numberOfArrays = (strlen($token) - 1) / 2;
for ($i = 0; $i < $numberOfArrays - 1; ++$i) {
$resolvedType = new Array_($resolvedType);
}
$types[] = $resolvedType;
$tokens->next();
} elseif ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION && $token[0] === ')') {
break;
} elseif ($token === '<') {
if (count($types) === 0) {
throw new RuntimeException(
'Unexpected collection operator "<", class name is missing'
);
}
$classType = array_pop($types);
if ($classType !== null) {
$types[] = $this->resolveCollection($tokens, $classType, $context);
}
$tokens->next();
} elseif ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION
&& ($token === '>' || trim($token) === ',')
) {
break;
} else {
$type = $this->resolveSingleType($token, $context);
$tokens->next();
if ($parserContext === self::PARSER_IN_NULLABLE) {
return $type;
}
$types[] = $type;
}
}
if ($token === '|') {
throw new RuntimeException(
'A type is missing after a type separator'
);
}
if (count($types) === 0) {
if ($parserContext === self::PARSER_IN_NULLABLE) {
throw new RuntimeException(
'A type is missing after a nullable character'
);
}
if ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION) {
throw new RuntimeException(
'A type is missing in an array expression'
);
}
if ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION) {
throw new RuntimeException(
'A type is missing in a collection expression'
);
}
} elseif (count($types) === 1) {
return $types[0];
}
return new Compound($types);
}
/**
* resolve the given type into a type object
*
* @param string $type the type string, representing a single type
*
* @return Type|Array_|Object_
*/
private function resolveSingleType(string $type, Context $context)
{
switch (true) {
case $this->isNullableType($type):
return $this->resolveNullableType($type, $context);
case $this->isKeyword($type):
return $this->resolveKeyword($type);
case ($this->isCompoundType($type)):
return $this->resolveCompoundType($type, $context);
case $this->isTypedArray($type):
return $this->resolveTypedArray($type, $context);
case $this->isFqsen($type):
@@ -119,32 +292,28 @@ final class TypeResolver
// @codeCoverageIgnoreStart
default:
// I haven't got the foggiest how the logic would come here but added this as a defense.
throw new \RuntimeException(
throw new RuntimeException(
'Unable to resolve type "' . $type . '", there is no known method to resolve it'
);
}
// @codeCoverageIgnoreEnd
}
/**
* Adds a keyword to the list of Keywords and associates it with a specific Value Object.
*
* @param string $keyword
* @param string $typeClassName
*
* @return void
*/
public function addKeyword($keyword, $typeClassName)
public function addKeyword(string $keyword, string $typeClassName) : void
{
if (!class_exists($typeClassName)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class'
. ' but we could not find the class ' . $typeClassName
);
}
if (!in_array(Type::class, class_implements($typeClassName))) {
throw new \InvalidArgumentException(
if (!in_array(Type::class, class_implements($typeClassName), true)) {
throw new InvalidArgumentException(
'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"'
);
}
@@ -156,10 +325,8 @@ final class TypeResolver
* Detects whether the given type represents an array.
*
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
*
* @return bool
*/
private function isTypedArray($type)
private function isTypedArray(string $type) : bool
{
return substr($type, -2) === self::OPERATOR_ARRAY;
}
@@ -168,10 +335,8 @@ final class TypeResolver
* Detects whether the given type represents a PHPDoc keyword.
*
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
*
* @return bool
*/
private function isKeyword($type)
private function isKeyword(string $type) : bool
{
return in_array(strtolower($type), array_keys($this->keywords), true);
}
@@ -180,119 +345,126 @@ final class TypeResolver
* Detects whether the given type represents a relative structural element name.
*
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
*
* @return bool
*/
private function isPartialStructuralElementName($type)
private function isPartialStructuralElementName(string $type) : bool
{
return ($type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type);
}
/**
* Tests whether the given type is a Fully Qualified Structural Element Name.
*
* @param string $type
*
* @return bool
*/
private function isFqsen($type)
private function isFqsen(string $type) : bool
{
return strpos($type, self::OPERATOR_NAMESPACE) === 0;
}
/**
* Tests whether the given type is a compound type (i.e. `string|int`).
*
* @param string $type
*
* @return bool
*/
private function isCompoundType($type)
{
return strpos($type, '|') !== false;
}
/**
* Test whether the given type is a nullable type (i.e. `?string`)
*
* @param string $type
*
* @return bool
*/
private function isNullableType($type)
{
return $type[0] === '?';
}
/**
* Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set.
*
* @param string $type
* @param Context $context
*
* @return Array_
*/
private function resolveTypedArray($type, Context $context)
private function resolveTypedArray(string $type, Context $context) : Array_
{
return new Array_($this->resolve(substr($type, 0, -2), $context));
return new Array_($this->resolveSingleType(substr($type, 0, -2), $context));
}
/**
* Resolves the given keyword (such as `string`) into a Type object representing that keyword.
*
* @param string $type
*
* @return Type
*/
private function resolveKeyword($type)
private function resolveKeyword(string $type) : Type
{
$className = $this->keywords[strtolower($type)];
return new $className();
}
/**
* Resolves the given FQSEN string into an FQSEN object.
*
* @param string $type
* @param Context|null $context
*
* @return Object_
*/
private function resolveTypedObject($type, Context $context = null)
private function resolveTypedObject(string $type, ?Context $context = null) : Object_
{
return new Object_($this->fqsenResolver->resolve($type, $context));
}
/**
* Resolves a compound type (i.e. `string|int`) into the appropriate Type objects or FQSEN.
* Resolves the collection values and keys
*
* @param string $type
* @param Context $context
*
* @return Compound
* @return Array_|Collection
*/
private function resolveCompoundType($type, Context $context)
private function resolveCollection(ArrayIterator $tokens, Type $classType, Context $context) : Type
{
$types = [];
$isArray = ((string) $classType === 'array');
foreach (explode('|', $type) as $part) {
$types[] = $this->resolve($part, $context);
// allow only "array" or class name before "<"
if (!$isArray
&& (!$classType instanceof Object_ || $classType->getFqsen() === null)) {
throw new RuntimeException(
$classType . ' is not a collection'
);
}
return new Compound($types);
$tokens->next();
$valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
$keyType = null;
if ($tokens->current() !== null && trim($tokens->current()) === ',') {
// if we have a comma, then we just parsed the key type, not the value type
$keyType = $valueType;
if ($isArray) {
// check the key type for an "array" collection. We allow only
// strings or integers.
if (!$keyType instanceof String_ &&
!$keyType instanceof Integer &&
!$keyType instanceof Compound
) {
throw new RuntimeException(
'An array can have only integers or strings as keys'
);
}
if ($keyType instanceof Compound) {
foreach ($keyType->getIterator() as $item) {
if (!$item instanceof String_ &&
!$item instanceof Integer
) {
throw new RuntimeException(
'An array can have only integers or strings as keys'
);
}
}
}
}
$tokens->next();
// now let's parse the value type
$valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
}
if ($tokens->current() !== '>') {
if (empty($tokens->current())) {
throw new RuntimeException(
'Collection: ">" is missing'
);
}
throw new RuntimeException(
'Unexpected character "' . $tokens->current() . '", ">" is missing'
);
}
if ($isArray) {
return new Array_($valueType, $keyType);
}
/** @psalm-suppress RedundantCondition */
if ($classType instanceof Object_) {
return $this->makeCollectionFromObject($classType, $valueType, $keyType);
}
throw new RuntimeException('Invalid $classType provided');
}
/**
* Resolve nullable types (i.e. `?string`) into a Nullable type wrapper
*
* @param string $type
* @param Context $context
*
* @return Nullable
*/
private function resolveNullableType($type, Context $context)
private function makeCollectionFromObject(Object_ $object, Type $valueType, ?Type $keyType = null) : Collection
{
return new Nullable($this->resolve(ltrim($type, '?'), $context));
return new Collection($object->getFqsen(), $valueType, $keyType);
}
}

View File

@@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use phpDocumentor\Reflection\Type;
/**
* Represents a list of values. This is an abstract class for Array_ and Collection.
*/
abstract class AbstractList implements Type
{
/** @var Type */
protected $valueType;
/** @var Type|null */
protected $keyType;
/** @var Type */
protected $defaultKeyType;
/**
* Initializes this representation of an array with the given Type.
*/
public function __construct(?Type $valueType = null, ?Type $keyType = null)
{
if ($valueType === null) {
$valueType = new Mixed_();
}
$this->valueType = $valueType;
$this->defaultKeyType = new Compound([new String_(), new Integer()]);
$this->keyType = $keyType;
}
/**
* Returns the type for the keys of this array.
*/
public function getKeyType() : Type
{
if ($this->keyType === null) {
return $this->defaultKeyType;
}
return $this->keyType;
}
/**
* Returns the value for the keys of this array.
*/
public function getValueType() : Type
{
return $this->valueType;
}
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*/
public function __toString() : string
{
if ($this->keyType) {
return 'array<' . $this->keyType . ',' . $this->valueType . '>';
}
if ($this->valueType instanceof Mixed_) {
return 'array';
}
if ($this->valueType instanceof Compound) {
return '(' . $this->valueType . ')[]';
}
return $this->valueType . '[]';
}
}

View File

@@ -1,19 +1,18 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use phpDocumentor\Reflection\Type;
/**
* Represents an array type as described in the PSR-5, the PHPDoc Standard.
*
@@ -23,64 +22,6 @@ use phpDocumentor\Reflection\Type;
* 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a
* type name.
*/
final class Array_ implements Type
final class Array_ extends AbstractList
{
/** @var Type */
private $valueType;
/** @var Type */
private $keyType;
/**
* Initializes this representation of an array with the given Type or Fqsen.
*
* @param Type $valueType
* @param Type $keyType
*/
public function __construct(Type $valueType = null, Type $keyType = null)
{
if ($keyType === null) {
$keyType = new Compound([ new String_(), new Integer() ]);
}
if ($valueType === null) {
$valueType = new Mixed_();
}
$this->valueType = $valueType;
$this->keyType = $keyType;
}
/**
* Returns the type for the keys of this array.
*
* @return Type
*/
public function getKeyType()
{
return $this->keyType;
}
/**
* Returns the value for the keys of this array.
*
* @return Type
*/
public function getValueType()
{
return $this->valueType;
}
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
{
if ($this->valueType instanceof Mixed_) {
return 'array';
}
return $this->valueType . '[]';
}
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Boolean implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'bool';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Callable_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'callable';
}

View File

@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\Type;
/**
* Represents a collection type as described in the PSR-5, the PHPDoc Standard.
*
* A collection can be represented in two forms:
*
* 1. `ACollectionObject<aValueType>`
* 2. `ACollectionObject<aValueType,aKeyType>`
*
* - ACollectionObject can be 'array' or an object that can act as an array
* - aValueType and aKeyType can be any type expression
*/
final class Collection extends AbstractList
{
/** @var Fqsen|null */
private $fqsen;
/**
* Initializes this representation of an array with the given Type or Fqsen.
*/
public function __construct(?Fqsen $fqsen, Type $valueType, ?Type $keyType = null)
{
parent::__construct($valueType, $keyType);
$this->fqsen = $fqsen;
}
/**
* Returns the FQSEN associated with this object.
*/
public function getFqsen() : ?Fqsen
{
return $this->fqsen;
}
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*/
public function __toString() : string
{
$objectType = (string) ($this->fqsen ?? 'object');
if ($this->keyType === null) {
return $objectType . '<' . $this->valueType . '>';
}
return $objectType . '<' . $this->keyType . ',' . $this->valueType . '>';
}
}

View File

@@ -1,20 +1,23 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use ArrayIterator;
use InvalidArgumentException;
use IteratorAggregate;
use phpDocumentor\Reflection\Type;
use function implode;
/**
* Value Object representing a Compound Type.
@@ -32,13 +35,15 @@ final class Compound implements Type, IteratorAggregate
* Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface.
*
* @param Type[] $types
* @throws \InvalidArgumentException when types are not all instance of Type
*
* @throws InvalidArgumentException When types are not all instance of Type.
*/
public function __construct(array $types)
{
foreach ($types as $type) {
/** @psalm-suppress RedundantConditionGivenDocblockType */
if (!$type instanceof Type) {
throw new \InvalidArgumentException('A compound type can only have other types as elements');
throw new InvalidArgumentException('A compound type can only have other types as elements');
}
}
@@ -47,12 +52,8 @@ final class Compound implements Type, IteratorAggregate
/**
* Returns the type at the given index.
*
* @param integer $index
*
* @return Type|null
*/
public function get($index)
public function get(int $index) : ?Type
{
if (!$this->has($index)) {
return null;
@@ -63,22 +64,16 @@ final class Compound implements Type, IteratorAggregate
/**
* Tests if this compound type has a type with the given index.
*
* @param integer $index
*
* @return bool
*/
public function has($index)
public function has(int $index) : bool
{
return isset($this->types[$index]);
}
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return implode('|', $this->types);
}

View File

@@ -1,17 +1,22 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use function strlen;
use function substr;
use function trim;
/**
* Provides information about the Context in which the DocBlock occurs that receives this context.
*
@@ -31,26 +36,27 @@ final class Context
/** @var string The current namespace. */
private $namespace;
/** @var array List of namespace aliases => Fully Qualified Namespace. */
/** @var string[] List of namespace aliases => Fully Qualified Namespace. */
private $namespaceAliases;
/**
* Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN)
* format (without a preceding `\`).
*
* @param string $namespace The namespace where this DocBlock resides in.
* @param array $namespaceAliases List of namespace aliases => Fully Qualified Namespace.
* @param string $namespace The namespace where this DocBlock resides in.
* @param string[] $namespaceAliases List of namespace aliases => Fully Qualified Namespace.
*/
public function __construct($namespace, array $namespaceAliases = [])
public function __construct(string $namespace, array $namespaceAliases = [])
{
$this->namespace = ('global' !== $namespace && 'default' !== $namespace)
? trim((string)$namespace, '\\')
$this->namespace = $namespace !== 'global' && $namespace !== 'default'
? trim($namespace, '\\')
: '';
foreach ($namespaceAliases as $alias => $fqnn) {
if ($fqnn[0] === '\\') {
$fqnn = substr($fqnn, 1);
}
if ($fqnn[strlen($fqnn) - 1] === '\\') {
$fqnn = substr($fqnn, 0, -1);
}
@@ -63,10 +69,8 @@ final class Context
/**
* Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in.
*
* @return string
*/
public function getNamespace()
public function getNamespace() : string
{
return $this->namespace;
}
@@ -77,7 +81,7 @@ final class Context
*
* @return string[]
*/
public function getNamespaceAliases()
public function getNamespaceAliases() : array
{
return $this->namespaceAliases;
}

View File

@@ -1,17 +1,44 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use ArrayIterator;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionClassConstant;
use ReflectionMethod;
use ReflectionParameter;
use ReflectionProperty;
use Reflector;
use RuntimeException;
use UnexpectedValueException;
use const T_AS;
use const T_CLASS;
use const T_CURLY_OPEN;
use const T_DOLLAR_OPEN_CURLY_BRACES;
use const T_NAMESPACE;
use const T_NS_SEPARATOR;
use const T_STRING;
use const T_USE;
use function array_merge;
use function file_exists;
use function file_get_contents;
use function get_class;
use function is_string;
use function token_get_all;
use function trim;
/**
* Convenience class to create a Context for DocBlocks when not using the Reflection Component of phpDocumentor.
*
@@ -24,31 +51,78 @@ namespace phpDocumentor\Reflection\Types;
final class ContextFactory
{
/** The literal used at the end of a use statement. */
const T_LITERAL_END_OF_USE = ';';
private const T_LITERAL_END_OF_USE = ';';
/** The literal used between sets of use statements */
const T_LITERAL_USE_SEPARATOR = ',';
private const T_LITERAL_USE_SEPARATOR = ',';
/**
* Build a Context given a Class Reflection.
*
* @param \Reflector $reflector
*
* @see Context for more information on Contexts.
*
* @return Context
*/
public function createFromReflector(\Reflector $reflector)
public function createFromReflector(Reflector $reflector) : Context
{
if (method_exists($reflector, 'getDeclaringClass')) {
$reflector = $reflector->getDeclaringClass();
if ($reflector instanceof ReflectionClass) {
return $this->createFromReflectionClass($reflector);
}
$fileName = $reflector->getFileName();
$namespace = $reflector->getNamespaceName();
if ($reflector instanceof ReflectionParameter) {
return $this->createFromReflectionParameter($reflector);
}
if (file_exists($fileName)) {
return $this->createForNamespace($namespace, file_get_contents($fileName));
if ($reflector instanceof ReflectionMethod) {
return $this->createFromReflectionMethod($reflector);
}
if ($reflector instanceof ReflectionProperty) {
return $this->createFromReflectionProperty($reflector);
}
if ($reflector instanceof ReflectionClassConstant) {
return $this->createFromReflectionClassConstant($reflector);
}
throw new UnexpectedValueException('Unhandled \Reflector instance given: ' . get_class($reflector));
}
private function createFromReflectionParameter(ReflectionParameter $parameter) : Context
{
$class = $parameter->getDeclaringClass();
if ($class) {
return $this->createFromReflectionClass($class);
}
throw new InvalidArgumentException('Unable to get class of ' . $parameter->getName());
}
private function createFromReflectionMethod(ReflectionMethod $method) : Context
{
return $this->createFromReflectionClass($method->getDeclaringClass());
}
private function createFromReflectionProperty(ReflectionProperty $property) : Context
{
return $this->createFromReflectionClass($property->getDeclaringClass());
}
private function createFromReflectionClassConstant(ReflectionClassConstant $constant) : Context
{
return $this->createFromReflectionClass($constant->getDeclaringClass());
}
private function createFromReflectionClass(ReflectionClass $class) : Context
{
$fileName = $class->getFileName();
$namespace = $class->getNamespaceName();
if (is_string($fileName) && file_exists($fileName)) {
$contents = file_get_contents($fileName);
if ($contents === false) {
throw new RuntimeException('Unable to read file "' . $fileName . '"');
}
return $this->createForNamespace($namespace, $contents);
}
return new Context($namespace, []);
@@ -57,19 +131,18 @@ final class ContextFactory
/**
* Build a Context for a namespace in the provided file contents.
*
* @param string $namespace It does not matter if a `\` precedes the namespace name, this method first normalizes.
* @param string $fileContents the file's contents to retrieve the aliases from with the given namespace.
*
* @see Context for more information on Contexts.
*
* @return Context
* @param string $namespace It does not matter if a `\` precedes the namespace name,
* this method first normalizes.
* @param string $fileContents The file's contents to retrieve the aliases from with the given namespace.
*/
public function createForNamespace($namespace, $fileContents)
public function createForNamespace(string $namespace, string $fileContents) : Context
{
$namespace = trim($namespace, '\\');
$useStatements = [];
$namespace = trim($namespace, '\\');
$useStatements = [];
$currentNamespace = '';
$tokens = new \ArrayIterator(token_get_all($fileContents));
$tokens = new ArrayIterator(token_get_all($fileContents));
while ($tokens->valid()) {
switch ($tokens->current()[0]) {
@@ -80,7 +153,7 @@ final class ContextFactory
// Fast-forward the iterator through the class so that any
// T_USE tokens found within are skipped - these are not
// valid namespace use statements so should be ignored.
$braceLevel = 0;
$braceLevel = 0;
$firstBraceFound = false;
while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) {
if ($tokens->current() === '{'
@@ -89,12 +162,14 @@ final class ContextFactory
if (!$firstBraceFound) {
$firstBraceFound = true;
}
$braceLevel++;
++$braceLevel;
}
if ($tokens->current() === '}') {
$braceLevel--;
--$braceLevel;
}
$tokens->next();
}
break;
@@ -104,6 +179,7 @@ final class ContextFactory
}
break;
}
$tokens->next();
}
@@ -112,12 +188,8 @@ final class ContextFactory
/**
* Deduce the name from tokens when we are at the T_NAMESPACE token.
*
* @param \ArrayIterator $tokens
*
* @return string
*/
private function parseNamespace(\ArrayIterator $tokens)
private function parseNamespace(ArrayIterator $tokens) : string
{
// skip to the first string or namespace separator
$this->skipToNextStringOrNamespaceSeparator($tokens);
@@ -135,22 +207,18 @@ final class ContextFactory
/**
* Deduce the names of all imports when we are at the T_USE token.
*
* @param \ArrayIterator $tokens
*
* @return string[]
*/
private function parseUseStatement(\ArrayIterator $tokens)
private function parseUseStatement(ArrayIterator $tokens) : array
{
$uses = [];
$continue = true;
while ($continue) {
while (true) {
$this->skipToNextStringOrNamespaceSeparator($tokens);
list($alias, $fqnn) = $this->extractUseStatement($tokens);
$uses[$alias] = $fqnn;
$uses = array_merge($uses, $this->extractUseStatements($tokens));
if ($tokens->current()[0] === self::T_LITERAL_END_OF_USE) {
$continue = false;
return $uses;
}
}
@@ -159,12 +227,8 @@ final class ContextFactory
/**
* Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token.
*
* @param \ArrayIterator $tokens
*
* @return void
*/
private function skipToNextStringOrNamespaceSeparator(\ArrayIterator $tokens)
private function skipToNextStringOrNamespaceSeparator(ArrayIterator $tokens) : void
{
while ($tokens->valid() && ($tokens->current()[0] !== T_STRING) && ($tokens->current()[0] !== T_NS_SEPARATOR)) {
$tokens->next();
@@ -173,38 +237,114 @@ final class ContextFactory
/**
* Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of
* a USE statement yet.
* a USE statement yet. This will return a key/value array of the alias => namespace.
*
* @param \ArrayIterator $tokens
* @return string[]
*
* @return string
* @psalm-suppress TypeDoesNotContainType
*/
private function extractUseStatement(\ArrayIterator $tokens)
private function extractUseStatements(ArrayIterator $tokens) : array
{
$result = [''];
while ($tokens->valid()
&& ($tokens->current()[0] !== self::T_LITERAL_USE_SEPARATOR)
&& ($tokens->current()[0] !== self::T_LITERAL_END_OF_USE)
) {
if ($tokens->current()[0] === T_AS) {
$result[] = '';
$extractedUseStatements = [];
$groupedNs = '';
$currentNs = '';
$currentAlias = '';
$state = 'start';
while ($tokens->valid()) {
$currentToken = $tokens->current();
$tokenId = is_string($currentToken) ? $currentToken : $currentToken[0];
$tokenValue = is_string($currentToken) ? null : $currentToken[1];
switch ($state) {
case 'start':
switch ($tokenId) {
case T_STRING:
case T_NS_SEPARATOR:
$currentNs .= $tokenValue;
$currentAlias = $tokenValue;
break;
case T_CURLY_OPEN:
case '{':
$state = 'grouped';
$groupedNs = $currentNs;
break;
case T_AS:
$state = 'start-alias';
break;
case self::T_LITERAL_USE_SEPARATOR:
case self::T_LITERAL_END_OF_USE:
$state = 'end';
break;
default:
break;
}
break;
case 'start-alias':
switch ($tokenId) {
case T_STRING:
$currentAlias = $tokenValue;
break;
case self::T_LITERAL_USE_SEPARATOR:
case self::T_LITERAL_END_OF_USE:
$state = 'end';
break;
default:
break;
}
break;
case 'grouped':
switch ($tokenId) {
case T_STRING:
case T_NS_SEPARATOR:
$currentNs .= $tokenValue;
$currentAlias = $tokenValue;
break;
case T_AS:
$state = 'grouped-alias';
break;
case self::T_LITERAL_USE_SEPARATOR:
$state = 'grouped';
$extractedUseStatements[$currentAlias] = $currentNs;
$currentNs = $groupedNs;
$currentAlias = '';
break;
case self::T_LITERAL_END_OF_USE:
$state = 'end';
break;
default:
break;
}
break;
case 'grouped-alias':
switch ($tokenId) {
case T_STRING:
$currentAlias = $tokenValue;
break;
case self::T_LITERAL_USE_SEPARATOR:
$state = 'grouped';
$extractedUseStatements[$currentAlias] = $currentNs;
$currentNs = $groupedNs;
$currentAlias = '';
break;
case self::T_LITERAL_END_OF_USE:
$state = 'end';
break;
default:
break;
}
}
if ($tokens->current()[0] === T_STRING || $tokens->current()[0] === T_NS_SEPARATOR) {
$result[count($result) - 1] .= $tokens->current()[1];
if ($state === 'end') {
break;
}
$tokens->next();
}
if (count($result) == 1) {
$backslashPos = strrpos($result[0], '\\');
if (false !== $backslashPos) {
$result[] = substr($result[0], $backslashPos + 1);
} else {
$result[] = $result[0];
}
if ($groupedNs !== $currentNs) {
$extractedUseStatements[$currentAlias] = $currentNs;
}
return array_reverse($result);
return $extractedUseStatements;
}
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Float_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'float';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -18,10 +19,8 @@ final class Integer implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'int';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2017 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Iterable_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'iterable';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Mixed_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'mixed';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Null_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'null';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2017 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -19,15 +20,11 @@ use phpDocumentor\Reflection\Type;
*/
final class Nullable implements Type
{
/**
* @var Type
*/
/** @var Type The actual type that is wrapped */
private $realType;
/**
* Initialises this nullable type using the real type embedded
*
* @param Type $realType
*/
public function __construct(Type $realType)
{
@@ -36,20 +33,16 @@ final class Nullable implements Type
/**
* Provide access to the actual type directly, if needed.
*
* @return Type
*/
public function getActualType()
public function getActualType() : Type
{
return $this->realType;
}
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return '?' . $this->realType->__toString();
}

View File

@@ -1,19 +1,22 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
namespace phpDocumentor\Reflection\Types;
use InvalidArgumentException;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\Type;
use function strpos;
/**
* Value Object representing an object.
@@ -30,15 +33,14 @@ final class Object_ implements Type
/**
* Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'.
*
* @param Fqsen $fqsen
* @throws \InvalidArgumentException when provided $fqsen is not a valid type.
* @throws InvalidArgumentException When provided $fqsen is not a valid type.
*/
public function __construct(Fqsen $fqsen = null)
public function __construct(?Fqsen $fqsen = null)
{
if (strpos((string)$fqsen, '::') !== false || strpos((string)$fqsen, '()') !== false) {
throw new \InvalidArgumentException(
if (strpos((string) $fqsen, '::') !== false || strpos((string) $fqsen, '()') !== false) {
throw new InvalidArgumentException(
'Object types can only refer to a class, interface or trait but a method, function, constant or '
. 'property was received: ' . (string)$fqsen
. 'property was received: ' . (string) $fqsen
);
}
@@ -47,23 +49,16 @@ final class Object_ implements Type
/**
* Returns the FQSEN associated with this object.
*
* @return Fqsen|null
*/
public function getFqsen()
public function getFqsen() : ?Fqsen
{
return $this->fqsen;
}
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
if ($this->fqsen) {
return (string)$this->fqsen;
return (string) $this->fqsen;
}
return 'object';

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -23,10 +24,8 @@ final class Parent_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'parent';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Resource_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'resource';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class Scalar implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'scalar';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -23,10 +24,8 @@ final class Self_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'self';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -28,10 +29,8 @@ final class Static_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'static';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -21,10 +22,8 @@ final class String_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'string';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -24,10 +25,8 @@ final class This implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return '$this';
}

View File

@@ -1,12 +1,13 @@
<?php
declare(strict_types=1);
/**
* This file is part of phpDocumentor.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link http://phpdoc.org
*/
@@ -24,10 +25,8 @@ final class Void_ implements Type
{
/**
* Returns a rendered output of the Type as it would be used in a DocBlock.
*
* @return string
*/
public function __toString()
public function __toString() : string
{
return 'void';
}