// The extraRecoverySet is needed for the foo(bar<x, 1, y>(z)) case, to tell whether we should // stop // on expression-indicating symbols or not private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet) { // Disabling token merge is required for cases like // Int?.(Foo) -> Bar // we don't support this case now // myBuilder.disableJoiningComplexTokens(); PsiBuilder.Marker typeRefMarker = mark(); parseAnnotations(false); if (at(IDENTIFIER) || at(PACKAGE_KEYWORD)) { parseUserType(); } else if (at(HASH)) { parseTupleType(); } else if (at(LPAR)) { PsiBuilder.Marker functionOrParenthesizedType = mark(); // This may be a function parameter list or just a prenthesized type advance(); // LPAR parseTypeRefContents(TokenSet.EMPTY) .drop(); // parenthesized types, no reference element around it is needed if (at(RPAR)) { advance(); // RPAR if (at(ARROW)) { // It's a function type with one parameter specified // (A) -> B functionOrParenthesizedType.rollbackTo(); parseFunctionType(); } else { // It's a parenthesized type // (A) functionOrParenthesizedType.drop(); } } else { // This must be a function type // (A, B) -> C // or // (a : A) -> C functionOrParenthesizedType.rollbackTo(); parseFunctionType(); } } else if (at(CAPITALIZED_THIS_KEYWORD)) { parseSelfType(); } else { errorWithRecovery( "Type expected", TokenSet.orSet( TOPLEVEL_OBJECT_FIRST, TokenSet.create(EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON), extraRecoverySet)); } while (at(QUEST)) { PsiBuilder.Marker precede = typeRefMarker.precede(); advance(); // QUEST typeRefMarker.done(NULLABLE_TYPE); typeRefMarker = precede; } if (at(DOT)) { // This is a receiver for a function type // A.(B) -> C // ^ PsiBuilder.Marker functionType = typeRefMarker.precede(); PsiBuilder.Marker receiverType = typeRefMarker.precede(); typeRefMarker.done(TYPE_REFERENCE); receiverType.done(FUNCTION_TYPE_RECEIVER); advance(); // DOT if (at(LPAR)) { parseFunctionTypeContents().drop(); } else { error("Expecting function type"); } typeRefMarker = functionType.precede(); functionType.done(FUNCTION_TYPE); } // myBuilder.restoreJoiningComplexTokensState(); return typeRefMarker; }