diff --git a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java index 0411936c4ad..847e45ccadb 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java @@ -94,6 +94,28 @@ import static org.jetbrains.jet.lexer.JetTokens.*; return false; } + protected boolean atSet(final TokenSet set) { + IElementType token = tt(); + if (set.contains(token)) return true; + if (set.contains(EOL_OR_SEMICOLON)) { + if (eof()) return true; + if (token == SEMICOLON) return true; + if (myBuilder.eolInLastWhitespace()) return true; + } + if (token == IDENTIFIER) { + for (IElementType type : set.getTypes()) { + if (type instanceof JetKeywordToken) { + JetKeywordToken expectedKeyword = (JetKeywordToken) type; + if (expectedKeyword.isSoft() && expectedKeyword.getValue().equals(myBuilder.getTokenText())) { + myBuilder.remapCurrentToken(type); + return true; + } + } + } + } + return false; + } + protected IElementType lookahead(int k) { PsiBuilder.Marker tmp = mark(); for (int i = 0; i < k; i++) advance(); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index dfe0b5a71a0..b57cabaa690 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -188,7 +188,7 @@ public class JetParsing extends AbstractJetParsing { declType = parseProperty(); } else if (keywordToken == TYPE_KEYWORD) { - declType = parseTypedef(); + declType = parseTypeDef(); } else if (keywordToken == DECOMPOSER_KEYWORD) { declType = parseDecomposer(); @@ -450,7 +450,7 @@ public class JetParsing extends AbstractJetParsing { * : modifiers "type" SimpleName typeParameters? "=" type * ; */ - private JetNodeType parseTypedef() { + private JetNodeType parseTypeDef() { assert at(TYPE_KEYWORD); advance(); // TYPE_KEYWORD @@ -479,32 +479,50 @@ public class JetParsing extends AbstractJetParsing { advance(); // VAL_KEYWORD or VAR_KEYWORD - PsiBuilder.Marker receiverTypeAttributes = mark(); - parseAttributeList(); - TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, EOL_OR_SEMICOLON); - if (at(IDENTIFIER) && propertyNameFollow.contains(lookahead(1))) { // There's no explicit receiver specified - // val [a] name = foo - receiverTypeAttributes.done(RECEIVER_TYPE_ATTRIBUTES); - advance(); // IDENTIFIER + + int lastDot = findLastDotBefore(propertyNameFollow); + + if (lastDot == -1) { + parseAttributeList(); + expect(IDENTIFIER, "Expecting property name or receiver type", propertyNameFollow); } - else { // There must be an explicit receiver - receiverTypeAttributes.rollbackTo(); // Attributes are a part of the receiver type - if (!TYPE_REF_FIRST.contains(tt())) { - errorUntil("Expecting receiver type or property name", propertyNameFollow); - } - else { - // TODO: if this type is annotated with an attribute, and it is a single identifier, - // TODO: it is NOT an error (fun [a] foo()) -- annotation on receiver - parseTypeRef(); - // The property name may appear as the last section of the type - if (at(DOT)) { - advance(); // DOT - expect(IDENTIFIER, "Expecting property name", propertyNameFollow); - } - } + else { + // The code below is NOT REENTRANT + myBuilder.setEOFPosition(lastDot); + parseTypeRef(); + myBuilder.unSetEOFPosition(); + + expect(DOT, "Expecting '.' before a property name", propertyNameFollow); + expect(IDENTIFIER, "Expecting property name", propertyNameFollow); } + +// PsiBuilder.Marker receiverTypeAttributes = mark(); +// parseAttributeList(); +// +// if (at(IDENTIFIER) && propertyNameFollow.contains(lookahead(1))) { // There's no explicit receiver specified +// // val [a] name = foo +// receiverTypeAttributes.done(RECEIVER_TYPE_ATTRIBUTES); +// advance(); // IDENTIFIER +// } +// else { // There must be an explicit receiver +// receiverTypeAttributes.rollbackTo(); // Attributes are a part of the receiver type +// if (!TYPE_REF_FIRST.contains(tt())) { +// errorUntil("Expecting receiver type or property name", propertyNameFollow); +// } +// else { +// // TODO: if this type is annotated with an attribute, and it is a single identifier, +// // TODO: it is NOT an error (fun [a] foo()) -- annotation on receiver +// parseTypeRef(); +// // The property name may appear as the last section of the type +// if (at(DOT)) { +// advance(); // DOT +// expect(IDENTIFIER, "Expecting property name", propertyNameFollow); +// } +// } +// } + if (at(COLON)) { advance(); // COLON parseTypeRef(); @@ -584,7 +602,7 @@ public class JetParsing extends AbstractJetParsing { // TODO: This code is very close to what we have for properties - int lastDot = findLastDotBeforeLPAR(); + int lastDot = findLastDotBefore(TokenSet.create(LPAR)); if (lastDot == -1) { // There's no explicit receiver type specified parseAttributeList(); @@ -598,7 +616,6 @@ public class JetParsing extends AbstractJetParsing { TokenSet functionNameFollow = TokenSet.create(LT, LPAR, COLON, EQ); expect(DOT, "Expecting '.' before a function name", functionNameFollow); expect(IDENTIFIER, "Expecting function name", functionNameFollow); - } // PsiBuilder.Marker receiverTypeAttributes = mark(); @@ -631,6 +648,7 @@ public class JetParsing extends AbstractJetParsing { parseTypeParameterList(TokenSet.orSet(TokenSet.create(LPAR), valueParametersFollow)); + parseValueParameterList(false, valueParametersFollow); if (at(COLON)) { @@ -649,21 +667,26 @@ public class JetParsing extends AbstractJetParsing { } /* - * Looks for a the last top-level (not inside any {} [] () <>) '.' occurring before a top-level '(' + * Looks for a the last top-level (not inside any {} [] () <>) '.' occurring before a + * top-level occurrence of a token from the stopSet */ - private int findLastDotBeforeLPAR() { + private int findLastDotBefore(TokenSet stopSet) { PsiBuilder.Marker currentPosition = mark(); int lastDot = -1; int openAngleBrackets = 0; int openBraces = 0; int openParentheses = 0; int openBrackets = 0; + IElementType previousToken = null; while (!eof()) { - if (at(LPAR)) { + if (atSet(stopSet)) { if (openAngleBrackets == 0 && openBrackets == 0 && openBraces == 0 - && openParentheses == 0) break; + && openParentheses == 0 + && previousToken != DOT) break; + } + if (at(LPAR)) { openParentheses++; } else if (at(LT)) { @@ -694,6 +717,7 @@ public class JetParsing extends AbstractJetParsing { && openParentheses == 0) { lastDot = myBuilder.getCurrentOffset(); } + previousToken = tt(); advance(); // skip token } currentPosition.rollbackTo(); diff --git a/idea/testData/psi/Functions_ERR.jet b/idea/testData/psi/Functions_ERR.jet index a473cb562b8..dc30b5d778e 100644 --- a/idea/testData/psi/Functions_ERR.jet +++ b/idea/testData/psi/Functions_ERR.jet @@ -1,7 +1,5 @@ fun foo) fun [a] f foo() -fun [a] T.foo.() -fun [a] T.{(A) : ()}() fun [a] T.foo(a : ) : bar fun [a()] T.foo(a : foo) : bar fun [a()] T.foo<>(a : foo) : bar @@ -10,3 +8,6 @@ fun [a()] T.foo<, T, , T>(a : foo) : bar fun [a()] T.foo(, a : foo, , a: b) : bar fun foo() : = a; + + +fun [a] T.{(A) : ()}.-() \ No newline at end of file diff --git a/idea/testData/psi/Functions_ERR.txt b/idea/testData/psi/Functions_ERR.txt index 509b2da37f4..c2c810ddf3c 100644 --- a/idea/testData/psi/Functions_ERR.txt +++ b/idea/testData/psi/Functions_ERR.txt @@ -33,84 +33,6 @@ JetFile: Functions_ERR.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiWhiteSpace('\n') - FUN - PsiElement(fun)('fun') - PsiWhiteSpace(' ') - TYPE_REFERENCE - ATTRIBUTE_ANNOTATION - PsiElement(LBRACKET)('[') - ATTRIBUTE - USER_TYPE - USER_TYPE - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACKET)(']') - PsiWhiteSpace(' ') - USER_TYPE - PsiElement(IDENTIFIER)('T') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') - PsiElement(DOT)('.') - PsiErrorElement:Expecting function name - - TYPE_PARAMETER_LIST - - VALUE_PARAMETER_LIST - PsiElement(LPAR)('(') - PsiElement(RPAR)(')') - PsiWhiteSpace('\n') - FUN - PsiElement(fun)('fun') - PsiWhiteSpace(' ') - TYPE_REFERENCE - ATTRIBUTE_ANNOTATION - PsiElement(LBRACKET)('[') - ATTRIBUTE - USER_TYPE - USER_TYPE - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACKET)(']') - PsiWhiteSpace(' ') - USER_TYPE - PsiElement(IDENTIFIER)('T') - TYPE_ARGUMENT_LIST - PsiElement(LT)('<') - TYPE_REFERENCE - USER_TYPE - PsiElement(IDENTIFIER)('T') - PsiElement(GT)('>') - PsiElement(DOT)('.') - PsiErrorElement:Expecting function name - PsiElement(LBRACE)('{') - TYPE_PARAMETER_LIST - - VALUE_PARAMETER_LIST - PsiElement(LPAR)('(') - PsiErrorElement:Expecting a parameter declaration - PsiElement(IDENTIFIER)('A') - PsiErrorElement:Expecting ')' - PsiElement(LT)('<') - PsiErrorElement:Expecting function body - PsiElement(IDENTIFIER)('B') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(GT)('>') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(LPAR)('(') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RPAR)(')') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RBRACE)('}') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(LPAR)('(') - PsiErrorElement:Expecting namespace or top level declaration - PsiElement(RPAR)(')') - PsiWhiteSpace('\n') FUN PsiElement(fun)('fun') PsiWhiteSpace(' ') @@ -431,4 +353,56 @@ JetFile: Functions_ERR.jet PsiElement(EQ)('=') PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('a') - PsiElement(SEMICOLON)(';') \ No newline at end of file + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n\n\n') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('T') + TYPE_ARGUMENT_LIST + PsiElement(LT)('<') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('T') + PsiElement(GT)('>') + PsiElement(DOT)('.') + FUNCTION_TYPE + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('A') + TYPE_ARGUMENT_LIST + PsiElement(LT)('<') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('B') + PsiElement(GT)('>') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(RBRACE)('}') + PsiElement(DOT)('.') + PsiErrorElement:Expecting function name + PsiElement(MINUS)('-') + TYPE_PARAMETER_LIST + + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') \ No newline at end of file diff --git a/idea/testData/psi/Properties.txt b/idea/testData/psi/Properties.txt index 567c075c47c..e73bf798543 100644 --- a/idea/testData/psi/Properties.txt +++ b/idea/testData/psi/Properties.txt @@ -3,24 +3,20 @@ JetFile: Properties.jet PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - TYPE_REFERENCE - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace('\n ') PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - TYPE_REFERENCE - ATTRIBUTE_ANNOTATION - PsiElement(LBRACKET)('[') - ATTRIBUTE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE USER_TYPE - USER_TYPE - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACKET)(']') - PsiWhiteSpace(' ') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace('\n ') PROPERTY PsiElement(val)('val') @@ -28,9 +24,8 @@ JetFile: Properties.jet TYPE_REFERENCE USER_TYPE PsiElement(IDENTIFIER)('foo') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('bar') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('bar') PsiWhiteSpace('\n ') PROPERTY PsiElement(val)('val') @@ -55,15 +50,12 @@ JetFile: Properties.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace('\n\n ') PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - RECEIVER_TYPE_ATTRIBUTES - PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(COLON)(':') @@ -75,14 +67,13 @@ JetFile: Properties.jet PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - RECEIVER_TYPE_ATTRIBUTES - ATTRIBUTE_ANNOTATION - PsiElement(LBRACKET)('[') - ATTRIBUTE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE USER_TYPE - USER_TYPE - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACKET)(']') + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') @@ -96,9 +87,8 @@ JetFile: Properties.jet TYPE_REFERENCE USER_TYPE PsiElement(IDENTIFIER)('foo') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('bar') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('bar') PsiWhiteSpace(' ') PsiElement(LBRACE)('{') PsiWhiteSpace('\n ') @@ -146,9 +136,8 @@ JetFile: Properties.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(EQ)('=') PsiWhiteSpace(' ') @@ -199,9 +188,8 @@ JetFile: Properties.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(COLON)(':') PsiWhiteSpace(' ') @@ -280,9 +268,8 @@ JetFile: Properties.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(COLON)(':') PsiWhiteSpace(' ') @@ -341,9 +328,8 @@ JetFile: Properties.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(COLON)(':') PsiWhiteSpace(' ') diff --git a/idea/testData/psi/Properties_ERR.jet b/idea/testData/psi/Properties_ERR.jet index 89253464d48..b6218534c94 100644 --- a/idea/testData/psi/Properties_ERR.jet +++ b/idea/testData/psi/Properties_ERR.jet @@ -1,6 +1,6 @@ -var - f = s -var - f {} -var - f : +var - {} +var f {} +var f : val foo : val [a foo = foo val foo.bar. diff --git a/idea/testData/psi/Properties_ERR.txt b/idea/testData/psi/Properties_ERR.txt index 26db2f39ed4..e4a042d9587 100644 --- a/idea/testData/psi/Properties_ERR.txt +++ b/idea/testData/psi/Properties_ERR.txt @@ -3,22 +3,8 @@ JetFile: Properties_ERR.jet PROPERTY PsiElement(var)('var') PsiWhiteSpace(' ') - PsiErrorElement:Expecting receiver type or property name + PsiErrorElement:Expecting property name or receiver type PsiElement(MINUS)('-') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('f') - PsiWhiteSpace(' ') - PsiElement(EQ)('=') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('s') - PsiWhiteSpace('\n') - PROPERTY - PsiElement(var)('var') - PsiWhiteSpace(' ') - PsiErrorElement:Expecting receiver type or property name - PsiElement(MINUS)('-') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('f') PsiWhiteSpace(' ') PsiElement(LBRACE)('{') PsiErrorElement:Expecting a getter and/or setter @@ -28,10 +14,17 @@ JetFile: Properties_ERR.jet PROPERTY PsiElement(var)('var') PsiWhiteSpace(' ') - PsiErrorElement:Expecting receiver type or property name - PsiElement(MINUS)('-') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('f') + PsiElement(IDENTIFIER)('f') + PsiWhiteSpace(' ') + PsiElement(LBRACE)('{') + PsiErrorElement:Expecting a getter and/or setter + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PROPERTY + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') PsiWhiteSpace(' ') PsiElement(COLON)(':') PsiWhiteSpace('\n') @@ -41,8 +34,6 @@ JetFile: Properties_ERR.jet PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - RECEIVER_TYPE_ATTRIBUTES - PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(COLON)(':') @@ -53,15 +44,14 @@ JetFile: Properties_ERR.jet PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - RECEIVER_TYPE_ATTRIBUTES - ATTRIBUTE_ANNOTATION - PsiElement(LBRACKET)('[') - ATTRIBUTE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE USER_TYPE - USER_TYPE - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ']' to close an attribute annotation - + PsiElement(IDENTIFIER)('a') + PsiErrorElement:Expecting ']' to close an attribute annotation + PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') @@ -85,14 +75,13 @@ JetFile: Properties_ERR.jet PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - RECEIVER_TYPE_ATTRIBUTES - ATTRIBUTE_ANNOTATION - PsiElement(LBRACKET)('[') - ATTRIBUTE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE USER_TYPE - USER_TYPE - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACKET)(']') + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') @@ -111,9 +100,8 @@ JetFile: Properties_ERR.jet TYPE_REFERENCE USER_TYPE PsiElement(IDENTIFIER)('foo') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('bar') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('bar') PsiWhiteSpace(' ') PsiElement(LBRACE)('{') PsiWhiteSpace('\n ') @@ -166,9 +154,8 @@ JetFile: Properties_ERR.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(EQ)('=') PsiWhiteSpace(' ') @@ -221,9 +208,8 @@ JetFile: Properties_ERR.jet PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiElement(RBRACE)('}') - PsiElement(DOT)('.') - USER_TYPE - PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(EQ)('=') PsiWhiteSpace(' ') @@ -282,8 +268,6 @@ JetFile: Properties_ERR.jet PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') - RECEIVER_TYPE_ATTRIBUTES - PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(LBRACE)('{')