Support filterIsInstance with generic parameter
This commit is contained in:
committed by
Yan Zhulanow
parent
e9d8398573
commit
bfced7dd1e
+11
-3
@@ -2,13 +2,15 @@
|
|||||||
package com.intellij.debugger.streams.kotlin.lib.sequence
|
package com.intellij.debugger.streams.kotlin.lib.sequence
|
||||||
|
|
||||||
import com.intellij.debugger.streams.kotlin.resolve.ChunkedResolver
|
import com.intellij.debugger.streams.kotlin.resolve.ChunkedResolver
|
||||||
import com.intellij.debugger.streams.kotlin.resolve.MapNotNullResolver
|
import com.intellij.debugger.streams.kotlin.resolve.FilteredMapResolver
|
||||||
import com.intellij.debugger.streams.kotlin.resolve.WindowedResolver
|
import com.intellij.debugger.streams.kotlin.resolve.WindowedResolver
|
||||||
|
import com.intellij.debugger.streams.kotlin.trace.impl.handler.sequence.FilterIsInstanceHandler
|
||||||
import com.intellij.debugger.streams.lib.IntermediateOperation
|
import com.intellij.debugger.streams.lib.IntermediateOperation
|
||||||
import com.intellij.debugger.streams.lib.impl.*
|
import com.intellij.debugger.streams.lib.impl.*
|
||||||
import com.intellij.debugger.streams.resolve.AppendResolver
|
import com.intellij.debugger.streams.resolve.AppendResolver
|
||||||
import com.intellij.debugger.streams.resolve.PairMapResolver
|
import com.intellij.debugger.streams.resolve.PairMapResolver
|
||||||
import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHandler
|
import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHandler
|
||||||
|
import com.intellij.debugger.streams.trace.impl.interpret.SimplePeekCallTraceInterpreter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
@@ -16,7 +18,9 @@ import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHan
|
|||||||
class KotlinSequencesSupport : LibrarySupportBase() {
|
class KotlinSequencesSupport : LibrarySupportBase() {
|
||||||
init {
|
init {
|
||||||
addIntermediateOperationsSupport(*filterOperations("filter", "filterNot", "filterIndexed",
|
addIntermediateOperationsSupport(*filterOperations("filter", "filterNot", "filterIndexed",
|
||||||
"filterIsInstance", "drop", "dropWhile", "minus", "minusElement", "take", "takeWhile", "onEach", "asSequence"))
|
"drop", "dropWhile", "minus", "minusElement", "take", "takeWhile", "onEach", "asSequence"))
|
||||||
|
|
||||||
|
addIntermediateOperationsSupport(FilterIsInstanceOperationHandler())
|
||||||
|
|
||||||
addIntermediateOperationsSupport(*mapOperations("map", "mapIndexed", "requireNoNulls", "withIndex",
|
addIntermediateOperationsSupport(*mapOperations("map", "mapIndexed", "requireNoNulls", "withIndex",
|
||||||
"zip", "constrainOnce"))
|
"zip", "constrainOnce"))
|
||||||
@@ -33,7 +37,7 @@ class KotlinSequencesSupport : LibrarySupportBase() {
|
|||||||
|
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
|
||||||
|
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", MapNotNullResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", FilteredMapResolver()))
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
|
||||||
}
|
}
|
||||||
@@ -49,4 +53,8 @@ class KotlinSequencesSupport : LibrarySupportBase() {
|
|||||||
|
|
||||||
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
|
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
|
||||||
names.map { SortedOperation(it) }.toTypedArray()
|
names.map { SortedOperation(it) }.toTypedArray()
|
||||||
|
|
||||||
|
private class FilterIsInstanceOperationHandler()
|
||||||
|
: IntermediateOperationBase("filterIsInstance", ::FilterIsInstanceHandler,
|
||||||
|
SimplePeekCallTraceInterpreter(), FilteredMapResolver())
|
||||||
}
|
}
|
||||||
+1
-1
@@ -8,7 +8,7 @@ import com.intellij.debugger.streams.trace.TraceInfo
|
|||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class MapNotNullResolver : ValuesOrderResolver {
|
class FilteredMapResolver : ValuesOrderResolver {
|
||||||
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
||||||
val before = info.valuesOrderBefore
|
val before = info.valuesOrderBefore
|
||||||
val after = info.valuesOrderAfter
|
val after = info.valuesOrderAfter
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
package com.intellij.debugger.streams.kotlin.trace.impl.handler.sequence
|
||||||
|
|
||||||
|
import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinTypes
|
||||||
|
import com.intellij.debugger.streams.trace.dsl.CodeBlock
|
||||||
|
import com.intellij.debugger.streams.trace.dsl.Dsl
|
||||||
|
import com.intellij.debugger.streams.trace.dsl.Expression
|
||||||
|
import com.intellij.debugger.streams.trace.dsl.VariableDeclaration
|
||||||
|
import com.intellij.debugger.streams.trace.impl.handler.unified.HandlerBase
|
||||||
|
import com.intellij.debugger.streams.trace.impl.handler.unified.PeekTraceHandler
|
||||||
|
import com.intellij.debugger.streams.wrapper.CallArgument
|
||||||
|
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
||||||
|
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
|
||||||
|
import com.intellij.debugger.streams.wrapper.impl.IntermediateStreamCallImpl
|
||||||
|
import com.intellij.openapi.util.TextRange.EMPTY_RANGE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vitaliy.Bibaev
|
||||||
|
*/
|
||||||
|
class FilterIsInstanceHandler(num: Int, call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
|
||||||
|
private companion object {
|
||||||
|
fun createHandler(num: Int, call: IntermediateStreamCall, dsl: Dsl): HandlerBase.Intermediate =
|
||||||
|
if (call.arguments.isEmpty()) MyWithGenericsHandler(num, call, dsl)
|
||||||
|
else PeekTraceHandler(num, call.name, call.typeBefore, call.typeAfter, dsl)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val filterHandler = createHandler(num, call, dsl)
|
||||||
|
|
||||||
|
// use explicit delegation to avoid issues with navigation
|
||||||
|
|
||||||
|
override fun additionalCallsAfter(): MutableList<IntermediateStreamCall> = filterHandler.additionalCallsAfter()
|
||||||
|
override fun additionalCallsBefore(): List<IntermediateStreamCall> = filterHandler.additionalCallsBefore()
|
||||||
|
override fun additionalVariablesDeclaration(): List<VariableDeclaration> = filterHandler.additionalVariablesDeclaration()
|
||||||
|
override fun getResultExpression(): Expression = filterHandler.resultExpression
|
||||||
|
override fun prepareResult(): CodeBlock = filterHandler.prepareResult()
|
||||||
|
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall = filterHandler.transformCall(call)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transforms filterIsInstance<ClassName> -> filter { it is ClassName }.map { it as ClassName }
|
||||||
|
*/
|
||||||
|
private class MyWithGenericsHandler(num: Int, private val call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
|
||||||
|
private val peekHandler = PeekTraceHandler(num, "filterIsInstance", call.typeBefore, call.typeAfter, dsl)
|
||||||
|
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
|
||||||
|
val mapperType = functionalType(call.typeBefore.genericTypeName, call.typeAfter.genericTypeName)
|
||||||
|
val mapper = CallArgumentImpl(mapperType, "{ x -> x as ${call.typeAfter.genericTypeName} }")
|
||||||
|
val result: MutableList<IntermediateStreamCall> = mutableListOf(syntheticMapCall(mapper))
|
||||||
|
result.addAll(peekHandler.additionalCallsAfter())
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun additionalCallsBefore(): List<IntermediateStreamCall> = peekHandler.additionalCallsBefore()
|
||||||
|
|
||||||
|
override fun additionalVariablesDeclaration(): List<VariableDeclaration> =
|
||||||
|
peekHandler.additionalVariablesDeclaration()
|
||||||
|
|
||||||
|
override fun getResultExpression(): Expression = peekHandler.resultExpression
|
||||||
|
|
||||||
|
override fun prepareResult(): CodeBlock = peekHandler.prepareResult()
|
||||||
|
|
||||||
|
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
|
||||||
|
val typeAfter = call.typeAfter.genericTypeName
|
||||||
|
val predicateType = functionalType(typeAfter, KotlinTypes.BOOLEAN.genericTypeName)
|
||||||
|
val predicate = CallArgumentImpl(predicateType, " { x -> x is $typeAfter} ")
|
||||||
|
return syntheticFilterCall(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun syntheticMapCall(mapper: CallArgument): IntermediateStreamCall =
|
||||||
|
IntermediateStreamCallImpl("map", listOf(mapper), call.typeBefore, call.typeAfter, EMPTY_RANGE)
|
||||||
|
|
||||||
|
private fun syntheticFilterCall(predicate: CallArgument): IntermediateStreamCall =
|
||||||
|
IntermediateStreamCallImpl("filter", listOf(predicate), call.typeBefore, call.typeBefore, EMPTY_RANGE)
|
||||||
|
|
||||||
|
private fun functionalType(argType: String, resultType: String): String {
|
||||||
|
return "($argType) -> $resultType"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,29 @@ LineBreakpoint created at FilterIsInstance.kt:5
|
|||||||
Run Java
|
Run Java
|
||||||
Connected to the target VM
|
Connected to the target VM
|
||||||
FilterIsInstance.kt:5
|
FilterIsInstance.kt:5
|
||||||
Exception caught: junit.framework.AssertionFailedError: Type inference failed: Not enough information to infer parameter R in inline fun <reified R> Sequence<*>.filterIsInstance(): Sequence<R>
|
arrayOf(true, "12", false).asSequence()
|
||||||
Please specify it explicitly.
|
.filterIsInstance()
|
||||||
, Type inference failed: Not enough information to infer parameter R in inline fun <reified R> Sequence<*>.filterIsInstance(): Sequence<R>
|
.forEach({})
|
||||||
Please specify it explicitly.
|
filterIsInstance
|
||||||
|
before: 1,3,4
|
||||||
WRONG! Should be fixed in the platform
|
after: 2,5
|
||||||
|
forEach
|
||||||
|
before: 2,5
|
||||||
|
after: nothing
|
||||||
|
mappings for filterIsInstance
|
||||||
|
direct:
|
||||||
|
1 -> 2
|
||||||
|
3 -> nothing
|
||||||
|
4 -> 5
|
||||||
|
reverse:
|
||||||
|
1 <- 2
|
||||||
|
4 <- 5
|
||||||
|
mappings for forEach
|
||||||
|
direct:
|
||||||
|
2 -> nothing
|
||||||
|
5 -> nothing
|
||||||
|
reverse:
|
||||||
|
empty
|
||||||
Disconnected from the target VM
|
Disconnected from the target VM
|
||||||
|
|
||||||
Process finished with exit code 0
|
Process finished with exit code 0
|
||||||
|
|||||||
Reference in New Issue
Block a user