/* * 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; }
/* * (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(); }
/* * 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); }
/* * 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); }
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); }
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; }
void parseTypeCodeFragment() { PsiBuilder.Marker marker = mark(); parseTypeRef(); while (!eof()) { error("unexpected symbol"); advance(); } marker.done(TYPE_CODE_FRAGMENT); }
/* * 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."); }
/* * 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); }
/* * 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); } }
/* * 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; }
/* * 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); }
/* * 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; }
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; }
/* * type * : attributes typeDescriptor * * typeDescriptor * : selfType * : functionType * : userType * : tupleType * : nullableType * ; * * nullableType * : typeDescriptor "?" */ void parseTypeRef() { parseTypeRef(TokenSet.EMPTY); }
/* * 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; }