Ejemplo n.º 1
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;
  }