Generate constructors with empty bodies for annotation classes

Default parameter values of primary constructor of an annotation class
are required to generate default values of annotation properties.
This commit is contained in:
Dmitry Petrov
2018-04-03 13:01:46 +03:00
parent e74c448c0a
commit 4016254fd4
6 changed files with 143 additions and 10 deletions
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -286,14 +285,11 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
val classDescriptor = irClass.descriptor
val primaryConstructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor ?: return null
val irPrimaryConstructor =
FunctionGenerator(declarationGenerator).generatePrimaryConstructor(primaryConstructorDescriptor, ktClassOrObject)
if (!DescriptorUtils.isAnnotationClass(classDescriptor)) {
irClass.addMember(irPrimaryConstructor)
}
return irPrimaryConstructor
return FunctionGenerator(declarationGenerator)
.generatePrimaryConstructor(primaryConstructorDescriptor, ktClassOrObject)
.also {
irClass.addMember(it)
}
}
private fun generateDeclarationsForPrimaryConstructorParameters(
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper
import org.jetbrains.kotlin.psi2ir.startOffsetOrUndefined
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
class FunctionGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
constructor(context: GeneratorContext) : this(DeclarationGenerator(context))
@@ -198,7 +199,10 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
ktClassOrObject: KtClassOrObject
): IrConstructor =
declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) {
if (primaryConstructorDescriptor.isExpect)
if (
primaryConstructorDescriptor.isExpect ||
DescriptorUtils.isAnnotationClass(primaryConstructorDescriptor.constructedClass)
)
null
else
generatePrimaryConstructorBody(ktClassOrObject)
@@ -0,0 +1,7 @@
annotation class Test1(val x: Int)
annotation class Test2(val x: Int = 0)
annotation class Test3(val x: Test1)
annotation class Test4(vararg val xs: Int)
@@ -0,0 +1,119 @@
FILE fqName:<root> fileName:/annotationClasses.kt
CLASS ANNOTATION_CLASS name:Test1 modality:FINAL visibility:public flags:
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:Test1 flags:
superClasses:
CLASS IR_EXTERNAL_DECLARATION_STUB INTERFACE name:Annotation modality:ABSTRACT visibility:public flags:
CONSTRUCTOR visibility:public <> (x:kotlin.Int) returnType:Test1 flags:
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val
FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public
EXPRESSION_BODY
GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-x> visibility:public modality:FINAL <> ($this:Test1) returnType:Int flags:
$this: VALUE_PARAMETER name:<this> type:Test1 flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): Int'
GET_FIELD 'x: Int' type=kotlin.Int origin=null
receiver: GET_VAR 'this@Test1: Test1' type=Test1 origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
overridden:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
overridden:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
overridden:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
CLASS ANNOTATION_CLASS name:Test2 modality:FINAL visibility:public flags:
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:Test2 flags:
superClasses:
CLASS IR_EXTERNAL_DECLARATION_STUB INTERFACE name:Annotation modality:ABSTRACT visibility:public flags:
CONSTRUCTOR visibility:public <> (x:kotlin.Int) returnType:Test2 flags:
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
EXPRESSION_BODY
CONST Int type=kotlin.Int value=0
PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val
FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public
EXPRESSION_BODY
GET_VAR 'value-parameter x: Int = ...' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-x> visibility:public modality:FINAL <> ($this:Test2) returnType:Int flags:
$this: VALUE_PARAMETER name:<this> type:Test2 flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): Int'
GET_FIELD 'x: Int' type=kotlin.Int origin=null
receiver: GET_VAR 'this@Test2: Test2' type=Test2 origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
overridden:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
overridden:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
overridden:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
CLASS ANNOTATION_CLASS name:Test3 modality:FINAL visibility:public flags:
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:Test3 flags:
superClasses:
CLASS IR_EXTERNAL_DECLARATION_STUB INTERFACE name:Annotation modality:ABSTRACT visibility:public flags:
CONSTRUCTOR visibility:public <> (x:Test1) returnType:Test3 flags:
VALUE_PARAMETER name:x index:0 type:Test1 flags:
PROPERTY name:x type:Test1 visibility:public modality:FINAL flags:val
FIELD PROPERTY_BACKING_FIELD name:x type:Test1 visibility:public
EXPRESSION_BODY
GET_VAR 'value-parameter x: Test1' type=Test1 origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-x> visibility:public modality:FINAL <> ($this:Test3) returnType:Test1 flags:
$this: VALUE_PARAMETER name:<this> type:Test3 flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): Test1'
GET_FIELD 'x: Test1' type=Test1 origin=null
receiver: GET_VAR 'this@Test3: Test3' type=Test3 origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
overridden:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
overridden:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
overridden:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
CLASS ANNOTATION_CLASS name:Test4 modality:FINAL visibility:public flags:
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:Test4 flags:
superClasses:
CLASS IR_EXTERNAL_DECLARATION_STUB INTERFACE name:Annotation modality:ABSTRACT visibility:public flags:
CONSTRUCTOR visibility:public <> (xs:kotlin.IntArray) returnType:Test4 flags:
VALUE_PARAMETER name:xs index:0 type:kotlin.IntArray varargElementType:kotlin.Int flags:vararg
PROPERTY name:xs type:kotlin.IntArray visibility:public modality:FINAL flags:val
FIELD PROPERTY_BACKING_FIELD name:xs type:kotlin.IntArray visibility:public
EXPRESSION_BODY
GET_VAR 'value-parameter vararg xs: Int' type=kotlin.IntArray origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xs> visibility:public modality:FINAL <> ($this:Test4) returnType:IntArray flags:
$this: VALUE_PARAMETER name:<this> type:Test4 flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-xs>(): IntArray'
GET_FIELD 'xs: IntArray' type=kotlin.IntArray origin=null
receiver: GET_VAR 'this@Test4: Test4' type=Test4 origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
overridden:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
overridden:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
overridden:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
+1
View File
@@ -62,6 +62,7 @@ FILE fqName:<root> fileName:/classes.kt
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:TestAnnotationClass flags:
superClasses:
CLASS IR_EXTERNAL_DECLARATION_STUB INTERFACE name:Annotation modality:ABSTRACT visibility:public flags:
CONSTRUCTOR visibility:public <> () returnType:TestAnnotationClass flags:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
overridden:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags:
@@ -39,6 +39,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irText/classes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("annotationClasses.kt")
public void testAnnotationClasses() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/annotationClasses.kt");
doTest(fileName);
}
@TestMetadata("argumentReorderingInDelegatingConstructorCall.kt")
public void testArgumentReorderingInDelegatingConstructorCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.kt");