From 9c574469ca25b53a6e412adb0330d94766b7023c Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 29 May 2015 18:38:01 +0300 Subject: [PATCH] Parsing: allow primary ctor in object syntactically It's needed for better recovering for cases of changes like 'class' -> 'object' The only sensible case when it's may be bad: class A { object B constructor() : super() } But it seems to be rare, and ';' can be used to separate object from secondary ctor --- .../jetbrains/kotlin/parsing/JetParsing.java | 10 +- .../psi/annotation/at/validDeclarations.kt | 2 +- .../psi/annotation/at/validDeclarations.txt | 1 + .../nestedClassAmbiguity.txt | 107 +++++++----------- grammar/src/class.grm | 5 +- grammar/src/class_members.grm | 2 +- 6 files changed, 57 insertions(+), 70 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java index 2b851f64d5a..ceb81b4f45a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParsing.java @@ -705,14 +705,18 @@ public class JetParsing extends AbstractJetParsing { * class * : modifiers ("class" | "interface") SimpleName * typeParameters? - * modifiers ("(" primaryConstructorParameter{","} ")")? + * primaryConstructor? * (":" annotations delegationSpecifier{","})? * typeConstraints * (classBody? | enumClassBody) * ; * + * primaryConstructor + * : (modifiers "constructor")? ("(" functionParameter{","} ")") + * ; + * * object - * : "object" SimpleName? ":" delegationSpecifier{","}? classBody? + * : "object" SimpleName? primaryConstructor? ":" delegationSpecifier{","}? classBody? * ; */ IElementType parseClassOrObject( @@ -761,7 +765,7 @@ public class JetParsing extends AbstractJetParsing { ); // Some modifiers found, but no parentheses following: class has already ended, and we are looking at something else - if ((object && at(CONSTRUCTOR_KEYWORD)) || (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD))) { + if (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD)) { beforeConstructorModifiers.rollbackTo(); return object ? OBJECT_DECLARATION : CLASS; } diff --git a/compiler/testData/psi/annotation/at/validDeclarations.kt b/compiler/testData/psi/annotation/at/validDeclarations.kt index 053d7320972..d0da076a65d 100644 --- a/compiler/testData/psi/annotation/at/validDeclarations.kt +++ b/compiler/testData/psi/annotation/at/validDeclarations.kt @@ -28,7 +28,7 @@ private @open [Ann1(1)] @Ann2("1") Ann3("2") class A( @companion object - @companion @private object B + @companion @private object B; @main diff --git a/compiler/testData/psi/annotation/at/validDeclarations.txt b/compiler/testData/psi/annotation/at/validDeclarations.txt index 69ffb693585..740f0f90789 100644 --- a/compiler/testData/psi/annotation/at/validDeclarations.txt +++ b/compiler/testData/psi/annotation/at/validDeclarations.txt @@ -419,6 +419,7 @@ JetFile: validDeclarations.kt PsiWhiteSpace(' ') OBJECT_DECLARATION_NAME PsiElement(IDENTIFIER)('B') + PsiElement(SEMICOLON)(';') PsiWhiteSpace('\n\n ') SECONDARY_CONSTRUCTOR MODIFIER_LIST diff --git a/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt b/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt index 909b8d42891..b1e4cadb45d 100644 --- a/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt +++ b/compiler/testData/psi/primaryConstructor/nestedClassAmbiguity.txt @@ -127,17 +127,14 @@ JetFile: nestedClassAmbiguity.kt PsiWhiteSpace(' ') OBJECT_DECLARATION_NAME PsiElement(IDENTIFIER)('Nested4') - PsiWhiteSpace('\n ') - SECONDARY_CONSTRUCTOR - PsiElement(constructor)('constructor') - VALUE_PARAMETER_LIST - PsiElement(LPAR)('(') - PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PRIMARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') PsiWhiteSpace(' ') - CONSTRUCTOR_DELEGATION_CALL - CONSTRUCTOR_DELEGATION_REFERENCE - - BLOCK + CLASS_BODY PsiElement(LBRACE)('{') PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n ') @@ -146,26 +143,29 @@ JetFile: nestedClassAmbiguity.kt 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 + PRIMARY_CONSTRUCTOR + MODIFIER_LIST + PsiElement(private)('private') + PsiWhiteSpace(' ') + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST PsiElement(LPAR)('(') PsiElement(RPAR)(')') PsiWhiteSpace(' ') - BLOCK + 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') @@ -176,45 +176,24 @@ JetFile: nestedClassAmbiguity.kt 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 + PRIMARY_CONSTRUCTOR + PsiElement(constructor)('constructor') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY PsiElement(LBRACE)('{') PsiWhiteSpace('\n ') FUN diff --git a/grammar/src/class.grm b/grammar/src/class.grm index bc8b7cd6e30..4b161ccacc6 100644 --- a/grammar/src/class.grm +++ b/grammar/src/class.grm @@ -17,12 +17,15 @@ internal class Example>(protected val x : Foo, y : So class : modifiers ("class" | "trait") SimpleName typeParameters? - (modifiers "constructor")? ("(" functionParameter{","} ")")? + primaryConstructor? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody) ; +primaryConstructor + : (modifiers "constructor")? ("(" functionParameter{","} ")") + ; classBody : ("{" members "}")? diff --git a/grammar/src/class_members.grm b/grammar/src/class_members.grm index a48a283e2e0..11b71e86fed 100644 --- a/grammar/src/class_members.grm +++ b/grammar/src/class_members.grm @@ -111,7 +111,7 @@ parameter ; object - : "object" SimpleName (":" delegationSpecifier{","})? classBody? // Class body can be optional: this is a declaration + : "object" SimpleName primaryConstructor? (":" delegationSpecifier{","})? classBody? // Class body can be optional: this is a declaration secondaryConstructor : modifiers "constructor" valueParameters (":" constructorDelegationCall)? block