Fix delegate property name clash in JS BE
See KT-19542
This commit is contained in:
@@ -1106,6 +1106,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("clashingNameInSubclass.kt")
|
||||||
|
public void testClashingNameInSubclass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/delegateProperty/clashingNameInSubclass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("delegateByExtensionProperty.kt")
|
@TestMetadata("delegateByExtensionProperty.kt")
|
||||||
public void testDelegateByExtensionProperty() throws Exception {
|
public void testDelegateByExtensionProperty() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/delegateProperty/delegateByExtensionProperty.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/delegateProperty/delegateByExtensionProperty.kt");
|
||||||
|
|||||||
@@ -159,16 +159,6 @@ public final class Namer {
|
|||||||
return DELEGATE;
|
return DELEGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String getDelegateName(@NotNull String propertyName) {
|
|
||||||
return propertyName + DELEGATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsNameRef getDelegateNameRef(String propertyName) {
|
|
||||||
return new JsNameRef(getDelegateName(propertyName), new JsThisRef());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
|
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
|
||||||
return pureFqn(CALL_FUNCTION, functionExpression);
|
return pureFqn(CALL_FUNCTION, functionExpression);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public final class StaticContext {
|
|||||||
private final Map<DeclarationDescriptor, JsName> nameCache = new HashMap<>();
|
private final Map<DeclarationDescriptor, JsName> nameCache = new HashMap<>();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Map<PropertyDescriptor, JsName> backingFieldNameCache = new HashMap<>();
|
private final Map<VariableDescriptorWithAccessors, JsName> backingFieldNameCache = new HashMap<>();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Map<DeclarationDescriptor, JsExpression> fqnCache = new HashMap<>();
|
private final Map<DeclarationDescriptor, JsExpression> fqnCache = new HashMap<>();
|
||||||
@@ -353,7 +353,7 @@ public final class StaticContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName getNameForBackingField(@NotNull PropertyDescriptor property) {
|
public JsName getNameForBackingField(@NotNull VariableDescriptorWithAccessors property) {
|
||||||
JsName name = backingFieldNameCache.get(property);
|
JsName name = backingFieldNameCache.get(property);
|
||||||
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
|
|||||||
+1
-1
@@ -407,7 +407,7 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName getNameForBackingField(@NotNull PropertyDescriptor property) {
|
public JsName getNameForBackingField(@NotNull VariableDescriptorWithAccessors property) {
|
||||||
return staticContext.getNameForBackingField(property);
|
return staticContext.getNameForBackingField(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -412,7 +412,7 @@ class ClassTranslator private constructor(
|
|||||||
function.parameters.add(i, JsParameter(name))
|
function.parameters.add(i, JsParameter(name))
|
||||||
if (fieldName != null && constructor == primaryConstructor) {
|
if (fieldName != null && constructor == primaryConstructor) {
|
||||||
val source = (constructor.descriptor as? DeclarationDescriptorWithSource)?.source
|
val source = (constructor.descriptor as? DeclarationDescriptorWithSource)?.source
|
||||||
additionalStatements += JsAstUtils.defineSimpleProperty(fieldName.ident, name.makeRef(), source)
|
additionalStatements += JsAstUtils.defineSimpleProperty(fieldName, name.makeRef(), source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -170,7 +170,6 @@ class DeclarationBodyVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression {
|
override fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression =
|
||||||
return Namer.getDelegateNameRef(descriptor.name.asString())
|
JsNameRef(context.getNameForBackingField(descriptor), JsThisRef())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
|||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer.getDelegateNameRef
|
|
||||||
import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName
|
import org.jetbrains.kotlin.js.translate.context.Namer.getReceiverParameterName
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
|
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
|
||||||
@@ -225,7 +224,7 @@ private class PropertyTranslator(
|
|||||||
private fun generateDefaultGetter(): JsPropertyInitializer {
|
private fun generateDefaultGetter(): JsPropertyInitializer {
|
||||||
val getterDescriptor = descriptor.getter ?: throw IllegalStateException("Getter descriptor should not be null")
|
val getterDescriptor = descriptor.getter ?: throw IllegalStateException("Getter descriptor should not be null")
|
||||||
val defaultFunction = createFunction(getterDescriptor).apply {
|
val defaultFunction = createFunction(getterDescriptor).apply {
|
||||||
val delegateRef = getDelegateNameRef(descriptor.name.asString())
|
val delegateRef = JsNameRef(context().getNameForBackingField(descriptor), JsThisRef())
|
||||||
DefaultPropertyTranslator(descriptor, context(), delegateRef).generateDefaultGetterFunction(getterDescriptor, this)
|
DefaultPropertyTranslator(descriptor, context(), delegateRef).generateDefaultGetterFunction(getterDescriptor, this)
|
||||||
}
|
}
|
||||||
return generateDefaultAccessor(getterDescriptor, defaultFunction)
|
return generateDefaultAccessor(getterDescriptor, defaultFunction)
|
||||||
@@ -234,7 +233,7 @@ private class PropertyTranslator(
|
|||||||
private fun generateDefaultSetter(): JsPropertyInitializer {
|
private fun generateDefaultSetter(): JsPropertyInitializer {
|
||||||
val setterDescriptor = descriptor.setter ?: throw IllegalStateException("Setter descriptor should not be null")
|
val setterDescriptor = descriptor.setter ?: throw IllegalStateException("Setter descriptor should not be null")
|
||||||
val defaultFunction = createFunction(setterDescriptor).apply {
|
val defaultFunction = createFunction(setterDescriptor).apply {
|
||||||
val delegateRef = getDelegateNameRef(descriptor.name.asString())
|
val delegateRef = JsNameRef(context().getNameForBackingField(descriptor), JsThisRef())
|
||||||
DefaultPropertyTranslator(descriptor, context(), delegateRef).generateDefaultSetterFunction(setterDescriptor, this)
|
DefaultPropertyTranslator(descriptor, context(), delegateRef).generateDefaultSetterFunction(setterDescriptor, this)
|
||||||
}
|
}
|
||||||
return generateDefaultAccessor(setterDescriptor, defaultFunction)
|
return generateDefaultAccessor(setterDescriptor, defaultFunction)
|
||||||
|
|||||||
+3
-3
@@ -43,12 +43,12 @@ public final class InitializerUtils {
|
|||||||
return assignment.makeStmt();
|
return assignment.makeStmt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
public static JsStatement generateInitializerForDelegate(
|
public static JsStatement generateInitializerForDelegate(
|
||||||
|
@NotNull TranslationContext context,
|
||||||
@NotNull PropertyDescriptor descriptor,
|
@NotNull PropertyDescriptor descriptor,
|
||||||
@NotNull JsExpression value
|
@NotNull JsExpression value
|
||||||
) {
|
) {
|
||||||
String name = descriptor.getName().asString();
|
return JsAstUtils.defineSimpleProperty(context.getNameForBackingField(descriptor), value, descriptor.getSource());
|
||||||
return JsAstUtils.defineSimpleProperty(Namer.getDelegateName(name), value, descriptor.getSource());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ public final class InitializerVisitor extends TranslatorVisitor<Void> {
|
|||||||
}
|
}
|
||||||
else if (delegate != null) {
|
else if (delegate != null) {
|
||||||
assert value != null;
|
assert value != null;
|
||||||
statement = generateInitializerForDelegate(descriptor, value);
|
statement = generateInitializerForDelegate(context, descriptor, value);
|
||||||
}
|
}
|
||||||
else if (Boolean.TRUE.equals(context.bindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
|
else if (Boolean.TRUE.equals(context.bindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
|
||||||
JsNameRef backingFieldReference = TranslationUtils.backingFieldReference(context, descriptor);
|
JsNameRef backingFieldReference = TranslationUtils.backingFieldReference(context, descriptor);
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ public final class JsAstUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsStatement defineSimpleProperty(@NotNull String name, @NotNull JsExpression value, @Nullable SourceElement source) {
|
public static JsStatement defineSimpleProperty(@NotNull JsName name, @NotNull JsExpression value, @Nullable SourceElement source) {
|
||||||
JsExpression assignment = assignment(new JsNameRef(name, new JsThisRef()), value);
|
JsExpression assignment = assignment(new JsNameRef(name, new JsThisRef()), value);
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
assignment.setSource(KotlinSourceElementKt.getPsi(source));
|
assignment.setSource(KotlinSourceElementKt.getPsi(source));
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1043
|
||||||
|
fun box(): String {
|
||||||
|
val b = B()
|
||||||
|
|
||||||
|
var r = b.getFooA()
|
||||||
|
if (r != "A.foo") return "fail1: $r"
|
||||||
|
|
||||||
|
r = b.getFooB()
|
||||||
|
if (r != "B.foo") return "fail2: $r"
|
||||||
|
|
||||||
|
r = b.getBarA()
|
||||||
|
if (r != "A.bar") return "fail3: $r"
|
||||||
|
|
||||||
|
r = b.getBarB()
|
||||||
|
if (r != "B.bar") return "fail4: $r"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
open val foo by lazy {
|
||||||
|
"A.foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val bar by lazy {
|
||||||
|
"A.bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBarA() = bar
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
override val foo by lazy {
|
||||||
|
"B.foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val bar by lazy {
|
||||||
|
"B.bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFooB() = foo
|
||||||
|
fun getFooA() = super.foo
|
||||||
|
fun getBarB() = bar
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user