DATACMNS-1338 - Calculate defaulting mask count in Kotlin default constructor resolution.
We now calculate the number of expected default masks to filter synthetic constructors that do not match the expected parameter count. A Kotlin constructor with argument defaulting generates a synthetic integer argument for every 32 constructor arguments. This is independent of the number of actual optional arguments. Previously, we used an non-exact check to consider constructors as default ones if they had at least two additional arguments. This caused the wrong constructor being used if the non-synthetic types matched the types of the default constructor.
This commit is contained in:
@@ -112,13 +112,12 @@ public class KotlinClassGeneratingEntityInstantiator extends ClassGeneratingEnti
|
||||
continue;
|
||||
}
|
||||
|
||||
// with a parameter count greater zero
|
||||
if (constructor.getParameterCount() == 0) {
|
||||
continue;
|
||||
}
|
||||
// candidates must contain at least two additional parameters (int, DefaultConstructorMarker).
|
||||
// Number of defaulting masks derives from the original constructor arg count
|
||||
int syntheticParameters = (constructor.getParameterCount() / Integer.SIZE) + 1
|
||||
+ /* DefaultConstructorMarker */ 1;
|
||||
|
||||
// candidates must contain at least two additional parameters (int, DefaultConstructorMarker)
|
||||
if (constructor.getParameterCount() + 2 > candidate.getParameterCount()) {
|
||||
if (constructor.getParameterCount() + syntheticParameters != candidate.getParameterCount()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import org.springframework.data.annotation.PersistenceConstructor
|
||||
import org.springframework.data.mapping.PersistentEntity
|
||||
import org.springframework.data.mapping.context.SamplePersistentProperty
|
||||
import org.springframework.data.mapping.model.MappingInstantiationException
|
||||
@@ -117,6 +118,21 @@ class KotlinClassGeneratingEntityInstantiatorUnitTests {
|
||||
Assertions.assertThat(instance.aBool).isTrue()
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1338
|
||||
fun `should create instance using @PersistenceConstructor`() {
|
||||
|
||||
val entity = this.entity as PersistentEntity<CustomUser, SamplePersistentProperty>
|
||||
val constructor = PreferredConstructorDiscoverer.discover<CustomUser, SamplePersistentProperty>(CustomUser::class.java)
|
||||
|
||||
doReturn("Walter").`when`(provider).getParameterValue<SamplePersistentProperty>(any())
|
||||
doReturn(constructor).whenever(entity).persistenceConstructor
|
||||
doReturn(constructor.constructor.declaringClass).whenever(entity).type
|
||||
|
||||
val instance: CustomUser = KotlinClassGeneratingEntityInstantiator().createInstance(entity, provider)
|
||||
|
||||
Assertions.assertThat(instance.id).isEqualTo("Walter")
|
||||
}
|
||||
|
||||
data class Contact(val firstname: String, val lastname: String)
|
||||
|
||||
data class ContactWithDefaulting(val prop0: String, val prop1: String = "White", val prop2: String,
|
||||
@@ -137,5 +153,22 @@ class KotlinClassGeneratingEntityInstantiatorUnitTests {
|
||||
|
||||
data class WithPrimitiveDefaulting(val aByte: Byte = 0, val aShort: Short = 0, val anInt: Int = 0, val aLong: Long = 0L,
|
||||
val aFloat: Float = 0.0f, val aDouble: Double = 0.0, val aChar: Char = 'a', val aBool: Boolean = true)
|
||||
|
||||
data class ContactWithPersistenceConstructor(val firstname: String, val lastname: String) {
|
||||
|
||||
@PersistenceConstructor
|
||||
constructor(firstname: String) : this(firstname, "")
|
||||
}
|
||||
|
||||
data class CustomUser(
|
||||
var id: String? = null,
|
||||
|
||||
var organisations: MutableList<Organisation> = mutableListOf()
|
||||
) {
|
||||
@PersistenceConstructor
|
||||
constructor(id: String?) : this(id, mutableListOf())
|
||||
}
|
||||
|
||||
data class Organisation(var id: String? = null)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user