public function getTestClassName()

in src/Retriever/ClassRetriever.hack [85:154]


  public function getTestClassName(): ?classname<HackTest> {
    $test_classes = $this->caseInsensitiveClassnames
      |> Vec\filter(
        $$,
        $name ==> \is_subclass_of($name, HackTest::class, true),
      );

    $count = C\count($test_classes);
    if ($count !== 1) {
      $all_classes = '';
      if (!C\is_empty($this->caseInsensitiveClassnames)) {
        $all_classes = ':';
        foreach ($this->caseInsensitiveClassnames as $cn) {
          $rc = new \ReflectionClass($cn);
          $all_classes .= "\n - ".$rc->getName();
          if ($rc->isSubclassOf(HackTest::class)) {
            $all_classes .= ' (is a test class)';
          } else {
            $all_classes .= ' (is not a subclass of '.HackTest::class.')';
          }
        }
      }
      throw new InvalidTestClassException(
        Str\format(
          'There must be exactly one test class in %s; found %d%s',
          $this->filename,
          $count,
          $all_classes,
        ),
      );
    }

    $rc = new \ReflectionClass(C\onlyx($test_classes));
    if ($rc->isAbstract()) {
      return null;
    }
    $name = $rc->getName(); // fixes capitalization

    $class_name = $name
      |> Str\split($$, '\\')
      |> C\lastx($$);
    $filename = $this->filename
      |> Str\split($$, '/')
      |> C\lastx($$)
      |> Str\split($$, '.')
      |> C\firstx($$);

    if ($class_name !== $filename) {
      throw new InvalidTestClassException(
        Str\format(
          'Class name (%s) must match filename (%s)',
          $class_name,
          $filename,
        ),
      );
    }
    if (!Str\ends_with($class_name, 'Test')) {
      throw new InvalidTestClassException(
        Str\format('Class name (%s) must end with Test', $class_name),
      );
    }
    $classname = $this->convertToClassname($name);
    if ($classname === null) {
      throw new InvalidTestClassException(
        Str\format('%s does not extend %s', $name, HackTest::class),
      );
    }

    return $classname;
  }