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 7ffebcc4cee..f504914a6db 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 @@ -39,52 +39,53 @@ trait CallInfo { val thisObject: JsExpression? val receiverObject: JsExpression? val nullableReceiverForSafeCall: JsExpression? - - val callableDescriptor: CallableDescriptor - get() { - return resolvedCall.getResultingDescriptor().getOriginal() - } - - fun isExtension(): Boolean = receiverObject != null - fun isMemberCall(): Boolean = thisObject != null - fun isSafeCall(): Boolean = nullableReceiverForSafeCall != null - fun isNative(): Boolean = AnnotationsUtils.isNativeObject(callableDescriptor) - - fun isSuperInvocation() : Boolean { - val thisObject = resolvedCall.getThisObject() - return thisObject is ExpressionReceiver && ((thisObject as ExpressionReceiver)).getExpression() is JetSuperExpression - } - - // TODO: toString for debug } -// if setTo == null, it is get access -class VariableAccessInfo(callInfo: CallInfo, private val setTo: JsExpression? = null): CallInfo by callInfo { - val variableDescriptor = super.callableDescriptor as VariableDescriptor - val variableName : JsName - get() { - return context.getNameForDescriptor(variableDescriptor) - } +// if value == null, it is get access +class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null): CallInfo by callInfo - fun isGetAccess(): Boolean = setTo == null +class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo - fun getSetToExpression(): JsExpression { - if (isGetAccess()) { - throw IllegalStateException("This is get, setTo is null. callInfo: $this") - } - return setTo!! + +val CallInfo.callableDescriptor: CallableDescriptor + get() { + return resolvedCall.getResultingDescriptor().getOriginal() } +fun CallInfo.isExtension(): Boolean { + return receiverObject != null +} +fun CallInfo.isMemberCall(): Boolean { + return thisObject != null +} +fun CallInfo.isSafeCall(): Boolean { + return resolvedCall.isSafeCall() +} +fun CallInfo.isNative(): Boolean { + return AnnotationsUtils.isNativeObject(callableDescriptor) +} +fun CallInfo.isSuperInvocation() : Boolean { + val thisObject = resolvedCall.getThisObject() + return thisObject is ExpressionReceiver && ((thisObject as ExpressionReceiver)).getExpression() is JetSuperExpression } -class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo { - val functionName : JsName - get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3) - return context.getNameForDescriptor(callableDescriptor) - } - - fun hasSpreadOperator() : Boolean { - return argumentsInfo.isHasSpreadOperator() +val VariableAccessInfo.variableDescriptor: VariableDescriptor + get() { + return callableDescriptor as VariableDescriptor } +val VariableAccessInfo.variableName : JsName + get() { + return context.getNameForDescriptor(variableDescriptor) + } +fun VariableAccessInfo.isGetAccess(): Boolean { + return value == null +} + +val FunctionCallInfo.functionName : JsName + get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3) + return context.getNameForDescriptor(callableDescriptor) + } +fun FunctionCallInfo.hasSpreadOperator() : Boolean { + return argumentsInfo.isHasSpreadOperator() } private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsExpression { @@ -92,7 +93,7 @@ private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsEx return getThisObject(getDeclarationDescriptorForReceiver(receiverValue)) } -private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo { +private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo { val receiverKind = resolvedCall.getExplicitReceiverKind() fun getNotNullReceiver1(): JsExpression { assert(receiver1 != null, "ResolvedCall say, that receiver(1) must be not null") @@ -136,7 +137,7 @@ private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall = resolvedCall override val thisObject: JsExpression? = getThisObject() override val receiverObject: JsExpression? = getReceiverObject() @@ -144,12 +145,8 @@ private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall.expectedReceivers(): Boolean { - return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER -} - fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall, receiver: JsExpression?): CallInfo { - return mainGetCallInfo(resolvedCall, receiver, null) + return createCallInfo(resolvedCall, receiver, null) } fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall, receiver: JsExpression?): FunctionCallInfo { @@ -158,7 +155,7 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall, receiver1: JsExpression?, receiver2: JsExpression?): FunctionCallInfo { - val callInfo = mainGetCallInfo(resolvedCall, receiver1, receiver2) + val callInfo = createCallInfo(resolvedCall, receiver1, receiver2) val receiverForArgsTranslator = if (resolvedCall.getExplicitReceiverKind() == BOTH_RECEIVERS) // TODO: remove this hack receiver2 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 f8c10ec0ea4..49ec0f58a0f 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 @@ -30,39 +30,40 @@ import com.google.dart.compiler.backend.js.ast.JsNameRef import org.jetbrains.k2js.translate.utils.JsAstUtils import org.jetbrains.k2js.translate.context.Namer import org.jetbrains.k2js.translate.utils.ErrorReportingUtils +import org.jetbrains.k2js.translate.utils.AnnotationsUtils val functionCallCases: CallCaseDispatcher = createFunctionCases() val variableAccessCases: CallCaseDispatcher = createVariableAccessCases() -fun TranslationContext.buildCall(resolvedCall: ResolvedCall, receiver: JsExpression? = null): JsExpression { - return buildCall(resolvedCall, receiver, null) +fun TranslationContext.buildCall(resolvedCall: ResolvedCall, receiverOrThisObject: JsExpression? = null): JsExpression { + return buildCall(resolvedCall, receiverOrThisObject, null) } -fun TranslationContext.buildGet(resolvedCall: ResolvedCall, receiver: JsExpression? = null): JsExpression { - val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiver), null); +fun TranslationContext.buildGet(resolvedCall: ResolvedCall, receiverOrThisObject: JsExpression? = null): JsExpression { + val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), null); return variableAccessCases.translate(variableAccessInfo) } -fun TranslationContext.buildSet(resolvedCall: ResolvedCall, setTo: JsExpression, receiver: JsExpression? = null): JsExpression { - val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiver), setTo); +fun TranslationContext.buildSet(resolvedCall: ResolvedCall, value: JsExpression, receiverOrThisObject: JsExpression? = null): JsExpression { + val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), value); return variableAccessCases.translate(variableAccessInfo) } fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, args: List, thisObject: JsExpression?): JsExpression { - val fakeCallInfo = object: CallInfo { - override val context: TranslationContext = this@buildFakeCall - override val resolvedCall: ResolvedCall - get() { - throw UnsupportedOperationException("Resolved call for direct call unsupported") - } - override val callableDescriptor: CallableDescriptor = functionDescriptor - override val thisObject: JsExpression? = thisObject - override val receiverObject: JsExpression? = null - override val nullableReceiverForSafeCall: JsExpression? = null + val argumentsInfo = CallArgumentTranslator.ArgumentsInfo(args, false, null); + val functionName = getNameForDescriptor(functionDescriptor) + val isNative = AnnotationsUtils.isNativeObject(functionDescriptor) + val hasSpreadOperator = false + if (thisObject != null) { + return DefaultCallCase.buildDefaultCallWithThisObject(argumentsInfo, thisObject, functionName, isNative, hasSpreadOperator) + } else { + return DefaultCallCase.buildDefaultCallWithoutReceiver(this, argumentsInfo, functionDescriptor, functionName, isNative, hasSpreadOperator) } - val fakeFunctionInfo = FunctionCallInfo(fakeCallInfo, CallArgumentTranslator.ArgumentsInfo(args, false, null)); - return DefaultCallCase(fakeFunctionInfo).translate() +} + +fun ResolvedCall.expectedReceivers(): Boolean { + return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER } private fun TranslationContext.buildCall(resolvedCall: ResolvedCall, receiver1: JsExpression?, receiver2: JsExpression?): JsExpression { @@ -151,7 +152,7 @@ open class VariableAccessCase(override val callInfo: VariableAccessInfo) : CallC if (isGetAccess()) { return ref } else { - return JsAstUtils.assignment(ref, getSetToExpression()) + return JsAstUtils.assignment(ref, value!!) } } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt b/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt index dfd73173b0e..ae819f21025 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt @@ -34,6 +34,7 @@ import org.jetbrains.k2js.translate.general.Translation import org.jetbrains.k2js.translate.utils.PsiUtils import com.google.dart.compiler.backend.js.ast.JsLiteral import com.google.dart.compiler.backend.js.ast.JsName +import org.jetbrains.k2js.translate.context.TranslationContext public fun addReceiverToArgs(receiver: JsExpression, arguments: List) : List { if (arguments.isEmpty()) @@ -47,26 +48,52 @@ public fun addReceiverToArgs(receiver: JsExpression, arguments: List { override fun VariableAccessInfo.canBeApply(): Boolean { return variableDescriptor is PropertyDescriptor @@ -89,7 +82,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc return if (isGetAccess()) Collections.emptyList() else - Collections.singletonList(getSetToExpression()) + Collections.singletonList(value!!) } override fun VariableAccessInfo.getDescriptor(): CallableDescriptor { @@ -97,7 +90,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc return if (isGetAccess()) { var getter = propertyDescriptor.getGetter() if (getter == null) { - val getterImpl = DescriptorFactory.createDefaultGetter(variableDescriptor) + val getterImpl = DescriptorFactory.createDefaultGetter(propertyDescriptor) getterImpl.initialize(propertyDescriptor.getType()) ((propertyDescriptor as PropertyDescriptorImpl)).initialize(getterImpl, propertyDescriptor.getSetter()) getter = getterImpl @@ -106,7 +99,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc } else { var setter = propertyDescriptor.getSetter() if (setter == null) { - val setterImpl = DescriptorFactory.createDefaultSetter(variableDescriptor) + val setterImpl = DescriptorFactory.createDefaultSetter(propertyDescriptor) ((propertyDescriptor as PropertyDescriptorImpl)).initialize(propertyDescriptor.getGetter(), setterImpl) setter = setterImpl } @@ -121,7 +114,7 @@ class SuperPropertyAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase return if (isGetAccess()) JsInvocation(context.namer().getCallGetProperty(), JsLiteral.THIS, thisObject!!, variableName) else - JsInvocation(context.namer().getCallSetProperty(), JsLiteral.THIS, thisObject!!, variableName, getSetToExpression()) + JsInvocation(context.namer().getCallSetProperty(), JsLiteral.THIS, thisObject!!, variableName, value!!) } } @@ -130,7 +123,6 @@ fun createVariableAccessCases(): CallCaseDispatcher