KT-2752: add draft implementation of JsName annotation. Fix some tests using the annotation
This commit is contained in:
@@ -23,7 +23,8 @@ enum class PredefinedAnnotation(fqName: String) {
|
|||||||
NATIVE("kotlin.js.native"),
|
NATIVE("kotlin.js.native"),
|
||||||
NATIVE_INVOKE("kotlin.js.nativeInvoke"),
|
NATIVE_INVOKE("kotlin.js.nativeInvoke"),
|
||||||
NATIVE_GETTER("kotlin.js.nativeGetter"),
|
NATIVE_GETTER("kotlin.js.nativeGetter"),
|
||||||
NATIVE_SETTER("kotlin.js.nativeSetter");
|
NATIVE_SETTER("kotlin.js.nativeSetter"),
|
||||||
|
JS_NAME("kotlin.js.JsName");
|
||||||
|
|
||||||
val fqName: FqName = FqName(fqName)
|
val fqName: FqName = FqName(fqName)
|
||||||
|
|
||||||
|
|||||||
@@ -135,11 +135,12 @@ class FQNGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (needsStableMangling(resolvedDescriptor)) {
|
val explicitName = getJsName(descriptor)
|
||||||
Pair(getStableMangledName(baseName, getArgumentTypesAsString(resolvedDescriptor)), true)
|
return when {
|
||||||
}
|
explicitName != null -> Pair(explicitName, true)
|
||||||
else {
|
needsStableMangling(resolvedDescriptor) ->
|
||||||
Pair(baseName, false)
|
Pair(getStableMangledName(baseName, getArgumentTypesAsString(resolvedDescriptor)), true)
|
||||||
|
else -> Pair(baseName, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,8 +168,7 @@ class FQNGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getStableMangledName(suggestedName: String, forCalculateId: String): String {
|
private fun getStableMangledName(suggestedName: String, forCalculateId: String): String {
|
||||||
val absHashCode = Math.abs(forCalculateId.hashCode())
|
val suffix = if (forCalculateId.isEmpty()) "" else "_${mangledId(forCalculateId)}\$"
|
||||||
val suffix = if (absHashCode == 0) "" else "_" + Integer.toString(absHashCode, Character.MAX_RADIX) + "$"
|
|
||||||
return suggestedName + suffix
|
return suggestedName + suffix
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,9 @@ class FQNGenerator {
|
|||||||
return when (containingDeclaration) {
|
return when (containingDeclaration) {
|
||||||
is PackageFragmentDescriptor -> descriptor.visibility.isPublicAPI
|
is PackageFragmentDescriptor -> descriptor.visibility.isPublicAPI
|
||||||
is ClassDescriptor -> {
|
is ClassDescriptor -> {
|
||||||
if (descriptor.modality == Modality.OPEN || descriptor.modality == Modality.ABSTRACT) return true
|
if (descriptor.modality == Modality.OPEN || descriptor.modality == Modality.ABSTRACT) {
|
||||||
|
return descriptor.visibility.isPublicAPI
|
||||||
|
}
|
||||||
|
|
||||||
// valueOf() is created in the library with a mangled name for every enum class
|
// valueOf() is created in the library with a mangled name for every enum class
|
||||||
if (descriptor is FunctionDescriptor && descriptor.isEnumValueOfMethod()) return true
|
if (descriptor is FunctionDescriptor && descriptor.isEnumValueOfMethod()) return true
|
||||||
@@ -210,4 +212,11 @@ class FQNGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic fun mangledId(forCalculateId: String): String {
|
||||||
|
val absHashCode = Math.abs(forCalculateId.hashCode())
|
||||||
|
return if (absHashCode != 0) Integer.toString(absHashCode, Character.MAX_RADIX) else ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,19 @@ public final class AnnotationsUtils {
|
|||||||
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.LIBRARY);
|
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.LIBRARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String getJsName(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
AnnotationDescriptor annotation = getAnnotationByName(descriptor, PredefinedAnnotation.JS_NAME.getFqName());
|
||||||
|
if (annotation == null) return null;
|
||||||
|
|
||||||
|
ConstantValue<?> value = annotation.getAllValueArguments().values().iterator().next();
|
||||||
|
assert value != null : "JsName annotation should always declare string parameter";
|
||||||
|
|
||||||
|
Object result = value.getValue();
|
||||||
|
assert result instanceof String : "Parameter of JsName annotation should be string";
|
||||||
|
return (String) result;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isPredefinedObject(@NotNull DeclarationDescriptor descriptor) {
|
public static boolean isPredefinedObject(@NotNull DeclarationDescriptor descriptor) {
|
||||||
for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) {
|
for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) {
|
||||||
if (hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) {
|
if (hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) {
|
||||||
|
|||||||
@@ -46,4 +46,8 @@ public annotation class enumerable()
|
|||||||
@native
|
@native
|
||||||
@Target(CLASS)
|
@Target(CLASS)
|
||||||
@Deprecated("Do not use this annotation: it is for internal use only")
|
@Deprecated("Do not use this annotation: it is for internal use only")
|
||||||
public annotation class marker
|
public annotation class marker
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR)
|
||||||
|
annotation class JsName(val name: String)
|
||||||
@@ -45,6 +45,7 @@ val Element?.elements: List<Element>
|
|||||||
get() = this?.elements() ?: emptyList()
|
get() = this?.elements() ?: emptyList()
|
||||||
|
|
||||||
@Deprecated("Use non-nullable receiver version elements()", ReplaceWith("this?.elements(localName) ?: emptyList()"))
|
@Deprecated("Use non-nullable receiver version elements()", ReplaceWith("this?.elements(localName) ?: emptyList()"))
|
||||||
|
@JsName("deprecated_elements")
|
||||||
fun Element?.elements(localName: String): List<Element> = this?.elements(localName) ?: emptyList()
|
fun Element?.elements(localName: String): List<Element> = this?.elements(localName) ?: emptyList()
|
||||||
|
|
||||||
/** Returns all the descendant elements given the local element name */
|
/** Returns all the descendant elements given the local element name */
|
||||||
@@ -53,11 +54,13 @@ fun Element.elements(localName: String = "*"): List<Element> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns all the descendant elements given the local element name */
|
/** Returns all the descendant elements given the local element name */
|
||||||
|
@JsName("deprecated_document_elements")
|
||||||
fun Document?.elements(localName: String = "*"): List<Element> {
|
fun Document?.elements(localName: String = "*"): List<Element> {
|
||||||
return this?.getElementsByTagName(localName)?.asElementList() ?: emptyList()
|
return this?.getElementsByTagName(localName)?.asElementList() ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Use non-nullable elements function instead", ReplaceWith("this?.elements(namespaceUri, localName) ?: emptyList()"))
|
@Deprecated("Use non-nullable elements function instead", ReplaceWith("this?.elements(namespaceUri, localName) ?: emptyList()"))
|
||||||
|
@JsName("deprecated_elements_2")
|
||||||
fun Element?.elements(namespaceUri: String, localName: String): List<Element> = this?.elements(namespaceUri, localName) ?: emptyList()
|
fun Element?.elements(namespaceUri: String, localName: String): List<Element> = this?.elements(namespaceUri, localName) ?: emptyList()
|
||||||
|
|
||||||
/** Returns all the descendant elements given the namespace URI and local element name */
|
/** Returns all the descendant elements given the namespace URI and local element name */
|
||||||
@@ -71,6 +74,7 @@ fun Document?.elements(namespaceUri: String, localName: String): List<Element> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Use non-null function instead with elvis", ReplaceWith("this?.asList() ?: emptyList()"))
|
@Deprecated("Use non-null function instead with elvis", ReplaceWith("this?.asList() ?: emptyList()"))
|
||||||
|
@JsName("deprecated_asList")
|
||||||
fun NodeList?.asList(): List<Node> = this?.asList() ?: emptyList()
|
fun NodeList?.asList(): List<Node> = this?.asList() ?: emptyList()
|
||||||
|
|
||||||
fun NodeList.asList(): List<Node> = NodeListAsList(this)
|
fun NodeList.asList(): List<Node> = NodeListAsList(this)
|
||||||
|
|||||||
@@ -17,48 +17,48 @@
|
|||||||
package kotlin.js.internal
|
package kotlin.js.internal
|
||||||
|
|
||||||
private object DoubleCompanionObject {
|
private object DoubleCompanionObject {
|
||||||
val MIN_VALUE: Double = js("Number.MIN_VALUE")
|
@JsName("MIN_VALUE") val MIN_VALUE: Double = js("Number.MIN_VALUE")
|
||||||
val MAX_VALUE: Double = js("Number.MAX_VALUE")
|
@JsName("MAX_VALUE") val MAX_VALUE: Double = js("Number.MAX_VALUE")
|
||||||
val POSITIVE_INFINITY: Double = js("Number.POSITIVE_INFINITY")
|
@JsName("POSITIVE_INFINITY") val POSITIVE_INFINITY: Double = js("Number.POSITIVE_INFINITY")
|
||||||
val NEGATIVE_INFINITY: Double = js("Number.NEGATIVE_INFINITY")
|
@JsName("NEGATIVE_INFINITY") val NEGATIVE_INFINITY: Double = js("Number.NEGATIVE_INFINITY")
|
||||||
val NaN: Double = js("Number.NaN")
|
@JsName("NaN") val NaN: Double = js("Number.NaN")
|
||||||
}
|
}
|
||||||
|
|
||||||
private object FloatCompanionObject {
|
private object FloatCompanionObject {
|
||||||
val MIN_VALUE: Float = js("Number.MIN_VALUE")
|
@JsName("MIN_VALUE") val MIN_VALUE: Float = js("Number.MIN_VALUE")
|
||||||
val MAX_VALUE: Float = js("Number.MAX_VALUE")
|
@JsName("MAX_VALUE") val MAX_VALUE: Float = js("Number.MAX_VALUE")
|
||||||
val POSITIVE_INFINITY: Float = js("Number.POSITIVE_INFINITY")
|
@JsName("POSITIVE_INFINITY") val POSITIVE_INFINITY: Float = js("Number.POSITIVE_INFINITY")
|
||||||
val NEGATIVE_INFINITY: Float = js("Number.NEGATIVE_INFINITY")
|
@JsName("NEGATIVE_INFINITY") val NEGATIVE_INFINITY: Float = js("Number.NEGATIVE_INFINITY")
|
||||||
val NaN: Float = js("Number.NaN")
|
@JsName("NaN") val NaN: Float = js("Number.NaN")
|
||||||
}
|
}
|
||||||
|
|
||||||
private object IntCompanionObject {
|
private object IntCompanionObject {
|
||||||
val MIN_VALUE: Int = -2147483647 - 1
|
@JsName("MIN_VALUE") val MIN_VALUE: Int = -2147483647 - 1
|
||||||
val MAX_VALUE: Int = 2147483647
|
@JsName("MAX_VALUE") val MAX_VALUE: Int = 2147483647
|
||||||
}
|
}
|
||||||
|
|
||||||
private object LongCompanionObject {
|
private object LongCompanionObject {
|
||||||
val MIN_VALUE: Long = js("Kotlin.Long.MIN_VALUE")
|
@JsName("MIN_VALUE") val MIN_VALUE: Long = js("Kotlin.Long.MIN_VALUE")
|
||||||
val MAX_VALUE: Long = js("Kotlin.Long.MAX_VALUE")
|
@JsName("MAX_VALUE") val MAX_VALUE: Long = js("Kotlin.Long.MAX_VALUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
private object ShortCompanionObject {
|
private object ShortCompanionObject {
|
||||||
val MIN_VALUE: Short = -32768
|
@JsName("MIN_VALUE") val MIN_VALUE: Short = -32768
|
||||||
val MAX_VALUE: Short = 32767
|
@JsName("MAX_VALUE") val MAX_VALUE: Short = 32767
|
||||||
}
|
}
|
||||||
|
|
||||||
private object ByteCompanionObject {
|
private object ByteCompanionObject {
|
||||||
val MIN_VALUE: Byte = -128
|
@JsName("MIN_VALUE") val MIN_VALUE: Byte = -128
|
||||||
val MAX_VALUE: Byte = 127
|
@JsName("MAX_VALUE") val MAX_VALUE: Byte = 127
|
||||||
}
|
}
|
||||||
|
|
||||||
private object CharCompanionObject {
|
private object CharCompanionObject {
|
||||||
public const val MIN_HIGH_SURROGATE: Char = '\uD800'
|
@JsName("MIN_HIGH_SURROGATE") public const val MIN_HIGH_SURROGATE: Char = '\uD800'
|
||||||
public const val MAX_HIGH_SURROGATE: Char = '\uDBFF'
|
@JsName("MAX_HIGH_SURROGATE") public const val MAX_HIGH_SURROGATE: Char = '\uDBFF'
|
||||||
public const val MIN_LOW_SURROGATE: Char = '\uDC00'
|
@JsName("MIN_LOW_SURROGATE") public const val MIN_LOW_SURROGATE: Char = '\uDC00'
|
||||||
public const val MAX_LOW_SURROGATE: Char = '\uDFFF'
|
@JsName("MAX_LOW_SURROGATE") public const val MAX_LOW_SURROGATE: Char = '\uDFFF'
|
||||||
public const val MIN_SURROGATE: Char = MIN_HIGH_SURROGATE
|
@JsName("MIN_SURROGATE") public const val MIN_SURROGATE: Char = MIN_HIGH_SURROGATE
|
||||||
public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
|
@JsName("MAX_SURROGATE") public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
|
||||||
}
|
}
|
||||||
|
|
||||||
private object StringCompanionObject {}
|
private object StringCompanionObject {}
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ val mixed_b = { mixed_boo() + mixed_boo(1) + mixed_boo("str") + mixed_boo("str",
|
|||||||
|
|
||||||
|
|
||||||
class TestInternal {
|
class TestInternal {
|
||||||
fun foo(): Int = 1
|
@JsName("foo") internal fun foo(): Int = 1
|
||||||
fun foo(i: Int): Int = 2
|
@JsName("foo_2") internal fun foo(i: Int): Int = 2
|
||||||
|
|
||||||
fun boo(i: Int): Int = 2
|
@JsName("boo_2") internal fun boo(i: Int): Int = 2
|
||||||
fun boo(s: String): Int = 3
|
@JsName("boo_3") internal fun boo(s: String): Int = 3
|
||||||
fun boo(): Int = 1
|
@JsName("boo") internal fun boo(): Int = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val internal_in_class_f = { TestInternal().foo() + TestInternal().foo(1) }
|
val internal_in_class_f = { TestInternal().foo() + TestInternal().foo(1) }
|
||||||
@@ -128,25 +128,15 @@ val public_ext_f: A.() -> Int = { -> this.foo() + this.foo }
|
|||||||
val public_ext_b: A.() -> Int = { -> this.boo() + this.boo }
|
val public_ext_b: A.() -> Int = { -> this.boo() + this.boo }
|
||||||
|
|
||||||
interface TestPublicInTrait {
|
interface TestPublicInTrait {
|
||||||
public fun foo(): Int = 2
|
@JsName("foo") fun foo(): Int = 2
|
||||||
public val foo: Int
|
@JsName("fooProp") val foo: Int
|
||||||
public val boo: Int
|
@JsName("booProp") val boo: Int
|
||||||
public fun boo(): Int = 2
|
@JsName("boo") fun boo(): Int = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
val public_in_trait_f = { obj: TestPublicInTrait -> obj.foo() + obj.foo }
|
val public_in_trait_f = { obj: TestPublicInTrait -> obj.foo() + obj.foo }
|
||||||
val public_in_trait_b = { obj: TestPublicInTrait -> obj.boo() + obj.boo }
|
val public_in_trait_b = { obj: TestPublicInTrait -> obj.boo() + obj.boo }
|
||||||
|
|
||||||
interface TestInternalInTrait {
|
|
||||||
fun foo(): Int = 2
|
|
||||||
val foo: Int
|
|
||||||
val boo: Int
|
|
||||||
fun boo(): Int = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
val internal_in_trait_f = { obj: TestInternalInTrait -> obj.foo() + obj.foo }
|
|
||||||
val internal_in_trait_b = { obj: TestInternalInTrait -> obj.boo() + obj.boo }
|
|
||||||
|
|
||||||
//Testing
|
//Testing
|
||||||
|
|
||||||
fun test(testName: String, ff: Any, fb: Any) {
|
fun test(testName: String, ff: Any, fb: Any) {
|
||||||
@@ -169,7 +159,6 @@ fun box(): String {
|
|||||||
|
|
||||||
test("public_ext_prop", public_ext_f, public_ext_b)
|
test("public_ext_prop", public_ext_f, public_ext_b)
|
||||||
test("public_in_trait", public_in_trait_f, public_in_trait_b)
|
test("public_in_trait", public_in_trait_f, public_in_trait_b)
|
||||||
test("internal_in_trait", internal_in_trait_f, internal_in_trait_b)
|
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class TrafficLight(override var pos: Vector, val direction: String, val startCol
|
|||||||
var timer = Timer(Vector(pos.x + 6, pos.y + 12))
|
var timer = Timer(Vector(pos.x + 6, pos.y + 12))
|
||||||
var currentColor = startColor;
|
var currentColor = startColor;
|
||||||
var isForceColorChange = false
|
var isForceColorChange = false
|
||||||
var changeColorForward = (startColor == "red")
|
private var changeColorForward = (startColor == "red")
|
||||||
|
|
||||||
init {
|
init {
|
||||||
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "red_color.png"))
|
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "red_color.png"))
|
||||||
|
|||||||
Reference in New Issue
Block a user