public function getFixedNode()

in src/Linters/GroupUseStatementsLinter.hack [335:520]


  public function getFixedNode(
    Script $script,
    dict<
      string,
      dict<
        string,
        (
          vec<INamespaceUseDeclaration>,
          vec<(
            string,
            ?string,
            vec<Trivia>,
            vec<Trivia>,
            vec<Trivia>,
            vec<Trivia>,
          )>,
        ),
      >,
    > $result,
  ): Script {
    foreach ($result as $kind => $result_kind) {
      foreach ($result_kind as $namespace => list($nodes, $names)) {
        $names = Vec\sort_by($names, ($name) ==> $name[0].'-'.($name[1] ?? ''));
        $names_count = C\count($names);

        $length = 8 +
          Str\length($kind) +
          Str\length($namespace) +
          (
            C\reduce(
              $names,
              ($l, $name) ==> {
                list(
                  $name,
                  $alias,
                  $name_leading,
                  $name_trailing,
                  $alias_trailing,
                  $comma_trailing,
                ) = $name;

                return $l +
                  Str\length($name) +
                  ($alias is nonnull ? 4 + Str\length($alias) : 0) +
                  C\reduce(
                    Vec\concat(
                      $name_leading,
                      $name_trailing,
                      $alias_trailing,
                      $comma_trailing,
                    ),
                    ($_lt, $trivia) ==> Str\length($trivia->getCode()),
                    0,
                  );
              },
              0,
            )
          );

        $multiple = false;
        if ($length > 80) {
          $multiple = true;
        }

        $i = 0;
        foreach ($nodes as $node) {
          if ($i === 0) {
            $use_token = $node->getFirstDescendantByType<UseToken>();
            $semi_token = $node->getFirstDescendantByType<SemicolonToken>();

            $script = $script->replace($node, new NamespaceGroupUseDeclaration(
              new UseToken(
                $use_token is nonnull ? $use_token->getLeading() : null,
                new NodeList(vec[new WhiteSpace(' ')]),
              ),
              (
                (string $kind): ?Token ==> {
                  switch ($kind) {
                    case 'function':
                      return new FunctionToken(
                        null,
                        new NodeList(vec[new WhiteSpace(' ')]),
                      );
                    case 'namespace':
                      return new NamespaceToken(
                        null,
                        new NodeList(vec[new WhiteSpace(' ')]),
                      );
                    case 'type':
                      return new TypeToken(
                        null,
                        new NodeList(vec[new WhiteSpace(' ')]),
                      );
                    default:
                      return null;
                  }
                }
              )($kind),
              new QualifiedName(
                new NodeList(
                  Str\split($namespace, '\\')
                    |> Vec\map($$, ($name) ==> {
                      return new ListItem(
                        new NameToken(null, null, $name),
                        new BackslashToken(null, null),
                      );
                    }),
                ),
              ),
              new LeftBraceToken(
                null,
                $multiple ? new NodeList(vec[new WhiteSpace("\n")]) : null,
              ),
              new NodeList(Vec\map_with_key($names, ($index, $name) ==> {
                list(
                  $name,
                  $alias,
                  $name_leading,
                  $name_trailing,
                  $alias_trailing,
                  $comma_trailing,
                ) = $name;
                return new ListItem(
                  new NamespaceUseClause(
                    /*$clause_kind*/ null,
                    new QualifiedName(
                      new NodeList(vec[
                        new ListItem(
                          new NameToken(
                            new NodeList(
                              $multiple
                                ? Vec\concat(
                                    vec[new WhiteSpace('  ')],
                                    $name_leading,
                                  )
                                : $name_leading,
                            ),
                            new NodeList($name_trailing),
                            $name,
                          ),
                          /*$separator*/ null,
                        ),
                      ]),
                    ),
                    $alias is nonnull
                      ? new AsToken(
                          new NodeList(vec[new WhiteSpace(' ')]),
                          new NodeList(vec[new WhiteSpace(' ')]),
                        )
                      : null,
                    $alias is nonnull
                      ? new NameToken(
                          null,
                          new NodeList($alias_trailing),
                          $alias,
                        )
                      : null,
                  ),
                  (!$multiple && $index === $names_count - 1)
                    ? null
                    : new CommaToken(
                        null,
                        new NodeList(Vec\concat($comma_trailing, vec[
                          $multiple
                            ? new WhiteSpace("\n")
                            : new WhiteSpace(' '),
                        ])),
                      ),
                );
              })),
              new RightBraceToken(null, null),
              new SemicolonToken(null, $semi_token?->getTrailing()),
            ));
          } else {
            $descendants = $script->getAncestorsOfDescendant($node);
            invariant(C\lastx($descendants) === $node, 'failed to find node');
            $parent = $descendants[C\count($descendants) - 2] as NodeList<_>;
            $script = $script->replace($parent, $parent->withoutChild($node));
          }
          $i++;
        }
      }
    }

    return $script;
  }