Пример #1
0
  /*
   * class
   *   : modifiers ("class" | "trait") SimpleName
   *       typeParameters?
   *         modifiers ("(" primaryConstructorParameter{","} ")")?
   *       (":" attributes delegationSpecifier{","})?
   *       typeConstraints
   *       (classBody? | enumClassBody)
   *   ;
   */
  IElementType parseClass(boolean enumClass) {
    assert _atSet(CLASS_KEYWORD, TRAIT_KEYWORD);
    advance(); // CLASS_KEYWORD or TRAIT_KEYWORD

    if (!parseIdeTemplate()) {
      expect(IDENTIFIER, "Class name expected", CLASS_NAME_RECOVERY_SET);
    }
    boolean typeParametersDeclared = parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET);

    PsiBuilder.Marker beforeConstructorModifiers = mark();
    boolean hasConstructorModifiers = parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST, false);

    // Some modifiers found, but no parentheses following: class has already ended, and we are
    // looking at something else
    if (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON)) {
      beforeConstructorModifiers.rollbackTo();
      return CLASS;
    }

    // We are still inside a class declaration
    beforeConstructorModifiers.drop();

    if (at(LPAR)) {
      parseValueParameterList(false, TokenSet.create(COLON, LBRACE));
    } else if (hasConstructorModifiers) {
      // A comprehensive error message for cases like:
      //    class A private : Foo
      // or
      //    class A private {
      error("Expecting primary constructor parameter list");
    }

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

    parseTypeConstraintsGuarded(typeParametersDeclared);

    if (at(LBRACE)) {
      if (enumClass) {
        parseEnumClassBody();
      } else {
        parseClassBody();
      }
    }

    return CLASS;
  }
Пример #2
0
  public IElementType parseProperty(boolean local) {
    if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) {
      advance(); // VAL_KEYWORD or VAR_KEYWORD
    } else {
      errorAndAdvance("Expecting 'val' or 'var'");
    }

    boolean typeParametersDeclared =
        at(LT) && parseTypeParameterList(TokenSet.create(IDENTIFIER, EQ, COLON, SEMICOLON));

    TokenSet propertyNameFollow =
        TokenSet.create(
            COLON,
            EQ,
            LBRACE,
            RBRACE,
            SEMICOLON,
            VAL_KEYWORD,
            VAR_KEYWORD,
            FUN_KEYWORD,
            CLASS_KEYWORD);

    myBuilder.disableJoiningComplexTokens();

    // TODO: extract constant
    int lastDot =
        matchTokenStreamPredicate(
            new LastBefore(
                new AtSet(DOT, SAFE_ACCESS),
                new AbstractTokenStreamPredicate() {
                  @Override
                  public boolean matching(boolean topLevel) {
                    if (topLevel && (at(EQ) || at(COLON))) return true;
                    if (topLevel && at(IDENTIFIER)) {
                      IElementType lookahead = lookahead(1);
                      return lookahead != LT
                          && lookahead != DOT
                          && lookahead != SAFE_ACCESS
                          && lookahead != QUEST;
                    }
                    return false;
                  }
                }));

    PsiBuilder.Marker receiver = mark();
    parseReceiverType("property", propertyNameFollow, lastDot);

    boolean multiDeclaration = at(LPAR);
    boolean receiverTypeDeclared = lastDot != -1;

    errorIf(
        receiver,
        multiDeclaration && receiverTypeDeclared,
        "Receiver type is not allowed on a multi-declaration");

    if (multiDeclaration) {
      PsiBuilder.Marker multiDecl = mark();
      parseMultiDeclarationName(propertyNameFollow);
      errorIf(multiDecl, !local, "Multi-declarations are only allowed for local variables/values");
    } else {
      parseFunctionOrPropertyName(receiverTypeDeclared, "property", propertyNameFollow);
    }

    myBuilder.restoreJoiningComplexTokensState();

    if (at(COLON)) {
      PsiBuilder.Marker type = mark();
      advance(); // COLON
      if (!parseIdeTemplate()) {
        parseTypeRef();
      }
      errorIf(type, multiDeclaration, "Type annotations are not allowed on multi-declarations");
    }

    parseTypeConstraintsGuarded(typeParametersDeclared);

    if (local) {
      if (at(BY_KEYWORD)) {
        parsePropertyDelegate();
      } else if (at(EQ)) {
        advance(); // EQ
        myExpressionParsing.parseExpression();
        // "val a = 1; b" must not be an infix call of b on "val ...;"
      }
    } else {
      if (at(BY_KEYWORD)) {
        parsePropertyDelegate();
        consumeIf(SEMICOLON);
      } else if (at(EQ)) {
        advance(); // EQ
        myExpressionParsing.parseExpression();
        consumeIf(SEMICOLON);
      }

      if (parsePropertyGetterOrSetter()) {
        parsePropertyGetterOrSetter();
      }
      if (!atSet(EOL_OR_SEMICOLON, RBRACE)) {
        if (getLastToken() != SEMICOLON) {
          errorUntil("Property getter or setter expected", TokenSet.create(EOL_OR_SEMICOLON));
        }
      } else {
        consumeIf(SEMICOLON);
      }
    }

    return multiDeclaration ? MULTI_VARIABLE_DECLARATION : PROPERTY;
  }
Пример #3
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;
  }