diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index b57cabaa690..cc5a260df7f 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -497,32 +497,6 @@ public class JetParsing extends AbstractJetParsing { 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(); @@ -618,32 +592,6 @@ public class JetParsing extends AbstractJetParsing { expect(IDENTIFIER, "Expecting function name", functionNameFollow); } -// PsiBuilder.Marker receiverTypeAttributes = mark(); -// -// parseAttributeList(); -// -// if (at(IDENTIFIER) && lookahead(1) == LPAR) { // There's no explicit receiver specified -// // fun [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", TokenSet.create(LPAR, EOL_OR_SEMICOLON)); -// } -// 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", TokenSet.create(LPAR)); -// } -// } -// } - TokenSet valueParametersFollow = TokenSet.create(COLON, EQ, LBRACE, SEMICOLON, RPAR); parseTypeParameterList(TokenSet.orSet(TokenSet.create(LPAR), valueParametersFollow)); @@ -768,7 +716,25 @@ public class JetParsing extends AbstractJetParsing { * ; */ private JetNodeType parseExtension() { - advance(); // TODO + assert at(EXTENSION_KEYWORD); + + advance(); // EXTENSION_KEYWORD + + consumeIf(IDENTIFIER); + + parseTypeParameterList(TokenSet.create(FOR_KEYWORD, LBRACE)); + + expect(FOR_KEYWORD, "Expecting 'for' to specify the type that is being extended", TYPE_REF_FIRST); + + parseTypeRef(); + + if (at(LBRACE)) { + parseClassBody(); + } + else { + consumeIf(SEMICOLON); + } + return EXTENSION; } diff --git a/idea/testData/psi/Extensions.jet b/idea/testData/psi/Extensions.jet new file mode 100644 index 00000000000..48a118942d9 --- /dev/null +++ b/idea/testData/psi/Extensions.jet @@ -0,0 +1,17 @@ +extension for bar +extension foo for bar +extension for bar +extension foo for bar +extension foo for {() : ()} + +extension for bar; +extension foo for bar; +extension for bar; +extension foo for bar; +extension foo for {() : ()}; + +extension for bar {} +extension foo for bar {} +extension for bar {} +extension foo for bar {} +extension foo for {() : ()} {} \ No newline at end of file diff --git a/idea/testData/psi/Extensions.txt b/idea/testData/psi/Extensions.txt new file mode 100644 index 00000000000..67ed4e4e7f0 --- /dev/null +++ b/idea/testData/psi/Extensions.txt @@ -0,0 +1,272 @@ +JetFile: Extensions.jet + NAMESPACE + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('foo') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('foo') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(RBRACE)('}') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('foo') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/idea/testData/psi/Extensions_ERR.jet b/idea/testData/psi/Extensions_ERR.jet new file mode 100644 index 00000000000..eeeb7e25139 --- /dev/null +++ b/idea/testData/psi/Extensions_ERR.jet @@ -0,0 +1,5 @@ +extension for +extension foo bar +extension for +extension foo for {() : ()} {} \ No newline at end of file diff --git a/idea/testData/psi/Extensions_ERR.txt b/idea/testData/psi/Extensions_ERR.txt new file mode 100644 index 00000000000..f33bb7b9f85 --- /dev/null +++ b/idea/testData/psi/Extensions_ERR.txt @@ -0,0 +1,86 @@ +JetFile: Extensions_ERR.jet + NAMESPACE + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(for)('for') + PsiWhiteSpace('\n') + TYPE_REFERENCE + PsiErrorElement:Type expected + + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiErrorElement:Expecting 'for' to specify the type that is being extended + + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('foo') + PsiErrorElement:Missing '>' + + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace('\n') + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace('\n') + TYPE_REFERENCE + PsiErrorElement:Type expected + + EXTENSION + PsiElement(extension)('extension') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + TYPE_PARAMETER_LIST + PsiElement(LT)('<') + TYPE_PARAMETER + PsiElement(IDENTIFIER)('A') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(for)('for') + PsiWhiteSpace(' ') + TYPE_REFERENCE + FUNCTION_TYPE + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java b/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java index ffbda54f452..8ca0ff27999 100644 --- a/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java +++ b/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java @@ -50,4 +50,6 @@ public class JetParsingTest extends ParsingTestCase { public void testProperties_ERR() throws Exception {doTest(true);} public void testFunctions() throws Exception {doTest(true);} public void testFunctions_ERR() throws Exception {doTest(true);} + public void testExtensions() throws Exception {doTest(true);} + public void testExtensions_ERR() throws Exception {doTest(true);} }