JS backend: cosmetic changes & remake fakeCall

This commit is contained in:
Erokhin Stanislav
2014-01-29 21:10:03 +04:00
parent f268f69cbf
commit 257d13e90b
4 changed files with 114 additions and 104 deletions
@@ -39,52 +39,53 @@ trait CallInfo {
val thisObject: JsExpression? val thisObject: JsExpression?
val receiverObject: JsExpression? val receiverObject: JsExpression?
val nullableReceiverForSafeCall: 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 // if value == null, it is get access
class VariableAccessInfo(callInfo: CallInfo, private val setTo: JsExpression? = null): CallInfo by callInfo { class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null): CallInfo by callInfo
val variableDescriptor = super.callableDescriptor as VariableDescriptor
val variableName : JsName
get() {
return context.getNameForDescriptor(variableDescriptor)
}
fun isGetAccess(): Boolean = setTo == null class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo
fun getSetToExpression(): JsExpression {
if (isGetAccess()) { val CallInfo.callableDescriptor: CallableDescriptor
throw IllegalStateException("This is get, setTo is null. callInfo: $this") get() {
} return resolvedCall.getResultingDescriptor().getOriginal()
return setTo!!
} }
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 VariableAccessInfo.variableDescriptor: VariableDescriptor
val functionName : JsName get() {
get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3) return callableDescriptor as VariableDescriptor
return context.getNameForDescriptor(callableDescriptor)
}
fun hasSpreadOperator() : Boolean {
return argumentsInfo.isHasSpreadOperator()
} }
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 { private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsExpression {
@@ -92,7 +93,7 @@ private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsEx
return getThisObject(getDeclarationDescriptorForReceiver(receiverValue)) return getThisObject(getDeclarationDescriptorForReceiver(receiverValue))
} }
private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo { private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo {
val receiverKind = resolvedCall.getExplicitReceiverKind() val receiverKind = resolvedCall.getExplicitReceiverKind()
fun getNotNullReceiver1(): JsExpression { fun getNotNullReceiver1(): JsExpression {
assert(receiver1 != null, "ResolvedCall say, that receiver(1) must be not null") assert(receiver1 != null, "ResolvedCall say, that receiver(1) must be not null")
@@ -136,7 +137,7 @@ private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall<out Ca
} }
} }
return object : CallInfo { return object : CallInfo {
override val context: TranslationContext = this@mainGetCallInfo override val context: TranslationContext = this@createCallInfo
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
override val thisObject: JsExpression? = getThisObject() override val thisObject: JsExpression? = getThisObject()
override val receiverObject: JsExpression? = getReceiverObject() override val receiverObject: JsExpression? = getReceiverObject()
@@ -144,12 +145,8 @@ private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall<out Ca
}; };
} }
fun ResolvedCall<out CallableDescriptor>.expectedReceivers(): Boolean {
return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER
}
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver: JsExpression?): CallInfo { fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver: JsExpression?): CallInfo {
return mainGetCallInfo(resolvedCall, receiver, null) return createCallInfo(resolvedCall, receiver, null)
} }
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression?): FunctionCallInfo { fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression?): FunctionCallInfo {
@@ -158,7 +155,7 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescri
// two receiver need only for FunctionCall in VariableAsFunctionResolvedCall // two receiver need only for FunctionCall in VariableAsFunctionResolvedCall
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): FunctionCallInfo { fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, 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 val receiverForArgsTranslator = if (resolvedCall.getExplicitReceiverKind() == BOTH_RECEIVERS) // TODO: remove this hack
receiver2 receiver2
@@ -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.utils.JsAstUtils
import org.jetbrains.k2js.translate.context.Namer import org.jetbrains.k2js.translate.context.Namer
import org.jetbrains.k2js.translate.utils.ErrorReportingUtils import org.jetbrains.k2js.translate.utils.ErrorReportingUtils
import org.jetbrains.k2js.translate.utils.AnnotationsUtils
val functionCallCases: CallCaseDispatcher<FunctionCallCase, FunctionCallInfo> = createFunctionCases() val functionCallCases: CallCaseDispatcher<FunctionCallCase, FunctionCallInfo> = createFunctionCases()
val variableAccessCases: CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> = createVariableAccessCases() val variableAccessCases: CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> = createVariableAccessCases()
fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression? = null): JsExpression { fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
return buildCall(resolvedCall, receiver, null) return buildCall(resolvedCall, receiverOrThisObject, null)
} }
fun TranslationContext.buildGet(resolvedCall: ResolvedCall<out VariableDescriptor>, receiver: JsExpression? = null): JsExpression { fun TranslationContext.buildGet(resolvedCall: ResolvedCall<out VariableDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiver), null); val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), null);
return variableAccessCases.translate(variableAccessInfo) return variableAccessCases.translate(variableAccessInfo)
} }
fun TranslationContext.buildSet(resolvedCall: ResolvedCall<out VariableDescriptor>, setTo: JsExpression, receiver: JsExpression? = null): JsExpression { fun TranslationContext.buildSet(resolvedCall: ResolvedCall<out VariableDescriptor>, value: JsExpression, receiverOrThisObject: JsExpression? = null): JsExpression {
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiver), setTo); val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), value);
return variableAccessCases.translate(variableAccessInfo) return variableAccessCases.translate(variableAccessInfo)
} }
fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, args: List<JsExpression>, thisObject: JsExpression?): JsExpression { fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, args: List<JsExpression>, thisObject: JsExpression?): JsExpression {
val fakeCallInfo = object: CallInfo { val argumentsInfo = CallArgumentTranslator.ArgumentsInfo(args, false, null);
override val context: TranslationContext = this@buildFakeCall val functionName = getNameForDescriptor(functionDescriptor)
override val resolvedCall: ResolvedCall<out CallableDescriptor> val isNative = AnnotationsUtils.isNativeObject(functionDescriptor)
get() { val hasSpreadOperator = false
throw UnsupportedOperationException("Resolved call for direct call unsupported") if (thisObject != null) {
} return DefaultCallCase.buildDefaultCallWithThisObject(argumentsInfo, thisObject, functionName, isNative, hasSpreadOperator)
override val callableDescriptor: CallableDescriptor = functionDescriptor } else {
override val thisObject: JsExpression? = thisObject return DefaultCallCase.buildDefaultCallWithoutReceiver(this, argumentsInfo, functionDescriptor, functionName, isNative, hasSpreadOperator)
override val receiverObject: JsExpression? = null
override val nullableReceiverForSafeCall: JsExpression? = null
} }
val fakeFunctionInfo = FunctionCallInfo(fakeCallInfo, CallArgumentTranslator.ArgumentsInfo(args, false, null)); }
return DefaultCallCase(fakeFunctionInfo).translate()
fun ResolvedCall<out CallableDescriptor>.expectedReceivers(): Boolean {
return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER
} }
private fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): JsExpression { private fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): JsExpression {
@@ -151,7 +152,7 @@ open class VariableAccessCase(override val callInfo: VariableAccessInfo) : CallC
if (isGetAccess()) { if (isGetAccess()) {
return ref return ref
} else { } else {
return JsAstUtils.assignment(ref, getSetToExpression()) return JsAstUtils.assignment(ref, value!!)
} }
} }
} }
@@ -34,6 +34,7 @@ import org.jetbrains.k2js.translate.general.Translation
import org.jetbrains.k2js.translate.utils.PsiUtils import org.jetbrains.k2js.translate.utils.PsiUtils
import com.google.dart.compiler.backend.js.ast.JsLiteral import com.google.dart.compiler.backend.js.ast.JsLiteral
import com.google.dart.compiler.backend.js.ast.JsName import com.google.dart.compiler.backend.js.ast.JsName
import org.jetbrains.k2js.translate.context.TranslationContext
public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>) : List<JsExpression> { public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>) : List<JsExpression> {
if (arguments.isEmpty()) if (arguments.isEmpty())
@@ -47,26 +48,52 @@ public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpressio
// call may be native and|or with spreadOperator // call may be native and|or with spreadOperator
class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) { //TODO: check spreadOperator class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) {
class object {
// TODO: refactor after fix ArgumentsInfo - duplicate code
private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression {
val cachedReceiver = argumentsInfo.getCachedReceiver()!!
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
}
override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native fun buildDefaultCallWithThisObject(argumentsInfo: CallArgumentTranslator.ArgumentsInfo,
val functionRef = JsNameRef(functionName, thisObject!!) thisObject: JsExpression,
return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments())) functionName: JsName,
isNative: Boolean,
hasSpreadOperator: Boolean): JsExpression {
if (isNative && hasSpreadOperator) {
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
}
val functionRef = JsNameRef(functionName, thisObject)
return JsInvocation(functionRef, argumentsInfo.getTranslateArguments())
}
fun buildDefaultCallWithoutReceiver(context: TranslationContext,
argumentsInfo: CallArgumentTranslator.ArgumentsInfo,
callableDescriptor: CallableDescriptor,
functionName: JsName,
isNative: Boolean,
hasSpreadOperator: Boolean): JsExpression {
if (isNative && hasSpreadOperator) {
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
}
if (isNative) {
return JsInvocation(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
}
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
val functionCall = JsNameRef(functionName, qualifierForFunction)
return JsInvocation(functionCall, argumentsInfo.getTranslateArguments())
}
} }
// TODO: refactor after fix ArgumentsInfo - duplicate code override fun FunctionCallInfo.noReceivers(): JsExpression {
private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression { return buildDefaultCallWithoutReceiver(context, argumentsInfo, callableDescriptor, functionName, isNative(), hasSpreadOperator())
val cachedReceiver = argumentsInfo.getCachedReceiver()!!
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
} }
override fun FunctionCallInfo.thisObject(): JsExpression { override fun FunctionCallInfo.thisObject(): JsExpression {
if (isNative() && hasSpreadOperator()) { return buildDefaultCallWithThisObject(argumentsInfo, thisObject!!, functionName, isNative(), hasSpreadOperator())
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
}
val functionRef = JsNameRef(functionName, thisObject!!)
return JsInvocation(functionRef, argumentsInfo.getTranslateArguments())
} }
override fun FunctionCallInfo.receiverArgument(): JsExpression { override fun FunctionCallInfo.receiverArgument(): JsExpression {
@@ -80,17 +107,10 @@ class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) {
val functionCall = JsNameRef(functionName, qualifierForFunction) // TODO: remake to call val functionCall = JsNameRef(functionName, qualifierForFunction) // TODO: remake to call
return JsInvocation(functionCall, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments())) return JsInvocation(functionCall, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
} }
override fun FunctionCallInfo.noReceivers(): JsExpression {
if (isNative() && hasSpreadOperator()) { override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName)) val functionRef = JsNameRef(functionName, thisObject!!)
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments()) return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
}
if (isNative()) {
return JsInvocation(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
}
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
val functionCall = JsNameRef(functionName, qualifierForFunction)
return JsInvocation(functionCall, argumentsInfo.getTranslateArguments())
} }
} }
@@ -59,7 +59,7 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa
return if (isGetAccess()) { return if (isGetAccess()) {
JsInvocation(funRef, receiverObject!!) JsInvocation(funRef, receiverObject!!)
} else { } else {
JsInvocation(funRef, receiverObject!!, getSetToExpression()) JsInvocation(funRef, receiverObject!!, value!!)
} }
} }
@@ -68,18 +68,11 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa
return if (isGetAccess()) { return if (isGetAccess()) {
JsInvocation(funRef, receiverObject!!) JsInvocation(funRef, receiverObject!!)
} else { } else {
JsInvocation(funRef, receiverObject!!, getSetToExpression()) JsInvocation(funRef, receiverObject!!, value!!)
} }
} }
} }
class ValueParameterAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) {
override fun VariableAccessInfo.noReceivers(): JsExpression {
assert(isGetAccess(), "It must be get access. CallInfo: $callInfo")
return variableName.makeRef()!!
}
}
class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo), DelegateIntrinsic<VariableAccessInfo> { class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo), DelegateIntrinsic<VariableAccessInfo> {
override fun VariableAccessInfo.canBeApply(): Boolean { override fun VariableAccessInfo.canBeApply(): Boolean {
return variableDescriptor is PropertyDescriptor return variableDescriptor is PropertyDescriptor
@@ -89,7 +82,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
return if (isGetAccess()) return if (isGetAccess())
Collections.emptyList<JsExpression>() Collections.emptyList<JsExpression>()
else else
Collections.singletonList(getSetToExpression()) Collections.singletonList(value!!)
} }
override fun VariableAccessInfo.getDescriptor(): CallableDescriptor { override fun VariableAccessInfo.getDescriptor(): CallableDescriptor {
@@ -97,7 +90,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
return if (isGetAccess()) { return if (isGetAccess()) {
var getter = propertyDescriptor.getGetter() var getter = propertyDescriptor.getGetter()
if (getter == null) { if (getter == null) {
val getterImpl = DescriptorFactory.createDefaultGetter(variableDescriptor) val getterImpl = DescriptorFactory.createDefaultGetter(propertyDescriptor)
getterImpl.initialize(propertyDescriptor.getType()) getterImpl.initialize(propertyDescriptor.getType())
((propertyDescriptor as PropertyDescriptorImpl)).initialize(getterImpl, propertyDescriptor.getSetter()) ((propertyDescriptor as PropertyDescriptorImpl)).initialize(getterImpl, propertyDescriptor.getSetter())
getter = getterImpl getter = getterImpl
@@ -106,7 +99,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
} else { } else {
var setter = propertyDescriptor.getSetter() var setter = propertyDescriptor.getSetter()
if (setter == null) { if (setter == null) {
val setterImpl = DescriptorFactory.createDefaultSetter(variableDescriptor) val setterImpl = DescriptorFactory.createDefaultSetter(propertyDescriptor)
((propertyDescriptor as PropertyDescriptorImpl)).initialize(propertyDescriptor.getGetter(), setterImpl) ((propertyDescriptor as PropertyDescriptorImpl)).initialize(propertyDescriptor.getGetter(), setterImpl)
setter = setterImpl setter = setterImpl
} }
@@ -121,7 +114,7 @@ class SuperPropertyAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase
return if (isGetAccess()) return if (isGetAccess())
JsInvocation(context.namer().getCallGetProperty(), JsLiteral.THIS, thisObject!!, variableName) JsInvocation(context.namer().getCallGetProperty(), JsLiteral.THIS, thisObject!!, variableName)
else 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<VariableAccessCase, Variable
caseDispatcher.addCase { DelegatePropertyAccessIntrinsic(it).intrinsic() } caseDispatcher.addCase { DelegatePropertyAccessIntrinsic(it).intrinsic() }
caseDispatcher.addCase(::SuperPropertyAccessCase) { it.isSuperInvocation() } caseDispatcher.addCase(::SuperPropertyAccessCase) { it.isSuperInvocation() }
//caseDispatcher.addCase(::ValueParameterAccessCase) { it.variableDescriptor is ValueParameterDescriptor}
caseDispatcher.addCase(::NativeVariableAccessCase) { it.isNative() } caseDispatcher.addCase(::NativeVariableAccessCase) { it.isNative() }
caseDispatcher.addCase(::DefaultVariableAccessCase) { true } // TODO: fix this caseDispatcher.addCase(::DefaultVariableAccessCase) { true } // TODO: fix this
return caseDispatcher return caseDispatcher