�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!RectorNamingInflector.php000064400000001707152535021720011522 0ustar00.+)(?Data|Info)$#'; public function __construct(Inflector $inflector) { $this->inflector = $inflector; } public function singularize(string $name) : string { $matches = Strings::match($name, self::DATA_INFO_SUFFIX_REGEX); if ($matches === null) { return $this->inflector->singularize($name); } $singularized = $this->inflector->singularize($matches['prefix']); $uninflectable = $matches['suffix']; return $singularized . $uninflectable; } } Rector/Foreach_/RenameForeachValueVariableToMatchExprVariableRector.php000064400000011670152535021720022336 0ustar00inflectorSingularResolver = $inflectorSingularResolver; $this->propertyFetchAnalyzer = $propertyFetchAnalyzer; $this->stmtsManipulator = $stmtsManipulator; $this->betterNodeFinder = $betterNodeFinder; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Renames value variable name in foreach loop to match expression variable', [new CodeSample(<<<'CODE_SAMPLE' class SomeClass { public function run() { $array = []; foreach ($variables as $property) { $array[] = $property; } } } CODE_SAMPLE , <<<'CODE_SAMPLE' class SomeClass { public function run() { $array = []; foreach ($variables as $variable) { $array[] = $variable; } } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [StmtsAwareInterface::class]; } /** * @param StmtsAwareInterface $node */ public function refactor(Node $node) : ?Node { if ($node->stmts === null) { return null; } $hasChanged = \false; foreach ($node->stmts as $key => $stmt) { if (!$stmt instanceof Foreach_) { continue; } $isPropertyFetch = $this->propertyFetchAnalyzer->isLocalPropertyFetch($stmt->expr); if (!$stmt->expr instanceof Variable && !$isPropertyFetch) { continue; } $exprName = $this->getName($stmt->expr); if ($exprName === null) { continue; } if ($stmt->keyVar instanceof Node) { continue; } $valueVarName = $this->getName($stmt->valueVar); if ($valueVarName === null) { continue; } $singularValueVarName = $this->inflectorSingularResolver->resolve($exprName); if ($singularValueVarName === $exprName) { continue; } if ($singularValueVarName === $valueVarName) { continue; } $alreadyUsedVariable = $this->betterNodeFinder->findVariableOfName($stmt->stmts, $singularValueVarName); if ($alreadyUsedVariable instanceof Variable) { continue; } if ($this->stmtsManipulator->isVariableUsedInNextStmt($node, $key + 1, $singularValueVarName)) { continue; } if ($this->stmtsManipulator->isVariableUsedInNextStmt($node, $key + 1, $valueVarName)) { continue; } $this->processRename($stmt, $valueVarName, $singularValueVarName); $hasChanged = \true; } if ($hasChanged) { return $node; } return null; } private function processRename(Foreach_ $foreach, string $valueVarName, string $singularValueVarName) : void { $foreach->valueVar = new Variable($singularValueVarName); $this->traverseNodesWithCallable($foreach->stmts, function (Node $node) use($singularValueVarName, $valueVarName) : ?Variable { if (!$node instanceof Variable) { return null; } if (!$this->isName($node, $valueVarName)) { return null; } return new Variable($singularValueVarName); }); } } Rector/Foreach_/RenameForeachValueVariableToMatchMethodCallReturnTypeRector.php000064400000012734152535021720024032 0ustar00breakingVariableRenameGuard = $breakingVariableRenameGuard; $this->expectedNameResolver = $expectedNameResolver; $this->namingConventionAnalyzer = $namingConventionAnalyzer; $this->variableRenamer = $variableRenamer; $this->foreachMatcher = $foreachMatcher; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Renames value variable name in foreach loop to match method type', [new CodeSample(<<<'CODE_SAMPLE' class SomeClass { public function run() { $array = []; foreach ($object->getMethods() as $property) { $array[] = $property; } } } CODE_SAMPLE , <<<'CODE_SAMPLE' class SomeClass { public function run() { $array = []; foreach ($object->getMethods() as $method) { $array[] = $method; } } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [ClassMethod::class, Closure::class, Function_::class]; } /** * @param ClassMethod|Closure|Function_ $node */ public function refactor(Node $node) : ?Node { if ($node->stmts === null) { return null; } $hasRenamed = \false; $this->traverseNodesWithCallable($node->stmts, function (Node $subNode) use($node, &$hasRenamed) : ?int { if ($subNode instanceof Class_ || $subNode instanceof Closure || $subNode instanceof Function_) { return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } if (!$subNode instanceof Foreach_) { return null; } $variableAndCallForeach = $this->foreachMatcher->match($subNode, $node); if (!$variableAndCallForeach instanceof VariableAndCallForeach) { return null; } $expectedName = $this->expectedNameResolver->resolveForForeach($variableAndCallForeach); if ($expectedName === null) { return null; } if ($this->isName($variableAndCallForeach->getVariable(), $expectedName)) { return null; } if ($this->shouldSkip($variableAndCallForeach, $expectedName)) { return null; } $hasChanged = $this->variableRenamer->renameVariableInFunctionLike($variableAndCallForeach->getFunctionLike(), $variableAndCallForeach->getVariableName(), $expectedName, null); // use different variable on purpose to avoid variable re-assign back to false // after go to other method if ($hasChanged) { $hasRenamed = \true; } return null; }); if ($hasRenamed) { return $node; } return null; } private function shouldSkip(VariableAndCallForeach $variableAndCallForeach, string $expectedName) : bool { if (\in_array($expectedName, self::UNREADABLE_GENERIC_NAMES, \true)) { return \true; } if ($this->namingConventionAnalyzer->isCallMatchingVariableName($variableAndCallForeach->getCall(), $variableAndCallForeach->getVariableName(), $expectedName)) { return \true; } return $this->breakingVariableRenameGuard->shouldSkipVariable($variableAndCallForeach->getVariableName(), $expectedName, $variableAndCallForeach->getFunctionLike(), $variableAndCallForeach->getVariable()); } } Rector/Assign/RenameVariableToMatchMethodCallReturnTypeRector.php000064400000016006152535021720021257 0ustar00breakingVariableRenameGuard = $breakingVariableRenameGuard; $this->expectedNameResolver = $expectedNameResolver; $this->namingConventionAnalyzer = $namingConventionAnalyzer; $this->varTagValueNodeRenamer = $varTagValueNodeRenamer; $this->variableAndCallAssignMatcher = $variableAndCallAssignMatcher; $this->variableRenamer = $variableRenamer; $this->docBlockUpdater = $docBlockUpdater; $this->phpDocInfoFactory = $phpDocInfoFactory; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Rename variable to match method return type', [new CodeSample(<<<'CODE_SAMPLE' class SomeClass { public function run() { $a = $this->getRunner(); } public function getRunner(): Runner { return new Runner(); } } CODE_SAMPLE , <<<'CODE_SAMPLE' class SomeClass { public function run() { $runner = $this->getRunner(); } public function getRunner(): Runner { return new Runner(); } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [ClassMethod::class, Closure::class, Function_::class]; } /** * @param ClassMethod|Closure|Function_ $node */ public function refactor(Node $node) : ?Node { if ($node->stmts === null) { return null; } $hasChanged = \false; foreach ($node->stmts as $stmt) { if (!$stmt instanceof Expression) { continue; } if (!$stmt->expr instanceof Assign) { continue; } $assign = $stmt->expr; $variableAndCallAssign = $this->variableAndCallAssignMatcher->match($assign, $node); if (!$variableAndCallAssign instanceof VariableAndCallAssign) { continue; } $call = $variableAndCallAssign->getCall(); $expectedName = $this->expectedNameResolver->resolveForCall($call); if ($expectedName === null) { continue; } if ($this->isName($assign->var, $expectedName)) { continue; } if ($this->shouldSkip($variableAndCallAssign, $expectedName)) { continue; } $this->renameVariable($variableAndCallAssign, $expectedName, $stmt); $hasChanged = \true; } if ($hasChanged) { return $node; } return null; } private function shouldSkip(VariableAndCallAssign $variableAndCallAssign, string $expectedName) : bool { if (Strings::match($expectedName, self::VALID_VARIABLE_NAME_REGEX) === null) { return \true; } if ($this->namingConventionAnalyzer->isCallMatchingVariableName($variableAndCallAssign->getCall(), $variableAndCallAssign->getVariableName(), $expectedName)) { return \true; } $isUnionName = Strings::match($variableAndCallAssign->getVariableName(), self::OR_BETWEEN_WORDS_REGEX); if ($isUnionName !== null) { return \true; } return $this->breakingVariableRenameGuard->shouldSkipVariable($variableAndCallAssign->getVariableName(), $expectedName, $variableAndCallAssign->getFunctionLike(), $variableAndCallAssign->getVariable()); } private function renameVariable(VariableAndCallAssign $variableAndCallAssign, string $expectedName, Expression $expression) : void { $this->variableRenamer->renameVariableInFunctionLike($variableAndCallAssign->getFunctionLike(), $variableAndCallAssign->getVariableName(), $expectedName, $variableAndCallAssign->getAssign()); $assignPhpDocInfo = $this->phpDocInfoFactory->createFromNode($expression); if (!$assignPhpDocInfo instanceof PhpDocInfo) { return; } $this->varTagValueNodeRenamer->renameAssignVarTagVariableName($assignPhpDocInfo, $variableAndCallAssign->getVariableName(), $expectedName); $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($expression); } } Rector/ClassMethod/RenameVariableToMatchNewTypeRector.php000064400000010117152535021720017553 0ustar00breakingVariableRenameGuard = $breakingVariableRenameGuard; $this->expectedNameResolver = $expectedNameResolver; $this->variableRenamer = $variableRenamer; $this->betterNodeFinder = $betterNodeFinder; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Rename variable to match new ClassType', [new CodeSample(<<<'CODE_SAMPLE' final class SomeClass { public function run() { $search = new DreamSearch(); $search->advance(); } } CODE_SAMPLE , <<<'CODE_SAMPLE' final class SomeClass { public function run() { $dreamSearch = new DreamSearch(); $dreamSearch->advance(); } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [ClassMethod::class]; } /** * @param ClassMethod $node */ public function refactor(Node $node) : ?Node { $hasChanged = \false; $assignsOfNew = $this->getAssignsOfNew($node); foreach ($assignsOfNew as $assignOfNew) { $expectedName = $this->expectedNameResolver->resolveForAssignNew($assignOfNew); // skip self name as not useful if ($expectedName === 'self') { continue; } /** @var Variable $variable */ $variable = $assignOfNew->var; if ($expectedName === null) { continue; } if ($this->isName($variable, $expectedName)) { continue; } $currentName = $this->getName($variable); if ($currentName === null) { continue; } if ($this->breakingVariableRenameGuard->shouldSkipVariable($currentName, $expectedName, $node, $variable)) { continue; } $hasChanged = \true; // 1. rename assigned variable $assignOfNew->var = new Variable($expectedName); // 2. rename variable in the $this->variableRenamer->renameVariableInFunctionLike($node, $currentName, $expectedName, $assignOfNew); } if (!$hasChanged) { return null; } return $node; } /** * @return Assign[] */ private function getAssignsOfNew(ClassMethod $classMethod) : array { /** @var Assign[] $assigns */ $assigns = $this->betterNodeFinder->findInstanceOf((array) $classMethod->stmts, Assign::class); return \array_filter($assigns, static function (Assign $assign) : bool { return $assign->expr instanceof New_; }); } } Rector/ClassMethod/RenameParamToMatchTypeRector.php000064400000011262152535021720016416 0ustar00breakingVariableRenameGuard = $breakingVariableRenameGuard; $this->expectedNameResolver = $expectedNameResolver; $this->matchParamTypeExpectedNameResolver = $matchParamTypeExpectedNameResolver; $this->paramRenameFactory = $paramRenameFactory; $this->paramRenamer = $paramRenamer; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Rename param to match ClassType', [new CodeSample(<<<'CODE_SAMPLE' final class SomeClass { public function run(Apple $pie) { $food = $pie; } } CODE_SAMPLE , <<<'CODE_SAMPLE' final class SomeClass { public function run(Apple $apple) { $food = $apple; } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [ClassMethod::class, Function_::class, Closure::class, ArrowFunction::class]; } /** * @param ClassMethod|Function_|Closure|ArrowFunction $node */ public function refactor(Node $node) : ?Node { $this->hasChanged = \false; foreach ($node->params as $param) { $expectedName = $this->expectedNameResolver->resolveForParamIfNotYet($param); if ($expectedName === null) { continue; } if ($this->shouldSkipParam($param, $expectedName, $node)) { continue; } $expectedName = $this->matchParamTypeExpectedNameResolver->resolve($param); if ($expectedName === null) { continue; } $paramRename = $this->paramRenameFactory->createFromResolvedExpectedName($node, $param, $expectedName); if (!$paramRename instanceof ParamRename) { continue; } $this->paramRenamer->rename($paramRename); $this->hasChanged = \true; } if (!$this->hasChanged) { return null; } return $node; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $classMethod */ private function shouldSkipParam(Param $param, string $expectedName, $classMethod) : bool { /** @var string $paramName */ $paramName = $this->getName($param); if ($this->breakingVariableRenameGuard->shouldSkipParam($paramName, $expectedName, $classMethod, $param)) { return \true; } if (!$classMethod instanceof ClassMethod) { return \false; } // promoted property if (!$this->isName($classMethod, MethodName::CONSTRUCT)) { return \false; } return $param->flags !== 0; } } Rector/Class_/RenamePropertyToMatchTypeRector.php000064400000010163152535021720016177 0ustar00matchTypePropertyRenamer = $matchTypePropertyRenamer; $this->propertyRenameFactory = $propertyRenameFactory; $this->matchPropertyTypeExpectedNameResolver = $matchPropertyTypeExpectedNameResolver; $this->propertyPromotionRenamer = $propertyPromotionRenamer; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Rename property and method param to match its type', [new CodeSample(<<<'CODE_SAMPLE' class SomeClass { /** * @var EntityManager */ private $eventManager; public function __construct(EntityManager $eventManager) { $this->eventManager = $eventManager; } } CODE_SAMPLE , <<<'CODE_SAMPLE' class SomeClass { /** * @var EntityManager */ private $entityManager; public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [Class_::class, Interface_::class]; } /** * @param Class_|Interface_ $node */ public function refactor(Node $node) : ?Node { $this->hasChanged = \false; $this->refactorClassProperties($node); $hasPromotedPropertyChanged = $this->propertyPromotionRenamer->renamePropertyPromotion($node); if ($this->hasChanged) { return $node; } if ($hasPromotedPropertyChanged) { return $node; } return null; } private function refactorClassProperties(ClassLike $classLike) : void { foreach ($classLike->getProperties() as $property) { $expectedPropertyName = $this->matchPropertyTypeExpectedNameResolver->resolve($property, $classLike); if ($expectedPropertyName === null) { continue; } $propertyRename = $this->propertyRenameFactory->createFromExpectedName($classLike, $property, $expectedPropertyName); if (!$propertyRename instanceof PropertyRename) { continue; } $renameProperty = $this->matchTypePropertyRenamer->rename($propertyRename); if (!$renameProperty instanceof Property) { continue; } $this->hasChanged = \true; } } } PhpDoc/VarTagValueNodeRenamer.php000064400000001531152535021720012735 0ustar00getVarTagValueNode(); if (!$varTagValueNode instanceof VarTagValueNode) { return; } if ($varTagValueNode->variableName !== '$' . $originalName) { return; } $varTagValueNode->variableName = '$' . $expectedName; // invoke node reprint - same as in php-parser $varTagValueNode->setAttribute(PhpDocAttributeKey::ORIG_NODE, null); } } RenameGuard/PropertyRenameGuard.php000064400000003137152535021720013414 0ustar00nodeTypeResolver = $nodeTypeResolver; $this->dateTimeAtNamingConventionGuard = $dateTimeAtNamingConventionGuard; $this->hasMagicGetSetGuard = $hasMagicGetSetGuard; } public function shouldSkip(PropertyRename $propertyRename) : bool { if (!$propertyRename->isPrivateProperty()) { return \true; } if ($this->nodeTypeResolver->isObjectType($propertyRename->getProperty(), new ObjectType('Ramsey\\Uuid\\UuidInterface'))) { return \true; } if ($this->dateTimeAtNamingConventionGuard->isConflicting($propertyRename)) { return \true; } return $this->hasMagicGetSetGuard->isConflicting($propertyRename); } } ValueObject/VariableAndCallAssign.php000064400000004250152535021720013574 0ustar00variable = $variable; $this->expr = $expr; $this->assign = $assign; $this->variableName = $variableName; $this->functionLike = $functionLike; } public function getVariable() : Variable { return $this->variable; } /** * @return \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall */ public function getCall() { return $this->expr; } public function getVariableName() : string { return $this->variableName; } /** * @return \PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_ */ public function getFunctionLike() { return $this->functionLike; } public function getAssign() : Assign { return $this->assign; } } ValueObject/ParamRename.php000064400000002265152535021720011657 0ustar00currentName = $currentName; $this->expectedName = $expectedName; $this->variable = $variable; $this->functionLike = $functionLike; } public function getCurrentName() : string { return $this->currentName; } public function getExpectedName() : string { return $this->expectedName; } public function getFunctionLike() : FunctionLike { return $this->functionLike; } public function getVariable() : Variable { return $this->variable; } } ValueObject/ExpectedName.php000064400000001252152535021720012024 0ustar00name = $name; $this->singularized = $singularized; } public function getName() : string { return $this->name; } public function getSingularized() : string { return $this->singularized; } public function isSingular() : bool { return $this->name === $this->singularized; } } ValueObject/VariableAndCallForeach.php000064400000003647152535021720013730 0ustar00variable = $variable; $this->expr = $expr; $this->variableName = $variableName; $this->functionLike = $functionLike; } public function getVariable() : Variable { return $this->variable; } /** * @return \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall */ public function getCall() { return $this->expr; } public function getVariableName() : string { return $this->variableName; } /** * @return \PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_ */ public function getFunctionLike() { return $this->functionLike; } } ValueObject/PropertyRename.php000064400000004212152535021720012435 0ustar00property = $property; $this->expectedName = $expectedName; $this->currentName = $currentName; $this->classLike = $classLike; $this->classLikeName = $classLikeName; $this->propertyProperty = $propertyProperty; // name must be valid RectorAssert::propertyName($currentName); RectorAssert::propertyName($expectedName); } public function getProperty() : Property { return $this->property; } public function isPrivateProperty() : bool { return $this->property->isPrivate(); } public function getExpectedName() : string { return $this->expectedName; } public function getCurrentName() : string { return $this->currentName; } public function isAlreadyExpectedName() : bool { return $this->currentName === $this->expectedName; } public function getClassLike() : ClassLike { return $this->classLike; } public function getClassLikeName() : string { return $this->classLikeName; } public function getPropertyProperty() : PropertyProperty { return $this->propertyProperty; } } VariableRenamer.php000064400000012135152535021720010320 0ustar00simpleCallableNodeTraverser = $simpleCallableNodeTraverser; $this->nodeNameResolver = $nodeNameResolver; $this->varTagValueNodeRenamer = $varTagValueNodeRenamer; $this->phpDocInfoFactory = $phpDocInfoFactory; } public function renameVariableInFunctionLike(FunctionLike $functionLike, string $oldName, string $expectedName, ?Assign $assign = null) : bool { $isRenamingActive = \false; if (!$assign instanceof Assign) { $isRenamingActive = \true; } $hasRenamed = \false; $currentStmt = null; $currentFunctionLike = null; $this->simpleCallableNodeTraverser->traverseNodesWithCallable((array) $functionLike->getStmts(), function (Node $node) use($oldName, $expectedName, $assign, &$isRenamingActive, &$hasRenamed, &$currentStmt, &$currentFunctionLike) { // skip param names if ($node instanceof Param) { return NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } if ($assign instanceof Assign && $node === $assign) { $isRenamingActive = \true; return null; } if ($node instanceof Stmt) { $currentStmt = $node; } if ($node instanceof FunctionLike) { $currentFunctionLike = $node; } if (!$node instanceof Variable) { return null; } // TODO: Should be implemented in BreakingVariableRenameGuard::shouldSkipParam() if ($this->isParamInParentFunction($node, $currentFunctionLike)) { return null; } if (!$isRenamingActive) { return null; } $variable = $this->renameVariableIfMatchesName($node, $oldName, $expectedName, $currentStmt); if ($variable instanceof Variable) { $hasRenamed = \true; } return $variable; }); return $hasRenamed; } private function isParamInParentFunction(Variable $variable, ?FunctionLike $functionLike) : bool { if (!$functionLike instanceof FunctionLike) { return \false; } $variableName = $this->nodeNameResolver->getName($variable); if ($variableName === null) { return \false; } $scope = $variable->getAttribute(AttributeKey::SCOPE); $functionLikeScope = $functionLike->getAttribute(AttributeKey::SCOPE); if ($scope instanceof MutatingScope && $functionLikeScope instanceof MutatingScope && $scope->equals($functionLikeScope)) { return \false; } foreach ($functionLike->getParams() as $param) { if ($this->nodeNameResolver->isName($param, $variableName)) { return \true; } } return \false; } private function renameVariableIfMatchesName(Variable $variable, string $oldName, string $expectedName, ?Stmt $currentStmt) : ?Variable { if (!$this->nodeNameResolver->isName($variable, $oldName)) { return null; } $variable->name = $expectedName; $variablePhpDocInfo = $this->resolvePhpDocInfo($variable, $currentStmt); $this->varTagValueNodeRenamer->renameAssignVarTagVariableName($variablePhpDocInfo, $oldName, $expectedName); return $variable; } /** * Expression doc block has higher priority */ private function resolvePhpDocInfo(Variable $variable, ?Stmt $currentStmt) : PhpDocInfo { if ($currentStmt instanceof Stmt) { return $this->phpDocInfoFactory->createFromNodeOrEmpty($currentStmt); } return $this->phpDocInfoFactory->createFromNodeOrEmpty($variable); } } PhpArray/ArrayFilter.php000064400000001174152535021720011234 0ustar00 $valueToCount */ $valueToCount = \array_count_values($values); $duplicatedValues = []; foreach ($valueToCount as $value => $count) { /** @var int $count */ if ($count < 2) { continue; } $duplicatedValues[] = $value; } return $duplicatedValues; } } ValueObjectFactory/PropertyRenameFactory.php000064400000002114152535021720015314 0ustar00nodeNameResolver = $nodeNameResolver; } public function createFromExpectedName(ClassLike $classLike, Property $property, string $expectedName) : ?PropertyRename { $currentName = $this->nodeNameResolver->getName($property); $className = (string) $this->nodeNameResolver->getName($classLike); try { return new PropertyRename($property, $expectedName, $currentName, $classLike, $className, $property->props[0]); } catch (InvalidArgumentException $exception) { } return null; } } ValueObjectFactory/ParamRenameFactory.php000064400000001743152535021720014537 0ustar00nodeNameResolver = $nodeNameResolver; } public function createFromResolvedExpectedName(FunctionLike $functionLike, Param $param, string $expectedName) : ?ParamRename { if ($param->var instanceof Error) { return null; } $currentName = $this->nodeNameResolver->getName($param->var); if ($currentName === null) { return null; } return new ParamRename($currentName, $expectedName, $param->var, $functionLike); } } PropertyRenamer/PropertyFetchRenamer.php000064400000003247152535021720014533 0ustar00simpleCallableNodeTraverser = $simpleCallableNodeTraverser; $this->propertyFetchAnalyzer = $propertyFetchAnalyzer; } public function renamePropertyFetchesInClass(ClassLike $classLike, string $currentName, string $expectedName) : void { // 1. replace property fetch rename in whole class $this->simpleCallableNodeTraverser->traverseNodesWithCallable($classLike, function (Node $node) use($currentName, $expectedName) : ?Node { if (!$this->propertyFetchAnalyzer->isLocalPropertyFetchName($node, $currentName)) { return null; } /** @var StaticPropertyFetch|PropertyFetch $node */ $node->name = $node instanceof PropertyFetch ? new Identifier($expectedName) : new VarLikeIdentifier($expectedName); return $node; }); } } PropertyRenamer/PropertyPromotionRenamer.php000064400000016740152535021720015472 0ustar00phpVersionProvider = $phpVersionProvider; $this->matchParamTypeExpectedNameResolver = $matchParamTypeExpectedNameResolver; $this->paramRenameFactory = $paramRenameFactory; $this->phpDocInfoFactory = $phpDocInfoFactory; $this->paramRenamer = $paramRenamer; $this->propertyFetchRenamer = $propertyFetchRenamer; $this->nodeNameResolver = $nodeNameResolver; $this->variableRenamer = $variableRenamer; $this->docBlockUpdater = $docBlockUpdater; } /** * @param \PhpParser\Node\Stmt\Class_|\PhpParser\Node\Stmt\Interface_ $classLike */ public function renamePropertyPromotion($classLike) : bool { $hasChanged = \false; if (!$this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::PROPERTY_PROMOTION)) { return \false; } $constructClassMethod = $classLike->getMethod(MethodName::CONSTRUCT); if (!$constructClassMethod instanceof ClassMethod) { return \false; } // resolve possible and existing param names $blockingParamNames = $this->resolveBlockingParamNames($constructClassMethod); foreach ($constructClassMethod->params as $param) { if ($param->flags === 0) { continue; } // promoted property $desiredPropertyName = $this->matchParamTypeExpectedNameResolver->resolve($param); if ($desiredPropertyName === null) { continue; } if (\in_array($desiredPropertyName, $blockingParamNames, \true)) { continue; } $currentParamName = $this->nodeNameResolver->getName($param); if ($this->isNameSuffixed($currentParamName, $desiredPropertyName)) { continue; } $this->renameParamVarNameAndVariableUsage($classLike, $constructClassMethod, $desiredPropertyName, $param); $hasChanged = \true; } return $hasChanged; } public function renameParamDoc(PhpDocInfo $phpDocInfo, ClassMethod $classMethod, Param $param, string $paramVarName, string $desiredPropertyName) : void { $paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramVarName); if (!$paramTagValueNode instanceof ParamTagValueNode) { return; } $paramRename = $this->paramRenameFactory->createFromResolvedExpectedName($classMethod, $param, $desiredPropertyName); if (!$paramRename instanceof ParamRename) { return; } $this->paramRenamer->rename($paramRename); $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); } private function renameParamVarNameAndVariableUsage(ClassLike $classLike, ClassMethod $classMethod, string $desiredPropertyName, Param $param) : void { if ($param->var instanceof Error) { return; } $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod); $currentParamName = $this->nodeNameResolver->getName($param); $this->propertyFetchRenamer->renamePropertyFetchesInClass($classLike, $currentParamName, $desiredPropertyName); /** @var string $paramVarName */ $paramVarName = $param->var->name; $this->renameParamDoc($classMethodPhpDocInfo, $classMethod, $param, $paramVarName, $desiredPropertyName); $param->var = new Variable($desiredPropertyName); $this->variableRenamer->renameVariableInFunctionLike($classMethod, $paramVarName, $desiredPropertyName); } /** * Sometimes the bare type is not enough. * This allows prefixing type in variable names, e.g. "Type $firstType" */ private function isNameSuffixed(string $currentParamName, string $desiredPropertyName) : bool { $currentNameLowercased = \strtolower($currentParamName); $expectedNameLowercased = \strtolower($desiredPropertyName); return \substr_compare($currentNameLowercased, $expectedNameLowercased, -\strlen($expectedNameLowercased)) === 0; } /** * @return int[]|string[] */ private function resolveBlockingParamNames(ClassMethod $classMethod) : array { $futureParamNames = []; foreach ($classMethod->params as $param) { $futureParamName = $this->matchParamTypeExpectedNameResolver->resolve($param); if ($futureParamName === null) { continue; } $futureParamNames[] = $futureParamName; } // remove null values $futureParamNames = \array_filter($futureParamNames); if ($futureParamNames === []) { return []; } // resolve duplicated names $blockingParamNames = []; $valuesToCount = \array_count_values($futureParamNames); foreach ($valuesToCount as $value => $count) { if ($count < 2) { continue; } $blockingParamNames[] = $value; } return $blockingParamNames; } } PropertyRenamer/MatchTypePropertyRenamer.php000064400000004267152535021720015403 0ustar00matchPropertyTypeConflictingNameGuard = $matchPropertyTypeConflictingNameGuard; $this->propertyRenameGuard = $propertyRenameGuard; $this->propertyFetchRenamer = $propertyFetchRenamer; } public function rename(PropertyRename $propertyRename) : ?Property { if ($this->matchPropertyTypeConflictingNameGuard->isConflicting($propertyRename)) { return null; } if ($propertyRename->isAlreadyExpectedName()) { return null; } if ($this->propertyRenameGuard->shouldSkip($propertyRename)) { return null; } $onlyPropertyProperty = $propertyRename->getPropertyProperty(); $onlyPropertyProperty->name = new VarLikeIdentifier($propertyRename->getExpectedName()); $this->renamePropertyFetchesInClass($propertyRename); return $propertyRename->getProperty(); } private function renamePropertyFetchesInClass(PropertyRename $propertyRename) : void { $this->propertyFetchRenamer->renamePropertyFetchesInClass($propertyRename->getClassLike(), $propertyRename->getCurrentName(), $propertyRename->getExpectedName()); } } NamingConvention/NamingConventionAnalyzer.php000064400000002432152535021720015516 0ustar00nodeNameResolver = $nodeNameResolver; } /** * Matches cases: * * $someNameSuffix = $this->getSomeName(); * $prefixSomeName = $this->getSomeName(); * $someName = $this->getSomeName(); * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $expr */ public function isCallMatchingVariableName($expr, string $currentName, string $expectedName) : bool { // skip "$call = $method->call();" based conventions $callName = $this->nodeNameResolver->getName($expr->name); if ($currentName === $callName) { return \true; } // starts with or ends with return StringUtils::isMatch($currentName, '#^(' . $expectedName . '|' . $expectedName . '$)#i'); } } Matcher/ForeachMatcher.php000064400000003012152535021720011511 0ustar00nodeNameResolver = $nodeNameResolver; $this->callMatcher = $callMatcher; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\Function_ $functionLike */ public function match(Foreach_ $foreach, $functionLike) : ?VariableAndCallForeach { $call = $this->callMatcher->matchCall($foreach); if (!$call instanceof Node) { return null; } if (!$foreach->valueVar instanceof Variable) { return null; } $variableName = $this->nodeNameResolver->getName($foreach->valueVar); if ($variableName === null) { return null; } return new VariableAndCallForeach($foreach->valueVar, $call, $variableName, $functionLike); } } Matcher/VariableAndCallAssignMatcher.php000064400000004200152535021720014253 0ustar00callMatcher = $callMatcher; $this->nodeNameResolver = $nodeNameResolver; $this->betterNodeFinder = $betterNodeFinder; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Stmt\Function_ $functionLike */ public function match(Assign $assign, $functionLike) : ?VariableAndCallAssign { $call = $this->callMatcher->matchCall($assign); if (!$call instanceof Node) { return null; } if (!$assign->var instanceof Variable) { return null; } $variableName = $this->nodeNameResolver->getName($assign->var); if ($variableName === null) { return null; } $isVariableFoundInCallArgs = (bool) $this->betterNodeFinder->findFirst($call->isFirstClassCallable() ? [] : $call->getArgs(), function (Node $subNode) use($variableName) : bool { return $subNode instanceof Variable && $this->nodeNameResolver->isName($subNode, $variableName); }); if ($isVariableFoundInCallArgs) { return null; } return new VariableAndCallAssign($assign->var, $call, $assign, $variableName, $functionLike); } } Matcher/CallMatcher.php000064400000001415152535021720011022 0ustar00expr instanceof MethodCall) { return $node->expr; } if ($node->expr instanceof StaticCall) { return $node->expr; } if ($node->expr instanceof FuncCall) { return $node->expr; } return null; } } ParamRenamer/ParamRenamer.php000064400000004517152535021720012212 0ustar00variableRenamer = $variableRenamer; $this->docBlockUpdater = $docBlockUpdater; $this->phpDocInfoFactory = $phpDocInfoFactory; } public function rename(ParamRename $paramRename) : void { // 1. rename param $paramRename->getVariable()->name = $paramRename->getExpectedName(); // 2. rename param in the rest of the method $this->variableRenamer->renameVariableInFunctionLike($paramRename->getFunctionLike(), $paramRename->getCurrentName(), $paramRename->getExpectedName(), null); // 3. rename @param variable in docblock too $this->renameParameterNameInDocBlock($paramRename); } private function renameParameterNameInDocBlock(ParamRename $paramRename) : void { $functionLike = $paramRename->getFunctionLike(); $phpDocInfo = $this->phpDocInfoFactory->createFromNode($functionLike); if (!$phpDocInfo instanceof PhpDocInfo) { return; } $paramTagValueNode = $phpDocInfo->getParamTagValueByName($paramRename->getCurrentName()); if (!$paramTagValueNode instanceof ParamTagValueNode) { return; } $paramTagValueNode->parameterName = '$' . $paramRename->getExpectedName(); $paramTagValueNode->setAttribute(PhpDocAttributeKey::ORIG_NODE, null); $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($functionLike); } } AssignVariableNameResolver/NewAssignVariableNameResolver.php000064400000002155152535021720020366 0ustar00 */ final class NewAssignVariableNameResolver implements AssignVariableNameResolverInterface { /** * @readonly * @var \Rector\NodeNameResolver\NodeNameResolver */ private $nodeNameResolver; public function __construct(NodeNameResolver $nodeNameResolver) { $this->nodeNameResolver = $nodeNameResolver; } public function match(Node $node) : bool { return $node instanceof New_; } /** * @param New_ $node */ public function resolve(Node $node) : string { $className = $this->nodeNameResolver->getName($node->class); if ($className === null) { throw new NotImplementedYetException(); } return $this->nodeNameResolver->getShortName($className); } } AssignVariableNameResolver/PropertyFetchAssignVariableNameResolver.php000064400000002610152535021720022427 0ustar00 */ final class PropertyFetchAssignVariableNameResolver implements AssignVariableNameResolverInterface { /** * @readonly * @var \Rector\NodeNameResolver\NodeNameResolver */ private $nodeNameResolver; public function __construct(NodeNameResolver $nodeNameResolver) { $this->nodeNameResolver = $nodeNameResolver; } public function match(Node $node) : bool { return $node instanceof PropertyFetch; } /** * @param PropertyFetch $node */ public function resolve(Node $node) : string { $varName = $this->nodeNameResolver->getName($node->var); if (!\is_string($varName)) { throw new NotImplementedYetException(); } $propertyName = $this->nodeNameResolver->getName($node->name); if (!\is_string($propertyName)) { throw new NotImplementedYetException(); } if ($varName === 'this') { return $propertyName; } return $varName . \ucfirst($propertyName); } } ExpectedNameResolver/InflectorSingularResolver.php000064400000006210152535021720016516 0ustar00 */ private const SINGULARIZE_MAP = ['news' => 'new']; /** * @var string * @see https://regex101.com/r/lbQaGC/3 */ private const CAMELCASE_REGEX = '#(?([a-z\\d]+|[A-Z\\d]{1,}[a-z\\d]+|_))#'; /** * @var string * @see https://regex101.com/r/2aGdkZ/2 */ private const BY_MIDDLE_REGEX = '#(?By[A-Z][a-zA-Z]+)#'; /** * @var string */ private const CAMELCASE = 'camelcase'; public function __construct(Inflector $inflector) { $this->inflector = $inflector; } public function resolve(string $currentName) : string { $matchBy = Strings::match($currentName, self::BY_MIDDLE_REGEX); if ($matchBy !== null) { return Strings::substring($currentName, 0, -\strlen((string) $matchBy['by'])); } $resolvedValue = $this->resolveSingularizeMap($currentName); if ($resolvedValue !== null) { return $resolvedValue; } $singularValueVarName = $this->singularizeCamelParts($currentName); if (\in_array($singularValueVarName, ['', '_'], \true)) { return $currentName; } $length = \strlen($singularValueVarName); if ($length < 40) { return $singularValueVarName; } return $currentName; } private function resolveSingularizeMap(string $currentName) : ?string { foreach (self::SINGULARIZE_MAP as $plural => $singular) { if ($currentName === $plural) { return $singular; } if (StringUtils::isMatch($currentName, '#' . \ucfirst($plural) . '#')) { $resolvedValue = Strings::replace($currentName, '#' . \ucfirst($plural) . '#', \ucfirst($singular)); return $this->singularizeCamelParts($resolvedValue); } if (StringUtils::isMatch($currentName, '#' . $plural . '#')) { $resolvedValue = Strings::replace($currentName, '#' . $plural . '#', $singular); return $this->singularizeCamelParts($resolvedValue); } } return null; } private function singularizeCamelParts(string $currentName) : string { $camelCases = Strings::matchAll($currentName, self::CAMELCASE_REGEX); $resolvedName = ''; foreach ($camelCases as $camelCase) { if (\in_array($camelCase[self::CAMELCASE], ['is', 'has', 'cms', 'this'], \true)) { $value = $camelCase[self::CAMELCASE]; } else { $value = $this->inflector->singularize($camelCase[self::CAMELCASE]); } $resolvedName .= $value; } return $resolvedName; } } ExpectedNameResolver/MatchPropertyTypeExpectedNameResolver.php000064400000007365152535021720021026 0ustar00propertyNaming = $propertyNaming; $this->phpDocInfoFactory = $phpDocInfoFactory; $this->nodeNameResolver = $nodeNameResolver; $this->propertyManipulator = $propertyManipulator; $this->reflectionResolver = $reflectionResolver; $this->staticTypeMapper = $staticTypeMapper; } public function resolve(Property $property, ClassLike $classLike) : ?string { if (!$classLike instanceof Class_) { return null; } $classReflection = $this->reflectionResolver->resolveClassReflection($property); if (!$classReflection instanceof ClassReflection) { return null; } $propertyName = $this->nodeNameResolver->getName($property); if ($this->propertyManipulator->isUsedByTrait($classReflection, $propertyName)) { return null; } $expectedName = $this->resolveExpectedName($property); if (!$expectedName instanceof ExpectedName) { return null; } // skip if already has suffix if (\substr_compare($propertyName, $expectedName->getName(), -\strlen($expectedName->getName())) === 0 || \substr_compare($propertyName, \ucfirst($expectedName->getName()), -\strlen(\ucfirst($expectedName->getName()))) === 0) { return null; } return $expectedName->getName(); } private function resolveExpectedName(Property $property) : ?ExpectedName { // property type first if ($property->type instanceof Node) { $propertyType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($property->type); return $this->propertyNaming->getExpectedNameFromType($propertyType); } // fallback to docblock $phpDocInfo = $this->phpDocInfoFactory->createFromNode($property); $hasVarTag = $phpDocInfo instanceof PhpDocInfo && $phpDocInfo->getVarTagValueNode() instanceof VarTagValueNode; if ($hasVarTag) { return $this->propertyNaming->getExpectedNameFromType($phpDocInfo->getVarType()); } return null; } } ExpectedNameResolver/MatchParamTypeExpectedNameResolver.php000064400000003271152535021720020232 0ustar00staticTypeMapper = $staticTypeMapper; $this->propertyNaming = $propertyNaming; $this->nodeTypeResolver = $nodeTypeResolver; } public function resolve(Param $param) : ?string { // nothing to verify if ($param->type === null) { return null; } // include nullable too // skip date time + date time interface, as should be kept if ($this->nodeTypeResolver->isObjectType($param->type, new ObjectType('DateTimeInterface'))) { return null; } $staticType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type); $expectedName = $this->propertyNaming->getExpectedNameFromType($staticType); if (!$expectedName instanceof ExpectedName) { return null; } return $expectedName->getName(); } } Naming/VariableNaming.php000064400000011555152535021720011356 0ustar00nodeNameResolver = $nodeNameResolver; $this->nodeTypeResolver = $nodeTypeResolver; $this->assignVariableNameResolvers = [$propertyFetchAssignVariableNameResolver, $newAssignVariableNameResolver]; } /** * @api used in downgrade */ public function createCountedValueName(string $valueName, ?Scope $scope) : string { if (!$scope instanceof Scope) { return $valueName; } // make sure variable name is unique if (!$scope->hasVariableType($valueName)->yes()) { return $valueName; } // we need to add number suffix until the variable is unique $i = 2; $countedValueNamePart = $valueName; while ($scope->hasVariableType($valueName)->yes()) { $valueName = $countedValueNamePart . $i; ++$i; } return $valueName; } private function resolveFromNodeAndType(Node $node, Type $type) : ?string { $variableName = $this->resolveBareFromNode($node); if ($variableName === null) { return null; } // adjust static to specific class if ($variableName === 'this' && $type instanceof ThisType) { $shortClassName = $this->nodeNameResolver->getShortName($type->getClassName()); return \lcfirst($shortClassName); } return $this->nodeNameResolver->getShortName($variableName); } private function resolveFromNode(Node $node) : ?string { $nodeType = $this->nodeTypeResolver->getType($node); return $this->resolveFromNodeAndType($node, $nodeType); } private function resolveBareFromNode(Node $node) : ?string { $unwrappedNode = $this->unwrapNode($node); if (!$unwrappedNode instanceof Node) { return null; } foreach ($this->assignVariableNameResolvers as $assignVariableNameResolver) { if ($assignVariableNameResolver->match($unwrappedNode)) { return $assignVariableNameResolver->resolve($unwrappedNode); } } if ($unwrappedNode instanceof MethodCall || $unwrappedNode instanceof NullsafeMethodCall || $unwrappedNode instanceof StaticCall) { return $this->resolveFromMethodCall($unwrappedNode); } if ($unwrappedNode instanceof FuncCall) { return $this->resolveFromNode($unwrappedNode->name); } $paramName = $this->nodeNameResolver->getName($unwrappedNode); if ($paramName !== null) { return $paramName; } if ($unwrappedNode instanceof String_) { return $unwrappedNode->value; } return null; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\NullsafeMethodCall|\PhpParser\Node\Expr\StaticCall $node */ private function resolveFromMethodCall($node) : ?string { if ($node->name instanceof MethodCall) { return $this->resolveFromMethodCall($node->name); } $methodName = $this->nodeNameResolver->getName($node->name); if (!\is_string($methodName)) { return null; } return $methodName; } private function unwrapNode(Node $node) : ?Node { if ($node instanceof Arg) { return $node->value; } if ($node instanceof Cast) { return $node->expr; } if ($node instanceof Ternary) { return $node->if; } return $node; } } Naming/PropertyNaming.php000064400000023146152535021720011454 0ustar00 */ private const CONTEXT_AWARE_NAMES_BY_TYPE = ['Twig\\Environment' => 'twigEnvironment']; /** * @var string */ private const INTERFACE = 'Interface'; /** * @var string * @see https://regex101.com/r/U78rUF/1 */ private const I_PREFIX_REGEX = '#^I[A-Z]#'; /** * @see https://regex101.com/r/hnU5pm/2/ * @var string */ private const GET_PREFIX_REGEX = '#^get(?[A-Z].+)#'; public function __construct(RectorNamingInflector $rectorNamingInflector, NodeTypeResolver $nodeTypeResolver) { $this->rectorNamingInflector = $rectorNamingInflector; $this->nodeTypeResolver = $nodeTypeResolver; } public function getExpectedNameFromMethodName(string $methodName) : ?ExpectedName { $matches = Strings::match($methodName, self::GET_PREFIX_REGEX); if ($matches === null) { return null; } $originalName = \lcfirst((string) $matches['root_name']); return new ExpectedName($originalName, $this->rectorNamingInflector->singularize($originalName)); } public function getExpectedNameFromType(Type $type) : ?ExpectedName { // keep collections untouched if ($type instanceof ObjectType) { if ($type->isInstanceOf('Doctrine\\Common\\Collections\\Collection')->yes()) { return null; } if ($type->isInstanceOf('Illuminate\\Support\\Collection')->yes()) { return null; } } $className = $this->resolveClassNameFromType($type); if (!\is_string($className)) { return null; } foreach (self::EXCLUDED_CLASSES as $excludedClass) { if (StringUtils::isMatch($className, $excludedClass)) { return null; } } // special cases to keep context foreach (self::CONTEXT_AWARE_NAMES_BY_TYPE as $specialType => $contextAwareName) { if ($className === $specialType) { return new ExpectedName($contextAwareName, $contextAwareName); } } $shortClassName = $this->resolveShortClassName($className); $shortClassName = $this->normalizeShortClassName($shortClassName); // prolong too short generic names with one namespace up $originalName = $this->prolongIfTooShort($shortClassName, $className); return new ExpectedName($originalName, $this->rectorNamingInflector->singularize($originalName)); } /** * @param \PHPStan\Type\ThisType|\PHPStan\Type\ObjectType|string $objectType */ public function fqnToVariableName($objectType) : string { if ($objectType instanceof ThisType) { $objectType = $objectType->getStaticObjectType(); } $className = $this->resolveClassName($objectType); $shortClassName = \strpos($className, '\\') !== \false ? (string) Strings::after($className, '\\', -1) : $className; $variableName = $this->removeInterfaceSuffixPrefix($shortClassName, 'interface'); $variableName = $this->removeInterfaceSuffixPrefix($variableName, 'abstract'); $variableName = $this->fqnToShortName($variableName); $variableName = \str_replace('_', '', $variableName); // prolong too short generic names with one namespace up return $this->prolongIfTooShort($variableName, $className); } private function resolveShortClassName(string $className) : string { if (\strpos($className, '\\') !== \false) { return (string) Strings::after($className, '\\', -1); } return $className; } private function removePrefixesAndSuffixes(string $shortClassName) : string { // is SomeInterface if (\substr_compare($shortClassName, self::INTERFACE, -\strlen(self::INTERFACE)) === 0) { $shortClassName = Strings::substring($shortClassName, 0, -\strlen(self::INTERFACE)); } // is ISomeClass if ($this->isPrefixedInterface($shortClassName)) { $shortClassName = Strings::substring($shortClassName, 1); } // is AbstractClass if (\strncmp($shortClassName, 'Abstract', \strlen('Abstract')) === 0) { return Strings::substring($shortClassName, \strlen('Abstract')); } return $shortClassName; } private function normalizeUpperCase(string $shortClassName) : string { // turns $SOMEUppercase => $someUppercase for ($i = 0; $i <= \strlen($shortClassName); ++$i) { if (\ctype_upper($shortClassName[$i]) && $this->isNumberOrUpper($shortClassName[$i + 1])) { $shortClassName[$i] = \strtolower($shortClassName[$i]); } else { break; } } return $shortClassName; } private function prolongIfTooShort(string $shortClassName, string $className) : string { if (\in_array($shortClassName, ['Factory', 'Repository'], \true)) { $namespaceAbove = (string) Strings::after($className, '\\', -2); $namespaceAbove = (string) Strings::before($namespaceAbove, '\\'); return \lcfirst($namespaceAbove) . $shortClassName; } return \lcfirst($shortClassName); } /** * @param \PHPStan\Type\ObjectType|string $objectType */ private function resolveClassName($objectType) : string { if ($objectType instanceof ObjectType) { return $objectType->getClassName(); } return $objectType; } private function fqnToShortName(string $fqn) : string { if (\strpos($fqn, '\\') === \false) { return $fqn; } $lastNamePart = Strings::after($fqn, '\\', -1); if (!\is_string($lastNamePart)) { throw new ShouldNotHappenException(); } if (\substr_compare($lastNamePart, self::INTERFACE, -\strlen(self::INTERFACE)) === 0) { return Strings::substring($lastNamePart, 0, -\strlen(self::INTERFACE)); } return $lastNamePart; } private function removeInterfaceSuffixPrefix(string $className, string $category) : string { // suffix $iSuffixMatch = Strings::match($className, '#' . $category . '$#i'); if ($iSuffixMatch !== null) { return Strings::substring($className, 0, -\strlen($category)); } // prefix $iPrefixMatch = Strings::match($className, '#^' . $category . '#i'); if ($iPrefixMatch !== null) { return Strings::substring($className, \strlen($category)); } // starts with "I\W+"? if (StringUtils::isMatch($className, self::I_PREFIX_REGEX)) { return Strings::substring($className, 1); } return $className; } private function isPrefixedInterface(string $shortClassName) : bool { if (\strlen($shortClassName) <= 3) { return \false; } if (\strncmp($shortClassName, 'I', \strlen('I')) !== 0) { return \false; } if (!\ctype_upper($shortClassName[1])) { return \false; } return \ctype_lower($shortClassName[2]); } private function isNumberOrUpper(string $char) : bool { if (\ctype_upper($char)) { return \true; } return \ctype_digit($char); } private function normalizeShortClassName(string $shortClassName) : string { $shortClassName = $this->removePrefixesAndSuffixes($shortClassName); // if all is upper-cased, it should be lower-cased if ($shortClassName === \strtoupper($shortClassName)) { $shortClassName = \strtolower($shortClassName); } // remove "_" $shortClassName = Strings::replace($shortClassName, '#_#'); return $this->normalizeUpperCase($shortClassName); } private function resolveClassNameFromType(Type $type) : ?string { $type = TypeCombinator::removeNull($type); if (!$type instanceof TypeWithClassName) { return null; } if ($type instanceof SelfObjectType) { return null; } if ($type instanceof StaticType) { return null; } // generic types are usually mix of parent type and specific type - various way to handle it if ($type instanceof GenericObjectType) { return null; } return $type instanceof AliasedObjectType ? $type->getClassName() : $this->nodeTypeResolver->getFullyQualifiedClassName($type); } } Naming/AliasNameResolver.php000064400000002351152535021720012045 0ustar00useImportsResolver = $useImportsResolver; } /** * @param array $uses */ public function resolveByName(FullyQualified $fullyQualified, array $uses) : ?string { $nameString = $fullyQualified->toString(); foreach ($uses as $use) { $prefix = $this->useImportsResolver->resolvePrefix($use); foreach ($use->uses as $useUse) { if (!$useUse->alias instanceof Identifier) { continue; } $fullyQualified = $prefix . $useUse->name->toString(); if ($fullyQualified !== $nameString) { continue; } return (string) $useUse->getAlias(); } } return null; } } Naming/UseImportsResolver.php000064400000004733152535021720012333 0ustar00currentFileProvider = $currentFileProvider; } /** * @return array */ public function resolve() : array { $namespace = $this->resolveNamespace(); if (!$namespace instanceof Node) { return []; } return \array_filter($namespace->stmts, static function (Stmt $stmt) : bool { return $stmt instanceof Use_ || $stmt instanceof GroupUse; }); } /** * @api * @return Use_[] */ public function resolveBareUses() : array { $namespace = $this->resolveNamespace(); if (!$namespace instanceof Node) { return []; } return \array_filter($namespace->stmts, static function (Stmt $stmt) : bool { return $stmt instanceof Use_; }); } /** * @param \PhpParser\Node\Stmt\Use_|\PhpParser\Node\Stmt\GroupUse $use */ public function resolvePrefix($use) : string { return $use instanceof GroupUse ? $use->prefix . '\\' : ''; } /** * @return \PhpParser\Node\Stmt\Namespace_|\Rector\PhpParser\Node\CustomNode\FileWithoutNamespace|null */ private function resolveNamespace() { /** @var File|null $file */ $file = $this->currentFileProvider->getFile(); if (!$file instanceof File) { return null; } $newStmts = $file->getNewStmts(); if ($newStmts === []) { return null; } /** @var Namespace_[]|FileWithoutNamespace[] $namespaces */ $namespaces = \array_filter($newStmts, static function (Stmt $stmt) : bool { return $stmt instanceof Namespace_ || $stmt instanceof FileWithoutNamespace; }); // multiple namespaces is not supported if (\count($namespaces) !== 1) { return null; } return \current($namespaces); } } Naming/ConflictingNameResolver.php000064400000012514152535021720013255 0ustar00 */ private $conflictingVariableNamesByClassMethod = []; public function __construct(ArrayFilter $arrayFilter, BetterNodeFinder $betterNodeFinder, \Rector\Naming\Naming\ExpectedNameResolver $expectedNameResolver, MatchParamTypeExpectedNameResolver $matchParamTypeExpectedNameResolver, FunctionLikeManipulator $functionLikeManipulator) { $this->arrayFilter = $arrayFilter; $this->betterNodeFinder = $betterNodeFinder; $this->expectedNameResolver = $expectedNameResolver; $this->matchParamTypeExpectedNameResolver = $matchParamTypeExpectedNameResolver; $this->functionLikeManipulator = $functionLikeManipulator; } /** * @return string[] * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $classMethod */ public function resolveConflictingVariableNamesForParam($classMethod) : array { $expectedNames = []; foreach ($classMethod->params as $param) { $expectedName = $this->matchParamTypeExpectedNameResolver->resolve($param); if ($expectedName === null) { continue; } $expectedNames[] = $expectedName; } return $this->arrayFilter->filterWithAtLeastTwoOccurences($expectedNames); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ public function hasNameIsInFunctionLike(string $variableName, $functionLike) : bool { $conflictingVariableNames = $this->resolveConflictingVariableNamesForNew($functionLike); return \in_array($variableName, $conflictingVariableNames, \true); } /** * @return string[] * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ private function resolveConflictingVariableNamesForNew($functionLike) : array { // cache it! $classMethodId = \spl_object_id($functionLike); if (isset($this->conflictingVariableNamesByClassMethod[$classMethodId])) { return $this->conflictingVariableNamesByClassMethod[$classMethodId]; } $paramNames = $this->functionLikeManipulator->resolveParamNames($functionLike); $newAssignNames = $this->resolveForNewAssigns($functionLike); $nonNewAssignNames = $this->resolveForNonNewAssigns($functionLike); $protectedNames = \array_merge($paramNames, $newAssignNames, $nonNewAssignNames); $protectedNames = $this->arrayFilter->filterWithAtLeastTwoOccurences($protectedNames); $this->conflictingVariableNamesByClassMethod[$classMethodId] = $protectedNames; return $protectedNames; } /** * @return string[] * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ private function resolveForNewAssigns($functionLike) : array { $names = []; /** @var Assign[] $assigns */ $assigns = $this->betterNodeFinder->findInstanceOf((array) $functionLike->getStmts(), Assign::class); foreach ($assigns as $assign) { $name = $this->expectedNameResolver->resolveForAssignNew($assign); if ($name === null) { continue; } $names[] = $name; } return $names; } /** * @return string[] * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ private function resolveForNonNewAssigns($functionLike) : array { $names = []; /** @var Assign[] $assigns */ $assigns = $this->betterNodeFinder->findInstanceOf((array) $functionLike->getStmts(), Assign::class); foreach ($assigns as $assign) { $name = $this->expectedNameResolver->resolveForAssignNonNew($assign); if ($name === null) { continue; } $names[] = $name; } return $names; } } Naming/OverridenExistingNamesResolver.php000064400000007357152535021720014662 0ustar00> */ private $overridenExistingVariableNamesByClassMethod = []; public function __construct(ArrayFilter $arrayFilter, BetterNodeFinder $betterNodeFinder, NodeNameResolver $nodeNameResolver) { $this->arrayFilter = $arrayFilter; $this->betterNodeFinder = $betterNodeFinder; $this->nodeNameResolver = $nodeNameResolver; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike */ public function hasNameInClassMethodForNew(string $variableName, $functionLike) : bool { $overridenVariableNames = $this->resolveOveriddenNamesForNew($functionLike); return \in_array($variableName, $overridenVariableNames, \true); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $classMethod */ public function hasNameInFunctionLikeForParam(string $expectedName, $classMethod) : bool { /** @var Assign[] $assigns */ $assigns = $this->betterNodeFinder->findInstanceOf((array) $classMethod->getStmts(), Assign::class); $usedVariableNames = []; foreach ($assigns as $assign) { if (!$assign->var instanceof Variable) { continue; } $variableName = $this->nodeNameResolver->getName($assign->var); if ($variableName === null) { continue; } $usedVariableNames[] = $variableName; } return \in_array($expectedName, $usedVariableNames, \true); } /** * @return string[] * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike */ private function resolveOveriddenNamesForNew($functionLike) : array { $classMethodId = \spl_object_id($functionLike); if (isset($this->overridenExistingVariableNamesByClassMethod[$classMethodId])) { return $this->overridenExistingVariableNamesByClassMethod[$classMethodId]; } $currentlyUsedNames = []; /** @var Assign[] $assigns */ $assigns = $this->betterNodeFinder->findInstanceOf((array) $functionLike->stmts, Assign::class); foreach ($assigns as $assign) { /** @var Variable $assignVariable */ $assignVariable = $assign->var; $currentVariableName = $this->nodeNameResolver->getName($assignVariable); if ($currentVariableName === null) { continue; } $currentlyUsedNames[] = $currentVariableName; } $currentlyUsedNames = \array_values($currentlyUsedNames); $currentlyUsedNames = $this->arrayFilter->filterWithAtLeastTwoOccurences($currentlyUsedNames); $this->overridenExistingVariableNamesByClassMethod[$classMethodId] = $currentlyUsedNames; return $currentlyUsedNames; } } Naming/ExpectedNameResolver.php000064400000017331152535021720012561 0ustar00nodeNameResolver = $nodeNameResolver; $this->nodeTypeResolver = $nodeTypeResolver; $this->propertyNaming = $propertyNaming; $this->matchParamTypeExpectedNameResolver = $matchParamTypeExpectedNameResolver; } public function resolveForParamIfNotYet(Param $param) : ?string { if ($param->type instanceof UnionType) { return null; } $expectedName = $this->matchParamTypeExpectedNameResolver->resolve($param); if ($expectedName === null) { return null; } /** @var string $currentName */ $currentName = $this->nodeNameResolver->getName($param->var); if ($currentName === $expectedName || \substr_compare($currentName, \ucfirst($expectedName), -\strlen(\ucfirst($expectedName))) === 0) { return null; } return $expectedName; } public function resolveForAssignNonNew(Assign $assign) : ?string { if ($assign->expr instanceof New_) { return null; } if (!$assign->var instanceof Variable) { return null; } /** @var Variable $variable */ $variable = $assign->var; return $this->nodeNameResolver->getName($variable); } public function resolveForAssignNew(Assign $assign) : ?string { if (!$assign->expr instanceof New_) { return null; } if (!$assign->var instanceof Variable) { return null; } /** @var New_ $new */ $new = $assign->expr; if (!$new->class instanceof Name) { return null; } $className = $this->nodeNameResolver->getName($new->class); $fullyQualifiedObjectType = new FullyQualifiedObjectType($className); if ($fullyQualifiedObjectType->isInstanceOf(DateTimeInterface::class)->yes()) { return null; } $expectedName = $this->propertyNaming->getExpectedNameFromType($fullyQualifiedObjectType); if (!$expectedName instanceof ExpectedName) { return null; } return $expectedName->getName(); } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\FuncCall $expr */ public function resolveForCall($expr) : ?string { if ($this->isDynamicNameCall($expr)) { return null; } $name = $this->nodeNameResolver->getName($expr->name); if ($name === null) { return null; } $returnedType = $this->nodeTypeResolver->getType($expr); if (!$returnedType->isObject()->yes()) { return null; } if ($this->isDateTimeType($returnedType)) { return null; } $expectedName = $this->propertyNaming->getExpectedNameFromType($returnedType); if ($expectedName instanceof ExpectedName) { return $expectedName->getName(); } // call with args can return different value, so skip there if not sure about the type if ($expr->args !== []) { return null; } $expectedNameFromMethodName = $this->propertyNaming->getExpectedNameFromMethodName($name); if ($expectedNameFromMethodName instanceof ExpectedName) { return $expectedNameFromMethodName->getName(); } return null; } public function resolveForForeach(VariableAndCallForeach $variableAndCallForeach) : ?string { $call = $variableAndCallForeach->getCall(); if ($this->isDynamicNameCall($call)) { return null; } $name = $this->nodeNameResolver->getName($call->name); if ($name === null) { return null; } $returnedType = $this->nodeTypeResolver->getType($call); if ($returnedType->isIterable()->no()) { return null; } $innerReturnedType = null; if ($returnedType instanceof ArrayType) { $innerReturnedType = $this->resolveReturnTypeFromArrayType($returnedType); if (!$innerReturnedType instanceof Type) { return null; } } $expectedNameFromType = $this->propertyNaming->getExpectedNameFromType($innerReturnedType ?? $returnedType); if ($this->isReturnedTypeAnArrayAndExpectedNameFromTypeNotNull($returnedType, $expectedNameFromType)) { return ($nullsafeVariable1 = $expectedNameFromType) ? $nullsafeVariable1->getSingularized() : null; } $expectedNameFromMethodName = $this->propertyNaming->getExpectedNameFromMethodName($name); if (!$expectedNameFromMethodName instanceof ExpectedName) { return ($nullsafeVariable2 = $expectedNameFromType) ? $nullsafeVariable2->getSingularized() : null; } if ($expectedNameFromMethodName->isSingular()) { return ($nullsafeVariable3 = $expectedNameFromType) ? $nullsafeVariable3->getSingularized() : null; } return $expectedNameFromMethodName->getSingularized(); } private function isReturnedTypeAnArrayAndExpectedNameFromTypeNotNull(Type $returnedType, ?ExpectedName $expectedName) : bool { return $returnedType instanceof ArrayType && $expectedName instanceof ExpectedName; } /** * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\FuncCall $expr */ private function isDynamicNameCall($expr) : bool { if ($expr->name instanceof StaticCall) { return \true; } if ($expr->name instanceof MethodCall) { return \true; } return $expr->name instanceof FuncCall; } private function resolveReturnTypeFromArrayType(ArrayType $arrayType) : ?Type { if (!$arrayType->getItemType() instanceof ObjectType) { return null; } return $arrayType->getItemType(); } /** * Skip date time, as custom naming */ private function isDateTimeType(Type $type) : bool { if (!$type instanceof ObjectType) { return \false; } if ($type->isInstanceOf('DateTimeInterface')->yes()) { return \true; } return $type->isInstanceOf('DateTime')->yes(); } } Contract/AssignVariableNameResolverInterface.php000064400000000467152535021720016101 0ustar00matchPropertyTypeExpectedNameResolver = $matchPropertyTypeExpectedNameResolver; $this->nodeNameResolver = $nodeNameResolver; $this->arrayFilter = $arrayFilter; } public function isConflicting(PropertyRename $propertyRename) : bool { $conflictingPropertyNames = $this->resolve($propertyRename->getClassLike()); return \in_array($propertyRename->getExpectedName(), $conflictingPropertyNames, \true); } /** * @return string[] */ private function resolve(ClassLike $classLike) : array { $expectedNames = []; foreach ($classLike->getProperties() as $property) { $expectedName = $this->matchPropertyTypeExpectedNameResolver->resolve($property, $classLike); if ($expectedName === null) { // fallback to existing name $expectedName = $this->nodeNameResolver->getName($property); } $expectedNames[] = $expectedName; } return $this->arrayFilter->filterWithAtLeastTwoOccurences($expectedNames); } } Guard/BreakingVariableRenameGuard.php000064400000020341152535021720013624 0ustar00betterNodeFinder = $betterNodeFinder; $this->conflictingNameResolver = $conflictingNameResolver; $this->nodeTypeResolver = $nodeTypeResolver; $this->overridenExistingNamesResolver = $overridenExistingNamesResolver; $this->typeUnwrapper = $typeUnwrapper; $this->nodeNameResolver = $nodeNameResolver; } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ public function shouldSkipVariable(string $currentName, string $expectedName, $functionLike, Variable $variable) : bool { // is the suffix? → also accepted $expectedNameCamelCase = \ucfirst($expectedName); if (\substr_compare($currentName, $expectedNameCamelCase, -\strlen($expectedNameCamelCase)) === 0) { return \true; } if ($this->conflictingNameResolver->hasNameIsInFunctionLike($expectedName, $functionLike)) { return \true; } if (!$functionLike instanceof ArrowFunction && $this->overridenExistingNamesResolver->hasNameInClassMethodForNew($currentName, $functionLike)) { return \true; } if ($this->isVariableAlreadyDefined($variable, $currentName)) { return \true; } if ($this->hasConflictVariable($functionLike, $expectedName)) { return \true; } return $functionLike instanceof Closure && $this->isUsedInClosureUsesName($expectedName, $functionLike); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $classMethod */ public function shouldSkipParam(string $currentName, string $expectedName, $classMethod, Param $param) : bool { // is the suffix? → also accepted $expectedNameCamelCase = \ucfirst($expectedName); if (\substr_compare($currentName, $expectedNameCamelCase, -\strlen($expectedNameCamelCase)) === 0) { return \true; } $conflictingNames = $this->conflictingNameResolver->resolveConflictingVariableNamesForParam($classMethod); if (\in_array($expectedName, $conflictingNames, \true)) { return \true; } if ($this->conflictingNameResolver->hasNameIsInFunctionLike($expectedName, $classMethod)) { return \true; } if ($this->overridenExistingNamesResolver->hasNameInFunctionLikeForParam($expectedName, $classMethod)) { return \true; } if ($param->var instanceof Error) { return \true; } if ($this->isVariableAlreadyDefined($param->var, $currentName)) { return \true; } if ($this->isRamseyUuidInterface($param)) { return \true; } if ($this->isGenerator($param)) { return \true; } if ($this->isDateTimeAtNamingConvention($param)) { return \true; } return (bool) $this->betterNodeFinder->findFirst((array) $classMethod->getStmts(), function (Node $node) use($expectedName) : bool { if (!$node instanceof Variable) { return \false; } return $this->nodeNameResolver->isName($node, $expectedName); }); } private function isVariableAlreadyDefined(Variable $variable, string $currentVariableName) : bool { $scope = $variable->getAttribute(AttributeKey::SCOPE); if (!$scope instanceof Scope) { return \false; } $trinaryLogic = $scope->hasVariableType($currentVariableName); if ($trinaryLogic->yes()) { return \true; } return $trinaryLogic->maybe(); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure|\PhpParser\Node\Expr\ArrowFunction $functionLike */ private function hasConflictVariable($functionLike, string $newName) : bool { if ($functionLike instanceof ArrowFunction) { return $this->betterNodeFinder->hasInstanceOfName(\array_merge([$functionLike->expr], $functionLike->params), Variable::class, $newName); } return $this->betterNodeFinder->hasInstanceOfName(\array_merge((array) $functionLike->stmts, $functionLike->params), Variable::class, $newName); } /** * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike */ private function isUsedInClosureUsesName(string $expectedName, $functionLike) : bool { if (!$functionLike instanceof Closure) { return \false; } return $this->betterNodeFinder->hasVariableOfName($functionLike->uses, $expectedName); } private function isRamseyUuidInterface(Param $param) : bool { return $this->nodeTypeResolver->isObjectType($param, new ObjectType('Ramsey\\Uuid\\UuidInterface')); } private function isDateTimeAtNamingConvention(Param $param) : bool { $type = $this->nodeTypeResolver->getType($param); $type = $this->typeUnwrapper->unwrapFirstObjectTypeFromUnionType($type); if (!$type instanceof TypeWithClassName) { return \false; } if (!\is_a($type->getClassName(), DateTimeInterface::class, \true)) { return \false; } /** @var string $currentName */ $currentName = $this->nodeNameResolver->getName($param); return StringUtils::isMatch($currentName, self::AT_NAMING_REGEX); } private function isGenerator(Param $param) : bool { if (!$param->type instanceof Node) { return \false; } $paramType = $this->nodeTypeResolver->getType($param); if (!$paramType instanceof ObjectType) { return \false; } if (\substr_compare($paramType->getClassName(), 'Generator', -\strlen('Generator')) === 0 || \substr_compare($paramType->getClassName(), 'Iterator', -\strlen('Iterator')) === 0) { return \true; } return $paramType->isInstanceOf('Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator')->yes(); } } Guard/DateTimeAtNamingConventionGuard.php000064400000002560152535021720014465 0ustar00nodeTypeResolver = $nodeTypeResolver; $this->typeUnwrapper = $typeUnwrapper; } public function isConflicting(PropertyRename $propertyRename) : bool { $type = $this->nodeTypeResolver->getType($propertyRename->getProperty()); $type = $this->typeUnwrapper->unwrapFirstObjectTypeFromUnionType($type); if (!$type instanceof TypeWithClassName) { return \false; } if (!\is_a($type->getClassName(), DateTimeInterface::class, \true)) { return \false; } return StringUtils::isMatch($propertyRename->getCurrentName(), \Rector\Naming\Guard\BreakingVariableRenameGuard::AT_NAMING_REGEX); } } Guard/HasMagicGetSetGuard.php000064400000001605152535021720012076 0ustar00reflectionProvider = $reflectionProvider; } public function isConflicting(PropertyRename $propertyRename) : bool { if (!$this->reflectionProvider->hasClass($propertyRename->getClassLikeName())) { return \false; } $classReflection = $this->reflectionProvider->getClass($propertyRename->getClassLikeName()); if ($classReflection->hasMethod('__set')) { return \true; } return $classReflection->hasMethod('__get'); } }