Skip to content

Commit

Permalink
DATACMNS-1338 - Calculate defaulting mask count in Kotlin default con…
Browse files Browse the repository at this point in the history
…structor 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.
  • Loading branch information
mp911de committed Jun 10, 2018
1 parent 0341f60 commit 53560e0
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
Expand Up @@ -112,13 +112,12 @@ private static Constructor<?> resolveDefaultConstructor(PersistentEntity<?, ?> e
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;
}

Expand Down
@@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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)
}

0 comments on commit 53560e0

Please sign in to comment.