diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md
index c05b1ca6f71..7a168a9961e 100644
--- a/docs/rector_rules_overview.md
+++ b/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# All 489 Rectors Overview
+# All 490 Rectors Overview
- [Projects](#projects)
- [General](#general)
@@ -22,7 +22,7 @@
- [Guzzle](#guzzle) (1)
- [JMS](#jms) (2)
- [Laravel](#laravel) (6)
-- [Legacy](#legacy) (1)
+- [Legacy](#legacy) (2)
- [MysqlToMysqli](#mysqltomysqli) (4)
- [Naming](#naming) (1)
- [Nette](#nette) (11)
@@ -4145,6 +4145,27 @@ Change singleton class to normal class that can be registered as a service
+### `FunctionToStaticMethodRector`
+
+- class: [`Rector\Legacy\Rector\Node\FunctionToStaticMethodRector`](/../master/rules/legacy/src/Rector/Node/FunctionToStaticMethodRector.php)
+
+Change functions to static calls, so composer can autoload them
+
+```diff
+-function some_function()
++class SomeUtilsClass
+ {
++ public static function someFunction()
++ {
++ }
+ }
+
+-some_function('lol');
++SomeUtilsClass::someFunction('lol');
+```
+
+
+
## MysqlToMysqli
### `MysqlAssignToMysqliRector`
diff --git a/ecs.yaml b/ecs.yaml
index 4c22dcc6d68..14181229ea1 100644
--- a/ecs.yaml
+++ b/ecs.yaml
@@ -1,3 +1,7 @@
+services:
+ SlevomatCodingStandard\Sniffs\Commenting\DisallowCommentAfterCodeSniff: null
+ SlevomatCodingStandard\Sniffs\Whitespaces\DuplicateSpacesSniff: null
+
parameters:
paths:
- "bin"
diff --git a/packages/node-collector/src/NodeCollector/ParsedFunctionLikeNodeCollector.php b/packages/node-collector/src/NodeCollector/ParsedFunctionLikeNodeCollector.php
index 01ebf537c9f..ba4ade49afc 100644
--- a/packages/node-collector/src/NodeCollector/ParsedFunctionLikeNodeCollector.php
+++ b/packages/node-collector/src/NodeCollector/ParsedFunctionLikeNodeCollector.php
@@ -171,7 +171,8 @@ final class ParsedFunctionLikeNodeCollector
private function addMethod(ClassMethod $classMethod): void
{
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
- if ($className === null) { // anonymous
+ // anonymous
+ if ($className === null) {
return;
}
@@ -192,7 +193,8 @@ final class ParsedFunctionLikeNodeCollector
$classType = $this->resolveNodeClassTypes($node->class);
}
- if ($classType instanceof MixedType) { // anonymous
+ // anonymous
+ if ($classType instanceof MixedType) {
return;
}
diff --git a/packages/node-collector/src/NodeFinder/MethodCallParsedNodesFinder.php b/packages/node-collector/src/NodeFinder/MethodCallParsedNodesFinder.php
index ff193eda415..c5d392b2fa8 100644
--- a/packages/node-collector/src/NodeFinder/MethodCallParsedNodesFinder.php
+++ b/packages/node-collector/src/NodeFinder/MethodCallParsedNodesFinder.php
@@ -30,7 +30,8 @@ final class MethodCallParsedNodesFinder
{
/** @var string|null $className */
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
- if ($className === null) { // anonymous
+ // anonymous
+ if ($className === null) {
return [];
}
diff --git a/packages/node-type-resolver/src/NodeScopeAndMetadataDecorator.php b/packages/node-type-resolver/src/NodeScopeAndMetadataDecorator.php
index 7cf8bb31867..8a0102e0333 100644
--- a/packages/node-type-resolver/src/NodeScopeAndMetadataDecorator.php
+++ b/packages/node-type-resolver/src/NodeScopeAndMetadataDecorator.php
@@ -134,7 +134,8 @@ final class NodeScopeAndMetadataDecorator
$nodes = $nodeTraverser->traverse($nodes);
$nodeTraverser = new NodeTraverser();
- $nodeTraverser->addVisitor($this->cloningVisitor); // needed also for format preserving printing
+ // needed also for format preserving printing
+ $nodeTraverser->addVisitor($this->cloningVisitor);
$nodeTraverser->addVisitor($this->parentAndNextNodeVisitor);
$nodeTraverser->addVisitor($this->functionMethodAndClassNodeVisitor);
$nodeTraverser->addVisitor($this->namespaceNodeVisitor);
diff --git a/packages/node-type-resolver/src/PHPStan/TypeComparator.php b/packages/node-type-resolver/src/PHPStan/TypeComparator.php
index e38a3b43db1..1385ce1b265 100644
--- a/packages/node-type-resolver/src/PHPStan/TypeComparator.php
+++ b/packages/node-type-resolver/src/PHPStan/TypeComparator.php
@@ -69,7 +69,7 @@ final class TypeComparator
}
/**
- * E.g. class A extends B, class B → A[] is subtype of B[] → keep A[]
+ * E.g. class A extends B, class B → A[] is subtype of B[] → keep A[]
*/
private function areArrayTypeWithSingleObjectChildToParent(Type $firstType, Type $secondType): bool
{
diff --git a/rules/code-quality/src/Rector/FuncCall/SingleInArrayToCompareRector.php b/rules/code-quality/src/Rector/FuncCall/SingleInArrayToCompareRector.php
index eb11e16486e..a52b445d37c 100644
--- a/rules/code-quality/src/Rector/FuncCall/SingleInArrayToCompareRector.php
+++ b/rules/code-quality/src/Rector/FuncCall/SingleInArrayToCompareRector.php
@@ -77,7 +77,8 @@ PHP
}
$onlyArrayItem = $arrayNode->items[0]->value;
- if (isset($node->args[2])) { // strict
+ // strict
+ if (isset($node->args[2])) {
return new Identical($node->args[0]->value, $onlyArrayItem);
}
diff --git a/rules/coding-style/src/Naming/ClassNaming.php b/rules/coding-style/src/Naming/ClassNaming.php
index 7af0641ed1a..79ad56aa96c 100644
--- a/rules/coding-style/src/Naming/ClassNaming.php
+++ b/rules/coding-style/src/Naming/ClassNaming.php
@@ -7,8 +7,11 @@ namespace Rector\CodingStyle\Naming;
use Nette\Utils\Strings;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
+use PhpParser\Node\Stmt\Function_;
use Rector\Core\Exception\ShouldNotHappenException;
+use Rector\Core\Util\StaticRectorStrings;
use Rector\NodeNameResolver\NodeNameResolver;
+use Symplify\SmartFileSystem\SmartFileInfo;
final class ClassNaming
{
@@ -45,4 +48,20 @@ final class ClassNaming
return Strings::before($fullyQualifiedName, '\\', -1) ?: null;
}
+
+ public function getNameFromFileInfo(SmartFileInfo $smartFileInfo): string
+ {
+ $basename = $smartFileInfo->getBasenameWithoutSuffix();
+
+ return StaticRectorStrings::underscoreToCamelCase($basename);
+ }
+
+ /**
+ * "some_function" → "someFunction"
+ */
+ public function createMethodNameFromFunction(Function_ $function): string
+ {
+ $functionName = (string) $function->name;
+ return StaticRectorStrings::underscoreToPascalCase($functionName);
+ }
}
diff --git a/rules/dead-code/src/Rector/MethodCall/RemoveDefaultArgumentValueRector.php b/rules/dead-code/src/Rector/MethodCall/RemoveDefaultArgumentValueRector.php
index 74962abda5f..2e4e7f1a4f7 100644
--- a/rules/dead-code/src/Rector/MethodCall/RemoveDefaultArgumentValueRector.php
+++ b/rules/dead-code/src/Rector/MethodCall/RemoveDefaultArgumentValueRector.php
@@ -152,7 +152,8 @@ PHP
/** @var string|null $className */
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
- if ($className === null) { // anonymous class
+ // anonymous class
+ if ($className === null) {
return [];
}
diff --git a/rules/laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php b/rules/laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php
index 3361389acb3..8e36992835f 100644
--- a/rules/laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php
+++ b/rules/laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php
@@ -94,7 +94,8 @@ PHP
{
return [
'Illuminate\Support\Facades\Cache' => [
- 'put' => 2, // time argument position
+ // time argument position
+ 'put' => 2,
'add' => 2,
],
Store::class => [
diff --git a/rules/legacy/config/config.yaml b/rules/legacy/config/config.yaml
index 88688f91b2c..b096b4bdac9 100644
--- a/rules/legacy/config/config.yaml
+++ b/rules/legacy/config/config.yaml
@@ -7,3 +7,4 @@ services:
resource: '../src'
exclude:
- '../src/Rector/**/*Rector.php'
+ - '../src/ValueObject/*'
diff --git a/rules/legacy/src/Rector/Node/FunctionToStaticMethodRector.php b/rules/legacy/src/Rector/Node/FunctionToStaticMethodRector.php
new file mode 100644
index 00000000000..9d8f5242881
--- /dev/null
+++ b/rules/legacy/src/Rector/Node/FunctionToStaticMethodRector.php
@@ -0,0 +1,184 @@
+classNaming = $classNaming;
+ }
+
+ public function getDefinition(): RectorDefinition
+ {
+ return new RectorDefinition('Change functions to static calls, so composer can autoload them', [
+ new CodeSample(
+ <<<'PHP'
+function some_function()
+{
+}
+
+some_function('lol');
+PHP
+,
+ <<<'PHP'
+class SomeUtilsClass
+{
+ public static function someFunction()
+ {
+ }
+}
+
+SomeUtilsClass::someFunction('lol');
+PHP
+
+ ),
+ ]);
+ }
+
+ public function refactor(SmartFileInfo $smartFileInfo): void
+ {
+ $nodes = $this->parseFileInfoToNodes($smartFileInfo);
+ $fileStmts = $this->getFileOrNamespaceStmts($nodes);
+
+ /** @var Function_[] $functions */
+ $functions = $this->betterNodeFinder->findInstanceOf($fileStmts, Function_::class);
+ if ($functions === []) {
+ return;
+ }
+
+ $shortClassName = $this->classNaming->getNameFromFileInfo($smartFileInfo);
+ $classBuilder = new ClassBuilder($shortClassName);
+ $classBuilder->makeFinal();
+
+ $className = $this->getFullyQualifiedName($nodes, $shortClassName);
+
+ foreach ($functions as $function) {
+ $functionName = $this->getName($function);
+ $methodName = $this->classNaming->createMethodNameFromFunction($function);
+ $this->functionNameToClassStaticMethod[$functionName] = new StaticCallPointer($className, $methodName);
+
+ $staticClassMethod = $this->createClassMethodFromFunction($methodName, $function);
+ $classBuilder->addStmt($staticClassMethod);
+
+ // remove after convert, we won't need it
+ $this->removeNode($function);
+ }
+
+ $class = $classBuilder->getNode();
+
+ $classFilePath = $smartFileInfo->getPath() . DIRECTORY_SEPARATOR . $shortClassName . '.php';
+ $nodesToPrint = $this->resolveNodesToPrint($nodes, $class);
+
+ // replace function calls with class static call
+
+ $this->traverseNodesWithCallable($nodes, function (Node $node) {
+ if (! $node instanceof FuncCall) {
+ return null;
+ }
+
+ $funcCallName = $this->getName($node);
+ $staticCallPointer = $this->functionNameToClassStaticMethod[$funcCallName] ?? null;
+ if ($staticCallPointer === null) {
+ return null;
+ }
+
+ $staticCall = $this->createStaticCall($staticCallPointer->getClass(), $staticCallPointer->getMethod());
+ $staticCall->args = $node->args;
+
+ return $staticCall;
+ });
+
+ // @todo decouple to PostRectorInterface, so it's covered in external files too
+ $this->printNewNodesToFilePath($nodesToPrint, $classFilePath);
+ }
+
+ /**
+ * @param Node[] $nodes
+ * @return Node[]
+ */
+ private function resolveNodesToPrint(array $nodes, Class_ $class): array
+ {
+ /** @var Namespace_|null $namespace */
+ $namespace = $this->betterNodeFinder->findFirstInstanceOf($nodes, Namespace_::class);
+ if ($namespace !== null) {
+ // put class first
+ $namespace->stmts = array_merge([$class], $namespace->stmts);
+
+ return [$namespace];
+ }
+
+ return [$class];
+ }
+
+ /**
+ * @param Node[] $nodes
+ * @return Node[]
+ */
+ private function getFileOrNamespaceStmts(array $nodes): array
+ {
+ /** @var Namespace_|null $namespace */
+ $namespace = $this->betterNodeFinder->findFirstInstanceOf($nodes, Namespace_::class);
+ if ($namespace === null) {
+ return $nodes;
+ }
+
+ return $namespace->stmts;
+ }
+
+ private function getFullyQualifiedName(array $nodes, string $shortClassName): string
+ {
+ /** @var Namespace_|null $namespace */
+ $namespace = $this->betterNodeFinder->findFirstInstanceOf($nodes, Namespace_::class);
+ if ($namespace === null) {
+ return $shortClassName;
+ }
+
+ $namespaceName = $this->getName($namespace);
+ if ($namespaceName === null) {
+ return $shortClassName;
+ }
+
+ return $namespaceName . '\\' . $shortClassName;
+ }
+
+ private function createClassMethodFromFunction(string $methodName, Function_ $function): ClassMethod
+ {
+ $methodBuilder = new Method($methodName);
+ $methodBuilder->makePublic();
+ $methodBuilder->makeStatic();
+ $methodBuilder->addStmts($function->stmts);
+
+ return $methodBuilder->getNode();
+ }
+}
diff --git a/rules/legacy/src/ValueObject/StaticCallPointer.php b/rules/legacy/src/ValueObject/StaticCallPointer.php
new file mode 100644
index 00000000000..9d9499825ce
--- /dev/null
+++ b/rules/legacy/src/ValueObject/StaticCallPointer.php
@@ -0,0 +1,34 @@
+class = $class;
+ $this->method = $method;
+ }
+
+ public function getClass(): string
+ {
+ return $this->class;
+ }
+
+ public function getMethod(): string
+ {
+ return $this->method;
+ }
+}
diff --git a/rules/legacy/tests/Rector/FileSystem/FunctionToStaticMethodRector/FunctionToStaticMethodRectorTest.php b/rules/legacy/tests/Rector/FileSystem/FunctionToStaticMethodRector/FunctionToStaticMethodRectorTest.php
new file mode 100644
index 00000000000..79f7c94efa2
--- /dev/null
+++ b/rules/legacy/tests/Rector/FileSystem/FunctionToStaticMethodRector/FunctionToStaticMethodRectorTest.php
@@ -0,0 +1,27 @@
+doTestFile(__DIR__ . '/Source/static_functions.php');
+
+ $this->assertFileExists(__DIR__ . '/Fixture/StaticFunctions.php');
+ $this->assertFileEquals(
+ __DIR__ . '/Source/ExpectedStaticFunctions.php',
+ __DIR__ . '/Fixture/StaticFunctions.php'
+ );
+ }
+
+ protected function getRectorClass(): string
+ {
+ return FunctionToStaticMethodRector::class;
+ }
+}
diff --git a/rules/legacy/tests/Rector/FileSystem/FunctionToStaticMethodRector/Source/ExpectedStaticFunctions.php b/rules/legacy/tests/Rector/FileSystem/FunctionToStaticMethodRector/Source/ExpectedStaticFunctions.php
new file mode 100644
index 00000000000..86ba60505ae
--- /dev/null
+++ b/rules/legacy/tests/Rector/FileSystem/FunctionToStaticMethodRector/Source/ExpectedStaticFunctions.php
@@ -0,0 +1,12 @@
+classesToSkip = $classesToSkip;
diff --git a/rules/php70/src/EregToPcreTransformer.php b/rules/php70/src/EregToPcreTransformer.php
index b1f90c2090e..8916badf54a 100644
--- a/rules/php70/src/EregToPcreTransformer.php
+++ b/rules/php70/src/EregToPcreTransformer.php
@@ -28,7 +28,8 @@ final class EregToPcreTransformer
':lower:' => '[:lower:]',
':print:' => '[:print:]',
':punct:' => '[:punct:]',
- ':space:' => '\013\s', // should include VT
+ // should include VT
+ ':space:' => '\013\s',
':upper:' => '[:upper:]',
':xdigit:' => '[:xdigit:]',
];
@@ -153,7 +154,8 @@ final class EregToPcreTransformer
throw new InvalidEregException('an invalid escape sequence at the end');
}
$r[$rr] .= $this->_ere2pcre_escape($content[$i]);
- } else { // including ] and } which are allowed as a literal character
+ } else {
+ // including ] and } which are allowed as a literal character
$r[$rr] .= $this->_ere2pcre_escape($char);
}
++$i;
@@ -181,7 +183,8 @@ final class EregToPcreTransformer
private function processBracket(string $content, int $i, int $l, array &$r, int $rr)
{
- if ($i + 1 < $l && $content[$i + 1] === ')') { // special case
+ // special case
+ if ($i + 1 < $l && $content[$i + 1] === ')') {
$r[$rr] .= '()';
++$i;
} else {
diff --git a/rules/phpunit/src/Rector/ExceptionAnnotationRector.php b/rules/phpunit/src/Rector/ExceptionAnnotationRector.php
index dc4ed9d992b..d1a83a2b2d4 100644
--- a/rules/phpunit/src/Rector/ExceptionAnnotationRector.php
+++ b/rules/phpunit/src/Rector/ExceptionAnnotationRector.php
@@ -113,7 +113,8 @@ PHP
private function createMethodCallExpressionFromTag(PhpDocTagNode $phpDocTagNode, string $method): MethodCall
{
$annotationContent = (string) $phpDocTagNode->value;
- $annotationContent = ltrim($annotationContent, '\\'); // this is needed due to BuilderHelpers
+ // this is needed due to BuilderHelpers
+ $annotationContent = ltrim($annotationContent, '\\');
return $this->createMethodCall('this', $method, [$annotationContent]);
}
diff --git a/rules/phpunit/src/Rector/MethodCall/GetMockBuilderGetMockToCreateMockRector.php b/rules/phpunit/src/Rector/MethodCall/GetMockBuilderGetMockToCreateMockRector.php
index 5e590742ff7..c2ec42fe498 100644
--- a/rules/phpunit/src/Rector/MethodCall/GetMockBuilderGetMockToCreateMockRector.php
+++ b/rules/phpunit/src/Rector/MethodCall/GetMockBuilderGetMockToCreateMockRector.php
@@ -69,7 +69,8 @@ PHP
}
if ($this->isName($node->var->name, 'disableOriginalConstructor')) {
- $getMockBuilderMethodCall = $node->var->var; // null;
+ // null;
+ $getMockBuilderMethodCall = $node->var->var;
} else {
$getMockBuilderMethodCall = $node->var;
}
diff --git a/src/Console/Command/ShowCommand.php b/src/Console/Command/ShowCommand.php
index 63363f2ea58..b6591c2c365 100644
--- a/src/Console/Command/ShowCommand.php
+++ b/src/Console/Command/ShowCommand.php
@@ -8,6 +8,7 @@ use Rector\Core\Contract\Rector\RectorInterface;
use Rector\Core\Php\TypeAnalyzer;
use Rector\Core\Yaml\YamlPrinter;
use Rector\PostRector\Contract\Rector\PostRectorInterface;
+use Rector\Utils\DoctrineAnnotationParserSyncer\Contract\Rector\ClassSyncerRectorInterface;
use ReflectionClass;
use ReflectionNamedType;
use Symfony\Component\Console\Input\InputInterface;
@@ -129,6 +130,11 @@ final class ShowCommand extends AbstractCommand
sort($rectors);
return array_filter($rectors, function (RectorInterface $rector) {
+ // utils rules
+ if ($rector instanceof ClassSyncerRectorInterface) {
+ return false;
+ }
+
// skip as internal and always run
return ! $rector instanceof PostRectorInterface;
});
diff --git a/src/FileSystem/FilesystemTweaker.php b/src/FileSystem/FilesystemTweaker.php
index 9737c1aec98..b6ecdaafa4d 100644
--- a/src/FileSystem/FilesystemTweaker.php
+++ b/src/FileSystem/FilesystemTweaker.php
@@ -19,9 +19,11 @@ final class FilesystemTweaker
{
$absoluteDirectories = [];
foreach ($directories as $directory) {
- if (Strings::contains($directory, '*')) { // is fnmatch for directories
+ // is fnmatch for directories
+ if (Strings::contains($directory, '*')) {
$absoluteDirectories = array_merge($absoluteDirectories, glob($directory, GLOB_ONLYDIR));
- } else { // is classic directory
+ } else {
+ // is classic directory
$this->ensureDirectoryExists($directory);
$absoluteDirectories[] = $directory;
}
diff --git a/src/Php/PhpVersionProvider.php b/src/Php/PhpVersionProvider.php
index f3360b20630..717d9c2e31e 100644
--- a/src/Php/PhpVersionProvider.php
+++ b/src/Php/PhpVersionProvider.php
@@ -32,7 +32,8 @@ final class PhpVersionProvider
// for tests
if (StaticPHPUnitEnvironment::isPHPUnitRun()) {
- return '10.0'; // so we don't have to up
+ // so we don't have to up
+ return '10.0';
}
// see https://getcomposer.org/doc/06-config.md#platform
diff --git a/src/Rector/MethodBody/NormalToFluentRector.php b/src/Rector/MethodBody/NormalToFluentRector.php
index a99ee4eb577..f89a523f383 100644
--- a/src/Rector/MethodBody/NormalToFluentRector.php
+++ b/src/Rector/MethodBody/NormalToFluentRector.php
@@ -179,7 +179,8 @@ PHP
$methodCallsToAdd = array_reverse($methodCallsToAdd);
foreach ($methodCallsToAdd as $methodCallToAdd) {
- $fluentMethodCall->var = new MethodCall( // make var a parent method call
+ // make var a parent method call
+ $fluentMethodCall->var = new MethodCall(
$fluentMethodCall->var,
$methodCallToAdd->name,
$methodCallToAdd->args
diff --git a/src/Rector/Property/PropertyToMethodRector.php b/src/Rector/Property/PropertyToMethodRector.php
index ae78689b795..33476ee1afd 100644
--- a/src/Rector/Property/PropertyToMethodRector.php
+++ b/src/Rector/Property/PropertyToMethodRector.php
@@ -181,7 +181,8 @@ PHP
/** @var Identifier $identifierNode */
$identifierNode = $propertyFetch->name;
- return $propertyToMethods[$identifierNode->toString()]; //[$type];
+ //[$type];
+ return $propertyToMethods[$identifierNode->toString()];
}
return null;
diff --git a/src/Testing/PHPUnit/AbstractFileSystemRectorTestCase.php b/src/Testing/PHPUnit/AbstractFileSystemRectorTestCase.php
index 81fa1d4e2c0..5dcf7733b2a 100644
--- a/src/Testing/PHPUnit/AbstractFileSystemRectorTestCase.php
+++ b/src/Testing/PHPUnit/AbstractFileSystemRectorTestCase.php
@@ -8,6 +8,7 @@ use Nette\Utils\FileSystem;
use Nette\Utils\Strings;
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesProcessor;
use Rector\Core\Configuration\Configuration;
+use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\HttpKernel\RectorKernel;
use Rector\FileSystemRector\Contract\FileSystemRectorInterface;
use Rector\FileSystemRector\FileSystemFileProcessor;
@@ -56,6 +57,15 @@ abstract class AbstractFileSystemRectorTestCase extends AbstractGenericRectorTes
{
$temporaryFilePath = $this->createTemporaryFilePathFromFilePath($file);
+ if ($temporaryFilePath === $file) {
+ $message = sprintf(
+ 'File %s is about to be copied to itself. Move it out of "/Fixture" directory to "/Source"',
+ $file
+ );
+
+ throw new ShouldNotHappenException($message);
+ }
+
$this->fileSystemFileProcessor->processFileInfo(new SmartFileInfo($temporaryFilePath));
$this->removedAndAddedFilesProcessor->run();
@@ -133,7 +143,7 @@ abstract class AbstractFileSystemRectorTestCase extends AbstractGenericRectorTes
$fileInfo->getBasename()
);
- FileSystem::copy($file, $temporaryFilePath);
+ FileSystem::copy($file, $temporaryFilePath, true);
return $temporaryFilePath;
}
diff --git a/src/Util/StaticRectorStrings.php b/src/Util/StaticRectorStrings.php
index 68c17e1a33c..82cbfc04c83 100644
--- a/src/Util/StaticRectorStrings.php
+++ b/src/Util/StaticRectorStrings.php
@@ -40,6 +40,13 @@ final class StaticRectorStrings
return self::camelCaseToGlue($input, '_');
}
+ public static function underscoreToPascalCase(string $string): string
+ {
+ $string = self::underscoreToCamelCase($string);
+
+ return lcfirst($string);
+ }
+
public static function underscoreToCamelCase(string $input): string
{
$nameParts = explode('_', $input);