Fix delegate property name clash in JS BE

See KT-19542
This commit is contained in:
Alexey Andreev
2017-09-04 14:24:07 +03:00
parent 28c9d274ec
commit b8aa2f81a2
11 changed files with 63 additions and 25 deletions
@@ -1106,6 +1106,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
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")
public void testDelegateByExtensionProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/delegateProperty/delegateByExtensionProperty.kt");
@@ -159,16 +159,6 @@ public final class Namer {
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
public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
return pureFqn(CALL_FUNCTION, functionExpression);
@@ -116,7 +116,7 @@ public final class StaticContext {
private final Map<DeclarationDescriptor, JsName> nameCache = new HashMap<>();
@NotNull
private final Map<PropertyDescriptor, JsName> backingFieldNameCache = new HashMap<>();
private final Map<VariableDescriptorWithAccessors, JsName> backingFieldNameCache = new HashMap<>();
@NotNull
private final Map<DeclarationDescriptor, JsExpression> fqnCache = new HashMap<>();
@@ -353,7 +353,7 @@ public final class StaticContext {
}
@NotNull
public JsName getNameForBackingField(@NotNull PropertyDescriptor property) {
public JsName getNameForBackingField(@NotNull VariableDescriptorWithAccessors property) {
JsName name = backingFieldNameCache.get(property);
if (name == null) {
@@ -407,7 +407,7 @@ public class TranslationContext {
}
@NotNull
public JsName getNameForBackingField(@NotNull PropertyDescriptor property) {
public JsName getNameForBackingField(@NotNull VariableDescriptorWithAccessors property) {
return staticContext.getNameForBackingField(property);
}
@@ -412,7 +412,7 @@ class ClassTranslator private constructor(
function.parameters.add(i, JsParameter(name))
if (fieldName != null && constructor == primaryConstructor) {
val source = (constructor.descriptor as? DeclarationDescriptorWithSource)?.source
additionalStatements += JsAstUtils.defineSimpleProperty(fieldName.ident, name.makeRef(), source)
additionalStatements += JsAstUtils.defineSimpleProperty(fieldName, name.makeRef(), source)
}
}
@@ -170,7 +170,6 @@ class DeclarationBodyVisitor(
}
}
override fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression {
return Namer.getDelegateNameRef(descriptor.name.asString())
}
override fun getBackingFieldReference(descriptor: PropertyDescriptor): JsExpression =
JsNameRef(context.getNameForBackingField(descriptor), JsThisRef())
}
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
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.TranslationContext
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
@@ -225,7 +224,7 @@ private class PropertyTranslator(
private fun generateDefaultGetter(): JsPropertyInitializer {
val getterDescriptor = descriptor.getter ?: throw IllegalStateException("Getter descriptor should not be null")
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)
}
return generateDefaultAccessor(getterDescriptor, defaultFunction)
@@ -234,7 +233,7 @@ private class PropertyTranslator(
private fun generateDefaultSetter(): JsPropertyInitializer {
val setterDescriptor = descriptor.setter ?: throw IllegalStateException("Setter descriptor should not be null")
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)
}
return generateDefaultAccessor(setterDescriptor, defaultFunction)
@@ -43,12 +43,12 @@ public final class InitializerUtils {
return assignment.makeStmt();
}
@Nullable
@NotNull
public static JsStatement generateInitializerForDelegate(
@NotNull TranslationContext context,
@NotNull PropertyDescriptor descriptor,
@NotNull JsExpression value
) {
String name = descriptor.getName().asString();
return JsAstUtils.defineSimpleProperty(Namer.getDelegateName(name), value, descriptor.getSource());
return JsAstUtils.defineSimpleProperty(context.getNameForBackingField(descriptor), value, descriptor.getSource());
}
}
@@ -55,7 +55,7 @@ public final class InitializerVisitor extends TranslatorVisitor<Void> {
}
else if (delegate != 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))) {
JsNameRef backingFieldReference = TranslationUtils.backingFieldReference(context, descriptor);
@@ -444,7 +444,7 @@ public final class JsAstUtils {
}
@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);
if (source != null) {
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
}