add RectorStrings

This commit is contained in:
Tomas Votruba 2019-02-02 16:14:13 +01:00
parent e103a991fe
commit a9338ab9c8
6 changed files with 123 additions and 5 deletions

View File

@ -2,6 +2,7 @@
namespace Rector\NetteToSymfony\Rector;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
@ -199,6 +200,9 @@ CODE_SAMPLE
$this->docBlockAnalyzer->addTag($classMethod, $phpDocTagNode);
}
// complete all other non-explicit methods, from "<presenter>/<action>"
$this->completeImplicitRoutes();
// remove routes
$this->removeNodes($assignNodes);
@ -265,6 +269,42 @@ CODE_SAMPLE
return $this->classMaintainer->getMethodByName($classNode, $routeInfo->getMethod());
}
private function completeImplicitRoutes(): void
{
$presenterClassNodes = $this->classLikeNodeCollector->findClassesBySuffix('Presenter');
foreach ($presenterClassNodes as $presenterClassNode) {
foreach ((array) $presenterClassNode->stmts as $classStmt) {
if (! $classStmt instanceof ClassMethod) {
continue;
}
// not an action method
if (! $classStmt->isPublic()) {
continue;
}
if (! $this->matchName($classStmt, '#^(render|action)#')) {
continue;
}
// already has Route tag
if ($this->docBlockAnalyzer->hasTag($classStmt, $this->routerClass)) {
continue;
}
$presenterName = $this->getName($presenterClassNode);
$shortPresenterName = Strings::after($presenterName, '\\', -1);
die;
dump($this->getName($classStmt));
die;
}
}
die;
}
private function isRouteStaticCallMatch(StaticCall $node): bool
{
$className = $this->getName($node->class);

View File

@ -12,11 +12,11 @@ final class RouterListToControllerAnnotationsRetorTest extends AbstractRectorTes
public function test(): void
{
$this->doTestFiles([
__DIR__ . '/Fixture/new_route_to_annotation.php.inc',
__DIR__ . '/Fixture/static_route_to_annotation.php.inc',
__DIR__ . '/Fixture/constant_reference_route_to_annotation.php.inc',
__DIR__ . '/Fixture/method_named_routes.php.inc',
// __DIR__ . '/Fixture/general_method_named_routes.php.inc',
// __DIR__ . '/Fixture/new_route_to_annotation.php.inc',
// __DIR__ . '/Fixture/static_route_to_annotation.php.inc',
// __DIR__ . '/Fixture/constant_reference_route_to_annotation.php.inc',
// __DIR__ . '/Fixture/method_named_routes.php.inc',
__DIR__ . '/Fixture/general_method_named_routes.php.inc',
]);
}

View File

@ -182,4 +182,22 @@ final class ClassLikeNodeCollector
return null;
}
/**
* @return Class_[]
*/
public function findClassesBySuffix(string $suffix): array
{
$classNodes = [];
foreach ($this->classes as $className => $classNode) {
if (! Strings::endsWith($className, $suffix)) {
continue;
}
$classNodes[] = $classNode;
}
return $classNodes;
}
}

View File

@ -2,6 +2,7 @@
namespace Rector\Rector;
use Nette\Utils\Strings;
use PhpParser\Node;
use Rector\PhpParser\Node\Resolver\NameResolver;
@ -34,6 +35,11 @@ trait NameResolverTrait
return $this->getName($firstNode) === $this->getName($secondNode);
}
public function matchName(Node $node, string $pattern): bool
{
return (bool) Strings::match($this->getName($node), $pattern);
}
public function isNameInsensitive(Node $node, string $name): bool
{
return $this->nameResolver->isNameInsensitive($node, $name);

View File

@ -2,6 +2,7 @@
namespace Rector\Util;
use Nette\Utils\Strings;
use Symfony\Component\Console\Input\StringInput;
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
@ -16,4 +17,26 @@ final class RectorStrings
return $privatesCaller->callPrivateMethod(new StringInput(''), 'tokenize', $command);
}
public static function camelCaseToDashes(string $input): string
{
return self::camelCaseToGlue($input, '-');
}
public static function camelCaseToUnderscore(string $input): string
{
return self::camelCaseToGlue($input, '_');
}
private static function camelCaseToGlue(string $input, string $glue): string
{
$matches = Strings::matchAll($input, '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!');
$parts = [];
foreach ($matches as $match) {
$parts[] = $match[0] === strtoupper($match[0]) ? strtolower($match[0]) : lcfirst($match[0]);
}
return implode($glue, $parts);
}
}

View File

@ -0,0 +1,31 @@
<?php declare(strict_types=1);
namespace Rector\Tests\Util;
use Iterator;
use PHPUnit\Framework\TestCase;
use Rector\Util\RectorStrings;
final class RectorStringsTest extends TestCase
{
/**
* @dataProvider provideDataForCamelCaseToUnderscore()
*/
public function testCamelCaseToUnderscore(string $content, string $expected): void
{
$this->assertSame($expected, RectorStrings::camelCaseToUnderscore($content));
}
public function provideDataForCamelCaseToUnderscore(): Iterator
{
yield ['simpleTest', 'simple_test'];
yield ['easy', 'easy'];
yield ['HTML', 'html'];
yield ['simpleXML', 'simple_xml'];
yield ['PDFLoad', 'pdf_load'];
yield ['startMIDDLELast', 'start_middle_last'];
yield ['AString', 'a_string'];
yield ['Some4Numbers234', 'some4_numbers234'];
yield ['TEST123String', 'test123_string'];
}
}