Optional JSParserImpl::parsePrimaryTypeAnnotationFlow()

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;
  }
}