diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt index 02e04ef1707..1aabd44ea45 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorConverter.kt @@ -121,12 +121,10 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter } private fun dropConstructorsForDefaultValues(primary: PsiMethod, toTargetConstructorMap: Map) { - //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) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt index 31172b2742c..25d3ccf6d4f 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt @@ -66,3 +66,6 @@ class Annotations(val annotations: List, 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) diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt index 250edb63daa..1f837a6a977 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt @@ -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 ")" } } diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java index c8752b50cb7..583bce28b59 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -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"); diff --git a/j2k/tests/testData/ast/constructors/constructorAnnotations.java b/j2k/tests/testData/ast/constructors/constructorAnnotations.java new file mode 100644 index 00000000000..9790c9541a4 --- /dev/null +++ b/j2k/tests/testData/ast/constructors/constructorAnnotations.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() { + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/constructors/constructorAnnotations.kt b/j2k/tests/testData/ast/constructors/constructorAnnotations.kt new file mode 100644 index 00000000000..78ae4eb6396 --- /dev/null +++ b/j2k/tests/testData/ast/constructors/constructorAnnotations.kt @@ -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() \ No newline at end of file