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
|
||||
|
||||
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.trace.impl.handler.sequence.FilterIsInstanceHandler
|
||||
import com.intellij.debugger.streams.lib.IntermediateOperation
|
||||
import com.intellij.debugger.streams.lib.impl.*
|
||||
import com.intellij.debugger.streams.resolve.AppendResolver
|
||||
import com.intellij.debugger.streams.resolve.PairMapResolver
|
||||
import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHandler
|
||||
import com.intellij.debugger.streams.trace.impl.interpret.SimplePeekCallTraceInterpreter
|
||||
|
||||
/**
|
||||
* @author Vitaliy.Bibaev
|
||||
@@ -16,7 +18,9 @@ import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHan
|
||||
class KotlinSequencesSupport : LibrarySupportBase() {
|
||||
init {
|
||||
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",
|
||||
"zip", "constrainOnce"))
|
||||
@@ -33,7 +37,7 @@ class KotlinSequencesSupport : LibrarySupportBase() {
|
||||
|
||||
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
|
||||
|
||||
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", MapNotNullResolver()))
|
||||
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", FilteredMapResolver()))
|
||||
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
|
||||
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
|
||||
}
|
||||
@@ -49,4 +53,8 @@ class KotlinSequencesSupport : LibrarySupportBase() {
|
||||
|
||||
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
|
||||
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
|
||||
*/
|
||||
class MapNotNullResolver : ValuesOrderResolver {
|
||||
class FilteredMapResolver : ValuesOrderResolver {
|
||||
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
||||
val before = info.valuesOrderBefore
|
||||
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
|
||||
Connected to the target VM
|
||||
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>
|
||||
Please specify it explicitly.
|
||||
, Type inference failed: Not enough information to infer parameter R in inline fun <reified R> Sequence<*>.filterIsInstance(): Sequence<R>
|
||||
Please specify it explicitly.
|
||||
|
||||
WRONG! Should be fixed in the platform
|
||||
|
||||
arrayOf(true, "12", false).asSequence()
|
||||
.filterIsInstance()
|
||||
.forEach({})
|
||||
filterIsInstance
|
||||
before: 1,3,4
|
||||
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
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
Reference in New Issue
Block a user