Updated Rector to commit db2e76b99c

db2e76b99c load stubs in config
This commit is contained in:
Tomas Votruba 2021-07-22 23:37:17 +00:00
parent 2f9cc5d362
commit a3e534ff19
121 changed files with 2361 additions and 1957 deletions

View File

@ -7,7 +7,7 @@
],
"require": {
"php": "^7.1|^8.0",
"phpstan/phpstan": "0.12.91"
"phpstan/phpstan": "0.12.93"
},
"autoload": {
"files": [

View File

@ -0,0 +1,15 @@
<?php
declare (strict_types=1);
namespace RectorPrefix20210722;
use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\DowngradePhp81\Rector\ClassConst\DowngradeFinalizePublicClassConstantRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $containerConfigurator) : void {
$parameters = $containerConfigurator->parameters();
$parameters->set(\Rector\Core\Configuration\Option::PHP_VERSION_FEATURES, \Rector\Core\ValueObject\PhpVersion::PHP_74);
$services = $containerConfigurator->services();
$services->set(\Rector\DowngradePhp81\Rector\ClassConst\DowngradeFinalizePublicClassConstantRector::class);
};

View File

@ -4,6 +4,7 @@ declare (strict_types=1);
namespace RectorPrefix20210722;
use Rector\Php81\Rector\Class_\MyCLabsClassToEnumRector;
use Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector;
use Rector\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
@ -12,4 +13,6 @@ return static function (\Symfony\Component\DependencyInjection\Loader\Configurat
$services->set(\Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class);
$services->set(\Rector\Php81\Rector\Class_\MyCLabsClassToEnumRector::class);
$services->set(\Rector\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector::class);
$services->set(\Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class);
$services->set(\Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class);
};

View File

@ -51,6 +51,7 @@ final class DependencyResolver
if ($mutatingScope->getFile() === $dependencyFile) {
continue;
}
// only work with files that we've analysed
if (!\in_array($dependencyFile, $analysedFileAbsolutesPaths, \true)) {
continue;
}

View File

@ -0,0 +1,34 @@
<?php
declare (strict_types=1);
namespace Rector\NodeTypeResolver\NodeTypeCorrector;
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\Type;
final class AccessoryNonEmptyStringTypeCorrector
{
/**
* @return \PHPStan\Type\Type|\PHPStan\Type\IntersectionType
*/
public function correct(\PHPStan\Type\Type $mainType)
{
if (!$mainType instanceof \PHPStan\Type\IntersectionType) {
return $mainType;
}
if (!$mainType->isSubTypeOf(new \PHPStan\Type\Accessory\AccessoryNonEmptyStringType())->yes()) {
return $mainType;
}
$clearIntersectionedTypes = [];
foreach ($mainType->getTypes() as $intersectionedType) {
if ($intersectionedType instanceof \PHPStan\Type\Accessory\AccessoryNonEmptyStringType) {
continue;
}
$clearIntersectionedTypes[] = $intersectionedType;
}
if (\count($clearIntersectionedTypes) === 1) {
return $clearIntersectionedTypes[0];
}
return new \PHPStan\Type\IntersectionType($clearIntersectionedTypes);
}
}

View File

@ -42,6 +42,7 @@ use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeCorrector\HasOffsetTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeResolver\IdentifierTypeResolver;
@ -79,6 +80,10 @@ final class NodeTypeResolver
* @var \Rector\NodeTypeResolver\NodeTypeCorrector\HasOffsetTypeCorrector
*/
private $hasOffsetTypeCorrector;
/**
* @var \Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector
*/
private $accessoryNonEmptyStringTypeCorrector;
/**
* @var \Rector\NodeTypeResolver\NodeTypeResolver\IdentifierTypeResolver
*/
@ -90,13 +95,14 @@ final class NodeTypeResolver
/**
* @param NodeTypeResolverInterface[] $nodeTypeResolvers
*/
public function __construct(\Rector\TypeDeclaration\PHPStan\Type\ObjectTypeSpecifier $objectTypeSpecifier, \Rector\Core\NodeAnalyzer\ClassAnalyzer $classAnalyzer, \Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector $genericClassStringTypeCorrector, \PHPStan\Reflection\ReflectionProvider $reflectionProvider, \Rector\NodeTypeResolver\NodeTypeCorrector\HasOffsetTypeCorrector $hasOffsetTypeCorrector, \Rector\NodeTypeResolver\NodeTypeResolver\IdentifierTypeResolver $identifierTypeResolver, \Rector\Core\Configuration\RenamedClassesDataCollector $renamedClassesDataCollector, array $nodeTypeResolvers)
public function __construct(\Rector\TypeDeclaration\PHPStan\Type\ObjectTypeSpecifier $objectTypeSpecifier, \Rector\Core\NodeAnalyzer\ClassAnalyzer $classAnalyzer, \Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector $genericClassStringTypeCorrector, \PHPStan\Reflection\ReflectionProvider $reflectionProvider, \Rector\NodeTypeResolver\NodeTypeCorrector\HasOffsetTypeCorrector $hasOffsetTypeCorrector, \Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector, \Rector\NodeTypeResolver\NodeTypeResolver\IdentifierTypeResolver $identifierTypeResolver, \Rector\Core\Configuration\RenamedClassesDataCollector $renamedClassesDataCollector, array $nodeTypeResolvers)
{
$this->objectTypeSpecifier = $objectTypeSpecifier;
$this->classAnalyzer = $classAnalyzer;
$this->genericClassStringTypeCorrector = $genericClassStringTypeCorrector;
$this->reflectionProvider = $reflectionProvider;
$this->hasOffsetTypeCorrector = $hasOffsetTypeCorrector;
$this->accessoryNonEmptyStringTypeCorrector = $accessoryNonEmptyStringTypeCorrector;
$this->identifierTypeResolver = $identifierTypeResolver;
$this->renamedClassesDataCollector = $renamedClassesDataCollector;
foreach ($nodeTypeResolvers as $nodeTypeResolver) {
@ -144,6 +150,7 @@ final class NodeTypeResolver
{
$type = $this->resolveByNodeTypeResolvers($node);
if ($type !== null) {
$type = $this->accessoryNonEmptyStringTypeCorrector->correct($type);
return $this->hasOffsetTypeCorrector->correct($type);
}
$scope = $node->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::SCOPE);
@ -168,6 +175,7 @@ final class NodeTypeResolver
return new \PHPStan\Type\ObjectWithoutClassType();
}
$type = $scope->getType($node);
$type = $this->accessoryNonEmptyStringTypeCorrector->correct($type);
// hot fix for phpstan not resolving chain method calls
if (!$node instanceof \PhpParser\Node\Expr\MethodCall) {
return $type;
@ -224,7 +232,7 @@ final class NodeTypeResolver
if ($staticType instanceof \PHPStan\Type\ObjectType) {
return $this->objectTypeSpecifier->narrowToFullyQualifiedOrAliasedObjectType($node, $staticType);
}
return $staticType;
return $this->accessoryNonEmptyStringTypeCorrector->correct($staticType);
}
public function isNumberType(\PhpParser\Node $node) : bool
{

View File

@ -0,0 +1,42 @@
<?php
declare (strict_types=1);
namespace Rector\PHPStanStaticTypeMapper\TypeMapper;
use PhpParser\Node;
use PhpParser\Node\Name;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
use PHPStan\Type\Type;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
/**
* @implements TypeMapperInterface<AccessoryNonEmptyStringType>
*/
final class AccessoryNonEmptyStringTypeMapper implements \Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface
{
/**
* @return class-string<Type>
*/
public function getNodeClass() : string
{
return \PHPStan\Type\Accessory\AccessoryNonEmptyStringType::class;
}
/**
* @param \PHPStan\Type\Type $type
* @param \Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind $typeKind
*/
public function mapToPHPStanPhpDocTypeNode($type, $typeKind) : \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
return new \PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode('string');
}
/**
* @param \PHPStan\Type\Type $type
* @param \Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind $typeKind
*/
public function mapToPhpParserNode($type, $typeKind) : ?\PhpParser\Node
{
return new \PhpParser\Node\Name('string');
}
}

View File

@ -55,7 +55,7 @@ abstract class AbstractRectorTestCase extends \Rector\Testing\PHPUnit\AbstractTe
// speed up
@\ini_set('memory_limit', '-1');
// include local files
if (\file_exists(__DIR__ . '/../../../preload.php')) {
if (\file_exists(__DIR__ . '/../../../preload.php') && \file_exists(__DIR__ . '/../../../vendor')) {
require_once __DIR__ . '/../../../preload.php';
}
$configFileInfo = new \Symplify\SmartFileSystem\SmartFileInfo($this->provideConfigFilePath());

View File

@ -221,6 +221,7 @@ require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulat
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php';

View File

@ -0,0 +1,52 @@
<?php
declare (strict_types=1);
namespace Rector\DowngradePhp81\Rector\ClassConst;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassConst;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://php.watch/versions/8.1/final-class-const
*
* @see \Rector\Tests\DowngradePhp81\Rector\ClassConst\DowngradeFinalizePublicClassConstantRector\DowngradeFinalizePublicClassConstantRectorTest
*/
final class DowngradeFinalizePublicClassConstantRector extends \Rector\Core\Rector\AbstractRector
{
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Remove final from class constants', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
final public const NAME = 'value';
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public const NAME = 'value';
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\ClassConst::class];
}
/**
* @param ClassConst $node
*/
public function refactor(\PhpParser\Node $node) : ?\PhpParser\Node
{
if (!$node->isFinal()) {
return null;
}
$this->visibilityManipulator->removeFinal($node);
return $node;
}
}

View File

@ -13,7 +13,7 @@ use Rector\Php70\Exception\InvalidEregException;
final class EregToPcreTransformer
{
/**
* @var string[]
* @var array<string, string>
*/
private const CHARACTER_CLASS_MAP = [
':alnum:' => '[:alnum:]',

View File

@ -0,0 +1,58 @@
<?php
declare (strict_types=1);
namespace Rector\Php81\Rector\ClassConst;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassConst;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://php.watch/versions/8.1/final-class-const
*
* @see \Rector\Tests\Php81\Rector\ClassConst\FinalizePublicClassConstantRector\FinalizePublicClassConstantRectorTest
*/
final class FinalizePublicClassConstantRector extends \Rector\Core\Rector\AbstractRector
{
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Add final to constants that', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public const NAME = 'value';
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public final const NAME = 'value';
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\ClassConst::class];
}
/**
* @param ClassConst $node
*/
public function refactor(\PhpParser\Node $node) : ?\PhpParser\Node
{
if ($node->isPrivate()) {
return null;
}
if ($node->isProtected()) {
return null;
}
if ($node->isFinal()) {
return null;
}
$this->visibilityManipulator->makeFinal($node);
return $node;
}
}

View File

@ -0,0 +1,104 @@
<?php
declare (strict_types=1);
namespace Rector\Php81\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use Rector\Core\NodeManipulator\PropertyManipulator;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @changelog https://wiki.php.net/rfc/readonly_properties_v2
*
* @see \Rector\Tests\Php81\Rector\Property\ReadOnlyPropertyRector\ReadOnlyPropertyRectorTest
*/
final class ReadOnlyPropertyRector extends \Rector\Core\Rector\AbstractRector
{
/**
* @var \Rector\Core\NodeManipulator\PropertyManipulator
*/
private $propertyManipulator;
public function __construct(\Rector\Core\NodeManipulator\PropertyManipulator $propertyManipulator)
{
$this->propertyManipulator = $propertyManipulator;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Decorate read-only property with `readonly` attribute', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function __construct(
private string $name
) {
}
public function getName()
{
return $this->name;
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public function __construct(
private readonly string $name
) {
}
public function getName()
{
return $this->name;
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\Property::class, \PhpParser\Node\Param::class];
}
/**
* @param Property|Param $node
*/
public function refactor(\PhpParser\Node $node) : ?\PhpParser\Node
{
if ($node instanceof \PhpParser\Node\Param) {
return $this->refactorParam($node);
}
// 1. is property read-only?
if ($this->propertyManipulator->isPropertyChangeableExceptConstructor($node)) {
return null;
}
if ($node->isReadonly()) {
return null;
}
$this->visibilityManipulator->makeReadonly($node);
return $node;
}
/**
* @return \PhpParser\Node\Param|null
*/
private function refactorParam(\PhpParser\Node\Param $param)
{
if ($param->flags === 0) {
return null;
}
// promoted property?
if ($this->propertyManipulator->isPropertyChangeableExceptConstructor($param)) {
return null;
}
if ($this->visibilityManipulator->hasVisibility($param, \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY)) {
return null;
}
$this->visibilityManipulator->makeReadonly($param);
return $param;
}
}

View File

@ -3,21 +3,22 @@
declare (strict_types=1);
namespace Rector\Privatization\NodeManipulator;
use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\Core\Exception\InvalidNodeTypeException;
use Rector\Core\ValueObject\Visibility;
use RectorPrefix20210722\Webmozart\Assert\Assert;
final class VisibilityManipulator
{
/**
* @var array<class-string<Stmt>>
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Param $node
*/
private const ALLOWED_NODE_TYPES = [\PhpParser\Node\Stmt\ClassMethod::class, \PhpParser\Node\Stmt\Property::class, \PhpParser\Node\Stmt\ClassConst::class, \PhpParser\Node\Stmt\Class_::class];
public function hasVisibility($node, int $visibility) : bool
{
return (bool) ($node->flags & $visibility);
}
/**
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst $node
*/
@ -43,7 +44,7 @@ final class VisibilityManipulator
$node->flags -= \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC;
}
/**
* @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod $node
* @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\ClassConst $node
*/
public function makeFinal($node) : void
{
@ -65,7 +66,6 @@ final class VisibilityManipulator
*/
public function removeVisibility($node) : void
{
$this->ensureIsClassMethodOrProperty($node, __METHOD__);
// no modifier
if ($node->flags === 0) {
return;
@ -109,27 +109,27 @@ final class VisibilityManipulator
{
$this->replaceVisibilityFlag($node, \Rector\Core\ValueObject\Visibility::PRIVATE);
}
public function removeFinal(\PhpParser\Node\Stmt\Class_ $class) : void
/**
* @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassConst $node
*/
public function removeFinal($node) : void
{
$class->flags -= \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL;
$node->flags -= \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL;
}
/**
* @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst $node
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $node
*/
public function makeReadonly($node) : void
{
$this->addVisibilityFlag($node, \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY);
}
/**
* @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst|\PhpParser\Node\Param $node
*/
private function addVisibilityFlag($node, int $visibility) : void
{
$this->ensureIsClassMethodOrProperty($node, __METHOD__);
$node->flags |= $visibility;
}
private function ensureIsClassMethodOrProperty(\PhpParser\Node $node, string $location) : void
{
foreach (self::ALLOWED_NODE_TYPES as $allowedNodeType) {
if (\is_a($node, $allowedNodeType, \true)) {
return;
}
}
throw new \Rector\Core\Exception\InvalidNodeTypeException(\sprintf('"%s" only accepts "%s" types. "%s" given.', $location, \implode('", "', self::ALLOWED_NODE_TYPES), \get_class($node)));
}
/**
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Property|\PhpParser\Node\Stmt\ClassConst $node
*/

View File

@ -16,11 +16,11 @@ final class VersionResolver
/**
* @var string
*/
public const PACKAGE_VERSION = '178f3f643c433c41cbcb05995eaeba9a25a427b7';
public const PACKAGE_VERSION = 'db2e76b99cfca0c66d190410f2011a073451e7dc';
/**
* @var string
*/
public const RELEASE_DATE = '2021-07-22 20:30:23';
public const RELEASE_DATE = '2021-07-23 01:26:20';
public static function resolvePackageVersion() : string
{
$process = new \RectorPrefix20210722\Symfony\Component\Process\Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);

View File

@ -16,16 +16,23 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PHPStan\Reflection\ParametersAcceptorSelector;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\ReadWrite\Guard\VariableToConstantGuard;
use Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer;
use RectorPrefix20210722\Symplify\PackageBuilder\Php\TypeChecker;
/**
* For inspiration to improve this service,
* @see examples of variable modifications in https://wiki.php.net/rfc/readonly_properties_v2#proposal
*/
final class PropertyManipulator
{
/**
@ -60,7 +67,11 @@ final class PropertyManipulator
* @var \Rector\Core\Reflection\ReflectionResolver
*/
private $reflectionResolver;
public function __construct(\Rector\Core\NodeManipulator\AssignManipulator $assignManipulator, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\ReadWrite\Guard\VariableToConstantGuard $variableToConstantGuard, \Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer $readWritePropertyAnalyzer, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \RectorPrefix20210722\Symplify\PackageBuilder\Php\TypeChecker $typeChecker, \Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder $propertyFetchFinder, \Rector\Core\Reflection\ReflectionResolver $reflectionResolver)
/**
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
public function __construct(\Rector\Core\NodeManipulator\AssignManipulator $assignManipulator, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\ReadWrite\Guard\VariableToConstantGuard $variableToConstantGuard, \Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer $readWritePropertyAnalyzer, \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory $phpDocInfoFactory, \RectorPrefix20210722\Symplify\PackageBuilder\Php\TypeChecker $typeChecker, \Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder $propertyFetchFinder, \Rector\Core\Reflection\ReflectionResolver $reflectionResolver, \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver)
{
$this->assignManipulator = $assignManipulator;
$this->betterNodeFinder = $betterNodeFinder;
@ -70,6 +81,7 @@ final class PropertyManipulator
$this->typeChecker = $typeChecker;
$this->propertyFetchFinder = $propertyFetchFinder;
$this->reflectionResolver = $reflectionResolver;
$this->nodeNameResolver = $nodeNameResolver;
}
/**
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $propertyOrPromotedParam
@ -81,6 +93,7 @@ final class PropertyManipulator
if ($phpDocInfo->hasByAnnotationClasses(['Doctrine\\ORM\\Mapping\\Id', 'Doctrine\\ORM\\Mapping\\Column', 'Doctrine\\ORM\\Mapping\\OneToMany', 'Doctrine\\ORM\\Mapping\\ManyToMany', 'Doctrine\\ORM\\Mapping\\ManyToOne', 'Doctrine\\ORM\\Mapping\\OneToOne', 'JMS\\Serializer\\Annotation\\Type'])) {
return \true;
}
// $propertyOrPromotedParam->attrGroups
$privatePropertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($propertyOrPromotedParam);
foreach ($privatePropertyFetches as $privatePropertyFetch) {
if ($this->readWritePropertyAnalyzer->isRead($privatePropertyFetch)) {
@ -100,6 +113,27 @@ final class PropertyManipulator
return $node->name instanceof \PhpParser\Node\Expr;
});
}
/**
* @param \PhpParser\Node\Stmt\Property|\PhpParser\Node\Param $propertyOrParam
*/
public function isPropertyChangeableExceptConstructor($propertyOrParam) : bool
{
$propertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($propertyOrParam);
foreach ($propertyFetches as $propertyFetch) {
if ($this->isChangeableContext($propertyFetch)) {
return \true;
}
// skip for constructor? it is allowed to set value in constructor method
$classMethod = $propertyFetch->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::METHOD_NODE);
if ($classMethod instanceof \PhpParser\Node\Stmt\ClassMethod && $this->nodeNameResolver->isName($classMethod->name, \Rector\Core\ValueObject\MethodName::CONSTRUCT)) {
continue;
}
if ($this->assignManipulator->isLeftPartOfAssign($propertyFetch)) {
return \true;
}
}
return \false;
}
public function isPropertyChangeable(\PhpParser\Node\Stmt\Property $property) : bool
{
$propertyFetches = $this->propertyFetchFinder->findPrivatePropertyFetches($property);
@ -107,15 +141,18 @@ final class PropertyManipulator
if ($this->isChangeableContext($propertyFetch)) {
return \true;
}
if ($this->assignManipulator->isLeftPartOfAssign($propertyFetch)) {
return \true;
}
}
return \false;
}
/**
* @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $expr
* @param \PhpParser\Node\Expr\PropertyFetch|\PhpParser\Node\Expr\StaticPropertyFetch $propertyFetch
*/
private function isChangeableContext($expr) : bool
private function isChangeableContext($propertyFetch) : bool
{
$parent = $expr->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE);
$parent = $propertyFetch->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE);
if (!$parent instanceof \PhpParser\Node) {
return \false;
}
@ -135,7 +172,7 @@ final class PropertyManipulator
return $this->isFoundByRefParam($caller);
}
}
return $this->assignManipulator->isLeftPartOfAssign($expr);
return \false;
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node

View File

@ -30,10 +30,10 @@ final class ProcessResultFactory
$fileDiffs = [];
$errors = [];
foreach ($files as $file) {
$errors = \array_merge($errors, $file->getErrors());
if ($file->getFileDiff() === null) {
continue;
}
$errors = \array_merge($errors, $file->getErrors());
$fileDiffs[] = $file->getFileDiff();
}
return new \Rector\Core\ValueObject\ProcessResult($fileDiffs, $errors, $this->removedAndAddedFilesCollector->getAddedFileCount(), $this->removedAndAddedFilesCollector->getRemovedFilesCount(), $this->nodesToRemoveCollector->getCount());

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2::getLoader();
return ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c::getLoader();

View File

@ -117,6 +117,7 @@ return array(
'PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php',
'PhpParser\\NameContext' => $vendorDir . '/nikic/php-parser/lib/PhpParser/NameContext.php',
@ -2177,6 +2178,7 @@ return array(
'Rector\\DowngradePhp80\\Rector\\StaticCall\\DowngradePhpTokenRector' => $baseDir . '/rules/DowngradePhp80/Rector/StaticCall/DowngradePhpTokenRector.php',
'Rector\\DowngradePhp80\\Reflection\\DefaultParameterValueResolver' => $baseDir . '/rules/DowngradePhp80/Reflection/DefaultParameterValueResolver.php',
'Rector\\DowngradePhp80\\ValueObject\\DowngradeAttributeToAnnotation' => $baseDir . '/rules/DowngradePhp80/ValueObject/DowngradeAttributeToAnnotation.php',
'Rector\\DowngradePhp81\\Rector\\ClassConst\\DowngradeFinalizePublicClassConstantRector' => $baseDir . '/rules/DowngradePhp81/Rector/ClassConst/DowngradeFinalizePublicClassConstantRector.php',
'Rector\\EarlyReturn\\NodeFactory\\InvertedIfFactory' => $baseDir . '/rules/EarlyReturn/NodeFactory/InvertedIfFactory.php',
'Rector\\EarlyReturn\\NodeTransformer\\ConditionInverter' => $baseDir . '/rules/EarlyReturn/NodeTransformer/ConditionInverter.php',
'Rector\\EarlyReturn\\Rector\\Foreach_\\ChangeNestedForeachIfsToEarlyContinueRector' => $baseDir . '/rules/EarlyReturn/Rector/Foreach_/ChangeNestedForeachIfsToEarlyContinueRector.php',
@ -2439,6 +2441,7 @@ return array(
'Rector\\NodeTypeResolver\\Exception\\MissingTagException' => $baseDir . '/packages/NodeTypeResolver/Exception/MissingTagException.php',
'Rector\\NodeTypeResolver\\MethodParameterTypeResolver' => $baseDir . '/packages/NodeTypeResolver/MethodParameterTypeResolver.php',
'Rector\\NodeTypeResolver\\NodeScopeAndMetadataDecorator' => $baseDir . '/packages/NodeTypeResolver/NodeScopeAndMetadataDecorator.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\AccessoryNonEmptyStringTypeCorrector' => $baseDir . '/packages/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyStringTypeCorrector.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\GenericClassStringTypeCorrector' => $baseDir . '/packages/NodeTypeResolver/NodeTypeCorrector/GenericClassStringTypeCorrector.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\HasOffsetTypeCorrector' => $baseDir . '/packages/NodeTypeResolver/NodeTypeCorrector/HasOffsetTypeCorrector.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\PregMatchTypeCorrector' => $baseDir . '/packages/NodeTypeResolver/NodeTypeCorrector/PregMatchTypeCorrector.php',
@ -2521,6 +2524,7 @@ return array(
'Rector\\PHPStanStaticTypeMapper\\TypeAnalyzer\\BoolUnionTypeAnalyzer' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeAnalyzer/BoolUnionTypeAnalyzer.php',
'Rector\\PHPStanStaticTypeMapper\\TypeAnalyzer\\UnionTypeAnalyzer' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php',
'Rector\\PHPStanStaticTypeMapper\\TypeAnalyzer\\UnionTypeCommonTypeNarrower' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeCommonTypeNarrower.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\AccessoryNonEmptyStringTypeMapper' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeMapper/AccessoryNonEmptyStringTypeMapper.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\ArrayTypeMapper' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\BooleanTypeMapper' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeMapper/BooleanTypeMapper.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\CallableTypeMapper' => $baseDir . '/packages/PHPStanStaticTypeMapper/TypeMapper/CallableTypeMapper.php',
@ -2756,8 +2760,10 @@ return array(
'Rector\\Php80\\ValueObject\\PropertyPromotionCandidate' => $baseDir . '/rules/Php80/ValueObject/PropertyPromotionCandidate.php',
'Rector\\Php80\\ValueObject\\StrStartsWith' => $baseDir . '/rules/Php80/ValueObject/StrStartsWith.php',
'Rector\\Php81\\NodeFactory\\EnumFactory' => $baseDir . '/rules/Php81/NodeFactory/EnumFactory.php',
'Rector\\Php81\\Rector\\ClassConst\\FinalizePublicClassConstantRector' => $baseDir . '/rules/Php81/Rector/ClassConst/FinalizePublicClassConstantRector.php',
'Rector\\Php81\\Rector\\Class_\\MyCLabsClassToEnumRector' => $baseDir . '/rules/Php81/Rector/Class_/MyCLabsClassToEnumRector.php',
'Rector\\Php81\\Rector\\MethodCall\\MyCLabsMethodCallToEnumConstRector' => $baseDir . '/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php',
'Rector\\Php81\\Rector\\Property\\ReadOnlyPropertyRector' => $baseDir . '/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php',
'Rector\\PhpAttribute\\NodeAnalyzer\\NamedArgumentsResolver' => $baseDir . '/packages/PhpAttribute/NodeAnalyzer/NamedArgumentsResolver.php',
'Rector\\PhpAttribute\\Printer\\DoctrineAnnotationFactory' => $baseDir . '/packages/PhpAttribute/Printer/DoctrineAnnotationFactory.php',
'Rector\\PhpAttribute\\Printer\\PhpAttributeGroupFactory' => $baseDir . '/packages/PhpAttribute/Printer/PhpAttributeGroupFactory.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2
class ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c
{
private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit735eb307678b1bf985488aa190e180a2::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInitb51d21490f998eb5d663e8d169cd873c::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
@ -42,19 +42,19 @@ class ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit735eb307678b1bf985488aa190e180a2::$files;
$includeFiles = Composer\Autoload\ComposerStaticInitb51d21490f998eb5d663e8d169cd873c::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire735eb307678b1bf985488aa190e180a2($fileIdentifier, $file);
composerRequireb51d21490f998eb5d663e8d169cd873c($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire735eb307678b1bf985488aa190e180a2($fileIdentifier, $file)
function composerRequireb51d21490f998eb5d663e8d169cd873c($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit735eb307678b1bf985488aa190e180a2
class ComposerStaticInitb51d21490f998eb5d663e8d169cd873c
{
public static $files = array (
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
@ -472,6 +472,7 @@ class ComposerStaticInit735eb307678b1bf985488aa190e180a2
'PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php',
'PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php',
'PhpParser\\NameContext' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/NameContext.php',
@ -2532,6 +2533,7 @@ class ComposerStaticInit735eb307678b1bf985488aa190e180a2
'Rector\\DowngradePhp80\\Rector\\StaticCall\\DowngradePhpTokenRector' => __DIR__ . '/../..' . '/rules/DowngradePhp80/Rector/StaticCall/DowngradePhpTokenRector.php',
'Rector\\DowngradePhp80\\Reflection\\DefaultParameterValueResolver' => __DIR__ . '/../..' . '/rules/DowngradePhp80/Reflection/DefaultParameterValueResolver.php',
'Rector\\DowngradePhp80\\ValueObject\\DowngradeAttributeToAnnotation' => __DIR__ . '/../..' . '/rules/DowngradePhp80/ValueObject/DowngradeAttributeToAnnotation.php',
'Rector\\DowngradePhp81\\Rector\\ClassConst\\DowngradeFinalizePublicClassConstantRector' => __DIR__ . '/../..' . '/rules/DowngradePhp81/Rector/ClassConst/DowngradeFinalizePublicClassConstantRector.php',
'Rector\\EarlyReturn\\NodeFactory\\InvertedIfFactory' => __DIR__ . '/../..' . '/rules/EarlyReturn/NodeFactory/InvertedIfFactory.php',
'Rector\\EarlyReturn\\NodeTransformer\\ConditionInverter' => __DIR__ . '/../..' . '/rules/EarlyReturn/NodeTransformer/ConditionInverter.php',
'Rector\\EarlyReturn\\Rector\\Foreach_\\ChangeNestedForeachIfsToEarlyContinueRector' => __DIR__ . '/../..' . '/rules/EarlyReturn/Rector/Foreach_/ChangeNestedForeachIfsToEarlyContinueRector.php',
@ -2794,6 +2796,7 @@ class ComposerStaticInit735eb307678b1bf985488aa190e180a2
'Rector\\NodeTypeResolver\\Exception\\MissingTagException' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/Exception/MissingTagException.php',
'Rector\\NodeTypeResolver\\MethodParameterTypeResolver' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/MethodParameterTypeResolver.php',
'Rector\\NodeTypeResolver\\NodeScopeAndMetadataDecorator' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/NodeScopeAndMetadataDecorator.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\AccessoryNonEmptyStringTypeCorrector' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/NodeTypeCorrector/AccessoryNonEmptyStringTypeCorrector.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\GenericClassStringTypeCorrector' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/NodeTypeCorrector/GenericClassStringTypeCorrector.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\HasOffsetTypeCorrector' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/NodeTypeCorrector/HasOffsetTypeCorrector.php',
'Rector\\NodeTypeResolver\\NodeTypeCorrector\\PregMatchTypeCorrector' => __DIR__ . '/../..' . '/packages/NodeTypeResolver/NodeTypeCorrector/PregMatchTypeCorrector.php',
@ -2876,6 +2879,7 @@ class ComposerStaticInit735eb307678b1bf985488aa190e180a2
'Rector\\PHPStanStaticTypeMapper\\TypeAnalyzer\\BoolUnionTypeAnalyzer' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeAnalyzer/BoolUnionTypeAnalyzer.php',
'Rector\\PHPStanStaticTypeMapper\\TypeAnalyzer\\UnionTypeAnalyzer' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeAnalyzer.php',
'Rector\\PHPStanStaticTypeMapper\\TypeAnalyzer\\UnionTypeCommonTypeNarrower' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeAnalyzer/UnionTypeCommonTypeNarrower.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\AccessoryNonEmptyStringTypeMapper' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeMapper/AccessoryNonEmptyStringTypeMapper.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\ArrayTypeMapper' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeMapper/ArrayTypeMapper.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\BooleanTypeMapper' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeMapper/BooleanTypeMapper.php',
'Rector\\PHPStanStaticTypeMapper\\TypeMapper\\CallableTypeMapper' => __DIR__ . '/../..' . '/packages/PHPStanStaticTypeMapper/TypeMapper/CallableTypeMapper.php',
@ -3111,8 +3115,10 @@ class ComposerStaticInit735eb307678b1bf985488aa190e180a2
'Rector\\Php80\\ValueObject\\PropertyPromotionCandidate' => __DIR__ . '/../..' . '/rules/Php80/ValueObject/PropertyPromotionCandidate.php',
'Rector\\Php80\\ValueObject\\StrStartsWith' => __DIR__ . '/../..' . '/rules/Php80/ValueObject/StrStartsWith.php',
'Rector\\Php81\\NodeFactory\\EnumFactory' => __DIR__ . '/../..' . '/rules/Php81/NodeFactory/EnumFactory.php',
'Rector\\Php81\\Rector\\ClassConst\\FinalizePublicClassConstantRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/ClassConst/FinalizePublicClassConstantRector.php',
'Rector\\Php81\\Rector\\Class_\\MyCLabsClassToEnumRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/Class_/MyCLabsClassToEnumRector.php',
'Rector\\Php81\\Rector\\MethodCall\\MyCLabsMethodCallToEnumConstRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/MethodCall/MyCLabsMethodCallToEnumConstRector.php',
'Rector\\Php81\\Rector\\Property\\ReadOnlyPropertyRector' => __DIR__ . '/../..' . '/rules/Php81/Rector/Property/ReadOnlyPropertyRector.php',
'Rector\\PhpAttribute\\NodeAnalyzer\\NamedArgumentsResolver' => __DIR__ . '/../..' . '/packages/PhpAttribute/NodeAnalyzer/NamedArgumentsResolver.php',
'Rector\\PhpAttribute\\Printer\\DoctrineAnnotationFactory' => __DIR__ . '/../..' . '/packages/PhpAttribute/Printer/DoctrineAnnotationFactory.php',
'Rector\\PhpAttribute\\Printer\\PhpAttributeGroupFactory' => __DIR__ . '/../..' . '/packages/PhpAttribute/Printer/PhpAttributeGroupFactory.php',
@ -3844,9 +3850,9 @@ class ComposerStaticInit735eb307678b1bf985488aa190e180a2
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit735eb307678b1bf985488aa190e180a2::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit735eb307678b1bf985488aa190e180a2::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit735eb307678b1bf985488aa190e180a2::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInitb51d21490f998eb5d663e8d169cd873c::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitb51d21490f998eb5d663e8d169cd873c::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitb51d21490f998eb5d663e8d169cd873c::$classMap;
}, null, ClassLoader::class);
}

View File

@ -721,17 +721,17 @@
},
{
"name": "nikic\/php-parser",
"version": "v4.11.0",
"version_normalized": "4.11.0.0",
"version": "v4.12.0",
"version_normalized": "4.12.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/nikic\/PHP-Parser.git",
"reference": "fe14cf3672a149364fb66dfe11bf6549af899f94"
"reference": "6608f01670c3cc5079e18c1dab1104e002579143"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/nikic\/PHP-Parser\/zipball\/fe14cf3672a149364fb66dfe11bf6549af899f94",
"reference": "fe14cf3672a149364fb66dfe11bf6549af899f94",
"url": "https:\/\/api.github.com\/repos\/nikic\/PHP-Parser\/zipball\/6608f01670c3cc5079e18c1dab1104e002579143",
"reference": "6608f01670c3cc5079e18c1dab1104e002579143",
"shasum": ""
},
"require": {
@ -742,7 +742,7 @@
"ircmaxell\/php-yacc": "^0.0.7",
"phpunit\/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"time": "2021-07-03T13:36:55+00:00",
"time": "2021-07-21T10:44:31+00:00",
"bin": [
"bin\/php-parse"
],
@ -774,7 +774,7 @@
],
"support": {
"issues": "https:\/\/github.com\/nikic\/PHP-Parser\/issues",
"source": "https:\/\/github.com\/nikic\/PHP-Parser\/tree\/v4.11.0"
"source": "https:\/\/github.com\/nikic\/PHP-Parser\/tree\/v4.12.0"
},
"install-path": "..\/nikic\/php-parser"
},
@ -832,17 +832,17 @@
},
{
"name": "phpstan\/phpstan",
"version": "0.12.91",
"version_normalized": "0.12.91.0",
"version": "dev-master",
"version_normalized": "dev-master",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpstan.git",
"reference": "8226701cd228a0d63c2df995de7ab6070c69ac6a"
"reference": "fc2d1db"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan\/zipball\/8226701cd228a0d63c2df995de7ab6070c69ac6a",
"reference": "8226701cd228a0d63c2df995de7ab6070c69ac6a",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan\/zipball\/fc2d1db",
"reference": "fc2d1db",
"shasum": ""
},
"require": {
@ -851,7 +851,8 @@
"conflict": {
"phpstan\/phpstan-shim": "*"
},
"time": "2021-07-04T15:31:48+00:00",
"time": "2021-07-22T16:20:09+00:00",
"default-branch": true,
"bin": [
"phpstan",
"phpstan.phar"
@ -875,7 +876,7 @@
"description": "PHPStan - PHP Static Analysis Tool",
"support": {
"issues": "https:\/\/github.com\/phpstan\/phpstan\/issues",
"source": "https:\/\/github.com\/phpstan\/phpstan\/tree\/0.12.91"
"source": "https:\/\/github.com\/phpstan\/phpstan\/tree\/master"
},
"funding": [
{
@ -1113,37 +1114,33 @@
},
{
"name": "rector\/extension-installer",
"version": "0.10.2",
"version_normalized": "0.10.2.0",
"version": "0.11.0",
"version_normalized": "0.11.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/extension-installer.git",
"reference": "56c97630fca170b5586b2f08e76348f924ebb8dd"
"reference": "10aedb0fab9a759ed9fa5a3396bd021960c10eab"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/extension-installer\/zipball\/56c97630fca170b5586b2f08e76348f924ebb8dd",
"reference": "56c97630fca170b5586b2f08e76348f924ebb8dd",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/extension-installer\/zipball\/10aedb0fab9a759ed9fa5a3396bd021960c10eab",
"reference": "10aedb0fab9a759ed9fa5a3396bd021960c10eab",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.1 || ^2.0",
"php": "^7.3 || ^8.0"
"php": "^8.0"
},
"require-dev": {
"composer\/composer": "^2.0",
"composer\/xdebug-handler": "2.0 as 1.4",
"friendsofphp\/php-cs-fixer": "^3.0",
"jangregor\/phpstan-prophecy": "^0.8.1",
"phpspec\/prophecy-phpunit": "^2.0",
"phpstan\/extension-installer": "^1.1",
"phpunit\/phpunit": "^9.5",
"rector\/rector-phpstan-rules": "^0.1",
"symplify\/easy-coding-standard": "^9.3.1",
"symplify\/phpstan-extensions": "^9.3",
"symplify\/phpstan-rules": "^9.3"
"rector\/phpstan-rules": "^0.3.4",
"rector\/rector-src": "dev-main",
"symplify\/easy-coding-standard": "^9.4.22",
"symplify\/phpstan-extensions": "^9.4.22"
},
"time": "2021-05-06T21:14:19+00:00",
"time": "2021-07-22T22:17:50+00:00",
"type": "composer-plugin",
"extra": {
"class": "Rector\\RectorInstaller\\Plugin"
@ -1161,7 +1158,7 @@
"description": "Composer plugin for automatic installation of Rector extensions",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/extension-installer\/issues",
"source": "https:\/\/github.com\/rectorphp\/extension-installer\/tree\/0.10.2"
"source": "https:\/\/github.com\/rectorphp\/extension-installer\/tree\/0.11.0"
},
"install-path": "..\/rector\/extension-installer"
},
@ -1351,17 +1348,17 @@
},
{
"name": "rector\/rector-nette",
"version": "0.11.16",
"version_normalized": "0.11.16.0",
"version": "0.11.17",
"version_normalized": "0.11.17.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-nette.git",
"reference": "ef1fe5ac65b240dead8ce6053acd4cb2213660d0"
"reference": "4701b615d500d265b2a194fd8e4a9f415b44feac"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-nette\/zipball\/ef1fe5ac65b240dead8ce6053acd4cb2213660d0",
"reference": "ef1fe5ac65b240dead8ce6053acd4cb2213660d0",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-nette\/zipball\/4701b615d500d265b2a194fd8e4a9f415b44feac",
"reference": "4701b615d500d265b2a194fd8e4a9f415b44feac",
"shasum": ""
},
"require": {
@ -1374,11 +1371,11 @@
"rector\/rector": "<0.11"
},
"require-dev": {
"nette\/application": "^3.0.7",
"nette\/application": "^3.1",
"nette\/di": "^3.0",
"nette\/forms": "3.0.*",
"phpstan\/extension-installer": "^1.1",
"phpstan\/phpstan-nette": "^0.12.16",
"phpstan\/phpstan-nette": "^0.12.21",
"phpunit\/phpunit": "^9.5",
"rector\/rector-phpstan-rules": "^0.3.4",
"rector\/rector-src": "dev-main",
@ -1387,7 +1384,7 @@
"symplify\/phpstan-rules": "^9.4",
"symplify\/rule-doc-generator": "^9.4"
},
"time": "2021-07-08T21:35:27+00:00",
"time": "2021-07-22T22:58:32+00:00",
"type": "rector-extension",
"extra": {
"branch-alias": {
@ -1412,23 +1409,23 @@
"description": "Rector upgrades rules for Nette Framework",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-nette\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-nette\/tree\/0.11.16"
"source": "https:\/\/github.com\/rectorphp\/rector-nette\/tree\/0.11.17"
},
"install-path": "..\/rector\/rector-nette"
},
{
"name": "rector\/rector-phpunit",
"version": "0.11.6",
"version_normalized": "0.11.6.0",
"version": "0.11.7",
"version_normalized": "0.11.7.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-phpunit.git",
"reference": "d729480c7faed1ac077100df201c82ab65a4b797"
"reference": "9daf9b37e1373fc449f3cb3854a9487f75994ddf"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/d729480c7faed1ac077100df201c82ab65a4b797",
"reference": "d729480c7faed1ac077100df201c82ab65a4b797",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/9daf9b37e1373fc449f3cb3854a9487f75994ddf",
"reference": "9daf9b37e1373fc449f3cb3854a9487f75994ddf",
"shasum": ""
},
"require": {
@ -1447,7 +1444,7 @@
"symplify\/phpstan-rules": "^9.2",
"symplify\/rule-doc-generator": "^9.4"
},
"time": "2021-07-04T12:38:37+00:00",
"time": "2021-07-22T22:55:16+00:00",
"type": "rector-extension",
"extra": {
"branch-alias": {
@ -1472,7 +1469,7 @@
"description": "Rector upgrades rules for PHPUnit",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-phpunit\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-phpunit\/tree\/0.11.6"
"source": "https:\/\/github.com\/rectorphp\/rector-phpunit\/tree\/0.11.7"
},
"install-path": "..\/rector\/rector-phpunit"
},
@ -1611,17 +1608,17 @@
},
{
"name": "ssch\/typo3-rector",
"version": "dev-main",
"version_normalized": "dev-main",
"version": "v0.11.22",
"version_normalized": "0.11.22.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/sabbelasichon\/typo3-rector.git",
"reference": "f5fd76a"
"reference": "6a26fcbf5bdbe60b77037f576e86d1c9bc560a87"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/sabbelasichon\/typo3-rector\/zipball\/f5fd76a",
"reference": "f5fd76a",
"url": "https:\/\/api.github.com\/repos\/sabbelasichon\/typo3-rector\/zipball\/6a26fcbf5bdbe60b77037f576e86d1c9bc560a87",
"reference": "6a26fcbf5bdbe60b77037f576e86d1c9bc560a87",
"shasum": ""
},
"require": {
@ -1647,8 +1644,7 @@
"symplify\/rule-doc-generator": "^9.4.22",
"tracy\/tracy": "^2.8"
},
"time": "2021-07-19T09:12:50+00:00",
"default-branch": true,
"time": "2021-07-17T17:04:11+00:00",
"type": "rector-extension",
"extra": {
"rector": {
@ -1680,7 +1676,7 @@
"description": "Instant fixes for your TYPO3 code by using Rector.",
"support": {
"issues": "https:\/\/github.com\/sabbelasichon\/typo3-rector\/issues",
"source": "https:\/\/github.com\/sabbelasichon\/typo3-rector\/tree\/main"
"source": "https:\/\/github.com\/sabbelasichon\/typo3-rector\/tree\/v0.11.22"
},
"funding": [
{

File diff suppressed because one or more lines are too long

View File

@ -20,6 +20,11 @@ top_statement_list:
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
;
ampersand:
T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
| T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG
;
reserved_non_modifiers:
T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
| T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
@ -246,7 +251,12 @@ variables_list:
optional_ref:
/* empty */ { $$ = false; }
| '&' { $$ = true; }
| ampersand { $$ = true; }
;
optional_arg_ref:
/* empty */ { $$ = false; }
| T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; }
;
optional_ellipsis:
@ -378,7 +388,7 @@ new_else_single:
foreach_variable:
variable { $$ = array($1, false); }
| '&' variable { $$ = array($2, true); }
| ampersand variable { $$ = array($2, true); }
| list_expr { $$ = array($1, false); }
;
@ -393,9 +403,9 @@ non_empty_parameter_list:
;
parameter:
optional_param_type optional_ref optional_ellipsis plain_variable
optional_param_type optional_arg_ref optional_ellipsis plain_variable
{ $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); }
| optional_param_type optional_ref optional_ellipsis plain_variable '=' static_scalar
| optional_param_type optional_arg_ref optional_ellipsis plain_variable '=' static_scalar
{ $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); }
;
@ -428,7 +438,7 @@ non_empty_argument_list:
argument:
expr { $$ = Node\Arg[$1, false, false]; }
| '&' variable { $$ = Node\Arg[$2, true, false]; }
| ampersand variable { $$ = Node\Arg[$2, true, false]; }
| T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; }
;
@ -562,8 +572,8 @@ expr:
variable { $$ = $1; }
| list_expr '=' expr { $$ = Expr\Assign[$1, $3]; }
| variable '=' expr { $$ = Expr\Assign[$1, $3]; }
| variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; }
| variable '=' '&' new_expr { $$ = Expr\AssignRef[$1, $4]; }
| variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; }
| variable '=' ampersand new_expr { $$ = Expr\AssignRef[$1, $4]; }
| new_expr { $$ = $1; }
| T_CLONE expr { $$ = Expr\Clone_[$2]; }
| variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; }
@ -589,7 +599,8 @@ expr:
| expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
| expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
| expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
| expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
| expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; }
| expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; }
@ -816,7 +827,10 @@ static_operation:
| static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
| static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
| static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
| static_scalar '&' static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| static_scalar T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG static_scalar
{ $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| static_scalar T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG static_scalar
{ $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
| static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; }
| static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; }
@ -986,8 +1000,8 @@ non_empty_array_pair_list:
array_pair:
expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; }
| expr { $$ = Expr\ArrayItem[$1, null, false]; }
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
| expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; }
| ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; }
| T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
;

View File

@ -20,6 +20,11 @@ top_statement_list:
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
;
ampersand:
T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
| T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG
;
reserved_non_modifiers:
T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
| T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
@ -33,7 +38,7 @@ reserved_non_modifiers:
semi_reserved:
reserved_non_modifiers
| T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
| T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY
;
identifier_ex:
@ -327,7 +332,12 @@ non_empty_variables_list:
optional_ref:
/* empty */ { $$ = false; }
| '&' { $$ = true; }
| ampersand { $$ = true; }
;
optional_arg_ref:
/* empty */ { $$ = false; }
| T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = true; }
;
optional_ellipsis:
@ -505,7 +515,7 @@ new_else_single:
foreach_variable:
variable { $$ = array($1, false); }
| '&' variable { $$ = array($2, true); }
| ampersand variable { $$ = array($2, true); }
| list_expr { $$ = array($1, false); }
| array_short_syntax { $$ = array($1, false); }
;
@ -525,16 +535,20 @@ optional_visibility_modifier:
| T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
| T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
| T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
| T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; }
;
parameter:
optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis plain_variable
optional_attributes optional_visibility_modifier optional_type_without_static
optional_arg_ref optional_ellipsis plain_variable
{ $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1);
$this->checkParam($$); }
| optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis plain_variable '=' expr
| optional_attributes optional_visibility_modifier optional_type_without_static
optional_arg_ref optional_ellipsis plain_variable '=' expr
{ $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1);
$this->checkParam($$); }
| optional_attributes optional_visibility_modifier optional_type_without_static optional_ref optional_ellipsis error
| optional_attributes optional_visibility_modifier optional_type_without_static
optional_arg_ref optional_ellipsis error
{ $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); }
;
@ -594,7 +608,7 @@ non_empty_argument_list:
argument:
expr { $$ = Node\Arg[$1, false, false]; }
| '&' variable { $$ = Node\Arg[$2, true, false]; }
| ampersand variable { $$ = Node\Arg[$2, true, false]; }
| T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; }
| identifier_ex ':' expr
{ $$ = new Node\Arg($3, false, false, attributes(), $1); }
@ -712,6 +726,7 @@ member_modifier:
| T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; }
| T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
| T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; }
| T_READONLY { $$ = Stmt\Class_::MODIFIER_READONLY; }
;
property_declaration_list:
@ -756,7 +771,7 @@ expr:
| list_expr '=' expr { $$ = Expr\Assign[$1, $3]; }
| array_short_syntax '=' expr { $$ = Expr\Assign[$1, $3]; }
| variable '=' expr { $$ = Expr\Assign[$1, $3]; }
| variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; }
| variable '=' ampersand variable { $$ = Expr\AssignRef[$1, $4]; }
| new_expr { $$ = $1; }
| match { $$ = $1; }
| T_CLONE expr { $$ = Expr\Clone_[$2]; }
@ -783,7 +798,8 @@ expr:
| expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
| expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
| expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
| expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
| expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
| expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; }
| expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; }
@ -1106,10 +1122,10 @@ inner_array_pair_list:
array_pair:
expr { $$ = Expr\ArrayItem[$1, null, false]; }
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
| ampersand variable { $$ = Expr\ArrayItem[$2, null, true]; }
| list_expr { $$ = Expr\ArrayItem[$1, null, false]; }
| expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; }
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
| expr T_DOUBLE_ARROW ampersand variable { $$ = Expr\ArrayItem[$4, $1, true]; }
| expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; }
| T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
| /* empty */ { $$ = null; }

View File

@ -18,7 +18,7 @@
%left T_BOOLEAN_AND
%left '|'
%left '^'
%left '&'
%left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
%left T_SL T_SR
@ -74,7 +74,7 @@
%token T_USE
%token T_INSTEADOF
%token T_GLOBAL
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_READONLY
%token T_VAR
%token T_UNSET
%token T_ISSET

View File

@ -69,6 +69,16 @@ class ClassConst implements \PhpParser\Builder
$this->flags = \PhpParser\BuilderHelpers::addModifier($this->flags, \PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE);
return $this;
}
/**
* Makes the constant final.
*
* @return $this The builder instance (for fluid interface)
*/
public function makeFinal()
{
$this->flags = \PhpParser\BuilderHelpers::addModifier($this->flags, \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL);
return $this;
}
/**
* Sets doc comment for the constant.
*

View File

@ -69,6 +69,16 @@ class Property implements \PhpParser\Builder
$this->flags = \PhpParser\BuilderHelpers::addModifier($this->flags, \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC);
return $this;
}
/**
* Makes the property readonly.
*
* @return $this The builder instance (for fluid interface)
*/
public function makeReadonly()
{
$this->flags = \PhpParser\BuilderHelpers::addModifier($this->flags, \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY);
return $this;
}
/**
* Sets default value for the property.
*

View File

@ -116,10 +116,11 @@ class Lexer
// detected by finding "gaps" in the token array. Unterminated comments are detected
// by checking if a trailing comment has a "*/" at the end.
//
// Additionally, we canonicalize to the PHP 8 comment format here, which does not include
// the trailing whitespace anymore.
//
// We also canonicalize to the PHP 8 T_NAME_* tokens.
// Additionally, we perform a number of canonicalizations here:
// * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore.
// * Use PHP 8.0 T_NAME_* tokens.
// * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and
// T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types.
$filePos = 0;
$line = 1;
$numTokens = \count($this->tokens);
@ -183,6 +184,14 @@ class Lexer
$numTokens -= $j - $i - 1;
}
}
if ($token === '&') {
$next = $i + 1;
while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) {
$next++;
}
$followedByVarOrVarArg = isset($this->tokens[$next]) && ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS);
$this->tokens[$i] = $token = [$followedByVarOrVarArg ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, '&', $line];
}
$tokenValue = \is_string($token) ? $token : $token[1];
$tokenLen = \strlen($tokenValue);
if (\substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
@ -362,6 +371,9 @@ class Lexer
'T_ATTRIBUTE',
// PHP 8.1
'T_ENUM',
'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
'T_READONLY',
];
// PHP-Parser might be used together with another library that also emulates some or all
// of these tokens. Perform a sanity-check that all already defined tokens have been
@ -442,12 +454,15 @@ class Lexer
$tokenMap[\T_MATCH] = \PhpParser\Parser\Tokens::T_MATCH;
$tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = \PhpParser\Parser\Tokens::T_NULLSAFE_OBJECT_OPERATOR;
$tokenMap[\T_ATTRIBUTE] = \PhpParser\Parser\Tokens::T_ATTRIBUTE;
$tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = \PhpParser\Parser\Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
$tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = \PhpParser\Parser\Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG;
$tokenMap[\T_ENUM] = \PhpParser\Parser\Tokens::T_ENUM;
$tokenMap[\T_READONLY] = \PhpParser\Parser\Tokens::T_READONLY;
return $tokenMap;
}
private function createIdentifierTokenMap() : array
{
// Based on semi_reserved production.
return \array_fill_keys([\T_STRING, \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, \T_MATCH], \true);
return \array_fill_keys([\T_STRING, \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, \T_MATCH], \true);
}
}

View File

@ -14,6 +14,7 @@ use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
use PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator;
use PhpParser\Lexer\TokenEmulator\ReverseEmulator;
use PhpParser\Lexer\TokenEmulator\TokenEmulator;
class Emulative extends \PhpParser\Lexer
@ -38,7 +39,7 @@ class Emulative extends \PhpParser\Lexer
$this->targetPhpVersion = $options['phpVersion'] ?? \PhpParser\Lexer\Emulative::PHP_8_1;
unset($options['phpVersion']);
parent::__construct($options);
$emulators = [new \PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator(), new \PhpParser\Lexer\TokenEmulator\FnTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\MatchTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator(), new \PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\AttributeEmulator(), new \PhpParser\Lexer\TokenEmulator\EnumTokenEmulator()];
$emulators = [new \PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator(), new \PhpParser\Lexer\TokenEmulator\FnTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\MatchTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator(), new \PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\AttributeEmulator(), new \PhpParser\Lexer\TokenEmulator\EnumTokenEmulator(), new \PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator()];
// Collect emulators that are relevant for the PHP version we're running
// and the PHP version we're targeting for emulation.
foreach ($emulators as $emulator) {

View File

@ -0,0 +1,21 @@
<?php
declare (strict_types=1);
namespace PhpParser\Lexer\TokenEmulator;
use PhpParser\Lexer\Emulative;
final class ReadonlyTokenEmulator extends \PhpParser\Lexer\TokenEmulator\KeywordEmulator
{
public function getPhpVersion() : string
{
return \PhpParser\Lexer\Emulative::PHP_8_1;
}
public function getKeywordString() : string
{
return 'readonly';
}
public function getKeywordToken() : int
{
return \T_READONLY;
}
}

View File

@ -58,6 +58,15 @@ class ClassConst extends \PhpParser\Node\Stmt
{
return (bool) ($this->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE);
}
/**
* Whether constant is final.
*
* @return bool
*/
public function isFinal() : bool
{
return (bool) ($this->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL);
}
public function getType() : string
{
return 'Stmt_ClassConst';

View File

@ -13,6 +13,7 @@ class Class_ extends \PhpParser\Node\Stmt\ClassLike
const MODIFIER_STATIC = 8;
const MODIFIER_ABSTRACT = 16;
const MODIFIER_FINAL = 32;
const MODIFIER_READONLY = 64;
const VISIBILITY_MODIFIER_MASK = 7;
// 1 | 2 | 4
/** @var int Type */
@ -91,6 +92,9 @@ class Class_ extends \PhpParser\Node\Stmt\ClassLike
if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
throw new \PhpParser\Error('Multiple final modifiers are not allowed');
}
if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) {
throw new \PhpParser\Error('Multiple readonly modifiers are not allowed');
}
if ($a & 48 && $b & 48) {
throw new \PhpParser\Error('Cannot use the final modifier on an abstract class member');
}

View File

@ -75,6 +75,15 @@ class Property extends \PhpParser\Node\Stmt
{
return (bool) ($this->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC);
}
/**
* Whether the property is readonly.
*
* @return bool
*/
public function isReadonly() : bool
{
return (bool) ($this->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY);
}
public function getType() : string
{
return 'Stmt_Property';

View File

@ -121,6 +121,9 @@ class NodeDumper
if ($flags & \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL) {
$strs[] = 'MODIFIER_FINAL';
}
if ($flags & \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY) {
$strs[] = 'MODIFIER_READONLY';
}
if ($strs) {
return \implode(' | ', $strs) . ' (' . $flags . ')';
} else {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -35,111 +35,114 @@ final class Tokens
const T_COALESCE = 283;
const T_BOOLEAN_OR = 284;
const T_BOOLEAN_AND = 285;
const T_IS_EQUAL = 286;
const T_IS_NOT_EQUAL = 287;
const T_IS_IDENTICAL = 288;
const T_IS_NOT_IDENTICAL = 289;
const T_SPACESHIP = 290;
const T_IS_SMALLER_OR_EQUAL = 291;
const T_IS_GREATER_OR_EQUAL = 292;
const T_SL = 293;
const T_SR = 294;
const T_INSTANCEOF = 295;
const T_INC = 296;
const T_DEC = 297;
const T_INT_CAST = 298;
const T_DOUBLE_CAST = 299;
const T_STRING_CAST = 300;
const T_ARRAY_CAST = 301;
const T_OBJECT_CAST = 302;
const T_BOOL_CAST = 303;
const T_UNSET_CAST = 304;
const T_POW = 305;
const T_NEW = 306;
const T_CLONE = 307;
const T_EXIT = 308;
const T_IF = 309;
const T_ELSEIF = 310;
const T_ELSE = 311;
const T_ENDIF = 312;
const T_LNUMBER = 313;
const T_DNUMBER = 314;
const T_STRING = 315;
const T_STRING_VARNAME = 316;
const T_VARIABLE = 317;
const T_NUM_STRING = 318;
const T_INLINE_HTML = 319;
const T_ENCAPSED_AND_WHITESPACE = 320;
const T_CONSTANT_ENCAPSED_STRING = 321;
const T_ECHO = 322;
const T_DO = 323;
const T_WHILE = 324;
const T_ENDWHILE = 325;
const T_FOR = 326;
const T_ENDFOR = 327;
const T_FOREACH = 328;
const T_ENDFOREACH = 329;
const T_DECLARE = 330;
const T_ENDDECLARE = 331;
const T_AS = 332;
const T_SWITCH = 333;
const T_MATCH = 334;
const T_ENDSWITCH = 335;
const T_CASE = 336;
const T_DEFAULT = 337;
const T_BREAK = 338;
const T_CONTINUE = 339;
const T_GOTO = 340;
const T_FUNCTION = 341;
const T_FN = 342;
const T_CONST = 343;
const T_RETURN = 344;
const T_TRY = 345;
const T_CATCH = 346;
const T_FINALLY = 347;
const T_USE = 348;
const T_INSTEADOF = 349;
const T_GLOBAL = 350;
const T_STATIC = 351;
const T_ABSTRACT = 352;
const T_FINAL = 353;
const T_PRIVATE = 354;
const T_PROTECTED = 355;
const T_PUBLIC = 356;
const T_VAR = 357;
const T_UNSET = 358;
const T_ISSET = 359;
const T_EMPTY = 360;
const T_HALT_COMPILER = 361;
const T_CLASS = 362;
const T_TRAIT = 363;
const T_INTERFACE = 364;
const T_ENUM = 365;
const T_EXTENDS = 366;
const T_IMPLEMENTS = 367;
const T_OBJECT_OPERATOR = 368;
const T_NULLSAFE_OBJECT_OPERATOR = 369;
const T_LIST = 370;
const T_ARRAY = 371;
const T_CALLABLE = 372;
const T_CLASS_C = 373;
const T_TRAIT_C = 374;
const T_METHOD_C = 375;
const T_FUNC_C = 376;
const T_LINE = 377;
const T_FILE = 378;
const T_START_HEREDOC = 379;
const T_END_HEREDOC = 380;
const T_DOLLAR_OPEN_CURLY_BRACES = 381;
const T_CURLY_OPEN = 382;
const T_PAAMAYIM_NEKUDOTAYIM = 383;
const T_NAMESPACE = 384;
const T_NS_C = 385;
const T_DIR = 386;
const T_NS_SEPARATOR = 387;
const T_ELLIPSIS = 388;
const T_NAME_FULLY_QUALIFIED = 389;
const T_NAME_QUALIFIED = 390;
const T_NAME_RELATIVE = 391;
const T_ATTRIBUTE = 392;
const T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG = 286;
const T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG = 287;
const T_IS_EQUAL = 288;
const T_IS_NOT_EQUAL = 289;
const T_IS_IDENTICAL = 290;
const T_IS_NOT_IDENTICAL = 291;
const T_SPACESHIP = 292;
const T_IS_SMALLER_OR_EQUAL = 293;
const T_IS_GREATER_OR_EQUAL = 294;
const T_SL = 295;
const T_SR = 296;
const T_INSTANCEOF = 297;
const T_INC = 298;
const T_DEC = 299;
const T_INT_CAST = 300;
const T_DOUBLE_CAST = 301;
const T_STRING_CAST = 302;
const T_ARRAY_CAST = 303;
const T_OBJECT_CAST = 304;
const T_BOOL_CAST = 305;
const T_UNSET_CAST = 306;
const T_POW = 307;
const T_NEW = 308;
const T_CLONE = 309;
const T_EXIT = 310;
const T_IF = 311;
const T_ELSEIF = 312;
const T_ELSE = 313;
const T_ENDIF = 314;
const T_LNUMBER = 315;
const T_DNUMBER = 316;
const T_STRING = 317;
const T_STRING_VARNAME = 318;
const T_VARIABLE = 319;
const T_NUM_STRING = 320;
const T_INLINE_HTML = 321;
const T_ENCAPSED_AND_WHITESPACE = 322;
const T_CONSTANT_ENCAPSED_STRING = 323;
const T_ECHO = 324;
const T_DO = 325;
const T_WHILE = 326;
const T_ENDWHILE = 327;
const T_FOR = 328;
const T_ENDFOR = 329;
const T_FOREACH = 330;
const T_ENDFOREACH = 331;
const T_DECLARE = 332;
const T_ENDDECLARE = 333;
const T_AS = 334;
const T_SWITCH = 335;
const T_MATCH = 336;
const T_ENDSWITCH = 337;
const T_CASE = 338;
const T_DEFAULT = 339;
const T_BREAK = 340;
const T_CONTINUE = 341;
const T_GOTO = 342;
const T_FUNCTION = 343;
const T_FN = 344;
const T_CONST = 345;
const T_RETURN = 346;
const T_TRY = 347;
const T_CATCH = 348;
const T_FINALLY = 349;
const T_USE = 350;
const T_INSTEADOF = 351;
const T_GLOBAL = 352;
const T_STATIC = 353;
const T_ABSTRACT = 354;
const T_FINAL = 355;
const T_PRIVATE = 356;
const T_PROTECTED = 357;
const T_PUBLIC = 358;
const T_READONLY = 359;
const T_VAR = 360;
const T_UNSET = 361;
const T_ISSET = 362;
const T_EMPTY = 363;
const T_HALT_COMPILER = 364;
const T_CLASS = 365;
const T_TRAIT = 366;
const T_INTERFACE = 367;
const T_ENUM = 368;
const T_EXTENDS = 369;
const T_IMPLEMENTS = 370;
const T_OBJECT_OPERATOR = 371;
const T_NULLSAFE_OBJECT_OPERATOR = 372;
const T_LIST = 373;
const T_ARRAY = 374;
const T_CALLABLE = 375;
const T_CLASS_C = 376;
const T_TRAIT_C = 377;
const T_METHOD_C = 378;
const T_FUNC_C = 379;
const T_LINE = 380;
const T_FILE = 381;
const T_START_HEREDOC = 382;
const T_END_HEREDOC = 383;
const T_DOLLAR_OPEN_CURLY_BRACES = 384;
const T_CURLY_OPEN = 385;
const T_PAAMAYIM_NEKUDOTAYIM = 386;
const T_NAMESPACE = 387;
const T_NS_C = 388;
const T_DIR = 389;
const T_NS_SEPARATOR = 390;
const T_ELLIPSIS = 391;
const T_NAME_FULLY_QUALIFIED = 392;
const T_NAME_QUALIFIED = 393;
const T_NAME_RELATIVE = 394;
const T_ATTRIBUTE = 395;
}

View File

@ -798,6 +798,9 @@ abstract class ParserAbstract implements \PhpParser\Parser
break;
}
}
if ($node->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY) {
$this->emitError(new \PhpParser\Error(\sprintf('Method %s() cannot be readonly', $node->name), $this->getAttributesAt($modifierPos)));
}
}
protected function checkClassConst(\PhpParser\Node\Stmt\ClassConst $node, $modifierPos)
{
@ -807,8 +810,8 @@ abstract class ParserAbstract implements \PhpParser\Parser
if ($node->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT) {
$this->emitError(new \PhpParser\Error("Cannot use 'abstract' as constant modifier", $this->getAttributesAt($modifierPos)));
}
if ($node->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL) {
$this->emitError(new \PhpParser\Error("Cannot use 'final' as constant modifier", $this->getAttributesAt($modifierPos)));
if ($node->flags & \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY) {
$this->emitError(new \PhpParser\Error("Cannot use 'readonly' as constant modifier", $this->getAttributesAt($modifierPos)));
}
}
protected function checkProperty(\PhpParser\Node\Stmt\Property $node, $modifierPos)

View File

@ -936,7 +936,7 @@ abstract class PrettyPrinterAbstract
*/
protected function pModifiers(int $modifiers)
{
return ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL ? 'final ' : '');
return ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_FINAL ? 'final ' : '') . ($modifiers & \PhpParser\Node\Stmt\Class_::MODIFIER_READONLY ? 'readonly ' : '');
}
/**
* Determine whether a list of nodes uses multiline formatting.
@ -983,7 +983,8 @@ abstract class PrettyPrinterAbstract
for ($i = 0; $i < 256; $i++) {
// Since PHP 7.1 The lower range is 0x80. However, we also want to support code for
// older versions.
$this->labelCharMap[\chr($i)] = $i >= 0x7f || \ctype_alnum($i);
$chr = \chr($i);
$this->labelCharMap[$chr] = $i >= 0x7f || \ctype_alnum($chr);
}
}
/**

Binary file not shown.

View File

@ -1,16 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmDh1GMACgkQzxoQjQ56
5yAFtRAAopxSVZxRbTdtWYJdyiNi9JKO0QyHbVdyFeL0W96geChem0x1hGdUGPI0
S/NkAQyFTNHizKnMKV1QXePlQ1HqRmy+bm7Z2Y29RXt3XoCGzgQiQl3Xfoaw1fy3
5vQKwSZdhpkW1xJxr5gHZ85jz39aqdQjvLBQH4XGOCldRVEJyQUVDdXV7cvubb9v
bXpMGF/iYEfV9A2gV3W4yFashOiwQ96vjxh1JrhytR2U1v1uwY450aKfDeK48sGm
Cix6mEPXv754GI2Yw+qjqfagghYaqbGr0XBCOIJJslsVb/VjuP8niPOloyxjSDiP
y57jMZ/J8OTVonhhUhI05H4YxKd5XGdsYYmnYDZm4XsJGtcfFPnFX+7dZYnNIFnW
/wFRxsqE5ZzH/a5ZwbfNRBDJp+0ELJlpLM+SdUQUXt0IYma2byGn/b81mZ2j0EB4
OkwzziDnJncy1g3jrDwas/bjI/PY7/kqzfa5rx/U3VgJmE5sUF6XYNlNvhnlDSIy
lFT/rlc92phvroZ6GO9s77QisWHm1iVLjdxJS71vUnXj2IkqGLZukMSlVz64tEce
ZOjdxERmcS6TOFuTaYJaJqePx6nRPv32aofSBgNeEBPCXBOEwV+16iOU53t38L1L
z6GI3VVlJHVUk0YWpSbzvnEKYD6qZDjewp6g3g5kuaTblpuTwyQ=
=RnK9
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmD5mrgACgkQzxoQjQ56
5yC58A//eiS34AJgHG+XCdGVZSgtmYXxrxv1t85xp1iZ/DvxnFRkgeG99PVAaGwE
qebeqKemN5CE93Kd0fkPv/S2MoLP0Km7qil79CzlfvSYofi7S+KElwqXGJnGkUbu
NZkUAwmVkSByeO7M2PWXUJE2UIsvVAGUJ1ghMf+ZT+8IIHK5BejMDm+aWbsceO1v
zqKcTQnWLzjqxluZWuom3WLk8Ira+bJnjlbvICQVyLaD5m6A3kZg0xjusQJYyeLA
T13vtkRhnFjWR6h02sSqMk32QSKJxx4jbTmteJMyPlimw5j2rCyV8avpUtDRdki/
FEg/7hv0h/18WaPL5/thLupZq57hRTdyqCa2QDgvXQHVny9oiP9KMXCyHSLhFn2g
4tIRLUXa8ehEV0RL0kTrxGMsuBwuRkR9u0Rge8jAMAzx1va0RwBAQQI8ZOIeA+nT
dl/gl8a0/2BtctW4VFfr3hhPXNA9RM/aCviMqz7gqvFqydQ/bMi5D5+O3V9QomSU
96q30aTtD3mbXnlZDprPtrlGQ6VymN3aRpha7/7GbUbee/8avY/puiYdcitbqWRQ
THjGU2rfZ+knMsL4NEVkle7NhQOU8Gt1VfDm4g6wxI07drfHNlwCMAkftxYewHfk
9pdtlhhobpzyQRutEqYpuiJs8eL3zgiGig1afZThX7O5vAz6WEs=
=pSGc
-----END PGP SIGNATURE-----

View File

@ -1,32 +0,0 @@
# Rector Extension Installer
[![Build](https://github.com/rectorphp/rector-installer/workflows/CI/badge.svg)](https://github.com/rectorphp/rector-installer/actions)
Composer plugin for automatic installation of Rector extensions.
## Usage
```bash
composer require --dev rector/rector-installer
```
## Instructions for extension developers
It's best to set the extension's composer package [type](https://getcomposer.org/doc/04-schema.md#type) to `rector-extension` for this plugin to be able to recognize it and to be [discoverable on Packagist](https://packagist.org/explore/?type=rector-extension).
Add `rector` key in the extension `composer.json`'s `extra` section:
```json
{
"extra": {
"rector": {
"includes": [
"config/config.php"
]
}
}
}
```
## Limitations
The extension installer depends on Composer script events, therefore you cannot use `--no-scripts` flag.

View File

@ -4,21 +4,17 @@
"description": "Composer plugin for automatic installation of Rector extensions",
"license": "MIT",
"require": {
"php": "^7.3 || ^8.0",
"php": "^8.0",
"composer-plugin-api": "^1.1 || ^2.0"
},
"require-dev": {
"rector\/rector-src": "dev-main",
"composer\/composer": "^2.0",
"composer\/xdebug-handler": "2.0 as 1.4",
"jangregor\/phpstan-prophecy": "^0.8.1",
"friendsofphp\/php-cs-fixer": "^3.0",
"phpspec\/prophecy-phpunit": "^2.0",
"phpstan\/extension-installer": "^1.1",
"phpunit\/phpunit": "^9.5",
"rector\/rector-phpstan-rules": "^0.1",
"symplify\/easy-coding-standard": "^9.3.1",
"symplify\/phpstan-extensions": "^9.3",
"symplify\/phpstan-rules": "^9.3"
"rector\/phpstan-rules": "^0.3.4",
"symplify\/easy-coding-standard": "^9.4.22",
"symplify\/phpstan-extensions": "^9.4.22"
},
"autoload": {
"psr-4": {
@ -31,14 +27,23 @@
}
},
"scripts": {
"check-cs": "ecs check src tests --verbose --ansi",
"fix-cs": "ecs check src tests --fix --verbose --ansi",
"check-cs": "ecs check --verbose --ansi",
"fix-cs": "ecs check --fix --verbose --ansi",
"phpstan": "vendor\/bin\/phpstan analyse --ansi --error-format symplify"
},
"repositories": [
{
"type": "path",
"version": "dev-main",
"url": "."
}
],
"config": {
"sort-packages": true
},
"extra": {
"class": "Rector\\RectorInstaller\\Plugin"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@ -1,21 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix20210722;
use RectorPrefix20210722\PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
use RectorPrefix20210722\PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Option;
use RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return static function (\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $containerConfigurator) : void {
$containerConfigurator->import(\RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Set\SetList::PSR_12);
$containerConfigurator->import(\RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Set\SetList::SYMPLIFY);
$containerConfigurator->import(\RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Set\SetList::COMMON);
$containerConfigurator->import(\RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Set\SetList::CLEAN_CODE);
$services = $containerConfigurator->services();
$services->set(\RectorPrefix20210722\PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer::class)->call('configure', [['annotations' => ['throws', 'author', 'package', 'group', 'required', 'phpstan-ignore-line', 'phpstan-ignore-next-line']]]);
$services->set(\RectorPrefix20210722\PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer::class)->call('configure', [['allow_mixed' => \true]]);
$parameters = $containerConfigurator->parameters();
$parameters->set(\RectorPrefix20210722\Symplify\EasyCodingStandard\ValueObject\Option::PATHS, [__DIR__ . '/ecs.php', __DIR__ . '/src', __DIR__ . '/tests']);
};

View File

@ -1,12 +0,0 @@
parameters:
level: max
paths:
- src
- tests
ignoreErrors:
# mostly mocking
-
message: '#Do not use chained method calls\. Put each on separated lines#'
path: tests

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>

View File

@ -0,0 +1,13 @@
<?php
declare (strict_types=1);
namespace RectorPrefix20210722;
use Rector\Php74\Rector\Property\TypedPropertyRector;
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(\Rector\Php74\Rector\Property\TypedPropertyRector::class);
$services->set(\Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class);
};

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.3'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.13'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.4'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.16'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.6'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.12'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main f5fd76a'));
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.3'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.13'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.4'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.17'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.7'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.12'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'v0.11.22'));
private function __construct()
{
}

View File

@ -11,16 +11,31 @@ use Composer\Script\Event;
use Composer\Script\ScriptEvents;
final class Plugin implements \Composer\Plugin\PluginInterface, \Composer\EventDispatcher\EventSubscriberInterface
{
public function activate(\Composer\Composer $composer, \Composer\IO\IOInterface $io) : void
/**
* @param \Composer\Composer $composer
* @param \Composer\IO\IOInterface $io
*/
public function activate($composer, $io) : void
{
}
public function deactivate(\Composer\Composer $composer, \Composer\IO\IOInterface $io) : void
/**
* @param \Composer\Composer $composer
* @param \Composer\IO\IOInterface $io
*/
public function deactivate($composer, $io) : void
{
}
public function uninstall(\Composer\Composer $composer, \Composer\IO\IOInterface $io) : void
/**
* @param \Composer\Composer $composer
* @param \Composer\IO\IOInterface $io
*/
public function uninstall($composer, $io) : void
{
}
public function process(\Composer\Script\Event $event) : void
/**
* @param \Composer\Script\Event $event
*/
public function process($event) : void
{
$io = $event->getIO();
$composer = $event->getComposer();

View File

@ -25,53 +25,58 @@ final class PluginInstaller
* @var string
*/
private static $generatedFileTemplate = <<<'CODE_SAMPLE'
<?php declare(strict_types = 1);
<?php
declare(strict_types = 1);
namespace Rector\RectorInstaller;
/**
* This class is generated by rector/extension-installer.
* @internal
*/
final class GeneratedConfig
{
public const EXTENSIONS = %s;
private function __construct()
{
}
public const EXTENSIONS = %s;
private function __construct()
{
}
}
CODE_SAMPLE;
/**
* @var Filesystem
* @var \Rector\RectorInstaller\Filesystem
*/
private $filesystem;
/**
* @var InstalledRepositoryInterface
* @var \Composer\Repository\InstalledRepositoryInterface
*/
private $localRepository;
/**
* @var IOInterface
* @var \Composer\IO\IOInterface
*/
private $io;
/**
* @var InstallationManager
* @var \Composer\Installer\InstallationManager
*/
private $installationManager;
/**
* @var string
*/
private $configurationFile;
/**
* @var ComposerFilesystem
*/
private $composerFilesystem;
/**
* @var string
*/
private $configurationFile;
public function __construct(\Rector\RectorInstaller\Filesystem $filesystem, \RectorPrefix20210722\Composer\Repository\InstalledRepositoryInterface $localRepository, \RectorPrefix20210722\Composer\IO\IOInterface $io, \RectorPrefix20210722\Composer\Installer\InstallationManager $installationManager, \RectorPrefix20210722\Composer\Util\Filesystem $composerFilesystem, string $configurationFile)
{
$this->filesystem = $filesystem;
$this->localRepository = $localRepository;
$this->io = $io;
$this->installationManager = $installationManager;
$this->configurationFile = $configurationFile;
$this->composerFilesystem = $composerFilesystem;
$this->configurationFile = $configurationFile;
}
public function install() : void
{

View File

@ -1,97 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorInstaller\Tests;
use RectorPrefix20210722\Composer\Installer\InstallationManager;
use RectorPrefix20210722\Composer\IO\IOInterface;
use RectorPrefix20210722\Composer\Package\PackageInterface;
use RectorPrefix20210722\Composer\Repository\InstalledRepositoryInterface;
use RectorPrefix20210722\PHPUnit\Framework\TestCase;
use RectorPrefix20210722\Prophecy\Argument;
use RectorPrefix20210722\Prophecy\PhpUnit\ProphecyTrait;
use RectorPrefix20210722\Prophecy\Prophecy\ObjectProphecy;
use Rector\RectorInstaller\Filesystem;
use Rector\RectorInstaller\PluginInstaller;
/**
* @covers PluginInstaller
*/
final class PluginInstallerTest extends \RectorPrefix20210722\PHPUnit\Framework\TestCase
{
use ProphecyTrait;
/**
* @var string
*/
private const FILE_HASH = 'hash';
/**
* @var PluginInstaller
*/
private $pluginInstaller;
/**
* @var InstalledRepositoryInterface|ObjectProphecy
*/
private $localRepository;
/**
* @var IOInterface|ObjectProphecy
*/
private $io;
/**
* @var InstallationManager|ObjectProphecy
*/
private $installationManager;
/**
* @var ObjectProphecy|Filesystem
*/
private $filesystem;
/**
* @var string
*/
private $configurationFile;
/**
* @var \Composer\Util\Filesystem|ObjectProphecy
*/
private $composerFilesystem;
protected function setUp() : void
{
$this->configurationFile = __FILE__;
$this->composerFilesystem = $this->prophesize(\RectorPrefix20210722\Composer\Util\Filesystem::class);
$this->filesystem = $this->prophesize(\Rector\RectorInstaller\Filesystem::class);
$this->filesystem->isFile($this->configurationFile)->shouldBeCalledOnce()->willReturn(\true);
$this->filesystem->hashFile($this->configurationFile)->willReturn(self::FILE_HASH);
$this->localRepository = $this->prophesize(\RectorPrefix20210722\Composer\Repository\InstalledRepositoryInterface::class);
$this->io = $this->prophesize(\RectorPrefix20210722\Composer\IO\IOInterface::class);
$this->installationManager = $this->prophesize(\RectorPrefix20210722\Composer\Installer\InstallationManager::class);
$this->pluginInstaller = new \Rector\RectorInstaller\PluginInstaller($this->filesystem->reveal(), $this->localRepository->reveal(), $this->io->reveal(), $this->installationManager->reveal(), $this->composerFilesystem->reveal(), $this->configurationFile);
}
public function testNoRectorPackagesInstalled() : void
{
$this->localRepository->getPackages()->willReturn([]);
$this->filesystem->writeFile($this->configurationFile, \RectorPrefix20210722\Prophecy\Argument::any())->shouldNotBeCalled();
$this->filesystem->hashEquals(self::FILE_HASH, \RectorPrefix20210722\Prophecy\Argument::any())->willReturn(\true);
$this->pluginInstaller->install();
}
public function testPackagesInstalled() : void
{
$rectorExtensionPackage = $this->prophesize(\RectorPrefix20210722\Composer\Package\PackageInterface::class);
$rectorExtensionPackage->getType()->willReturn(\Rector\RectorInstaller\PluginInstaller::RECTOR_EXTENSION_TYPE);
$rectorExtensionPackage->getName()->willReturn('rector/doctrine');
$rectorExtensionPackage->getFullPrettyVersion()->willReturn('rector/doctrine');
$rectorExtensionPackage->getExtra()->willReturn([\Rector\RectorInstaller\PluginInstaller::RECTOR_EXTRA_KEY => ['includes' => ['config/config.php']]]);
$nonRectorExtensionPackage = $this->prophesize(\RectorPrefix20210722\Composer\Package\PackageInterface::class);
$nonRectorExtensionPackageWithExtra = $this->prophesize(\RectorPrefix20210722\Composer\Package\PackageInterface::class);
$nonRectorExtensionPackageWithExtra->getType()->willReturn(null);
$nonRectorExtensionPackageWithExtra->getName()->willReturn('rector/foo');
$nonRectorExtensionPackageWithExtra->getFullPrettyVersion()->willReturn('rector/foo');
$nonRectorExtensionPackageWithExtra->getExtra()->willReturn([\Rector\RectorInstaller\PluginInstaller::RECTOR_EXTRA_KEY => ['includes' => ['config/config.php']]]);
$packages = [$rectorExtensionPackage, $nonRectorExtensionPackage, $nonRectorExtensionPackageWithExtra];
$this->io->write('<info>rector/rector-installer:</info> Extensions installed')->shouldBeCalledOnce();
$this->io->write(\sprintf('> <info>%s:</info> installed', 'rector/doctrine'))->shouldBeCalledOnce();
$this->io->write(\sprintf('> <info>%s:</info> installed', 'rector/foo'))->shouldBeCalledOnce();
$this->installationManager->getInstallPath($rectorExtensionPackage)->shouldBeCalledOnce();
$this->installationManager->getInstallPath($nonRectorExtensionPackageWithExtra)->shouldBeCalledOnce();
$this->filesystem->hashEquals(self::FILE_HASH, \RectorPrefix20210722\Prophecy\Argument::any())->willReturn(\false);
$this->filesystem->writeFile($this->configurationFile, \RectorPrefix20210722\Prophecy\Argument::any())->shouldBeCalledOnce();
$this->localRepository->getPackages()->willReturn($packages);
$this->pluginInstaller->install();
}
}

View File

@ -15,8 +15,8 @@
"symplify\/phpstan-rules": "^9.4",
"symplify\/phpstan-extensions": "^9.4",
"symplify\/easy-coding-standard": "^9.4",
"phpstan\/phpstan-nette": "^0.12.16",
"nette\/application": "^3.0.7",
"phpstan\/phpstan-nette": "^0.12.21",
"nette\/application": "^3.1",
"nette\/di": "^3.0",
"nette\/forms": "3.0.*",
"symplify\/rule-doc-generator": "^9.4",

View File

@ -70,6 +70,8 @@ final class AssignAnalyzer
$variable = new \PhpParser\Node\Expr\Variable($variableName);
$assignedArrayDimFetch = clone $arrayDimFetch;
$assign = new \PhpParser\Node\Expr\Assign($variable, $assignedArrayDimFetch);
$variable->setAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE, $assign);
$assignedArrayDimFetch->setAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE, $assign);
return new \PhpParser\Node\Stmt\Expression($assign);
}
}

View File

@ -3,6 +3,7 @@
declare (strict_types=1);
namespace Rector\Nette\NodeAnalyzer;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\FunctionLike;
@ -18,6 +19,10 @@ use Rector\NodeNestingScope\ScopeNestingComparator;
use Rector\NodeNestingScope\ValueObject\ControlStructure;
final class TemplatePropertyAssignCollector
{
/**
* @var array<class-string<\PhpParser\Node>>
*/
private const NODE_TYPES = \Rector\NodeNestingScope\ValueObject\ControlStructure::CONDITIONAL_NODE_SCOPE_TYPES + [\PhpParser\Node\FunctionLike::class];
/**
* @var \PhpParser\Node\Stmt\Return_|null
*/
@ -65,6 +70,21 @@ final class TemplatePropertyAssignCollector
}
return new \Rector\Nette\ValueObject\TemplateParametersAssigns($this->alwaysTemplateParameterAssigns, $this->conditionalTemplateParameterAssigns);
}
/**
* @return Node[]
*/
private function getFoundParents(\PhpParser\Node\Expr\PropertyFetch $propertyFetch) : array
{
$foundParents = [];
/** @var class-string<Node> $nodeType */
foreach (self::NODE_TYPES as $nodeType) {
$parentType = $this->betterNodeFinder->findParentType($propertyFetch->var, $nodeType);
if ($parentType instanceof \PhpParser\Node) {
$foundParents[] = $parentType;
}
}
return $foundParents;
}
private function collectVariableFromAssign(\PhpParser\Node\Expr\Assign $assign) : void
{
if (!$assign->var instanceof \PhpParser\Node\Expr\PropertyFetch) {
@ -75,18 +95,18 @@ final class TemplatePropertyAssignCollector
return;
}
$propertyFetch = $assign->var;
/** @var array<class-string<\PhpParser\Node>> $nodeTypes */
$nodeTypes = \Rector\NodeNestingScope\ValueObject\ControlStructure::CONDITIONAL_NODE_SCOPE_TYPES + [\PhpParser\Node\FunctionLike::class];
$foundParent = $this->betterNodeFinder->findParentTypes($propertyFetch->var, $nodeTypes);
if ($foundParent && $this->scopeNestingComparator->isInBothIfElseBranch($foundParent, $propertyFetch)) {
$this->conditionalTemplateParameterAssigns[] = new \Rector\Nette\ValueObject\ConditionalTemplateParameterAssign($assign, $parameterName);
return;
}
if ($foundParent instanceof \PhpParser\Node\Stmt\If_) {
return;
}
if ($foundParent instanceof \PhpParser\Node\Stmt\Else_) {
return;
$foundParents = $this->getFoundParents($propertyFetch);
foreach ($foundParents as $foundParent) {
if ($this->scopeNestingComparator->isInBothIfElseBranch($foundParent, $propertyFetch)) {
$this->conditionalTemplateParameterAssigns[] = new \Rector\Nette\ValueObject\ConditionalTemplateParameterAssign($assign, $parameterName);
return;
}
if ($foundParent instanceof \PhpParser\Node\Stmt\If_) {
return;
}
if ($foundParent instanceof \PhpParser\Node\Stmt\Else_) {
return;
}
}
// there is a return before this assign, to do not remove it and keep ti
if (!$this->returnAnalyzer->isBeforeLastReturn($assign, $this->lastReturn)) {

View File

@ -10,6 +10,7 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Scalar\String_;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\Rector\AbstractRector;
use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer;
use Rector\Renaming\NodeManipulator\IdentifierManipulator;
@ -73,35 +74,53 @@ final class AssertIssetToSpecificMethodRector extends \Rector\Core\Rector\Abstra
$issetNode = $node->args[0]->value;
$issetNodeArg = $issetNode->vars[0];
if ($issetNodeArg instanceof \PhpParser\Node\Expr\PropertyFetch) {
$this->refactorPropertyFetchNode($node, $issetNodeArg);
} elseif ($issetNodeArg instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
$this->refactorArrayDimFetchNode($node, $issetNodeArg);
if ($this->hasMagicIsset($issetNodeArg->var)) {
return null;
}
return $this->refactorPropertyFetchNode($node, $issetNodeArg);
}
if ($issetNodeArg instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
return $this->refactorArrayDimFetchNode($node, $issetNodeArg);
}
return $node;
}
private function hasMagicIsset(\PhpParser\Node $node) : bool
{
$resolved = $this->nodeTypeResolver->resolve($node);
if (!$resolved instanceof \PHPStan\Type\TypeWithClassName) {
return \false;
}
$reflection = $resolved->getClassReflection();
if ($reflection === null) {
return \false;
}
return $reflection->hasMethod('__isset');
}
/**
* @param MethodCall|StaticCall $node
*/
private function refactorPropertyFetchNode(\PhpParser\Node $node, \PhpParser\Node\Expr\PropertyFetch $propertyFetch) : void
private function refactorPropertyFetchNode(\PhpParser\Node $node, \PhpParser\Node\Expr\PropertyFetch $propertyFetch) : ?\PhpParser\Node
{
$name = $this->getName($propertyFetch);
if ($name === null) {
return;
return null;
}
$this->identifierManipulator->renameNodeWithMap($node, [self::ASSERT_TRUE => 'assertObjectHasAttribute', self::ASSERT_FALSE => 'assertObjectNotHasAttribute']);
$oldArgs = $node->args;
unset($oldArgs[0]);
$newArgs = $this->nodeFactory->createArgs([new \PhpParser\Node\Scalar\String_($name), $propertyFetch->var]);
$node->args = $this->appendArgs($newArgs, $oldArgs);
return $node;
}
/**
* @param MethodCall|StaticCall $node
*/
private function refactorArrayDimFetchNode(\PhpParser\Node $node, \PhpParser\Node\Expr\ArrayDimFetch $arrayDimFetch) : void
private function refactorArrayDimFetchNode(\PhpParser\Node $node, \PhpParser\Node\Expr\ArrayDimFetch $arrayDimFetch) : \PhpParser\Node
{
$this->identifierManipulator->renameNodeWithMap($node, [self::ASSERT_TRUE => 'assertArrayHasKey', self::ASSERT_FALSE => 'assertArrayNotHasKey']);
$oldArgs = $node->args;
unset($oldArgs[0]);
$node->args = \array_merge($this->nodeFactory->createArgs([$arrayDimFetch->dim, $arrayDimFetch->var]), $oldArgs);
return $node;
}
}

View File

@ -5,6 +5,7 @@ namespace Rector\PHPUnit\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
@ -97,7 +98,7 @@ CODE_SAMPLE
if (!$this->isName($node->name, 'withConsecutive')) {
return null;
}
if ($this->areAllArgArrayTypes($node)) {
if ($this->hasArrayArgType($node)) {
return null;
}
// is a mock?
@ -112,12 +113,10 @@ CODE_SAMPLE
if (!$this->reflectionProvider->hasClass($mockClass)) {
return null;
}
$classReflection = $this->reflectionProvider->getClass($mockClass);
$classReflection = $classReflection->getNativeReflection();
$reflectionMethod = $classReflection->getMethod($mockMethod);
$numberOfParameters = $reflectionMethod->getNumberOfParameters();
$numberOfParameters = $this->resolveNumberOfRequiredParameters($mockClass, $mockMethod);
$values = [];
foreach ($node->args as $arg) {
// already an array
$values[] = $arg->value;
}
// simple check argument count fits to method required args
@ -132,16 +131,18 @@ CODE_SAMPLE
}
return $node;
}
private function areAllArgArrayTypes(\PhpParser\Node\Expr\MethodCall $methodCall) : bool
private function hasArrayArgType(\PhpParser\Node\Expr\MethodCall $methodCall) : bool
{
foreach ($methodCall->args as $arg) {
if ($arg->value instanceof \PhpParser\Node\Expr\Array_) {
return \true;
}
$argumentStaticType = $this->getStaticType($arg->value);
if ($argumentStaticType instanceof \PHPStan\Type\ArrayType) {
continue;
return \true;
}
return \false;
}
return \true;
return \false;
}
private function inferMockedClassName(\PhpParser\Node\Expr\MethodCall $methodCall) : ?string
{
@ -179,7 +180,7 @@ CODE_SAMPLE
}
throw new \Rector\Core\Exception\ShouldNotHappenException();
}
private function findRootVariableOfChainCall(\PhpParser\Node\Expr\MethodCall $methodCall) : ?\PhpParser\Node\Expr\Variable
private function findRootVariableOfChainCall(\PhpParser\Node\Expr\MethodCall $methodCall) : \PhpParser\Node\Expr\Variable
{
$currentMethodCallee = $methodCall->var;
while (!$currentMethodCallee instanceof \PhpParser\Node\Expr\Variable) {
@ -187,4 +188,11 @@ CODE_SAMPLE
}
return $currentMethodCallee;
}
private function resolveNumberOfRequiredParameters(string $mockClass, string $mockMethod) : int
{
$classReflection = $this->reflectionProvider->getClass($mockClass);
$nativeClassReflection = $classReflection->getNativeReflection();
$reflectionMethod = $nativeClassReflection->getMethod($mockMethod);
return $reflectionMethod->getNumberOfParameters();
}
}

View File

@ -9,8 +9,8 @@ $loader = require_once __DIR__.'/autoload.php';
if (!class_exists('AutoloadIncluder', false) && !interface_exists('AutoloadIncluder', false) && !trait_exists('AutoloadIncluder', false)) {
spl_autoload_call('RectorPrefix20210722\AutoloadIncluder');
}
if (!class_exists('ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2', false) && !interface_exists('ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2', false) && !trait_exists('ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2', false)) {
spl_autoload_call('RectorPrefix20210722\ComposerAutoloaderInit735eb307678b1bf985488aa190e180a2');
if (!class_exists('ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c', false) && !interface_exists('ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c', false) && !trait_exists('ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c', false)) {
spl_autoload_call('RectorPrefix20210722\ComposerAutoloaderInitb51d21490f998eb5d663e8d169cd873c');
}
if (!class_exists('Doctrine\Inflector\Inflector', false) && !interface_exists('Doctrine\Inflector\Inflector', false) && !trait_exists('Doctrine\Inflector\Inflector', false)) {
spl_autoload_call('RectorPrefix20210722\Doctrine\Inflector\Inflector');
@ -3308,9 +3308,9 @@ if (!function_exists('print_node')) {
return \RectorPrefix20210722\print_node(...func_get_args());
}
}
if (!function_exists('composerRequire735eb307678b1bf985488aa190e180a2')) {
function composerRequire735eb307678b1bf985488aa190e180a2() {
return \RectorPrefix20210722\composerRequire735eb307678b1bf985488aa190e180a2(...func_get_args());
if (!function_exists('composerRequireb51d21490f998eb5d663e8d169cd873c')) {
function composerRequireb51d21490f998eb5d663e8d169cd873c() {
return \RectorPrefix20210722\composerRequireb51d21490f998eb5d663e8d169cd873c(...func_get_args());
}
}
if (!function_exists('parseArgs')) {

View File

@ -19,14 +19,14 @@
"phpstan\/extension-installer": "^1.1",
"phpunit\/phpunit": "^9.5",
"rector\/rector-generator": "^0.1.7",
"rector\/rector-phpstan-rules": "^0.3.4",
"rector\/phpstan-rules": "^0.3.4",
"rector\/rector-src": "dev-main",
"symfony\/console": "^5.3.x-dev",
"symplify\/coding-standard": "^9.3",
"symplify\/easy-coding-standard": "^9.3",
"symplify\/phpstan-extensions": "^9.3",
"symplify\/phpstan-rules": "^9.3",
"symplify\/rule-doc-generator": "^9.3",
"symplify\/coding-standard": "^9.4.22",
"symplify\/easy-coding-standard": "^9.4.22",
"symplify\/phpstan-extensions": "^9.4.22",
"symplify\/phpstan-rules": "^9.4.22",
"symplify\/rule-doc-generator": "^9.4.22",
"tracy\/tracy": "^2.8"
},
"autoload": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,7 @@ use RectorPrefix20210722\Helmich\TypoScriptParser\Parser\Printer\PrettyPrinter;
use RectorPrefix20210722\Helmich\TypoScriptParser\Parser\Traverser\Traverser;
use RectorPrefix20210722\Helmich\TypoScriptParser\Tokenizer\Tokenizer;
use RectorPrefix20210722\Helmich\TypoScriptParser\Tokenizer\TokenizerInterface;
use Rector\RectorGenerator\FileSystem\ConfigFilesystem;
use Ssch\TYPO3Rector\FileProcessor\TypoScript\TypoScriptFileProcessor;
use RectorPrefix20210722\Symfony\Component\Console\Output\BufferedOutput;
use RectorPrefix20210722\Symfony\Component\Console\Output\OutputInterface;
@ -31,4 +32,8 @@ return static function (\Symfony\Component\DependencyInjection\Loader\Configurat
$services->alias(\RectorPrefix20210722\Symfony\Component\Console\Output\OutputInterface::class, \RectorPrefix20210722\Symfony\Component\Console\Output\BufferedOutput::class);
$services->set(\RectorPrefix20210722\Helmich\TypoScriptParser\Parser\AST\Builder::class);
$services->set(\Ssch\TYPO3Rector\FileProcessor\TypoScript\TypoScriptFileProcessor::class)->call('configure', [[\Ssch\TYPO3Rector\FileProcessor\TypoScript\TypoScriptFileProcessor::ALLOWED_FILE_EXTENSIONS => ['typoscript', 'ts', 'txt', 'pagets', 'constantsts', 'setupts', 'tsconfig', 't3s', 't3c', 'typoscriptconstants', 'typoscriptsetupts']]]);
// custom generator
$services->set(\Rector\RectorGenerator\FileSystem\ConfigFilesystem::class);
$services->set(\Rector\RectorGenerator\TemplateFactory::class);
$services->set(\PhpParser\PrettyPrinter\Standard::class);
};

View File

@ -2284,7 +2284,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
## RemoveColPosParameterRector
Remove parameter colPos from methods.
Remove parameter `$colPos` from methods.
- class: [`Ssch\TYPO3Rector\Rector\v9\v3\RemoveColPosParameterRector`](../src/Rector/v9/v3/RemoveColPosParameterRector.php)

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\Resources\Icons;
use RectorPrefix20210722\Nette\Utils\Strings;
use Rector\Core\Contract\Processor\FileProcessorInterface;
use Rector\Core\ValueObject\Application\File;
use Rector\Core\ValueObject\Configuration;
@ -55,7 +54,7 @@ final class IconsFileProcessor implements \Rector\Core\Contract\Processor\FilePr
public function supports($file, $configuration) : bool
{
$smartFileInfo = $file->getSmartFileInfo();
if (!\RectorPrefix20210722\Nette\Utils\Strings::contains($smartFileInfo->getFilename(), 'ext_icon')) {
if (\strpos($smartFileInfo->getFilename(), 'ext_icon') === \false) {
return \false;
}
$extEmConfSmartFileInfo = $this->filesFinder->findExtEmConfRelativeFromGivenFileInfo($smartFileInfo);

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
abstract class AbstractGlobalConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
@ -11,7 +10,7 @@ abstract class AbstractGlobalConditionMatcher implements \Ssch\TYPO3Rector\Contr
/**
* @var array<string, string>
*/
public const IENV_MAPPING_NORMALIZED = ['SCRIPT_NAME' => 'getScriptName', 'SCRIPT_FILENAME' => 'getScriptFilename', 'REQUEST_URI' => 'getRequestUri', 'TYPO3_REV_PROXY' => 'isBehindReverseProxy', 'REMOTE_ADDR' => 'getRemoteAddress', 'HTTP_HOST' => 'getHttpHost', 'TYPO3_DOCUMENT_ROOT' => 'getDocumentRoot', 'TYPO3_HOST_ONLY' => 'getRequestHostOnly', 'TYPO3_PORT' => 'getRequestPort', 'TYPO3_REQUEST_HOST' => 'getRequestHost', 'TYPO3_REQUEST_URL' => 'getRequestUrl', 'TYPO3_REQUEST_SCRIPT' => 'getRequestScript', 'TYPO3_REQUEST_DIR' => 'getRequestDir', 'TYPO3_SITE_URL' => 'getSiteUrl', 'TYPO3_SITE_PATH' => 'getSitePath', 'TYPO3_SITE_SCRIPT' => 'getSiteScript', 'TYPO3_SSL' => 'isHttps', 'PATH_INFO' => 'getScriptName'];
public const IENV_MAPPING_NORMALIZED = ['SCRIPT_NAME' => 'getScriptName', 'SCRIPT_FILENAME' => 'getScriptFilename', 'REQUEST_URI' => 'getRequestUri', 'TYPO3_REV_PROXY' => 'isBehindReverseProxy', 'REMOTE_ADDR' => 'getRemoteAddress', 'HTTP_HOST' => 'getHttpHost', 'TYPO3_DOCUMENT_ROOT' => 'getDocumentRoot', 'TYPO3_HOST_ONLY' => 'getRequestHostOnly', 'TYPO3_PORT' => 'getRequestPort', 'TYPO3_REQUEST_HOST' => 'getRequestHost', 'TYPO3_REQUEST_URL' => 'getRequestUrl', 'TYPO3_REQUEST_SCRIPT' => 'getRequestScript', 'TYPO3_REQUEST_DIR' => 'getRequestDir', 'TYPO3_SITE_URL' => 'getSiteUrl', 'TYPO3_SITE_PATH' => 'getSitePath', 'TYPO3_SITE_SCRIPT' => 'getSiteScript', 'TYPO3_SSL' => 'isHttps', 'HTTPS' => 'isHttps', 'PATH_INFO' => 'getScriptName'];
/**
* @var string[]
*/
@ -27,7 +26,7 @@ abstract class AbstractGlobalConditionMatcher implements \Ssch\TYPO3Rector\Contr
*/
protected function refactorTsfe($property, $operator, $value) : string
{
if (\RectorPrefix20210722\Nette\Utils\Strings::startsWith($property, 'page')) {
if (\strncmp($property, 'page', \strlen('page')) === 0) {
$parameters = \Ssch\TYPO3Rector\Helper\ArrayUtility::trimExplode('|', $property, \true);
return \sprintf('page["%s"] %s %s', $parameters[1], self::OPERATOR_MAPPING[$operator], $value);
}
@ -51,17 +50,17 @@ abstract class AbstractGlobalConditionMatcher implements \Ssch\TYPO3Rector\Contr
{
$condition = 'ERROR not implemented';
if (\array_key_exists($property, self::IENV_MAPPING_NORMALIZED)) {
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($value, '*')) {
if (\strpos($value, '*') !== \false) {
return \sprintf('like(request.getNormalizedParams().%s(), "%s")', self::IENV_MAPPING_NORMALIZED[$property], $value);
}
if (\RectorPrefix20210722\Nette\Utils\Strings::startsWith(self::IENV_MAPPING_NORMALIZED[$property], 'get')) {
if (\strncmp(self::IENV_MAPPING_NORMALIZED[$property], 'get', \strlen('get')) === 0) {
$condition = \sprintf('request.getNormalizedParams().%s() %s "%s"', self::IENV_MAPPING_NORMALIZED[$property], self::OPERATOR_MAPPING[$operator], $value);
} else {
$condition = \sprintf('request.getNormalizedParams().%s()', self::IENV_MAPPING_NORMALIZED[$property]);
}
}
if (\in_array($property, self::IENV_KEEP_SERVER_PARAMS, \true)) {
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($value, '*')) {
if (\strpos($value, '*') !== \false) {
return \sprintf('like(request.getServerParams()[\'%s\'], "%s")', $property, $value);
}
$condition = \sprintf('request.getServerParams()[\'%s\'] %s "%s"', $property, self::OPERATOR_MAPPING[$operator], $value);

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
abstract class AbstractRootlineConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
@ -29,10 +28,10 @@ abstract class AbstractRootlineConditionMatcher implements \Ssch\TYPO3Rector\Con
*/
public function shouldApply($condition) : bool
{
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($condition, self::CONTAINS_CONSTANT)) {
if (\strpos($condition, self::CONTAINS_CONSTANT) !== \false) {
return \false;
}
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, $this->getType());
return \strncmp($condition, $this->getType(), \strlen($this->getType())) === 0;
}
protected abstract function getType() : string;
protected abstract function getExpression() : string;

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
final class AdminUserConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
{
@ -31,6 +30,6 @@ final class AdminUserConditionMatcher implements \Ssch\TYPO3Rector\Contract\File
*/
public function shouldApply($condition) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
final class ApplicationContextConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
@ -37,7 +36,7 @@ final class ApplicationContextConditionMatcher implements \Ssch\TYPO3Rector\Cont
*/
public function shouldApply($condition) : bool
{
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($condition, self::CONTAINS_CONSTANT)) {
if (\strpos($condition, self::CONTAINS_CONSTANT) !== \false) {
return \false;
}
return 1 === \preg_match('#^' . self::TYPE . self::ZERO_ONE_OR_MORE_WHITESPACES . '=[^=]#', $condition);

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
final class BrowserConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
{
@ -23,6 +22,6 @@ final class BrowserConditionMatcher implements \Ssch\TYPO3Rector\Contract\FilePr
*/
public function shouldApply($condition) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
final class CompatVersionConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
{
@ -27,6 +26,6 @@ final class CompatVersionConditionMatcher implements \Ssch\TYPO3Rector\Contract\
*/
public function shouldApply($condition) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
final class GlobalStringConditionMatcher extends \Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions\AbstractGlobalConditionMatcher
{
@ -56,10 +55,10 @@ final class GlobalStringConditionMatcher extends \Ssch\TYPO3Rector\FileProcessor
*/
public function shouldApply($condition) : bool
{
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($condition, self::CONTAINS_CONSTANT)) {
if (\strpos($condition, self::CONTAINS_CONSTANT) !== \false) {
return \false;
}
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
private function refactorGetPost(string $property, string $operator, string $value) : string
{

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Rector\Core\Exception\ShouldNotHappenException;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
final class GlobalVarConditionMatcher extends \Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions\AbstractGlobalConditionMatcher
@ -91,7 +90,7 @@ final class GlobalVarConditionMatcher extends \Ssch\TYPO3Rector\FileProcessor\Ty
*/
public function shouldApply($condition) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
private function refactorGetPost(string $property, string $operator, string $value) : string
{
@ -109,7 +108,7 @@ final class GlobalVarConditionMatcher extends \Ssch\TYPO3Rector\FileProcessor\Ty
}
private function createBackendUserCondition(string $property, string $operator, string $value) : string
{
$delimiter = \RectorPrefix20210722\Nette\Utils\Strings::contains($property, ':') ? ':' : '|';
$delimiter = \strpos($property, ':') !== \false ? ':' : '|';
[, $property] = \Ssch\TYPO3Rector\Helper\ArrayUtility::trimExplode($delimiter, $property, \true, 2);
if (!\array_key_exists($property, self::USER_PROPERTY_MAPPING)) {
$message = \sprintf('The property "%s" can not be mapped for condition BE_USER', $property);

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
final class HostnameConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
@ -24,7 +23,7 @@ final class HostnameConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileP
$values = \Ssch\TYPO3Rector\Helper\ArrayUtility::trimExplode(',', $matches[1], \true);
$newConditions = [];
foreach ($values as $value) {
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($value, '*')) {
if (\strpos($value, '*') !== \false) {
$newConditions[] = \sprintf('like(request.getNormalizedParams().getHttpHost(), "%s")', $value);
} else {
$newConditions[] = \sprintf('request.getNormalizedParams().getHttpHost() == "%s"', $value);
@ -37,7 +36,7 @@ final class HostnameConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileP
*/
public function shouldApply($condition) : bool
{
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($condition, self::CONTAINS_CONSTANT)) {
if (\strpos($condition, self::CONTAINS_CONSTANT) !== \false) {
return \false;
}
return 1 === \preg_match('#^' . self::TYPE . self::ZERO_ONE_OR_MORE_WHITESPACES . '=[^=]#', $condition);

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
final class IPConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
@ -29,9 +28,9 @@ final class IPConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcess
*/
public function shouldApply($condition) : bool
{
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($condition, self::CONTAINS_CONSTANT)) {
if (\strpos($condition, self::CONTAINS_CONSTANT) !== \false) {
return \false;
}
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
final class LanguageConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
{
@ -27,6 +26,6 @@ final class LanguageConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileP
*/
public function shouldApply($condition) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
use Ssch\TYPO3Rector\Helper\ArrayUtility;
final class TreeLevelConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
@ -29,9 +28,9 @@ final class TreeLevelConditionMatcher implements \Ssch\TYPO3Rector\Contract\File
*/
public function shouldApply($condition) : bool
{
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($condition, self::CONTAINS_CONSTANT)) {
if (\strpos($condition, self::CONTAINS_CONSTANT) !== \false) {
return \false;
}
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Conditions;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher;
final class VersionConditionMatcher implements \Ssch\TYPO3Rector\Contract\FileProcessor\TypoScript\Conditions\TyposcriptConditionMatcher
{
@ -23,6 +22,6 @@ final class VersionConditionMatcher implements \Ssch\TYPO3Rector\Contract\FilePr
*/
public function shouldApply($condition) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::startsWith($condition, self::TYPE);
return \strncmp($condition, self::TYPE, \strlen(self::TYPE)) === 0;
}
}

View File

@ -5,7 +5,6 @@ namespace Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector;
use RectorPrefix20210722\Helmich\TypoScriptParser\Parser\AST\Operator\Assignment;
use RectorPrefix20210722\Helmich\TypoScriptParser\Parser\AST\Statement;
use RectorPrefix20210722\Nette\Utils\Strings;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
@ -18,7 +17,7 @@ final class AdditionalHeadersToArrayTypoScriptRector extends \Ssch\TYPO3Rector\F
if (!$statement instanceof \RectorPrefix20210722\Helmich\TypoScriptParser\Parser\AST\Operator\Assignment) {
return;
}
if (!\RectorPrefix20210722\Nette\Utils\Strings::startsWith($statement->object->relativeName, 'additionalHeaders')) {
if (\strncmp($statement->object->relativeName, 'additionalHeaders', \strlen('additionalHeaders')) !== 0) {
return;
}
$this->hasChanged = \true;

View File

@ -51,7 +51,7 @@ final class ExtbasePersistenceTypoScriptRector extends \Ssch\TYPO3Rector\FilePro
if (!$statement instanceof \RectorPrefix20210722\Helmich\TypoScriptParser\Parser\AST\Operator\Assignment) {
return;
}
if (!\RectorPrefix20210722\Nette\Utils\Strings::contains($statement->object->absoluteName, 'persistence.classes')) {
if (\strpos($statement->object->absoluteName, 'persistence.classes') === \false) {
return;
}
$paths = \explode('.', $statement->object->absoluteName);

View File

@ -149,9 +149,9 @@ final class TypoScriptFileProcessor implements \Ssch\TYPO3Rector\Contract\Proces
$this->typoscriptPrinter->printStatements($originalStatements, $this->output);
$typoScriptContent = \rtrim($this->output->fetch()) . $editorConfiguration->getNewLine();
$file->changeFileContent($typoScriptContent);
} catch (\RectorPrefix20210722\Helmich\TypoScriptParser\Tokenizer\TokenizerException $tokenizerException) {
} catch (\RectorPrefix20210722\Helmich\TypoScriptParser\Tokenizer\TokenizerException $exception) {
return;
} catch (\RectorPrefix20210722\Helmich\TypoScriptParser\Parser\ParseError $parseError) {
} catch (\RectorPrefix20210722\Helmich\TypoScriptParser\Parser\ParseError $exception) {
$smartFileInfo = $file->getSmartFileInfo();
$errorFile = $smartFileInfo->getRelativeFilePath();
$this->rectorOutputStyle->warning(\sprintf('TypoScriptParser Error in: %s. File skipped.', $errorFile));

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\Yaml\Form;
use RectorPrefix20210722\Nette\Utils\Strings;
use Rector\Core\Contract\Processor\FileProcessorInterface;
use Rector\Core\Provider\CurrentFileProvider;
use Rector\Core\ValueObject\Application\File;
@ -69,7 +68,7 @@ final class FormYamlFileProcessor implements \Rector\Core\Contract\Processor\Fil
public function supports($file, $configuration) : bool
{
$smartFileInfo = $file->getSmartFileInfo();
return \RectorPrefix20210722\Nette\Utils\Strings::endsWith($smartFileInfo->getFilename(), 'yaml');
return \substr_compare($smartFileInfo->getFilename(), 'yaml', -\strlen('yaml')) === 0;
}
/**
* @return string[]

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\FileProcessor\Yaml\Form\Rector;
use RectorPrefix20210722\Nette\Utils\Strings;
use Ssch\TYPO3Rector\Contract\FileProcessor\Yaml\Form\FormYamlRectorInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -79,7 +78,7 @@ CODE_SAMPLE
{
$newTranslations = [];
foreach ($oldTranslations as $oldTranslationFileKey => $oldTranslationFile) {
if (!\RectorPrefix20210722\Nette\Utils\Strings::startsWith($oldTranslationFile, 'EXT:form')) {
if (\strncmp($oldTranslationFile, 'EXT:form', \strlen('EXT:form')) !== 0) {
$newTranslations[$oldTranslationFileKey] = $oldTranslationFile;
}
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\Helper;
use RectorPrefix20210722\Nette\Utils\Strings;
use RectorPrefix20210722\Symplify\EasyTesting\PHPUnit\StaticPHPUnitEnvironment;
use Symplify\SmartFileSystem\SmartFileInfo;
final class FilesFinder
@ -67,6 +66,6 @@ final class FilesFinder
}
private function endsWith(\Symplify\SmartFileSystem\SmartFileInfo $fileInfo, string $needle) : bool
{
return \RectorPrefix20210722\Nette\Utils\Strings::endsWith($fileInfo->getFilename(), $needle);
return \substr_compare($fileInfo->getFilename(), $needle, -\strlen($needle)) === 0;
}
}

View File

@ -210,7 +210,7 @@ final class InitializeArgumentsClassMethodFactory
}
$phpStanType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($paramTagValueNode->type, $param);
$docString = $phpStanType->describe(\PHPStan\Type\VerbosityLevel::typeOnly());
if ('[]' === \substr($docString, -2)) {
if (\substr_compare($docString, '[]', -\strlen('[]')) === 0) {
return 'array';
}
return $docString;

View File

@ -7,6 +7,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Nop;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ObjectType;
@ -36,6 +37,11 @@ final class ConfigurationManagerAddControllerConfigurationMethodRector extends \
if (!$this->isObjectType($node, new \PHPStan\Type\ObjectType('TYPO3\\CMS\\Extbase\\Configuration\\AbstractConfigurationManager'))) {
return null;
}
// already checked
$classMethod = $node->getMethod('getControllerConfiguration');
if ($classMethod instanceof \PhpParser\Node\Stmt\ClassMethod) {
return null;
}
$this->addMethodGetControllerConfiguration($node);
return $node;
}

View File

@ -59,7 +59,7 @@ final class ForceTemplateParsingInTsfeAndTemplateServiceRector extends \Rector\C
$this->addNodeAfterNode($contextCall, $node);
try {
$this->removeNode($node);
} catch (\Rector\Core\Exception\ShouldNotHappenException $shouldNotHappenException) {
} catch (\Rector\Core\Exception\ShouldNotHappenException $exception) {
$parentNode = $node->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE);
$this->removeNode($parentNode);
}

View File

@ -9,6 +9,7 @@ use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Nop;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\ObjectType;
@ -58,6 +59,11 @@ final class InjectEnvironmentServiceIfNeededInResponseRector extends \Rector\Cor
if (!$this->isPropertyEnvironmentServiceInUse($node)) {
return null;
}
// already added
$classMethod = $node->getMethod('injectEnvironmentService');
if ($classMethod instanceof \PhpParser\Node\Stmt\ClassMethod) {
return null;
}
$this->addInjectEnvironmentServiceMethod($node);
$property = $this->createEnvironmentServiceProperty();
$this->addNodeAfterNode(new \PhpParser\Node\Stmt\Nop(), $property);

View File

@ -70,16 +70,16 @@ CODE_SAMPLE
)]);
}
/**
* @param ConstFetch|StaticCall $node
* @param \PhpParser\Node\Expr\ConstFetch|\PhpParser\Node\Expr\StaticCall $node
*/
public function isMethodVerifyFilenameAgainstDenyPattern(\PhpParser\Node $node) : bool
public function isMethodVerifyFilenameAgainstDenyPattern($node) : bool
{
return $node instanceof \PhpParser\Node\Expr\StaticCall && $this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType($node, new \PHPStan\Type\ObjectType('TYPO3\\CMS\\Core\\Utility\\GeneralUtility')) && $this->isName($node->name, 'verifyFilenameAgainstDenyPattern');
}
/**
* @param ConstFetch|StaticCall $node
* @param \PhpParser\Node\Expr\ConstFetch|\PhpParser\Node\Expr\StaticCall $node
*/
private function shouldSkip(\PhpParser\Node $node) : bool
private function shouldSkip($node) : bool
{
if ($this->isMethodVerifyFilenameAgainstDenyPattern($node)) {
return \false;
@ -87,9 +87,9 @@ CODE_SAMPLE
return !$this->isConstFileDenyPatternDefault($node);
}
/**
* @param ConstFetch|StaticCall $node
* @param \PhpParser\Node\Expr\ConstFetch|\PhpParser\Node\Expr\StaticCall $node
*/
private function isConstFileDenyPatternDefault(\PhpParser\Node $node) : bool
private function isConstFileDenyPatternDefault($node) : bool
{
return $node instanceof \PhpParser\Node\Expr\ConstFetch && $this->isName($node->name, 'FILE_DENY_PATTERN_DEFAULT');
}

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\Rector\v11\v0;
use RectorPrefix20210722\Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Exit_;
use PhpParser\Node\Expr\FuncCall;
@ -12,7 +11,6 @@ use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -46,21 +44,19 @@ final class ExtbaseControllerActionsMustReturnResponseInterfaceRector extends \R
if ($this->shouldSkip($node)) {
return null;
}
foreach ($this->extractReturnCalls($node) as $returnCall) {
if (!$returnCall instanceof \PhpParser\Node\Stmt\Return_) {
continue;
}
$returnCallExpression = $returnCall->expr;
$returns = $this->findReturns($node);
foreach ($returns as $return) {
$returnCallExpression = $return->expr;
if ($returnCallExpression instanceof \PhpParser\Node\Expr\FuncCall && $this->isName($returnCallExpression->name, 'json_encode')) {
$returnCall->expr = $this->nodeFactory->createMethodCall($this->nodeFactory->createPropertyFetch(self::THIS, 'responseFactory'), 'createJsonResponse', [$returnCall->expr]);
$return->expr = $this->nodeFactory->createMethodCall($this->nodeFactory->createPropertyFetch(self::THIS, 'responseFactory'), 'createJsonResponse', [$return->expr]);
} else {
// avoid duplication
if ($returnCall->expr instanceof \PhpParser\Node\Expr\MethodCall && $this->isName($returnCall->expr->name, self::HTML_RESPONSE)) {
if ($return->expr instanceof \PhpParser\Node\Expr\MethodCall && $this->isName($return->expr->name, self::HTML_RESPONSE)) {
$args = [];
} else {
$args = [$returnCall->expr];
$args = [$return->expr];
}
$returnCall->expr = $this->nodeFactory->createMethodCall(self::THIS, self::HTML_RESPONSE, $args);
$return->expr = $this->nodeFactory->createMethodCall(self::THIS, self::HTML_RESPONSE, $args);
}
}
$node->returnType = new \PhpParser\Node\Name\FullyQualified('Psr\\Http\\Message\\ResponseInterface');
@ -116,10 +112,10 @@ CODE_SAMPLE
if (null === $methodName) {
return \true;
}
if (!\RectorPrefix20210722\Nette\Utils\Strings::endsWith($methodName, 'Action')) {
if (\substr_compare($methodName, 'Action', -\strlen('Action')) !== 0) {
return \true;
}
if (\RectorPrefix20210722\Nette\Utils\Strings::startsWith($methodName, 'initialize')) {
if (\strncmp($methodName, 'initialize', \strlen('initialize')) === 0) {
return \true;
}
if ($this->hasExitCall($node)) {
@ -131,13 +127,11 @@ CODE_SAMPLE
return $this->alreadyResponseReturnType($node);
}
/**
* @return Return_[]|Node[]
* @return Return_[]
*/
private function extractReturnCalls(\PhpParser\Node\Stmt\ClassMethod $node) : array
private function findReturns(\PhpParser\Node\Stmt\ClassMethod $classMethod) : array
{
return $this->betterNodeFinder->find((array) $node->stmts, function (\PhpParser\Node $node) : bool {
return $node instanceof \PhpParser\Node\Stmt\Return_;
});
return $this->betterNodeFinder->findInstanceOf((array) $classMethod->stmts, \PhpParser\Node\Stmt\Return_::class);
}
private function hasRedirectCall(\PhpParser\Node\Stmt\ClassMethod $node) : bool
{
@ -159,18 +153,14 @@ CODE_SAMPLE
}
private function alreadyResponseReturnType(\PhpParser\Node\Stmt\ClassMethod $node) : bool
{
foreach ($this->extractReturnCalls($node) as $returnCall) {
if (!$returnCall instanceof \PhpParser\Node\Stmt\Return_) {
$returns = $this->findReturns($node);
$responseObjectType = new \PHPStan\Type\ObjectType('Psr\\Http\\Message\\ResponseInterface');
foreach ($returns as $return) {
if (null === $return->expr) {
continue;
}
if (null === $returnCall->expr) {
continue;
}
$returnType = $this->nodeTypeResolver->getStaticType($returnCall->expr);
if (!$returnType instanceof \PHPStan\Type\TypeWithClassName) {
continue;
}
if ($returnType->isSuperTypeOf(new \PHPStan\Type\ObjectType('Psr\\Http\\Message\\ResponseInterface'))->yes()) {
$returnType = $this->nodeTypeResolver->getStaticType($return->expr);
if ($returnType->isSuperTypeOf($responseObjectType)->yes()) {
return \true;
}
}

View File

@ -100,7 +100,7 @@ CODE_SAMPLE
// If it is the only method call, we can safely delete the node here.
$this->removeNode($node);
return $node;
} catch (\Rector\Core\Exception\ShouldNotHappenException $shouldNotHappenException) {
} catch (\Rector\Core\Exception\ShouldNotHappenException $exception) {
$chainMethodCalls = $this->fluentChainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($node);
if (!$this->sameClassMethodCallAnalyzer->haveSingleClass($chainMethodCalls)) {
return null;

View File

@ -74,7 +74,7 @@ CODE_SAMPLE
// If it is the only method call, we can safely delete the node here.
$this->removeNode($node);
return $node;
} catch (\Rector\Core\Exception\ShouldNotHappenException $shouldNotHappenException) {
} catch (\Rector\Core\Exception\ShouldNotHappenException $exception) {
$chainMethodCalls = $this->fluentChainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($node);
if (!$this->sameClassMethodCallAnalyzer->haveSingleClass($chainMethodCalls)) {
return null;

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\Rector\v7\v4;
use RectorPrefix20210722\Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Rector\AbstractRector;
@ -54,7 +53,7 @@ CODE_SAMPLE
}
foreach (self::MAPPING_OLD_TO_NEW_PATHS as $oldPath => $newPath) {
$oldPathPrefixed = \sprintf('LLL:EXT:%s', $oldPath);
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($value, $oldPathPrefixed)) {
if (\strpos($value, $oldPathPrefixed) !== \false) {
$newPathPrefixed = \sprintf('LLL:EXT:%s', $newPath);
return new \PhpParser\Node\Scalar\String_(\str_replace($oldPathPrefixed, $newPathPrefixed, $value));
}

View File

@ -46,18 +46,17 @@ final class RenamePiListBrowserResultsRector extends \Rector\Core\Rector\Abstrac
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Rename pi_list_browseresults calls to renderPagination', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample('$this->pi_list_browseresults', '$this->renderPagination')]);
}
/**
* @param string|mixed[] $newMethod
*
* @return MethodCall|ArrayDimFetch
* @param string|string[] $newMethodNames
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\ArrayDimFetch
*/
private function process(\PhpParser\Node\Expr\MethodCall $node, $newMethod) : \PhpParser\Node
private function process(\PhpParser\Node\Expr\MethodCall $methodCall, $newMethodNames)
{
if (\is_string($newMethod)) {
$node->name = new \PhpParser\Node\Identifier($newMethod);
return $node;
if (\is_string($newMethodNames)) {
$methodCall->name = new \PhpParser\Node\Identifier($newMethodNames);
return $methodCall;
}
// special case for array dim fetch
$node->name = new \PhpParser\Node\Identifier($newMethod['name']);
return new \PhpParser\Node\Expr\ArrayDimFetch($node, \PhpParser\BuilderHelpers::normalizeValue($newMethod['array_key']));
$methodCall->name = new \PhpParser\Node\Identifier($newMethodNames['name']);
return new \PhpParser\Node\Expr\ArrayDimFetch($methodCall, \PhpParser\BuilderHelpers::normalizeValue($newMethodNames['array_key']));
}
}

View File

@ -118,16 +118,16 @@ CODE_SAMPLE
)]);
}
/**
* @param StaticCall|MethodCall $node
* @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $node
*/
public function removeMethods(\PhpParser\Node $node) : void
public function removeMethods($node) : void
{
if ($this->isNames($node->name, self::REMOVED_METHODS)) {
$methodName = $this->getName($node->name);
if (null !== $methodName) {
try {
$this->removeNode($node);
} catch (\Rector\Core\Exception\ShouldNotHappenException $shouldNotHappenException) {
} catch (\Rector\Core\Exception\ShouldNotHappenException $exception) {
$parentNode = $node->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE);
$this->removeNode($parentNode);
}
@ -135,9 +135,9 @@ CODE_SAMPLE
}
}
/**
* @param StaticCall|MethodCall $node
* @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $node
*/
public function renameMethod(\PhpParser\Node $node) : void
public function renameMethod($node) : void
{
if ($this->isName($node->name, self::RENAMED_METHOD)) {
$methodName = $this->getName($node->name);
@ -147,9 +147,9 @@ CODE_SAMPLE
}
}
/**
* @param StaticCall|MethodCall $node
* @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $node
*/
private function migrateMethodsToMarkerBasedTemplateService(\PhpParser\Node $node) : ?\PhpParser\Node
private function migrateMethodsToMarkerBasedTemplateService($node) : ?\PhpParser\Node
{
if ($this->isNames($node->name, self::MOVED_METHODS_TO_MARKER_BASED_TEMPLATES)) {
$methodName = $this->getName($node->name);
@ -162,9 +162,9 @@ CODE_SAMPLE
return null;
}
/**
* @param StaticCall|MethodCall $node
* @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $node
*/
private function shouldSkip(\PhpParser\Node $node) : bool
private function shouldSkip($node) : bool
{
$skip = \false;
if (!$this->isNames($node->name, self::MOVED_METHODS_TO_MARKER_BASED_TEMPLATES) && !$this->isNames($node->name, self::REMOVED_METHODS) && !$this->isName($node->name, self::RENAMED_METHOD)) {

View File

@ -68,7 +68,7 @@ CODE_SAMPLE
)]);
}
/**
* @param MethodCall|PropertyFetch $node
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\PropertyFetch $node
*/
private function shouldSkip($node) : bool
{

View File

@ -41,7 +41,7 @@ final class RemoveRteHtmlParserEvalWriteFileRector extends \Rector\Core\Rector\A
try {
$this->removeNode($node);
return $node;
} catch (\Rector\Core\Exception\ShouldNotHappenException $shouldNotHappenException) {
} catch (\Rector\Core\Exception\ShouldNotHappenException $exception) {
$parentNode = $node->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::PARENT_NODE);
$this->removeNode($parentNode);
return $node;

View File

@ -3,7 +3,6 @@
declare (strict_types=1);
namespace Ssch\TYPO3Rector\Rector\v8\v5;
use RectorPrefix20210722\Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Rector\AbstractRector;
@ -33,7 +32,7 @@ final class MoveLanguageFilesFromLocallangToResourcesRector extends \Rector\Core
{
$value = $this->valueResolver->getValue($node);
foreach (self::MAPPING_OLD_TO_NEW_PATHS as $oldPath => $newPath) {
if (\RectorPrefix20210722\Nette\Utils\Strings::contains($value, $oldPath)) {
if (\strpos($value, $oldPath) !== \false) {
return new \PhpParser\Node\Scalar\String_(\str_replace($oldPath, $newPath, $value));
}
}

Some files were not shown because too many files have changed in this diff Show More