Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 28 additions & 1 deletion packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfoFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
use Rector\Configuration\CurrentNodeProvider;
use Rector\DoctrinePhpDocParser\PhpDocParser\OrmTagParser;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\StaticTypeMapper;

final class PhpDocInfoFactory
Expand All @@ -35,6 +36,11 @@ final class PhpDocInfoFactory
*/
private $staticTypeMapper;

/**
* @var PhpDocInfo[]
*/
private $phpDocInfoByObjectHash = [];

public function __construct(
PhpDocParser $phpDocParser,
Lexer $lexer,
Expand All @@ -49,6 +55,12 @@ public function __construct(

public function createFromNode(Node $node): PhpDocInfo
{
$hash = $this->createUniqueDocNodeHash($node);

if (isset($this->phpDocInfoByObjectHash[$hash])) {
return $this->phpDocInfoByObjectHash[$hash];
}

/** needed for @see OrmTagParser */
$this->currentNodeProvider->setNode($node);

Expand All @@ -60,7 +72,10 @@ public function createFromNode(Node $node): PhpDocInfo

$phpDocNode = $this->setPositionOfLastToken($phpDocNode);

return new PhpDocInfo($phpDocNode, $tokens, $content, $this->staticTypeMapper, $node);
$phpDocInfo = new PhpDocInfo($phpDocNode, $tokens, $content, $this->staticTypeMapper, $node);
$this->phpDocInfoByObjectHash[$hash] = $phpDocInfo;

return $phpDocInfo;
}

/**
Expand All @@ -84,4 +99,16 @@ private function setPositionOfLastToken(

return $attributeAwarePhpDocNode;
}

private function createUniqueDocNodeHash(Node $node): string
{
$objectHash = spl_object_hash($node);

if ($node->getDocComment() === null) {
throw new ShouldNotHappenException(sprintf('"%s" is missing a DocComment node', get_class($node)));
}
$docCommentHash = spl_object_hash($node->getDocComment());

return $objectHash . $docCommentHash;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php declare(strict_types=1);

namespace Rector\BetterPhpDocParser\Tests\PhpDocInfo\PhpDocInfoPrinter;

use Iterator;
use Nette\Utils\FileSystem;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\BetterPhpDocParser\Tests\PhpDocInfo\PhpDocInfoPrinter\Source\Doctrine\IndexInTable;

final class DoctrineTest extends AbstractPhpDocInfoPrinterTest
{
/**
* @dataProvider provideDataForTestClass()
*/
public function testClass(string $docFilePath, Node $node, string $expectedDocFilePath): void
{
$docComment = FileSystem::read($docFilePath);
$phpDocInfo = $this->createPhpDocInfoFromDocCommentAndNode($docComment, $node);

$expectedDoc = FileSystem::read($expectedDocFilePath);

$this->assertSame(
$expectedDoc,
$this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo),
'Caused in ' . $docFilePath
);
}

/**
* @return string[]|Class_[]
*/
public function provideDataForTestClass(): Iterator
{
yield [
__DIR__ . '/Source/Doctrine/index_in_table.txt',
new Class_(IndexInTable::class),
__DIR__ . '/Source/Doctrine/expected_index_in_table.txt',
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare(strict_types=1);

namespace Rector\BetterPhpDocParser\Tests\PhpDocInfo\PhpDocInfoPrinter\Source\Doctrine;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Table(
* name="building",
* indexes={
* @ORM\Index(name="isDemoBuilding", columns={"is_demo_building"})
* }
* )
*/
final class IndexInTable
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @ORM\Table(name="building",
* indexes={@ORM\Index(name="isDemoBuilding",
* columns={"is_demo_building"})}
* )
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @ORM\Table(
* name="building",
* indexes={
* @ORM\Index(name="isDemoBuilding", columns={"is_demo_building"})
* }
* )
*/
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpParser\Node\Resolver\NameResolver;
use ReflectionClass;
Expand Down Expand Up @@ -84,7 +85,7 @@ private function createPropertyReflectionFromPropertyNode(Property $property): R
/** @var string $className */
$className = $property->getAttribute(AttributeKey::CLASS_NAME);

if ($className === null || ! class_exists($className)) {
if ($className === null || ! ClassExistenceStaticHelper::doesClassLikeExist($className)) {
throw new ShouldNotHappenException(sprintf(
'Class "%s" for property "%s" was not found.',
(string) $className,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
<?php declare(strict_types=1);

namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_;
namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_;

use Rector\DoctrinePhpDocParser\Array_\ArrayItemStaticHelper;
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\AbstractDoctrineTagValueNode;

final class UniqueConstraintTagValueNode extends AbstractDoctrineTagValueNode
abstract class AbstractIndexTagValueNode extends AbstractDoctrineTagValueNode
{
/**
* @var string
*/
public const SHORT_NAME = '@ORM\UniqueConstraint';

/**
* @var string
*/
Expand All @@ -25,12 +20,12 @@ final class UniqueConstraintTagValueNode extends AbstractDoctrineTagValueNode
/**
* @var mixed[]|null
*/
private $options;
private $columns;

/**
* @var mixed[]|null
*/
private $columns;
private $options;

/**
* @param mixed[]|null $columns
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php declare(strict_types=1);

namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_;

final class IndexTagValueNode extends AbstractIndexTagValueNode
{
/**
* @var string
*/
public const SHORT_NAME = '@ORM\Index';
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Rector\DoctrinePhpDocParser\Array_\ArrayItemStaticHelper;
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\AbstractDoctrineTagValueNode;
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\UniqueConstraintTagValueNode;

final class TableTagValueNode extends AbstractDoctrineTagValueNode
{
Expand All @@ -24,9 +23,9 @@ final class TableTagValueNode extends AbstractDoctrineTagValueNode
private $schema;

/**
* @var mixed[]|null
* @var IndexTagValueNode[]
*/
private $indexes;
private $indexes = [];

/**
* @var UniqueConstraintTagValueNode[]
Expand All @@ -40,12 +39,13 @@ final class TableTagValueNode extends AbstractDoctrineTagValueNode

/**
* @param mixed[] $options
* @param IndexTagValueNode[] $indexes
* @param UniqueConstraintTagValueNode[] $uniqueConstraints
*/
public function __construct(
?string $name,
?string $schema,
?array $indexes,
array $indexes,
array $uniqueConstraints,
array $options,
?string $originalContent = null
Expand Down Expand Up @@ -73,8 +73,12 @@ public function __toString(): string
$contentItems['schema'] = sprintf('schema="%s"', $this->schema);
}

if ($this->indexes) {
$contentItems['indexes'] = $this->printArrayItem($this->indexes, 'indexes');
if ($this->indexes !== []) {
$indexesAsString = $this->printTagValueNodesSeparatedByComma(
$this->indexes,
IndexTagValueNode::SHORT_NAME
);
$contentItems['indexes'] = sprintf('indexes={%s}', $indexesAsString);
}

if ($this->uniqueConstraints !== []) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php declare(strict_types=1);

namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_;

final class UniqueConstraintTagValueNode extends AbstractIndexTagValueNode
{
/**
* @var string
*/
public const SHORT_NAME = '@ORM\UniqueConstraint';
}
62 changes: 8 additions & 54 deletions packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\OneToOne;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\UniqueConstraint;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
Expand All @@ -31,7 +29,6 @@
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\ManyToOneTagValueNode;
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\OneToManyTagValueNode;
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\OneToOneTagValueNode;
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\UniqueConstraintTagValueNode;
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpParser\Node\Resolver\NameResolver;
Expand All @@ -47,21 +44,22 @@ final class OrmTagParser extends AbstractPhpDocParser
/**
* @var string
*/
public const JOIN_COLUMN_PATTERN = '#@ORM\\\\JoinColumn\((?<singleJoinColumn>.*?)\),?#s';
private const JOIN_COLUMN_PATTERN = '#@ORM\\\\JoinColumn\((?<singleJoinColumn>.*?)\),?#s';

/**
* @var string
* @var NameResolver
*/
public const UNIQUE_CONSTRAINT_PATTERN = '#@ORM\\\\UniqueConstraint\((?<singleUniqueConstraint>.*?)\),?#s';
private $nameResolver;

/**
* @var NameResolver
* @var TableTagValueNodeFactory
*/
private $nameResolver;
private $tableTagValueNodeFactory;

public function __construct(NameResolver $nameResolver)
public function __construct(NameResolver $nameResolver, TableTagValueNodeFactory $tableTagValueNodeFactory)
{
$this->nameResolver = $nameResolver;
$this->tableTagValueNodeFactory = $tableTagValueNodeFactory;
}

public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
Expand All @@ -82,7 +80,7 @@ public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValu
}

if ($tag === TableTagValueNode::SHORT_NAME) {
return $this->createTableTagValueNode($currentPhpNode, $annotationContent);
return $this->tableTagValueNodeFactory->create($currentPhpNode, $annotationContent);
}
}

Expand Down Expand Up @@ -164,34 +162,6 @@ private function createInheritanceTypeTagValueNode(Class_ $class): InheritanceTy
return new InheritanceTypeTagValueNode($inheritanceType->value);
}

private function createTableTagValueNode(Class_ $class, string $annotationContent): TableTagValueNode
{
/** @var Table $table */
$table = $this->nodeAnnotationReader->readClassAnnotation($class, Table::class);

$uniqueConstraintContents = Strings::matchAll($annotationContent, self::UNIQUE_CONSTRAINT_PATTERN);

$uniqueConstraintsTagValueNodes = [];
if ($table->uniqueConstraints !== null) {
foreach ($table->uniqueConstraints as $key => $uniqueConstraint) {
$currentUniqueConstraintContent = $uniqueConstraintContents[$key]['singleUniqueConstraint'];
$uniqueConstraintsTagValueNodes[] = $this->createUniqueConstantTagValueNodeFromUniqueConstaint(
$uniqueConstraint,
$currentUniqueConstraintContent
);
}
}

return new TableTagValueNode(
$table->name,
$table->schema,
$table->indexes,
$uniqueConstraintsTagValueNodes,
$table->options,
$annotationContent
);
}

private function createColumnTagValueNode(Property $property, string $annotationContent): ColumnTagValueNode
{
/** @var Column $column */
Expand Down Expand Up @@ -336,22 +306,6 @@ private function resolveFqnTargetEntity(string $targetEntity, Node $node): strin
return $targetEntity;
}

private function createUniqueConstantTagValueNodeFromUniqueConstaint(
UniqueConstraint $uniqueConstraint,
string $annotationContent
): UniqueConstraintTagValueNode {
// doctrine orm compatibility
$flags = property_exists($uniqueConstraint, 'flags') ? $uniqueConstraint->flags : [];

return new UniqueConstraintTagValueNode(
$uniqueConstraint->name,
$uniqueConstraint->columns,
$flags,
$uniqueConstraint->options,
$annotationContent
);
}

private function createJoinColumnTagValueNodeFromJoinColumnAnnotation(
JoinColumn $joinColumn,
string $annotationContent
Expand Down
Loading