private static function addBoilerplate()

in src/markdown-extensions/extracted-code-blocks/FilterBase.php [293:398]


  private static function addBoilerplate(
    string $path,
    string $extracted_code,
  ): string {
    // Strip #! and <?hh lines so that we don't insert any code before them
    // below. The stripped lines are added back at the end.
    $m = Regex\first_match($extracted_code, re"/^(#!.*\n|)(<\\?hh.*\n|)\\s*/");
    $headers = $m is nonnull ? $m[0] : '';
    $code = Str\strip_prefix($extracted_code, $headers);

    // If we can't find any top-level declarations, assume the code block
    // contains top-level code that needs to be wrapped in an <<__EntryPoint>>
    // function. This would ideally be done using HHAST, but that would be too
    // expensive.
    if (!Regex\matches(
      $code,
      re"/^(namespace|use|const|(async |)function|[a-z ]*class|interface|trait|enum) /m",
    )) {
      $code = Str\trim_right($code)
        |> Str\split($$, "\n")
        |> Vec\map($$, $line ==> Str\trim_right('  '.$line))
        |> Str\join($$, "\n");
      $code = "<<__EntryPoint>>\n".
        "async function _main(): Awaitable<void> {\n$code\n}\n";
    }

    // Insert \init_docs_autoloader() call at the beginning of the
    // <<__EntryPoint>> function (if there is one).
    if (
      !Str\ends_with($path, '.'.self::TYPE_ERRORS) &&
      Str\contains($code, '<<__EntryPoint>>') &&
      !Str\contains($code, 'init_docs_autoloader()')
    ) {
      $entrypoint_opening_brace = Str\search(
        $code,
        '{',
        Str\search($code, '<<__EntryPoint>>') as nonnull
      );
      invariant(
        $entrypoint_opening_brace is nonnull,
        'Failed to locate <<__EntryPoint>> opening brace.',
      );
      $code = Str\slice($code, 0, $entrypoint_opening_brace + 1).
        "\n  \\init_docs_autoloader();\n".
        Str\slice($code, $entrypoint_opening_brace + 1);
    }

    // Insert `use` clauses for common HSL namespaces. There might be some false
    // positives here, but that's fine.
    $uses = vec[];
    foreach (self::COMMON_HSL_NAMESPACES as $ns) {
      if (
        Str\contains($code, $ns.'\\') &&
        !\preg_match('/^use namespace HH\\\\Lib\\\\.*'.$ns.'/m', $code)
      ) {
        $uses[] = $ns;
      }
    }
    if (!C\is_empty($uses)) {
      $uses_str = Str\join($uses, ', ');
      if (C\count($uses) > 1) {
        $uses_str = '{'.$uses_str.'}';
      }
      $code = 'use namespace HH\\Lib\\'.$uses_str.";\n\n$code";
    }

    // Generate a unique namespace name (unless one is already specified),
    // e.g. HHVM\UserDocumentation\Guides\Hack\GettingStarted\MyFirstProgram.
    if (
      !Str\starts_with($code, 'namespace ') &&
      !Str\contains($code, "\nnamespace ")
    ) {
      // Cut off anything after the first period. This makes it possible to
      // force multiple examples to use the same namespace, e.g. example.hack
      // and example.inc.hack.
      $suffix = Str\split(\basename($path), '.', 2)[1];
      $ns = Str\strip_suffix($path, '.'.$suffix)
        |> Str\strip_prefix($$, BuildPaths::EXAMPLES_EXTRACT_DIR.'/')
        |> Str\split($$, '/')
        |> Vec\map(
          $$,
          $part ==> Str\trim_left($part, '0123456789-_')
            |> Str\capitalize($$)
            |> Regex\replace_with( // convert to CamelCase
              $$,
              re"/[^a-zA-Z0-9]+([a-zA-Z0-9])/",
              $match ==> Str\uppercase($match[1]),
            ),
        )
        |> Str\join($$, '\\');
      $code = 'namespace HHVM\\UserDocumentation\\'.$ns.";\n\n$code";
    }

    if ($code !== $extracted_code) {
      $code =
        "// WARNING: Contains some auto-generated boilerplate code, see:\n".
        '// '.__METHOD__."\n\n".
        $code;
    }

    if (Str\contains($path, '.php') && !Str\contains($headers, '<?hh')) {
      $code = "<?hh\n\n".$code;
    }

    return $headers.$code;
  }