Skip to content

Commit

Permalink
[TypeDeclaration] Do not remove multiple docblocks with comment on Ty…
Browse files Browse the repository at this point in the history
…pedPropertyFromAssignsRector (#3263)

* [TypeDeclaration] Do not remove multiple comments on TypedPropertyFromAssignsRector

more fixture rules-tests

Fix

Fixed 🎉

final touch: eol

Final touch: return null on multiple docs

updated to mark Doc as Comment when not in last, as the used one is last

Final touch: clean up

[ci-review] Rector Rectify

apply setDocComment after set comments attribute

failing fixture preserve multiple docs no change

type

create another attribute to save previous docs

* Try using new main doc

* phpstan

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* Final touch: move to DocblockUpdater

* Final touch: clean up

* Final touch: clean up

* Really Really Final touch: add comment

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Jan 3, 2023
1 parent 27d5714 commit 8c439cf
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 1 deletion.
52 changes: 51 additions & 1 deletion packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\BetterPhpDocParser\PhpDocInfo;

use PhpParser\Comment;
use PhpParser\Comment\Doc;
use PhpParser\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
Expand Down Expand Up @@ -35,7 +36,7 @@ public function __construct(
private readonly StaticTypeMapper $staticTypeMapper,
private readonly AnnotationNaming $annotationNaming,
private readonly RectorChangeCollector $rectorChangeCollector,
private readonly PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder,
private readonly PhpDocNodeByTypeFinder $phpDocNodeByTypeFinder
) {
}

Expand Down Expand Up @@ -76,6 +77,13 @@ public function createFromNode(Node $node): ?PhpDocInfo
$tokenIterator = new BetterTokenIterator([]);
$phpDocNode = new PhpDocNode([]);
} else {
$comments = $node->getComments();
$docs = array_filter($comments, static fn (Comment $comment): bool => $comment instanceof Doc);

if (count($docs) > 1) {
$this->storePreviousDocs($node, $comments, $docComment);
}

$text = $docComment->getText();
$tokens = $this->lexer->tokenize($text);
$tokenIterator = new BetterTokenIterator($tokens);
Expand Down Expand Up @@ -107,6 +115,48 @@ public function createEmpty(Node $node): PhpDocInfo
return $phpDocInfo;
}

/**
* @param Comment[]|Doc[] $comments
*/
private function storePreviousDocs(Node $node, array $comments, Doc $doc): void
{
$previousDocsAsComments = [];
$newMainDoc = null;

foreach ($comments as $comment) {
// On last Doc, stop
if ($comment === $doc) {
break;
}

// pure comment
if (! $comment instanceof Doc) {
$previousDocsAsComments[] = $comment;
continue;
}

// make Doc as comment Doc that not last
$previousDocsAsComments[] = new Comment(
$comment->getText(),
$comment->getStartLine(),
$comment->getStartFilePos(),
$comment->getStartTokenPos(),
$comment->getEndLine(),
$comment->getEndFilePos(),
$comment->getEndTokenPos()
);

/**
* Make last Doc before main Doc to candidate main Doc
* so it can immediatelly be used as replacement of Main doc when main doc removed
*/
$newMainDoc = $comment;
}

$node->setAttribute(AttributeKey::PREVIOUS_DOCS_AS_COMMENTS, $previousDocsAsComments);
$node->setAttribute(AttributeKey::NEW_MAIN_DOC, $newMainDoc);
}

/**
* Needed for printing
*/
Expand Down
12 changes: 12 additions & 0 deletions packages/Comments/NodeDocBlock/DocBlockUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ public function updateRefactoredNodeWithPhpDocInfo(Node $node): void

private function setCommentsAttribute(Node $node): void
{
if ($node->hasAttribute(AttributeKey::PREVIOUS_DOCS_AS_COMMENTS)) {
/** @var Comment[] $previousDocsAsComments */
$previousDocsAsComments = $node->getAttribute(AttributeKey::PREVIOUS_DOCS_AS_COMMENTS);
$node->setAttribute(AttributeKey::COMMENTS, $previousDocsAsComments);
}

if ($node->hasAttribute(AttributeKey::NEW_MAIN_DOC)) {
/** @var Doc $newMainDoc */
$newMainDoc = $node->getAttribute(AttributeKey::NEW_MAIN_DOC);
$node->setDocComment($newMainDoc);
}

$comments = array_filter($node->getComments(), static fn (Comment $comment): bool => ! $comment instanceof Doc);
$node->setAttribute(AttributeKey::COMMENTS, $comments);
}
Expand Down
12 changes: 12 additions & 0 deletions packages/NodeTypeResolver/Node/AttributeKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ final class AttributeKey
*/
public const COMMENTS = 'comments';

/**
* Cover multi docs
* @var string
*/
public const PREVIOUS_DOCS_AS_COMMENTS = 'previous_docs_as_comments';

/**
* Cover multi docs
* @var string
*/
public const NEW_MAIN_DOC = 'new_main_doc';

/**
* Internal php-parser name.
* Do not change this even if you want!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector\Fixture;

final class DoNotRemoveMultipleDocblockComment
{
// A comment

/**
* Another comment
*/

/**
* @var \DateTime
*/
private $property;

public function __construct()
{
$this->property = new \DateTime();
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector\Fixture;

final class DoNotRemoveMultipleDocblockComment
{
// A comment
/**
* Another comment
*/
private \DateTime $property;

public function __construct()
{
$this->property = new \DateTime();
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector\Fixture;

final class DoNotRemoveMultipleDocblockComment2
{
// A comment

/**
* Another comment
*/

/**
* Another comment inside main doc
*
* @var \DateTime
*/
private $property;

public function __construct()
{
$this->property = new \DateTime();
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector\Fixture;

final class DoNotRemoveMultipleDocblockComment2
{
// A comment
/**
* Another comment
*/
/**
* Another comment inside main doc
*/
private \DateTime $property;

public function __construct()
{
$this->property = new \DateTime();
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector\Fixture;

final class PreserveMultipleDocsNoChange
{
// A comment

/**
* Another comment
*/

/**
* @var class-string
*/
private $property;

public function __construct()
{
$this->property = 'DateTime';
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector\Fixture;

final class PreserveMultipleDocsNoChange
{
// A comment

/**
* Another comment
*/

/**
* @var class-string
*/
private string $property;

public function __construct()
{
$this->property = 'DateTime';
}
}

?>

0 comments on commit 8c439cf

Please sign in to comment.