Ejemplo n.º 1
0
  /*
   * function
   *   : modifiers "fun" typeParameters?
   *       (type "." | attributes)?
   *       SimpleName
   *       typeParameters? functionParameters (":" type)?
   *       typeConstraints
   *       functionBody?
   *   ;
   */
  IElementType parseFunction() {
    assert _at(FUN_KEYWORD);

    advance(); // FUN_KEYWORD

    // Recovery for the case of class A { fun| }
    if (at(RBRACE)) {
      error("Function body expected");
      return FUN;
    }

    boolean typeParameterListOccurred = false;
    if (at(LT)) {
      parseTypeParameterList(TokenSet.create(LBRACKET, LBRACE, LPAR));
      typeParameterListOccurred = true;
    }

    myBuilder.disableJoiningComplexTokens();
    int lastDot = findLastBefore(RECEIVER_TYPE_TERMINATORS, TokenSet.create(LPAR), true);

    TokenSet functionNameFollow = TokenSet.create(LT, LPAR, COLON, EQ);
    parseReceiverType("function", functionNameFollow, lastDot);

    parseFunctionOrPropertyName(lastDot != -1, "function", functionNameFollow);

    myBuilder.restoreJoiningComplexTokensState();

    TokenSet valueParametersFollow = TokenSet.create(COLON, EQ, LBRACE, SEMICOLON, RPAR);

    if (at(LT)) {
      PsiBuilder.Marker error = mark();
      parseTypeParameterList(TokenSet.orSet(TokenSet.create(LPAR), valueParametersFollow));
      errorIf(
          error,
          typeParameterListOccurred,
          "Only one type parameter list is allowed for a function");
      typeParameterListOccurred = true;
    }

    if (at(LPAR)) {
      parseValueParameterList(false, valueParametersFollow);
    } else {
      error("Expecting '('");
    }

    if (at(COLON)) {
      advance(); // COLON

      if (!parseIdeTemplate()) {
        parseTypeRef();
      }
    }

    parseTypeConstraintsGuarded(typeParameterListOccurred);

    if (at(SEMICOLON)) {
      advance(); // SEMICOLON
    } else if (at(EQ) || at(LBRACE)) {
      parseFunctionBody();
    }

    return FUN;
  }