Implement handler for filter call for kotlin collections

This commit is contained in:
Vitaliy.Bibaev
2017-11-16 10:41:48 +03:00
committed by Yan Zhulanow
parent 3b14ed9ae8
commit 246f79ab86
2 changed files with 90 additions and 0 deletions
@@ -0,0 +1,21 @@
package com.intellij.debugger.streams.kotlin.trace.impl.handler.collections
import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinTypes
import com.intellij.debugger.streams.wrapper.*
import com.intellij.debugger.streams.wrapper.impl.IntermediateStreamCallImpl
import com.intellij.debugger.streams.wrapper.impl.TerminatorStreamCallImpl
/**
* @author Vitaliy.Bibaev
*/
fun IntermediateStreamCall.withArgs(args: List<CallArgument>) =
IntermediateStreamCallImpl(name, args, typeBefore, typeAfter, textRange)
fun TerminatorStreamCall.withArgs(args: List<CallArgument>) =
TerminatorStreamCallImpl(name, args, typeBefore, resultType, textRange)
fun StreamCall.typeBefore() =
if (StreamCall@ this is TypeBeforeAware) StreamCall@ this.typeBefore else KotlinTypes.ANY
fun StreamCall.typeAfter() =
if (StreamCall@ this is TypeAfterAware) StreamCall@ this.typeAfter else KotlinTypes.ANY
@@ -1,7 +1,76 @@
package com.intellij.debugger.streams.kotlin.trace.impl.handler.collections
import com.intellij.debugger.streams.trace.dsl.*
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
import com.intellij.debugger.streams.trace.impl.handler.type.ClassTypeImpl
import com.intellij.debugger.streams.wrapper.CallArgument
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
import com.intellij.debugger.streams.wrapper.StreamCall
import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
/**
* @author Vitaliy.Bibaev
*/
class FilterCallHandler : BothSemanticsHandler {
private companion object {
val VALUES_ARRAY_NAME = "objectsInPredicate"
val PREDICATE_RESULT_ARRAY_NAME = "filteringResults"
fun oldPredicateVariableName(order: Int): String = "filterPredicate" + order
}
override fun variablesDeclaration(call: StreamCall, order: Int, dsl: Dsl): List<VariableDeclaration> {
val types = dsl.types
val timeToObjectMap = dsl.linkedMap(types.INT, call.typeBefore(), call.name + "Values" + order)
val predicateResultMap = dsl.linkedMap(types.INT, types.BOOLEAN, call.name + "PredicateValue" + order)
val predicate = call.arguments[0]
// TODO: use generic types in CallArgument
val oldFilterPredicate = dsl.variable(ClassTypeImpl(predicate.type), oldPredicateVariableName(order))
return listOf(timeToObjectMap.defaultDeclaration(), predicateResultMap.defaultDeclaration(),
dsl.declaration(oldFilterPredicate, TextExpression(predicate.text), false))
}
override fun prepareResult(dsl: Dsl, variables: List<Variable>): CodeBlock {
val values = variables[0] as MapVariable
val filterResult = variables[1] as MapVariable
return dsl.block {
add(values.convertToArray(dsl, VALUES_ARRAY_NAME))
add(filterResult.convertToArray(dsl, PREDICATE_RESULT_ARRAY_NAME))
}
}
override fun additionalCallsBefore(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
override fun additionalCallsAfter(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
override fun getResultExpression(call: StreamCall, dsl: Dsl, variables: List<Variable>): Expression {
return dsl.newArray(dsl.types.ANY, TextExpression(VALUES_ARRAY_NAME), TextExpression(PREDICATE_RESULT_ARRAY_NAME))
}
override fun transformAsIntermediateCall(call: IntermediateStreamCall, variables: List<Variable>, dsl: Dsl): IntermediateStreamCall {
return call.withArgs(listOf(createNewPredicate(variables, dsl)))
}
override fun transformAsTerminalCall(call: TerminatorStreamCall, variables: List<Variable>, dsl: Dsl): TerminatorStreamCall {
return call.withArgs(listOf(createNewPredicate(variables, dsl)))
}
private fun createNewPredicate(variables: List<Variable>, dsl: Dsl): CallArgument {
val valuesMap = variables[0] as MapVariable
val filteringMap = variables[1] as MapVariable
val oldPredicate = variables[2]
val newPredicate = dsl.lambda("value") {
+dsl.updateTime()
+valuesMap.set(dsl.currentTime(), lambdaArg)
val filterResult = dsl.variable(dsl.types.BOOLEAN, "result")
declare(filterResult, oldPredicate.call("invoke", lambdaArg), false)
+filteringMap.set(dsl.currentTime(), filterResult)
doReturn(filterResult)
}.toCode()
return CallArgumentImpl(oldPredicate.type.genericTypeName, newPredicate)
}
}