Updated Rector to commit befc5441a1ef5c19cabf9cae0619d5c2cd23a028

befc5441a1 Add real path to filePaths when not false (#3004)
This commit is contained in:
Tomas Votruba 2022-10-21 10:12:40 +00:00
parent ab87062075
commit 48bf5c84cd
26 changed files with 166 additions and 161 deletions

View File

@ -17,12 +17,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '4cecebfd7e86cafd9e09f8e1fd493046aa1181ea';
public const PACKAGE_VERSION = 'befc5441a1ef5c19cabf9cae0619d5c2cd23a028';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2022-10-20 09:35:30';
public const RELEASE_DATE = '2022-10-21 12:06:48';
/**
* @var int
*/

View File

@ -72,7 +72,13 @@ final class FilesFinder
$this->addFilterWithExcludedPaths($finder);
$filePaths = [];
foreach ($finder as $fileInfo) {
$filePaths[] = $fileInfo->getRealPath();
// getRealPath() function will return false when it checks broken symlinks.
// So we should check if this file exists or we got broken symlink
/** @var string|false $path */
$path = $fileInfo->getRealPath();
if ($path !== \false) {
$filePaths[] = $path;
}
}
return $this->unchangedFilesFilter->filterAndJoinWithDependentFileInfos($filePaths);
}

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitde18bf78c8ab1941d04592e5ed547edb::getLoader();
return ComposerAutoloaderInit301cfadbfd36bd0127c30eb0acf01702::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitde18bf78c8ab1941d04592e5ed547edb
class ComposerAutoloaderInit301cfadbfd36bd0127c30eb0acf01702
{
private static $loader;
@ -22,19 +22,19 @@ class ComposerAutoloaderInitde18bf78c8ab1941d04592e5ed547edb
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitde18bf78c8ab1941d04592e5ed547edb', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit301cfadbfd36bd0127c30eb0acf01702', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitde18bf78c8ab1941d04592e5ed547edb', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit301cfadbfd36bd0127c30eb0acf01702', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit301cfadbfd36bd0127c30eb0acf01702::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb::$files;
$includeFiles = \Composer\Autoload\ComposerStaticInit301cfadbfd36bd0127c30eb0acf01702::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequirede18bf78c8ab1941d04592e5ed547edb($fileIdentifier, $file);
composerRequire301cfadbfd36bd0127c30eb0acf01702($fileIdentifier, $file);
}
return $loader;
@ -46,7 +46,7 @@ class ComposerAutoloaderInitde18bf78c8ab1941d04592e5ed547edb
* @param string $file
* @return void
*/
function composerRequirede18bf78c8ab1941d04592e5ed547edb($fileIdentifier, $file)
function composerRequire301cfadbfd36bd0127c30eb0acf01702($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb
class ComposerStaticInit301cfadbfd36bd0127c30eb0acf01702
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -3093,9 +3093,9 @@ class ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitde18bf78c8ab1941d04592e5ed547edb::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit301cfadbfd36bd0127c30eb0acf01702::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit301cfadbfd36bd0127c30eb0acf01702::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit301cfadbfd36bd0127c30eb0acf01702::$classMap;
}, null, ClassLoader::class);
}

View File

@ -296,31 +296,31 @@
},
{
"name": "doctrine\/inflector",
"version": "2.0.5",
"version_normalized": "2.0.5.0",
"version": "2.0.6",
"version_normalized": "2.0.6.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/doctrine\/inflector.git",
"reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392"
"reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/doctrine\/inflector\/zipball\/ade2b3bbfb776f27f0558e26eed43b5d9fe1b392",
"reference": "ade2b3bbfb776f27f0558e26eed43b5d9fe1b392",
"url": "https:\/\/api.github.com\/repos\/doctrine\/inflector\/zipball\/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
"reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine\/coding-standard": "^9",
"doctrine\/coding-standard": "^10",
"phpstan\/phpstan": "^1.8",
"phpstan\/phpstan-phpunit": "^1.1",
"phpstan\/phpstan-strict-rules": "^1.3",
"phpunit\/phpunit": "^8.5 || ^9.5",
"vimeo\/psalm": "^4.25"
},
"time": "2022-09-07T09:01:28+00:00",
"time": "2022-10-20T09:10:12+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -370,7 +370,7 @@
],
"support": {
"issues": "https:\/\/github.com\/doctrine\/inflector\/issues",
"source": "https:\/\/github.com\/doctrine\/inflector\/tree\/2.0.5"
"source": "https:\/\/github.com\/doctrine\/inflector\/tree\/2.0.6"
},
"funding": [
{
@ -685,17 +685,17 @@
},
{
"name": "phpstan\/phpdoc-parser",
"version": "1.11.0",
"version_normalized": "1.11.0.0",
"version": "1.13.0",
"version_normalized": "1.13.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpdoc-parser.git",
"reference": "7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65"
"reference": "33aefcdab42900e36366d0feab6206e2dd68f947"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65",
"reference": "7d1e81213b0c7eb8d5a9f524456cbc2778ed5c65",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/33aefcdab42900e36366d0feab6206e2dd68f947",
"reference": "33aefcdab42900e36366d0feab6206e2dd68f947",
"shasum": ""
},
"require": {
@ -710,7 +710,7 @@
"phpunit\/phpunit": "^9.5",
"symfony\/process": "^5.2"
},
"time": "2022-10-14T13:32:28+00:00",
"time": "2022-10-21T09:57:39+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -727,7 +727,7 @@
"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\/1.11.0"
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.13.0"
},
"install-path": "..\/phpstan\/phpdoc-parser"
},

File diff suppressed because one or more lines are too long

View File

@ -42,7 +42,7 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine\/coding-standard": "^9",
"doctrine\/coding-standard": "^10",
"phpstan\/phpstan": "^1.8",
"phpstan\/phpstan-phpunit": "^1.1",
"phpstan\/phpstan-strict-rules": "^1.3",

View File

@ -9,9 +9,7 @@ use RectorPrefix202210\Doctrine\Inflector\Rules\Transformation;
use RectorPrefix202210\Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular() : iterable
{
(yield new Transformation(new Pattern('(s)tatuses$'), 'RectorPrefix202210\\1\\2tatus'));
@ -58,9 +56,7 @@ class Inflectible
(yield new Transformation(new Pattern('^shorts$'), 'shorts'));
(yield new Transformation(new Pattern('s$'), ''));
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural() : iterable
{
(yield new Transformation(new Pattern('(s)tatus$'), 'RectorPrefix202210\\1\\2tatuses'));
@ -89,9 +85,7 @@ class Inflectible
(yield new Transformation(new Pattern('^$'), ''));
(yield new Transformation(new Pattern('$'), 's'));
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular() : iterable
{
(yield new Substitution(new Word('atlas'), new Word('atlases')));
@ -150,6 +144,7 @@ class Inflectible
(yield new Substitution(new Word('runner-up'), new Word('runners-up')));
(yield new Substitution(new Word('safe'), new Word('safes')));
(yield new Substitution(new Word('sex'), new Word('sexes')));
(yield new Substitution(new Word('sieve'), new Word('sieves')));
(yield new Substitution(new Word('soliloquy'), new Word('soliloquies')));
(yield new Substitution(new Word('son-in-law'), new Word('sons-in-law')));
(yield new Substitution(new Word('syllabus'), new Word('syllabi')));

View File

@ -6,9 +6,7 @@ namespace RectorPrefix202210\Doctrine\Inflector\Rules\English;
use RectorPrefix202210\Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular() : iterable
{
yield from self::getDefault();
@ -26,9 +24,7 @@ final class Uninflected
(yield new Pattern('trivia'));
(yield new Pattern('utopia'));
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural() : iterable
{
yield from self::getDefault();
@ -37,9 +33,7 @@ final class Uninflected
(yield new Pattern('\\w+ware$'));
(yield new Pattern('media'));
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault() : iterable
{
(yield new Pattern('\\w+media'));

View File

@ -9,9 +9,7 @@ use RectorPrefix202210\Doctrine\Inflector\Rules\Transformation;
use RectorPrefix202210\Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular() : iterable
{
(yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\\1ail'));
@ -20,9 +18,7 @@ class Inflectible
(yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/'), '\\1'));
(yield new Transformation(new Pattern('/s$/'), ''));
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural() : iterable
{
(yield new Transformation(new Pattern('/(s|x|z)$/'), '\\1'));
@ -34,9 +30,7 @@ class Inflectible
(yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|lieu|pou|au|eu|eau)$/'), '\\1x'));
(yield new Transformation(new Pattern('/$/'), 's'));
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular() : iterable
{
(yield new Substitution(new Word('monsieur'), new Word('messieurs')));

View File

@ -6,23 +6,17 @@ namespace RectorPrefix202210\Doctrine\Inflector\Rules\French;
use RectorPrefix202210\Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault() : iterable
{
(yield new Pattern(''));

View File

@ -9,26 +9,20 @@ use RectorPrefix202210\Doctrine\Inflector\Rules\Transformation;
use RectorPrefix202210\Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular() : iterable
{
(yield new Transformation(new Pattern('/re$/i'), 'r'));
(yield new Transformation(new Pattern('/er$/i'), ''));
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural() : iterable
{
(yield new Transformation(new Pattern('/e$/i'), 'er'));
(yield new Transformation(new Pattern('/r$/i'), 're'));
(yield new Transformation(new Pattern('/$/'), 'er'));
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular() : iterable
{
(yield new Substitution(new Word('konto'), new Word('konti')));

View File

@ -6,23 +6,17 @@ namespace RectorPrefix202210\Doctrine\Inflector\Rules\NorwegianBokmal;
use RectorPrefix202210\Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault() : iterable
{
(yield new Pattern('barn'));

View File

@ -9,9 +9,7 @@ use RectorPrefix202210\Doctrine\Inflector\Rules\Transformation;
use RectorPrefix202210\Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular() : iterable
{
(yield new Transformation(new Pattern('/^(g|)ases$/i'), '\\1ás'));
@ -31,9 +29,7 @@ class Inflectible
(yield new Transformation(new Pattern('/^(á|gá)s$/i'), '\\1s'));
(yield new Transformation(new Pattern('/([^ê])s$/i'), '\\1'));
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural() : iterable
{
(yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\\1aes'));
@ -54,9 +50,7 @@ class Inflectible
(yield new Transformation(new Pattern('/(s)$/i'), '\\1'));
(yield new Transformation(new Pattern('/$/'), 's'));
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular() : iterable
{
(yield new Substitution(new Word('abdomen'), new Word('abdomens')));

View File

@ -6,23 +6,17 @@ namespace RectorPrefix202210\Doctrine\Inflector\Rules\Portuguese;
use RectorPrefix202210\Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault() : iterable
{
(yield new Pattern('tórax'));

View File

@ -9,9 +9,7 @@ use RectorPrefix202210\Doctrine\Inflector\Rules\Transformation;
use RectorPrefix202210\Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular() : iterable
{
(yield new Transformation(new Pattern('/ereses$/'), 'erés'));
@ -20,9 +18,7 @@ class Inflectible
(yield new Transformation(new Pattern('/es$/'), ''));
(yield new Transformation(new Pattern('/s$/'), ''));
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural() : iterable
{
(yield new Transformation(new Pattern('/ú([sn])$/i'), 'RectorPrefix202210\\u\\1es'));
@ -35,9 +31,7 @@ class Inflectible
(yield new Transformation(new Pattern('/([^aeéiou])$/i'), '\\1es'));
(yield new Transformation(new Pattern('/$/'), 's'));
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular() : iterable
{
(yield new Substitution(new Word('el'), new Word('los')));

View File

@ -6,23 +6,17 @@ namespace RectorPrefix202210\Doctrine\Inflector\Rules\Spanish;
use RectorPrefix202210\Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault() : iterable
{
(yield new Pattern('lunes'));

View File

@ -9,24 +9,18 @@ use RectorPrefix202210\Doctrine\Inflector\Rules\Transformation;
use RectorPrefix202210\Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular() : iterable
{
(yield new Transformation(new Pattern('/l[ae]r$/i'), ''));
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural() : iterable
{
(yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\\1ler'));
(yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\\1lar'));
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular() : iterable
{
(yield new Substitution(new Word('ben'), new Word('biz')));

View File

@ -6,23 +6,17 @@ namespace RectorPrefix202210\Doctrine\Inflector\Rules\Turkish;
use RectorPrefix202210\Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural() : iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault() : iterable
{
(yield new Pattern('lunes'));

View File

@ -17,19 +17,23 @@ class AssertTagMethodValueNode implements \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDo
public $method;
/** @var bool */
public $isNegated;
/** @var bool */
public $isEquality;
/** @var string (may be empty) */
public $description;
public function __construct(TypeNode $type, string $parameter, string $method, bool $isNegated, string $description)
public function __construct(TypeNode $type, string $parameter, string $method, bool $isNegated, string $description, bool $isEquality = \false)
{
$this->type = $type;
$this->parameter = $parameter;
$this->method = $method;
$this->isNegated = $isNegated;
$this->isEquality = $isEquality;
$this->description = $description;
}
public function __toString() : string
{
$isNegated = $this->isNegated ? '!' : '';
return trim("{$this->type} {$isNegated}{$this->parameter}->{$this->method}() {$this->description}");
$isEquality = $this->isEquality ? '=' : '';
return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->method}() {$this->description}");
}
}

View File

@ -17,19 +17,23 @@ class AssertTagPropertyValueNode implements \PHPStan\PhpDocParser\Ast\PhpDoc\Php
public $property;
/** @var bool */
public $isNegated;
/** @var bool */
public $isEquality;
/** @var string (may be empty) */
public $description;
public function __construct(TypeNode $type, string $parameter, string $property, bool $isNegated, string $description)
public function __construct(TypeNode $type, string $parameter, string $property, bool $isNegated, string $description, bool $isEquality = \false)
{
$this->type = $type;
$this->parameter = $parameter;
$this->property = $property;
$this->isNegated = $isNegated;
$this->isEquality = $isEquality;
$this->description = $description;
}
public function __toString() : string
{
$isNegated = $this->isNegated ? '!' : '';
return trim("{$this->type} {$isNegated}{$this->parameter}->{$this->property} {$this->description}");
$isEquality = $this->isEquality ? '=' : '';
return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->property} {$this->description}");
}
}

View File

@ -15,18 +15,22 @@ class AssertTagValueNode implements \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagVa
public $parameter;
/** @var bool */
public $isNegated;
/** @var bool */
public $isEquality;
/** @var string (may be empty) */
public $description;
public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description)
public function __construct(TypeNode $type, string $parameter, bool $isNegated, string $description, bool $isEquality = \false)
{
$this->type = $type;
$this->parameter = $parameter;
$this->isNegated = $isNegated;
$this->isEquality = $isEquality;
$this->description = $description;
}
public function __toString() : string
{
$isNegated = $this->isNegated ? '!' : '';
return trim("{$this->type} {$isNegated}{$this->parameter} {$this->description}");
$isEquality = $this->isEquality ? '=' : '';
return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter} {$this->description}");
}
}

View File

@ -5,10 +5,22 @@ namespace PHPStan\PhpDocParser\Parser;
use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;
use function chr;
use function hexdec;
use function octdec;
use function preg_replace_callback;
use function str_replace;
use function strtolower;
use function trim;
use function substr;
class ConstExprParser
{
private const REPLACEMENTS = ['\\' => '\\', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1b"];
/** @var bool */
private $unescapeStrings;
public function __construct(bool $unescapeStrings = \false)
{
$this->unescapeStrings = $unescapeStrings;
}
public function parse(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, bool $trimStrings = \false) : Ast\ConstExpr\ConstExprNode
{
if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) {
@ -21,17 +33,14 @@ class ConstExprParser
$tokens->next();
return new Ast\ConstExpr\ConstExprIntegerNode($value);
}
if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING, Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
$value = $tokens->currentTokenValue();
if ($trimStrings) {
$value = trim($tokens->currentTokenValue(), "'");
}
$tokens->next();
return new Ast\ConstExpr\ConstExprStringNode($value);
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
$value = $tokens->currentTokenValue();
if ($trimStrings) {
$value = trim($tokens->currentTokenValue(), '"');
if ($this->unescapeStrings) {
$value = self::unescapeString($value);
} else {
$value = substr($value, 1, -1);
}
}
$tokens->next();
return new Ast\ConstExpr\ConstExprStringNode($value);
@ -104,4 +113,52 @@ class ConstExprParser
}
return new Ast\ConstExpr\ConstExprArrayItemNode($key, $value);
}
private static function unescapeString(string $string) : string
{
$quote = $string[0];
if ($quote === '\'') {
return str_replace(['\\\\', '\\\''], ['\\', '\''], substr($string, 1, -1));
}
return self::parseEscapeSequences(substr($string, 1, -1), '"');
}
/**
* Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130
*/
private static function parseEscapeSequences(string $str, string $quote) : string
{
$str = str_replace('\\' . $quote, $quote, $str);
return preg_replace_callback('~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\\{([0-9a-fA-F]+)\\})~', static function ($matches) {
$str = $matches[1];
if (isset(self::REPLACEMENTS[$str])) {
return self::REPLACEMENTS[$str];
}
if ($str[0] === 'x' || $str[0] === 'X') {
return chr(hexdec(substr($str, 1)));
}
if ($str[0] === 'u') {
return self::codePointToUtf8(hexdec($matches[2]));
}
return chr(octdec($str));
}, $str);
}
/**
* Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154
*/
private static function codePointToUtf8(int $num) : string
{
if ($num <= 0x7f) {
return chr($num);
}
if ($num <= 0x7ff) {
return chr(($num >> 6) + 0xc0) . chr(($num & 0x3f) + 0x80);
}
if ($num <= 0xffff) {
return chr(($num >> 12) + 0xe0) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
}
if ($num <= 0x1fffff) {
return chr(($num >> 18) + 0xf0) . chr(($num >> 12 & 0x3f) + 0x80) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
}
// Invalid UTF-8 codepoint escape sequence: Codepoint too large
return "<EFBFBD>";
}
}

View File

@ -364,15 +364,16 @@ class PhpDocParser
private function parseAssertTagValue(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagValueNode
{
$isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED);
$isEquality = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
$type = $this->typeParser->parse($tokens);
$parameter = $this->parseAssertParameter($tokens);
$description = $this->parseOptionalDescription($tokens);
if (array_key_exists('method', $parameter)) {
return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description);
return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description, $isEquality);
} elseif (array_key_exists('property', $parameter)) {
return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description);
return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description, $isEquality);
}
return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description);
return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description, $isEquality);
}
/**
* @return array{parameter: string}|array{parameter: string, property: string}|array{parameter: string, method: string}

View File

@ -182,7 +182,7 @@ class TypeParser
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$elseType = $this->parse($tokens);
$elseType = $this->subParse($tokens);
return new Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated);
}
/** @phpstan-impure */
@ -203,7 +203,7 @@ class TypeParser
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$elseType = $this->parse($tokens);
$elseType = $this->subParse($tokens);
return new Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated);
}
/** @phpstan-impure */