class NoClassMetadataOnAbstractTestClasses

Ensures abstract test base classes do not carry metadata.

@implements Rule<\PHPStan\Node\InClassNode>

@internal

Hierarchy

Expanded class hierarchy of NoClassMetadataOnAbstractTestClasses

1 file declares its use of NoClassMetadataOnAbstractTestClasses
NoClassMetadataOnAbstractTestClassesTest.php in core/tests/PHPStan/tests/NoClassMetadataOnAbstractTestClassesTest.php

File

core/tests/PHPStan/Rules/NoClassMetadataOnAbstractTestClasses.php, line 24

Namespace

Drupal\PHPStan\Rules
View source
final class NoClassMetadataOnAbstractTestClasses implements Rule {
  
  /**
   * PHPUnit metadata annotations.
   *
   * @var list<string>
   */
  private array $annotationTargets = [
    '@after',
    '@afterClass',
    '@author',
    '@backupGlobals',
    '@backupStaticAttributes',
    '@before',
    '@beforeClass',
    '@covers',
    '@coversDefaultClass',
    '@coversNothing',
    '@dataProvider',
    '@depends',
    '@doesNotPerformAssertions',
    '@group',
    '@large',
    '@medium',
    '@postCondition',
    '@preCondition',
    '@preserveGlobalState',
    '@requires',
    '@runInSeparateProcess',
    '@runTestsInSeparateProcesses',
    '@small',
    '@test',
    '@testdox',
    '@testWith',
    '@ticket',
    '@uses',
  ];
  public function __construct(private ReflectionProvider $reflectionProvider) {
  }
  
  /**
   * {@inheritdoc}
   */
  public function getNodeType() : string {
    return InClassNode::class;
  }
  
  /**
   * {@inheritdoc}
   */
  public function processNode(Node $node, Scope $scope) : array {
    $class = $node->getClassReflection();
    if ($class->isSubclassOfClass($this->reflectionProvider
      ->getClass(TestCase::class)) && $class->isAbstract()) {
      $fails = [];
      foreach ($class->getAttributes() as $attribute) {
        if (str_starts_with($attribute->getName(), 'PHPUnit\\Framework\\Attributes\\')) {
          $fails[] = RuleErrorBuilder::message("Abstract test class {$class->getName()} must not add attribute {$attribute->getName()}.")
            ->identifier('abstractTestClass.metadataForbidden')
            ->line($node->getStartLine())
            ->build();
        }
      }
      $resolvedPhpDoc = $class->getResolvedPhpDoc();
      if ($resolvedPhpDoc) {
        foreach ($resolvedPhpDoc->getPhpDocNodes() as $phpDocNode) {
          foreach ($phpDocNode->getTags() as $tag) {
            if (in_array($tag->name, $this->annotationTargets, TRUE)) {
              $fails[] = RuleErrorBuilder::message("Abstract test class {$class->getName()} must not add annotation {$tag->name}.")
                ->identifier('abstractTestClass.metadataForbidden')
                ->line($node->getStartLine())
                ->build();
            }
          }
        }
      }
      return $fails;
    }
    return [];
  }

}

Members


Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.