Dep: update
주로 PHAN
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
version: 1
|
||||
update_configs:
|
||||
- package_manager: "php:composer"
|
||||
directory: "/"
|
||||
update_schedule: "weekly"
|
||||
automerged_updates:
|
||||
- match:
|
||||
dependency_type: "development"
|
||||
update_type: "all"
|
||||
- match:
|
||||
dependency_type: "production"
|
||||
update_type: "semver:patch"
|
||||
@@ -1,250 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
name: Qa workflow
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Restore/cache tools folder
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: tools
|
||||
key: all-tools-${{ github.sha }}
|
||||
restore-keys: |
|
||||
all-tools-${{ github.sha }}-
|
||||
all-tools-
|
||||
|
||||
- name: composer
|
||||
uses: docker://composer
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
args: install --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
- name: composer-require-checker
|
||||
uses: docker://phpga/composer-require-checker-ga
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
args: check --config-file ./composer-require-config.json composer.json
|
||||
|
||||
- name: Install phive
|
||||
run: make install-phive
|
||||
|
||||
- name: Install PHAR dependencies
|
||||
run: tools/phive.phar --no-progress install --copy --trust-gpg-keys 4AA394086372C20A,D2CCAC42F6295E7D,E82B2FB314E9906E,8E730BA25823D8B5 --force-accept-unsigned
|
||||
|
||||
phpunit-with-coverage:
|
||||
runs-on: ubuntu-latest
|
||||
name: Unit tests
|
||||
needs: setup
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Restore/cache vendor folder
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: vendor
|
||||
key: all-build-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
all-build-${{ hashFiles('**/composer.lock') }}
|
||||
all-build-
|
||||
|
||||
- name: Restore/cache tools folder
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: tools
|
||||
key: all-tools-${{ github.sha }}
|
||||
restore-keys: |
|
||||
all-tools-${{ github.sha }}-
|
||||
all-tools-
|
||||
|
||||
- name: PHPUnit
|
||||
uses: docker://phpdoc/phpunit-ga:latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Quick check code coverage level
|
||||
run: php tests/coverage-checker.php 89
|
||||
|
||||
phpunit:
|
||||
name: Unit tests for PHP version ${{ matrix.php-versions }} on ${{ matrix.operating-system }}
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macOS-latest
|
||||
php-versions: ['7.2', '7.3', '7.4']
|
||||
env:
|
||||
extensions: mbstring
|
||||
key: cache-v1 # can be any string, change to clear the extension cache.
|
||||
|
||||
needs:
|
||||
- setup
|
||||
- phpunit-with-coverage
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Setup cache environment
|
||||
id: cache-env
|
||||
uses: shivammathur/cache-extensions@v1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
key: ${{ env.key }}
|
||||
|
||||
- name: Cache extensions
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.cache-env.outputs.dir }}
|
||||
key: ${{ steps.cache-env.outputs.key }}
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extension: ${{ env.extensions }}
|
||||
ini-values: memory_limit=2G, display_errors=On, error_reporting=-1
|
||||
|
||||
- name: Restore/cache tools folder
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: tools
|
||||
key: all-tools-${{ github.sha }}
|
||||
restore-keys: |
|
||||
all-tools-${{ github.sha }}-
|
||||
all-tools-
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
- name: Run PHPUnit
|
||||
continue-on-error: true
|
||||
run: php tools/phpunit
|
||||
|
||||
codestyle:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup, phpunit]
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Restore/cache vendor folder
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: vendor
|
||||
key: all-build-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
all-build-${{ hashFiles('**/composer.lock') }}
|
||||
all-build-
|
||||
- name: Code style check
|
||||
uses: phpDocumentor/coding-standard@master
|
||||
with:
|
||||
args: -s
|
||||
|
||||
phpstan:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup, phpunit]
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Restore/cache vendor folder
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: vendor
|
||||
key: all-build-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
all-build-${{ hashFiles('**/composer.lock') }}
|
||||
all-build-
|
||||
- name: PHPStan
|
||||
uses: phpDocumentor/phpstan-ga@0.12.3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
args: analyse src --configuration phpstan.neon
|
||||
|
||||
psalm:
|
||||
name: Psalm
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system:
|
||||
- ubuntu-latest
|
||||
php-versions: ['7.2']
|
||||
env:
|
||||
extensions: mbstring
|
||||
key: cache-v1 # can be any string, change to clear the extension cache.
|
||||
|
||||
needs:
|
||||
- setup
|
||||
- phpunit
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Setup cache environment
|
||||
id: cache-env
|
||||
uses: shivammathur/cache-extensions@v1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
key: ${{ env.key }}
|
||||
|
||||
- name: Cache extensions
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.cache-env.outputs.dir }}
|
||||
key: ${{ steps.cache-env.outputs.key }}
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@master
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extension: ${{ env.extensions }}
|
||||
tools: psalm
|
||||
ini-values: memory_limit=2G, display_errors=On, error_reporting=-1
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
- name: Run psalm
|
||||
run: psalm --output-format=github
|
||||
|
||||
|
||||
bc_check:
|
||||
name: BC Check
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup, phpunit]
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: fetch tags
|
||||
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
- name: BC Check
|
||||
uses: docker://nyholm/roave-bc-check-ga
|
||||
@@ -1,37 +0,0 @@
|
||||
.PHONY: install-phive
|
||||
install-phive:
|
||||
mkdir tools; \
|
||||
wget -O tools/phive.phar https://phar.io/releases/phive.phar; \
|
||||
wget -O tools/phive.phar.asc https://phar.io/releases/phive.phar.asc; \
|
||||
gpg --keyserver pool.sks-keyservers.net --recv-keys 0x9D8A98B29B2D5D79; \
|
||||
gpg --verify tools/phive.phar.asc tools/phive.phar; \
|
||||
chmod +x tools/phive.phar
|
||||
|
||||
.PHONY: setup
|
||||
setup: install-phive
|
||||
docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phar-ga:latest php tools/phive.phar install --force-accept-unsigned
|
||||
|
||||
.PHONY: phpcs
|
||||
phpcs:
|
||||
docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpcs-ga:v1.0.0 -s
|
||||
|
||||
.PHONY: phpcbf
|
||||
phpcbf:
|
||||
docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpcs-ga:v1.0.0 phpcbf
|
||||
|
||||
.PHONY: phpstan
|
||||
phpstan:
|
||||
docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpstan-ga:latest analyse src --no-progress --configuration phpstan.neon
|
||||
|
||||
.PHONY: psalm
|
||||
psalm:
|
||||
docker run -it --rm -v${PWD}:/opt/project -w /opt/project mickaelandrieu/psalm-ga
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
docker run -it --rm -v${CURDIR}:/github/workspace phpdoc/phpunit-ga
|
||||
docker run -it --rm -v${CURDIR}:/data -w /data php:7.2 -f ./tests/coverage-checker.php 89
|
||||
|
||||
.PHONY: pre-commit-test
|
||||
pre-commit-test: test phpcs phpstan psalm
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
+6
-7
@@ -14,15 +14,14 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"phpdocumentor/type-resolver": "^1.0",
|
||||
"webmozart/assert": "^1",
|
||||
"phpdocumentor/reflection-common": "^2.0",
|
||||
"ext-filter": "^7.1"
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpdocumentor/type-resolver": "^1.3",
|
||||
"webmozart/assert": "^1.9.1",
|
||||
"phpdocumentor/reflection-common": "^2.2",
|
||||
"ext-filter": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1",
|
||||
"doctrine/instantiator": "^1"
|
||||
"mockery/mockery": "~1.3.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phive xmlns="https://phar.io/phive">
|
||||
<phar name="phpunit" version="^8.4.3" installed="8.4.3" location="./tools/phpunit" copy="true"/>
|
||||
<phar name="phpstan" version="^0.9.1" installed="0.12.2" location="./tools/phpstan" copy="true"/>
|
||||
</phive>
|
||||
@@ -1,17 +0,0 @@
|
||||
<?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="phpDocumentor">
|
||||
<exclude name="SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException" />
|
||||
</rule>
|
||||
|
||||
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix">
|
||||
<exclude-pattern>*/src/*/Abstract*.php</exclude-pattern>
|
||||
</rule>
|
||||
</ruleset>
|
||||
@@ -1,8 +0,0 @@
|
||||
includes:
|
||||
- /composer/vendor/phpstan/phpstan-mockery/extension.neon
|
||||
- /composer/vendor/phpstan/phpstan-webmozart-assert/extension.neon
|
||||
|
||||
parameters:
|
||||
level: max
|
||||
ignoreErrors:
|
||||
- '#Call to static method Webmozart\\Assert\\Assert::implementsInterface\(\) with class-string#'
|
||||
@@ -1,45 +0,0 @@
|
||||
<?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>
|
||||
<RedundantConditionGivenDocblockType>
|
||||
<errorLevel type="info">
|
||||
<!-- Psalm is very strict and believe that because we documented a type, it is redundant to assert it -->
|
||||
<file name="src/DocBlock/StandardTagFactory.php"/>
|
||||
</errorLevel>
|
||||
</RedundantConditionGivenDocblockType>
|
||||
|
||||
<PossiblyNullArrayOffset>
|
||||
<errorLevel type="info">
|
||||
<!-- Psalm forbid accessing an array with a null offset but it's still working code without notice -->
|
||||
<file name="src/DocBlock/StandardTagFactory.php"/>
|
||||
</errorLevel>
|
||||
</PossiblyNullArrayOffset>
|
||||
|
||||
<DeprecatedInterface>
|
||||
<errorLevel type="info">
|
||||
<!-- Will be removed in 6.0.0 issues/211 -->
|
||||
<referencedClass name="phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod"/>
|
||||
</errorLevel>
|
||||
</DeprecatedInterface>
|
||||
|
||||
<RedundantConditionGivenDocblockType>
|
||||
<errorLevel type="info">
|
||||
<!-- Psalm manage to infer a more precise type than PHPStan. notNull assert is needed for PHPStan but
|
||||
Psalm sees it as redundant -->
|
||||
<directory name="src/DocBlock/Tags/"/>
|
||||
</errorLevel>
|
||||
</RedundantConditionGivenDocblockType>
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
+2
-6
@@ -14,13 +14,12 @@ declare(strict_types=1);
|
||||
namespace phpDocumentor\Reflection\DocBlock;
|
||||
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use Webmozart\Assert\Assert;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function ltrim;
|
||||
use function min;
|
||||
use function preg_split;
|
||||
use function str_replace;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
@@ -98,7 +97,7 @@ class DescriptionFactory
|
||||
return [$contents];
|
||||
}
|
||||
|
||||
$parts = preg_split(
|
||||
return Utils::pregSplit(
|
||||
'/\{
|
||||
# "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally.
|
||||
(?!@\})
|
||||
@@ -127,9 +126,6 @@ class DescriptionFactory
|
||||
0,
|
||||
PREG_SPLIT_DELIM_CAPTURE
|
||||
);
|
||||
Assert::isArray($parts);
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-5
@@ -17,7 +17,6 @@ use InvalidArgumentException;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Author;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Covers;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag;
|
||||
@@ -37,6 +36,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\Version;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use ReflectionMethod;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionParameter;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_merge;
|
||||
@@ -165,7 +165,7 @@ final class StandardTagFactory implements TagFactory
|
||||
{
|
||||
Assert::stringNotEmpty($tagName);
|
||||
Assert::classExists($handler);
|
||||
Assert::implementsInterface($handler, StaticMethod::class);
|
||||
Assert::implementsInterface($handler, Tag::class);
|
||||
|
||||
if (strpos($tagName, '\\') && $tagName[0] !== '\\') {
|
||||
throw new InvalidArgumentException(
|
||||
@@ -255,10 +255,16 @@ final class StandardTagFactory implements TagFactory
|
||||
{
|
||||
$arguments = [];
|
||||
foreach ($parameters as $parameter) {
|
||||
$class = $parameter->getClass();
|
||||
$type = $parameter->getType();
|
||||
$typeHint = null;
|
||||
if ($class !== null) {
|
||||
$typeHint = $class->getName();
|
||||
if ($type instanceof ReflectionNamedType) {
|
||||
$typeHint = $type->getName();
|
||||
if ($typeHint === 'self') {
|
||||
$declaringClass = $parameter->getDeclaringClass();
|
||||
if ($declaringClass !== null) {
|
||||
$typeHint = $declaringClass->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($locator[$typeHint])) {
|
||||
@@ -282,6 +288,8 @@ final class StandardTagFactory implements TagFactory
|
||||
* Retrieves a series of ReflectionParameter objects for the static 'create' method of the given
|
||||
* tag handler class name.
|
||||
*
|
||||
* @param class-string $handlerClassName
|
||||
*
|
||||
* @return ReflectionParameter[]
|
||||
*/
|
||||
private function fetchParametersForHandlerFactoryMethod(string $handlerClassName) : array
|
||||
|
||||
@@ -71,7 +71,15 @@ final class Author extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->authorName . ($this->authorEmail !== '' ? ' <' . $this->authorEmail . '>' : '');
|
||||
if ($this->authorEmail) {
|
||||
$authorEmail = '<' . $this->authorEmail . '>';
|
||||
} else {
|
||||
$authorEmail = '';
|
||||
}
|
||||
|
||||
$authorName = (string) $this->authorName;
|
||||
|
||||
return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,8 +18,10 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function preg_split;
|
||||
use function array_key_exists;
|
||||
use function explode;
|
||||
|
||||
/**
|
||||
* Reflection class for a @covers tag in a Docblock.
|
||||
@@ -47,19 +49,31 @@ final class Covers extends BaseTag implements Factory\StaticMethod
|
||||
?FqsenResolver $resolver = null,
|
||||
?TypeContext $context = null
|
||||
) : self {
|
||||
Assert::notEmpty($body);
|
||||
Assert::stringNotEmpty($body);
|
||||
Assert::notNull($descriptionFactory);
|
||||
Assert::notNull($resolver);
|
||||
|
||||
$parts = preg_split('/\s+/Su', $body, 2);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
|
||||
return new static(
|
||||
$resolver->resolve($parts[0], $context),
|
||||
self::resolveFqsen($parts[0], $resolver, $context),
|
||||
$descriptionFactory->create($parts[1] ?? '', $context)
|
||||
);
|
||||
}
|
||||
|
||||
private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
|
||||
{
|
||||
Assert::notNull($fqsenResolver);
|
||||
$fqsenParts = explode('::', $parts);
|
||||
$resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
|
||||
|
||||
if (!array_key_exists(1, $fqsenParts)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
return new Fqsen($resolved . '::' . $fqsenParts[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the structural element this tag refers to.
|
||||
*/
|
||||
@@ -73,6 +87,14 @@ final class Covers extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->refers . ($this->description ? ' ' . $this->description->render() : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$refers = (string) $this->refers;
|
||||
|
||||
return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod
|
||||
|
||||
public function __construct(?string $version = null, ?Description $description = null)
|
||||
{
|
||||
Assert::nullOrStringNotEmpty($version);
|
||||
Assert::nullOrNotEmpty($version);
|
||||
|
||||
$this->version = $version;
|
||||
$this->description = $description;
|
||||
@@ -95,6 +95,14 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->version ?? '') . ($this->description ? ' ' . $this->description->render() : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$version = (string) $this->version;
|
||||
|
||||
return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,15 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
/** @var string|null */
|
||||
private $content;
|
||||
|
||||
public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content)
|
||||
{
|
||||
Assert::notEmpty($filePath);
|
||||
Assert::greaterThanEq($startingLine, 0);
|
||||
public function __construct(
|
||||
string $filePath,
|
||||
bool $isURI,
|
||||
int $startingLine,
|
||||
int $lineCount,
|
||||
?string $content
|
||||
) {
|
||||
Assert::stringNotEmpty($filePath);
|
||||
Assert::greaterThanEq($startingLine, 1);
|
||||
Assert::greaterThanEq($lineCount, 0);
|
||||
|
||||
$this->filePath = $filePath;
|
||||
@@ -63,8 +68,8 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
|
||||
public function getContent() : string
|
||||
{
|
||||
if ($this->content === null) {
|
||||
$filePath = '"' . $this->filePath . '"';
|
||||
if ($this->content === null || $this->content === '') {
|
||||
$filePath = $this->filePath;
|
||||
if ($this->isURI) {
|
||||
$filePath = $this->isUriRelative($this->filePath)
|
||||
? str_replace('%2F', '/', rawurlencode($this->filePath))
|
||||
@@ -85,7 +90,7 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
public static function create(string $body) : ?Tag
|
||||
{
|
||||
// File component: File path in quotes or File URI / Source information
|
||||
if (!preg_match('/^(?:\"([^\"]+)\"|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) {
|
||||
if (!preg_match('/^\s*(?:(\"[^\"]+\")|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -107,7 +112,7 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
// Starting line / Number of lines / Description
|
||||
if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) {
|
||||
$startingLine = (int) $contentMatches[1];
|
||||
if (isset($contentMatches[2]) && $contentMatches[2] !== '') {
|
||||
if (isset($contentMatches[2])) {
|
||||
$lineCount = (int) $contentMatches[2];
|
||||
}
|
||||
|
||||
@@ -134,7 +139,7 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
*/
|
||||
public function getFilePath() : string
|
||||
{
|
||||
return $this->filePath;
|
||||
return trim($this->filePath, '"');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +147,22 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->filePath . ($this->content ? ' ' . $this->content : '');
|
||||
$filePath = (string) $this->filePath;
|
||||
$isDefaultLine = $this->startingLine === 1 && $this->lineCount === 0;
|
||||
$startingLine = !$isDefaultLine ? (string) $this->startingLine : '';
|
||||
$lineCount = !$isDefaultLine ? (string) $this->lineCount : '';
|
||||
$content = (string) $this->content;
|
||||
|
||||
return $filePath
|
||||
. ($startingLine !== ''
|
||||
? ($filePath !== '' ? ' ' : '') . $startingLine
|
||||
: '')
|
||||
. ($lineCount !== ''
|
||||
? ($filePath !== '' || $startingLine !== '' ? ' ' : '') . $lineCount
|
||||
: '')
|
||||
. ($content !== ''
|
||||
? ($filePath !== '' || $startingLine !== '' || $lineCount !== '' ? ' ' : '') . $content
|
||||
: '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,7 +64,13 @@ final class Generic extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->description ? $this->description->render() : '';
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+31
-20
@@ -8,12 +8,13 @@ use Closure;
|
||||
use Exception;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionFunction;
|
||||
use Throwable;
|
||||
use function array_map;
|
||||
use function array_walk_recursive;
|
||||
use function get_class;
|
||||
use function get_resource_type;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function sprintf;
|
||||
@@ -80,29 +81,12 @@ final class InvalidTag implements Tag
|
||||
$traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace');
|
||||
$traceProperty->setAccessible(true);
|
||||
|
||||
$flatten =
|
||||
/** @param mixed $value */
|
||||
static function (&$value) : void {
|
||||
if ($value instanceof Closure) {
|
||||
$closureReflection = new ReflectionFunction($value);
|
||||
$value = sprintf(
|
||||
'(Closure at %s:%s)',
|
||||
$closureReflection->getFileName(),
|
||||
$closureReflection->getStartLine()
|
||||
);
|
||||
} elseif (is_object($value)) {
|
||||
$value = sprintf('object(%s)', get_class($value));
|
||||
} elseif (is_resource($value)) {
|
||||
$value = sprintf('resource(%s)', get_resource_type($value));
|
||||
}
|
||||
};
|
||||
|
||||
do {
|
||||
$trace = $exception->getTrace();
|
||||
if (isset($trace[0]['args'])) {
|
||||
$trace = array_map(
|
||||
static function (array $call) use ($flatten) : array {
|
||||
array_walk_recursive($call['args'], $flatten);
|
||||
function (array $call) : array {
|
||||
$call['args'] = array_map([$this, 'flattenArguments'], $call['args']);
|
||||
|
||||
return $call;
|
||||
},
|
||||
@@ -117,6 +101,33 @@ final class InvalidTag implements Tag
|
||||
$traceProperty->setAccessible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function flattenArguments($value)
|
||||
{
|
||||
if ($value instanceof Closure) {
|
||||
$closureReflection = new ReflectionFunction($value);
|
||||
$value = sprintf(
|
||||
'(Closure at %s:%s)',
|
||||
$closureReflection->getFileName(),
|
||||
$closureReflection->getStartLine()
|
||||
);
|
||||
} elseif (is_object($value)) {
|
||||
$value = sprintf('object(%s)', get_class($value));
|
||||
} elseif (is_resource($value)) {
|
||||
$value = sprintf('resource(%s)', get_resource_type($value));
|
||||
} elseif (is_array($value)) {
|
||||
$value = array_map([$this, 'flattenArguments'], $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function render(?Formatter $formatter = null) : string
|
||||
{
|
||||
if ($formatter === null) {
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace phpDocumentor\Reflection\DocBlock\Tags;
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function preg_split;
|
||||
|
||||
/**
|
||||
* Reflection class for a @link tag in a Docblock.
|
||||
* Reflection class for a {@}link tag in a Docblock.
|
||||
*/
|
||||
final class Link extends BaseTag implements Factory\StaticMethod
|
||||
{
|
||||
@@ -46,8 +46,7 @@ final class Link extends BaseTag implements Factory\StaticMethod
|
||||
) : self {
|
||||
Assert::notNull($descriptionFactory);
|
||||
|
||||
$parts = preg_split('/\s+/Su', $body, 2);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
$description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
|
||||
|
||||
return new static($parts[0], $description);
|
||||
@@ -66,6 +65,14 @@ final class Link extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->link . ($this->description ? ' ' . $this->description->render() : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$link = (string) $this->link;
|
||||
|
||||
return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +213,25 @@ final class Method extends BaseTag implements Factory\StaticMethod
|
||||
$arguments[] = $argument['type'] . ' $' . $argument['name'];
|
||||
}
|
||||
|
||||
return trim(($this->isStatic() ? 'static ' : '')
|
||||
. (string) $this->returnType . ' '
|
||||
. $this->methodName
|
||||
. '(' . implode(', ', $arguments) . ')'
|
||||
. ($this->description ? ' ' . $this->description->render() : ''));
|
||||
$argumentStr = '(' . implode(', ', $arguments) . ')';
|
||||
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$static = $this->isStatic ? 'static' : '';
|
||||
|
||||
$returnType = (string) $this->returnType;
|
||||
|
||||
$methodName = (string) $this->methodName;
|
||||
|
||||
return $static
|
||||
. ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '')
|
||||
. ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $methodName : '')
|
||||
. $argumentStr
|
||||
. ($description !== '' ? ' ' . $description : '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,11 +18,11 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
@@ -38,17 +38,22 @@ final class Param extends TagWithType implements Factory\StaticMethod
|
||||
/** @var bool determines whether this is a variadic argument */
|
||||
private $isVariadic;
|
||||
|
||||
/** @var bool determines whether this is passed by reference */
|
||||
private $isReference;
|
||||
|
||||
public function __construct(
|
||||
?string $variableName,
|
||||
?Type $type = null,
|
||||
bool $isVariadic = false,
|
||||
?Description $description = null
|
||||
?Description $description = null,
|
||||
bool $isReference = false
|
||||
) {
|
||||
$this->name = 'param';
|
||||
$this->variableName = $variableName;
|
||||
$this->type = $type;
|
||||
$this->isVariadic = $isVariadic;
|
||||
$this->description = $description;
|
||||
$this->isReference = $isReference;
|
||||
}
|
||||
|
||||
public static function create(
|
||||
@@ -64,39 +69,46 @@ final class Param extends TagWithType implements Factory\StaticMethod
|
||||
[$firstPart, $body] = self::extractTypeFromBody($body);
|
||||
|
||||
$type = null;
|
||||
$parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$variableName = '';
|
||||
$isVariadic = false;
|
||||
$isReference = false;
|
||||
|
||||
// if the first item that is encountered is not a variable; it is a type
|
||||
if ($firstPart && $firstPart[0] !== '$') {
|
||||
if ($firstPart && !self::strStartsWithVariable($firstPart)) {
|
||||
$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]) && (strpos($parts[0], '$') === 0 || strpos($parts[0], '...$') === 0)) {
|
||||
// if the next item starts with a $ or ...$ or &$ or &...$ it must be the variable name
|
||||
if (isset($parts[0]) && self::strStartsWithVariable($parts[0])) {
|
||||
$variableName = array_shift($parts);
|
||||
array_shift($parts);
|
||||
if ($type) {
|
||||
array_shift($parts);
|
||||
}
|
||||
|
||||
Assert::notNull($variableName);
|
||||
|
||||
if (strpos($variableName, '...') === 0) {
|
||||
$isVariadic = true;
|
||||
$variableName = substr($variableName, 3);
|
||||
}
|
||||
|
||||
if (strpos($variableName, '$') === 0) {
|
||||
$variableName = substr($variableName, 1);
|
||||
} elseif (strpos($variableName, '&$') === 0) {
|
||||
$isReference = true;
|
||||
$variableName = substr($variableName, 2);
|
||||
} elseif (strpos($variableName, '...$') === 0) {
|
||||
$isVariadic = true;
|
||||
$variableName = substr($variableName, 4);
|
||||
} elseif (strpos($variableName, '&...$') === 0) {
|
||||
$isVariadic = true;
|
||||
$isReference = true;
|
||||
$variableName = substr($variableName, 5);
|
||||
}
|
||||
}
|
||||
|
||||
$description = $descriptionFactory->create(implode('', $parts), $context);
|
||||
|
||||
return new static($variableName, $type, $isVariadic, $description);
|
||||
return new static($variableName, $type, $isVariadic, $description, $isReference);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,14 +127,46 @@ final class Param extends TagWithType implements Factory\StaticMethod
|
||||
return $this->isVariadic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this tag is passed by reference.
|
||||
*/
|
||||
public function isReference() : bool
|
||||
{
|
||||
return $this->isReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation for this tag.
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->type ? $this->type . ' ' : '')
|
||||
. ($this->isVariadic() ? '...' : '')
|
||||
. ($this->variableName !== null ? '$' . $this->variableName : '')
|
||||
. ($this->description ? ' ' . $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$variableName = '';
|
||||
if ($this->variableName) {
|
||||
$variableName .= ($this->isReference ? '&' : '') . ($this->isVariadic ? '...' : '');
|
||||
$variableName .= '$' . $this->variableName;
|
||||
}
|
||||
|
||||
$type = (string) $this->type;
|
||||
|
||||
return $type
|
||||
. ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
|
||||
. ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
|
||||
private static function strStartsWithVariable(string $str) : bool
|
||||
{
|
||||
return strpos($str, '$') === 0
|
||||
||
|
||||
strpos($str, '...$') === 0
|
||||
||
|
||||
strpos($str, '&$') === 0
|
||||
||
|
||||
strpos($str, '&...$') === 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
@@ -57,8 +57,7 @@ final class Property extends TagWithType implements Factory\StaticMethod
|
||||
|
||||
[$firstPart, $body] = self::extractTypeFromBody($body);
|
||||
$type = null;
|
||||
$parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$variableName = '';
|
||||
|
||||
// if the first item that is encountered is not a variable; it is a type
|
||||
@@ -69,10 +68,12 @@ final class Property extends TagWithType implements Factory\StaticMethod
|
||||
array_unshift($parts, $firstPart);
|
||||
}
|
||||
|
||||
// if the next item starts with a $ or ...$ it must be the variable name
|
||||
// if the next item starts with a $ it must be the variable name
|
||||
if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
|
||||
$variableName = array_shift($parts);
|
||||
array_shift($parts);
|
||||
if ($type) {
|
||||
array_shift($parts);
|
||||
}
|
||||
|
||||
Assert::notNull($variableName);
|
||||
|
||||
@@ -97,8 +98,22 @@ final class Property extends TagWithType implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->type ? $this->type . ' ' : '')
|
||||
. ($this->variableName ? '$' . $this->variableName : '')
|
||||
. ($this->description ? ' ' . $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
if ($this->variableName) {
|
||||
$variableName = '$' . $this->variableName;
|
||||
} else {
|
||||
$variableName = '';
|
||||
}
|
||||
|
||||
$type = (string) $this->type;
|
||||
|
||||
return $type
|
||||
. ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
|
||||
. ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
+23
-8
@@ -18,11 +18,11 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
@@ -57,8 +57,7 @@ final class PropertyRead extends TagWithType implements Factory\StaticMethod
|
||||
|
||||
[$firstPart, $body] = self::extractTypeFromBody($body);
|
||||
$type = null;
|
||||
$parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$variableName = '';
|
||||
|
||||
// if the first item that is encountered is not a variable; it is a type
|
||||
@@ -69,10 +68,12 @@ final class PropertyRead extends TagWithType implements Factory\StaticMethod
|
||||
array_unshift($parts, $firstPart);
|
||||
}
|
||||
|
||||
// if the next item starts with a $ or ...$ it must be the variable name
|
||||
// if the next item starts with a $ it must be the variable name
|
||||
if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
|
||||
$variableName = array_shift($parts);
|
||||
array_shift($parts);
|
||||
if ($type) {
|
||||
array_shift($parts);
|
||||
}
|
||||
|
||||
Assert::notNull($variableName);
|
||||
|
||||
@@ -97,8 +98,22 @@ final class PropertyRead extends TagWithType implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->type ? $this->type . ' ' : '')
|
||||
. ($this->variableName ? '$' . $this->variableName : '')
|
||||
. ($this->description ? ' ' . $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
if ($this->variableName) {
|
||||
$variableName = '$' . $this->variableName;
|
||||
} else {
|
||||
$variableName = '';
|
||||
}
|
||||
|
||||
$type = (string) $this->type;
|
||||
|
||||
return $type
|
||||
. ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
|
||||
. ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
+23
-8
@@ -18,11 +18,11 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
@@ -57,8 +57,7 @@ final class PropertyWrite extends TagWithType implements Factory\StaticMethod
|
||||
|
||||
[$firstPart, $body] = self::extractTypeFromBody($body);
|
||||
$type = null;
|
||||
$parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$variableName = '';
|
||||
|
||||
// if the first item that is encountered is not a variable; it is a type
|
||||
@@ -69,10 +68,12 @@ final class PropertyWrite extends TagWithType implements Factory\StaticMethod
|
||||
array_unshift($parts, $firstPart);
|
||||
}
|
||||
|
||||
// if the next item starts with a $ or ...$ it must be the variable name
|
||||
// if the next item starts with a $ it must be the variable name
|
||||
if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
|
||||
$variableName = array_shift($parts);
|
||||
array_shift($parts);
|
||||
if ($type) {
|
||||
array_shift($parts);
|
||||
}
|
||||
|
||||
Assert::notNull($variableName);
|
||||
|
||||
@@ -97,8 +98,22 @@ final class PropertyWrite extends TagWithType implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->type ? $this->type . ' ' : '')
|
||||
. ($this->variableName ? '$' . $this->variableName : '')
|
||||
. ($this->description ? ' ' . $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
if ($this->variableName) {
|
||||
$variableName = '$' . $this->variableName;
|
||||
} else {
|
||||
$variableName = '';
|
||||
}
|
||||
|
||||
$type = (string) $this->type;
|
||||
|
||||
return $type
|
||||
. ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
|
||||
. ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,14 @@ final class Return_ extends TagWithType implements Factory\StaticMethod
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->type ?: 'mixed') . ' ' . (string) $this->description;
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$type = $this->type ? '' . $this->type : 'mixed';
|
||||
|
||||
return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,14 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_key_exists;
|
||||
use function explode;
|
||||
use function preg_match;
|
||||
use function preg_split;
|
||||
|
||||
/**
|
||||
* Reflection class for an {@}see tag in a Docblock.
|
||||
@@ -50,11 +53,9 @@ final class See extends BaseTag implements Factory\StaticMethod
|
||||
?DescriptionFactory $descriptionFactory = null,
|
||||
?TypeContext $context = null
|
||||
) : self {
|
||||
Assert::notNull($typeResolver);
|
||||
Assert::notNull($descriptionFactory);
|
||||
|
||||
$parts = preg_split('/\s+/Su', $body, 2);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
$description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
|
||||
|
||||
// https://tools.ietf.org/html/rfc2396#section-3
|
||||
@@ -62,7 +63,20 @@ final class See extends BaseTag implements Factory\StaticMethod
|
||||
return new static(new Url($parts[0]), $description);
|
||||
}
|
||||
|
||||
return new static(new FqsenRef($typeResolver->resolve($parts[0], $context)), $description);
|
||||
return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description);
|
||||
}
|
||||
|
||||
private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
|
||||
{
|
||||
Assert::notNull($fqsenResolver);
|
||||
$fqsenParts = explode('::', $parts);
|
||||
$resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
|
||||
|
||||
if (!array_key_exists(1, $fqsenParts)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
return new Fqsen($resolved . '::' . $fqsenParts[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,6 +92,14 @@ final class See extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->refers . ($this->description ? ' ' . $this->description->render() : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$refers = (string) $this->refers;
|
||||
|
||||
return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ final class Since extends BaseTag implements Factory\StaticMethod
|
||||
|
||||
public function __construct(?string $version = null, ?Description $description = null)
|
||||
{
|
||||
Assert::nullOrStringNotEmpty($version);
|
||||
Assert::nullOrNotEmpty($version);
|
||||
|
||||
$this->version = $version;
|
||||
$this->description = $description;
|
||||
@@ -89,6 +89,14 @@ final class Since extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return (string) $this->version . ($this->description ? ' ' . (string) $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$version = (string) $this->version;
|
||||
|
||||
return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,8 +96,22 @@ final class Source extends BaseTag implements Factory\StaticMethod
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->startingLine
|
||||
. ($this->lineCount !== null ? ' ' . $this->lineCount : '')
|
||||
. ($this->description ? ' ' . (string) $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$startingLine = (string) $this->startingLine;
|
||||
|
||||
$lineCount = $this->lineCount !== null ? '' . $this->lineCount : '';
|
||||
|
||||
return $startingLine
|
||||
. ($lineCount !== ''
|
||||
? ($startingLine || $startingLine === '0' ? ' ' : '') . $lineCount
|
||||
: '')
|
||||
. ($description !== ''
|
||||
? ($startingLine || $startingLine === '0' || $lineCount !== '' ? ' ' : '') . $description
|
||||
: '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,14 @@ final class Throws extends TagWithType implements Factory\StaticMethod
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
return (string) $this->type . ' ' . (string) $this->description;
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$type = (string) $this->type;
|
||||
|
||||
return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function preg_split;
|
||||
use function array_key_exists;
|
||||
use function explode;
|
||||
|
||||
/**
|
||||
* Reflection class for a {@}uses tag in a Docblock.
|
||||
@@ -50,16 +52,27 @@ final class Uses extends BaseTag implements Factory\StaticMethod
|
||||
Assert::notNull($resolver);
|
||||
Assert::notNull($descriptionFactory);
|
||||
|
||||
$parts = preg_split('/\s+/Su', $body, 2);
|
||||
Assert::isArray($parts);
|
||||
Assert::allString($parts);
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
|
||||
return new static(
|
||||
$resolver->resolve($parts[0], $context),
|
||||
self::resolveFqsen($parts[0], $resolver, $context),
|
||||
$descriptionFactory->create($parts[1] ?? '', $context)
|
||||
);
|
||||
}
|
||||
|
||||
private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
|
||||
{
|
||||
Assert::notNull($fqsenResolver);
|
||||
$fqsenParts = explode('::', $parts);
|
||||
$resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
|
||||
|
||||
if (!array_key_exists(1, $fqsenParts)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
return new Fqsen($resolved . '::' . $fqsenParts[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the structural element this tag refers to.
|
||||
*/
|
||||
@@ -73,6 +86,14 @@ final class Uses extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->refers . ' ' . (string) $this->description;
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$refers = (string) $this->refers;
|
||||
|
||||
return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
@@ -57,8 +57,7 @@ final class Var_ extends TagWithType implements Factory\StaticMethod
|
||||
|
||||
[$firstPart, $body] = self::extractTypeFromBody($body);
|
||||
|
||||
$parts = preg_split('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
Assert::isArray($parts);
|
||||
$parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE);
|
||||
$type = null;
|
||||
$variableName = '';
|
||||
|
||||
@@ -70,10 +69,12 @@ final class Var_ extends TagWithType implements Factory\StaticMethod
|
||||
array_unshift($parts, $firstPart);
|
||||
}
|
||||
|
||||
// if the next item starts with a $ or ...$ it must be the variable name
|
||||
// if the next item starts with a $ it must be the variable name
|
||||
if (isset($parts[0]) && strpos($parts[0], '$') === 0) {
|
||||
$variableName = array_shift($parts);
|
||||
array_shift($parts);
|
||||
if ($type) {
|
||||
array_shift($parts);
|
||||
}
|
||||
|
||||
Assert::notNull($variableName);
|
||||
|
||||
@@ -98,8 +99,22 @@ final class Var_ extends TagWithType implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ($this->type ? $this->type . ' ' : '')
|
||||
. (empty($this->variableName) ? '' : '$' . $this->variableName)
|
||||
. ($this->description ? ' ' . $this->description : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
if ($this->variableName) {
|
||||
$variableName = '$' . $this->variableName;
|
||||
} else {
|
||||
$variableName = '';
|
||||
}
|
||||
|
||||
$type = (string) $this->type;
|
||||
|
||||
return $type
|
||||
. ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '')
|
||||
. ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,14 @@ final class Version extends BaseTag implements Factory\StaticMethod
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return ((string) $this->version) .
|
||||
($this->description instanceof Description ? ' ' . $this->description->render() : '');
|
||||
if ($this->description) {
|
||||
$description = $this->description->render();
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$version = (string) $this->version;
|
||||
|
||||
return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection\Exception;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use const PREG_BACKTRACK_LIMIT_ERROR;
|
||||
use const PREG_BAD_UTF8_ERROR;
|
||||
use const PREG_BAD_UTF8_OFFSET_ERROR;
|
||||
use const PREG_INTERNAL_ERROR;
|
||||
use const PREG_JIT_STACKLIMIT_ERROR;
|
||||
use const PREG_NO_ERROR;
|
||||
use const PREG_RECURSION_LIMIT_ERROR;
|
||||
|
||||
final class PcreException extends InvalidArgumentException
|
||||
{
|
||||
public static function createFromPhpError(int $errorCode) : self
|
||||
{
|
||||
switch ($errorCode) {
|
||||
case PREG_BACKTRACK_LIMIT_ERROR:
|
||||
return new self('Backtrack limit error');
|
||||
case PREG_RECURSION_LIMIT_ERROR:
|
||||
return new self('Recursion limit error');
|
||||
case PREG_BAD_UTF8_ERROR:
|
||||
return new self('Bad UTF8 error');
|
||||
case PREG_BAD_UTF8_OFFSET_ERROR:
|
||||
return new self('Bad UTF8 offset error');
|
||||
case PREG_JIT_STACKLIMIT_ERROR:
|
||||
return new self('Jit stacklimit error');
|
||||
case PREG_NO_ERROR:
|
||||
case PREG_INTERNAL_ERROR:
|
||||
default:
|
||||
}
|
||||
|
||||
return new self('Unknown Pcre error');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?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;
|
||||
|
||||
use phpDocumentor\Reflection\Exception\PcreException;
|
||||
use function preg_last_error;
|
||||
use function preg_split as php_preg_split;
|
||||
|
||||
abstract class Utils
|
||||
{
|
||||
/**
|
||||
* Wrapper function for phps preg_split
|
||||
*
|
||||
* This function is inspired by {@link https://github.com/thecodingmachine/safe/blob/master/generated/pcre.php}. But
|
||||
* since this library is all about performance we decided to strip everything we don't need. Reducing the amount
|
||||
* of files that have to be loaded, ect.
|
||||
*
|
||||
* @param string $pattern The pattern to search for, as a string.
|
||||
* @param string $subject The input string.
|
||||
* @param int|null $limit If specified, then only substrings up to limit are returned with the
|
||||
* rest of the string being placed in the last substring. A limit of -1 or 0 means "no limit".
|
||||
* @param int $flags flags can be any combination of the following flags (combined with the | bitwise operator):
|
||||
* *PREG_SPLIT_NO_EMPTY*
|
||||
* If this flag is set, only non-empty pieces will be returned by preg_split().
|
||||
* *PREG_SPLIT_DELIM_CAPTURE*
|
||||
* If this flag is set, parenthesized expression in the delimiter pattern will be captured
|
||||
* and returned as well.
|
||||
* *PREG_SPLIT_OFFSET_CAPTURE*
|
||||
* If this flag is set, for every occurring match the appendant string offset will also be returned.
|
||||
* Note that this changes the return value in an array where every element is an array consisting of the
|
||||
* matched string at offset 0 and its string offset into subject at offset 1.
|
||||
*
|
||||
* @return string[] Returns an array containing substrings of subject split along boundaries matched by pattern
|
||||
*
|
||||
* @throws PcreException
|
||||
*/
|
||||
public static function pregSplit(string $pattern, string $subject, ?int $limit = -1, int $flags = 0) : array
|
||||
{
|
||||
$parts = php_preg_split($pattern, $subject, $limit, $flags);
|
||||
if ($parts === false) {
|
||||
throw PcreException::createFromPhpError(preg_last_error());
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user