public function __construct()

in src/DocBlock/DocBlock.hack [33:142]


  public function __construct(private string $rawDocBlock) {
    $lines = $rawDocBlock
      |> Str\trim($$)
      |> Str\strip_prefix($$, '/**')
      |> Str\strip_suffix($$, '*/')
      |> Str\trim($$)
      |> Str\split($$, "\n")
      |> Vec\map($$, $l ==> Str\trim_left($l));

    $content_lines = vec[];
    $finished_content = false;
    $at_lines = vec[];

    foreach ($lines as $line) {
      if (Str\starts_with($line, '* ')) {
        $line = Str\strip_prefix($line, '* ');
      } else {
        $line = Str\strip_prefix($line, '*');
      }

      if (Str\starts_with($line, '@')) {
        $finished_content = true;
      }

      if ($finished_content) {
        $at_lines[] = $line;
        continue;
      } else {
        $content_lines[] = $line;
        continue;
      }
    }

    $content = Str\trim_left(Str\join($content_lines, "\n"));

    // Find first period that is not nested e.g. inside a link's URL.
    $first_period = null;
    $nesting_level = 0;
    for ($i = 0; $i < Str\length($content); ++$i) {
      if ($content[$i] === '.' && $nesting_level === 0) {
        $first_period = $i;
        break;
      } else if ($content[$i] === '(' || $content[$i] === '[') {
        ++$nesting_level;
      } else if ($content[$i] === ')' || $content[$i] === ']') {
        // Trim at 0 in case the docblock is not correctly parenthesized.
        $nesting_level = Math\maxva($nesting_level - 1, 0);
      }
    }

    if ($first_period !== null) {
      // Handle '...'
      $slice = Str\slice($content, $first_period);
      $x = Str\trim_left($slice, '.');
      $diff = Str\length($slice) - Str\length($x);
      if ($diff > 2) {
        $first_period = Str\search($content, '.', $first_period + $diff);
      }
    }

    $first_para = Str\search($content, "\n\n");
    if ($first_period === null && $first_para !== null) {
      $sep = $first_para;
    } else if ($first_period !== null && $first_para === null) {
      $sep = $first_period;
    } else if ($first_period !== null && $first_para !== null) {
      $sep = Math\minva($first_para, $first_period);
    } else {
      $sep = null;
    }

    if ($sep === null && $content !== '') {
      $this->summary = $content;
    } else if ($sep !== null) {
      $this->summary = Str\trim(Str\slice($content, 0, $sep));
      $description = Str\trim(Str\slice($content, $sep + 1));
      if ($description !== '') {
        $this->description = $description;
      }
    }

    $current_tag = null;
    $tags = vec[];

    foreach ($at_lines as $line) {
      $line = Str\trim($line);
      if (Str\starts_with($line, '@')) {
        if ($current_tag !== null) {
          $tags[] = $current_tag;
        }
        $current_tag = $line;
      } else {
        $current_tag .= "\n".$line;
      }
    }
    if ($current_tag !== null) {
      $tags[] = $current_tag;
    }

    foreach ($tags as $tag) {
      $space = Str\search($tag, ' ');
      if ($space === null) {
        $this->tags[] = tuple($tag, null);
        continue;
      }
      $key = Str\slice($tag, 0, $space);
      $value = Str\trim(Str\slice($tag, $space + 1));
      $this->tags[] = tuple($key, $value);
    }
  }