diff --git a/Annotations/AnnotationGenerator.php b/Annotations/AnnotationGenerator.php index f4e8f89..4e045e4 100644 --- a/Annotations/AnnotationGenerator.php +++ b/Annotations/AnnotationGenerator.php @@ -11,6 +11,9 @@ namespace Piwik\Plugins\OpenApiDocs\Annotations; +use Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\DocBlock\Tags\Param; +use Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\DocBlock\Tags\TagWithType; +use Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\DocBlockFactory; use Piwik\API\DocumentationGenerator; use Piwik\API\NoDefaultValue; use Piwik\API\Proxy; @@ -24,11 +27,6 @@ use Piwik\UrlHelper; use Piwik\Validators\BaseValidator; use Piwik\Validators\NotEmpty; -use PHPStan\PhpDocParser\Lexer\Lexer; -use PHPStan\PhpDocParser\Parser\PhpDocParser; -use PHPStan\PhpDocParser\Parser\TypeParser; -use PHPStan\PhpDocParser\Parser\ConstExprParser; -use PHPStan\PhpDocParser\Parser\TokenIterator; class AnnotationGenerator { @@ -282,21 +280,21 @@ protected function buildAnnotationForMethod(array $rules, string $pluginName, \R */ public function getParamInfoFromDocBlock(string $docBlock): array { - $lexer = new Lexer(); - $tokens = $lexer->tokenize($docBlock); - $expressionParser = new ConstExprParser(); - $parser = new PhpDocParser(new TypeParser($expressionParser), $expressionParser); - $node = $parser->parse(new TokenIterator($tokens)); + $factory = DocBlockFactory::createInstance(); + $docBlockObject = $factory->create($docBlock); $params = []; - foreach ($node->getParamTagValues() as $param) { - $name = ltrim($param->parameterName, '$'); + foreach ($docBlockObject->getTagsByName('param') as $param) { + if (!($param instanceof Param)) { + continue; + } + $name = ltrim($param->getVariableName(), '$'); $params[$name] = [ - 'type' => (string)$param->type, + 'type' => (string) $param->getType(), // Normalise the description. E.g. remove linebreaks and indentation - 'description' => trim(preg_replace(['/^\h+/m', '/\R+/u',], ['', ' '], $param->description)), - 'byRef' => $param->isReference, - 'variadic' => $param->isVariadic, + 'description' => trim(preg_replace(['/^\h+/m', '/\R+/u',], ['', ' '], (string) $param->getDescription())), + 'byRef' => $param->isReference(), + 'variadic' => $param->isVariadic(), ]; } return $params; @@ -313,27 +311,24 @@ public function getParamInfoFromDocBlock(string $docBlock): array */ public function getResponseInfoFromDocBlock(string $docBlock): array { - $lexer = new Lexer(); - $tokens = $lexer->tokenize($docBlock); - $expressionParser = new ConstExprParser(); - $parser = new PhpDocParser(new TypeParser($expressionParser), $expressionParser); - $node = $parser->parse(new TokenIterator($tokens)); + $factory = DocBlockFactory::createInstance(); + $docBlockObject = $factory->create($docBlock); $responseInfo = ['type' => null]; - $returnTags = $node->getReturnTagValues(); - if (empty($returnTags)) { + $returnTags = $docBlockObject->getTagsByName('return'); + if (empty($returnTags) || !($returnTags[0] instanceof TagWithType)) { return $responseInfo; } $returnTag = $returnTags[0]; - $tagValue = strval($returnTag->type); + $tagValue = strval($returnTag->getType()); $responseInfo['type'] = $this->getOpenApiTypeFromPhpType($tagValue); if ($responseInfo['type'] === 'string' && !empty($tagValue) && strtolower($tagValue) !== 'string') { $responseInfo['type'] = ''; $responseInfo['description'] = 'Response of unknown type'; } - if (!empty($returnTag->description)) { - $responseInfo['description'] = $returnTag->description; + if (!empty($returnTag->getDescription())) { + $responseInfo['description'] = $returnTag->getDescription(); } return $responseInfo; diff --git a/Commands/GenerateAnnotations.php b/Commands/GenerateAnnotations.php index 1c147df..d5faa45 100644 --- a/Commands/GenerateAnnotations.php +++ b/Commands/GenerateAnnotations.php @@ -72,11 +72,6 @@ protected function doExecute(): int $input = $this->getInput(); $output = $this->getOutput(); - if (!class_exists('PHPStan\PhpDocParser\Parser\PhpDocParser')) { - $output->writeln("This command requires phpstan/phpdoc-parser. It should be available while running Matomo in development mode."); - return self::FAILURE; - } - $plugin = $input->getOption('plugin'); if (empty($plugin)) { throw new \RuntimeException('Please specify a plugin name.'); diff --git a/composer.json b/composer.json index c36ed8c..bf84190 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,8 @@ { "require": { "zircote/swagger-php": "^5.4", - "doctrine/annotations": "^2.0" + "doctrine/annotations": "^2.0", + "phpdocumentor/reflection-docblock": "^5.6" }, "replace": { "monolog/monolog": "*", diff --git a/composer.lock b/composer.lock index 96d7444..bdaa0d8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c02410b41ab976b8400bb73dedbf07dc", + "content-hash": "453a28cb96a34b8b4d977dc6f929ec57", "packages": [ { "name": "doctrine/annotations", @@ -82,6 +82,54 @@ }, "time": "2024-09-05T10:17:24+00:00" }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, { "name": "doctrine/lexer", "version": "3.0.1", @@ -217,6 +265,228 @@ }, "time": "2025-08-13T20:13:15+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.6.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" + }, + "time": "2025-08-01T19:43:32+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + }, + "time": "2024-11-09T15:12:26+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" + }, + "time": "2025-08-30T15:50:23+00:00" + }, { "name": "psr/cache", "version": "3.0.0", @@ -560,6 +830,64 @@ ], "time": "2025-08-27T11:34:33+00:00" }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, { "name": "zircote/swagger-php", "version": "5.4.0", diff --git a/phpstan-bootstrap.php b/phpstan-bootstrap.php new file mode 100644 index 0000000..bdf349e --- /dev/null +++ b/phpstan-bootstrap.php @@ -0,0 +1,4 @@ + 'array', + 'description' => 'Some test description for the return annotation.', ]; $this->assertEquals($expected, $this->annotationGenerator->getResponseInfoFromDocBlock(self::EXAMPLE_API_METHOD_DOC_BLOCK1)); } diff --git a/vendor/autoload_original.php b/vendor/autoload_original.php index 8349aed..1baee05 100644 --- a/vendor/autoload_original.php +++ b/vendor/autoload_original.php @@ -22,4 +22,4 @@ require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInitc02410b41ab976b8400bb73dedbf07dc::getLoader(); +return ComposerAutoloaderInit1e9ddc6b3f094bbece3e6bb946077640::getLoader(); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 6050e83..c16cefd 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -6,12 +6,16 @@ $baseDir = dirname($vendorDir); return array( + 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), + 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), + 'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'), 'OpenApi\\' => array($vendorDir . '/zircote/swagger-php/src'), + 'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'), 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/src'), 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index b6f351c..91515b8 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitc02410b41ab976b8400bb73dedbf07dc +class ComposerAutoloaderInit1e9ddc6b3f094bbece3e6bb946077640 { private static $loader; @@ -22,16 +22,16 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitc02410b41ab976b8400bb73dedbf07dc', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit1e9ddc6b3f094bbece3e6bb946077640', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInitc02410b41ab976b8400bb73dedbf07dc', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit1e9ddc6b3f094bbece3e6bb946077640', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit1e9ddc6b3f094bbece3e6bb946077640::getInitializer($loader)); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticInit1e9ddc6b3f094bbece3e6bb946077640::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 66659ed..5081b9f 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,13 +4,21 @@ namespace Composer\Autoload; -class ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc +class ComposerStaticInit1e9ddc6b3f094bbece3e6bb946077640 { public static $files = array( ); public static $prefixLengthsPsr4 = array ( + 'p' => + array ( + 'phpDocumentor\\Reflection\\' => 25, + ), + 'W' => + array ( + 'Webmozart\\Assert\\' => 17, + ), 'S' => array ( 'Symfony\\Polyfill\\Ctype\\' => 23, @@ -21,6 +29,7 @@ class ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc array ( 'Psr\\Cache\\' => 10, 'PhpParser\\' => 10, + 'PHPStan\\PhpDocParser\\' => 21, ), 'O' => array ( @@ -28,12 +37,23 @@ class ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc ), 'D' => array ( + 'Doctrine\\Deprecations\\' => 22, 'Doctrine\\Common\\Lexer\\' => 22, 'Doctrine\\Common\\Annotations\\' => 28, ), ); public static $prefixDirsPsr4 = array ( + 'phpDocumentor\\Reflection\\' => + array ( + 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', + 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', + 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', + ), + 'Webmozart\\Assert\\' => + array ( + 0 => __DIR__ . '/..' . '/webmozart/assert/src', + ), 'Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', @@ -54,10 +74,18 @@ class ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc array ( 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', ), + 'PHPStan\\PhpDocParser\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src', + ), 'OpenApi\\' => array ( 0 => __DIR__ . '/..' . '/zircote/swagger-php/src', ), + 'Doctrine\\Deprecations\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/deprecations/src', + ), 'Doctrine\\Common\\Lexer\\' => array ( 0 => __DIR__ . '/..' . '/doctrine/lexer/src', @@ -75,9 +103,9 @@ class ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInitc02410b41ab976b8400bb73dedbf07dc::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInit1e9ddc6b3f094bbece3e6bb946077640::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit1e9ddc6b3f094bbece3e6bb946077640::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit1e9ddc6b3f094bbece3e6bb946077640::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 3575ed6..acf0d66 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -79,6 +79,57 @@ }, "install-path": "../doctrine/annotations" }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "version_normalized": "1.1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "time": "2025-04-07T20:06:18+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "install-path": "../doctrine/deprecations" + }, { "name": "doctrine/lexer", "version": "3.0.1", @@ -220,6 +271,240 @@ }, "install-path": "../nikic/php-parser" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "version_normalized": "2.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2020-06-27T09:03:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "install-path": "../phpdocumentor/reflection-common" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.6.3", + "version_normalized": "5.6.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" + }, + "time": "2025-08-01T19:43:32+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" + }, + "install-path": "../phpdocumentor/reflection-docblock" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.10.0", + "version_normalized": "1.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "time": "2024-11-09T15:12:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + }, + "install-path": "../phpdocumentor/type-resolver" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.3.0", + "version_normalized": "2.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "time": "2025-08-30T15:50:23+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" + }, + "install-path": "../phpstan/phpdoc-parser" + }, { "name": "psr/cache", "version": "3.0.0", @@ -578,6 +863,67 @@ ], "install-path": "../symfony/yaml" }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "version_normalized": "1.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "time": "2022-06-03T18:03:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "install-path": "../webmozart/assert" + }, { "name": "zircote/swagger-php", "version": "5.4.0", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 08b6452..a4447cc 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-5.x-dev', 'version' => 'dev-5.x-dev', - 'reference' => '7773ba7c581833d8cfe2eb522cb7516d132720af', + 'reference' => 'b5ecf24dbc489a212c869ea6953193928bdb8d36', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,7 +13,7 @@ '__root__' => array( 'pretty_version' => 'dev-5.x-dev', 'version' => 'dev-5.x-dev', - 'reference' => '7773ba7c581833d8cfe2eb522cb7516d132720af', + 'reference' => 'b5ecf24dbc489a212c869ea6953193928bdb8d36', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -28,6 +28,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'doctrine/deprecations' => array( + 'pretty_version' => '1.1.5', + 'version' => '1.1.5.0', + 'reference' => '459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/deprecations', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'doctrine/lexer' => array( 'pretty_version' => '3.0.1', 'version' => '3.0.1.0', @@ -52,6 +61,42 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'phpdocumentor/reflection-common' => array( + 'pretty_version' => '2.2.0', + 'version' => '2.2.0.0', + 'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/reflection-common', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpdocumentor/reflection-docblock' => array( + 'pretty_version' => '5.6.3', + 'version' => '5.6.3.0', + 'reference' => '94f8051919d1b0369a6bcc7931d679a511c03fe9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpdocumentor/type-resolver' => array( + 'pretty_version' => '1.10.0', + 'version' => '1.10.0.0', + 'reference' => '679e3ce485b99e84c775d28e2e96fade9a7fb50a', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/type-resolver', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpstan/phpdoc-parser' => array( + 'pretty_version' => '2.3.0', + 'version' => '2.3.0.0', + 'reference' => '1e0cd5370df5dd2e556a36b9c62f62e555870495', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'psr/cache' => array( 'pretty_version' => '3.0.0', 'version' => '3.0.0.0', @@ -103,6 +148,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'webmozart/assert' => array( + 'pretty_version' => '1.11.0', + 'version' => '1.11.0.0', + 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', + 'type' => 'library', + 'install_path' => __DIR__ . '/../webmozart/assert', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'zircote/swagger-php' => array( 'pretty_version' => '5.4.0', 'version' => '5.4.0.0', diff --git a/vendor/prefixed/doctrine/deprecations/LICENSE b/vendor/prefixed/doctrine/deprecations/LICENSE new file mode 100644 index 0000000..156905c --- /dev/null +++ b/vendor/prefixed/doctrine/deprecations/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-2021 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/prefixed/doctrine/deprecations/src/Deprecation.php b/vendor/prefixed/doctrine/deprecations/src/Deprecation.php new file mode 100644 index 0000000..2402264 --- /dev/null +++ b/vendor/prefixed/doctrine/deprecations/src/Deprecation.php @@ -0,0 +1,241 @@ +|null */ + private static $type; + /** @var LoggerInterface|null */ + private static $logger; + /** @var array */ + private static $ignoredPackages = []; + /** @var array */ + private static $triggeredDeprecations = []; + /** @var array */ + private static $ignoredLinks = []; + /** @var bool */ + private static $deduplication = \true; + /** + * Trigger a deprecation for the given package and identfier. + * + * The link should point to a Github issue or Wiki entry detailing the + * deprecation. It is additionally used to de-duplicate the trigger of the + * same deprecation during a request. + * + * @param float|int|string $args + */ + public static function trigger(string $package, string $link, string $message, ...$args) : void + { + $type = self::$type ?? self::getTypeFromEnv(); + if ($type === self::TYPE_NONE) { + return; + } + if (isset(self::$ignoredLinks[$link])) { + return; + } + if (array_key_exists($link, self::$triggeredDeprecations)) { + self::$triggeredDeprecations[$link]++; + } else { + self::$triggeredDeprecations[$link] = 1; + } + if (self::$deduplication === \true && self::$triggeredDeprecations[$link] > 1) { + return; + } + if (isset(self::$ignoredPackages[$package])) { + return; + } + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + $message = sprintf($message, ...$args); + self::delegateTriggerToBackend($message, $backtrace, $link, $package); + } + /** + * Trigger a deprecation for the given package and identifier when called from outside. + * + * "Outside" means we assume that $package is currently installed as a + * dependency and the caller is not a file in that package. When $package + * is installed as a root package then deprecations triggered from the + * tests folder are also considered "outside". + * + * This deprecation method assumes that you are using Composer to install + * the dependency and are using the default /vendor/ folder and not a + * Composer plugin to change the install location. The assumption is also + * that $package is the exact composer packge name. + * + * Compared to {@link trigger()} this method causes some overhead when + * deprecation tracking is enabled even during deduplication, because it + * needs to call {@link debug_backtrace()} + * + * @param float|int|string $args + */ + public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args) : void + { + $type = self::$type ?? self::getTypeFromEnv(); + if ($type === self::TYPE_NONE) { + return; + } + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + // first check that the caller is not from a tests folder, in which case we always let deprecations pass + if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === \false) { + $path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $package) . DIRECTORY_SEPARATOR; + if (strpos($backtrace[0]['file'], $path) === \false) { + return; + } + if (strpos($backtrace[1]['file'], $path) !== \false) { + return; + } + } + if (isset(self::$ignoredLinks[$link])) { + return; + } + if (array_key_exists($link, self::$triggeredDeprecations)) { + self::$triggeredDeprecations[$link]++; + } else { + self::$triggeredDeprecations[$link] = 1; + } + if (self::$deduplication === \true && self::$triggeredDeprecations[$link] > 1) { + return; + } + if (isset(self::$ignoredPackages[$package])) { + return; + } + $message = sprintf($message, ...$args); + self::delegateTriggerToBackend($message, $backtrace, $link, $package); + } + /** @param list $backtrace */ + private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package) : void + { + $type = self::$type ?? self::getTypeFromEnv(); + if (($type & self::TYPE_PSR_LOGGER) > 0) { + $context = ['file' => $backtrace[0]['file'] ?? null, 'line' => $backtrace[0]['line'] ?? null, 'package' => $package, 'link' => $link]; + assert(self::$logger !== null); + self::$logger->notice($message, $context); + } + if (!(($type & self::TYPE_TRIGGER_ERROR) > 0)) { + return; + } + $message .= sprintf(' (%s:%d called by %s:%d, %s, package %s)', self::basename($backtrace[0]['file'] ?? 'native code'), $backtrace[0]['line'] ?? 0, self::basename($backtrace[1]['file'] ?? 'native code'), $backtrace[1]['line'] ?? 0, $link, $package); + @trigger_error($message, E_USER_DEPRECATED); + } + /** + * A non-local-aware version of PHPs basename function. + */ + private static function basename(string $filename) : string + { + $pos = strrpos($filename, DIRECTORY_SEPARATOR); + if ($pos === \false) { + return $filename; + } + return substr($filename, $pos + 1); + } + public static function enableTrackingDeprecations() : void + { + self::$type = self::$type ?? self::getTypeFromEnv(); + self::$type |= self::TYPE_TRACK_DEPRECATIONS; + } + public static function enableWithTriggerError() : void + { + self::$type = self::$type ?? self::getTypeFromEnv(); + self::$type |= self::TYPE_TRIGGER_ERROR; + } + public static function enableWithPsrLogger(LoggerInterface $logger) : void + { + self::$type = self::$type ?? self::getTypeFromEnv(); + self::$type |= self::TYPE_PSR_LOGGER; + self::$logger = $logger; + } + public static function withoutDeduplication() : void + { + self::$deduplication = \false; + } + public static function disable() : void + { + self::$type = self::TYPE_NONE; + self::$logger = null; + self::$deduplication = \true; + self::$ignoredLinks = []; + foreach (self::$triggeredDeprecations as $link => $count) { + self::$triggeredDeprecations[$link] = 0; + } + } + public static function ignorePackage(string $packageName) : void + { + self::$ignoredPackages[$packageName] = \true; + } + public static function ignoreDeprecations(string ...$links) : void + { + foreach ($links as $link) { + self::$ignoredLinks[$link] = \true; + } + } + public static function getUniqueTriggeredDeprecationsCount() : int + { + return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) { + return $carry + $count; + }, 0); + } + /** + * Returns each triggered deprecation link identifier and the amount of occurrences. + * + * @return array + */ + public static function getTriggeredDeprecations() : array + { + return self::$triggeredDeprecations; + } + /** @return int-mask-of */ + private static function getTypeFromEnv() : int + { + switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) { + case 'trigger': + self::$type = self::TYPE_TRIGGER_ERROR; + break; + case 'track': + self::$type = self::TYPE_TRACK_DEPRECATIONS; + break; + default: + self::$type = self::TYPE_NONE; + break; + } + return self::$type; + } +} diff --git a/vendor/prefixed/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php b/vendor/prefixed/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php new file mode 100644 index 0000000..4ae78f3 --- /dev/null +++ b/vendor/prefixed/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php @@ -0,0 +1,43 @@ + */ + private $doctrineDeprecationsExpectations = []; + /** @var array */ + private $doctrineNoDeprecationsExpectations = []; + public function expectDeprecationWithIdentifier(string $identifier) : void + { + $this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + } + public function expectNoDeprecationWithIdentifier(string $identifier) : void + { + $this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + } + /** @before */ + #[Before] + public function enableDeprecationTracking() : void + { + Deprecation::enableTrackingDeprecations(); + } + /** @after */ + #[After] + public function verifyDeprecationsAreTriggered() : void + { + foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) { + $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + $this->assertTrue($actualCount > $expectation, sprintf("Expected deprecation with identifier '%s' was not triggered by code executed in test.", $identifier)); + } + foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) { + $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + $this->assertTrue($actualCount === $expectation, sprintf("Expected deprecation with identifier '%s' was triggered by code executed in test, but expected not to.", $identifier)); + } + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-common/LICENSE b/vendor/prefixed/phpdocumentor/reflection-common/LICENSE new file mode 100644 index 0000000..ed6926c --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-common/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 phpDocumentor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/prefixed/phpdocumentor/reflection-common/src/Element.php b/vendor/prefixed/phpdocumentor/reflection-common/src/Element.php new file mode 100644 index 0000000..d97d473 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-common/src/Element.php @@ -0,0 +1,27 @@ +fqsen = $fqsen; + if (isset($matches[2])) { + $this->name = $matches[2]; + } else { + $matches = explode('\\', $fqsen); + $name = end($matches); + assert(is_string($name)); + $this->name = trim($name, '()'); + } + } + /** + * converts this class to string. + */ + public function __toString() : string + { + return $this->fqsen; + } + /** + * Returns the name of the element without path. + */ + public function getName() : string + { + return $this->name; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-common/src/Location.php b/vendor/prefixed/phpdocumentor/reflection-common/src/Location.php new file mode 100644 index 0000000..6e43386 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-common/src/Location.php @@ -0,0 +1,47 @@ +lineNumber = $lineNumber; + $this->columnNumber = $columnNumber; + } + /** + * Returns the line number that is covered by this location. + */ + public function getLineNumber() : int + { + return $this->lineNumber; + } + /** + * Returns the column number (character position on a line) for this location object. + */ + public function getColumnNumber() : int + { + return $this->columnNumber; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-common/src/Project.php b/vendor/prefixed/phpdocumentor/reflection-common/src/Project.php new file mode 100644 index 0000000..c3e8aa7 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-common/src/Project.php @@ -0,0 +1,23 @@ +summary = $summary; + $this->description = $description ?: new DocBlock\Description(''); + foreach ($tags as $tag) { + $this->addTag($tag); + } + $this->context = $context; + $this->location = $location; + $this->isTemplateEnd = $isTemplateEnd; + $this->isTemplateStart = $isTemplateStart; + } + public function getSummary() : string + { + return $this->summary; + } + public function getDescription() : DocBlock\Description + { + return $this->description; + } + /** + * Returns the current context. + */ + public function getContext() : ?Types\Context + { + return $this->context; + } + /** + * Returns the current location. + */ + public function getLocation() : ?Location + { + return $this->location; + } + /** + * Returns whether this DocBlock is the start of a Template section. + * + * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker + * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. + * + * An example of such an opening is: + * + * ``` + * /**#@+ + * * My DocBlock + * * / + * ``` + * + * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all + * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). + * + * @see self::isTemplateEnd() for the check whether a closing marker was provided. + */ + public function isTemplateStart() : bool + { + return $this->isTemplateStart; + } + /** + * Returns whether this DocBlock is the end of a Template section. + * + * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. + */ + public function isTemplateEnd() : bool + { + return $this->isTemplateEnd; + } + /** + * Returns the tags for this DocBlock. + * + * @return Tag[] + */ + public function getTags() : array + { + return $this->tags; + } + /** + * Returns an array of tags matching the given name. If no tags are found + * an empty array is returned. + * + * @param string $name String to search by. + * + * @return Tag[] + */ + public function getTagsByName(string $name) : array + { + $result = []; + foreach ($this->getTags() as $tag) { + if ($tag->getName() !== $name) { + continue; + } + $result[] = $tag; + } + return $result; + } + /** + * Returns an array of tags with type matching the given name. If no tags are found + * an empty array is returned. + * + * @param string $name String to search by. + * + * @return TagWithType[] + */ + public function getTagsWithTypeByName(string $name) : array + { + $result = []; + foreach ($this->getTagsByName($name) as $tag) { + if (!$tag instanceof TagWithType) { + continue; + } + $result[] = $tag; + } + return $result; + } + /** + * Checks if a tag of a certain type is present in this DocBlock. + * + * @param string $name Tag name to check for. + */ + public function hasTag(string $name) : bool + { + foreach ($this->getTags() as $tag) { + if ($tag->getName() === $name) { + return \true; + } + } + return \false; + } + /** + * Remove a tag from this DocBlock. + * + * @param Tag $tagToRemove The tag to remove. + */ + public function removeTag(Tag $tagToRemove) : void + { + foreach ($this->tags as $key => $tag) { + if ($tag === $tagToRemove) { + unset($this->tags[$key]); + break; + } + } + } + /** + * Adds a tag to this DocBlock. + * + * @param Tag $tag The tag to add. + */ + private function addTag(Tag $tag) : void + { + $this->tags[] = $tag; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Description.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Description.php new file mode 100644 index 0000000..dc2721d --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Description.php @@ -0,0 +1,108 @@ +create('This is a {@see Description}', $context); + * + * The description factory will interpret the given body and create a body template and list of tags from them, and pass + * that onto the constructor if this class. + * + * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace + * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial + * > type names and FQSENs. + * + * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this: + * + * $description = new Description( + * 'This is a %1$s', + * [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ] + * ); + * + * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object + * is mainly responsible for rendering. + * + * @see DescriptionFactory to create a new Description. + * @see Tags\Formatter for the formatting of the body and tags. + */ +class Description +{ + /** + * @var string + */ + private $bodyTemplate; + /** @var Tag[] */ + private $tags; + /** + * Initializes a Description with its body (template) and a listing of the tags used in the body template. + * + * @param Tag[] $tags + */ + public function __construct(string $bodyTemplate, array $tags = []) + { + $this->bodyTemplate = $bodyTemplate; + $this->tags = $tags; + } + /** + * Returns the body template. + */ + public function getBodyTemplate() : string + { + return $this->bodyTemplate; + } + /** + * Returns the tags for this DocBlock. + * + * @return Tag[] + */ + public function getTags() : array + { + return $this->tags; + } + /** + * Renders this description as a string where the provided formatter will format the tags in the expected string + * format. + */ + public function render(?Formatter $formatter = null) : string + { + if ($this->tags === []) { + return vsprintf($this->bodyTemplate, []); + } + if ($formatter === null) { + $formatter = new PassthroughFormatter(); + } + $tags = []; + foreach ($this->tags as $tag) { + $tags[] = '{' . $formatter->format($tag) . '}'; + } + return vsprintf($this->bodyTemplate, $tags); + } + /** + * Returns a plain string representation of this description. + */ + public function __toString() : string + { + return $this->render(); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php new file mode 100644 index 0000000..fc7dd64 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php @@ -0,0 +1,157 @@ +tagFactory = $tagFactory; + } + /** + * Returns the parsed text of this description. + */ + public function create(string $contents, ?TypeContext $context = null) : Description + { + $tokens = $this->lex($contents); + $count = count($tokens); + $tagCount = 0; + $tags = []; + for ($i = 1; $i < $count; $i += 2) { + $tags[] = $this->tagFactory->create($tokens[$i], $context); + $tokens[$i] = '%' . ++$tagCount . '$s'; + } + //In order to allow "literal" inline tags, the otherwise invalid + //sequence "{@}" is changed to "@", and "{}" is changed to "}". + //"%" is escaped to "%%" because of vsprintf. + //See unit tests for examples. + for ($i = 0; $i < $count; $i += 2) { + $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); + } + return new Description(implode('', $tokens), $tags); + } + /** + * Strips the contents from superfluous whitespace and splits the description into a series of tokens. + * + * @return string[] A series of tokens of which the description text is composed. + */ + private function lex(string $contents) : array + { + $contents = $this->removeSuperfluousStartingWhitespace($contents); + // performance optimalization; if there is no inline tag, don't bother splitting it up. + if (strpos($contents, '{@') === \false) { + return [$contents]; + } + return Utils::pregSplit('/\\{ + # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally. + (?!@\\}) + # We want to capture the whole tag line, but without the inline tag delimiters. + (\\@ + # Match everything up to the next delimiter. + [^{}]* + # Nested inline tag content should not be captured, or it will appear in the result separately. + (?: + # Match nested inline tags. + (?: + # Because we did not catch the tag delimiters earlier, we must be explicit with them here. + # Notice that this also matches "{}", as a way to later introduce it as an escape sequence. + \\{(?1)?\\} + | + # Make sure we match hanging "{". + \\{ + ) + # Match content after the nested inline tag. + [^{}]* + )* # If there are more inline tags, match them as well. We use "*" since there may not be any + # nested inline tags. + ) + \\}/Sux', $contents, 0, PREG_SPLIT_DELIM_CAPTURE); + } + /** + * Removes the superfluous from a multi-line description. + * + * When a description has more than one line then it can happen that the second and subsequent lines have an + * additional indentation. This is commonly in use with tags like this: + * + * {@}since 1.1.0 This is an example + * description where we have an + * indentation in the second and + * subsequent lines. + * + * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent + * lines and this may cause rendering issues when, for example, using a Markdown converter. + */ + private function removeSuperfluousStartingWhitespace(string $contents) : string + { + $lines = Utils::pregSplit("/\r\n?|\n/", $contents); + // if there is only one line then we don't have lines with superfluous whitespace and + // can use the contents as-is + if (count($lines) <= 1) { + return $contents; + } + // determine how many whitespace characters need to be stripped + $startingSpaceCount = 9999999; + for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) { + // lines with a no length do not count as they are not indented at all + if (trim($lines[$i]) === '') { + continue; + } + // determine the number of prefixing spaces by checking the difference in line length before and after + // an ltrim + $startingSpaceCount = min($startingSpaceCount, strlen($lines[$i]) - strlen(ltrim($lines[$i]))); + } + // strip the number of spaces from each line + if ($startingSpaceCount > 0) { + for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) { + $lines[$i] = substr($lines[$i], $startingSpaceCount); + } + } + return implode("\n", $lines); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php new file mode 100644 index 0000000..18605a3 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php @@ -0,0 +1,135 @@ +getFilePath(); + $file = $this->getExampleFileContents($filename); + if ($file === null) { + return sprintf('** File not found : %s **', $filename); + } + return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount())); + } + /** + * Registers the project's root directory where an 'examples' folder can be expected. + */ + public function setSourceDirectory(string $directory = '') : void + { + $this->sourceDirectory = $directory; + } + /** + * Returns the project's root directory where an 'examples' folder can be expected. + */ + public function getSourceDirectory() : string + { + return $this->sourceDirectory; + } + /** + * Registers a series of directories that may contain examples. + * + * @param string[] $directories + */ + public function setExampleDirectories(array $directories) : void + { + $this->exampleDirectories = $directories; + } + /** + * Returns a series of directories that may contain examples. + * + * @return string[] + */ + public function getExampleDirectories() : array + { + return $this->exampleDirectories; + } + /** + * Attempts to find the requested example file and returns its contents or null if no file was found. + * + * This method will try several methods in search of the given example file, the first one it encounters is + * returned: + * + * 1. Iterates through all examples folders for the given filename + * 2. Checks the source folder for the given filename + * 3. Checks the 'examples' folder in the current working directory for examples + * 4. Checks the path relative to the current working directory for the given filename + * + * @return string[] all lines of the example file + */ + private function getExampleFileContents(string $filename) : ?array + { + $normalizedPath = null; + foreach ($this->exampleDirectories as $directory) { + $exampleFileFromConfig = $this->constructExamplePath($directory, $filename); + if (is_readable($exampleFileFromConfig)) { + $normalizedPath = $exampleFileFromConfig; + break; + } + } + if ($normalizedPath === null) { + if (is_readable($this->getExamplePathFromSource($filename))) { + $normalizedPath = $this->getExamplePathFromSource($filename); + } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) { + $normalizedPath = $this->getExamplePathFromExampleDirectory($filename); + } elseif (is_readable($filename)) { + $normalizedPath = $filename; + } + } + $lines = $normalizedPath !== null && is_readable($normalizedPath) ? file($normalizedPath) : \false; + return $lines !== \false ? $lines : null; + } + /** + * Get example filepath based on the example directory inside your project. + */ + private function getExamplePathFromExampleDirectory(string $file) : string + { + return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file; + } + /** + * Returns a path to the example file in the given directory.. + */ + private function constructExamplePath(string $directory, string $file) : string + { + return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file; + } + /** + * Get example filepath based on sourcecode. + */ + private function getExamplePathFromSource(string $file) : string + { + return sprintf('%s%s%s', trim($this->getSourceDirectory(), '\\/'), DIRECTORY_SEPARATOR, trim($file, '"')); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php new file mode 100644 index 0000000..40d2990 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php @@ -0,0 +1,111 @@ +indent = $indent; + $this->indentString = $indentString; + $this->isFirstLineIndented = $indentFirstLine; + $this->lineLength = $lineLength; + $this->tagFormatter = $tagFormatter ?: new PassthroughFormatter(); + $this->lineEnding = $lineEnding; + } + /** + * Generate a DocBlock comment. + * + * @param DocBlock $docblock The DocBlock to serialize. + * + * @return string The serialized doc block. + */ + public function getDocComment(DocBlock $docblock) : string + { + $indent = str_repeat($this->indentString, $this->indent); + $firstIndent = $this->isFirstLineIndented ? $indent : ''; + // 3 === strlen(' * ') + $wrapLength = $this->lineLength !== null ? $this->lineLength - strlen($indent) - 3 : null; + $text = $this->removeTrailingSpaces($indent, $this->addAsterisksForEachLine($indent, $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength))); + $comment = $firstIndent . "/**\n"; + if ($text) { + $comment .= $indent . ' * ' . $text . "\n"; + $comment .= $indent . " *\n"; + } + $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment); + return str_replace("\n", $this->lineEnding, $comment . $indent . ' */'); + } + private function removeTrailingSpaces(string $indent, string $text) : string + { + return str_replace(sprintf("\n%s * \n", $indent), sprintf("\n%s *\n", $indent), $text); + } + private function addAsterisksForEachLine(string $indent, string $text) : string + { + return str_replace("\n", sprintf("\n%s * ", $indent), $text); + } + private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, ?int $wrapLength) : string + { + $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() : ''); + if ($wrapLength !== null) { + $text = wordwrap($text, $wrapLength); + return $text; + } + return $text; + } + private function addTagBlock(DocBlock $docblock, ?int $wrapLength, string $indent, string $comment) : string + { + foreach ($docblock->getTags() as $tag) { + $tagText = $this->tagFormatter->format($tag); + if ($wrapLength !== null) { + $tagText = wordwrap($tagText, $wrapLength); + } + $tagText = str_replace("\n", sprintf("\n%s * ", $indent), $tagText); + $comment .= sprintf("%s * %s\n", $indent, $tagText); + } + return $comment; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php new file mode 100644 index 0000000..f2cd41a --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php @@ -0,0 +1,310 @@ + Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise + * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to + * > verify that a dependency is actually passed. + * + * This Factory also features a Service Locator component that is used to pass the right dependencies to the + * `create` method of a tag; each dependency should be registered as a service or as a parameter. + * + * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass + * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface. + */ +final class StandardTagFactory implements TagFactory +{ + /** PCRE regular expression matching a tag name. */ + public const REGEX_TAGNAME = '[\\w\\-\\_\\\\:]+'; + /** + * @var array|Factory> An array with a tag as a key, and an + * FQCN to a class that handles it as an array value. + */ + private $tagHandlerMappings = [ + 'author' => Author::class, + 'covers' => Covers::class, + 'deprecated' => Deprecated::class, + // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example', + 'link' => LinkTag::class, + 'mixin' => Mixin::class, + 'method' => Method::class, + 'param' => Param::class, + 'property-read' => PropertyRead::class, + 'property' => Property::class, + 'property-write' => PropertyWrite::class, + 'return' => Return_::class, + 'see' => SeeTag::class, + 'since' => Since::class, + 'source' => Source::class, + 'template-covariant' => TemplateCovariant::class, + 'throw' => Throws::class, + 'throws' => Throws::class, + 'uses' => Uses::class, + 'var' => Var_::class, + 'version' => Version::class, + ]; + /** + * @var array> An array with an annotation as a key, and an + * FQCN to a class that handles it as an array value. + */ + private $annotationMappings = []; + /** + * @var ReflectionParameter[][] a lazy-loading cache containing parameters + * for each tagHandler that has been used. + */ + private $tagHandlerParameterCache = []; + /** + * @var \Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\FqsenResolver + */ + private $fqsenResolver; + /** + * @var mixed[] an array representing a simple Service Locator where we can store parameters and + * services that can be inserted into the Factory Methods of Tag Handlers. + */ + private $serviceLocator = []; + /** + * Initialize this tag factory with the means to resolve an FQSEN and optionally a list of tag handlers. + * + * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property + * is used. + * + * @see self::registerTagHandler() to add a new tag handler to the existing default list. + * + * @param array> $tagHandlers + */ + public function __construct(FqsenResolver $fqsenResolver, ?array $tagHandlers = null) + { + $this->fqsenResolver = $fqsenResolver; + if ($tagHandlers !== null) { + $this->tagHandlerMappings = $tagHandlers; + } + $this->addService($fqsenResolver, FqsenResolver::class); + } + public function create(string $tagLine, ?TypeContext $context = null) : Tag + { + if (!$context) { + $context = new TypeContext(''); + } + [$tagName, $tagBody] = $this->extractTagParts($tagLine); + return $this->createTag(trim($tagBody), $tagName, $context); + } + /** + * @param mixed $value + */ + public function addParameter(string $name, $value) : void + { + $this->serviceLocator[$name] = $value; + } + public function addService(object $service, ?string $alias = null) : void + { + $this->serviceLocator[$alias ?? get_class($service)] = $service; + } + /** {@inheritDoc} */ + public function registerTagHandler(string $tagName, $handler) : void + { + Assert::stringNotEmpty($tagName); + if (strpos($tagName, '\\') !== \false && $tagName[0] !== '\\') { + throw new InvalidArgumentException('A namespaced tag must have a leading backslash as it must be fully qualified'); + } + if (is_object($handler)) { + Assert::isInstanceOf($handler, Factory::class); + $this->tagHandlerMappings[$tagName] = $handler; + return; + } + Assert::classExists($handler); + Assert::implementsInterface($handler, Tag::class); + $this->tagHandlerMappings[$tagName] = $handler; + } + /** + * Extracts all components for a tag. + * + * @return string[] + */ + private function extractTagParts(string $tagLine) : array + { + $matches = []; + if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\\s\\(\\{])\\s*([^\\s].*)|$)/us', $tagLine, $matches)) { + throw new InvalidArgumentException('The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors'); + } + return array_slice($matches, 1); + } + /** + * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the + * body was invalid. + */ + private function createTag(string $body, string $name, TypeContext $context) : Tag + { + $handlerClassName = $this->findHandlerClassName($name, $context); + $arguments = $this->getArgumentsForParametersFromWiring($this->fetchParametersForHandlerFactoryMethod($handlerClassName), $this->getServiceLocatorWithDynamicParameters($context, $name, $body)); + if (array_key_exists('tagLine', $arguments)) { + $arguments['tagLine'] = sprintf('@%s %s', $name, $body); + } + try { + $callable = [$handlerClassName, 'create']; + Assert::isCallable($callable); + /** @phpstan-var callable(string): ?Tag $callable */ + $tag = call_user_func_array($callable, $arguments); + return $tag ?? InvalidTag::create($body, $name); + } catch (InvalidArgumentException $e) { + return InvalidTag::create($body, $name)->withError($e); + } + } + /** + * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). + * + * @return class-string|Factory + */ + private function findHandlerClassName(string $tagName, TypeContext $context) + { + $handlerClassName = Generic::class; + if (isset($this->tagHandlerMappings[$tagName])) { + $handlerClassName = $this->tagHandlerMappings[$tagName]; + } elseif ($this->isAnnotation($tagName)) { + // TODO: Annotation support is planned for a later stage and as such is disabled for now + $tagName = (string) $this->fqsenResolver->resolve($tagName, $context); + if (isset($this->annotationMappings[$tagName])) { + $handlerClassName = $this->annotationMappings[$tagName]; + } + } + return $handlerClassName; + } + /** + * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters. + * + * @param ReflectionParameter[] $parameters + * @param mixed[] $locator + * + * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters + * is provided with this method. + */ + private function getArgumentsForParametersFromWiring(array $parameters, array $locator) : array + { + $arguments = []; + foreach ($parameters as $parameter) { + $type = $parameter->getType(); + $typeHint = null; + if ($type instanceof ReflectionNamedType) { + $typeHint = $type->getName(); + if ($typeHint === 'self') { + $declaringClass = $parameter->getDeclaringClass(); + if ($declaringClass !== null) { + $typeHint = $declaringClass->getName(); + } + } + } + $parameterName = $parameter->getName(); + if (isset($locator[$typeHint])) { + $arguments[$parameterName] = $locator[$typeHint]; + continue; + } + if (isset($locator[$parameterName])) { + $arguments[$parameterName] = $locator[$parameterName]; + continue; + } + $arguments[$parameterName] = null; + } + return $arguments; + } + /** + * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given + * tag handler class name. + * + * @param class-string|Factory $handler + * + * @return ReflectionParameter[] + */ + private function fetchParametersForHandlerFactoryMethod($handler) : array + { + $handlerClassName = is_object($handler) ? get_class($handler) : $handler; + if (!isset($this->tagHandlerParameterCache[$handlerClassName])) { + $methodReflection = new ReflectionMethod($handlerClassName, 'create'); + $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters(); + } + return $this->tagHandlerParameterCache[$handlerClassName]; + } + /** + * Returns a copy of this class' Service Locator with added dynamic parameters, + * such as the tag's name, body and Context. + * + * @param TypeContext $context The Context (namespace and aliases) that may be + * passed and is used to resolve FQSENs. + * @param string $tagName The name of the tag that may be + * passed onto the factory method of the Tag class. + * @param string $tagBody The body of the tag that may be + * passed onto the factory method of the Tag class. + * + * @return mixed[] + */ + private function getServiceLocatorWithDynamicParameters(TypeContext $context, string $tagName, string $tagBody) : array + { + return array_merge($this->serviceLocator, ['name' => $tagName, 'body' => $tagBody, TypeContext::class => $context]); + } + /** + * Returns whether the given tag belongs to an annotation. + * + * @todo this method should be populated once we implement Annotation notation support. + */ + private function isAnnotation(string $tagContent) : bool + { + // 1. Contains a namespace separator + // 2. Contains parenthesis + // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part + // of the annotation class name matches the found tag name + return \false; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php new file mode 100644 index 0000000..e8adf64 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php @@ -0,0 +1,25 @@ +|Factory $handler FQCN of handler. + * + * @throws InvalidArgumentException If the tag name is not a string. + * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but + * does not start with a backslash. + * @throws InvalidArgumentException If the handler is not a string. + * @throws InvalidArgumentException If the handler is not an existing class. + * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface. + */ + public function registerTagHandler(string $tagName, $handler) : void; +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php new file mode 100644 index 0000000..d082638 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php @@ -0,0 +1,85 @@ +authorName = $authorName; + $this->authorEmail = $authorEmail; + } + /** + * Gets the author's name. + * + * @return string The author's name. + */ + public function getAuthorName() : string + { + return $this->authorName; + } + /** + * Returns the author's email. + * + * @return string The author's email. + */ + public function getEmail() : string + { + return $this->authorEmail; + } + /** + * Returns this tag in string form. + */ + public function __toString() : string + { + if ($this->authorEmail) { + $authorEmail = '<' . $this->authorEmail . '>'; + } else { + $authorEmail = ''; + } + $authorName = $this->authorName; + return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : ''); + } + /** + * Attempts to create a new Author object based on the tag body. + */ + public static function create(string $body) : ?self + { + $splitTagContent = preg_match('/^([^\\<]*)(?:\\<([^\\>]*)\\>)?$/u', $body, $matches); + if (!$splitTagContent) { + return null; + } + $authorName = trim($matches[1]); + $email = isset($matches[2]) ? trim($matches[2]) : ''; + return new static($authorName, $email); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php new file mode 100644 index 0000000..0c88bc2 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php @@ -0,0 +1,45 @@ +name; + } + public function getDescription() : ?Description + { + return $this->description; + } + public function render(?Formatter $formatter = null) : string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + return $formatter->format($this); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php new file mode 100644 index 0000000..e779e11 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php @@ -0,0 +1,82 @@ +refers = $refers; + $this->description = $description; + } + public static function create(string $body, ?DescriptionFactory $descriptionFactory = null, ?FqsenResolver $resolver = null, ?TypeContext $context = null) : self + { + Assert::stringNotEmpty($body); + Assert::notNull($descriptionFactory); + Assert::notNull($resolver); + $parts = Utils::pregSplit('/\\s+/Su', $body, 2); + return new static(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. + */ + public function getReference() : Fqsen + { + return $this->refers; + } + /** + * Returns a string representation of this tag. + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $refers = (string) $this->refers; + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php new file mode 100644 index 0000000..cbba1d6 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php @@ -0,0 +1,86 @@ +version = $version; + $this->description = $description; + } + /** + * @return static + */ + public static function create(?string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + if ($body === null || $body === '') { + return new static(); + } + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) { + return new static(null, $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null); + } + Assert::notNull($descriptionFactory); + return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context)); + } + /** + * Gets the version section of the tag. + */ + public function getVersion() : ?string + { + return $this->version; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $version = (string) $this->version; + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php new file mode 100644 index 0000000..abed618 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php @@ -0,0 +1,153 @@ +filePath = $filePath; + $this->startingLine = $startingLine; + $this->lineCount = $lineCount; + if ($content !== null) { + $this->content = trim($content); + } + $this->isURI = $isURI; + } + public function getContent() : string + { + if ($this->content === null || $this->content === '') { + $filePath = $this->filePath; + if ($this->isURI) { + $filePath = $this->isUriRelative($this->filePath) ? str_replace('%2F', '/', rawurlencode($this->filePath)) : $this->filePath; + } + return trim($filePath); + } + return $this->content; + } + public function getDescription() : ?string + { + return $this->content; + } + public static function create(string $body) : ?Tag + { + // File component: File path in quotes or File URI / Source information + if (!preg_match('/^\\s*(?:(\\"[^\\"]+\\")|(\\S+))(?:\\s+(.*))?$/sux', $body, $matches)) { + return null; + } + $filePath = null; + $fileUri = null; + if (array_key_exists(1, $matches) && $matches[1] !== '') { + $filePath = $matches[1]; + } else { + $fileUri = array_key_exists(2, $matches) ? $matches[2] : ''; + } + $startingLine = 1; + $lineCount = 0; + $description = null; + if (array_key_exists(3, $matches)) { + $description = $matches[3]; + // 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])) { + $lineCount = (int) $contentMatches[2]; + } + if (array_key_exists(3, $contentMatches)) { + $description = $contentMatches[3]; + } + } + } + return new static($filePath ?? $fileUri ?? '', $fileUri !== null, $startingLine, $lineCount, $description); + } + /** + * Returns the file path. + * + * @return string Path to a file to use as an example. + * May also be an absolute URI. + */ + public function getFilePath() : string + { + return trim($this->filePath, '"'); + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + $filePath = $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 : ''); + } + /** + * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute). + */ + private function isUriRelative(string $uri) : bool + { + return strpos($uri, ':') === \false; + } + public function getStartingLine() : int + { + return $this->startingLine; + } + public function getLineCount() : int + { + return $this->lineCount; + } + public function getName() : string + { + return 'example'; + } + public function render(?Formatter $formatter = null) : string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + return $formatter->format($this); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php new file mode 100644 index 0000000..546ebd4 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Extends_.php @@ -0,0 +1,39 @@ +name = 'extends'; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body) : ?Tag + { + Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + return null; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php new file mode 100644 index 0000000..06f459b --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php @@ -0,0 +1,105 @@ + \true, 'lines' => \true]); + $this->lexer = new Lexer($config); + $constParser = new ConstExprParser($config); + $this->parser = new PhpDocParser($config, new TypeParser($config, $constParser), $constParser); + } else { + $this->lexer = new Lexer(\true); + $constParser = new ConstExprParser(\true, \true, ['lines' => \true, 'indexes' => \true]); + $this->parser = new PhpDocParser(new TypeParser($constParser, \true, ['lines' => \true, 'indexes' => \true]), $constParser, \true, \true, ['lines' => \true, 'indexes' => \true], \true); + } + $this->factories = $factories; + } + public function create(string $tagLine, ?TypeContext $context = null) : Tag + { + $tokens = $this->tokenizeLine($tagLine . "\n"); + $ast = $this->parser->parseTag($tokens); + if (property_exists($ast->value, 'description') === \true) { + $ast->value->setAttribute('description', rtrim($ast->value->description . $tokens->joinUntil(Lexer::TOKEN_END), "\n")); + } + if ($context === null) { + $context = new TypeContext(''); + } + try { + foreach ($this->factories as $factory) { + if ($factory->supports($ast, $context)) { + return $factory->create($ast, $context); + } + } + } catch (RuntimeException $e) { + return InvalidTag::create((string) $ast->value, 'method')->withError($e); + } + return InvalidTag::create((string) $ast->value, $ast->name); + } + /** + * Solve the issue with the lexer not tokenizing the line correctly + * + * This method is a workaround for the lexer that includes newline tokens with spaces. For + * phpstan this isn't an issue, as it doesn't do a lot of things with the indentation of descriptions. + * But for us is important to keep the indentation of the descriptions, so we need to fix the lexer output. + */ + private function tokenizeLine(string $tagLine) : TokenIterator + { + $tokens = $this->lexer->tokenize($tagLine); + $fixed = []; + foreach ($tokens as $token) { + if ($token[1] === Lexer::TOKEN_PHPDOC_EOL && rtrim($token[0], " \t") !== $token[0]) { + $fixed[] = [rtrim($token[Lexer::VALUE_OFFSET], " \t"), Lexer::TOKEN_PHPDOC_EOL, $token[2] ?? 0]; + $fixed[] = [ltrim($token[Lexer::VALUE_OFFSET], "\n\r"), Lexer::TOKEN_HORIZONTAL_WS, ($token[2] ?? 0) + 1]; + continue; + } + $fixed[] = $token; + } + return new TokenIterator($fixed); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php new file mode 100644 index 0000000..5030658 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ExtendsFactory.php @@ -0,0 +1,47 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof ExtendsTagValueNode && $node->name === '@extends'; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ExtendsTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Extends_($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php new file mode 100644 index 0000000..3430320 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Factory.php @@ -0,0 +1,38 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof ImplementsTagValueNode && $node->name === '@implements'; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ImplementsTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Implements_($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php new file mode 100644 index 0000000..99fc96e --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodFactory.php @@ -0,0 +1,58 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, MethodTagValueNode::class); + return new Method($tagValue->methodName, [], $this->createReturnType($tagValue, $context), $tagValue->isStatic, $this->descriptionFactory->create($tagValue->description, $context), \false, array_map(function (MethodTagValueParameterNode $param) use($context) { + return new MethodParameter(trim($param->parameterName, '$'), $param->type === null ? new Mixed_() : $this->typeResolver->createType($param->type, $context), $param->isReference, $param->isVariadic, $param->defaultValue === null ? MethodParameter::NO_DEFAULT_VALUE : (string) $param->defaultValue); + }, $tagValue->parameters)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof MethodTagValueNode; + } + private function createReturnType(MethodTagValueNode $tagValue, Context $context) : Type + { + if ($tagValue->returnType === null) { + return new Void_(); + } + return $this->typeResolver->createType($tagValue->returnType, $context); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php new file mode 100644 index 0000000..91c7388 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/MethodParameterFactory.php @@ -0,0 +1,84 @@ +{$method}($defaultValue); + } + return ''; + } + private function formatDouble(float $defaultValue) : string + { + return var_export($defaultValue, \true); + } + /** + * @param mixed $defaultValue + */ + private function formatNull($defaultValue) : string + { + return 'null'; + } + private function formatInteger(int $defaultValue) : string + { + return var_export($defaultValue, \true); + } + private function formatString(string $defaultValue) : string + { + return var_export($defaultValue, \true); + } + private function formatBoolean(bool $defaultValue) : string + { + return var_export($defaultValue, \true); + } + /** + * @param array<(array|int|float|bool|string|object|null)> $defaultValue + */ + private function formatArray(array $defaultValue) : string + { + $formatedValue = '['; + foreach ($defaultValue as $key => $value) { + $method = 'format' . ucfirst(gettype($value)); + if (!method_exists($this, $method)) { + continue; + } + $formatedValue .= $this->{$method}($value); + if ($key === array_key_last($defaultValue)) { + continue; + } + $formatedValue .= ','; + } + return $formatedValue . ']'; + } + private function formatObject(object $defaultValue) : string + { + return 'new ' . get_class($defaultValue) . '()'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php new file mode 100644 index 0000000..ffb0336 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PHPStanFactory.php @@ -0,0 +1,13 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + if ($tagValue instanceof InvalidTagValueNode) { + Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/362', sprintf('Param tag value "%s" is invalid, falling back to legacy parsing. Please update your docblocks.', $tagValue->value)); + return Param::create($tagValue->value, $this->typeResolver, $this->descriptionFactory, $context); + } + Assert::isInstanceOfAny($tagValue, [ParamTagValueNode::class, TypelessParamTagValueNode::class]); + if (($tagValue->type ?? null) instanceof OffsetAccessTypeNode) { + return InvalidTag::create((string) $tagValue, 'param'); + } + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Param(trim($tagValue->parameterName, '$'), $this->typeResolver->createType($tagValue->type ?? new IdentifierTypeNode('mixed'), $context), $tagValue->isVariadic, $this->descriptionFactory->create($description, $context), $tagValue->isReference); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof ParamTagValueNode || $node->value instanceof TypelessParamTagValueNode || $node->name === '@param'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php new file mode 100644 index 0000000..24cd813 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyFactory.php @@ -0,0 +1,48 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, PropertyTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Property(trim($tagValue->propertyName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof PropertyTagValueNode && $node->name === '@property'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php new file mode 100644 index 0000000..8636d38 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyReadFactory.php @@ -0,0 +1,48 @@ +typeResolver = $typeResolver; + $this->descriptionFactory = $descriptionFactory; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, PropertyTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new PropertyRead(trim($tagValue->propertyName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof PropertyTagValueNode && $node->name === '@property-read'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php new file mode 100644 index 0000000..a7b7b06 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/PropertyWriteFactory.php @@ -0,0 +1,48 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, PropertyTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new PropertyWrite(trim($tagValue->propertyName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof PropertyTagValueNode && $node->name === '@property-write'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php new file mode 100644 index 0000000..46003dc --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/ReturnFactory.php @@ -0,0 +1,47 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ReturnTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Return_($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof ReturnTagValueNode; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php new file mode 100644 index 0000000..3ae3ebb --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php @@ -0,0 +1,23 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof ExtendsTagValueNode && $node->name === '@template-extends'; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ExtendsTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new TemplateExtends($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php new file mode 100644 index 0000000..9b79403 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateFactory.php @@ -0,0 +1,48 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, TemplateTagValueNode::class); + $name = $tagValue->name; + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Template($name, $this->typeResolver->createType($tagValue->bound, $context), $this->typeResolver->createType($tagValue->default, $context), $this->descriptionFactory->create($description, $context)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof TemplateTagValueNode && $node->name === '@template'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php new file mode 100644 index 0000000..025bf32 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/TemplateImplementsFactory.php @@ -0,0 +1,47 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof ImplementsTagValueNode && $node->name === '@template-implements'; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, ImplementsTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new TemplateImplements($this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php new file mode 100644 index 0000000..bac9713 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/VarFactory.php @@ -0,0 +1,48 @@ +descriptionFactory = $descriptionFactory; + $this->typeResolver = $typeResolver; + } + public function create(PhpDocTagNode $node, Context $context) : Tag + { + $tagValue = $node->value; + Assert::isInstanceOf($tagValue, VarTagValueNode::class); + $description = $tagValue->getAttribute('description'); + if (is_string($description) === \false) { + $description = $tagValue->description; + } + return new Var_(trim($tagValue->variableName, '$'), $this->typeResolver->createType($tagValue->type, $context), $this->descriptionFactory->create($description, $context)); + } + public function supports(PhpDocTagNode $node, Context $context) : bool + { + return $node->value instanceof VarTagValueNode; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php new file mode 100644 index 0000000..890828f --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php @@ -0,0 +1,21 @@ +maxLen = max($this->maxLen, strlen($tag->getName())); + } + } + /** + * Formats the given tag to return a simple plain text version. + */ + public function format(Tag $tag) : string + { + return '@' . $tag->getName() . str_repeat(' ', $this->maxLen - strlen($tag->getName()) + 1) . $tag; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php new file mode 100644 index 0000000..7a4eeea --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php @@ -0,0 +1,26 @@ +getName() . ' ' . $tag); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php new file mode 100644 index 0000000..2ee5f40 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php @@ -0,0 +1,71 @@ +validateTagName($name); + $this->name = $name; + $this->description = $description; + } + /** + * Creates a new tag that represents any unknown tag type. + * + * @return static + */ + public static function create(string $body, string $name = '', ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::stringNotEmpty($name); + Assert::notNull($descriptionFactory); + $description = $body !== '' ? $descriptionFactory->create($body, $context) : null; + return new static($name, $description); + } + /** + * Returns the tag as a serialized string + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + return $description; + } + /** + * Validates if the tag name matches the expected format, otherwise throws an exception. + */ + private function validateTagName(string $name) : void + { + if (!preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { + throw new InvalidArgumentException('The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' . 'hyphens and backslashes.'); + } + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php new file mode 100644 index 0000000..a746e6b --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Implements_.php @@ -0,0 +1,39 @@ +name = 'implements'; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body) : ?Tag + { + Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + return null; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php new file mode 100644 index 0000000..79f2977 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php @@ -0,0 +1,127 @@ +name = $name; + $this->body = $body; + } + public function getException() : ?Throwable + { + return $this->throwable; + } + public function getName() : string + { + return $this->name; + } + public static function create(string $body, string $name = '') : self + { + return new self($name, $body); + } + public function withError(Throwable $exception) : self + { + $this->flattenExceptionBacktrace($exception); + $tag = new self($this->name, $this->body); + $tag->throwable = $exception; + return $tag; + } + /** + * Removes all complex types from backtrace + * + * Not all objects are serializable. So we need to remove them from the + * stored exception to be sure that we do not break existing library usage. + */ + private function flattenExceptionBacktrace(Throwable $exception) : void + { + $traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace'); + if (\PHP_VERSION_ID < 80100) { + $traceProperty->setAccessible(\true); + } + do { + $trace = $exception->getTrace(); + if (isset($trace[0]['args'])) { + $trace = array_map(function (array $call) : array { + $call['args'] = array_map([$this, 'flattenArguments'], $call['args'] ?? []); + return $call; + }, $trace); + } + $traceProperty->setValue($exception, $trace); + $exception = $exception->getPrevious(); + } while ($exception !== null); + if (\PHP_VERSION_ID < 80100) { + $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) { + $formatter = new Formatter\PassthroughFormatter(); + } + return $formatter->format($this); + } + public function __toString() : string + { + return $this->body; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php new file mode 100644 index 0000000..fc66297 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php @@ -0,0 +1,67 @@ +link = $link; + $this->description = $description; + } + public static function create(string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::notNull($descriptionFactory); + $parts = Utils::pregSplit('/\\s+/Su', $body, 2); + $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; + return new static($parts[0], $description); + } + /** + * Gets the link + */ + public function getLink() : string + { + return $this->link; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $link = $this->link; + return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php new file mode 100644 index 0000000..04a4308 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php @@ -0,0 +1,277 @@ +> $arguments + * @param MethodParameter[] $parameters + * @phpstan-param array $arguments + */ + public function __construct(string $methodName, array $arguments = [], ?Type $returnType = null, bool $static = \false, ?Description $description = null, bool $returnsReference = \false, ?array $parameters = null) + { + Assert::stringNotEmpty($methodName); + if ($returnType === null) { + $returnType = new Void_(); + } + $arguments = $this->filterArguments($arguments); + $this->methodName = $methodName; + $this->returnType = $returnType; + $this->isStatic = $static; + $this->description = $description; + $this->returnsReference = $returnsReference; + $this->parameters = $parameters ?? $this->fromLegacyArguments($arguments); + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : ?self + { + trigger_error('Create using static factory is deprecated, this method should not be called directly + by library consumers', E_USER_DEPRECATED); + Assert::stringNotEmpty($body); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + // 1. none or more whitespace + // 2. optionally the keyword "static" followed by whitespace + // 3. optionally a word with underscores followed by whitespace : as + // type for the return value + // 4. optionally an ampersand followed or not by whitespace : as + // a reference + // 5. then optionally a word with underscores followed by () and + // whitespace : as method name as used by phpDocumentor + // 6. then a word with underscores, followed by ( and any character + // until a ) and whitespace : as method name with signature + // 7. any remaining text : as description + if (!preg_match('/^ + # Static keyword + # Declares a static method ONLY if type is also present + (?: + (static) + \\s+ + )? + # Return type + (?: + ( + (?:[\\w\\|_\\\\]*\\$this[\\w\\|_\\\\]*) + | + (?: + (?:[\\w\\|_\\\\]+) + # array notation + (?:\\[\\])* + )*+ + ) + \\s+ + )? + # Returns reference + (?: + (&) + \\s* + )? + # Method name + ([\\w_]+) + # Arguments + (?: + \\(([^\\)]*)\\) + )? + \\s* + # Description + (.*) + $/sux', $body, $matches)) { + return null; + } + [, $static, $returnType, $returnsReference, $methodName, $argumentLines, $description] = $matches; + $static = $static === 'static'; + if ($returnType === '') { + $returnType = 'void'; + } + $returnsReference = $returnsReference === '&'; + $returnType = $typeResolver->resolve($returnType, $context); + $description = $descriptionFactory->create($description, $context); + /** @phpstan-var array $arguments */ + $arguments = []; + if ($argumentLines !== '') { + $argumentsExploded = explode(',', $argumentLines); + foreach ($argumentsExploded as $argument) { + $argument = explode(' ', self::stripRestArg(trim($argument)), 2); + if (strpos($argument[0], '$') === 0) { + $argumentName = substr($argument[0], 1); + $argumentType = new Mixed_(); + } else { + $argumentType = $typeResolver->resolve($argument[0], $context); + $argumentName = ''; + if (isset($argument[1])) { + $argument[1] = self::stripRestArg($argument[1]); + $argumentName = substr($argument[1], 1); + } + } + $arguments[] = ['name' => $argumentName, 'type' => $argumentType]; + } + } + return new static($methodName, $arguments, $returnType, $static, $description, $returnsReference); + } + /** + * Retrieves the method name. + */ + public function getMethodName() : string + { + return $this->methodName; + } + /** + * @deprecated Method deprecated, use {@see self::getParameters()} + * + * @return array> + * @phpstan-return array + */ + public function getArguments() : array + { + trigger_error('Method deprecated, use ::getParameters()', E_USER_DEPRECATED); + return array_map(static function (MethodParameter $methodParameter) { + return ['name' => $methodParameter->getName(), 'type' => $methodParameter->getType()]; + }, $this->parameters); + } + /** @return MethodParameter[] */ + public function getParameters() : array + { + return $this->parameters; + } + /** + * Checks whether the method tag describes a static method or not. + * + * @return bool TRUE if the method declaration is for a static method, FALSE otherwise. + */ + public function isStatic() : bool + { + return $this->isStatic; + } + public function getReturnType() : Type + { + return $this->returnType; + } + public function returnsReference() : bool + { + return $this->returnsReference; + } + public function __toString() : string + { + $arguments = []; + foreach ($this->parameters as $parameter) { + $arguments[] = (string) $parameter; + } + $argumentStr = '(' . implode(', ', $arguments) . ')'; + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $static = $this->isStatic ? 'static' : ''; + $returnType = (string) $this->returnType; + $methodName = $this->methodName; + $reference = $this->returnsReference ? '&' : ''; + return $static . ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '') . ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $reference . $methodName : '') . $argumentStr . ($description !== '' ? ' ' . $description : ''); + } + /** + * @param mixed[][]|string[] $arguments + * @phpstan-param array $arguments + * + * @return mixed[][] + * @phpstan-return array + */ + private function filterArguments(array $arguments = []) : array + { + $result = []; + foreach ($arguments as $argument) { + if (is_string($argument)) { + $argument = ['name' => $argument]; + } + if (!isset($argument['type'])) { + $argument['type'] = new Mixed_(); + } + $keys = array_keys($argument); + sort($keys); + if ($keys !== ['name', 'type']) { + throw new InvalidArgumentException('Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, \true)); + } + $result[] = $argument; + } + return $result; + } + private static function stripRestArg(string $argument) : string + { + if (strpos($argument, '...') === 0) { + $argument = trim(substr($argument, 3)); + } + return $argument; + } + /** + * @param array{name: string, type: Type} $arguments + * @phpstan-param array $arguments + * + * @return MethodParameter[] + */ + private function fromLegacyArguments(array $arguments) : array + { + trigger_error('Create method parameters via legacy format is deprecated add parameters via the constructor', E_USER_DEPRECATED); + return array_map(static function ($arg) { + return new MethodParameter($arg['name'], $arg['type']); + }, $arguments); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php new file mode 100644 index 0000000..1b2ef29 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/MethodParameter.php @@ -0,0 +1,75 @@ +type = $type; + $this->isReference = $isReference; + $this->isVariadic = $isVariadic; + $this->name = $name; + $this->defaultValue = $defaultValue; + } + public function getName() : string + { + return $this->name; + } + public function getType() : Type + { + return $this->type; + } + public function isReference() : bool + { + return $this->isReference; + } + public function isVariadic() : bool + { + return $this->isVariadic; + } + public function getDefaultValue() : ?string + { + if ($this->defaultValue === self::NO_DEFAULT_VALUE) { + return null; + } + return (new MethodParameterFactory())->format($this->defaultValue); + } + public function __toString() : string + { + return $this->getType() . ' ' . ($this->isReference() ? '&' : '') . ($this->isVariadic() ? '...' : '') . '$' . $this->getName() . ($this->defaultValue !== self::NO_DEFAULT_VALUE ? (new MethodParameterFactory())->format($this->defaultValue) : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php new file mode 100644 index 0000000..be31adc --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Mixin.php @@ -0,0 +1,40 @@ +name = 'mixin'; + $this->type = $type; + $this->description = $description; + } + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$type, $description] = self::extractTypeFromBody($body); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); + return new static($type, $description); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php new file mode 100644 index 0000000..f65026d --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php @@ -0,0 +1,141 @@ +name = 'param'; + $this->variableName = $variableName; + $this->type = $type; + $this->isVariadic = $isVariadic; + $this->description = $description; + $this->isReference = $isReference; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + Assert::stringNotEmpty($body); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $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 && !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 ...$ or &$ or &...$ it must be the variable name + if (isset($parts[0]) && self::strStartsWithVariable($parts[0])) { + $variableName = array_shift($parts); + if ($type) { + array_shift($parts); + } + Assert::notNull($variableName); + 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, $isReference); + } + /** + * Returns the variable's name. + */ + public function getVariableName() : ?string + { + return $this->variableName; + } + /** + * Returns whether this tag is variadic. + */ + public function isVariadic() : bool + { + 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 + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $variableName = ''; + if ($this->variableName !== null && $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; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php new file mode 100644 index 0000000..465ddcd --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php @@ -0,0 +1,104 @@ +name = 'property'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + Assert::stringNotEmpty($body); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $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 + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); + } + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { + $variableName = array_shift($parts); + if ($type) { + array_shift($parts); + } + Assert::notNull($variableName); + $variableName = substr($variableName, 1); + } + $description = $descriptionFactory->create(implode('', $parts), $context); + return new static($variableName, $type, $description); + } + /** + * Returns the variable's name. + */ + public function getVariableName() : ?string + { + return $this->variableName; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + if ($this->variableName !== null && $this->variableName !== '') { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + $type = (string) $this->type; + return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php new file mode 100644 index 0000000..5588764 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php @@ -0,0 +1,104 @@ +name = 'property-read'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + Assert::stringNotEmpty($body); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $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 + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); + } + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { + $variableName = array_shift($parts); + if ($type) { + array_shift($parts); + } + Assert::notNull($variableName); + $variableName = substr($variableName, 1); + } + $description = $descriptionFactory->create(implode('', $parts), $context); + return new static($variableName, $type, $description); + } + /** + * Returns the variable's name. + */ + public function getVariableName() : ?string + { + return $this->variableName; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + if ($this->variableName !== null && $this->variableName !== '') { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + $type = (string) $this->type; + return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php new file mode 100644 index 0000000..5023751 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php @@ -0,0 +1,104 @@ +name = 'property-write'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + Assert::stringNotEmpty($body); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $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 + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); + } + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { + $variableName = array_shift($parts); + if ($type) { + array_shift($parts); + } + Assert::notNull($variableName); + $variableName = substr($variableName, 1); + } + $description = $descriptionFactory->create(implode('', $parts), $context); + return new static($variableName, $type, $description); + } + /** + * Returns the variable's name. + */ + public function getVariableName() : ?string + { + return $this->variableName; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + 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 : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php new file mode 100644 index 0000000..a888149 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php @@ -0,0 +1,35 @@ +fqsen = $fqsen; + } + /** + * @return string string representation of the referenced fqsen + */ + public function __toString() : string + { + return (string) $this->fqsen; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php new file mode 100644 index 0000000..dcf6d3b --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php @@ -0,0 +1,20 @@ +uri = $uri; + } + public function __toString() : string + { + return $this->uri; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php new file mode 100644 index 0000000..87e0ca9 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php @@ -0,0 +1,47 @@ +name = 'return'; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$type, $description] = self::extractTypeFromBody($body); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); + return new static($type, $description); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php new file mode 100644 index 0000000..cd808a5 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php @@ -0,0 +1,89 @@ +refers = $refers; + $this->description = $description; + } + public static function create(string $body, ?FqsenResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::notNull($descriptionFactory); + $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 + if (preg_match('#\\w://\\w#', $parts[0])) { + return new static(new Url($parts[0]), $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]); + } + /** + * Returns the ref of this tag. + */ + public function getReference() : Reference + { + return $this->refers; + } + /** + * Returns a string representation of this tag. + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $refers = (string) $this->refers; + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php new file mode 100644 index 0000000..e1f74c7 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php @@ -0,0 +1,83 @@ +version = $version; + $this->description = $description; + } + public static function create(?string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : ?self + { + if ($body === null || $body === '') { + return new static(); + } + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) { + return null; + } + Assert::notNull($descriptionFactory); + return new static($matches[1], $descriptionFactory->create($matches[2] ?? '', $context)); + } + /** + * Gets the version section of the tag. + */ + public function getVersion() : ?string + { + return $this->version; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + $version = (string) $this->version; + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php new file mode 100644 index 0000000..18ca2d7 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php @@ -0,0 +1,92 @@ +startingLine = (int) $startingLine; + $this->lineCount = $lineCount !== null ? (int) $lineCount : null; + $this->description = $description; + } + public static function create(string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::stringNotEmpty($body); + Assert::notNull($descriptionFactory); + $startingLine = 1; + $lineCount = null; + $description = null; + // Starting line / Number of lines / Description + if (preg_match('/^([1-9]\\d*)\\s*(?:((?1))\\s+)?(.*)$/sux', $body, $matches)) { + $startingLine = (int) $matches[1]; + if (isset($matches[2]) && $matches[2] !== '') { + $lineCount = (int) $matches[2]; + } + $description = $matches[3]; + } + return new static($startingLine, $lineCount, $descriptionFactory->create($description ?? '', $context)); + } + /** + * Gets the starting line. + * + * @return int The starting line, relative to the structural element's + * location. + */ + public function getStartingLine() : int + { + return $this->startingLine; + } + /** + * Returns the number of lines. + * + * @return int|null The number of lines, relative to the starting line. NULL + * means "to the end". + */ + public function getLineCount() : ?int + { + return $this->lineCount; + } + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $startingLine = (string) $this->startingLine; + $lineCount = $this->lineCount !== null ? ' ' . $this->lineCount : ''; + return $startingLine . $lineCount . ($description !== '' ? ' ' . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php new file mode 100644 index 0000000..1918a28 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php @@ -0,0 +1,70 @@ +type; + } + /** + * @return string[] + */ + protected static function extractTypeFromBody(string $body) : array + { + $type = ''; + $nestingLevel = 0; + for ($i = 0, $iMax = strlen($body); $i < $iMax; $i++) { + $character = $body[$i]; + if ($nestingLevel === 0 && trim($character) === '') { + break; + } + $type .= $character; + if (in_array($character, ['<', '(', '[', '{'])) { + $nestingLevel++; + continue; + } + if (in_array($character, ['>', ')', ']', '}'])) { + $nestingLevel--; + continue; + } + } + if ($nestingLevel < 0 || $nestingLevel > 0) { + throw new InvalidArgumentException(sprintf('Could not find type in %s, please check for malformed notations', $body)); + } + $description = trim(substr($body, strlen($type))); + return [$type, $description]; + } + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $type = (string) $this->type; + return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php new file mode 100644 index 0000000..7f4d516 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Template.php @@ -0,0 +1,73 @@ +name = 'template'; + $this->templateName = $templateName; + $this->bound = $bound; + $this->default = $default; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body) : ?Tag + { + Deprecation::trigger('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + return null; + } + public function getTemplateName() : string + { + return $this->templateName; + } + public function getBound() : ?Type + { + return $this->bound; + } + public function getDefault() : ?Type + { + return $this->default; + } + public function __toString() : string + { + $bound = $this->bound !== null ? ' of ' . $this->bound : ''; + $default = $this->default !== null ? ' = ' . $this->default : ''; + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + return $this->templateName . $bound . $default . ($description !== '' ? ' ' . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php new file mode 100644 index 0000000..4db5074 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateCovariant.php @@ -0,0 +1,40 @@ +name = 'template-covariant'; + $this->type = $type; + $this->description = $description; + } + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$type, $description] = self::extractTypeFromBody($body); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); + return new static($type, $description); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php new file mode 100644 index 0000000..0c839e9 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateExtends.php @@ -0,0 +1,26 @@ +name = 'template-extends'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php new file mode 100644 index 0000000..865228a --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TemplateImplements.php @@ -0,0 +1,26 @@ +name = 'template-implements'; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php new file mode 100644 index 0000000..5b3e17d --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php @@ -0,0 +1,40 @@ +name = 'throws'; + $this->type = $type; + $this->description = $description; + } + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$type, $description] = self::extractTypeFromBody($body); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); + return new static($type, $description); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php new file mode 100644 index 0000000..599cb34 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php @@ -0,0 +1,81 @@ +refers = $refers; + $this->description = $description; + } + public static function create(string $body, ?FqsenResolver $resolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Assert::notNull($resolver); + Assert::notNull($descriptionFactory); + $parts = Utils::pregSplit('/\\s+/Su', $body, 2); + return new static(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. + */ + public function getReference() : Fqsen + { + return $this->refers; + } + /** + * Returns a string representation of this tag. + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $refers = (string) $this->refers; + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php new file mode 100644 index 0000000..1fd6c08 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php @@ -0,0 +1,104 @@ +name = 'var'; + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + /** + * @deprecated Create using static factory is deprecated, + * this method should not be called directly by library consumers + */ + public static function create(string $body, ?TypeResolver $typeResolver = null, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : self + { + Deprecation::triggerIfCalledFromOutside('phpdocumentor/reflection-docblock', 'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361', 'Create using static factory is deprecated, this method should not be called directly + by library consumers'); + Assert::stringNotEmpty($body); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + [$firstPart, $body] = self::extractTypeFromBody($body); + $parts = Utils::pregSplit('/(\\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); + $type = null; + $variableName = ''; + // if the first item that is encountered is not a variable; it is a type + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); + } + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { + $variableName = array_shift($parts); + if ($type) { + array_shift($parts); + } + Assert::notNull($variableName); + $variableName = substr($variableName, 1); + } + $description = $descriptionFactory->create(implode('', $parts), $context); + return new static($variableName, $type, $description); + } + /** + * Returns the variable's name. + */ + public function getVariableName() : ?string + { + return $this->variableName; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description !== null) { + $description = $this->description->render(); + } else { + $description = ''; + } + if ($this->variableName !== null && $this->variableName !== '') { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + $type = (string) $this->type; + return $type . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php new file mode 100644 index 0000000..978fa8a --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php @@ -0,0 +1,86 @@ +version = $version; + $this->description = $description; + } + public static function create(?string $body, ?DescriptionFactory $descriptionFactory = null, ?TypeContext $context = null) : ?self + { + if ($body === null || $body === '') { + return new static(); + } + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\\s*(.+)?$/sux', $body, $matches)) { + return null; + } + $description = null; + if ($descriptionFactory !== null) { + $description = $descriptionFactory->create($matches[2] ?? '', $context); + } + return new static($matches[1], $description); + } + /** + * Gets the version section of the tag. + */ + public function getVersion() : ?string + { + return $this->version; + } + /** + * Returns a string representation for this tag. + */ + public function __toString() : string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + $version = (string) $this->version; + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlockFactory.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlockFactory.php new file mode 100644 index 0000000..18af241 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlockFactory.php @@ -0,0 +1,271 @@ +descriptionFactory = $descriptionFactory; + $this->tagFactory = $tagFactory; + } + /** + * Factory method for easy instantiation. + * + * @param array|Factory> $additionalTags + */ + public static function createInstance(array $additionalTags = []) : DocBlockFactoryInterface + { + $fqsenResolver = new FqsenResolver(); + $tagFactory = new StandardTagFactory($fqsenResolver); + $descriptionFactory = new DescriptionFactory($tagFactory); + $typeResolver = new TypeResolver($fqsenResolver); + $phpstanTagFactory = new AbstractPHPStanFactory(new ParamFactory($typeResolver, $descriptionFactory), new VarFactory($typeResolver, $descriptionFactory), new ReturnFactory($typeResolver, $descriptionFactory), new PropertyFactory($typeResolver, $descriptionFactory), new PropertyReadFactory($typeResolver, $descriptionFactory), new PropertyWriteFactory($typeResolver, $descriptionFactory), new MethodFactory($typeResolver, $descriptionFactory), new ImplementsFactory($typeResolver, $descriptionFactory), new ExtendsFactory($typeResolver, $descriptionFactory), new TemplateFactory($typeResolver, $descriptionFactory), new TemplateImplementsFactory($typeResolver, $descriptionFactory), new TemplateExtendsFactory($typeResolver, $descriptionFactory)); + $tagFactory->addService($descriptionFactory); + $tagFactory->addService($typeResolver); + $tagFactory->registerTagHandler('param', $phpstanTagFactory); + $tagFactory->registerTagHandler('var', $phpstanTagFactory); + $tagFactory->registerTagHandler('return', $phpstanTagFactory); + $tagFactory->registerTagHandler('property', $phpstanTagFactory); + $tagFactory->registerTagHandler('property-read', $phpstanTagFactory); + $tagFactory->registerTagHandler('property-write', $phpstanTagFactory); + $tagFactory->registerTagHandler('method', $phpstanTagFactory); + $tagFactory->registerTagHandler('extends', $phpstanTagFactory); + $tagFactory->registerTagHandler('implements', $phpstanTagFactory); + $tagFactory->registerTagHandler('template', $phpstanTagFactory); + $tagFactory->registerTagHandler('template-extends', $phpstanTagFactory); + $tagFactory->registerTagHandler('template-implements', $phpstanTagFactory); + $docBlockFactory = new self($descriptionFactory, $tagFactory); + foreach ($additionalTags as $tagName => $tagHandler) { + $docBlockFactory->registerTagHandler($tagName, $tagHandler); + } + return $docBlockFactory; + } + /** + * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the + * getDocComment method (such as a ReflectionClass object). + */ + public function create($docblock, ?Types\Context $context = null, ?Location $location = null) : DocBlock + { + if (is_object($docblock)) { + if (!method_exists($docblock, 'getDocComment')) { + $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; + throw new InvalidArgumentException($exceptionMessage); + } + $docblock = $docblock->getDocComment(); + Assert::string($docblock); + } + Assert::stringNotEmpty($docblock); + if ($context === null) { + $context = new Types\Context(''); + } + $parts = $this->splitDocBlock($this->stripDocComment($docblock)); + [$templateMarker, $summary, $description, $tags] = $parts; + return new DocBlock($summary, $description ? $this->descriptionFactory->create($description, $context) : null, $this->parseTagBlock($tags, $context), $context, $location, $templateMarker === '#@+', $templateMarker === '#@-'); + } + /** + * @param class-string|Factory $handler + */ + public function registerTagHandler(string $tagName, $handler) : void + { + $this->tagFactory->registerTagHandler($tagName, $handler); + } + /** + * Strips the asterisks from the DocBlock comment. + * + * @param string $comment String containing the comment text. + */ + private function stripDocComment(string $comment) : string + { + $comment = preg_replace('#[ \\t]*(?:\\/\\*\\*|\\*\\/|\\*)?[ \\t]?(.*)?#u', '$1', $comment); + Assert::string($comment); + $comment = trim($comment); + // reg ex above is not able to remove */ from a single line docblock + if (substr($comment, -2) === '*/') { + $comment = trim(substr($comment, 0, -2)); + } + return str_replace(["\r\n", "\r"], "\n", $comment); + } + // phpcs:disable + /** + * Splits the DocBlock into a template marker, summary, description and block of tags. + * + * @param string $comment Comment to split into the sub-parts. + * + * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + * + * @author Mike van Riel for extending the regex with template marker support. + * + * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. + */ + private function splitDocBlock(string $comment) : array + { + // phpcs:enable + // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This + // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the + // performance impact of running a regular expression + if (strpos($comment, '@') === 0) { + return ['', '', '', $comment]; + } + // clears all extra horizontal whitespace from the line endings to prevent parsing issues + $comment = preg_replace('/\\h*$/Sum', '', $comment); + Assert::string($comment); + /* + * Splits the docblock into a template marker, summary, description and tags section. + * + * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may + * occur after it and will be stripped). + * - The short description is started from the first character until a dot is encountered followed by a + * newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing + * errors). This is optional. + * - The long description, any character until a new line is encountered followed by an @ and word + * characters (a tag). This is optional. + * - Tags; the remaining characters + * + * Big thanks to RichardJ for contributing this Regular Expression + */ + preg_match('/ + \\A + # 1. Extract the template marker + (?:(\\#\\@\\+|\\#\\@\\-)\\n?)? + + # 2. Extract the summary + (?: + (?! @\\pL ) # The summary may not start with an @ + ( + [^\\n.]+ + (?: + (?! \\. \\n | \\n{2} ) # End summary upon a dot followed by newline or two newlines + [\\n.]* (?! [ \\t]* @\\pL ) # End summary when an @ is found as first character on a new line + [^\\n.]+ # Include anything else + )* + \\.? + )? + ) + + # 3. Extract the description + (?: + \\s* # Some form of whitespace _must_ precede a description because a summary must be there + (?! @\\pL ) # The description may not start with an @ + ( + [^\\n]+ + (?: \\n+ + (?! [ \\t]* @\\pL ) # End description when an @ is found as first character on a new line + [^\\n]+ # Include anything else + )* + ) + )? + + # 4. Extract the tags (anything that follows) + (\\s+ [\\s\\S]*)? # everything that follows + /ux', $comment, $matches); + array_shift($matches); + while (count($matches) < 4) { + $matches[] = ''; + } + return $matches; + } + /** + * Creates the tag objects. + * + * @param string $tags Tag block to parse. + * @param Types\Context $context Context of the parsed Tag + * + * @return DocBlock\Tag[] + */ + private function parseTagBlock(string $tags, Types\Context $context) : array + { + $tags = $this->filterTagBlock($tags); + if ($tags === null) { + return []; + } + $result = []; + $lines = $this->splitTagBlockIntoTagLines($tags); + foreach ($lines as $key => $tagLine) { + $result[$key] = $this->tagFactory->create(trim($tagLine), $context); + } + return $result; + } + /** + * @return string[] + */ + private function splitTagBlockIntoTagLines(string $tags) : array + { + $result = []; + foreach (explode("\n", $tags) as $tagLine) { + if ($tagLine !== '' && strpos($tagLine, '@') === 0) { + $result[] = $tagLine; + } else { + $result[count($result) - 1] .= "\n" . $tagLine; + } + } + return $result; + } + private function filterTagBlock(string $tags) : ?string + { + $tags = trim($tags); + if (!$tags) { + return null; + } + if ($tags[0] !== '@') { + // @codeCoverageIgnoreStart + // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that + // we didn't foresee. + throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); + // @codeCoverageIgnoreEnd + } + return $tags; + } +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php new file mode 100644 index 0000000..ee53578 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php @@ -0,0 +1,20 @@ +> $additionalTags + */ + public static function createInstance(array $additionalTags = []) : self; + /** + * @param string|object $docblock + */ + public function create($docblock, ?Types\Context $context = null, ?Location $location = null) : DocBlock; +} diff --git a/vendor/prefixed/phpdocumentor/reflection-docblock/src/Exception/PcreException.php b/vendor/prefixed/phpdocumentor/reflection-docblock/src/Exception/PcreException.php new file mode 100644 index 0000000..01896aa --- /dev/null +++ b/vendor/prefixed/phpdocumentor/reflection-docblock/src/Exception/PcreException.php @@ -0,0 +1,35 @@ +resolve('string'); + echo get_class($type); // phpDocumentor\Reflection\Types\String_ + +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 :php:class:`\phpDocumentor\Reflection\Types\Context` class that +will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. + +Read more about the Context class in the next section. diff --git a/vendor/prefixed/phpdocumentor/type-resolver/docs/index.rst b/vendor/prefixed/phpdocumentor/type-resolver/docs/index.rst new file mode 100644 index 0000000..0ff9a8b --- /dev/null +++ b/vendor/prefixed/phpdocumentor/type-resolver/docs/index.rst @@ -0,0 +1,17 @@ +============= +Type resolver +============= + +This project part of the phpDocumentor project. It is capable of creating an object structure of the type +specifications found in the PHPDoc blocks of a project. This can be useful for static analysis of a project +or other behavior that requires knowledge of the types used in a project like automatically build forms. + +This project aims to cover all types that are available in PHPDoc and PHP itself. And is open for extension by +third party developers. + +.. toctree:: + :maxdepth: 2 + :hidden: + + index + getting-started diff --git a/vendor/prefixed/phpdocumentor/type-resolver/phpdoc.dist.xml b/vendor/prefixed/phpdocumentor/type-resolver/phpdoc.dist.xml new file mode 100644 index 0000000..6c98991 --- /dev/null +++ b/vendor/prefixed/phpdocumentor/type-resolver/phpdoc.dist.xml @@ -0,0 +1,46 @@ + + + Type Resolver + + build/docs + + + latest + + + src/ + + api + + + php + + + template + template-extends + template-implements + extends + implements + + phpDocumentor + + + + docs + + guides + + + +