src/__Private/codegen/CodegenTokenFromData.hack (108 lines of code) (raw):
/*
* Copyright (c) 2017-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\HHAST\__Private;
use namespace Facebook\TypeAssert;
use namespace HH\Lib\Str;
use type Facebook\HackCodegen\{
CodegenFileType,
HackBuilderKeys,
HackBuilderValues,
};
final class CodegenTokenFromData extends CodegenBase {
<<__Override>>
public function generate(): void {
$cg = $this->getCodegenFactory();
$tokens = $this->getSchemaTokens();
$class_map = dict[];
$class_map_with_text = dict[];
foreach ($tokens['noText'] as $token) {
$kind = StrP\underscored($token['token_kind']);
$class_map[$kind] = Str\format(
'HHAST\\%sToken::class',
$token['token_kind'],
);
}
foreach ($tokens['fixedText'] as $token) {
$text = TypeAssert\not_null($token['token_text']);
$kind = $token['token_kind'];
if (Str\lowercase($text) === Str\uppercase($text)) {
$class_map[$text] = Str\format('HHAST\\%sToken::class', $kind);
} else {
$class_map_with_text[$text] = Str\format(
'HHAST\\%sToken::class',
$kind,
);
}
}
foreach ($tokens['variableText'] as $token) {
$kind = StrP\underscored($token['token_kind']);
$class_map_with_text[$kind] = Str\format(
'HHAST\\%sToken::class',
$token['token_kind'],
);
}
$cg
->codegenFile($this->getOutputDirectory().'/token_from_data.hack')
->setFileType(CodegenFileType::DOT_HACK)
->setNamespace('Facebook\\HHAST\\__Private')
->useNamespace('Facebook\\HHAST')
->addClass(
$cg
->codegenClass('TokenClassMap')
->addConstant(
$cg
->codegenClassConstant('WITH_TEXT')
->setType('dict<string, classname<HHAST\TokenWithVariableText>>')
->setValue(
$class_map_with_text,
HackBuilderValues::dict(
HackBuilderKeys::export(),
HackBuilderValues::literal(),
),
),
)
->addConstant(
$cg
->codegenClassConstant('WITHOUT_TEXT')
->setType('dict<string, classname<HHAST\TokenWithFixedText>>')
->setValue(
$class_map,
HackBuilderValues::dict(
HackBuilderKeys::export(),
HackBuilderValues::literal(),
),
),
),
)
->addFunction(
$cg
->codegenFunction('token_from_data')
->setReturnType('HHAST\\Token')
->addParameter('SourceRef $source_ref')
->addParameter('string $token_kind')
->addParameter('HHAST\\NodeList<HHAST\\Trivia> $leading')
->addParameter('HHAST\\NodeList<HHAST\\Trivia> $trailing')
->addParameter('string $token_text')
->setBody(
$cg
->codegenHackBuilder()
->add('$cls = TokenClassMap::WITHOUT_TEXT[$token_kind] ?? null;')
->add(
'if ($cls !== null) { return new $cls($leading, $trailing, $source_ref ); }',
)
->add('$cls = TokenClassMap::WITH_TEXT[$token_kind] ?? null;')
->add(
'if ($cls !== null) { return new $cls($leading, $trailing, $token_text, $source_ref ); }',
)
->addMultilineCall(
'throw new HHAST\\UnsupportedTokenError',
vec[
'$source_ref[\'file\']',
'$source_ref[\'offset\']',
'$token_kind',
],
)
->getCode(),
),
)
->save();
}
}