Fixed KT-5383 J2K: preserve annotations from primary constructor + never drop constructors with annotations
#KT-5383 Fixed
This commit is contained in:
@@ -121,12 +121,10 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
||||
}
|
||||
|
||||
private fun dropConstructorsForDefaultValues(primary: PsiMethod, toTargetConstructorMap: Map<PsiMethod, TargetConstructorInfo>) {
|
||||
//TODO: should we drop when annotations exist?
|
||||
|
||||
val dropCandidates = toTargetConstructorMap
|
||||
.filter { it.value.parameterDefaults != null }
|
||||
.map { it.key }
|
||||
.filter { it.accessModifier() == primary.accessModifier() }
|
||||
.filter { it.accessModifier() == primary.accessModifier() && it.getModifierList().getAnnotations().isEmpty() /* do not drop constructors with annotations */ }
|
||||
.sortBy { -it.getParameterList().getParametersCount() } // we will try to drop them starting from ones with more parameters
|
||||
val primaryParamCount = primary.getParameterList().getParametersCount()
|
||||
@DropCandidatesLoop
|
||||
@@ -340,7 +338,7 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
||||
//TODO: we can generate it private when secondary constructors are supported by Kotlin
|
||||
//val modifiers = Modifiers(listOf(Modifier.PRIVATE)).assignNoPrototype()
|
||||
val parameterList = ParameterList(parameters).assignNoPrototype()
|
||||
val constructorSignature = PrimaryConstructorSignature(modifiers, parameterList).assignNoPrototype()
|
||||
val constructorSignature = PrimaryConstructorSignature(Annotations.Empty, modifiers, parameterList).assignNoPrototype()
|
||||
val updatedMembers = classBody.members.filter { !fieldsToInitialize.contains(it) }
|
||||
return ClassBody(constructorSignature, updatedMembers, classBody.classObjectMembers, updatedFactoryFunctions, classBody.lBrace, classBody.rBrace)
|
||||
}
|
||||
|
||||
@@ -66,3 +66,6 @@ class Annotations(val annotations: List<Annotation>, val newLines: Boolean) : El
|
||||
val Empty = Annotations(listOf(), false)
|
||||
}
|
||||
}
|
||||
|
||||
fun Annotations.withBrackets(): Annotations
|
||||
= Annotations(annotations.map { Annotation(it.name, it.arguments, true).assignPrototypesFrom(it) }, newLines).assignPrototypesFrom(this)
|
||||
|
||||
@@ -37,17 +37,23 @@ class PrimaryConstructor(annotations: Annotations,
|
||||
public fun signature(): PrimaryConstructorSignature {
|
||||
val noBody = block.isEmpty
|
||||
val inheritance = CommentsAndSpacesInheritance(blankLinesBefore = false, commentsAfter = noBody, commentsInside = noBody)
|
||||
return PrimaryConstructorSignature(modifiers, parameterList).assignPrototypesFrom(this, inheritance)
|
||||
return PrimaryConstructorSignature(annotations, modifiers, parameterList).assignPrototypesFrom(this, inheritance)
|
||||
}
|
||||
}
|
||||
|
||||
class PrimaryConstructorSignature(val modifiers: Modifiers, val parameterList: ParameterList) : Element() {
|
||||
class PrimaryConstructorSignature(val annotations: Annotations, val modifiers: Modifiers, val parameterList: ParameterList) : Element() {
|
||||
override fun generateCode(builder: CodeBuilder) {
|
||||
val accessModifier = modifiers.filter { it in ACCESS_MODIFIERS && it != Modifier.PUBLIC }
|
||||
if (accessModifier.isEmpty && parameterList.parameters.isEmpty()) return
|
||||
if (accessModifier.isEmpty && annotations.isEmpty && parameterList.parameters.isEmpty()) return
|
||||
|
||||
if (!annotations.isEmpty) {
|
||||
builder append " " append annotations.withBrackets()
|
||||
}
|
||||
|
||||
if (!accessModifier.isEmpty) {
|
||||
builder append " " append accessModifier
|
||||
}
|
||||
|
||||
builder append "(" append parameterList append ")"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,6 +821,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
doTest("j2k/tests/testData/ast/constructors/chain.java");
|
||||
}
|
||||
|
||||
@TestMetadata("constructorAnnotations.java")
|
||||
public void testConstructorAnnotations() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/constructors/constructorAnnotations.java");
|
||||
}
|
||||
|
||||
@TestMetadata("customerBuilder.java")
|
||||
public void testCustomerBuilder() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/constructors/customerBuilder.java");
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import javaApi.Anon5;
|
||||
|
||||
class A {
|
||||
private final int a;
|
||||
private final int b;
|
||||
|
||||
@Anon5(10)
|
||||
public A(int a, int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Deprecated // this constructor will not be replaced by default parameter value in primary because of this annotation
|
||||
public A(int a) {
|
||||
this(a, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
@Anon5(11)
|
||||
public B() {
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
@Anon5(12)
|
||||
private C() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import javaApi.Anon5
|
||||
|
||||
|
||||
deprecated("") // this constructor will not be replaced by default parameter value in primary because of this annotation
|
||||
fun A(a: Int): A {
|
||||
return A(a, 1)
|
||||
}
|
||||
|
||||
class A
|
||||
[Anon5(10)]
|
||||
(private val a: Int, private val b: Int)
|
||||
|
||||
class B [Anon5(11)]
|
||||
()
|
||||
|
||||
class C [Anon5(12)]
|
||||
private()
|
||||
Reference in New Issue
Block a user