KT-2752: fix JsName with explicit use target. Add some tests for JsName with use targets
This commit is contained in:
+5
@@ -0,0 +1,5 @@
|
||||
class A {
|
||||
@property:JsName("x_") <!JS_NAME_ON_ACCESSOR_AND_PROPERTY!>@get:JsName("getX_")<!> val x: Int = 0
|
||||
|
||||
<!JS_NAME_IS_NOT_ON_ALL_ACCESSORS!>@get:JsName("getY_") var y: Int = 0<!>
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
@property:kotlin.js.JsName(name = "x_") public final val x: kotlin.Int = 0
|
||||
public final var y: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -349,6 +349,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jsNameUseTargetOnProperty.kt")
|
||||
public void testJsNameUseTargetOnProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameUseTargetOnProperty.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("methodAndMethod.kt")
|
||||
public void testMethodAndMethod() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/methodAndMethod.kt");
|
||||
|
||||
@@ -37,7 +37,7 @@ object JsNameChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
|
||||
if (AnnotationsUtils.getJsName(descriptor) == null) return
|
||||
val jsNamePsi = AnnotationsUtils.getJsNameAnnotationPsi(bindingContext, declaration) ?: return
|
||||
val jsNamePsi = AnnotationsUtils.getJsNameAnnotationPsi(bindingContext, declaration, descriptor) ?: return
|
||||
|
||||
when (descriptor) {
|
||||
is ConstructorDescriptor -> {
|
||||
|
||||
@@ -22,15 +22,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.js.PredefinedAnnotation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.psi.KtAnnotated;
|
||||
import org.jetbrains.kotlin.psi.KtAnnotation;
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
|
||||
@@ -124,7 +122,8 @@ public final class AnnotationsUtils {
|
||||
|
||||
@Nullable
|
||||
private static AnnotationDescriptor getAnnotationByName(@NotNull DeclarationDescriptor descriptor, @NotNull FqName fqName) {
|
||||
return descriptor.getAnnotations().findAnnotation(fqName);
|
||||
AnnotationWithTarget annotationWithTarget = Annotations.Companion.findAnyAnnotation(descriptor.getAnnotations(), (fqName));
|
||||
return annotationWithTarget != null ? annotationWithTarget.getAnnotation() : null;
|
||||
}
|
||||
|
||||
public static boolean isNativeObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
@@ -137,15 +136,9 @@ public final class AnnotationsUtils {
|
||||
|
||||
@Nullable
|
||||
public static String getJsName(@NotNull DeclarationDescriptor descriptor) {
|
||||
AnnotationDescriptor annotation = getAnnotationByName(descriptor, new FqName(JS_NAME));
|
||||
AnnotationDescriptor annotation = getJsNameAnnotation(descriptor);
|
||||
if (annotation == null) return null;
|
||||
|
||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
PropertyAccessorDescriptor accessor = (PropertyAccessorDescriptor) descriptor;
|
||||
AnnotationDescriptor propertyAnnotation = getAnnotationByName(accessor.getCorrespondingProperty(), new FqName(JS_NAME));
|
||||
if (propertyAnnotation == annotation) return null;
|
||||
}
|
||||
|
||||
ConstantValue<?> value = annotation.getAllValueArguments().values().iterator().next();
|
||||
assert value != null : "JsName annotation should always declare string parameter";
|
||||
|
||||
@@ -155,26 +148,28 @@ public final class AnnotationsUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static KtAnnotationEntry getJsNameAnnotationPsi(@NotNull BindingContext context, @NotNull KtAnnotated annotated) {
|
||||
return findAnnotationPsi(context, annotated, new FqName(JS_NAME));
|
||||
private static AnnotationDescriptor getJsNameAnnotation(@NotNull DeclarationDescriptor descriptor) {
|
||||
AnnotationDescriptor annotation = getAnnotationByName(descriptor, new FqName(JS_NAME));
|
||||
if (annotation == null) return null;
|
||||
|
||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
PropertyAccessorDescriptor accessor = (PropertyAccessorDescriptor) descriptor;
|
||||
AnnotationDescriptor propertyAnnotation = getAnnotationByName(accessor.getCorrespondingProperty(), new FqName(JS_NAME));
|
||||
if (propertyAnnotation == annotation) return null;
|
||||
}
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KtAnnotationEntry findAnnotationPsi(
|
||||
@NotNull BindingContext context, @NotNull KtAnnotated annotated,
|
||||
@NotNull FqName nameToFind
|
||||
) {
|
||||
FqNameUnsafe nameToFindUnsafe = nameToFind.toUnsafe();
|
||||
public static KtAnnotationEntry getJsNameAnnotationPsi(@NotNull BindingContext context, @NotNull KtAnnotated annotated,
|
||||
@NotNull DeclarationDescriptor descriptor) {
|
||||
AnnotationDescriptor annotation = getJsNameAnnotation(descriptor);
|
||||
if (annotation == null) return null;
|
||||
|
||||
for (KtAnnotationEntry entry : annotated.getAnnotationEntries()) {
|
||||
AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, entry);
|
||||
assert annotationDescriptor != null : "Annotation descriptor expected for annotation entry: " +
|
||||
PsiUtilsKt.getTextWithLocation(entry);
|
||||
ClassifierDescriptor typeDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor();
|
||||
assert typeDescriptor instanceof ClassDescriptor : "Annotation type should be ClassDescriptor: " +
|
||||
PsiUtilsKt.getTextWithLocation(entry);
|
||||
FqNameUnsafe entryName = DescriptorUtils.getFqName(typeDescriptor);
|
||||
if (entryName.equals(nameToFindUnsafe)) {
|
||||
if (annotationDescriptor == annotation) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package kotlin.js
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
@native
|
||||
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, VALUE_PARAMETER)
|
||||
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
public annotation class native(public val name: String = "")
|
||||
|
||||
@native
|
||||
|
||||
@@ -1177,6 +1177,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jsNamePropertyDelegation.kt")
|
||||
public void testJsNamePropertyDelegation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/delegation/jsNamePropertyDelegation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("onObject.kt")
|
||||
public void testOnObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/delegation/onObject.kt");
|
||||
@@ -5281,6 +5287,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jsNamePropertyAccessors.kt")
|
||||
public void testJsNamePropertyAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/jsNamePropertyAccessors.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt1519.kt")
|
||||
public void testKt1519() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/kt1519.kt");
|
||||
@@ -5880,6 +5892,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("accessorsWithJsName.kt")
|
||||
public void testAccessorsWithJsName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/propertyAccess/accessorsWithJsName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPropertyAccess() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/propertyAccess"), Pattern.compile("^([^_](.+))\\.kt$"), true);
|
||||
}
|
||||
@@ -5902,6 +5920,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultAccessorsWithJsName.kt")
|
||||
public void testDefaultAccessorsWithJsName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/propertyAccess/defaultAccessorsWithJsName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enumerable.kt")
|
||||
public void testEnumerable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/propertyAccess/enumerable.kt");
|
||||
@@ -5980,6 +6004,18 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("staticAccessorsWithJsName.kt")
|
||||
public void testStaticAccessorsWithJsName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/propertyAccess/staticAccessorsWithJsName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("subclassAccessorsWithJsNameInSuper.kt")
|
||||
public void testSubclassAccessorsWithJsNameInSuper() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/propertyAccess/subclassAccessorsWithJsNameInSuper.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("twoClassesWithProperties.kt")
|
||||
public void testTwoClassesWithProperties() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/propertyAccess/twoClassesWithProperties.kt");
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
|
||||
+4
-4
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
|
||||
@@ -42,7 +42,7 @@ object NativeVariableAccessCase : VariableAccessCase() {
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val methodRef = context.getNameForDescriptor(getAccessDescriptor())
|
||||
JsInvocation(fqnWithoutSideEffects(methodRef, dispatchReceiver!!), *additionalArguments.toTypedArray())
|
||||
JsInvocation(pureFqn(methodRef, dispatchReceiver!!), *additionalArguments.toTypedArray())
|
||||
}
|
||||
else {
|
||||
constructAccessExpression(JsNameRef(variableName, dispatchReceiver!!))
|
||||
@@ -152,8 +152,8 @@ object SuperPropertyAccessCase : VariableAccessCase() {
|
||||
|
||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val accessor = getAccessDescriptor()
|
||||
val prototype = fqnWithoutSideEffects(Namer.getPrototypeName(), context.getQualifiedReference(descriptor.containingDeclaration))
|
||||
val funRef = Namer.getFunctionCallRef(fqnWithoutSideEffects(context.getNameForDescriptor(accessor), prototype))
|
||||
val prototype = pureFqn(Namer.getPrototypeName(), context.getQualifiedReference(descriptor.containingDeclaration))
|
||||
val funRef = Namer.getFunctionCallRef(pureFqn(context.getNameForDescriptor(accessor), prototype))
|
||||
val arguments = listOf(dispatchReceiver!!) + additionalArguments
|
||||
JsInvocation(funRef, *arguments.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ public final class JsDescriptorUtils {
|
||||
return !isExtension(propertyDescriptor) &&
|
||||
isDefaultAccessor(propertyDescriptor.getGetter()) &&
|
||||
isDefaultAccessor(propertyDescriptor.getSetter()) &&
|
||||
!TranslationUtils.shouldGenerateAccessors(propertyDescriptor) &&
|
||||
!ModalityKt.isOverridableOrOverrides(propertyDescriptor);
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -3,19 +3,23 @@ package foo
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class A {
|
||||
@JsName("xx") val x: Int by B()
|
||||
@JsName("xx") val x: Int by B(23)
|
||||
|
||||
@get:JsName("getYY") val y: Int by B(42)
|
||||
}
|
||||
|
||||
class B {
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = 23
|
||||
class B(val value: Int) {
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
assertEquals(23, a.x)
|
||||
assertEquals(42, a.y)
|
||||
|
||||
val d: dynamic = a
|
||||
assertEquals(23, d.xx)
|
||||
assertEquals(42, d.getYY())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+2
-2
@@ -3,10 +3,10 @@ package foo
|
||||
|
||||
fun bar(x: Int) = x
|
||||
|
||||
fun box(): Boolean {
|
||||
fun box(): String {
|
||||
assertEquals(23, bar(23))
|
||||
assertEquals(42, foo.bar.x)
|
||||
return true
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: foobar.kt
|
||||
|
||||
+2
-2
@@ -5,12 +5,12 @@ private fun bar() = 23
|
||||
|
||||
private val bar = 42
|
||||
|
||||
fun box(): Boolean {
|
||||
fun box(): String {
|
||||
assertEquals(23, bar())
|
||||
assertEquals(42, bar)
|
||||
assertEquals(32, foo.bar.x)
|
||||
|
||||
return true
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: foobar.kt
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package foo
|
||||
|
||||
class A {
|
||||
@get:JsName("getX_") val x = 23
|
||||
|
||||
@get:JsName("getY_") @set:JsName("setY_") var y = 0
|
||||
|
||||
@JsName("z_") var z = 0
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
|
||||
assertEquals(23, a.x)
|
||||
assertEquals(0, a.y)
|
||||
a.y = 42
|
||||
assertEquals(42, a.y)
|
||||
a.z = 99
|
||||
assertEquals(99, a.z)
|
||||
|
||||
val d: dynamic = A()
|
||||
|
||||
assertEquals(23, d.getX_())
|
||||
assertEquals(0, d.getY_())
|
||||
d.setY_(42)
|
||||
assertEquals(42, d.getY_())
|
||||
d.z_ = 99
|
||||
assertEquals(99, d.z_)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// ONLY_THIS_QUALIFIED_REFERENCES: foo_qltb3l$
|
||||
// ONLY_THIS_QUALIFIED_REFERENCES: foo_0
|
||||
|
||||
package foo
|
||||
|
||||
|
||||
+9
-1
@@ -11,7 +11,11 @@ open class A {
|
||||
}
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
interface C {
|
||||
@get:JsName("getZ_") val z: Int
|
||||
}
|
||||
|
||||
class B : A(), C {
|
||||
override val x: Int
|
||||
get() = 42
|
||||
|
||||
@@ -20,6 +24,8 @@ class B : A() {
|
||||
set(value) {
|
||||
super.y = value + 2
|
||||
}
|
||||
|
||||
override val z = 55
|
||||
}
|
||||
|
||||
fun getPackage() = js("return Kotlin.modules.JS_TESTS.foo")
|
||||
@@ -31,6 +37,7 @@ fun box(): String {
|
||||
assertEquals(15, a.y)
|
||||
a.y = 13
|
||||
assertEquals(30, a.y)
|
||||
assertEquals(55, a.z)
|
||||
|
||||
val d: dynamic = B()
|
||||
|
||||
@@ -38,6 +45,7 @@ fun box(): String {
|
||||
assertEquals(15, d.getY_())
|
||||
d.setY_(13)
|
||||
assertEquals(30, d.getY_())
|
||||
assertEquals(55, d.getZ_())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user