complete @see annotation, minor improvements

This commit is contained in:
TomasVotruba 2020-05-03 16:07:56 +02:00
parent 7f396171f9
commit a952cac41c
12 changed files with 118 additions and 19 deletions

View File

@ -252,3 +252,8 @@ parameters:
- '#Class (.*?) should be written with \:\:class notation, string found#'
- '#Parameter \#2 \$key of method Rector\\BetterPhpDocParser\\PhpDocNode\\AbstractTagValueNode\:\:printArrayItem\(\) expects string\|null, int\|string given#'
- '#Method Rector\\Naming\\Naming\\PropertyNaming\:\:resolveShortClassName\(\) should return string but returns string\|null#'
-
message: "#^Class \"Rector\\\\PSR4\\\\Rector\\\\Namespace_\\\\NormalizeNamespaceByPSR4ComposerAutoloadRector\" is missing @see annotation with test case class reference$#"
count: 1
path: rules/psr4/src/Rector/Namespace_/NormalizeNamespaceByPSR4ComposerAutoloadRector.php

View File

@ -11,6 +11,9 @@ use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NetteTesterToPHPUnit\AssertManipulator;
/**
* @see \Rector\NetteTesterToPHPUnit\Tests\Rector\Class_\NetteTesterClassToPHPUnitClassRector\NetteTesterPHPUnitRectorTest
*/
final class NetteAssertToPHPUnitAssertRector extends AbstractRector
{
/**

View File

@ -15,6 +15,9 @@ use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
* @see \Rector\Oxid\Tests\Rector\FuncCall\OxidReplaceBackwardsCompatabilityClassRector\OxidReplaceBackwardsCompatabilityClassRectorTest
*/
final class OxidReplaceBackwardsCompatabilityClassRector extends AbstractRector
{
/**

View File

@ -18,6 +18,8 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @source https://wiki.php.net/rfc/deprecations_php_7_2#each
*
* @see \Rector\Php72\Tests\Rector\Each\EachRectorTest
*/
final class ListEachRector extends AbstractRector
{

View File

@ -18,6 +18,8 @@ use Rector\Core\RectorDefinition\RectorDefinition;
/**
* @source https://wiki.php.net/rfc/deprecations_php_7_2#each
*
* @see \Rector\Php72\Tests\Rector\Each\EachRectorTest
*/
final class WhileEachToForeachRector extends AbstractRector
{

View File

@ -2,6 +2,7 @@ services:
_defaults:
public: true
autowire: true
autoconfigure: true
Rector\PSR4\:
resource: '../src'

View File

@ -23,6 +23,10 @@ use Rector\Sensio\Helper\TemplateGuesser;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
/**
* @see \Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\TemplateAnnotationVersion3RectorTest
* @see \Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\TemplateAnnotationVersion5RectorTest
*/
final class TemplateAnnotationRector extends AbstractRector
{
/**
@ -139,6 +143,7 @@ PHP
private function getSensioTemplateTagValueNode(ClassMethod $classMethod): ?SensioTemplateTagValueNode
{
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;

View File

@ -15,6 +15,9 @@ use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
/**
* @see \Rector\Core\Tests\Rector\Architecture\DependencyInjection\ActionInjectionToConstructorInjectionRector\ActionInjectionToConstructorInjectionRectorTest
*/
final class ReplaceVariableByPropertyFetchRector extends AbstractRector
{
/**

View File

@ -5,13 +5,21 @@ declare(strict_types=1);
namespace Rector\PHPStanExtensions\Rule;
use Nette\Utils\Strings;
use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
use PHPStan\PhpDoc\ResolvedPhpDocBlock;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Rules\Rule;
use PHPStan\Type\FileTypeMapper;
use Rector\Core\Contract\Rector\PhpRectorInterface;
use Rector\PostRector\Contract\Rector\PostRectorInterface;
/**
* @see \Rector\PHPStanExtensions\Tests\Rule\SeeAnnotationToTestRule\SeeAnnotationToTestRuleTest
*/
final class SeeAnnotationToTestRule implements Rule
{
/**
@ -51,37 +59,30 @@ final class SeeAnnotationToTestRule implements Rule
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->name === null) {
$classReflection = $this->matchClassReflection($node);
if ($classReflection === null) {
return [];
}
$className = (string) $node->namespacedName;
if (! $this->isClassMatch($className)) {
if ($this->shouldSkipClassReflection($classReflection)) {
return [];
}
$classReflection = $this->broker->getClass($className);
$docComment = $node->getDocComment();
if ($docComment === null) {
return [sprintf(self::ERROR_MESSAGE, $className)];
return [sprintf(self::ERROR_MESSAGE, $classReflection->getName())];
}
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
$scope->getFile(),
$classReflection->getName(),
null,
null,
$docComment->getText()
);
$resolvedPhpDoc = $this->resolvePhpDoc($scope, $classReflection, $docComment);
$seeTags = $resolvedPhpDoc->getPhpDocNode()->getTagsByName('@see');
// @todo validate to refer a TestCase class
if ($seeTags !== []) {
return [];
}
return [sprintf(self::ERROR_MESSAGE, $className)];
return [sprintf(self::ERROR_MESSAGE, $classReflection->getName())];
}
private function isClassMatch(string $className): bool
@ -94,4 +95,48 @@ final class SeeAnnotationToTestRule implements Rule
return false;
}
private function shouldSkipClassReflection(ClassReflection $classReflection): bool
{
if (! $this->isClassMatch($classReflection->getName())) {
return true;
}
if ($classReflection->isAbstract()) {
return true;
}
// meta-Rector
if ($classReflection->isSubclassOf(PostRectorInterface::class)) {
return true;
}
// skip filesystem for now
return ! $classReflection->isSubclassOf(PhpRectorInterface::class);
}
private function matchClassReflection(Class_ $node): ?ClassReflection
{
if ($node->name === null) {
return null;
}
$className = (string) $node->namespacedName;
if (! class_exists($className)) {
return null;
}
return $this->broker->getClass($className);
}
private function resolvePhpDoc(Scope $scope, ClassReflection $classReflection, Doc $doc): ResolvedPhpDocBlock
{
return $this->fileTypeMapper->getResolvedPhpDoc(
$scope->getFile(),
$classReflection->getName(),
null,
null,
$doc->getText()
);
}
}

View File

@ -4,7 +4,22 @@ declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\SeeAnnotationToTestRule\Fixture;
final class ClassMissingDocBlockRector
{
use PhpParser\Node;
use Rector\Core\Contract\Rector\PhpRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\RectorDefinition;
final class ClassMissingDocBlockRector extends AbstractRector implements PhpRectorInterface
{
public function getNodeTypes(): array
{
}
public function refactor(Node $node): ?Node
{
}
public function getDefinition(): RectorDefinition
{
}
}

View File

@ -4,10 +4,25 @@ declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\SeeAnnotationToTestRule\Fixture;
use PhpParser\Node;
use Rector\Core\Contract\Rector\PhpRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
* Some doc block
*/
final class ClassMissingSeeAnnotationRector
final class ClassMissingSeeAnnotationRector extends AbstractRector implements PhpRectorInterface
{
public function getNodeTypes(): array
{
}
public function refactor(Node $node): ?Node
{
}
public function getDefinition(): RectorDefinition
{
}
}

View File

@ -24,10 +24,10 @@ final class SeeAnnotationToTestRuleTest extends AbstractServiceAwareRuleTestCase
public function provideData(): Iterator
{
$errorMessage = sprintf(SeeAnnotationToTestRule::ERROR_MESSAGE, ClassMissingDocBlockRector::class);
yield [__DIR__ . '/Fixture/ClassMissingDocBlockRector.php', [[$errorMessage, 7]]];
yield [__DIR__ . '/Fixture/ClassMissingDocBlockRector.php', [[$errorMessage, 12]]];
$errorMessage = sprintf(SeeAnnotationToTestRule::ERROR_MESSAGE, ClassMissingSeeAnnotationRector::class);
yield [__DIR__ . '/Fixture/ClassMissingSeeAnnotationRector.php', [[$errorMessage, 10]]];
yield [__DIR__ . '/Fixture/ClassMissingSeeAnnotationRector.php', [[$errorMessage, 15]]];
}
protected function getRule(): Rule