KT-5524 Support [platformName] annotation for class members
@platformName is now supported for final non-overriding class member functions (including property accessors). Front-end provides diagnostics for inapplicable annotation cases. Code generation updated: - ignore kotlin.platform.platformName annotation for Java class methods; - bridges generation generates proper JVM declarations in case of methods renamed with @platformName. @platformName-related tests added. #KT-5524 Fixed
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import kotlin.platform.platformName;
|
||||
|
||||
public class FakePlatformName {
|
||||
@platformName(name = "fake")
|
||||
public String foo() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public String fake() {
|
||||
return "fake";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun box(): String {
|
||||
val test1 = FakePlatformName().foo()
|
||||
if (test1 != "foo") return "Failed: FakePlatformName().foo()==$test1"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
import kotlin.platform.*
|
||||
|
||||
// See:
|
||||
// http://kotlinlang.org/docs/reference/java-interop.html#handling-signature-clashes-with-platformname
|
||||
// https://youtrack.jetbrains.com/issue/KT-5524
|
||||
|
||||
val strs = listOf("abc", "def")
|
||||
val ints = listOf(1, 2, 3)
|
||||
|
||||
class C {
|
||||
// Instance methods
|
||||
|
||||
@platformName("instMethodStr")
|
||||
fun instMethod(list: List<String>): String = "instMethodStr"
|
||||
|
||||
@platformName("instMethodInt")
|
||||
fun instMethod(list: List<Int>): String = "instMethodInt"
|
||||
|
||||
// Properties
|
||||
|
||||
var rwProperty: Int
|
||||
@platformName("get_rwProperty")
|
||||
get() = 123
|
||||
@platformName("set_rwProperty")
|
||||
set(v) {}
|
||||
|
||||
var rwValue = 111
|
||||
|
||||
fun getRwProperty(): Int = rwValue
|
||||
|
||||
fun setRwProperty(v: Int) {
|
||||
rwValue = v
|
||||
}
|
||||
|
||||
// Extension methods
|
||||
|
||||
class Inner
|
||||
|
||||
@platformName("extMethodWithGenericParamStr")
|
||||
fun Inner.extMethodWithGenericParam(list: List<String>): String = "extMethodWithGenericParamStr"
|
||||
|
||||
@platformName("extMethodWithGenericParamInt")
|
||||
fun Inner.extMethodWithGenericParam(list: List<Int>): String = "extMethodWithGenericParamInt"
|
||||
|
||||
// This is already covered by extMethodWithGenericParam(), but might be relevant for a platform
|
||||
// with extension method code generation strategy different from Java 6.
|
||||
|
||||
@platformName("extMethodWithGenericReceiverStr")
|
||||
fun List<String>.extMethodWithGenericReceiver(): String = "extMethodWithGenericReceiverStr"
|
||||
|
||||
@platformName("extMethodWithGenericReceiverInt")
|
||||
fun List<Int>.extMethodWithGenericReceiver(): String = "extMethodWithGenericReceiverInt"
|
||||
|
||||
// Extension method vs instance method
|
||||
|
||||
@platformName("ambigMethod1")
|
||||
fun ambigMethod(str: String): String = "ambigMethod1"
|
||||
|
||||
@platformName("ambigMethod2")
|
||||
fun String.ambigMethod(): String = "ambigMethod2"
|
||||
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val c = C()
|
||||
|
||||
// Instance methods:
|
||||
// method signatures with erased types SHOULD NOT clash
|
||||
|
||||
val test1 = c.instMethod(strs)
|
||||
if (test1 != "instMethodStr") return "Fail: c.instMethod(strs)==$test1"
|
||||
|
||||
val test2 = c.instMethod(ints)
|
||||
if (test2 != "instMethodInt") return "Fail: c.instMethod(ints)==$test2"
|
||||
|
||||
// Properties:
|
||||
// property accessors SHOULD NOT clash with class methods
|
||||
|
||||
val test3 = c.rwProperty
|
||||
if (test3 != 123) return "Fail: c.rwProperty==$test3"
|
||||
|
||||
val test3a = c.getRwProperty()
|
||||
if (test3a != 111) return "Fail: c.getRwProperty()==$test3a"
|
||||
|
||||
c.setRwProperty(444)
|
||||
val test3b = c.rwProperty
|
||||
if (test3b != 123) return "Fail: c.rwProperty==$test3b after c.setRwProperty(1234)"
|
||||
val test3c = c.getRwProperty()
|
||||
if (test3c != 444) return "Fail: c.getRwProperty()==$test3c after c.setRwProperty(1234)"
|
||||
|
||||
// Extension methods:
|
||||
// method signatures with erased types SHOULD NOT clash
|
||||
|
||||
val test4 = with(c) { C.Inner().extMethodWithGenericParam(strs) }
|
||||
if (test4 != "extMethodWithGenericParamStr") return "Fail: with(c) { C.Inner().extMethodWithGenericParam(strs) }==$test4"
|
||||
|
||||
val test5 = with(c) { C.Inner().extMethodWithGenericParam(ints) }
|
||||
if (test5 != "extMethodWithGenericParamInt") return "Fail: with(c) { C.Inner().extMethodWithGenericParam(ints) }==$test5"
|
||||
|
||||
val test6 = with(c) { strs.extMethodWithGenericReceiver() }
|
||||
if (test6 != "extMethodWithGenericReceiverStr") return "Fail: with(c) { strs.extMethodWithGenericReceiver() }==$test6"
|
||||
|
||||
val test7 = with(c) { ints.extMethodWithGenericReceiver() }
|
||||
if (test7 != "extMethodWithGenericReceiverInt") return "Fail: with(c) { ints.extMethodWithGenericReceiver() }==$test7"
|
||||
|
||||
// Extension method SHOULD NOT clash with instance method with the same Java signature.
|
||||
|
||||
val str = "abc"
|
||||
|
||||
val test8 = with(c) { ambigMethod(str) }
|
||||
if (test8 != "ambigMethod1") return "Fail: with(c) { ambigMethod(str) }==$test8"
|
||||
|
||||
val test9 = with(c) { str.ambigMethod() }
|
||||
if (test9 != "ambigMethod2") return "Fail: with(c) { str.ambigMethod() }==$test9"
|
||||
|
||||
// Everything is fine.
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
|
||||
Vendored
+39
-15
@@ -8,10 +8,10 @@ fun foo() {}
|
||||
@platformName("b")
|
||||
fun Any.foo() {}
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("c")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("c")<!>
|
||||
val px = 1
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("d")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("d")<!>
|
||||
val Any.px : Int
|
||||
get() = 1
|
||||
|
||||
@@ -31,37 +31,61 @@ var vardef: Int = 1
|
||||
@platformName("i")
|
||||
set
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("C")<!>
|
||||
class C <!INAPPLICABLE_ANNOTATION!>platformName("primary")<!> constructor() {
|
||||
<!INAPPLICABLE_ANNOTATION!>platformName("ctr")<!> constructor(x: Int): this() {}
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("a")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("C")<!>
|
||||
class C <!INAPPLICABLE_PLATFORM_NAME!>platformName("primary")<!> constructor() {
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>platformName("ctr")<!> constructor(x: Int): this() {}
|
||||
|
||||
@platformName("a")
|
||||
fun foo() {}
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("b")<!>
|
||||
@platformName("b")
|
||||
fun Any.foo() {}
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("c")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("c")<!>
|
||||
val px = 1
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("d")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("d")<!>
|
||||
val Any.px : Int
|
||||
get() = 1
|
||||
|
||||
val valx: Int
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("e")<!>
|
||||
@platformName("e")
|
||||
get() = 1
|
||||
|
||||
var varx: Int
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("f")<!>
|
||||
@platformName("f")
|
||||
get() = 1
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("g")<!>
|
||||
@platformName("g")
|
||||
set(v) {}
|
||||
}
|
||||
|
||||
fun foo1() {
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("a")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("a")<!>
|
||||
fun foo() {}
|
||||
|
||||
<!INAPPLICABLE_ANNOTATION!>@platformName("a")<!>
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("a")<!>
|
||||
val x = 1
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AB {
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("AB_absFun1")<!>
|
||||
abstract fun absFun1()
|
||||
|
||||
abstract fun absFun2()
|
||||
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("AB_openFun")<!>
|
||||
open fun openFun() {}
|
||||
}
|
||||
|
||||
class D: AB() {
|
||||
override fun absFun1() {}
|
||||
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("D_absFun2")<!>
|
||||
override fun absFun2() {}
|
||||
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("D_openFun")<!>
|
||||
final override fun openFun() {}
|
||||
|
||||
@platformName("D_finalFun")
|
||||
fun finalFun() {}
|
||||
}
|
||||
|
||||
Vendored
+22
-1
@@ -1,4 +1,4 @@
|
||||
package
|
||||
package
|
||||
|
||||
kotlin.platform.platformName(name = "c": kotlin.String) internal val px: kotlin.Int = 1
|
||||
internal val valx: kotlin.Int
|
||||
@@ -9,6 +9,16 @@ kotlin.platform.platformName(name = "a": kotlin.String) internal fun foo(): kotl
|
||||
internal fun foo1(): kotlin.Unit
|
||||
kotlin.platform.platformName(name = "b": kotlin.String) internal fun kotlin.Any.foo(): kotlin.Unit
|
||||
|
||||
internal abstract class AB {
|
||||
public constructor AB()
|
||||
kotlin.platform.platformName(name = "AB_absFun1": kotlin.String) internal abstract fun absFun1(): kotlin.Unit
|
||||
internal abstract fun absFun2(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
kotlin.platform.platformName(name = "AB_openFun": kotlin.String) internal open fun openFun(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
kotlin.platform.platformName(name = "C": kotlin.String) internal final class C {
|
||||
kotlin.platform.platformName(name = "primary": kotlin.String) public constructor C()
|
||||
kotlin.platform.platformName(name = "ctr": kotlin.String) public constructor C(/*0*/ x: kotlin.Int)
|
||||
@@ -22,3 +32,14 @@ kotlin.platform.platformName(name = "C": kotlin.String) internal final class C {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
kotlin.platform.platformName(name = "b": kotlin.String) internal final fun kotlin.Any.foo(): kotlin.Unit
|
||||
}
|
||||
|
||||
internal final class D : AB {
|
||||
public constructor D()
|
||||
internal open override /*1*/ fun absFun1(): kotlin.Unit
|
||||
kotlin.platform.platformName(name = "D_absFun2": kotlin.String) internal open override /*1*/ fun absFun2(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "D_finalFun": kotlin.String) internal final fun finalFun(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
kotlin.platform.platformName(name = "D_openFun": kotlin.String) internal final override /*1*/ fun openFun(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+18
-1
@@ -4,4 +4,21 @@ import kotlin.platform.*
|
||||
@platformName("bar")
|
||||
fun foo(a: Any) {}
|
||||
|
||||
fun Any.foo() {}
|
||||
fun Any.foo() {}
|
||||
|
||||
@platformName("barInt")
|
||||
fun bar(x: List<Int>) {}
|
||||
|
||||
@platformName("barStr")
|
||||
fun bar(x: List<String>) {}
|
||||
|
||||
class C {
|
||||
var rwProp: Int
|
||||
@platformName("get_rwProp")
|
||||
get() = 0
|
||||
@platformName("set_rwProp")
|
||||
set(v) {}
|
||||
|
||||
fun getRwProp(): Int = 123
|
||||
fun setRwProp(v: Int) {}
|
||||
}
|
||||
|
||||
+13
-1
@@ -1,4 +1,16 @@
|
||||
package
|
||||
package
|
||||
|
||||
kotlin.platform.platformName(name = "barInt": kotlin.String) internal fun bar(/*0*/ x: kotlin.List<kotlin.Int>): kotlin.Unit
|
||||
kotlin.platform.platformName(name = "barStr": kotlin.String) internal fun bar(/*0*/ x: kotlin.List<kotlin.String>): kotlin.Unit
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal fun foo(/*0*/ a: kotlin.Any): kotlin.Unit
|
||||
internal fun kotlin.Any.foo(): kotlin.Unit
|
||||
|
||||
internal final class C {
|
||||
public constructor C()
|
||||
internal final var rwProp: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal final fun getRwProp(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
internal final fun setRwProp(/*0*/ v: kotlin.Int): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
Vendored
+49
-1
@@ -4,4 +4,52 @@ import kotlin.platform.*
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>@platformName("bar")
|
||||
fun foo(a: Any)<!> {}
|
||||
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun bar(a: Any)<!> {}
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun bar(a: Any)<!> {}
|
||||
|
||||
class C {
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>@platformName("foo1")
|
||||
fun foo(list: List<Int>)<!> {}
|
||||
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>@platformName("foo1")
|
||||
fun foo(list: List<String>)<!> {}
|
||||
}
|
||||
|
||||
// Conflicts in inheritance.
|
||||
|
||||
// A1 -> B1 with accidental override
|
||||
|
||||
open class A1 {
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("bar")<!>
|
||||
open fun foo() {}
|
||||
}
|
||||
|
||||
class B1 : A1() {
|
||||
<!ACCIDENTAL_OVERRIDE!>fun bar()<!> {}
|
||||
}
|
||||
|
||||
// A2 -> B2 with intended override and conflicting JVM declarations
|
||||
|
||||
open class A2 {
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("bar")<!>
|
||||
open fun foo() {}
|
||||
}
|
||||
|
||||
class <!CONFLICTING_JVM_DECLARATIONS!>B2<!> : A2() {
|
||||
override fun foo() {}
|
||||
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>fun bar()<!> {}
|
||||
}
|
||||
|
||||
// A3 -> B3 -> C3 with accidental override
|
||||
|
||||
open class A3 {
|
||||
<!INAPPLICABLE_PLATFORM_NAME!>@platformName("bar")<!>
|
||||
open fun foo() {}
|
||||
}
|
||||
|
||||
open class B3: A3() {
|
||||
}
|
||||
|
||||
class C3: B3() {
|
||||
<!ACCIDENTAL_OVERRIDE!>fun bar()<!> {}
|
||||
}
|
||||
Vendored
+69
-1
@@ -1,4 +1,72 @@
|
||||
package
|
||||
package
|
||||
|
||||
internal fun bar(/*0*/ a: kotlin.Any): kotlin.Unit
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal fun foo(/*0*/ a: kotlin.Any): kotlin.Unit
|
||||
|
||||
internal open class A1 {
|
||||
public constructor A1()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal open class A2 {
|
||||
public constructor A2()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal open class A3 {
|
||||
public constructor A3()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class B1 : A1 {
|
||||
public constructor B1()
|
||||
internal final fun bar(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class B2 : A2 {
|
||||
public constructor B2()
|
||||
internal final fun bar(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
internal open override /*1*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal open class B3 : A3 {
|
||||
public constructor B3()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class C {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "foo1": kotlin.String) internal final fun foo(/*0*/ list: kotlin.List<kotlin.Int>): kotlin.Unit
|
||||
kotlin.platform.platformName(name = "foo1": kotlin.String) internal final fun foo(/*0*/ list: kotlin.List<kotlin.String>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
internal final class C3 : B3 {
|
||||
public constructor C3()
|
||||
internal final fun bar(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
kotlin.platform.platformName(name = "bar": kotlin.String) internal open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user