Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ad5ba53
phpstan fixes
TomasVotruba Jul 16, 2017
e59acf0
[Reconstructor] NamedServicesToConstructor init
TomasVotruba Jul 16, 2017
95d1055
[Reconstructor] NamedServicesToConstructor next
TomasVotruba Jul 16, 2017
31e3549
[Builder] add PropertyBuilder
TomasVotruba Jul 16, 2017
30c1624
[Builder] PropertyBuilder fixes
TomasVotruba Jul 16, 2017
aea9c41
[Reconstructor] details
TomasVotruba Jul 16, 2017
05ae2c0
[Reconstructor] add expr check
TomasVotruba Jul 16, 2017
dbaec74
fix phsptan
TomasVotruba Jul 16, 2017
723d363
ecs init
TomasVotruba Jul 16, 2017
34bc21f
decouple refactoring method for both cases
TomasVotruba Jul 16, 2017
7c2a01a
[Analyzer] decouple ClassAnalyzer
TomasVotruba Jul 16, 2017
885a4e4
simplify
TomasVotruba Jul 16, 2017
4fe18ba
NamedServicesReconstructor - add test for double use of one service
TomasVotruba Jul 16, 2017
595d0f0
upgrade to nikic/php-parser 4.0-dev
TomasVotruba Jul 16, 2017
e32453e
use format preserving AST Transformation, disable PHPStan, doesn't wo…
TomasVotruba Jul 16, 2017
3a6eee5
[NodeTraverser] use it instead of Dispatcher and own solution
TomasVotruba Jul 18, 2017
ebe7698
cleanup
TomasVotruba Jul 18, 2017
8f87dd5
cleanup
TomasVotruba Jul 18, 2017
3e10bdf
cleanup
TomasVotruba Jul 19, 2017
222557c
[NamedServicesToContructor] split NodeVisitors to do particular job
TomasVotruba Jul 19, 2017
94daf88
decouple ServiceFromKernelResolver
TomasVotruba Jul 19, 2017
deaaa01
remove unused helper method
TomasVotruba Jul 19, 2017
82e8858
namespace typos fix
TomasVotruba Jul 20, 2017
01a5fd8
make test pass
TomasVotruba Jul 20, 2017
80314eb
decouple ClassPropertyCollector, [NamedServicesToContstructor] change…
TomasVotruba Jul 20, 2017
09c13a1
[NamedServicesToContrutor] make tests pass
TomasVotruba Jul 20, 2017
5120451
cleanup
TomasVotruba Jul 20, 2017
5dfa359
cleanup
TomasVotruba Jul 20, 2017
9ab6c84
add StateHolder as hotfix for printer bug
TomasVotruba Jul 20, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ This tool will *reconstruct* (change) your code - **run it only in a new clean g

## All Reconstructors

- `InjectAnnotationToConstructorReconstructor`
- `InjectAnnotationToConstructorNodeTraverser` ([Nette](https://github.com/nette/))
- `NamedServicesToConstructorNodeTraverser` ([Symfony](https://github.com/symfony/))


## Install
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
"php": "^7.1",
"symfony/console": "^3.3",
"symfony/dependency-injection": "^3.3",
"nikic/php-parser": "^3.0",
"ocramius/code-generator-utils": "^0.4.1"
"nikic/php-parser": "4.0.x-dev as 3.0.2",
"ocramius/code-generator-utils": "^0.4",
"nette/utils": "^2.4"
},
"require-dev": {
"phpunit/phpunit": "^6.2",
"tracy/tracy": "^2.4",
"symplify/easy-coding-standard": "^2.1",
"symplify/easy-coding-standard": "@dev",
"phpstan/phpstan": "^0.7"
},
"autoload": {
Expand All @@ -33,6 +34,6 @@
"all": ["phpunit", "@cs", "@ps"],
"cs": "ecs check src tests",
"fs": "ecs check src tests --fix",
"ps": "phpstan analyse src tests --level 7 -c phpstan.neon"
"ps": "phpstan analyse src tests --level 7 --configuration phpstan.neon"
}
}
3 changes: 3 additions & 0 deletions easy-coding-standard.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
includes:
# todo:
# - vendor/symplify/easy-coding-standard/config/
5 changes: 2 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
parameters:
ignoreErrors:
- '#should return PhpParser\\Node\[\] but returns PhpParser\\Node\[\]\|null#'
# annotated => bug
- '#Access to an undefined property PhpParser\\Node\\Expr::\$value#'
- '#Internal error#'
# - '#should return PhpParser\\Node\[\] but returns PhpParser\\Node\[\]\|null#'
35 changes: 21 additions & 14 deletions src/Application/FileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

namespace Rector\Application;

use PhpParser\Lexer;
use PhpParser\NodeTraverser;
use PhpParser\Parser;
use Rector\Dispatcher\NodeDispatcher;
use Rector\Printer\CodeStyledPrinter;
use SplFileInfo;

Expand All @@ -15,20 +16,26 @@ final class FileProcessor
private $parser;

/**
* @var NodeDispatcher
* @var CodeStyledPrinter
*/
private $nodeDispatcher;
private $codeStyledPrinter;

/**
* @var CodeStyledPrinter
* @var NodeTraverser
*/
private $codeStyledPrinter;
private $nodeTraverser;

public function __construct(Parser $parser, CodeStyledPrinter $codeStyledPrinter, NodeDispatcher $nodeDispatcher)
/**
* @var Lexer
*/
private $lexer;

public function __construct(Parser $parser, CodeStyledPrinter $codeStyledPrinter, Lexer $lexer, NodeTraverser $nodeTraverser)
{
$this->parser = $parser;
$this->nodeDispatcher = $nodeDispatcher;
$this->codeStyledPrinter = $codeStyledPrinter;
$this->nodeTraverser = $nodeTraverser;
$this->lexer = $lexer;
}

/**
Expand All @@ -44,18 +51,18 @@ public function processFiles(array $files): void
public function processFile(SplFileInfo $file): void
{
$fileContent = file_get_contents($file->getRealPath());
$nodes = $this->parser->parse($fileContent);
if ($nodes === null) {
$oldStmts = $this->parser->parse($fileContent);
if ($oldStmts === null) {
return;
}

$originalNodes = $this->cloneArrayOfObjects($nodes);
$oldStmts = $this->cloneArrayOfObjects($oldStmts);

foreach ($nodes as $node) {
$this->nodeDispatcher->dispatch($node);
}
$oldTokens = $this->lexer->getTokens();

$newStmts = $this->nodeTraverser->traverse($oldStmts);

$this->codeStyledPrinter->printToFile($file, $originalNodes, $nodes);
$this->codeStyledPrinter->printToFile($file, $newStmts, $oldStmts, $oldTokens);
}

/**
Expand Down
26 changes: 26 additions & 0 deletions src/Builder/Class_/ClassPropertyCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php declare(strict_types=1);

namespace Rector\Builder\Class_;

final class ClassPropertyCollector
{
/**
* @var string[][]
*/
private $classProperties = [];

public function addPropertyForClass(string $class, string $propertyType, string $propertyName): void
{
$this->classProperties[$class] = [
$propertyType => $propertyName
];
}

/**
* @return string[]
*/
public function getPropertiesforClass(string $class): array
{
return $this->classProperties[$class] ?? [];
}
}
22 changes: 20 additions & 2 deletions src/Builder/ConstructorMethodBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Rector\Builder;

use Nette\Utils\Arrays;
use PhpParser\Builder\Method;
use PhpParser\Builder\Param;
use PhpParser\BuilderFactory;
Expand Down Expand Up @@ -49,7 +50,7 @@ public function addPropertyAssignToClass(Class_ $classNode, string $propertyType
->addParam($this->createParameter($propertyType, $propertyName))
->addStmts($assign);

$classNode->stmts[] = $constructorMethod->getNode();
$this->addAsFirstMethod($classNode, $constructorMethod->getNode());
}

private function createParameter(string $propertyType, string $propertyName): Param
Expand All @@ -69,4 +70,21 @@ private function createPropertyAssignment(string $propertyName): array
$propertyName
));
}
}

private function addAsFirstMethod(Class_ $classNode, ClassMethod $constructorMethod): void
{
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof ClassMethod) {
Arrays::insertBefore(
$classNode->stmts,
$key,
['before_' . $key => $constructorMethod]
);

return;
}
}

$classNode->stmts[] = $constructorMethod;
}
}
29 changes: 29 additions & 0 deletions src/Builder/Kernel/ServiceFromKernelResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types=1);

namespace Rector\Builder\Kernel;

use Symfony\Component\HttpKernel\Kernel;

final class ServiceFromKernelResolver
{
public function resolveServiceClassByNameFromKernel(string $serviceName, string $kernelClass): ?string
{
/** @var Kernel $kernel */
$kernel = new $kernelClass('dev', true);
$kernel->boot();

// @todo: cache
// @todo: initialize without creating cache or log directory
// @todo: call only loadBundles() and initializeContainer() methods

$container = $kernel->getContainer();
if (! $container->has($serviceName)) {
// service name could not be found
return null;
}

$service = $container->get($serviceName);

return get_class($service);
}
}
14 changes: 14 additions & 0 deletions src/Builder/Naming/NameResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);

namespace Rector\Builder\Naming;

final class NameResolver
{
public function resolvePropertyNameFromType(string $serviceType): string
{
$serviceNameParts = explode('\\', $serviceType);
$lastNamePart = array_pop($serviceNameParts);

return lcfirst($lastNamePart);
}
}
77 changes: 77 additions & 0 deletions src/Builder/PropertyBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php declare(strict_types=1);

namespace Rector\Builder;

use Nette\Utils\Arrays;
use PhpParser\BuilderFactory;
use PhpParser\Comment\Doc;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;

final class PropertyBuilder
{
/**
* @var BuilderFactory
*/
private $builderFactory;

public function __construct(BuilderFactory $builderFactory)
{
$this->builderFactory = $builderFactory;
}

public function addPropertyToClass(Class_ $classNode, string $propertyType, string $propertyName): void
{
$propertyNode = $this->buildPrivatePropertyNode($propertyType, $propertyName);

// add before first method
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof ClassMethod) {
Arrays::insertBefore(
$classNode->stmts,
$key,
['before_' . $key => $propertyNode]
);

return;
}
}

// or after last property
$previousElement = null;
foreach ($classNode->stmts as $key => $classElementNode) {
if ($previousElement instanceof Property && ! $classElementNode instanceof Property) {
Arrays::insertBefore(
$classNode->stmts,
$key,
['before_' . $key => $propertyNode]
);

return;
}

$previousElement = $classElementNode;
}

$classNode->stmts[] = $propertyNode;
}

private function buildPrivatePropertyNode(string $propertyType, string $propertyName): Property
{
$docComment = $this->createDocWithVarAnnotation($propertyType);

$propertyBuilder = $this->builderFactory->property($propertyName)
->makePrivate()
->setDocComment($docComment);

return $propertyBuilder->getNode();
}

private function createDocWithVarAnnotation(string $propertyType): Doc
{
return new Doc('/**'
. PHP_EOL . ' * @var ' . $propertyType
. PHP_EOL . ' */');
}
}
2 changes: 0 additions & 2 deletions src/Console/Command/ReconstructCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ protected function configure(): void
{
$this->setName(self::NAME);
$this->setDescription('Reconstruct set of your code.');

// @todo: use modular configure from ApiGen
$this->addArgument(
self::ARGUMENT_SOURCE_NAME,
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
Expand Down
12 changes: 0 additions & 12 deletions src/Contract/Dispatcher/ReconstructorInterface.php

This file was deleted.

14 changes: 7 additions & 7 deletions src/DependencyInjection/CompilerPass/CollectorCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace Rector\DependencyInjection\CompilerPass;

use Rector\Contract\Dispatcher\ReconstructorInterface;
use Rector\Dispatcher\NodeDispatcher;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
Expand All @@ -15,7 +15,7 @@ final class CollectorCompilerPass implements CompilerPassInterface
public function process(ContainerBuilder $containerBuilder): void
{
$this->collectCommandsToConsoleApplication($containerBuilder);
$this->collectReconstructorsToNodeDispatcher($containerBuilder);
$this->collectNodeVisitorsToTraverser($containerBuilder);
}

private function collectCommandsToConsoleApplication(ContainerBuilder $containerBuilder): void
Expand All @@ -28,13 +28,13 @@ private function collectCommandsToConsoleApplication(ContainerBuilder $container
);
}

private function collectReconstructorsToNodeDispatcher(ContainerBuilder $containerBuilder): void
private function collectNodeVisitorsToTraverser(ContainerBuilder $containerBuilder): void
{
DefinitionCollector::loadCollectorWithType(
$containerBuilder,
NodeDispatcher::class,
ReconstructorInterface::class,
'addReconstructor'
NodeTraverser::class,
NodeVisitor::class,
'addVisitor'
);
}
}
29 changes: 0 additions & 29 deletions src/Dispatcher/NodeDispatcher.php

This file was deleted.

Loading