diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/lib/KotlinCollectionLibrarySupport.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/lib/KotlinCollectionLibrarySupport.kt index 97e04280a7b..0c5384ba8d9 100644 --- a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/lib/KotlinCollectionLibrarySupport.kt +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/lib/KotlinCollectionLibrarySupport.kt @@ -1,11 +1,11 @@ package com.intellij.debugger.streams.kotlin.lib -import com.intellij.debugger.streams.kotlin.resolve.FilterOrderResolver import com.intellij.debugger.streams.kotlin.trace.impl.handler.collections.* import com.intellij.debugger.streams.kotlin.trace.impl.interpret.FilterTraceInterpreter import com.intellij.debugger.streams.lib.IntermediateOperation import com.intellij.debugger.streams.lib.TerminalOperation import com.intellij.debugger.streams.lib.impl.LibrarySupportBase +import com.intellij.debugger.streams.resolve.FilterResolver import com.intellij.debugger.streams.resolve.ValuesOrderResolver import com.intellij.debugger.streams.trace.CallTraceInterpreter import com.intellij.debugger.streams.trace.IntermediateCallHandler @@ -19,7 +19,8 @@ import com.intellij.debugger.streams.wrapper.TerminatorStreamCall */ class KotlinCollectionLibrarySupport : LibrarySupportBase() { init { - addOperation(FilterOperation("filter", FilterCallHandler())) + addOperation(FilterOperation("filter", FilterCallHandler(), true)) + addOperation(FilterOperation("filterNot", FilterCallHandler(), false)) } private fun addOperation(operation: CollectionOperation) { @@ -40,9 +41,9 @@ class KotlinCollectionLibrarySupport : LibrarySupportBase() { wrapper.createTerminatorHandler(call, resultExpression, dsl) } - private class FilterOperation(name: String, handler: BothSemanticsHandler) + private class FilterOperation(name: String, handler: BothSemanticsHandler, valueToAccept: Boolean) : CollectionOperation(name, handler) { - override val traceInterpreter: CallTraceInterpreter = FilterTraceInterpreter() - override val valuesOrderResolver: ValuesOrderResolver = FilterOrderResolver() + override val traceInterpreter: CallTraceInterpreter = FilterTraceInterpreter(valueToAccept) + override val valuesOrderResolver: ValuesOrderResolver = FilterResolver() } } diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/resolve/FilterOrderResolver.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/resolve/FilterOrderResolver.kt deleted file mode 100644 index 5a0401e36ca..00000000000 --- a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/resolve/FilterOrderResolver.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.intellij.debugger.streams.kotlin.resolve - -import com.intellij.debugger.streams.resolve.ValuesOrderResolver -import com.intellij.debugger.streams.trace.TraceInfo - -/** - * @author Vitaliy.Bibaev - */ -class FilterOrderResolver : ValuesOrderResolver { - override fun resolve(info: TraceInfo): ValuesOrderResolver.Result { - return ValuesOrderResolver.Result.of(emptyMap(), emptyMap()) - } -} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/FilterTraceInterpreter.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/FilterTraceInterpreter.kt index e7b4573f8e2..d508de00e3a 100644 --- a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/FilterTraceInterpreter.kt +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/FilterTraceInterpreter.kt @@ -1,22 +1,66 @@ package com.intellij.debugger.streams.kotlin.trace.impl.interpret import com.intellij.debugger.streams.trace.CallTraceInterpreter +import com.intellij.debugger.streams.trace.TraceElement import com.intellij.debugger.streams.trace.TraceInfo -import com.intellij.debugger.streams.trace.impl.interpret.ValuesOrderInfo +import com.intellij.debugger.streams.trace.impl.TraceElementImpl import com.intellij.debugger.streams.trace.impl.interpret.ex.UnexpectedValueTypeException import com.intellij.debugger.streams.wrapper.StreamCall import com.sun.jdi.ArrayReference +import com.sun.jdi.BooleanValue +import com.sun.jdi.IntegerValue import com.sun.jdi.Value /** * @author Vitaliy.Bibaev */ -class FilterTraceInterpreter : CallTraceInterpreter { +class FilterTraceInterpreter(private val predicateValueToAccept: Boolean) : CallTraceInterpreter { override fun resolve(call: StreamCall, value: Value): TraceInfo { if (value !is ArrayReference) throw UnexpectedValueTypeException("array reference excepted, but actual: ${value.type().name()}") - val times = value.getValue(0) - val values = value.getValue(1) - val predicateResults = value.getValue(0) - return ValuesOrderInfo.empty(call) + val before = resolveValuesBefore(value.getValue(0)) + val filteringMap = value.getValue(1) + val after = resolveValuesAfter(before, filteringMap) + + return ValuesOrder(call, before, after) + } + + private fun resolveValuesBefore(map: Value): Map { + val (keys, objects) = InterpreterUtil.extractMap(map) + val result: MutableList = mutableListOf() + for (i in 0.until(keys.length())) { + val time = keys.getValue(i) + val value = objects.getValue(i) + if (time !is IntegerValue) throw UnexpectedValueTypeException("time should be represented by integer value") + result.add(TraceElementImpl(time.value(), value)) + } + + return InterpreterUtil.createIndexByTime(result) + } + + private fun resolveValuesAfter(before: Map, filteringMap: Value): Map { + val predicateValues = extractPredicateValues(filteringMap) + val result = linkedMapOf() + for ((beforeTime, value) in before) { + val predicateValue = predicateValues[beforeTime] + if (predicateValue == predicateValueToAccept) { + result[beforeTime + 1] = value + } + } + + return result + } + + private fun extractPredicateValues(filteringMap: Value): Map { + val (keys, values) = InterpreterUtil.extractMap(filteringMap) + val result = mutableMapOf() + for (i in 0.until(keys.length())) { + val time = keys.getValue(i) + val value = values.getValue(i) + if (time !is IntegerValue) throw UnexpectedValueTypeException("time should be represented by integer value") + if (value !is BooleanValue) throw UnexpectedValueTypeException("predicate value should be represented by boolean value") + result[time.value()] = value.value() + } + + return result } } \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/InterpreterUtil.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/InterpreterUtil.kt new file mode 100644 index 00000000000..e1c293cd2ba --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/InterpreterUtil.kt @@ -0,0 +1,32 @@ +package com.intellij.debugger.streams.kotlin.trace.impl.interpret + +import com.intellij.debugger.streams.trace.TraceElement +import com.intellij.debugger.streams.trace.impl.interpret.ex.UnexpectedValueException +import com.sun.jdi.ArrayReference +import com.sun.jdi.Value + +/** + * @author Vitaliy.Bibaev + */ +object InterpreterUtil { + + fun extractMap(value: Value): MapRepresentation { + if (value !is ArrayReference || value.length() != 2) { + throw UnexpectedValueException("Map should be represented by array with two nested arrays: keys and values") + } + + val keys = value.getValue(0) + val values = value.getValue(1) + + if (keys !is ArrayReference || values !is ArrayReference || keys.length() != values.length()) { + throw UnexpectedValueException("Keys and values should be arrays with equal counts of elements") + } + + return MapRepresentation(keys, values) + } + + fun createIndexByTime(elements: List): Map = + elements.associate { elem -> elem.time to elem } + + data class MapRepresentation(val keys: ArrayReference, val values: ArrayReference) +} diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/ValuesOrder.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/ValuesOrder.kt new file mode 100644 index 00000000000..d43ff0ee187 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/interpret/ValuesOrder.kt @@ -0,0 +1,23 @@ +package com.intellij.debugger.streams.kotlin.trace.impl.interpret + +import com.intellij.debugger.streams.trace.TraceElement +import com.intellij.debugger.streams.trace.TraceInfo +import com.intellij.debugger.streams.wrapper.StreamCall + +/** + * @author Vitaliy.Bibaev + */ +class ValuesOrder(private val call: StreamCall, + private val before: Map, + private val after: Map) + : TraceInfo { + override fun getValuesOrderBefore(): Map = before + + override fun getCall(): StreamCall = call + + override fun getValuesOrderAfter(): Map = after + + override fun getDirectTrace(): MutableMap>? = null + + override fun getReverseTrace(): MutableMap>? = null +} \ No newline at end of file