in src/__Private/codegen/CodegenRelations.hack [36:126]
private async function generateAsync(): Awaitable<void> {
print("Generating file list to infer relationships...\n");
$files = $this->getFileList();
print("Infering relationships, this can take a long time...\n");
$done = new Ref(0);
$start = \microtime(true);
$relationships = new Ref(dict[]);
$queue = new Async\Semaphore(
/* limit = */ 32,
async $file ==> {
try {
$links = await $this->getRelationsInFileAsync($file);
$new = dict[];
foreach ($links as $key => $children) {
$relationships->v[$key] ??= keyset[];
$new_children = Keyset\diff($children, $relationships->v[$key]);
if ($new_children) {
$new[$key] = $children;
}
}
if ($new) {
await execute_async('hhvm', '-l', $file);
foreach ($new as $key => $children) {
$relationships->v[$key] = Keyset\union(
$relationships->v[$key],
$children,
);
}
}
} catch (\Throwable $_) {
// HHVM and Hack tests intentionally include lots of invalid
// files
} finally {
$done->v++;
}
},
);
concurrent {
await Dict\map_async(
$files,
async $file ==> await $queue->waitForAsync($file),
);
await async {
$total = C\count($files);
while ($done->v < $total) {
/* HHAST_IGNORE_ERROR[DontAwaitInALoop] */
await \HH\Asio\usleep(1000 * 1000);
if ($done->v === 0) {
continue;
}
$ratio = ((float)$done->v) / $total;
$now = \microtime(true);
$elapsed = $now - $start;
$rate = $done->v / $elapsed;
$end = $start + ($total / $rate);
\fprintf(
\STDERR,
"%d%%\t(%d / %d)\tExpected finish in %ds at %s\n",
(int)($ratio * 100),
$done->v,
$total,
(int)($end - $now),
\strftime('%H:%M:%S', (int)$end),
);
}
};
}
$cg = $this->getCodegenFactory();
$cg->codegenFile($this->getOutputDirectory().'/inferred_relationships.hack')
->setFileType(CodegenFileType::DOT_HACK)
->setNamespace('Facebook\\HHAST\\__Private')
->addConstant(
$cg->codegenConstant('INFERRED_RELATIONSHIPS')
->setType('dict<string, keyset<string>>')
->setValue(
$relationships->v
|> Dict\sort_by_key($$)
|> Dict\map($$, $children ==> Keyset\sort($children)),
HackBuilderValues::dict(
HackBuilderKeys::export(),
HackBuilderValues::keyset(HackBuilderValues::export()),
),
),
)
->save();
print("... done!\n");
}