class TestClassMethodMetadata

Validates method-level PHPUnit test metadata in test classes.

@implements Rule<\PHPStan\Node\InClassMethodNode>

@internal

Hierarchy

Expanded class hierarchy of TestClassMethodMetadata

1 file declares its use of TestClassMethodMetadata
TestClassMethodMetadataTest.php in core/tests/PHPStan/tests/TestClassMethodMetadataTest.php

File

core/tests/PHPStan/Rules/TestClassMethodMetadata.php, line 25

Namespace

Drupal\PHPStan\Rules
View source
final class TestClassMethodMetadata 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, private FileTypeMapper $fileTypeMapper) {
  }
  
  /**
   * {@inheritdoc}
   */
  public function getNodeType() : string {
    return InClassMethodNode::class;
  }
  
  /**
   * {@inheritdoc}
   */
  public function processNode(Node $node, Scope $scope) : array {
    $class = $node->getClassReflection();
    // We only process PHPUnit test classes here.
    if (!$class->isSubclassOfClass($this->reflectionProvider
      ->getClass(TestCase::class))) {
      return [];
    }
    $method = $node->getMethodReflection();
    // Resolve the method's PHPDoc.
    $resolvedPhpDoc = $this->fileTypeMapper
      ->getResolvedPhpDoc($scope->getFile(), $scope->isInClass() ? $scope->getClassReflection()
      ->getName() : NULL, $scope->isInTrait() ? $scope->getTraitReflection()
      ->getName() : NULL, $method->getName(), $method->getDocComment() ?? '');
    $fails = [];
    // Test methods should no longer have PHPUnit metadata annotations.
    if ($resolvedPhpDoc) {
      foreach ($resolvedPhpDoc->getPhpDocNodes() as $phpDocNode) {
        foreach ($phpDocNode->getTags() as $tag) {
          if (in_array($tag->name, $this->annotationTargets, TRUE)) {
            $fails[] = RuleErrorBuilder::message("Test method {$method->getName()} must not add annotation {$tag->name}.")
              ->identifier('testMethod.metadataForbidden')
              ->line($node->getStartLine())
              ->build();
          }
        }
      }
    }
    return $fails;
  }

}

Members

Title Sort descending Modifiers Object type Summary
TestClassMethodMetadata::$annotationTargets private property PHPUnit metadata annotations.
TestClassMethodMetadata::getNodeType public function
TestClassMethodMetadata::processNode public function
TestClassMethodMetadata::__construct public function

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