From 7ee13ca353b8ce449d8df4bd5cfce0a088001dfa Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Mon, 12 Nov 2018 09:41:18 +0100 Subject: [PATCH] Generalize parameter index calculation in ASM 7 support Second part for d2a205c72df66445250cb806b7245e19bceadb98 commit #KT-27774 Fixed --- .../structure/impl/classFiles/Annotations.kt | 19 ++++++- .../java/structure/impl/classFiles/Methods.kt | 9 +++- .../kotlin/gradle/SimpleKotlinGradleIT.kt | 22 ++++++++ .../testProject/groovyInterop/build.gradle | 2 + .../groovy/ClassWithReferenceToInner.groovy | 8 ++- .../lib/src/main/groovy/GEnum.groovy | 17 ++++++ .../lib/src/main/groovy/InnerClass.groovy | 17 ++++++ .../src/main/kotlin/MyKotlinClass.kt | 6 --- .../src/test/kotlin/GroovyInteropTest.kt | 41 +++++++++++++++ .../interopWithProguarded/build.gradle | 28 ++++++++++ .../interopWithProguarded/lib/build.gradle | 52 +++++++++++++++++++ .../lib/src/main/java/JEnum.java | 13 +++++ .../lib/src/main/java/JInnerClass.java | 17 ++++++ .../lib/src/main/java/KEnum.kt | 11 ++++ .../lib/src/main/java/KInnerClass.kt | 11 ++++ .../interopWithProguarded/settings.gradle | 1 + .../test/kotlin/InteropWithProguardedTest.kt | 40 ++++++++++++++ .../testProject/scalaInterop/build.gradle | 28 ++++++++++ .../testProject/scalaInterop/lib/build.gradle | 10 ++++ .../scalaInterop/lib/src/main/java/Foo.java | 7 +++ .../lib/src/main/scala/SInnerClass.scala | 5 ++ .../testProject/scalaInterop/settings.gradle | 1 + .../src/test/kotlin/ScalaInteropTest.kt | 22 ++++++++ 23 files changed, 376 insertions(+), 11 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/GEnum.groovy create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/InnerClass.groovy delete mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/main/kotlin/MyKotlinClass.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/test/kotlin/GroovyInteropTest.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JEnum.java create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JInnerClass.java create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KEnum.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KInnerClass.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/settings.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/src/test/kotlin/InteropWithProguardedTest.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/java/Foo.java create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/scala/SInnerClass.scala create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/settings.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/src/test/kotlin/ScalaInteropTest.kt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt index 02d2e3bd8d9..94513807f62 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt @@ -29,10 +29,14 @@ internal class AnnotationsAndParameterCollectorMethodVisitor( private val member: BinaryJavaMethodBase, private val context: ClassifierResolutionContext, private val signatureParser: BinaryClassSignatureParser, - private val parametersToSkipNumber: Int + private val parametersToSkipNumber: Int, + private val parametersCountInMethodDesc: Int ) : MethodVisitor(ASM_API_VERSION_FOR_CLASS_READING) { private var parameterIndex = 0 + private var visibleAnnotableParameterCount = parametersCountInMethodDesc + private var invisibleAnnotableParameterCount = parametersCountInMethodDesc + override fun visitAnnotationDefault(): AnnotationVisitor? { member.safeAs()?.hasAnnotationParameterDefaultValue = true // We don't store default value in Java model @@ -59,8 +63,19 @@ internal class AnnotationsAndParameterCollectorMethodVisitor( desc, context, signatureParser ) + @Suppress("NOTHING_TO_OVERRIDE") + override fun visitAnnotableParameterCount(parameterCount: Int, visible: Boolean) { + if (visible) { + visibleAnnotableParameterCount = parameterCount + } else { + invisibleAnnotableParameterCount = parameterCount + } + } + override fun visitParameterAnnotation(parameter: Int, desc: String, visible: Boolean): AnnotationVisitor? { - val index = if (Opcodes.API_VERSION <= Opcodes.ASM6) parameter - parametersToSkipNumber else parameter + val absoluteParameterIndex = + parameter + parametersCountInMethodDesc - if (visible) visibleAnnotableParameterCount else invisibleAnnotableParameterCount + val index = absoluteParameterIndex - parametersToSkipNumber if (index < 0) return null val annotations = diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt index 5f9890b8811..389c024a8ed 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Methods.kt @@ -106,7 +106,14 @@ abstract class BinaryJavaMethodBase( else -> 0 } - return member to AnnotationsAndParameterCollectorMethodVisitor(member, parentContext, signatureParser, paramIgnoreCount) + return member to + AnnotationsAndParameterCollectorMethodVisitor( + member, + parentContext, + signatureParser, + paramIgnoreCount, + Type.getArgumentTypes(desc).size + ) } private fun parseMethodDescription( diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SimpleKotlinGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SimpleKotlinGradleIT.kt index 7394597e30c..7594becf198 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SimpleKotlinGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SimpleKotlinGradleIT.kt @@ -111,6 +111,28 @@ class SimpleKotlinGradleIT : BaseGradleIT() { @Test fun testGroovyInterop() { Project("groovyInterop").build("build") { + assertTasksExecuted(":test") + assertContains("GroovyInteropTest PASSED") + assertSuccessful() + } + } + + //Proguard corrupts RuntimeInvisibleParameterAnnotations/RuntimeVisibleParameterAnnotations tables: + // https://sourceforge.net/p/proguard/bugs/735/ + @Test + fun testInteropWithProguarded() { + Project("interopWithProguarded").build("build") { + assertTasksExecuted(":test") + assertContains("InteropWithProguardedTest PASSED") + assertSuccessful() + } + } + + @Test + fun testScalaInterop() { + Project("scalaInterop").build("build") { + assertTasksExecuted(":test") + assertContains("ScalaInteropTest PASSED") assertSuccessful() } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/build.gradle index 44f5030c014..bb76dbcce7b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/build.gradle @@ -18,6 +18,8 @@ repositories { dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + testCompile 'junit:junit:4.12' compile project(":lib") } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/ClassWithReferenceToInner.groovy b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/ClassWithReferenceToInner.groovy index 08b7fe9bf5d..6055d5263b4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/ClassWithReferenceToInner.groovy +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/ClassWithReferenceToInner.groovy @@ -1,7 +1,11 @@ public class ClassWithReferenceToInner { - public void f1(Thread.State state) {} + public String f1(Thread.State state) { + return "OK" + } - public void f2(Outer.Nested nested) {} + public String f2(Outer.Nested nested) { + return "OK" + } } class Outer { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/GEnum.groovy b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/GEnum.groovy new file mode 100644 index 00000000000..97dd6a3c256 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/GEnum.groovy @@ -0,0 +1,17 @@ +package genum + +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +@Retention(RetentionPolicy.RUNTIME) +@interface FooEnum {} + +enum GEnum { + FOO("123"); + + String value + + GEnum(@FooEnum String value) { + this.value = value + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/InnerClass.groovy b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/InnerClass.groovy new file mode 100644 index 00000000000..8d0d027d749 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/lib/src/main/groovy/InnerClass.groovy @@ -0,0 +1,17 @@ +package inner + +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +@Retention(RetentionPolicy.RUNTIME) +@interface FooInner {} + +class Outer { + class Inner { + String name + + Inner(@FooInner String name) { + this.name = name + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/main/kotlin/MyKotlinClass.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/main/kotlin/MyKotlinClass.kt deleted file mode 100644 index 1ddd25dfba0..00000000000 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/main/kotlin/MyKotlinClass.kt +++ /dev/null @@ -1,6 +0,0 @@ -fun main(args: Array) { - System.out.println(MyTraitAccessor().myField) - - System.out.println(ClassWithReferenceToInner().f1(null)) - System.out.println(ClassWithReferenceToInner().f2(null)) -} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/test/kotlin/GroovyInteropTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/test/kotlin/GroovyInteropTest.kt new file mode 100644 index 00000000000..f4f52f1fc0a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/groovyInterop/src/test/kotlin/GroovyInteropTest.kt @@ -0,0 +1,41 @@ +import org.junit.Assert +import kotlin.reflect.full.valueParameters + +class GroovyInteropTest { + + @org.junit.Test + fun classWithReferenceToInner() { + Assert.assertEquals("OK", ClassWithReferenceToInner().f1(null)) + Assert.assertEquals("OK", ClassWithReferenceToInner().f2(null)) + } + + @org.junit.Test + fun groovyTraitAccessor() { + Assert.assertEquals(1, MyTraitAccessor().myField) + } + + @org.junit.Test + fun parametersInInnerClassConstructor() { + val inner = inner.Outer().Inner("123") + Assert.assertEquals("123", inner.name) + + val valueParameters = inner::class.constructors.single().valueParameters + Assert.assertEquals(1, valueParameters.size) + val annotations = valueParameters[0].annotations + Assert.assertEquals(1, annotations.size) + Assert.assertEquals("FooInner", annotations[0].annotationClass.simpleName) + } + + @org.junit.Test + fun parametersInEnumConstructor() { + val enumValue = genum.GEnum.FOO + Assert.assertEquals("123", enumValue.value) + + val valueParameters = enumValue::class.constructors.single().valueParameters + Assert.assertTrue(valueParameters.isNotEmpty()) + //valueParameters.last() cause Groovy doesn't mark name and ordinal as synthetic and doesn't generate signature + val annotations = valueParameters.last().annotations + Assert.assertEquals(1, annotations.size) + Assert.assertEquals("FooEnum", annotations[0].annotationClass.simpleName) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/build.gradle new file mode 100644 index 00000000000..a610154c434 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/build.gradle @@ -0,0 +1,28 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: "kotlin" +apply plugin: "java" + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + testCompile 'junit:junit:4.12' + compile project(path: ":lib", configuration: "proguarded") +} + +compileKotlin { + kotlinOptions.jvmTarget = "1.8" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/build.gradle new file mode 100644 index 00000000000..fe4fc2bab05 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/build.gradle @@ -0,0 +1,52 @@ +apply plugin: 'java' +apply plugin: 'kotlin' + +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'net.sf.proguard:proguard-gradle:6.0.3' + } +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + +} + +task obfuscate(type: proguard.gradle.ProGuardTask, dependsOn: jar) { + injars "${jar.archivePath}" + outjars "$buildDir/proguard/out.jar" + libraryjars "$System.env.JAVA_HOME/jre/lib/rt.jar" + libraryjars configurations["compile"] + + dontobfuscate + dontoptimize + keep 'class *' + keepclassmembers 'class * { \ + public (...); \ + }' + +} + +configurations { + proguarded +} + +artifacts { + proguarded(file(obfuscate.outJarFiles[0])) { + name 'out' + type 'jar' + builtBy obfuscate + } +} + + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JEnum.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JEnum.java new file mode 100644 index 00000000000..112668d5816 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JEnum.java @@ -0,0 +1,13 @@ +package jenum; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public enum JEnum { + OK("123"); + + @Retention(RetentionPolicy.RUNTIME) + public @interface Foo {} + + JEnum(@Foo String foo) {} +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JInnerClass.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JInnerClass.java new file mode 100644 index 00000000000..cff2476e387 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/JInnerClass.java @@ -0,0 +1,17 @@ +package iclass; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class JInnerClass { + @Retention(RetentionPolicy.RUNTIME) + public @interface Foo {} + + public class Inner { + public String foo; + + public Inner(@Foo String foo) { + this.foo = foo; + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KEnum.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KEnum.kt new file mode 100644 index 00000000000..5cec89ddc24 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KEnum.kt @@ -0,0 +1,11 @@ +package kenum + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +enum class KEnum(@Foo val foo: String) { + OK("123"); + + @Retention(RetentionPolicy.RUNTIME) + annotation class Foo {} +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KInnerClass.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KInnerClass.kt new file mode 100644 index 00000000000..923b2720687 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/lib/src/main/java/KInnerClass.kt @@ -0,0 +1,11 @@ +package kclass + +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +public class KInnerClass { + @Retention(RetentionPolicy.RUNTIME) + annotation class Foo + + inner class Inner(@Foo val foo: String){} +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/settings.gradle new file mode 100644 index 00000000000..ea3dc068931 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/settings.gradle @@ -0,0 +1 @@ +include ":lib" diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/src/test/kotlin/InteropWithProguardedTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/src/test/kotlin/InteropWithProguardedTest.kt new file mode 100644 index 00000000000..fb4662c538a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/interopWithProguarded/src/test/kotlin/InteropWithProguardedTest.kt @@ -0,0 +1,40 @@ +import org.junit.Assert +import kotlin.reflect.full.valueParameters +import kotlin.reflect.KClass + +class InteropWithProguardedTest { + + @org.junit.Test + fun parametersInInnerJavaClassConstructor() { + val inner = iclass.JInnerClass().Inner("123") + testAnnotationsInConstructor(inner::class) + } + + @org.junit.Test + fun parametersInInnerKotlinClassConstructor() { + val inner = kclass.KInnerClass().Inner("123") + testAnnotationsInConstructor(inner::class) + } + + @org.junit.Test + fun parametersInJavaEnumConstructor() { + val enumValue = jenum.JEnum.OK + Assert.assertEquals("OK", enumValue.name) + testAnnotationsInConstructor(enumValue::class) + } + + @org.junit.Test + fun parametersInKotlinEnumConstructor() { + val enumValue = kenum.KEnum.OK + Assert.assertEquals("OK", enumValue.name) + testAnnotationsInConstructor(enumValue::class) + } + + private fun testAnnotationsInConstructor(clazz: KClass<*>) { + val valueParameters = clazz.constructors.single().valueParameters + Assert.assertTrue(valueParameters.isNotEmpty()) + val annotations = valueParameters[0].annotations + Assert.assertEquals(1, annotations.size) + Assert.assertEquals("Foo", annotations[0].annotationClass.simpleName) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/build.gradle new file mode 100644 index 00000000000..bb76dbcce7b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/build.gradle @@ -0,0 +1,28 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: "kotlin" +apply plugin: "java" + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + testCompile 'junit:junit:4.12' + compile project(":lib") +} + +compileKotlin { + kotlinOptions.jvmTarget = "1.8" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/build.gradle new file mode 100644 index 00000000000..d752acaa0cf --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/build.gradle @@ -0,0 +1,10 @@ +apply plugin: "java" +apply plugin: "scala" + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.scala-lang:scala-library:2.12.7' +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/java/Foo.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/java/Foo.java new file mode 100644 index 00000000000..fb76d2d0226 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/java/Foo.java @@ -0,0 +1,7 @@ +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Foo { + +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/scala/SInnerClass.scala b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/scala/SInnerClass.scala new file mode 100644 index 00000000000..89178de6229 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/lib/src/main/scala/SInnerClass.scala @@ -0,0 +1,5 @@ +class Outer { + class Inner(@Foo val name: String) { + var x = 1 + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/settings.gradle new file mode 100644 index 00000000000..ea3dc068931 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/settings.gradle @@ -0,0 +1 @@ +include ":lib" diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/src/test/kotlin/ScalaInteropTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/src/test/kotlin/ScalaInteropTest.kt new file mode 100644 index 00000000000..b1c015c535e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/scalaInterop/src/test/kotlin/ScalaInteropTest.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +import org.junit.Assert +import kotlin.reflect.full.valueParameters + +class ScalaInteropTest { + + @org.junit.Test + fun parametersInInnerClassConstructor() { + val inner = Outer().Inner("123") + Assert.assertEquals("123", inner.name()) + + val valueParameters = inner::class.constructors.single().valueParameters + Assert.assertEquals(1, valueParameters.size) + val annotations = valueParameters[0].annotations + Assert.assertEquals(1, annotations.size) + Assert.assertEquals("Foo", annotations[0].annotationClass.simpleName) + } +}