diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index dd1900f8137..408227f6054 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -39,6 +39,8 @@ public interface JetNodeTypes { JetNodeType VALUE_ARGUMENT_LIST = new JetNodeType("VALUE_ARGUMENT_LIST"); JetNodeType VALUE_ARGUMENT = new JetNodeType("VALUE_ARGUMENT"); JetNodeType TYPE_REFERENCE = new JetNodeType("TYPE_REFERENCE"); + JetNodeType LABELED_TUPLE_ENTRY = new JetNodeType("LABELED_TUPLE_ENTRY"); + JetNodeType TUPLE_TYPE = new JetNodeType("TUPLE_TYPE"); IElementType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME"); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index f6e78dde5c1..57142c60668 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -683,16 +683,34 @@ public class JetParsing { list.done(TYPE_ARGUMENT_LIST); } + /* + * tupleType + * : "(" type{","}? ")" + * : "(" parameter{","} ")" // tuple with named entries, the names do not affect assignment compatibility + * ; + */ private void parseTupleType() { assert at(LPAR); + PsiBuilder.Marker tuple = mark(); + advance(); // LPAR if (!at(RPAR)) { while (true) { - if (TokenSet.create(IDENTIFIER, LBRACE, LPAR).contains(tt())) { + if (at(COLON)) errorAndAdvance("Expecting a name for tuple entry"); + + if (at(IDENTIFIER) && lookahead(1) == COLON) { + PsiBuilder.Marker labeledEntry = mark(); + advance(); // IDENTIFIER + advance(); // COLON parseTypeRef(); - } else { + labeledEntry.done(LABELED_TUPLE_ENTRY); + } + else if (TokenSet.create(LBRACKET, IDENTIFIER, LBRACE, LPAR).contains(tt())) { + parseTypeRef(); + } + else { error("Type expected"); break; } @@ -702,6 +720,8 @@ public class JetParsing { } expect(RPAR, "Expecting ')"); + + tuple.done(TUPLE_TYPE); } /* diff --git a/idea/testData/psi/TupleTypes.jet b/idea/testData/psi/TupleTypes.jet new file mode 100644 index 00000000000..98047a6d660 --- /dev/null +++ b/idea/testData/psi/TupleTypes.jet @@ -0,0 +1,10 @@ +class F( + a : (), + x : (X), + b : (A, B), + c : (x : Int, y : Int), + a : [x] (), + x : [x]([x] X), + b : [x] ([x] A, [x]B), + c : [x] (x : [x] Int, y : [x] Int) + ) \ No newline at end of file diff --git a/idea/testData/psi/TupleTypes.txt b/idea/testData/psi/TupleTypes.txt new file mode 100644 index 00000000000..ea78bd7e33d --- /dev/null +++ b/idea/testData/psi/TupleTypes.txt @@ -0,0 +1,227 @@ +JetFile: TupleTypes.jet + NAMESPACE + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('F') + TYPE_PARAMETER_LIST + + PRIMARY_CONSTRUCTOR_PARAMETERS_LIST + PsiElement(LPAR)('(') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('X') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('A') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('B') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('c') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('X') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('A') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + USER_TYPE + PsiElement(IDENTIFIER)('B') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('c') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + TUPLE_TYPE + PsiElement(LPAR)('(') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RPAR)(')') \ No newline at end of file diff --git a/idea/testData/psi/TupleTypes_ERR.jet b/idea/testData/psi/TupleTypes_ERR.jet new file mode 100644 index 00000000000..75924194f84 --- /dev/null +++ b/idea/testData/psi/TupleTypes_ERR.jet @@ -0,0 +1,10 @@ +class F( + a : (), + x : (X), + b : (A, ), + c : (x : , : Int), + a : [x] (), + x : [x]([x X), + b : [x] ([x] A, [x]B), + c : [x] (x : [x] Int, y : [x] Int) + ) \ No newline at end of file diff --git a/idea/testData/psi/TupleTypes_ERR.txt b/idea/testData/psi/TupleTypes_ERR.txt new file mode 100644 index 00000000000..d630176430c --- /dev/null +++ b/idea/testData/psi/TupleTypes_ERR.txt @@ -0,0 +1,225 @@ +JetFile: TupleTypes_ERR.jet + NAMESPACE + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('F') + TYPE_PARAMETER_LIST + + PRIMARY_CONSTRUCTOR_PARAMETERS_LIST + PsiElement(LPAR)('(') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('X') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('A') + PsiElement(COMMA)(',') + PsiErrorElement:Type expected + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('c') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + TUPLE_TYPE + PsiElement(LPAR)('(') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting a name for tuple entry + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + TUPLE_TYPE + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiErrorElement:Expecting ']' to close an attribute annotation + + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('X') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + TUPLE_TYPE + PsiElement(LPAR)('(') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('A') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + USER_TYPE + PsiElement(IDENTIFIER)('B') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR_PARAMETER + PsiElement(IDENTIFIER)('c') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + TUPLE_TYPE + PsiElement(LPAR)('(') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + LABELED_TUPLE_ENTRY + PsiElement(IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + ATTRIBUTE_ANNOTATION + PsiElement(LBRACKET)('[') + ATTRIBUTE + USER_TYPE + USER_TYPE + PsiElement(IDENTIFIER)('x') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + USER_TYPE + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RPAR)(')') \ 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 54485911e95..e8cb4e9ba31 100644 --- a/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java +++ b/idea/tests/org/jetbrains/jet/parsing/JetParsingTest.java @@ -40,4 +40,6 @@ public class JetParsingTest extends ParsingTestCase { public void testTypeDef() throws Exception {doTest(true);} public void testTypeDef_ERR() throws Exception {doTest(true);} public void testTypeAnnotations() throws Exception {doTest(true);} + public void testTupleTypes() throws Exception {doTest(true);} + public void testTupleTypes_ERR() throws Exception {doTest(true);} }