KT-2752: add draft implementation of JsName annotation. Fix some tests using the annotation

This commit is contained in:
Alexey Andreev
2016-05-30 12:35:41 +03:00
parent 8738458c34
commit 5e3aa33b13
8 changed files with 75 additions and 55 deletions
@@ -23,7 +23,8 @@ enum class PredefinedAnnotation(fqName: String) {
NATIVE("kotlin.js.native"),
NATIVE_INVOKE("kotlin.js.nativeInvoke"),
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)
@@ -135,11 +135,12 @@ class FQNGenerator {
}
}
return if (needsStableMangling(resolvedDescriptor)) {
Pair(getStableMangledName(baseName, getArgumentTypesAsString(resolvedDescriptor)), true)
}
else {
Pair(baseName, false)
val explicitName = getJsName(descriptor)
return when {
explicitName != null -> Pair(explicitName, true)
needsStableMangling(resolvedDescriptor) ->
Pair(getStableMangledName(baseName, getArgumentTypesAsString(resolvedDescriptor)), true)
else -> Pair(baseName, false)
}
}
@@ -167,8 +168,7 @@ class FQNGenerator {
}
private fun getStableMangledName(suggestedName: String, forCalculateId: String): String {
val absHashCode = Math.abs(forCalculateId.hashCode())
val suffix = if (absHashCode == 0) "" else "_" + Integer.toString(absHashCode, Character.MAX_RADIX) + "$"
val suffix = if (forCalculateId.isEmpty()) "" else "_${mangledId(forCalculateId)}\$"
return suggestedName + suffix
}
@@ -187,7 +187,9 @@ class FQNGenerator {
return when (containingDeclaration) {
is PackageFragmentDescriptor -> descriptor.visibility.isPublicAPI
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
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);
}
@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) {
for (PredefinedAnnotation annotation : PredefinedAnnotation.values()) {
if (hasAnnotationOrInsideAnnotatedClass(descriptor, annotation)) {
+5 -1
View File
@@ -46,4 +46,8 @@ public annotation class enumerable()
@native
@Target(CLASS)
@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)
+4
View File
@@ -45,6 +45,7 @@ val Element?.elements: List<Element>
get() = this?.elements() ?: 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()
/** 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 */
@JsName("deprecated_document_elements")
fun Document?.elements(localName: String = "*"): List<Element> {
return this?.getElementsByTagName(localName)?.asElementList() ?: 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()
/** 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()"))
@JsName("deprecated_asList")
fun NodeList?.asList(): List<Node> = this?.asList() ?: emptyList()
fun NodeList.asList(): List<Node> = NodeListAsList(this)
@@ -17,48 +17,48 @@
package kotlin.js.internal
private object DoubleCompanionObject {
val MIN_VALUE: Double = js("Number.MIN_VALUE")
val MAX_VALUE: Double = js("Number.MAX_VALUE")
val POSITIVE_INFINITY: Double = js("Number.POSITIVE_INFINITY")
val NEGATIVE_INFINITY: Double = js("Number.NEGATIVE_INFINITY")
val NaN: Double = js("Number.NaN")
@JsName("MIN_VALUE") val MIN_VALUE: Double = js("Number.MIN_VALUE")
@JsName("MAX_VALUE") val MAX_VALUE: Double = js("Number.MAX_VALUE")
@JsName("POSITIVE_INFINITY") val POSITIVE_INFINITY: Double = js("Number.POSITIVE_INFINITY")
@JsName("NEGATIVE_INFINITY") val NEGATIVE_INFINITY: Double = js("Number.NEGATIVE_INFINITY")
@JsName("NaN") val NaN: Double = js("Number.NaN")
}
private object FloatCompanionObject {
val MIN_VALUE: Float = js("Number.MIN_VALUE")
val MAX_VALUE: Float = js("Number.MAX_VALUE")
val POSITIVE_INFINITY: Float = js("Number.POSITIVE_INFINITY")
val NEGATIVE_INFINITY: Float = js("Number.NEGATIVE_INFINITY")
val NaN: Float = js("Number.NaN")
@JsName("MIN_VALUE") val MIN_VALUE: Float = js("Number.MIN_VALUE")
@JsName("MAX_VALUE") val MAX_VALUE: Float = js("Number.MAX_VALUE")
@JsName("POSITIVE_INFINITY") val POSITIVE_INFINITY: Float = js("Number.POSITIVE_INFINITY")
@JsName("NEGATIVE_INFINITY") val NEGATIVE_INFINITY: Float = js("Number.NEGATIVE_INFINITY")
@JsName("NaN") val NaN: Float = js("Number.NaN")
}
private object IntCompanionObject {
val MIN_VALUE: Int = -2147483647 - 1
val MAX_VALUE: Int = 2147483647
@JsName("MIN_VALUE") val MIN_VALUE: Int = -2147483647 - 1
@JsName("MAX_VALUE") val MAX_VALUE: Int = 2147483647
}
private object LongCompanionObject {
val MIN_VALUE: Long = js("Kotlin.Long.MIN_VALUE")
val MAX_VALUE: Long = js("Kotlin.Long.MAX_VALUE")
@JsName("MIN_VALUE") val MIN_VALUE: Long = js("Kotlin.Long.MIN_VALUE")
@JsName("MAX_VALUE") val MAX_VALUE: Long = js("Kotlin.Long.MAX_VALUE")
}
private object ShortCompanionObject {
val MIN_VALUE: Short = -32768
val MAX_VALUE: Short = 32767
@JsName("MIN_VALUE") val MIN_VALUE: Short = -32768
@JsName("MAX_VALUE") val MAX_VALUE: Short = 32767
}
private object ByteCompanionObject {
val MIN_VALUE: Byte = -128
val MAX_VALUE: Byte = 127
@JsName("MIN_VALUE") val MIN_VALUE: Byte = -128
@JsName("MAX_VALUE") val MAX_VALUE: Byte = 127
}
private object CharCompanionObject {
public const val MIN_HIGH_SURROGATE: Char = '\uD800'
public const val MAX_HIGH_SURROGATE: Char = '\uDBFF'
public const val MIN_LOW_SURROGATE: Char = '\uDC00'
public const val MAX_LOW_SURROGATE: Char = '\uDFFF'
public const val MIN_SURROGATE: Char = MIN_HIGH_SURROGATE
public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
@JsName("MIN_HIGH_SURROGATE") public const val MIN_HIGH_SURROGATE: Char = '\uD800'
@JsName("MAX_HIGH_SURROGATE") public const val MAX_HIGH_SURROGATE: Char = '\uDBFF'
@JsName("MIN_LOW_SURROGATE") public const val MIN_LOW_SURROGATE: Char = '\uDC00'
@JsName("MAX_LOW_SURROGATE") public const val MAX_LOW_SURROGATE: Char = '\uDFFF'
@JsName("MIN_SURROGATE") public const val MIN_SURROGATE: Char = MIN_HIGH_SURROGATE
@JsName("MAX_SURROGATE") public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
}
private object StringCompanionObject {}
@@ -56,12 +56,12 @@ val mixed_b = { mixed_boo() + mixed_boo(1) + mixed_boo("str") + mixed_boo("str",
class TestInternal {
fun foo(): Int = 1
fun foo(i: Int): Int = 2
@JsName("foo") internal fun foo(): Int = 1
@JsName("foo_2") internal fun foo(i: Int): Int = 2
fun boo(i: Int): Int = 2
fun boo(s: String): Int = 3
fun boo(): Int = 1
@JsName("boo_2") internal fun boo(i: Int): Int = 2
@JsName("boo_3") internal fun boo(s: String): Int = 3
@JsName("boo") internal fun boo(): Int = 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 }
interface TestPublicInTrait {
public fun foo(): Int = 2
public val foo: Int
public val boo: Int
public fun boo(): Int = 2
@JsName("foo") fun foo(): Int = 2
@JsName("fooProp") val foo: Int
@JsName("booProp") val boo: Int
@JsName("boo") fun boo(): Int = 2
}
val public_in_trait_f = { obj: TestPublicInTrait -> obj.foo() + obj.foo }
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
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_in_trait", public_in_trait_f, public_in_trait_b)
test("internal_in_trait", internal_in_trait_f, internal_in_trait_b)
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 currentColor = startColor;
var isForceColorChange = false
var changeColorForward = (startColor == "red")
private var changeColorForward = (startColor == "red")
init {
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "red_color.png"))