Generalize parameter index calculation in ASM 7 support
Second part for d2a205c72d commit
#KT-27774 Fixed
This commit is contained in:
+17
-2
@@ -29,10 +29,14 @@ internal class AnnotationsAndParameterCollectorMethodVisitor(
|
|||||||
private val member: BinaryJavaMethodBase,
|
private val member: BinaryJavaMethodBase,
|
||||||
private val context: ClassifierResolutionContext,
|
private val context: ClassifierResolutionContext,
|
||||||
private val signatureParser: BinaryClassSignatureParser,
|
private val signatureParser: BinaryClassSignatureParser,
|
||||||
private val parametersToSkipNumber: Int
|
private val parametersToSkipNumber: Int,
|
||||||
|
private val parametersCountInMethodDesc: Int
|
||||||
) : MethodVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
|
) : MethodVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
|
||||||
private var parameterIndex = 0
|
private var parameterIndex = 0
|
||||||
|
|
||||||
|
private var visibleAnnotableParameterCount = parametersCountInMethodDesc
|
||||||
|
private var invisibleAnnotableParameterCount = parametersCountInMethodDesc
|
||||||
|
|
||||||
override fun visitAnnotationDefault(): AnnotationVisitor? {
|
override fun visitAnnotationDefault(): AnnotationVisitor? {
|
||||||
member.safeAs<BinaryJavaMethod>()?.hasAnnotationParameterDefaultValue = true
|
member.safeAs<BinaryJavaMethod>()?.hasAnnotationParameterDefaultValue = true
|
||||||
// We don't store default value in Java model
|
// We don't store default value in Java model
|
||||||
@@ -59,8 +63,19 @@ internal class AnnotationsAndParameterCollectorMethodVisitor(
|
|||||||
desc, context, signatureParser
|
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? {
|
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
|
if (index < 0) return null
|
||||||
|
|
||||||
val annotations =
|
val annotations =
|
||||||
|
|||||||
+8
-1
@@ -106,7 +106,14 @@ abstract class BinaryJavaMethodBase(
|
|||||||
else -> 0
|
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(
|
private fun parseMethodDescription(
|
||||||
|
|||||||
+22
@@ -111,6 +111,28 @@ class SimpleKotlinGradleIT : BaseGradleIT() {
|
|||||||
@Test
|
@Test
|
||||||
fun testGroovyInterop() {
|
fun testGroovyInterop() {
|
||||||
Project("groovyInterop").build("build") {
|
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()
|
assertSuccessful()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -18,6 +18,8 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
compile project(":lib")
|
compile project(":lib")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -1,7 +1,11 @@
|
|||||||
public class ClassWithReferenceToInner {
|
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 {
|
class Outer {
|
||||||
|
|||||||
+17
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-6
@@ -1,6 +0,0 @@
|
|||||||
fun main(args: Array<String>) {
|
|
||||||
System.out.println(MyTraitAccessor().myField)
|
|
||||||
|
|
||||||
System.out.println(ClassWithReferenceToInner().f1(null))
|
|
||||||
System.out.println(ClassWithReferenceToInner().f2(null))
|
|
||||||
}
|
|
||||||
+41
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -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"
|
||||||
|
}
|
||||||
+52
@@ -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 <init>(...); \
|
||||||
|
}'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
proguarded
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
proguarded(file(obfuscate.outJarFiles[0])) {
|
||||||
|
name 'out'
|
||||||
|
type 'jar'
|
||||||
|
builtBy obfuscate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+13
@@ -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) {}
|
||||||
|
}
|
||||||
+17
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -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 {}
|
||||||
|
}
|
||||||
+11
@@ -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){}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
include ":lib"
|
||||||
+40
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -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"
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
apply plugin: "java"
|
||||||
|
apply plugin: "scala"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'org.scala-lang:scala-library:2.12.7'
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Foo {
|
||||||
|
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class Outer {
|
||||||
|
class Inner(@Foo val name: String) {
|
||||||
|
var x = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
include ":lib"
|
||||||
+22
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user