private function migrateClass()

in src/Migrations/XHPLibV3ToV4Migration.hack [239:312]


  private function migrateClass(
    ClassishDeclaration $class,
    (function(string, Node): string) $type_resolver,
  ): ClassishDeclaration {
    if (
      !$class->getKeyword() is ClassToken ||
      $class->getExtendsList() is null ||
      $class->getBody()->getElements() is null
    ) {
      return $class;
    }

    $method_name = idx(
      self::ASYNCIFY_METHODS,
      $type_resolver(
        self::withoutTrivia($class->getExtendsListx()),
        $class->getExtendsListx(),
      ),
    );
    if ($method_name is null) {
      return $class;
    }

    foreach ($class->getBody()->getElementsx()->getChildren() as $decl) {
      if (!$decl is MethodishDeclaration) {
        continue;
      }
      $new_header = $decl->getFunctionDeclHeader();
      if (self::withoutTrivia($new_header->getName()) !== $method_name) {
        continue;
      }
      // asyncify return type
      if ($new_header->hasType()) {
        $new_header = $new_header->withType(
          self::asyncifyType($new_header->getTypex()),
        );
      }
      // add `async` keyword
      if (
        $new_header->hasModifiers() && !$new_header->getModifiersx()->isEmpty()
      ) {
        $new_header = $new_header->withModifiers(NodeList::createMaybeEmptyList(
          Vec\concat(
            $new_header->getModifiersx()->getChildren(),
            vec[new AsyncToken(null, self::space())],
          ),
        ));
      } else {
        // If there are no existing modifiers, also move leading Trivia from
        // the `function` token to the new `async` token.
        $new_header = $new_header
          ->withModifiers(NodeList::createMaybeEmptyList(vec[
            new AsyncToken(
              $new_header->getKeyword()->getLeading(),
              self::space(),
            ),
          ]))
          ->withKeyword($new_header->getKeyword()->withLeading(null));
      }
      return $class->replaceDescendant(
        $decl->getFunctionDeclHeader(),
        // append `Async` to method name
        $new_header->withName(
          new NameToken(
            $new_header->getName()->getFirstTokenx()->getLeading(),
            $new_header->getName()->getLastTokenx()->getTrailing(),
            $method_name.self::ASYNC_METHOD_SUFFIX,
          ),
        ),
      );
    }

    return $class;
  }