diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java index 198e05caf25..9f437e7364a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java @@ -438,9 +438,8 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker list = mark(); boolean empty = true; while (!eof()) { - if (annotationParsingMode.atMemberStart && atSet(SOFT_KEYWORDS_AT_MEMBER_START)) { - break; - } + if (annotationParsingMode.atMemberStart && atSet(SOFT_KEYWORDS_AT_MEMBER_START)) break; + if (annotationParsingMode == PRIMARY_CONSTRUCTOR_MODIFIER_LIST && atSet(CONSTRUCTOR_KEYWORD, WHERE_KEYWORD)) break; if (at(AT)) { IElementType strictlyNextToken = myBuilder.rawLookup(1); @@ -689,7 +688,7 @@ public class JetParsing extends AbstractJetParsing { boolean hasConstructorModifiers = parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST); // Some modifiers found, but no parentheses following: class has already ended, and we are looking at something else - if (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON)) { + if ((object && at(CONSTRUCTOR_KEYWORD)) || (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD))) { beforeConstructorModifiers.rollbackTo(); constructorModifiersMarker.drop(); return object ? OBJECT_DECLARATION : CLASS; @@ -698,17 +697,27 @@ public class JetParsing extends AbstractJetParsing { // We are still inside a class declaration beforeConstructorModifiers.drop(); + boolean hasConstructorKeyword = at(CONSTRUCTOR_KEYWORD); + if (hasConstructorKeyword) { + advance(); // CONSTRUCTOR_KEYWORD + } + if (at(LPAR)) { parseValueParameterList(false, /* typeRequired = */ true, TokenSet.create(LBRACE, RBRACE)); primaryConstructorMarker.done(PRIMARY_CONSTRUCTOR); } - else if (hasConstructorModifiers) { + else if (hasConstructorModifiers || hasConstructorKeyword) { // A comprehensive error message for cases like: // class A private : Foo // or // class A private { primaryConstructorMarker.done(PRIMARY_CONSTRUCTOR); - error("Expecting primary constructor parameter list"); + if (hasConstructorKeyword) { + error("Expecting primary constructor parameter list"); + } + else { + error("Expecting 'constructor' keyword"); + } } else { primaryConstructorMarker.drop(); @@ -2246,7 +2255,7 @@ public class JetParsing extends AbstractJetParsing { ONLY_ESCAPED_REGULAR_ANNOTATIONS(false, false, false, true), ALLOW_UNESCAPED_REGULAR_ANNOTATIONS(true, false, false, true), ALLOW_UNESCAPED_REGULAR_ANNOTATIONS_AT_MEMBER_MODIFIER_LIST(true, false, true, true), - PRIMARY_CONSTRUCTOR_MODIFIER_LIST(false, false, false, false); + PRIMARY_CONSTRUCTOR_MODIFIER_LIST(true, false, false, true); boolean allowShortAnnotations; boolean isFileAnnotationParsingMode; diff --git a/compiler/testData/psi/PrimaryConstructorModifiers_ERR.txt b/compiler/testData/psi/PrimaryConstructorModifiers_ERR.txt index d626f3c5cd4..1042580c94b 100644 --- a/compiler/testData/psi/PrimaryConstructorModifiers_ERR.txt +++ b/compiler/testData/psi/PrimaryConstructorModifiers_ERR.txt @@ -20,7 +20,7 @@ JetFile: PrimaryConstructorModifiers_ERR.kt PRIMARY_CONSTRUCTOR MODIFIER_LIST PsiElement(private)('private') - PsiErrorElement:Expecting primary constructor parameter list + PsiErrorElement:Expecting 'constructor' keyword PsiWhiteSpace(' ') CLASS_BODY diff --git a/compiler/testData/psi/annotation/at/primaryConstructor.txt b/compiler/testData/psi/annotation/at/primaryConstructor.txt index 00c975f52b8..a1fd9cb89ac 100644 --- a/compiler/testData/psi/annotation/at/primaryConstructor.txt +++ b/compiler/testData/psi/annotation/at/primaryConstructor.txt @@ -8,9 +8,8 @@ JetFile: primaryConstructor.kt PsiWhiteSpace(' ') PRIMARY_CONSTRUCTOR MODIFIER_LIST - PsiErrorElement:Only annotations in '[]' can be declared here - PsiElement(AT)('@') ANNOTATION_ENTRY + PsiElement(AT)('@') CONSTRUCTOR_CALLEE TYPE_REFERENCE USER_TYPE @@ -35,9 +34,8 @@ JetFile: primaryConstructor.kt PsiWhiteSpace(' ') PRIMARY_CONSTRUCTOR MODIFIER_LIST - PsiErrorElement:Only annotations in '[]' can be declared here - PsiElement(AT)('@') ANNOTATION_ENTRY + PsiElement(AT)('@') CONSTRUCTOR_CALLEE TYPE_REFERENCE USER_TYPE @@ -126,9 +124,7 @@ JetFile: primaryConstructor.kt PsiElement(IDENTIFIER)('Ann4') PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') - PsiErrorElement:Only annotations in '[]' can be declared here - PsiElement(AT)('@') - PsiElement(private)('private') + PsiElement(private)('@private') PsiWhiteSpace(' ') PsiErrorElement:Expected modifier or annotation after '@' PsiElement(AT)('@') @@ -153,9 +149,8 @@ JetFile: primaryConstructor.kt MODIFIER_LIST PsiElement(private)('private') PsiWhiteSpace(' ') - PsiErrorElement:Only annotations in '[]' can be declared here - PsiElement(AT)('@') ANNOTATION_ENTRY + PsiElement(AT)('@') CONSTRUCTOR_CALLEE TYPE_REFERENCE USER_TYPE @@ -175,7 +170,7 @@ JetFile: primaryConstructor.kt REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('Int') PsiElement(RPAR)(')') - PsiErrorElement:Expecting primary constructor parameter list + PsiErrorElement:Expecting 'constructor' keyword PsiWhiteSpace(' ') PsiElement(COLON)(':') @@ -204,9 +199,7 @@ JetFile: primaryConstructor.kt PsiElement(IDENTIFIER)('Ann5') PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') - PsiErrorElement:Only annotations in '[]' can be declared here - PsiElement(AT)('@') - PsiElement(private)('private') + PsiElement(private)('@private') PsiWhiteSpace(' ') PsiErrorElement:Expected modifier or annotation after '@' PsiElement(AT)('@') diff --git a/compiler/testData/psi/primaryConstructor/local.kt b/compiler/testData/psi/primaryConstructor/local.kt new file mode 100644 index 00000000000..ac8a8f54523 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/local.kt @@ -0,0 +1,4 @@ +fun foo() { + class A1 constructor() + class A2 Ann private constructor() +} diff --git a/compiler/testData/psi/primaryConstructor/local.txt b/compiler/testData/psi/primaryConstructor/local.txt new file mode 100644 index 00000000000..ea17423ede4 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/local.txt @@ -0,0 +1,47 @@ +JetFile: local.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A1') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A2') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.kt b/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.kt new file mode 100644 index 00000000000..de558f3bce0 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.kt @@ -0,0 +1,28 @@ +class Outer1 { + class Nested1 + + private Ann constructor() +} + +class Outer2 { + class Nested2; + + private Ann constructor() +} + +class Outer3 { + class Nested3 + + private Ann constructor() : super() {} +} + +class Outer4 { + object Nested4 + constructor() {} + + object Nested5 private constructor() : super() {} +} + +object TopLevel constructor(val x: Int) { + fun foo() {} +} diff --git a/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt b/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt new file mode 100644 index 00000000000..909b8d42891 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt @@ -0,0 +1,232 @@ +JetFile: nestedClassAmbiguity.kt + PACKAGE_DIRECTIVE + + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer1') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested1') + PsiWhiteSpace('\n\n ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer2') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested2') + PsiElement(SEMICOLON)(';') + PsiWhiteSpace('\n\n ') + SECONDARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + CONSTRUCTOR_DELEGATION_CALL + CONSTRUCTOR_DELEGATION_REFERENCE + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer3') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested3') + PsiWhiteSpace('\n\n ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CALL + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + PsiErrorElement:Type expected + PsiElement(super)('super') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer4') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + OBJECT_DECLARATION + PsiElement(object)('object') + PsiWhiteSpace(' ') + OBJECT_DECLARATION_NAME + PsiElement(IDENTIFIER)('Nested4') + PsiWhiteSpace('\n ') + SECONDARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CONSTRUCTOR_DELEGATION_CALL + CONSTRUCTOR_DELEGATION_REFERENCE + + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + OBJECT_DECLARATION + PsiElement(object)('object') + PsiWhiteSpace(' ') + OBJECT_DECLARATION_NAME + PsiElement(IDENTIFIER)('Nested5') + PsiWhiteSpace(' ') + SECONDARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + CONSTRUCTOR_DELEGATION_CALL + CONSTRUCTOR_DELEGATION_REFERENCE + PsiElement(super)('super') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + OBJECT_DECLARATION + PsiElement(object)('object') + PsiWhiteSpace(' ') + OBJECT_DECLARATION_NAME + PsiElement(IDENTIFIER)('TopLevel') + PsiWhiteSpace(' ') + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('constructor') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + PsiErrorElement:Expecting an expression + + PsiErrorElement:Expecting ')' + PsiElement(val)('val') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiErrorElement:Expecting a top level declaration + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiErrorElement:Expecting a top level declaration + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + FUN + PsiErrorElement:Expecting a top level declaration + + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/primaryConstructor/recovery.kt b/compiler/testData/psi/primaryConstructor/recovery.kt new file mode 100644 index 00000000000..ca24cc1681a --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/recovery.kt @@ -0,0 +1,18 @@ +class A0 @Ann (x: Int) { + val x = 1 +} + +class A1 Ann : Base() + +class A2 Ann + +class A3 Ann { + fun foo() +} + +class A4 constructor {} +class A5 constructor : Base {} + +class A7 Ann(1) (x: Int) +class A8 Ann() {} +class A9 Ann() : Base() diff --git a/compiler/testData/psi/primaryConstructor/recovery.txt b/compiler/testData/psi/primaryConstructor/recovery.txt new file mode 100644 index 00000000000..331461d40f6 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/recovery.txt @@ -0,0 +1,244 @@ +JetFile: recovery.kt + PACKAGE_DIRECTIVE + + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A0') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + BINARY_WITH_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + OPERATION_REFERENCE + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A1') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CALL + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Base') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A2') + PsiWhiteSpace(' ') + CLASS + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace('\n\n') + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A3') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A4') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + PsiErrorElement:Expecting primary constructor parameter list + + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A5') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + PsiErrorElement:Expecting primary constructor parameter list + + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CLASS + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Base') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A7') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A8') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A9') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CALL + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Base') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') \ No newline at end of file diff --git a/compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.kt b/compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.kt new file mode 100644 index 00000000000..108dc4ef9c8 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.kt @@ -0,0 +1,25 @@ +class Outer1 { + class Nested1 + + private Ann () +} + +class Outer2 { + class Nested2 private Ann + fun foo() {} +} + +class Outer3 { + class Nested3 private Ann {} + fun foo() +} + +class Outer4 { + class Nested3 private Ann() {} + fun foo() +} + +class Outer4 { + class Nested3 private Ann() : Base() + fun foo() +} diff --git a/compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.txt b/compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.txt new file mode 100644 index 00000000000..c469e786506 --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.txt @@ -0,0 +1,205 @@ +JetFile: recoveryNestedClassAmbiguity.kt + PACKAGE_DIRECTIVE + + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer1') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested1') + PsiWhiteSpace('\n\n ') + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting member declaration + + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer2') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested2') + PsiWhiteSpace(' ') + FUN + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace('\n ') + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer3') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested3') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer4') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested3') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Outer4') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('Nested3') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'constructor' keyword + + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CALL + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Base') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/primaryConstructor/valid.kt b/compiler/testData/psi/primaryConstructor/valid.kt new file mode 100644 index 00000000000..3e49a64739b --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/valid.kt @@ -0,0 +1,13 @@ +class A0 +constructor() {} +class A1 +private constructor(y: Int) : Base1(), Base2 { + val x: Int +} +class A2 @private constructor(y: Int) + +class A3 Ann(1) private constructor(y: Int) + +class A4 private Ann(1) constructor(y: Int) + +class A5 @Ann private constructor() {} diff --git a/compiler/testData/psi/primaryConstructor/valid.txt b/compiler/testData/psi/primaryConstructor/valid.txt new file mode 100644 index 00000000000..7cd6af7765a --- /dev/null +++ b/compiler/testData/psi/primaryConstructor/valid.txt @@ -0,0 +1,193 @@ +JetFile: valid.kt + PACKAGE_DIRECTIVE + + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A0') + PsiWhiteSpace('\n') + PRIMARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A1') + PsiWhiteSpace('\n') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('y') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATOR_SUPER_CALL + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Base1') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DELEGATOR_SUPER_CLASS + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Base2') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A2') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('@private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('y') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A3') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('y') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A4') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('y') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A5') + PsiWhiteSpace(' ') + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Ann') + PsiWhiteSpace(' ') + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java index cc0f709acc2..9d3d2f12348 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java @@ -1531,6 +1531,45 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { } } + @TestMetadata("compiler/testData/psi/primaryConstructor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PrimaryConstructor extends AbstractJetParsingTest { + public void testAllFilesPresentInPrimaryConstructor() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/primaryConstructor"), Pattern.compile("^(.*)\\.kts?$"), true); + } + + @TestMetadata("local.kt") + public void testLocal() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/primaryConstructor/local.kt"); + doParsingTest(fileName); + } + + @TestMetadata("nestedClassAmbiguity.kt") + public void testNestedClassAmbiguity() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.kt"); + doParsingTest(fileName); + } + + @TestMetadata("recovery.kt") + public void testRecovery() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/primaryConstructor/recovery.kt"); + doParsingTest(fileName); + } + + @TestMetadata("recoveryNestedClassAmbiguity.kt") + public void testRecoveryNestedClassAmbiguity() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/primaryConstructor/recoveryNestedClassAmbiguity.kt"); + doParsingTest(fileName); + } + + @TestMetadata("valid.kt") + public void testValid() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/primaryConstructor/valid.kt"); + doParsingTest(fileName); + } + } + @TestMetadata("compiler/testData/psi/propertyDelegate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/grammar/src/class.grm b/grammar/src/class.grm index b1b5e2fd040..bc8b7cd6e30 100644 --- a/grammar/src/class.grm +++ b/grammar/src/class.grm @@ -17,7 +17,7 @@ internal class Example>(protected val x : Foo, y : So class : modifiers ("class" | "trait") SimpleName typeParameters? - modifiers ("(" functionParameter{","} ")")? + (modifiers "constructor")? ("(" functionParameter{","} ")")? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody)