diff --git a/src/Code/AbstractMemberGenerator.php b/src/Code/AbstractMemberGenerator.php index b9561d6..01a9bf8 100644 --- a/src/Code/AbstractMemberGenerator.php +++ b/src/Code/AbstractMemberGenerator.php @@ -20,7 +20,7 @@ * @copyright Copyright (c) 2005-2019 Zend Technologies USA Inc. (http://www.zend.com) * @license https://github.com/zendframework/zend-code/blob/master/LICENSE.md New BSD License */ -abstract class AbstractMemberGenerator implements StatementGenerator +abstract class AbstractMemberGenerator implements \OpenCodeModeling\CodeAst\StatementGenerator { /**#@+ * @const int Flags for construction usage diff --git a/src/Code/BodyGenerator.php b/src/Code/BodyGenerator.php index c0a377d..c813f6b 100644 --- a/src/Code/BodyGenerator.php +++ b/src/Code/BodyGenerator.php @@ -12,7 +12,7 @@ use PhpParser\Parser; -final class BodyGenerator implements StatementGenerator +final class BodyGenerator implements \OpenCodeModeling\CodeAst\StatementGenerator { /** * @var Parser diff --git a/src/Code/ClassGenerator.php b/src/Code/ClassGenerator.php index a118876..8666776 100644 --- a/src/Code/ClassGenerator.php +++ b/src/Code/ClassGenerator.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2005-2019 Zend Technologies USA Inc. (http://www.zend.com) * @license https://github.com/zendframework/zend-code/blob/master/LICENSE.md New BSD License */ -final class ClassGenerator implements StatementGenerator +final class ClassGenerator implements \OpenCodeModeling\CodeAst\StatementGenerator { public const FLAG_ABSTRACT = Class_::MODIFIER_ABSTRACT; public const FLAG_FINAL = Class_::MODIFIER_FINAL; diff --git a/src/Code/IdentifierGenerator.php b/src/Code/IdentifierGenerator.php index 4e440ed..6f589c6 100644 --- a/src/Code/IdentifierGenerator.php +++ b/src/Code/IdentifierGenerator.php @@ -10,12 +10,13 @@ namespace OpenCodeModeling\CodeAst\Code; +use OpenCodeModeling\CodeAst\IdentifiedStatementGenerator; use PhpParser\Node\Stmt; -final class IdentifierGenerator implements StatementGenerator +final class IdentifierGenerator implements IdentifiedStatementGenerator { /** - * @var StatementGenerator + * @var \OpenCodeModeling\CodeAst\StatementGenerator */ private $statementGenerator; @@ -24,7 +25,7 @@ final class IdentifierGenerator implements StatementGenerator */ private $identifier; - public function __construct(string $identifier, StatementGenerator $statementGenerator) + public function __construct(string $identifier, \OpenCodeModeling\CodeAst\StatementGenerator $statementGenerator) { $this->identifier = $identifier; $this->statementGenerator = $statementGenerator; @@ -35,6 +36,11 @@ public function getIdentifier(): string return $this->identifier; } + public function identifier(): string + { + return $this->identifier; + } + public function generate(): array { $stmt = $this->statementGenerator->generate(); diff --git a/src/Code/StatementGenerator.php b/src/Code/StatementGenerator.php index 8cb4557..1be6063 100644 --- a/src/Code/StatementGenerator.php +++ b/src/Code/StatementGenerator.php @@ -12,6 +12,9 @@ use PhpParser\Node; +/** + * @deprecated Use \OpenCodeModeling\CodeAst\StatementGenerator + */ interface StatementGenerator { /** diff --git a/src/IdentifiedStatementGenerator.php b/src/IdentifiedStatementGenerator.php new file mode 100644 index 0000000..a02cf06 --- /dev/null +++ b/src/IdentifiedStatementGenerator.php @@ -0,0 +1,16 @@ + + **/ + private $stmts; + + /** + * @param string $identifier + * @param Node\Stmt ...$stmts + */ + public function __construct(string $identifier, Node\Stmt ...$stmts) + { + $this->identifier = $identifier; + $this->stmts = $stmts; + } + + /** + * @return string + */ + public function identifier(): string + { + return $this->identifier; + } + + public function generate() + { + return $this->stmts; + } +} diff --git a/src/NodeVisitor/ClassConstant.php b/src/NodeVisitor/ClassConstant.php index 8ddcdbf..6e1d50e 100644 --- a/src/NodeVisitor/ClassConstant.php +++ b/src/NodeVisitor/ClassConstant.php @@ -12,6 +12,8 @@ use OpenCodeModeling\CodeAst\Code\ClassConstGenerator; use OpenCodeModeling\CodeAst\Code\IdentifierGenerator; +use OpenCodeModeling\CodeAst\IdentifiedStatementGenerator; +use OpenCodeModeling\CodeAst\Node\StatementGenerator; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Namespace_; @@ -20,15 +22,25 @@ final class ClassConstant extends NodeVisitorAbstract { /** - * @var IdentifierGenerator + * @var IdentifiedStatementGenerator */ private $lineGenerator; - public function __construct(IdentifierGenerator $lineGenerator) + public function __construct(IdentifiedStatementGenerator $lineGenerator) { $this->lineGenerator = $lineGenerator; } + public static function fromNode(Node\Stmt\ClassConst $node): self + { + return new self( + new StatementGenerator( + $node->consts[0]->name->name, + $node + ) + ); + } + public static function forClassConstant( string $constantName, $constantValue, @@ -79,7 +91,7 @@ private function checkConstantExists(Class_ $node): bool { foreach ($node->stmts as $stmt) { if ($stmt instanceof Node\Stmt\ClassConst - && $stmt->consts[0]->name->name === $this->lineGenerator->getIdentifier() + && $stmt->consts[0]->name->name === $this->lineGenerator->identifier() ) { return true; } diff --git a/src/NodeVisitor/ClassFile.php b/src/NodeVisitor/ClassFile.php index 346f5c1..eb466d5 100644 --- a/src/NodeVisitor/ClassFile.php +++ b/src/NodeVisitor/ClassFile.php @@ -32,6 +32,11 @@ public function __construct(ClassGenerator $classGenerator) $this->classGenerator = $classGenerator; } + public static function fromNode(Class_ $node): self + { + return new self(new ClassGenerator($node->name->name)); + } + public function beforeTraverse(array $nodes) { foreach ($nodes as $node) { diff --git a/src/NodeVisitor/ClassNamespace.php b/src/NodeVisitor/ClassNamespace.php index be2cfa7..27033e2 100644 --- a/src/NodeVisitor/ClassNamespace.php +++ b/src/NodeVisitor/ClassNamespace.php @@ -32,6 +32,11 @@ public function __construct(string $namespace) $this->builderFactory = new BuilderFactory(); } + public static function fromNode(Stmt\Namespace_ $node): self + { + return new self($node->name->toString()); + } + public function afterTraverse(array $nodes): ?array { if ($this->hasNamespace($nodes)) { diff --git a/src/NodeVisitor/Collector.php b/src/NodeVisitor/Collector.php new file mode 100644 index 0000000..7ae39d0 --- /dev/null +++ b/src/NodeVisitor/Collector.php @@ -0,0 +1,68 @@ +visitors = []; + + foreach ($nodes as $node) { + $this->determineVisitor($node); + } + + return null; + } + + private function determineVisitor(Node $node): void + { + switch (true) { + case $node instanceof Namespace_: + $this->visitors[] = ClassNamespace::fromNode($node); + break; + case $node instanceof Node\Stmt\Class_: + $this->visitors[] = ClassFile::fromNode($node); + + foreach ($node->stmts as $stmt) { + $this->determineVisitor($stmt); + } + break; + case $node instanceof Node\Stmt\ClassConst: + $this->visitors[] = ClassConstant::fromNode($node); + break; + default: + break; + } + } + + public function visitors(): array + { + return $this->visitors; + } + + public function injectVisitors(NodeTraverser $nodeTraverser): void + { + foreach ($this->visitors as $visitor) { + $nodeTraverser->addVisitor(clone $visitor); + } + } +} diff --git a/src/StatementGenerator.php b/src/StatementGenerator.php new file mode 100644 index 0000000..ce5ead5 --- /dev/null +++ b/src/StatementGenerator.php @@ -0,0 +1,21 @@ +parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7); + $this->printer = new Standard(['shortArraySyntax' => true]); + } + + /** + * @test + */ + public function it_detects_visitors_for_class_and_constant(): void + { + $expectedCode = <<<'EOF' +parser->parse($expectedCode); + + $visitorCollector = new Collector(); + + $nodeTraverser = new NodeTraverser(); + $nodeTraverser->addVisitor($visitorCollector); + + $nodeTraverser->traverse($ast); + + $detectedVisitors = $visitorCollector->visitors(); + + $this->assertCount(2, $detectedVisitors); + + $this->assertCode($expectedCode, $visitorCollector, $ast); + $this->assertCode($expectedCode, $visitorCollector, $this->parser->parse('')); + } + + private function assertCode(string $expectedCode, Collector $visitorCollector, array $ast): void + { + $nodeTraverser = new NodeTraverser(); + + $visitorCollector->injectVisitors($nodeTraverser); + + $this->assertSame($expectedCode, $this->printer->prettyPrintFile($nodeTraverser->traverse($ast))); + } +}