Fix bug when onEach extension call is not found for arrays
This commit is contained in:
committed by
Yan Zhulanow
parent
aa7f1073e6
commit
7c417a59dc
+31
-7
@@ -6,18 +6,22 @@ import com.intellij.debugger.streams.kotlin.psi.KotlinPsiUtil
|
|||||||
import com.intellij.debugger.streams.kotlin.psi.callName
|
import com.intellij.debugger.streams.kotlin.psi.callName
|
||||||
import com.intellij.debugger.streams.kotlin.psi.resolveType
|
import com.intellij.debugger.streams.kotlin.psi.resolveType
|
||||||
import com.intellij.debugger.streams.psi.ChainTransformer
|
import com.intellij.debugger.streams.psi.ChainTransformer
|
||||||
|
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
|
||||||
import com.intellij.debugger.streams.wrapper.CallArgument
|
import com.intellij.debugger.streams.wrapper.CallArgument
|
||||||
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
||||||
|
import com.intellij.debugger.streams.wrapper.QualifierExpression
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChain
|
import com.intellij.debugger.streams.wrapper.StreamChain
|
||||||
import com.intellij.debugger.streams.wrapper.impl.*
|
import com.intellij.debugger.streams.wrapper.impl.*
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
@@ -37,15 +41,10 @@ class KotlinChainTransformerImpl(private val typeExtractor: CallTypeExtractor) :
|
|||||||
terminationsPsiCall.valueArguments.map { createCallArgument(terminationsPsiCall, it) },
|
terminationsPsiCall.valueArguments.map { createCallArgument(terminationsPsiCall, it) },
|
||||||
typeBeforeTerminator, resultType, terminationsPsiCall.textRange)
|
typeBeforeTerminator, resultType, terminationsPsiCall.textRange)
|
||||||
|
|
||||||
val qualifierTypeAfter =
|
val typeAfterQualifier =
|
||||||
if (intermediateCalls.isEmpty()) typeBeforeTerminator else intermediateCalls.first().typeBefore
|
if (intermediateCalls.isEmpty()) typeBeforeTerminator else intermediateCalls.first().typeBefore
|
||||||
|
|
||||||
val firstCall = callChain.first()
|
val qualifier = createQualifier(callChain.first(), typeAfterQualifier)
|
||||||
val parent = firstCall.parent
|
|
||||||
val qualifier = if (parent is KtDotQualifiedExpression)
|
|
||||||
QualifierExpressionImpl(parent.receiverExpression.text, parent.receiverExpression.textRange, qualifierTypeAfter)
|
|
||||||
else // This is possible only when {@code this} inherits Stream/Iterable/Sequence/etc
|
|
||||||
QualifierExpressionImpl("", TextRange.EMPTY_RANGE, qualifierTypeAfter)
|
|
||||||
|
|
||||||
return StreamChainImpl(qualifier, intermediateCalls, terminationCall, context)
|
return StreamChainImpl(qualifier, intermediateCalls, terminationCall, context)
|
||||||
}
|
}
|
||||||
@@ -61,4 +60,29 @@ class KotlinChainTransformerImpl(private val typeExtractor: CallTypeExtractor) :
|
|||||||
val parameter = resolvedCall.getParameterForArgument(arg) ?: return arg.toCallArgument()
|
val parameter = resolvedCall.getParameterForArgument(arg) ?: return arg.toCallArgument()
|
||||||
return CallArgumentImpl(KotlinPsiUtil.getTypeName(parameter.type), arg.text)
|
return CallArgumentImpl(KotlinPsiUtil.getTypeName(parameter.type), arg.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createQualifier(expression: PsiElement, typeAfter: GenericType): QualifierExpression {
|
||||||
|
val parent = expression.parent as? KtDotQualifiedExpression
|
||||||
|
?: return QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfter)
|
||||||
|
val receiver = parent.receiverExpression
|
||||||
|
val qualifier = QualifierExpressionImpl(receiver.text, receiver.textRange, typeAfter)
|
||||||
|
if (receiver.resolveType().isArray) {
|
||||||
|
return WrappedQualifier(qualifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
return qualifier
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin arrays has not {@code onEach} extension. But current implementation uses onEach to increment a time counter.
|
||||||
|
* We use asIterable to avoid further issues with the transformed expression evaluation
|
||||||
|
*/
|
||||||
|
private class WrappedQualifier(private val qualifierExpression: QualifierExpression)
|
||||||
|
: QualifierExpression by qualifierExpression {
|
||||||
|
override val text: String
|
||||||
|
get() = qualifierExpression.text + ".asIterable()"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val KotlinType.isArray: Boolean
|
||||||
|
get() = KotlinBuiltIns.isArray(this) || KotlinBuiltIns.isPrimitiveArray(this)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-9
@@ -2,15 +2,18 @@ LineBreakpoint created at FilterPrimitiveAsTermination.kt:5
|
|||||||
Run Java
|
Run Java
|
||||||
Connected to the target VM
|
Connected to the target VM
|
||||||
FilterPrimitiveAsTermination.kt:5
|
FilterPrimitiveAsTermination.kt:5
|
||||||
Exception caught: junit.framework.AssertionFailedError: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
|
byteArrayOf(1, 3, 50).asIterable()
|
||||||
@SinceKotlin public inline fun <S : CharSequence> ???.onEach(action: (Char) -> Unit): ??? defined in kotlin.text
|
.filter({ it == 50.toByte() })
|
||||||
@SinceKotlin public inline fun <T, C : Iterable<???>> ByteArray.onEach(action: (???) -> Unit): ByteArray defined in kotlin.collections
|
filter
|
||||||
@SinceKotlin public inline fun <K, V, M : Map<out ???, ???>> ByteArray.onEach(action: (Map.Entry<???, ???>) -> Unit): ByteArray defined in kotlin.collections
|
before: 4,6,8
|
||||||
@SinceKotlin public fun <T> Sequence<???>.onEach(action: (???) -> Unit): Sequence<???> defined in kotlin.sequences, Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
|
after: 8
|
||||||
@SinceKotlin public inline fun <S : CharSequence> ???.onEach(action: (Char) -> Unit): ??? defined in kotlin.text
|
mappings for filter
|
||||||
@SinceKotlin public inline fun <T, C : Iterable<???>> ByteArray.onEach(action: (???) -> Unit): ByteArray defined in kotlin.collections
|
direct:
|
||||||
@SinceKotlin public inline fun <K, V, M : Map<out ???, ???>> ByteArray.onEach(action: (Map.Entry<???, ???>) -> Unit): ByteArray defined in kotlin.collections
|
4 -> nothing
|
||||||
@SinceKotlin public fun <T> Sequence<???>.onEach(action: (???) -> Unit): Sequence<???> defined in kotlin.sequences
|
6 -> nothing
|
||||||
|
8 -> 8
|
||||||
|
reverse:
|
||||||
|
8 <- 8
|
||||||
Disconnected from the target VM
|
Disconnected from the target VM
|
||||||
|
|
||||||
WRONG!
|
WRONG!
|
||||||
|
|||||||
Reference in New Issue
Block a user