/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
namespace Facebook\HackCodegen;
use namespace HH\Lib\{Str, Vec};
final class HackfmtFormatter implements ICodegenFormatter {
public function __construct(private IHackCodegenConfig $config) {}
public function format(string $code, string $_file_name): string {
$output = vec[];
$exit_code = null;
$tempnam = \tempnam(\sys_get_temp_dir(), 'hack-codegen-hackfmt').'.hack';
$options = $this->getFormattedOptions();
try {
\file_put_contents($tempnam, $code);
\exec(
'hackfmt '.$options.' '.\escapeshellarg($tempnam),
inout $output,
inout $exit_code,
);
} finally {
\unlink($tempnam);
}
invariant($exit_code === 0, 'Failed to invoke hackfmt');
return Str\join($output, "\n")."\n";
}
private function getFormattedOptions(): string {
$options = vec[
'--indent-width',
(string)$this->config->getSpacesPerIndentation(),
'--line-width',
(string)$this->config->getMaxLineLength(),
];
if ($this->config->shouldUseTabs()) {
$options[] = '--tabs';
}
// HHVM < 4.48 always formats generated code. HHVM 4.48 never does (so this
// formatter is broken on that version). HHVM >= 4.49 formats generated code
// iff the following flag is provided:
if (\version_compare(\HHVM_VERSION, '4.49') >= 0) {
$options[] = '--format-generated-code';
}
return Vec\map($options, \escapeshellarg) |> Str\join($$, ' ');
}
}