diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallInfo.kt b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallInfo.kt index ab4f2f41fcd..f4fec446bbf 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallInfo.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallInfo.kt @@ -40,7 +40,7 @@ open class BaseCallInfo( val receiverObject: JsExpression?, val nullableReceiverForSafeCall: JsExpression? ) { - val callableDescriptor = resolvedCall.getResultingDescriptor().getOriginal() + open val callableDescriptor = resolvedCall.getResultingDescriptor().getOriginal() fun isExtension(): Boolean = receiverObject != null fun isMemberCall(): Boolean = thisObject != null @@ -61,7 +61,7 @@ private open class CallInfoWrapper(callInfo: BaseCallInfo) : // if setTo == null, it is get access class VariableAccessInfo(callInfo: BaseCallInfo, private val setTo: JsExpression? = null): CallInfoWrapper(callInfo) { val variableDescriptor = super.callableDescriptor as VariableDescriptor - val propertyName : JsName + val variableName : JsName get() { return context.getNameForDescriptor(variableDescriptor) } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ClearCallTranslator.kt b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ClearCallTranslator.kt index 92f176ca6a9..91526ec8e55 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ClearCallTranslator.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ClearCallTranslator.kt @@ -114,7 +114,7 @@ open class FunctionCallCase(override val callInfo: FunctionCallInfo) : CallCase< open class VariableAccessCase(override val callInfo: VariableAccessInfo) : CallCase { protected fun VariableAccessInfo.getAccessFunctionName(): String { - return Namer.getNameForAccessor(propertyName.getIdent()!!, isGetAccess(), false) + return Namer.getNameForAccessor(variableName.getIdent()!!, isGetAccess(), false) } protected fun VariableAccessInfo.constructAccessExpression(ref: JsNameRef): JsExpression { @@ -153,6 +153,7 @@ class CallCaseDispatcher, I : BaseCallInfo> { } trait DelegateIntrinsic : CallCase { + fun I.canBeApply(): Boolean = true fun I.getReceiver(): JsExpression? { return when (resolvedCall.getExplicitReceiverKind()) { THIS_OBJECT -> thisObject @@ -171,6 +172,9 @@ trait DelegateIntrinsic : CallCase { } fun intrinsic(): JsExpression? { - return callInfo.intrinsic() + return if (callInfo.canBeApply()) + callInfo.intrinsic() + else + null } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/VarialbeCallCases.kt b/js/js.translator/src/org/jetbrains/k2js/translate/reference/VarialbeCallCases.kt index 7c614b33542..6b3600e2e57 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/VarialbeCallCases.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/VarialbeCallCases.kt @@ -22,35 +22,40 @@ import com.google.dart.compiler.backend.js.ast.JsLiteral import org.jetbrains.k2js.translate.utils.JsAstUtils import com.google.dart.compiler.backend.js.ast.JsInvocation import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor +import org.jetbrains.jet.lang.descriptors.CallableDescriptor +import java.util.Collections +import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.jet.lang.resolve.DescriptorFactory +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor class NativeVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) { override fun VariableAccessInfo.receiverArgument(): JsExpression { - return constructAccessExpression(JsNameRef(propertyName, receiverObject!!)) + return constructAccessExpression(JsNameRef(variableName, receiverObject!!)) } override fun VariableAccessInfo.thisObject(): JsExpression { - return constructAccessExpression(JsNameRef(propertyName, thisObject!!)) + return constructAccessExpression(JsNameRef(variableName, thisObject!!)) } override fun VariableAccessInfo.noReceivers(): JsExpression { - return constructAccessExpression(propertyName.makeRef()!!) + return constructAccessExpression(variableName.makeRef()!!) } } class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) { override fun VariableAccessInfo.noReceivers(): JsExpression { - return constructAccessExpression(context.getQualifierForDescriptor(callableDescriptor)!!) + return constructAccessExpression(context.getQualifiedReference(variableDescriptor)) } override fun VariableAccessInfo.thisObject(): JsExpression { - return constructAccessExpression(JsNameRef(propertyName, thisObject!!)) + return constructAccessExpression(JsNameRef(variableName, thisObject!!)) } override fun VariableAccessInfo.receiverArgument(): JsExpression { - val funRef = JsNameRef(getAccessFunctionName(), context.getQualifierForDescriptor(callableDescriptor)) + val funRef = JsNameRef(getAccessFunctionName(), context.getQualifierForDescriptor(variableDescriptor)) return if (isGetAccess()) { JsInvocation(funRef, receiverObject!!) } else { @@ -71,15 +76,50 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa class ValueParameterAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) { override fun VariableAccessInfo.noReceivers(): JsExpression { assert(isGetAccess(), "It must be get access. CallInfo: $callInfo") - return propertyName.makeRef()!! + return variableName.makeRef()!! } } +class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo), DelegateIntrinsic { + override fun VariableAccessInfo.canBeApply(): Boolean { + return variableDescriptor is PropertyDescriptor + } + + override fun VariableAccessInfo.getArgs(): List { + return if (isGetAccess()) + Collections.emptyList() + else + Collections.singletonList(getSetToExpression()) + } + + override fun VariableAccessInfo.getDescriptor(): CallableDescriptor { + val propertyDescriptor = variableDescriptor as PropertyDescriptor + return if (isGetAccess()) { + var getter = propertyDescriptor.getGetter() + if (getter == null) { + val getterImpl = DescriptorFactory.createDefaultGetter(variableDescriptor) + getterImpl.initialize(propertyDescriptor.getType()) + ((propertyDescriptor as PropertyDescriptorImpl)).initialize(getterImpl, propertyDescriptor.getSetter()) + getter = getterImpl + } + getter!! + } else { + var setter = propertyDescriptor.getSetter() + if (setter == null) { + val setterImpl = DescriptorFactory.createDefaultSetter(variableDescriptor) + ((propertyDescriptor as PropertyDescriptorImpl)).initialize(propertyDescriptor.getGetter(), setterImpl) + setter = setterImpl + } + setter!! + } + } +} fun createVariableAccessCases(): CallCaseDispatcher { val caseDispatcher = CallCaseDispatcher() - caseDispatcher.addCase(::ValueParameterAccessCase) { it.callableDescriptor is ValueParameterDescriptor} + caseDispatcher.addCase { DelegatePropertyAccessIntrinsic(it).intrinsic() } + caseDispatcher.addCase(::ValueParameterAccessCase) { it.variableDescriptor is ValueParameterDescriptor} caseDispatcher.addCase(::NativeVariableAccessCase) { it.isNative() } caseDispatcher.addCase(::DefaultVariableAccessCase) { true } // TODO: fix this return caseDispatcher