in lib/Parser/JSParserImpl-flow.cpp [1059:1255]
Optional<ESTree::Node *> JSParserImpl::parsePrimaryTypeAnnotationFlow() {
SMLoc start = tok_->getStartLoc();
switch (tok_->getKind()) {
case TokenKind::star:
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::ExistsTypeAnnotationNode());
case TokenKind::less:
return parseFunctionTypeAnnotationFlow();
case TokenKind::l_paren:
return parseFunctionOrGroupTypeAnnotationFlow();
case TokenKind::l_brace:
case TokenKind::l_bracepipe:
return parseObjectTypeAnnotationFlow(
AllowProtoProperty::No,
AllowStaticProperty::No,
AllowSpreadProperty::Yes);
case TokenKind::rw_interface: {
advance(JSLexer::GrammarContext::Type);
ESTree::NodeList extends{};
auto optBody = parseInterfaceTailFlow(start, extends);
if (!optBody)
return None;
return setLocation(
start,
*optBody,
new (context_) ESTree::InterfaceTypeAnnotationNode(
std::move(extends), *optBody));
}
case TokenKind::rw_typeof: {
advance(JSLexer::GrammarContext::Type);
auto optPrimary = parsePrimaryTypeAnnotationFlow();
if (!optPrimary)
return None;
return setLocation(
start,
getPrevTokenEndLoc(),
new (context_) ESTree::TypeofTypeAnnotationNode(*optPrimary));
}
case TokenKind::l_square:
return parseTupleTypeAnnotationFlow();
case TokenKind::rw_static:
case TokenKind::rw_this:
case TokenKind::identifier:
if (tok_->getResWordOrIdentifier() == anyIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::AnyTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == mixedIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::MixedTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == emptyIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::EmptyTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == booleanIdent_ ||
tok_->getResWordOrIdentifier() == boolIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::BooleanTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == numberIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::NumberTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == symbolIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::SymbolTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == stringIdent_) {
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::StringTypeAnnotationNode());
}
if (tok_->getResWordOrIdentifier() == interfaceIdent_) {
advance(JSLexer::GrammarContext::Type);
ESTree::NodeList extends{};
auto optBody = parseInterfaceTailFlow(start, extends);
if (!optBody)
return None;
return setLocation(
start,
*optBody,
new (context_) ESTree::InterfaceTypeAnnotationNode(
std::move(extends), *optBody));
}
{
auto optGeneric = parseGenericTypeFlow();
if (!optGeneric)
return None;
return *optGeneric;
}
case TokenKind::rw_null:
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::NullLiteralTypeAnnotationNode());
case TokenKind::rw_void:
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::VoidTypeAnnotationNode());
case TokenKind::string_literal: {
UniqueString *str = tok_->getStringLiteral();
UniqueString *raw = lexer_.getStringLiteral(tok_->inputStr());
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::StringLiteralTypeAnnotationNode(str, raw));
}
case TokenKind::numeric_literal: {
double value = tok_->getNumericLiteral();
UniqueString *raw = lexer_.getStringLiteral(tok_->inputStr());
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::NumberLiteralTypeAnnotationNode(value, raw));
}
case TokenKind::bigint_literal: {
UniqueString *raw = tok_->getBigIntLiteral();
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::BigIntLiteralTypeAnnotationNode(raw));
}
case TokenKind::minus: {
advance(JSLexer::GrammarContext::Type);
if (check(TokenKind::numeric_literal)) {
// Negate the literal.
double value = -tok_->getNumericLiteral();
UniqueString *raw = lexer_.getStringLiteral(StringRef(
start.getPointer(),
tok_->getEndLoc().getPointer() - start.getPointer()));
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::NumberLiteralTypeAnnotationNode(value, raw));
} else if (check(TokenKind::bigint_literal)) {
UniqueString *raw = lexer_.getStringLiteral(StringRef(
start.getPointer(),
tok_->getEndLoc().getPointer() - start.getPointer()));
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::BigIntLiteralTypeAnnotationNode(raw));
} else {
errorExpected(
TokenKind::numeric_literal,
"in type annotation",
"start of annotation",
start);
return None;
}
}
case TokenKind::rw_true:
case TokenKind::rw_false: {
bool value = check(TokenKind::rw_true);
auto *raw = tok_->getResWordIdentifier();
return setLocation(
start,
advance(JSLexer::GrammarContext::Type).End,
new (context_) ESTree::BooleanLiteralTypeAnnotationNode(value, raw));
}
default:
if (tok_->isResWord()) {
auto optGeneric = parseGenericTypeFlow();
if (!optGeneric)
return None;
return *optGeneric;
}
error(tok_->getStartLoc(), "unexpected token in type annotation");
return None;
}
}