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
2 changes: 2 additions & 0 deletions .phpstorm.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
\Rector\NodeTypeResolver\Node\AttributeKey::START_TOKEN_POSITION,
\Rector\NodeTypeResolver\Node\AttributeKey::ORIGINAL_NODE,
\Rector\NodeTypeResolver\Node\AttributeKey::IS_UNREACHABLE,
\Rector\NodeTypeResolver\Node\AttributeKey::PHP_DOC_INFO,
);

expectedArguments(
Expand All @@ -61,4 +62,5 @@
\Rector\NodeTypeResolver\Node\AttributeKey::START_TOKEN_POSITION,
\Rector\NodeTypeResolver\Node\AttributeKey::ORIGINAL_NODE,
\Rector\NodeTypeResolver\Node\AttributeKey::IS_UNREACHABLE,
\Rector\NodeTypeResolver\Node\AttributeKey::PHP_DOC_INFO,
);
1 change: 1 addition & 0 deletions ecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ parameters:

Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff:
- 'packages/MinimalScope/src/Rector/Class_/ChangeLocalPropertyToVariableRector.php'
- 'packages/CodingStyle/src/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.php'
# solve later
- 'src/Console/Command/ScreenFileCommand.php'
- 'packages/Doctrine/src/Rector/ClassMethod/AddMethodCallBasedParamTypeRector.php'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Rector\Autodiscovery\FileMover\FileMover;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
use Symplify\SmartFileSystem\SmartFileInfo;
Expand Down Expand Up @@ -102,7 +103,7 @@ private function areDoctrineEntityNodes(array $nodes): bool
return false;
}

$phpDocInfo = $this->getPhpDocInfo($class);
$phpDocInfo = $class->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Rector\BetterPhpDocParser\Attributes\Attribute;

use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;

final class Attribute
{
/**
Expand All @@ -12,9 +14,10 @@ final class Attribute
public const HAS_DESCRIPTION_WITH_ORIGINAL_SPACES = 'has_description_with_restored_spaces';

/**
* @experiment
* @var string
*/
public const PHP_DOC_NODE_INFO = 'php_doc_node_info';
public const START_END = StartEndValueObject::class;

/**
* @var string
Expand Down
14 changes: 14 additions & 0 deletions packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Nette\Utils\Strings;
use PhpParser\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
Expand All @@ -16,7 +17,9 @@
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
use Rector\BetterPhpDocParser\Annotation\AnnotationNaming;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\StaticTypeMapper;

Expand Down Expand Up @@ -78,6 +81,17 @@ public function getOriginalContent(): string
return $this->originalContent;
}

public function addPhpDocTagNode(PhpDocChildNode $phpDocChildNode): void
{
$this->phpDocNode->children[] = $phpDocChildNode;
}

public function addTagValueNodeWithShortName(AbstractTagValueNode $tagValueNode): void
{
$spacelessPhpDocTagNode = new SpacelessPhpDocTagNode($tagValueNode::SHORT_NAME, $tagValueNode);
$this->addPhpDocTagNode($spacelessPhpDocTagNode);
}

public function getPhpDocNode(): AttributeAwarePhpDocNode
{
return $this->phpDocNode;
Expand Down
63 changes: 21 additions & 42 deletions packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfoFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
namespace Rector\BetterPhpDocParser\PhpDocInfo;

use PhpParser\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface;
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
use Rector\Configuration\CurrentNodeProvider;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\StaticTypeMapper;

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

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

public function __construct(
PhpDocParser $phpDocParser,
Lexer $lexer,
Expand All @@ -57,41 +54,30 @@ 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 PhpDocNodeFactoryInterface */
$this->currentNodeProvider->setNode($node);

$content = $node->getDocComment()->getText();
$tokens = $this->lexer->tokenize($content);
if ($node->getDocComment() === null) {
$content = '';
$tokens = [];
$phpDocNode = new AttributeAwarePhpDocNode([]);
} else {
$content = $node->getDocComment()->getText();

$tokenIterator = new TokenIterator($tokens);
$tokens = $this->lexer->tokenize($content);
$tokenIterator = new TokenIterator($tokens);

/** @var AttributeAwarePhpDocNode $phpDocNode */
$phpDocNode = $this->phpDocParser->parse($tokenIterator);
$phpDocNode = $this->setPositionOfLastToken($phpDocNode);
/** @var AttributeAwarePhpDocNode $phpDocNode */
$phpDocNode = $this->phpDocParser->parse($tokenIterator);
$phpDocNode = $this->setPositionOfLastToken($phpDocNode);
}

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

return $phpDocInfo;
}

private function createUniqueDocNodeHash(Node $node): string
{
$this->ensureNodeHasDocComment($node);

$objectHash = spl_object_hash($node);
$docCommentHash = spl_object_hash($node->getDocComment());
$docCommentContentHash = sha1($node->getDocComment()->getText());

return $objectHash . $docCommentHash . $docCommentContentHash;
}

/**
* Needed for printing
*/
Expand All @@ -106,20 +92,13 @@ private function setPositionOfLastToken(
/** @var AttributeAwareNodeInterface $lastChildNode */
$lastChildNode = array_pop($phpDocChildNodes);

$phpDocNodeInfo = $lastChildNode->getAttribute(Attribute::PHP_DOC_NODE_INFO);
if ($phpDocNodeInfo !== null) {
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $phpDocNodeInfo->getEnd());
}
/** @var StartEndValueObject $startEndValueObject */
$startEndValueObject = $lastChildNode->getAttribute(Attribute::START_END);

return $attributeAwarePhpDocNode;
}

private function ensureNodeHasDocComment(Node $node): void
{
if ($node->getDocComment() !== null) {
return;
if ($startEndValueObject !== null) {
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $startEndValueObject->getEnd());
}

throw new ShouldNotHappenException(sprintf('"%s" is missing a DocComment node', get_class($node)));
return $attributeAwarePhpDocNode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
*/
protected $hasNewlineAfterOpening = false;

/**
* @var string|null
*/
protected $originalContent;

/**
* @param mixed[] $item
*/
Expand Down Expand Up @@ -60,6 +65,10 @@ protected function printContentItems(array $contentItems): string
}

if ($contentItems === []) {
if ($this->originalContent !== null && Strings::endsWith($this->originalContent, '()')) {
return '()';
}

return '';
}

Expand Down Expand Up @@ -131,6 +140,7 @@ protected function resolveOriginalContentSpacingAndOrder(?string $originalConten
return;
}

$this->originalContent = $originalContent;
$this->orderedVisibleItems = ArrayItemStaticHelper::resolveAnnotationItemsOrder($originalContent);
$this->hasNewlineAfterOpening = (bool) Strings::match($originalContent, '#^\(\s+#m');
$this->hasNewlineBeforeClosing = (bool) Strings::match($originalContent, '#\s+\)$#m');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ final class InheritanceTypeTagValueNode extends AbstractDoctrineTagValueNode
*/
private $value;

public function __construct(?string $value)
public function __construct(?string $value, ?string $originalContent)
{
$this->value = $value;
$this->resolveOriginalContentSpacingAndOrder($originalContent);
}

public function __toString(): string
Expand All @@ -29,6 +30,10 @@ public function __toString(): string
return '';
}

return '("' . $this->value . '")';
if ($this->originalContent && ! in_array('value', (array) $this->orderedVisibleItems, true)) {
return '("' . $this->value . '")';
}

return '(value="' . $this->value . '")';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ public function __toString(): string
$contentItems = [];

if ($this->name !== null) {
$contentItems['name'] = sprintf('name="%s"', $this->name);
if ($this->originalContent !== null && ! in_array('name', (array) $this->orderedVisibleItems, true)) {
$contentItems[] = '"' . $this->name . '"';
} else {
$contentItems['name'] = sprintf('name="%s"', $this->name);
}
}

if ($this->schema !== null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,6 @@ public function __toString(): string
{
$contentItems = [];

if ($this->nullable !== null) {
$contentItems['nullable'] = sprintf('nullable=%s', $this->nullable ? 'true' : 'false');
}

if ($this->name) {
$contentItems['name'] = sprintf('name="%s"', $this->name);
}
Expand All @@ -95,7 +91,12 @@ public function __toString(): string
$contentItems['referencedColumnName'] = sprintf('referencedColumnName="%s"', $this->referencedColumnName);
}

if ($this->unique !== null) {
if ($this->nullable !== null) {
$contentItems['nullable'] = sprintf('nullable=%s', $this->nullable ? 'true' : 'false');
}

// skip default value
if ($this->unique !== null && $this->unique) {
$contentItems['unique'] = sprintf('unique=%s', $this->unique ? 'true' : 'false');
}

Expand Down Expand Up @@ -134,13 +135,13 @@ public function isNullable(): ?bool
return $this->nullable;
}

public function changeName(string $newName): void
public function getTag(): ?string
{
$this->name = $newName;
return $this->tag ?: self::SHORT_NAME;
}

public function getTag(): ?string
public function getUnique(): ?bool
{
return $this->tag ?: self::SHORT_NAME;
return $this->unique;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,23 @@ public function __toString(): string
$itemContents = [];

if ($this->serviceName) {
$itemContents[] = $this->serviceName;
$itemContents[] = '"' . $this->serviceName . '"';
}

if ($this->required !== null) {
$itemContents[] = sprintf('required=%s', $this->required ? 'true' : 'false');
}

if ($this->strict !== null) {
// skip default
if (! $this->strict) {
$itemContents[] = sprintf('strict=%s', $this->strict ? 'true' : 'false');
}

if ($itemContents === []) {
return '';
}

$stringContent = implode(', ', $itemContents);

return '(' . $stringContent . ')';
return $this->printContentItems($itemContents);
}

public function getServiceName(): ?string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator
return null;
}

return new InheritanceTypeTagValueNode($inheritanceType->value);
$annotationContent = $this->resolveContentFromTokenIterator($tokenIterator);

return new InheritanceTypeTagValueNode($inheritanceType->value, $annotationContent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ private function parseChildAndStoreItsPositions(TokenIterator $tokenIterator): N
$startEndValueObject = new StartEndValueObject($tokenStart, $tokenEnd);

$attributeAwareNode = $this->attributeAwareNodeFactory->createFromNode($phpDocNode);
$attributeAwareNode->setAttribute(Attribute::PHP_DOC_NODE_INFO, $startEndValueObject);
$attributeAwareNode->setAttribute(Attribute::START_END, $startEndValueObject);

$possibleMultilineText = $this->multilineSpaceFormatPreserver->resolveCurrentPhpDocNodeText(
$attributeAwareNode
Expand Down
Loading