Skip to content

Commit

Permalink
[AutoImport] Fixing auto import on multiple @\ usage (#5271)
Browse files Browse the repository at this point in the history
* add fixture

* [AutoImport] Fixing auto import on multiple @\ usage

* more fixtures

* more fixtures

* fixing printer take 1

* fix partial

* fix phpstan

---------

Co-authored-by: Tomas Votruba <tomas.vot@gmail.com>
  • Loading branch information
samsonasik and TomasVotruba committed Nov 21, 2023
1 parent 189a026 commit e138f84
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,18 @@ private function transformGenericTagValueNodesToDoctrineAnnotationTagValueNodes(
foreach ($phpDocNode->children as $key => $phpDocChildNode) {
// the @\FQN use case
if ($phpDocChildNode instanceof PhpDocTextNode) {
$spacelessPhpDocTagNode = $this->resolveFqnAnnotationSpacelessPhpDocTagNode(
$spacelessPhpDocTagNodes = $this->resolveFqnAnnotationSpacelessPhpDocTagNode(
$phpDocChildNode,
$currentPhpNode
);
if (! $spacelessPhpDocTagNode instanceof SpacelessPhpDocTagNode) {

if ($spacelessPhpDocTagNodes === []) {
continue;
}

$phpDocNode->children[$key] = $spacelessPhpDocTagNode;
unset($phpDocNode->children[$key]);
array_splice($phpDocNode->children, $key, 0, $spacelessPhpDocTagNodes);

continue;
}

Expand Down Expand Up @@ -304,28 +307,36 @@ private function combineStartAndEnd(
return new StartAndEnd($currentStartAndEnd->getStart(), $nextStartAndEnd->getEnd());
}

/**
* @return SpacelessPhpDocTagNode[]
*/
private function resolveFqnAnnotationSpacelessPhpDocTagNode(
PhpDocTextNode $phpDocTextNode,
Node $currentPhpNode
): ?SpacelessPhpDocTagNode {
$match = Strings::match($phpDocTextNode->text, self::LONG_ANNOTATION_REGEX);
$fullyQualifiedAnnotationClass = $match['class_name'] ?? null;
): array {
$matches = Strings::matchAll($phpDocTextNode->text, self::LONG_ANNOTATION_REGEX);
$spacelessPhpDocTagNodes = [];
foreach ($matches as $match) {
$fullyQualifiedAnnotationClass = $match['class_name'] ?? null;

if ($fullyQualifiedAnnotationClass === null) {
return null;
}
if ($fullyQualifiedAnnotationClass === null) {
continue;
}

$annotationContent = $match['annotation_content'] ?? null;
$tagName = '@\\' . $fullyQualifiedAnnotationClass;
$annotationContent = $match['annotation_content'] ?? null;
$tagName = '@\\' . $fullyQualifiedAnnotationClass;

$formerStartEnd = $phpDocTextNode->getAttribute(PhpDocAttributeKey::START_AND_END);
$formerStartEnd = $phpDocTextNode->getAttribute(PhpDocAttributeKey::START_AND_END);

return $this->createDoctrineSpacelessPhpDocTagNode(
$annotationContent,
$tagName,
$fullyQualifiedAnnotationClass,
$formerStartEnd,
$currentPhpNode
);
$spacelessPhpDocTagNodes[] = $this->createDoctrineSpacelessPhpDocTagNode(
$annotationContent,
$tagName,
$fullyQualifiedAnnotationClass,
$formerStartEnd,
$currentPhpNode
);
}

return $spacelessPhpDocTagNodes;
}
}
2 changes: 1 addition & 1 deletion packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private function printEnd(string $output): string
}

if ($lastTokenPosition === 0) {
$lastTokenPosition = 1;
return $output . "\n */";
}

return $this->addTokensFromTo($output, $lastTokenPosition, $this->tokenCount, true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

class TwoRoutesWithPrevDoc
{
/**
* @return Response
* @\Symfony\Component\Routing\Annotation\Route("/first", methods={"GET"})
* @\Symfony\Component\Routing\Annotation\Route("/second", methods={"GET"})
*/
public function some(): Response
{
return new Response();
}
}
36 changes: 36 additions & 0 deletions tests/Issues/AutoImport/Fixture/DocBlock/two_routes.php.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

class TwoRoutes
{
/**
* @\Symfony\Component\Routing\Annotation\Route("/first", methods={"GET"})
* @\Symfony\Component\Routing\Annotation\Route("/second", methods={"GET"})
*/
public function some(): Response
{
return new Response();
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

use Symfony\Component\Routing\Annotation\Route;
class TwoRoutes
{
/**
* @Route("/first", methods={"GET"})
* @Route("/second", methods={"GET"})
*/
public function some(): Response
{
return new Response();
}
}

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

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

class TwoRoutesWithNextDoc
{
/**
* @\Symfony\Component\Routing\Annotation\Route("/first", methods={"GET"})
* @\Symfony\Component\Routing\Annotation\Route("/second", methods={"GET"})
* @return Response
*/
public function some(): Response
{
return new Response();
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

use Symfony\Component\Routing\Annotation\Route;
class TwoRoutesWithNextDoc
{
/**
* @Route("/first", methods={"GET"})
* @Route("/second", methods={"GET"})
* @return Response
*/
public function some(): Response
{
return new Response();
}
}

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

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

class TwoRoutesWithNextDoc2
{
/**
* @\Symfony\Component\Routing\Annotation\Route("/first", methods={"GET"})
* @\Symfony\Component\Routing\Annotation\Route("/second", methods={"GET"})
* @return Response
* @\Symfony\Component\Routing\Annotation\Route("/third", methods={"GET"})
*/
public function some(): Response
{
return new Response();
}
}

?>
-----
<?php

namespace Rector\Core\Tests\Issues\AutoImport\Fixture\DocBlock;

use Symfony\Component\Routing\Annotation\Route;
class TwoRoutesWithNextDoc2
{
/**
* @Route("/first", methods={"GET"})
* @Route("/second", methods={"GET"})
* @return Response
* @\Symfony\Component\Routing\Annotation\Route("/third", methods={"GET"})
*/
public function some(): Response
{
return new Response();
}
}

?>

0 comments on commit e138f84

Please sign in to comment.