2020-05-02 18:52:16 +00:00
|
|
|
<?php
|
|
|
|
|
2021-05-09 20:15:43 +00:00
|
|
|
declare (strict_types=1);
|
2020-05-02 21:25:24 +00:00
|
|
|
namespace Rector\Naming\Naming;
|
2020-05-02 18:52:16 +00:00
|
|
|
|
2021-05-29 17:17:11 +00:00
|
|
|
use RectorPrefix20210529\Nette\Utils\Strings;
|
2021-03-01 01:28:35 +00:00
|
|
|
use PhpParser\Node\Expr\PropertyFetch;
|
2021-01-20 11:41:35 +00:00
|
|
|
use PhpParser\Node\Stmt\ClassLike;
|
2020-09-22 20:22:10 +00:00
|
|
|
use PhpParser\Node\Stmt\ClassMethod;
|
|
|
|
use PhpParser\Node\Stmt\Property;
|
|
|
|
use PhpParser\Node\Stmt\Return_;
|
2021-02-28 07:47:48 +00:00
|
|
|
use PHPStan\Reflection\ReflectionProvider;
|
2020-07-01 21:41:49 +00:00
|
|
|
use PHPStan\Type\ObjectType;
|
2020-05-02 18:52:16 +00:00
|
|
|
use PHPStan\Type\StaticType;
|
|
|
|
use PHPStan\Type\Type;
|
|
|
|
use PHPStan\Type\TypeWithClassName;
|
2020-09-22 20:22:10 +00:00
|
|
|
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
2020-09-15 08:23:13 +00:00
|
|
|
use Rector\Naming\RectorNamingInflector;
|
2020-09-09 08:52:43 +00:00
|
|
|
use Rector\Naming\ValueObject\ExpectedName;
|
2020-09-22 20:22:10 +00:00
|
|
|
use Rector\NodeNameResolver\NodeNameResolver;
|
|
|
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
2021-01-15 20:27:36 +00:00
|
|
|
use Rector\NodeTypeResolver\NodeTypeResolver;
|
2020-07-19 18:19:25 +00:00
|
|
|
use Rector\PHPStanStaticTypeMapper\Utils\TypeUnwrapper;
|
2020-12-24 16:31:24 +00:00
|
|
|
use Rector\StaticTypeMapper\ValueObject\Type\SelfObjectType;
|
2020-08-01 16:59:36 +00:00
|
|
|
/**
|
|
|
|
* @deprecated
|
|
|
|
* @todo merge with very similar logic in
|
|
|
|
* @see VariableNaming
|
2021-03-12 22:20:25 +00:00
|
|
|
* @see \Rector\Tests\Naming\Naming\PropertyNamingTest
|
2020-08-01 16:59:36 +00:00
|
|
|
*/
|
2020-05-02 18:52:16 +00:00
|
|
|
final class PropertyNaming
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var string[]
|
|
|
|
*/
|
2020-06-29 20:01:32 +00:00
|
|
|
private const EXCLUDED_CLASSES = ['#Closure#', '#^Spl#', '#FileInfo#', '#^std#', '#Iterator#', '#SimpleXML#'];
|
2020-07-01 21:41:49 +00:00
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private const INTERFACE = 'Interface';
|
2020-09-22 20:22:10 +00:00
|
|
|
/**
|
|
|
|
* @see https://regex101.com/r/RDhBNR/1
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private const PREFIXED_CLASS_METHODS_REGEX = '#^(is|are|was|were|has|have|had|can)[A-Z].+#';
|
2020-09-23 09:16:40 +00:00
|
|
|
/**
|
|
|
|
* @var string
|
2020-10-29 18:04:33 +00:00
|
|
|
* @see https://regex101.com/r/U78rUF/1
|
2020-09-23 09:16:40 +00:00
|
|
|
*/
|
|
|
|
private const I_PREFIX_REGEX = '#^I[A-Z]#';
|
|
|
|
/**
|
|
|
|
* @see https://regex101.com/r/hnU5pm/2/
|
|
|
|
* @var string
|
|
|
|
*/
|
2020-12-24 22:16:27 +00:00
|
|
|
private const GET_PREFIX_REGEX = '#^get(?<root_name>[A-Z].+)#';
|
2020-07-19 18:19:25 +00:00
|
|
|
/**
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \Rector\PHPStanStaticTypeMapper\Utils\TypeUnwrapper
|
2020-07-19 18:19:25 +00:00
|
|
|
*/
|
|
|
|
private $typeUnwrapper;
|
2020-09-09 08:52:43 +00:00
|
|
|
/**
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \Rector\Naming\RectorNamingInflector
|
2020-09-09 08:52:43 +00:00
|
|
|
*/
|
2020-09-15 08:23:13 +00:00
|
|
|
private $rectorNamingInflector;
|
2020-09-22 20:22:10 +00:00
|
|
|
/**
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
|
2020-09-22 20:22:10 +00:00
|
|
|
*/
|
|
|
|
private $betterNodeFinder;
|
|
|
|
/**
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \Rector\NodeNameResolver\NodeNameResolver
|
2020-09-22 20:22:10 +00:00
|
|
|
*/
|
|
|
|
private $nodeNameResolver;
|
2021-01-15 20:27:36 +00:00
|
|
|
/**
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \Rector\NodeTypeResolver\NodeTypeResolver
|
2021-01-15 20:27:36 +00:00
|
|
|
*/
|
|
|
|
private $nodeTypeResolver;
|
2021-02-28 07:47:48 +00:00
|
|
|
/**
|
2021-05-10 23:39:21 +00:00
|
|
|
* @var \PHPStan\Reflection\ReflectionProvider
|
2021-02-28 07:47:48 +00:00
|
|
|
*/
|
|
|
|
private $reflectionProvider;
|
2021-05-10 22:23:08 +00:00
|
|
|
public function __construct(\Rector\PHPStanStaticTypeMapper\Utils\TypeUnwrapper $typeUnwrapper, \Rector\Naming\RectorNamingInflector $rectorNamingInflector, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver, \Rector\NodeTypeResolver\NodeTypeResolver $nodeTypeResolver, \PHPStan\Reflection\ReflectionProvider $reflectionProvider)
|
2021-05-09 20:15:43 +00:00
|
|
|
{
|
2020-07-19 18:19:25 +00:00
|
|
|
$this->typeUnwrapper = $typeUnwrapper;
|
2020-09-15 08:23:13 +00:00
|
|
|
$this->rectorNamingInflector = $rectorNamingInflector;
|
2020-09-22 20:22:10 +00:00
|
|
|
$this->betterNodeFinder = $betterNodeFinder;
|
|
|
|
$this->nodeNameResolver = $nodeNameResolver;
|
2021-01-15 20:27:36 +00:00
|
|
|
$this->nodeTypeResolver = $nodeTypeResolver;
|
2021-02-28 07:47:48 +00:00
|
|
|
$this->reflectionProvider = $reflectionProvider;
|
2020-09-09 08:52:43 +00:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
public function getExpectedNameFromMethodName(string $methodName) : ?\Rector\Naming\ValueObject\ExpectedName
|
2020-09-09 08:52:43 +00:00
|
|
|
{
|
2021-05-29 17:17:11 +00:00
|
|
|
$matches = \RectorPrefix20210529\Nette\Utils\Strings::match($methodName, self::GET_PREFIX_REGEX);
|
2020-09-09 08:52:43 +00:00
|
|
|
if ($matches === null) {
|
|
|
|
return null;
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
$originalName = \lcfirst($matches['root_name']);
|
2021-05-10 22:23:08 +00:00
|
|
|
return new \Rector\Naming\ValueObject\ExpectedName($originalName, $this->rectorNamingInflector->singularize($originalName));
|
2020-07-19 18:19:25 +00:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
public function getExpectedNameFromType(\PHPStan\Type\Type $type) : ?\Rector\Naming\ValueObject\ExpectedName
|
2020-05-02 18:52:16 +00:00
|
|
|
{
|
2020-12-06 00:27:00 +00:00
|
|
|
$type = $this->typeUnwrapper->unwrapNullableType($type);
|
2021-05-10 22:23:08 +00:00
|
|
|
if (!$type instanceof \PHPStan\Type\TypeWithClassName) {
|
2020-05-02 18:52:16 +00:00
|
|
|
return null;
|
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
if ($type instanceof \Rector\StaticTypeMapper\ValueObject\Type\SelfObjectType) {
|
2020-05-02 18:52:16 +00:00
|
|
|
return null;
|
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
if ($type instanceof \PHPStan\Type\StaticType) {
|
2020-05-02 18:52:16 +00:00
|
|
|
return null;
|
|
|
|
}
|
2021-01-15 20:27:36 +00:00
|
|
|
$className = $this->nodeTypeResolver->getFullyQualifiedClassName($type);
|
2020-05-02 18:52:16 +00:00
|
|
|
foreach (self::EXCLUDED_CLASSES as $excludedClass) {
|
2021-05-29 17:17:11 +00:00
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::match($className, $excludedClass)) {
|
2020-05-02 18:52:16 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$shortClassName = $this->resolveShortClassName($className);
|
|
|
|
$shortClassName = $this->removePrefixesAndSuffixes($shortClassName);
|
|
|
|
// if all is upper-cased, it should be lower-cased
|
2021-05-09 20:15:43 +00:00
|
|
|
if ($shortClassName === \strtoupper($shortClassName)) {
|
|
|
|
$shortClassName = \strtolower($shortClassName);
|
2020-05-02 18:52:16 +00:00
|
|
|
}
|
|
|
|
// remove "_"
|
2021-05-29 17:17:11 +00:00
|
|
|
$shortClassName = \RectorPrefix20210529\Nette\Utils\Strings::replace($shortClassName, '#_#', '');
|
2020-05-02 18:52:16 +00:00
|
|
|
$shortClassName = $this->normalizeUpperCase($shortClassName);
|
2020-08-30 16:55:16 +00:00
|
|
|
// prolong too short generic names with one namespace up
|
2020-09-09 08:52:43 +00:00
|
|
|
$originalName = $this->prolongIfTooShort($shortClassName, $className);
|
2021-05-10 22:23:08 +00:00
|
|
|
return new \Rector\Naming\ValueObject\ExpectedName($originalName, $this->rectorNamingInflector->singularize($originalName));
|
2020-05-02 18:52:16 +00:00
|
|
|
}
|
2020-07-01 21:41:49 +00:00
|
|
|
/**
|
|
|
|
* @param ObjectType|string $objectType
|
|
|
|
*/
|
2021-05-09 20:15:43 +00:00
|
|
|
public function fqnToVariableName($objectType) : string
|
2020-07-01 21:41:49 +00:00
|
|
|
{
|
|
|
|
$className = $this->resolveClassName($objectType);
|
|
|
|
$shortName = $this->fqnToShortName($className);
|
|
|
|
$shortName = $this->removeInterfaceSuffixPrefix($className, $shortName);
|
2020-08-30 16:55:16 +00:00
|
|
|
// prolong too short generic names with one namespace up
|
|
|
|
return $this->prolongIfTooShort($shortName, $className);
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
|
|
|
/**
|
2021-04-19 16:15:52 +00:00
|
|
|
* @changelog https://stackoverflow.com/a/2792045/1348344
|
2020-07-01 21:41:49 +00:00
|
|
|
*/
|
2021-05-09 20:15:43 +00:00
|
|
|
public function underscoreToName(string $underscoreName) : string
|
2020-07-01 21:41:49 +00:00
|
|
|
{
|
2021-05-09 20:15:43 +00:00
|
|
|
$uppercaseWords = \ucwords($underscoreName, '_');
|
|
|
|
$pascalCaseName = \str_replace('_', '', $uppercaseWords);
|
|
|
|
return \lcfirst($pascalCaseName);
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
public function getExpectedNameFromBooleanPropertyType(\PhpParser\Node\Stmt\Property $property) : ?string
|
2020-09-22 20:22:10 +00:00
|
|
|
{
|
|
|
|
$prefixedClassMethods = $this->getPrefixedClassMethods($property);
|
|
|
|
if ($prefixedClassMethods === []) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
$classMethods = $this->filterClassMethodsWithPropertyFetchReturnOnly($prefixedClassMethods, $property);
|
2021-05-09 20:15:43 +00:00
|
|
|
if (\count($classMethods) !== 1) {
|
2020-09-22 20:22:10 +00:00
|
|
|
return null;
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
$classMethod = \reset($classMethods);
|
2020-09-22 20:22:10 +00:00
|
|
|
return $this->nodeNameResolver->getName($classMethod);
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function resolveShortClassName(string $className) : string
|
2020-08-05 20:45:36 +00:00
|
|
|
{
|
2021-05-29 17:17:11 +00:00
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::contains($className, '\\')) {
|
|
|
|
return (string) \RectorPrefix20210529\Nette\Utils\Strings::after($className, '\\', -1);
|
2020-08-05 20:45:36 +00:00
|
|
|
}
|
|
|
|
return $className;
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function removePrefixesAndSuffixes(string $shortClassName) : string
|
2020-05-02 18:52:16 +00:00
|
|
|
{
|
|
|
|
// is SomeInterface
|
2021-05-29 17:17:11 +00:00
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::endsWith($shortClassName, self::INTERFACE)) {
|
|
|
|
$shortClassName = \RectorPrefix20210529\Nette\Utils\Strings::substring($shortClassName, 0, -\strlen(self::INTERFACE));
|
2020-05-02 18:52:16 +00:00
|
|
|
}
|
|
|
|
// is ISomeClass
|
|
|
|
if ($this->isPrefixedInterface($shortClassName)) {
|
2021-05-29 17:17:11 +00:00
|
|
|
$shortClassName = \RectorPrefix20210529\Nette\Utils\Strings::substring($shortClassName, 1);
|
2020-05-02 18:52:16 +00:00
|
|
|
}
|
|
|
|
// is AbstractClass
|
2021-05-29 17:17:11 +00:00
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::startsWith($shortClassName, 'Abstract')) {
|
|
|
|
$shortClassName = \RectorPrefix20210529\Nette\Utils\Strings::substring($shortClassName, \strlen('Abstract'));
|
2020-05-02 18:52:16 +00:00
|
|
|
}
|
|
|
|
return $shortClassName;
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function normalizeUpperCase(string $shortClassName) : string
|
2020-05-02 18:52:16 +00:00
|
|
|
{
|
|
|
|
// turns $SOMEUppercase => $someUppercase
|
2021-05-09 20:15:43 +00:00
|
|
|
for ($i = 0; $i <= \strlen($shortClassName); ++$i) {
|
|
|
|
if (\ctype_upper($shortClassName[$i]) && $this->isNumberOrUpper($shortClassName[$i + 1])) {
|
|
|
|
$shortClassName[$i] = \strtolower($shortClassName[$i]);
|
2020-05-02 18:52:16 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $shortClassName;
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function prolongIfTooShort(string $shortClassName, string $className) : string
|
2020-08-30 16:55:16 +00:00
|
|
|
{
|
2021-05-09 20:15:43 +00:00
|
|
|
if (\in_array($shortClassName, ['Factory', 'Repository'], \true)) {
|
2021-05-29 17:17:11 +00:00
|
|
|
$namespaceAbove = (string) \RectorPrefix20210529\Nette\Utils\Strings::after($className, '\\', -2);
|
|
|
|
$namespaceAbove = (string) \RectorPrefix20210529\Nette\Utils\Strings::before($namespaceAbove, '\\');
|
2021-05-09 20:15:43 +00:00
|
|
|
return \lcfirst($namespaceAbove) . $shortClassName;
|
2020-08-30 16:55:16 +00:00
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
return \lcfirst($shortClassName);
|
2020-08-30 16:55:16 +00:00
|
|
|
}
|
2020-08-05 20:45:36 +00:00
|
|
|
/**
|
|
|
|
* @param ObjectType|string $objectType
|
|
|
|
*/
|
2021-05-09 20:15:43 +00:00
|
|
|
private function resolveClassName($objectType) : string
|
2020-05-13 20:43:48 +00:00
|
|
|
{
|
2021-05-10 22:23:08 +00:00
|
|
|
if ($objectType instanceof \PHPStan\Type\ObjectType) {
|
2020-08-05 20:45:36 +00:00
|
|
|
return $objectType->getClassName();
|
2020-05-13 20:43:48 +00:00
|
|
|
}
|
2020-08-05 20:45:36 +00:00
|
|
|
return $objectType;
|
2020-05-13 20:43:48 +00:00
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function fqnToShortName(string $fqn) : string
|
2020-07-01 21:41:49 +00:00
|
|
|
{
|
2021-05-29 17:17:11 +00:00
|
|
|
if (!\RectorPrefix20210529\Nette\Utils\Strings::contains($fqn, '\\')) {
|
2020-07-01 21:41:49 +00:00
|
|
|
return $fqn;
|
|
|
|
}
|
|
|
|
/** @var string $lastNamePart */
|
2021-05-29 17:17:11 +00:00
|
|
|
$lastNamePart = \RectorPrefix20210529\Nette\Utils\Strings::after($fqn, '\\', -1);
|
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::endsWith($lastNamePart, self::INTERFACE)) {
|
|
|
|
return \RectorPrefix20210529\Nette\Utils\Strings::substring($lastNamePart, 0, -\strlen(self::INTERFACE));
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
|
|
|
return $lastNamePart;
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function removeInterfaceSuffixPrefix(string $className, string $shortName) : string
|
2020-07-01 21:41:49 +00:00
|
|
|
{
|
|
|
|
// remove interface prefix/suffix
|
2021-05-09 20:15:43 +00:00
|
|
|
if (!$this->reflectionProvider->hasClass($className)) {
|
2020-07-01 21:41:49 +00:00
|
|
|
return $shortName;
|
|
|
|
}
|
|
|
|
// starts with "I\W+"?
|
2021-05-29 17:17:11 +00:00
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::match($shortName, self::I_PREFIX_REGEX)) {
|
|
|
|
return \RectorPrefix20210529\Nette\Utils\Strings::substring($shortName, 1);
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
2021-05-29 17:17:11 +00:00
|
|
|
if (\RectorPrefix20210529\Nette\Utils\Strings::endsWith($shortName, self::INTERFACE)) {
|
|
|
|
return \RectorPrefix20210529\Nette\Utils\Strings::substring($shortName, -\strlen(self::INTERFACE));
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
|
|
|
return $shortName;
|
|
|
|
}
|
2020-09-22 20:22:10 +00:00
|
|
|
/**
|
|
|
|
* @return ClassMethod[]
|
|
|
|
*/
|
2021-05-10 22:23:08 +00:00
|
|
|
private function getPrefixedClassMethods(\PhpParser\Node\Stmt\Property $property) : array
|
2020-09-22 20:22:10 +00:00
|
|
|
{
|
2021-05-10 22:23:08 +00:00
|
|
|
$classLike = $property->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::CLASS_NODE);
|
|
|
|
if (!$classLike instanceof \PhpParser\Node\Stmt\ClassLike) {
|
2020-09-22 20:22:10 +00:00
|
|
|
return [];
|
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
$classMethods = $this->betterNodeFinder->findInstanceOf($classLike, \PhpParser\Node\Stmt\ClassMethod::class);
|
|
|
|
return \array_filter($classMethods, function (\PhpParser\Node\Stmt\ClassMethod $classMethod) : bool {
|
2021-03-01 01:28:35 +00:00
|
|
|
return $this->isBoolishMethodName($classMethod);
|
2020-09-22 20:22:10 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @param ClassMethod[] $prefixedClassMethods
|
|
|
|
* @return ClassMethod[]
|
|
|
|
*/
|
2021-05-10 22:23:08 +00:00
|
|
|
private function filterClassMethodsWithPropertyFetchReturnOnly(array $prefixedClassMethods, \PhpParser\Node\Stmt\Property $property) : array
|
2021-05-09 20:15:43 +00:00
|
|
|
{
|
2021-03-01 01:28:35 +00:00
|
|
|
$classMethodName = $this->nodeNameResolver->getName($property);
|
2021-05-10 22:23:08 +00:00
|
|
|
return \array_filter($prefixedClassMethods, function (\PhpParser\Node\Stmt\ClassMethod $classMethod) use($classMethodName) : bool {
|
2021-03-01 01:28:35 +00:00
|
|
|
return $this->doesClassMethodMatchReturnPropertyFetch($classMethod, $classMethodName);
|
2020-09-22 20:22:10 +00:00
|
|
|
});
|
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function isPrefixedInterface(string $shortClassName) : bool
|
2020-07-01 21:41:49 +00:00
|
|
|
{
|
2021-05-09 20:15:43 +00:00
|
|
|
if (\strlen($shortClassName) <= 3) {
|
|
|
|
return \false;
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
2021-05-29 17:17:11 +00:00
|
|
|
if (!\RectorPrefix20210529\Nette\Utils\Strings::startsWith($shortClassName, 'I')) {
|
2021-05-09 20:15:43 +00:00
|
|
|
return \false;
|
2020-08-05 20:45:36 +00:00
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
if (!\ctype_upper($shortClassName[1])) {
|
|
|
|
return \false;
|
2020-12-19 15:24:53 +00:00
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
return \ctype_lower($shortClassName[2]);
|
2020-08-05 20:45:36 +00:00
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
private function isNumberOrUpper(string $char) : bool
|
2020-08-05 20:45:36 +00:00
|
|
|
{
|
2021-05-09 20:15:43 +00:00
|
|
|
if (\ctype_upper($char)) {
|
|
|
|
return \true;
|
2020-08-05 20:45:36 +00:00
|
|
|
}
|
2021-05-09 20:15:43 +00:00
|
|
|
return \ctype_digit($char);
|
2020-07-01 21:41:49 +00:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
private function isBoolishMethodName(\PhpParser\Node\Stmt\ClassMethod $classMethod) : bool
|
2021-03-01 01:28:35 +00:00
|
|
|
{
|
|
|
|
$classMethodName = $this->nodeNameResolver->getName($classMethod);
|
2021-05-29 17:17:11 +00:00
|
|
|
return (bool) \RectorPrefix20210529\Nette\Utils\Strings::match($classMethodName, self::PREFIXED_CLASS_METHODS_REGEX);
|
2021-03-01 01:28:35 +00:00
|
|
|
}
|
2021-05-10 22:23:08 +00:00
|
|
|
private function doesClassMethodMatchReturnPropertyFetch(\PhpParser\Node\Stmt\ClassMethod $classMethod, string $currentClassMethodName) : bool
|
2021-05-09 20:15:43 +00:00
|
|
|
{
|
2021-03-01 01:28:35 +00:00
|
|
|
$possibleReturn = $classMethod->stmts[0] ?? null;
|
2021-05-10 22:23:08 +00:00
|
|
|
if (!$possibleReturn instanceof \PhpParser\Node\Stmt\Return_) {
|
2021-05-09 20:15:43 +00:00
|
|
|
return \false;
|
2021-03-01 01:28:35 +00:00
|
|
|
}
|
|
|
|
$node = $possibleReturn->expr;
|
2021-05-10 22:23:08 +00:00
|
|
|
if (!$node instanceof \PhpParser\Node\Expr\PropertyFetch) {
|
2021-05-09 20:15:43 +00:00
|
|
|
return \false;
|
2021-03-01 01:28:35 +00:00
|
|
|
}
|
|
|
|
return $this->nodeNameResolver->isName($node->name, $currentClassMethodName);
|
|
|
|
}
|
2020-05-02 18:52:16 +00:00
|
|
|
}
|