public function migrateFile()

in src/Migrations/IsRefinementMigration.hack [16:112]


  public function migrateFile(string $_path, Script $ast): Script {
    $map = dict[
      'is_string' => () ==> new StringToken(null, null),
      'is_int' => () ==> new IntToken(null, null),
      'is_float' => () ==> new FloatToken(null, null),
      'is_bool' => () ==> new BoolToken(null, null),
      'is_resource' => () ==> new ResourceToken(null, null),
      'is_vec' => () ==> new VectorTypeSpecifier(
        new VecToken(null, null),
        new LessThanToken(null, null),
        new SimpleTypeSpecifier(new NameToken(null, null, '_')),
        /* trailing comma */ null,
        new GreaterThanToken(null, null),
      ),
      'is_keyset' => () ==> new KeysetTypeSpecifier(
        new KeysetToken(null, null),
        new LessThanToken(null, null),
        new SimpleTypeSpecifier(new NameToken(null, null, '_')),
        /* trailing comma */ null,
        new GreaterThanToken(null, null),
      ),
      'is_dict' => () ==> new DictionaryTypeSpecifier(
        new DictToken(null, null),
        new LessThanToken(null, null),
        NodeList::createMaybeEmptyList(vec[
          new ListItem(
            new SimpleTypeSpecifier(new NameToken(null, null, '_')),
            new CommaToken(null, new NodeList(vec[new WhiteSpace(' ')])),
          ),
          new ListItem(
            new SimpleTypeSpecifier(new NameToken(null, null, '_')),
            null,
          ),
        ]),
        new GreaterThanToken(null, null),
      ),
    ];

    return $ast->rewriteDescendants(($node, $parents) ==> {
      if (!$node is FunctionCallExpression) {
        return $node;
      }
      $name = $node->getReceiver();
      if ($name is NameToken) {
        $key = $name->getText();
      } else if ($name is QualifiedName) {
        $key = $name->getParts()->getChildrenOfItems()
          |> Vec\map($$, $item ==> $item?->getText() ?? '')
          |> Str\join($$, '\\')
          |> Str\strip_prefix($$, '\\');
      } else {
        return $node;
      }

      $make_replacement = $map[$key] ?? null;
      if ($make_replacement === null) {
        return $node;
      }
      $replacement = $make_replacement();
      if (!$replacement is ITypeSpecifier) {
        $replacement = new SimpleTypeSpecifier($replacement);
      }
      $replacement = new IsExpression(
        $node->getArgumentListx()->getChildrenOfItems()[0],
        new IsToken(
          new NodeList(vec[new WhiteSpace(' ')]),
          new NodeList(vec[new WhiteSpace(' ')]),
        ),
        $replacement,
      );

      $parent = C\lastx($parents);
      // Whitelist of cases where parenthese are not needed
      if (
        ($parent is ListItem<_>) ||
        ($parent is IfStatement) ||
        ($parent is ParenthesizedExpression)
      ) {
        $first = $replacement->getFirstTokenx();
        $last = $replacement->getLastTokenx();
        return $replacement->replace(
          $first,
          $first->withLeading($node->getFirstTokenx()->getLeading()),
        )
          ->replace(
            $last,
            $last->withTrailing($node->getLastTokenx()->getTrailing()),
          );
      }

      return new ParenthesizedExpression(
        new LeftParenToken($node->getFirstTokenx()->getLeading(), null),
        $replacement,
        new RightParenToken(null, $node->getLastTokenx()->getTrailing()),
      );
    });
  }