diff --git a/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt index fa950d5d658..04068b62387 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/AnnotationConverter.kt @@ -98,15 +98,15 @@ class AnnotationConverter(private val converter: Converter) { val nameRef = annotation.getNameReferenceElement() val name = Identifier((nameRef ?: return null).getText()!!).assignPrototype(nameRef) val annotationClass = nameRef.resolve() as? PsiClass - val lastMethod = annotationClass?.getMethods()?.lastOrNull() val arguments = annotation.getParameterList().getAttributes().flatMap { - val method = annotationClass?.findMethodsByName(it.getName() ?: "value", false)?.firstOrNull() + val parameterName = it.getName() ?: "value" + val method = annotationClass?.findMethodsByName(parameterName, false)?.firstOrNull() val expectedType = method?.getReturnType() val attrName = it.getName()?.let { Identifier(it).assignNoPrototype() } val value = it.getValue() - val isVarArg = method == lastMethod /* converted to vararg in Kotlin */ + val isVarArg = parameterName == "value" /* converted to vararg in Kotlin */ val attrValues = convertAttributeValue(value, expectedType, isVarArg, it.getName() == null) attrValues.map { attrName to converter.deferredElement(it) } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt index 3a6183f5060..1464abab967 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt @@ -234,21 +234,36 @@ class Converter private( val paramModifiers = Modifiers(listOf(Modifier.PUBLIC)).assignNoPrototype() val noBlankLinesInheritance = CommentsAndSpacesInheritance(blankLinesBefore = false) val annotationMethods = psiClass.getMethods().filterIsInstance() - val parameters = annotationMethods - .map { method -> + val (methodsNamedValue, otherMethods) = annotationMethods.partition { it.getName() == "value" } + + fun createParameter(type: Type, method: PsiAnnotationMethod): Parameter { + type.assignPrototype(method.getReturnTypeElement(), noBlankLinesInheritance) + + return Parameter(method.declarationIdentifier(), + type, + Parameter.VarValModifier.Val, + convertAnnotations(method), + paramModifiers, + annotationConverter.convertAnnotationMethodDefault(method)).assignPrototype(method, noBlankLinesInheritance) + } + + val parameters = + // Argument named `value` comes first if it exists + // Convert it as vararg if it's array + methodsNamedValue. + map { method -> val returnType = method.getReturnType() - val typeConverted = if (method == annotationMethods.last() && returnType is PsiArrayType) + val typeConverted = if (returnType is PsiArrayType) VarArgType(typeConverter.convertType(returnType.getComponentType(), Nullability.NotNull)) else typeConverter.convertType(returnType, Nullability.NotNull) - typeConverted.assignPrototype(method.getReturnTypeElement(), noBlankLinesInheritance) - Parameter(method.declarationIdentifier(), - typeConverted, - Parameter.VarValModifier.Val, - convertAnnotations(method), - paramModifiers, - annotationConverter.convertAnnotationMethodDefault(method)).assignPrototype(method, noBlankLinesInheritance) + createParameter(typeConverted, method) + } + + otherMethods + .map { method -> + val typeConverted = typeConverter.convertType(method.getReturnType(), Nullability.NotNull) + createParameter(typeConverted, method) } val parameterList = ParameterList(parameters).assignNoPrototype() val constructorSignature = if (parameterList.parameters.isNotEmpty()) diff --git a/j2k/testData/fileOrElement/annotations/annotationInterface2.kt b/j2k/testData/fileOrElement/annotations/annotationInterface2.kt index 7dfb5332986..959d36ad959 100644 --- a/j2k/testData/fileOrElement/annotations/annotationInterface2.kt +++ b/j2k/testData/fileOrElement/annotations/annotationInterface2.kt @@ -1,4 +1,4 @@ -annotation class Anon(public val s: String = "a", public val stringArray: Array = array("a", "b"), public vararg val intArray: Int) +annotation class Anon(public val s: String = "a", public val stringArray: Array = array("a", "b"), public val intArray: IntArray) -Anon(intArray = *intArray(1, 2)) +Anon(intArray = intArray(1, 2)) class A \ No newline at end of file diff --git a/j2k/testData/fileOrElement/annotations/annotationInterface4.java b/j2k/testData/fileOrElement/annotations/annotationInterface4.java new file mode 100644 index 00000000000..87232b6dd4d --- /dev/null +++ b/j2k/testData/fileOrElement/annotations/annotationInterface4.java @@ -0,0 +1,24 @@ +@interface Anon { + String[] value(); + int x() default 1; +} + +@Anon("a", "b") +interface I1 { + +} + +@Anon("c", "d", x = 1) +interface I2 { + +} + +@Anon({"c", "d"}, x = 1) +interface I3 { + +} + +@Anon(value = {"c", "d"}) +interface I4 { + +} diff --git a/j2k/testData/fileOrElement/annotations/annotationInterface4.kt b/j2k/testData/fileOrElement/annotations/annotationInterface4.kt new file mode 100644 index 00000000000..cd0e4076e9d --- /dev/null +++ b/j2k/testData/fileOrElement/annotations/annotationInterface4.kt @@ -0,0 +1,13 @@ +annotation class Anon(public vararg val value: String, public val x: Int = 1) + +Anon("a", "b") +trait I1 + +Anon("c", "d", x = 1) +trait I2 + +Anon("c", "d", x = 1) +trait I3 + +Anon(value = *array("c", "d")) +trait I4 \ No newline at end of file diff --git a/j2k/testData/fileOrElement/annotations/annotationUsages.kt b/j2k/testData/fileOrElement/annotations/annotationUsages.kt index 1ff48460991..b67c62299ba 100644 --- a/j2k/testData/fileOrElement/annotations/annotationUsages.kt +++ b/j2k/testData/fileOrElement/annotations/annotationUsages.kt @@ -1,13 +1,13 @@ import javaApi.* -Anon1(value = array("a"), stringArray = array("b"), intArray = intArray(1, 2), string = "x") +Anon1(value = *array("a"), stringArray = array("b"), intArray = intArray(1, 2), string = "x") Anon2(value = "a", intValue = 1, charValue = 'a') Anon3(e = E.A, stringArray = array(), value = *array("a", "b")) Anon4("x", "y") Anon5(1) -Anon6(array("x", "y")) +Anon6("x", "y") Anon7(javaClass(), javaClass()) -Anon8(classes = *array(javaClass(), javaClass())) +Anon8(classes = array(javaClass(), javaClass())) class C { Anon5(1) deprecated("") private val field1 = 0 @@ -19,7 +19,7 @@ class C { Anon5(1) var field4 = 0 - Anon6(array()) + Anon6 fun foo(deprecated("") p1: Int, deprecated("") Anon5(2) p2: Char) { [deprecated("")] [Anon5(3)] val c = 'a' } diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index 4aad7e91764..e31920fcca7 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -134,6 +134,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("annotationInterface4.java") + public void testAnnotationInterface4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationInterface4.java"); + doTest(fileName); + } + @TestMetadata("annotationUsages.java") public void testAnnotationUsages() throws Exception { String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationUsages.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 166c31f849b..8523e3ed6f9 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -134,6 +134,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("annotationInterface4.java") + public void testAnnotationInterface4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationInterface4.java"); + doTest(fileName); + } + @TestMetadata("annotationUsages.java") public void testAnnotationUsages() throws Exception { String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/annotations/annotationUsages.java");