Beispiel #1
0
  /*
   * functionParameterRest
   *   : parameter ("=" element)?
   *   ;
   */
  private boolean parseFunctionParameterRest() {
    boolean noErrors = true;

    // Recovery for the case 'fun foo(Array<String>) {}'
    if (at(IDENTIFIER) && lookahead(1) == LT) {
      error("Parameter name expected");
      parseTypeRef();
      noErrors = false;
    } else {
      expect(IDENTIFIER, "Parameter name expected", PARAMETER_NAME_RECOVERY_SET);

      if (at(COLON)) {
        advance(); // COLON
        parseTypeRef();
      } else {
        errorWithRecovery("Parameters must have type annotation", PARAMETER_NAME_RECOVERY_SET);
        noErrors = false;
      }
    }

    if (at(EQ)) {
      advance(); // EQ
      myExpressionParsing.parseExpression();
    }

    return noErrors;
  }
Beispiel #2
0
  /*
   * (SimpleName (":" type)){","}
   */
  public void parseMultiDeclarationName(TokenSet follow) {
    // Parsing multi-name, e.g.
    //   val (a, b) = foo()
    myBuilder.disableNewlines();
    advance(); // LPAR

    TokenSet recoverySet = TokenSet.orSet(PARAMETER_NAME_RECOVERY_SET, follow);
    if (!atSet(follow)) {
      while (true) {
        if (at(COMMA)) {
          errorAndAdvance("Expecting a name");
        } else if (at(RPAR)) {
          error("Expecting a name");
          break;
        }
        PsiBuilder.Marker property = mark();
        expect(IDENTIFIER, "Expecting a name", recoverySet);

        if (at(COLON)) {
          advance(); // COLON
          parseTypeRef(follow);
        }
        property.done(MULTI_VARIABLE_DECLARATION_ENTRY);

        if (!at(COMMA)) break;
        advance(); // COMMA
      }
    }

    expect(RPAR, "Expecting ')'", follow);
    myBuilder.restoreNewlinesState();
  }
Beispiel #3
0
  /*
   * initializer
   *   : attributes "this" valueArguments
   *   : attributes constructorInvocation // type parameters may (must?) be omitted
   *   ;
   */
  private void parseInitializer() {
    PsiBuilder.Marker initializer = mark();
    parseAnnotations(false);

    IElementType type;
    if (at(THIS_KEYWORD)) {
      PsiBuilder.Marker mark = mark();
      advance(); // THIS_KEYWORD
      mark.done(THIS_CONSTRUCTOR_REFERENCE);
      type = THIS_CALL;
    } else if (atSet(TYPE_REF_FIRST)) {
      PsiBuilder.Marker reference = mark();
      parseTypeRef();
      reference.done(CONSTRUCTOR_CALLEE);
      type = DELEGATOR_SUPER_CALL;
    } else {
      errorWithRecovery(
          "Expecting constructor call (this(...)) or supertype initializer",
          TokenSet.create(LBRACE, COMMA));
      initializer.drop();
      return;
    }
    myExpressionParsing.parseValueArgumentList();

    initializer.done(type);
  }
Beispiel #4
0
  /*
   * typeConstraint
   *   : attributes SimpleName ":" type
   *   : attributes "class" "object" SimpleName ":" type
   *   ;
   */
  private void parseTypeConstraint() {
    PsiBuilder.Marker constraint = mark();

    parseAnnotations(false);

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

      expect(OBJECT_KEYWORD, "Expecting 'object'", TYPE_REF_FIRST);
    }

    PsiBuilder.Marker reference = mark();
    if (expect(
        IDENTIFIER,
        "Expecting type parameter name",
        TokenSet.orSet(TokenSet.create(COLON, COMMA), TYPE_REF_FIRST))) {
      reference.done(REFERENCE_EXPRESSION);
    } else {
      reference.drop();
    }

    expect(COLON, "Expecting ':' before the upper bound", TYPE_REF_FIRST);

    parseTypeRef();

    constraint.done(TYPE_CONSTRAINT);
  }
Beispiel #5
0
  private PsiBuilder.Marker parseFunctionTypeContents() {
    assert _at(LPAR) : tt();
    PsiBuilder.Marker functionType = mark();

    //        advance(); // LPAR
    //
    //        int lastLPar = findLastBefore(TokenSet.create(LPAR), TokenSet.create(COLON), false);
    //        if (lastLPar >= 0 && lastLPar > myBuilder.getCurrentOffset()) {
    //            TODO : -1 is a hack?
    //            createTruncatedBuilder(lastLPar - 1).parseTypeRef();
    //            advance(); // DOT
    //        }

    parseValueParameterList(true, TokenSet.EMPTY);

    //        if (at(COLON)) {
    //            advance(); // COLON // expect(COLON, "Expecting ':' followed by a return type",
    // TYPE_REF_FIRST);

    expect(ARROW, "Expecting '->' to specify return type of a function type", TYPE_REF_FIRST);
    parseTypeRef();
    //        }

    return functionType; // .done(FUNCTION_TYPE);
  }
Beispiel #6
0
  boolean tryParseTypeArgumentList(TokenSet extraRecoverySet) {
    myBuilder.disableNewlines();
    advance(); // LT

    while (true) {
      PsiBuilder.Marker projection = mark();

      //            TokenSet lookFor = TokenSet.create(IDENTIFIER);
      //            TokenSet stopAt = TokenSet.create(COMMA, COLON, GT);
      //            parseModifierListWithShortAnnotations(MODIFIER_LIST, lookFor, stopAt);
      // Currently we do not allow annotations
      parseModifierList(MODIFIER_LIST, false);

      if (at(MUL)) {
        advance(); // MUL
      } else {
        parseTypeRef(extraRecoverySet);
      }
      projection.done(TYPE_PROJECTION);
      if (!at(COMMA)) break;
      advance(); // COMMA
    }

    boolean atGT = at(GT);
    if (!atGT) {
      error("Expecting a '>'");
    } else {
      advance(); // GT
    }
    myBuilder.restoreNewlinesState();
    return atGT;
  }
Beispiel #7
0
  void parseTypeCodeFragment() {
    PsiBuilder.Marker marker = mark();
    parseTypeRef();

    while (!eof()) {
      error("unexpected symbol");
      advance();
    }

    marker.done(TYPE_CODE_FRAGMENT);
  }
Beispiel #8
0
  /*
   * tupleType
   *   : "#" "(" type{","}? ")"
   *   : "#" "(" parameter{","} ")" // tuple with named entries, the names do not affect assignment compatibility
   *   ;
   */
  @Deprecated // Tuples are dropped, but parsing is left to minimize surprising. This code should be
  // removed some time (in Kotlin 1.0?)
  private void parseTupleType() {
    assert _at(HASH);

    PsiBuilder.Marker tuple = mark();

    myBuilder.disableNewlines();
    advance(); // HASH
    consumeIf(LPAR);

    if (!at(RPAR)) {
      while (true) {
        if (at(COLON)) {
          errorAndAdvance("Expecting a name for tuple entry");
        }

        if (at(IDENTIFIER) && lookahead(1) == COLON) {
          advance(); // IDENTIFIER
          advance(); // COLON
          parseTypeRef();
        } else if (TYPE_REF_FIRST.contains(tt())) {
          parseTypeRef();
        } else {
          error("Type expected");
          break;
        }
        if (!at(COMMA)) break;
        advance(); // COMMA
      }
    }

    consumeIf(RPAR);
    myBuilder.restoreNewlinesState();

    tuple.error("Tuples are not supported. Use data classes instead.");
  }
Beispiel #9
0
  /*
   * typeParameter
   *   : modifiers SimpleName (":" userType)?
   *   ;
   */
  private void parseTypeParameter() {
    if (atSet(TYPE_PARAMETER_GT_RECOVERY_SET)) {
      error("Type parameter declaration expected");
      return;
    }

    PsiBuilder.Marker mark = mark();

    parseModifierListWithShortAnnotations(
        MODIFIER_LIST, TokenSet.create(IDENTIFIER), TokenSet.create(COMMA, GT, COLON));

    expect(IDENTIFIER, "Type parameter name expected", TokenSet.EMPTY);

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

    mark.done(TYPE_PARAMETER);
  }
Beispiel #10
0
  /*
   * attributes delegationSpecifier
   *
   * delegationSpecifier
   *   : constructorInvocation // type and constructor arguments
   *   : userType
   *   : explicitDelegation
   *   ;
   *
   * explicitDelegation
   *   : userType "by" element
   *   ;
   */
  private void parseDelegationSpecifier() {
    PsiBuilder.Marker delegator = mark();
    parseAnnotations(false);

    PsiBuilder.Marker reference = mark();
    parseTypeRef();

    if (at(BY_KEYWORD)) {
      reference.drop();
      advance(); // BY_KEYWORD
      createForByClause(myBuilder).myExpressionParsing.parseExpression();
      delegator.done(DELEGATOR_BY);
    } else if (at(LPAR)) {
      reference.done(CONSTRUCTOR_CALLEE);
      myExpressionParsing.parseValueArgumentList();
      delegator.done(DELEGATOR_SUPER_CALL);
    } else {
      reference.drop();
      delegator.done(DELEGATOR_SUPER_CLASS);
    }
  }
Beispiel #11
0
  /*
   * typedef
   *   : modifiers "type" SimpleName (typeParameters typeConstraints)? "=" type
   *   ;
   */
  JetNodeType parseTypeDef() {
    assert _at(TYPE_KEYWORD);

    advance(); // TYPE_KEYWORD

    expect(
        IDENTIFIER,
        "Type name expected",
        TokenSet.orSet(TokenSet.create(LT, EQ, SEMICOLON), TOPLEVEL_OBJECT_FIRST));

    if (parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET)) {
      parseTypeConstraints();
    }

    expect(EQ, "Expecting '='", TokenSet.orSet(TOPLEVEL_OBJECT_FIRST, TokenSet.create(SEMICOLON)));

    parseTypeRef();

    consumeIf(SEMICOLON);

    return TYPEDEF;
  }
Beispiel #12
0
  /*
   * functionParameters
   *   : "(" functionParameter{","}? ")" // default values
   *   ;
   *
   * functionParameter
   *   : modifiers functionParameterRest
   *   ;
   *
   * functionParameterRest
   *   : parameter ("=" element)?
   *   ;
   */
  void parseValueParameterList(boolean isFunctionTypeContents, TokenSet recoverySet) {
    assert _at(LPAR);
    PsiBuilder.Marker parameters = mark();

    myBuilder.disableNewlines();
    advance(); // LPAR

    if (!parseIdeTemplate()) {
      if (!at(RPAR) && !atSet(recoverySet)) {
        while (true) {
          if (at(COMMA)) {
            errorAndAdvance("Expecting a parameter declaration");
          } else if (at(RPAR)) {
            error("Expecting a parameter declaration");
            break;
          }
          if (isFunctionTypeContents) {
            if (!tryParseValueParameter()) {
              PsiBuilder.Marker valueParameter = mark();
              parseModifierList(MODIFIER_LIST, false); // lazy, out, ref
              parseTypeRef();
              valueParameter.done(VALUE_PARAMETER);
            }
          } else {
            parseValueParameter();
          }
          if (at(COMMA)) {
            advance(); // COMMA
          } else if (!atSet(VALUE_PARAMETER_FIRST)) break;
        }
      }
    }

    expect(RPAR, "Expecting ')'", recoverySet);
    myBuilder.restoreNewlinesState();

    parameters.done(VALUE_PARAMETER_LIST);
  }
Beispiel #13
0
  /*
   * getterOrSetter
   *   : modifiers ("get" | "set")
   *   :
   *        (     "get" "(" ")"
   *           |
   *              "set" "(" modifiers parameter ")"
   *        ) functionBody
   *   ;
   */
  private boolean parsePropertyGetterOrSetter() {
    PsiBuilder.Marker getterOrSetter = mark();

    parseModifierList(MODIFIER_LIST, false);

    if (!at(GET_KEYWORD) && !at(SET_KEYWORD)) {
      getterOrSetter.rollbackTo();
      return false;
    }

    boolean setter = at(SET_KEYWORD);
    advance(); // GET_KEYWORD or SET_KEYWORD

    if (!at(LPAR)) {
      // Account for Jet-114 (val a : int get {...})
      TokenSet ACCESSOR_FIRST_OR_PROPERTY_END =
          TokenSet.orSet(
              MODIFIER_KEYWORDS,
              TokenSet.create(LBRACKET, GET_KEYWORD, SET_KEYWORD, EOL_OR_SEMICOLON, RBRACE));
      if (!atSet(ACCESSOR_FIRST_OR_PROPERTY_END)) {
        errorUntil(
            "Accessor body expected",
            TokenSet.orSet(ACCESSOR_FIRST_OR_PROPERTY_END, TokenSet.create(LBRACE, LPAR, EQ)));
      } else {
        getterOrSetter.done(PROPERTY_ACCESSOR);
        return true;
      }
    }

    myBuilder.disableNewlines();
    expect(LPAR, "Expecting '('", TokenSet.create(RPAR, IDENTIFIER, COLON, LBRACE, EQ));
    if (setter) {
      PsiBuilder.Marker parameterList = mark();
      PsiBuilder.Marker setterParameter = mark();
      parseModifierListWithShortAnnotations(
          MODIFIER_LIST, TokenSet.create(IDENTIFIER), TokenSet.create(RPAR, COMMA, COLON));
      expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(RPAR, COLON, LBRACE, EQ));

      if (at(COLON)) {
        advance(); // COLON
        parseTypeRef();
      }
      setterParameter.done(VALUE_PARAMETER);
      parameterList.done(VALUE_PARAMETER_LIST);
    }
    if (!at(RPAR))
      errorUntil("Expecting ')'", TokenSet.create(RPAR, COLON, LBRACE, EQ, EOL_OR_SEMICOLON));
    expect(RPAR, "Expecting ')'", TokenSet.create(RPAR, COLON, LBRACE, EQ));
    myBuilder.restoreNewlinesState();

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

      parseTypeRef();
    }

    parseFunctionBody();

    getterOrSetter.done(PROPERTY_ACCESSOR);

    return true;
  }
Beispiel #14
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;
  }
Beispiel #15
0
 /*
  * type
  *   : attributes typeDescriptor
  *
  * typeDescriptor
  *   : selfType
  *   : functionType
  *   : userType
  *   : tupleType
  *   : nullableType
  *   ;
  *
  * nullableType
  *   : typeDescriptor "?"
  */
 void parseTypeRef() {
   parseTypeRef(TokenSet.EMPTY);
 }
Beispiel #16
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;
  }