Apply project code style settings to sequence debugger code

This commit is contained in:
Vitaliy.Bibaev
2018-06-09 11:12:48 +03:00
committed by Yan Zhulanow
parent 245a358ea8
commit 2d22267cf1
67 changed files with 1480 additions and 1413 deletions
@@ -5,5 +5,5 @@ package org.jetbrains.kotlin.idea.debugger.sequence.lib
* @author Vitaliy.Bibaev
*/
object LibraryUtil {
val KOTLIN_LANGUAGE_ID = "kotlin"
val KOTLIN_LANGUAGE_ID = "kotlin"
}
@@ -1,7 +1,6 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.lib.collections
import org.jetbrains.kotlin.idea.debugger.sequence.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
@@ -16,38 +15,39 @@ import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections.BothSemanticHandlerWrapper
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections.BothSemanticsHandler
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections.FilterCallHandler
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.interpret.FilterTraceInterpreter
/**
* @author Vitaliy.Bibaev
*/
class KotlinCollectionLibrarySupport : LibrarySupportBase() {
init {
addOperation(FilterOperation("filter", FilterCallHandler(), true))
addOperation(FilterOperation("filterNot", FilterCallHandler(), false))
}
init {
addOperation(FilterOperation("filter", FilterCallHandler(), true))
addOperation(FilterOperation("filterNot", FilterCallHandler(), false))
}
private fun addOperation(operation: CollectionOperation) {
addIntermediateOperationsSupport(operation)
addTerminationOperationsSupport(operation)
}
private fun addOperation(operation: CollectionOperation) {
addIntermediateOperationsSupport(operation)
addTerminationOperationsSupport(operation)
}
private abstract class CollectionOperation(override val name: String,
handler: BothSemanticsHandler
)
: IntermediateOperation, TerminalOperation {
private abstract class CollectionOperation(
override val name: String,
handler: BothSemanticsHandler
) : IntermediateOperation, TerminalOperation {
private val wrapper = BothSemanticHandlerWrapper(handler)
private val wrapper = BothSemanticHandlerWrapper(handler)
override fun getTraceHandler(callOrder: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
wrapper.createIntermediateHandler(callOrder, call, dsl)
override fun getTraceHandler(callOrder: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
wrapper.createIntermediateHandler(callOrder, call, dsl)
override fun getTraceHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
wrapper.createTerminatorHandler(call, resultExpression, dsl)
}
override fun getTraceHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
wrapper.createTerminatorHandler(call, resultExpression, dsl)
}
private class FilterOperation(name: String, handler: BothSemanticsHandler, valueToAccept: Boolean)
: CollectionOperation(name, handler) {
override val traceInterpreter: CallTraceInterpreter = FilterTraceInterpreter(valueToAccept)
override val valuesOrderResolver: ValuesOrderResolver = FilterResolver()
}
private class FilterOperation(name: String, handler: BothSemanticsHandler, valueToAccept: Boolean) :
CollectionOperation(name, handler) {
override val traceInterpreter: CallTraceInterpreter = FilterTraceInterpreter(valueToAccept)
override val valuesOrderResolver: ValuesOrderResolver = FilterResolver()
}
}
@@ -1,34 +1,34 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.lib.collections
import org.jetbrains.kotlin.idea.debugger.sequence.lib.LibraryUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.collections.KotlinCollectionChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCollectionsPeekCallFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.debugger.sequence.lib.LibraryUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.collections.KotlinCollectionChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCollectionsPeekCallFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
/**
* @author Vitaliy.Bibaev
*/
class KotlinCollectionSupportProvider : LibrarySupportProvider {
private companion object {
val builder: StreamChainBuilder = KotlinCollectionChainBuilder()
val support: LibrarySupport = KotlinCollectionLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
}
private companion object {
val builder: StreamChainBuilder = KotlinCollectionChainBuilder()
val support: LibrarySupport = KotlinCollectionLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
}
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getChainBuilder(): StreamChainBuilder = builder
override fun getChainBuilder(): StreamChainBuilder = builder
override fun getLibrarySupport(): LibrarySupport = support
override fun getLibrarySupport(): LibrarySupport = support
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder
= KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder =
KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
}
@@ -1,6 +1,13 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.lib.java
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.lib.impl.StandardLibrarySupport
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.debugger.sequence.lib.LibraryUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.PackageBasedCallChecker
@@ -9,33 +16,26 @@ import org.jetbrains.kotlin.idea.debugger.sequence.psi.java.JavaStreamChainTypeE
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.JavaPeekCallFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.lib.impl.StandardLibrarySupport
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
/**
* @author Vitaliy.Bibaev
*/
class JavaStandardLibrarySupportProvider : LibrarySupportProvider {
private companion object {
val builder = TerminatedChainBuilder(
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
PackageBasedCallChecker("java.util.stream")
)
val support = StandardLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
}
private companion object {
val builder = TerminatedChainBuilder(
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
PackageBasedCallChecker("java.util.stream")
)
val support = StandardLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
}
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getChainBuilder(): StreamChainBuilder = builder
override fun getChainBuilder(): StreamChainBuilder = builder
override fun getLibrarySupport(): LibrarySupport = support
override fun getLibrarySupport(): LibrarySupport = support
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder =
KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder =
KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
}
@@ -1,6 +1,13 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.lib.java
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.lib.impl.StreamExLibrarySupport
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.debugger.sequence.lib.LibraryUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.PackageBasedCallChecker
@@ -9,33 +16,26 @@ import org.jetbrains.kotlin.idea.debugger.sequence.psi.java.JavaStreamChainTypeE
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.JavaPeekCallFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.lib.impl.StreamExLibrarySupport
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
/**
* @author Vitaliy.Bibaev
*/
class StreamExLibrarySupportProvider : LibrarySupportProvider {
private companion object {
val streamChainBuilder = TerminatedChainBuilder(
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
PackageBasedCallChecker("one.util.streamex")
)
val support = StreamExLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
}
private companion object {
val streamChainBuilder = TerminatedChainBuilder(
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
PackageBasedCallChecker("one.util.streamex")
)
val support = StreamExLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
}
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getChainBuilder(): StreamChainBuilder = streamChainBuilder
override fun getChainBuilder(): StreamChainBuilder = streamChainBuilder
override fun getLibrarySupport(): LibrarySupport = support
override fun getLibrarySupport(): LibrarySupport = support
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder = expressionBuilder
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder = expressionBuilder
}
@@ -1,6 +1,12 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.lib.sequence
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.debugger.sequence.lib.LibraryUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.TerminatedChainBuilder
@@ -9,33 +15,27 @@ import org.jetbrains.kotlin.idea.debugger.sequence.psi.sequence.SequenceTypeExtr
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCollectionsPeekCallFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
import com.intellij.debugger.streams.lib.LibrarySupport
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.openapi.project.Project
/**
* @author Vitaliy.Bibaev
*/
class KotlinSequenceSupportProvider : LibrarySupportProvider {
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
private companion object {
val builder: StreamChainBuilder = TerminatedChainBuilder(
KotlinChainTransformerImpl(SequenceTypeExtractor()),
SequenceCallChecker()
)
val support = KotlinSequencesSupport()
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
}
private companion object {
val builder: StreamChainBuilder = TerminatedChainBuilder(
KotlinChainTransformerImpl(SequenceTypeExtractor()),
SequenceCallChecker()
)
val support = KotlinSequencesSupport()
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
}
override fun getChainBuilder(): StreamChainBuilder = builder
override fun getChainBuilder(): StreamChainBuilder = builder
override fun getLibrarySupport(): LibrarySupport = support
override fun getLibrarySupport(): LibrarySupport = support
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder = expressionBuilder
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder = expressionBuilder
}
@@ -1,62 +1,70 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.lib.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.resolve.ChunkedResolver
import org.jetbrains.kotlin.idea.debugger.sequence.resolve.FilteredMapResolver
import org.jetbrains.kotlin.idea.debugger.sequence.resolve.WindowedResolver
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.sequence.FilterIsInstanceHandler
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.sequence.KotlinDistinctByHandler
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
import org.jetbrains.kotlin.idea.debugger.sequence.resolve.ChunkedResolver
import org.jetbrains.kotlin.idea.debugger.sequence.resolve.FilteredMapResolver
import org.jetbrains.kotlin.idea.debugger.sequence.resolve.WindowedResolver
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.sequence.FilterIsInstanceHandler
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.sequence.KotlinDistinctByHandler
/**
* @author Vitaliy.Bibaev
*/
class KotlinSequencesSupport : LibrarySupportBase() {
init {
addIntermediateOperationsSupport(*filterOperations("filter", "filterNot", "filterIndexed",
"drop", "dropWhile", "minus", "minusElement", "take", "takeWhile", "onEach", "asSequence"))
init {
addIntermediateOperationsSupport(
*filterOperations(
"filter", "filterNot", "filterIndexed",
"drop", "dropWhile", "minus", "minusElement", "take", "takeWhile", "onEach", "asSequence"
)
)
addIntermediateOperationsSupport(FilterIsInstanceOperationHandler())
addIntermediateOperationsSupport(FilterIsInstanceOperationHandler())
addIntermediateOperationsSupport(*mapOperations("map", "mapIndexed", "requireNoNulls", "withIndex",
"zip", "constrainOnce"))
addIntermediateOperationsSupport(
*mapOperations(
"map", "mapIndexed", "requireNoNulls", "withIndex",
"zip", "constrainOnce"
)
)
addIntermediateOperationsSupport(*flatMapOperations("flatMap", "flatten"))
addIntermediateOperationsSupport(*flatMapOperations("flatMap", "flatten"))
addIntermediateOperationsSupport(*sortedOperations("sorted", "sortedBy", "sortedDescending", "sortedWith"))
addIntermediateOperationsSupport(*sortedOperations("sorted", "sortedBy", "sortedDescending", "sortedWith"))
addIntermediateOperationsSupport(DistinctOperation("distinct", ::DistinctTraceHandler))
addIntermediateOperationsSupport(DistinctOperation("distinctBy", ::KotlinDistinctByHandler))
addIntermediateOperationsSupport(DistinctOperation("distinct", ::DistinctTraceHandler))
addIntermediateOperationsSupport(DistinctOperation("distinctBy", ::KotlinDistinctByHandler))
addIntermediateOperationsSupport(ConcatOperation("plus", AppendResolver()))
addIntermediateOperationsSupport(ConcatOperation("plusElement", AppendResolver()))
addIntermediateOperationsSupport(ConcatOperation("plus", AppendResolver()))
addIntermediateOperationsSupport(ConcatOperation("plusElement", AppendResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", FilteredMapResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
}
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", FilteredMapResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
}
private fun filterOperations(vararg names: String): Array<IntermediateOperation> =
names.map { FilterOperation(it) }.toTypedArray()
private fun filterOperations(vararg names: String): Array<IntermediateOperation> =
names.map { FilterOperation(it) }.toTypedArray()
private fun mapOperations(vararg names: String): Array<IntermediateOperation> =
names.map { MappingOperation(it) }.toTypedArray()
private fun mapOperations(vararg names: String): Array<IntermediateOperation> =
names.map { MappingOperation(it) }.toTypedArray()
private fun flatMapOperations(vararg names: String): Array<IntermediateOperation> =
names.map { FlatMappingOperation(it) }.toTypedArray()
private fun flatMapOperations(vararg names: String): Array<IntermediateOperation> =
names.map { FlatMappingOperation(it) }.toTypedArray()
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
names.map { SortedOperation(it) }.toTypedArray()
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
names.map { SortedOperation(it) }.toTypedArray()
private class FilterIsInstanceOperationHandler()
: IntermediateOperationBase("filterIsInstance", ::FilterIsInstanceHandler,
SimplePeekCallTraceInterpreter(), FilteredMapResolver()
)
private class FilterIsInstanceOperationHandler() : IntermediateOperationBase(
"filterIsInstance", ::FilterIsInstanceHandler,
SimplePeekCallTraceInterpreter(), FilteredMapResolver()
)
}
@@ -9,23 +9,23 @@ import org.jetbrains.kotlin.types.KotlinType
* @author Vitaliy.Bibaev
*/
interface CallTypeExtractor {
fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes
fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes
fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes
fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes
data class IntermediateCallTypes(val typeBefore: GenericType, val typeAfter: GenericType)
data class TerminatorCallTypes(val typeBefore: GenericType, val resultType: GenericType)
data class IntermediateCallTypes(val typeBefore: GenericType, val typeAfter: GenericType)
data class TerminatorCallTypes(val typeBefore: GenericType, val resultType: GenericType)
abstract class Base : CallTypeExtractor {
override fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes =
IntermediateCallTypes(extractItemsType(call.receiverType()), extractItemsType(call.resolveType()))
abstract class Base : CallTypeExtractor {
override fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes =
IntermediateCallTypes(extractItemsType(call.receiverType()), extractItemsType(call.resolveType()))
override fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes =
TerminatorCallTypes(extractItemsType(call.receiverType()), getResultType(call.resolveType()))
override fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes =
TerminatorCallTypes(extractItemsType(call.receiverType()), getResultType(call.resolveType()))
protected abstract fun extractItemsType(type: KotlinType?): GenericType
protected abstract fun getResultType(type: KotlinType): GenericType
protected abstract fun extractItemsType(type: KotlinType?): GenericType
protected abstract fun getResultType(type: KotlinType): GenericType
}
}
}
@@ -18,20 +18,20 @@ import org.jetbrains.kotlin.types.KotlinType
*/
object KotlinPsiUtil {
private val WITH_TYPES_RENDERER = DescriptorRenderer.FQ_NAMES_IN_TYPES
private val WITH_TYPES_RENDERER = DescriptorRenderer.FQ_NAMES_IN_TYPES
fun getTypeName(type: KotlinType): String {
if (type is FlexibleType) {
return WITH_TYPES_RENDERER.renderType(type.approximateFlexibleTypes())
fun getTypeName(type: KotlinType): String {
if (type is FlexibleType) {
return WITH_TYPES_RENDERER.renderType(type.approximateFlexibleTypes())
}
return WITH_TYPES_RENDERER.renderType(type)
}
return WITH_TYPES_RENDERER.renderType(type)
}
fun getTypeWithoutTypeParameters(type: KotlinType): String {
val descriptor = type.constructor.declarationDescriptor ?: return getTypeName(type)
return descriptor.fqNameSafe.asString()
}
fun getTypeWithoutTypeParameters(type: KotlinType): String {
val descriptor = type.constructor.declarationDescriptor ?: return getTypeName(type)
return descriptor.fqNameSafe.asString()
}
}
fun KtExpression.resolveType(): KotlinType =
@@ -40,16 +40,16 @@ fun KtExpression.resolveType(): KotlinType =
fun KtCallExpression.callName(): String = this.calleeExpression!!.text
fun KtCallExpression.receiver(): ReceiverValue? {
val resolvedCall = getResolvedCall(analyze()) ?: return null
return resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver
val resolvedCall = getResolvedCall(analyze()) ?: return null
return resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver
}
fun KtCallExpression.previousCall(): KtCallExpression? {
val parent = this.parent as? KtDotQualifiedExpression ?: return null
val receiverExpression = parent.receiverExpression
if (receiverExpression is KtCallExpression) return receiverExpression
if (receiverExpression is KtDotQualifiedExpression) return receiverExpression.selectorExpression as? KtCallExpression
return null
val parent = this.parent as? KtDotQualifiedExpression ?: return null
val receiverExpression = parent.receiverExpression
if (receiverExpression is KtCallExpression) return receiverExpression
if (receiverExpression is KtDotQualifiedExpression) return receiverExpression.selectorExpression as? KtCallExpression
return null
}
fun KtCallExpression.receiverType(): KotlinType? = receiver()?.type
@@ -7,8 +7,8 @@ import org.jetbrains.kotlin.psi.KtCallExpression
* @author Vitaliy.Bibaev
*/
interface StreamCallChecker {
fun isIntermediateCall(expression: KtCallExpression): Boolean
fun isTerminationCall(expression: KtCallExpression): Boolean
fun isIntermediateCall(expression: KtCallExpression): Boolean
fun isTerminationCall(expression: KtCallExpression): Boolean
fun isStreamCall(expression: KtCallExpression): Boolean = isIntermediateCall(expression) || isTerminationCall(expression)
fun isStreamCall(expression: KtCallExpression): Boolean = isIntermediateCall(expression) || isTerminationCall(expression)
}
@@ -1,14 +1,14 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.collections
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
import org.jetbrains.kotlin.idea.debugger.sequence.psi.resolveType
import com.intellij.debugger.streams.psi.ChainTransformer
import com.intellij.debugger.streams.wrapper.QualifierExpression
import com.intellij.debugger.streams.wrapper.StreamChain
import com.intellij.debugger.streams.wrapper.impl.StreamChainImpl
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
import org.jetbrains.kotlin.idea.debugger.sequence.psi.resolveType
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.types.KotlinType
@@ -16,30 +16,29 @@ import org.jetbrains.kotlin.types.KotlinType
* @author Vitaliy.Bibaev
*/
class CollectionChainTransformer : ChainTransformer<KtCallExpression> {
private val transformer = KotlinChainTransformerImpl(KotlinCollectionsTypeExtractor())
private val transformer = KotlinChainTransformerImpl(KotlinCollectionsTypeExtractor())
override fun transform(chainCalls: List<KtCallExpression>, context: PsiElement): StreamChain {
val chain = transformer.transform(chainCalls, context)
override fun transform(chainCalls: List<KtCallExpression>, context: PsiElement): StreamChain {
val chain = transformer.transform(chainCalls, context)
if (chainCalls.first().resolveType().isArray) {
val qualifier = WrappedQualifier(chain.qualifierExpression)
return StreamChainImpl(qualifier, chain.intermediateCalls, chain.terminationCall, chain.context)
if (chainCalls.first().resolveType().isArray) {
val qualifier = WrappedQualifier(chain.qualifierExpression)
return StreamChainImpl(qualifier, chain.intermediateCalls, chain.terminationCall, chain.context)
}
return chain
}
return chain
}
/**
* Kotlin arrays have 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
* TODO: Avoid showing "asIterable()" in the tab name in trace window
*/
private class WrappedQualifier(private val qualifierExpression: QualifierExpression) : QualifierExpression by qualifierExpression {
override val text: String
get() = qualifierExpression.text + ".asIterable()"
}
/**
* Kotlin arrays have 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
* TODO: Avoid showing "asIterable()" in the tab name in trace window
*/
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)
private val KotlinType.isArray: Boolean
get() = KotlinBuiltIns.isArray(this) || KotlinBuiltIns.isPrimitiveArray(this)
}
@@ -13,64 +13,66 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
* @author Vitaliy.Bibaev
*/
class KotlinCollectionChainBuilder
: KotlinChainBuilderBase(CollectionChainTransformer()) {
private companion object {
// TODO: Avoid enumeration of all available types
val SUPPORTED_RECEIVERS = setOf("kotlin.collections.Iterable", "kotlin.CharSequence", "kotlin.Array",
"kotlin.BooleanArray", "kotlin.ByteArray", "kotlin.ShortArray", "kotlin.CharArray", "kotlin.IntArray",
"kotlin.LongArray", "kotlin.DoubleArray", "kotlin.FloatArray")
}
private fun isCollectionTransformationCall(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType() ?: return false
if (isTypeSuitable(receiverType)) return true
return receiverType.supertypes().any { isTypeSuitable(it) }
}
override val existenceChecker: ExistenceChecker = object : ExistenceChecker() {
override fun visitCallExpression(expression: KtCallExpression) {
if (isFound()) return
if (isCollectionTransformationCall(expression)) {
fireElementFound()
} else {
super.visitCallExpression(expression)
}
: KotlinChainBuilderBase(CollectionChainTransformer()) {
private companion object {
// TODO: Avoid enumeration of all available types
val SUPPORTED_RECEIVERS = setOf(
"kotlin.collections.Iterable", "kotlin.CharSequence", "kotlin.Array",
"kotlin.BooleanArray", "kotlin.ByteArray", "kotlin.ShortArray", "kotlin.CharArray", "kotlin.IntArray",
"kotlin.LongArray", "kotlin.DoubleArray", "kotlin.FloatArray"
)
}
}
override fun createChainsBuilder(): ChainBuilder = object : ChainBuilder() {
private val previousCalls: MutableMap<KtCallExpression, KtCallExpression> = mutableMapOf()
private val visitedCalls: MutableSet<KtCallExpression> = mutableSetOf()
private fun isCollectionTransformationCall(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType() ?: return false
if (isTypeSuitable(receiverType)) return true
return receiverType.supertypes().any { isTypeSuitable(it) }
}
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
if (isCollectionTransformationCall(expression)) {
visitedCalls.add(expression)
val previous = expression.previousCall()
if (previous != null && isCollectionTransformationCall(previous)) {
previousCalls[expression] = previous
override val existenceChecker: ExistenceChecker = object : ExistenceChecker() {
override fun visitCallExpression(expression: KtCallExpression) {
if (isFound()) return
if (isCollectionTransformationCall(expression)) {
fireElementFound()
} else {
super.visitCallExpression(expression)
}
}
}
}
override fun chains(): List<List<KtCallExpression>> {
val notLastCalls: Set<KtCallExpression> = previousCalls.values.toSet()
return visitedCalls.filter { it !in notLastCalls }.map { buildPsiChain(it) }
override fun createChainsBuilder(): ChainBuilder = object : ChainBuilder() {
private val previousCalls: MutableMap<KtCallExpression, KtCallExpression> = mutableMapOf()
private val visitedCalls: MutableSet<KtCallExpression> = mutableSetOf()
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
if (isCollectionTransformationCall(expression)) {
visitedCalls.add(expression)
val previous = expression.previousCall()
if (previous != null && isCollectionTransformationCall(previous)) {
previousCalls[expression] = previous
}
}
}
override fun chains(): List<List<KtCallExpression>> {
val notLastCalls: Set<KtCallExpression> = previousCalls.values.toSet()
return visitedCalls.filter { it !in notLastCalls }.map { buildPsiChain(it) }
}
private fun buildPsiChain(expression: KtCallExpression): List<KtCallExpression> {
val result = mutableListOf<KtCallExpression>()
var current: KtCallExpression? = expression
while (current != null) {
result.add(current)
current = previousCalls[current]
}
result.reverse()
return result
}
}
private fun buildPsiChain(expression: KtCallExpression): List<KtCallExpression> {
val result = mutableListOf<KtCallExpression>()
var current: KtCallExpression? = expression
while (current != null) {
result.add(current)
current = previousCalls[current]
}
result.reverse()
return result
}
}
private fun isTypeSuitable(type: KotlinType): Boolean =
SUPPORTED_RECEIVERS.contains(KotlinPsiUtil.getTypeWithoutTypeParameters(type))
private fun isTypeSuitable(type: KotlinType): Boolean =
SUPPORTED_RECEIVERS.contains(KotlinPsiUtil.getTypeWithoutTypeParameters(type))
}
@@ -1,13 +1,13 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.collections
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.idea.debugger.sequence.psi.CallTypeExtractor
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.ANY
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.NULLABLE_ANY
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.supertypes
@@ -15,45 +15,45 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
* @author Vitaliy.Bibaev
*/
class KotlinCollectionsTypeExtractor : CallTypeExtractor.Base() {
private companion object {
val LOG = Logger.getInstance(KotlinCollectionsTypeExtractor::class.java)
}
override fun extractItemsType(type: KotlinType?): GenericType {
if (type == null) return NULLABLE_ANY
return tryToFindElementType(type) ?: defaultType(type)
}
override fun getResultType(type: KotlinType): GenericType {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return KotlinTypes.primitiveTypeByName(typeName) ?: KotlinTypes.primitiveArrayByName(typeName) ?: getAny(type)
}
private fun tryToFindElementType(type: KotlinType): GenericType? {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
if (typeName == "kotlin.collections.Iterable" || typeName == "kotlin.Array") {
if (type.arguments.isEmpty()) return NULLABLE_ANY
val itemsType = type.arguments.first().type
if (itemsType.isMarkedNullable) return NULLABLE_ANY
val primitiveType = KotlinTypes.primitiveTypeByName(KotlinPsiUtil.getTypeWithoutTypeParameters(itemsType))
return primitiveType ?: ANY
private companion object {
val LOG = Logger.getInstance(KotlinCollectionsTypeExtractor::class.java)
}
if (typeName == "kotlin.String" || typeName == "kotlin.CharSequence") return KotlinTypes.CHAR
override fun extractItemsType(type: KotlinType?): GenericType {
if (type == null) return NULLABLE_ANY
val primitiveArray = KotlinTypes.primitiveArrayByName(typeName)
if (primitiveArray != null) return primitiveArray.elementType
return tryToFindElementType(type) ?: defaultType(type)
}
return type.supertypes().asSequence()
.map(this::tryToFindElementType)
.firstOrNull()
}
override fun getResultType(type: KotlinType): GenericType {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return KotlinTypes.primitiveTypeByName(typeName) ?: KotlinTypes.primitiveArrayByName(typeName) ?: getAny(type)
}
private fun defaultType(type: KotlinType): GenericType {
LOG.warn("Could not find type of items for type ${KotlinPsiUtil.getTypeName(type)}")
return getAny(type)
}
private fun getAny(type: KotlinType): GenericType = if (type.isMarkedNullable) NULLABLE_ANY else ANY
private fun tryToFindElementType(type: KotlinType): GenericType? {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
if (typeName == "kotlin.collections.Iterable" || typeName == "kotlin.Array") {
if (type.arguments.isEmpty()) return NULLABLE_ANY
val itemsType = type.arguments.first().type
if (itemsType.isMarkedNullable) return NULLABLE_ANY
val primitiveType = KotlinTypes.primitiveTypeByName(KotlinPsiUtil.getTypeWithoutTypeParameters(itemsType))
return primitiveType ?: ANY
}
if (typeName == "kotlin.String" || typeName == "kotlin.CharSequence") return KotlinTypes.CHAR
val primitiveArray = KotlinTypes.primitiveArrayByName(typeName)
if (primitiveArray != null) return primitiveArray.elementType
return type.supertypes().asSequence()
.map(this::tryToFindElementType)
.firstOrNull()
}
private fun defaultType(type: KotlinType): GenericType {
LOG.warn("Could not find type of items for type ${KotlinPsiUtil.getTypeName(type)}")
return getAny(type)
}
private fun getAny(type: KotlinType): GenericType = if (type.isMarkedNullable) NULLABLE_ANY else ANY
}
@@ -13,81 +13,81 @@ import org.jetbrains.kotlin.psi.*
* @author Vitaliy.Bibaev
*/
abstract class KotlinChainBuilderBase(private val transformer: ChainTransformer<KtCallExpression>) : StreamChainBuilder {
protected abstract val existenceChecker: ExistenceChecker
protected abstract val existenceChecker: ExistenceChecker
override fun isChainExists(startElement: PsiElement): Boolean {
val start = if (startElement is PsiWhiteSpace) PsiUtil.ignoreWhiteSpaces(startElement) else startElement
var element = getLatestElementInScope(start)
existenceChecker.reset()
while (element != null && !existenceChecker.isFound()) {
existenceChecker.reset()
element.accept(existenceChecker)
element = toUpperLevel(element)
override fun isChainExists(startElement: PsiElement): Boolean {
val start = if (startElement is PsiWhiteSpace) PsiUtil.ignoreWhiteSpaces(startElement) else startElement
var element = getLatestElementInScope(start)
existenceChecker.reset()
while (element != null && !existenceChecker.isFound()) {
existenceChecker.reset()
element.accept(existenceChecker)
element = toUpperLevel(element)
}
return existenceChecker.isFound()
}
return existenceChecker.isFound()
}
override fun build(startElement: PsiElement): List<StreamChain> {
val visitor = createChainsBuilder()
val start = if (startElement is PsiWhiteSpace) PsiUtil.ignoreWhiteSpaces(startElement) else startElement
var element = getLatestElementInScope(start)
while (element != null) {
element.accept(visitor)
element = toUpperLevel(element)
}
override fun build(startElement: PsiElement): List<StreamChain> {
val visitor = createChainsBuilder()
val start = if (startElement is PsiWhiteSpace) PsiUtil.ignoreWhiteSpaces(startElement) else startElement
var element = getLatestElementInScope(start)
while (element != null) {
element.accept(visitor)
element = toUpperLevel(element)
return visitor.chains().map { transformer.transform(it, startElement) }
}
return visitor.chains().map { transformer.transform(it, startElement) }
}
private fun toUpperLevel(element: PsiElement): PsiElement? {
var current = element.parent
private fun toUpperLevel(element: PsiElement): PsiElement? {
var current = element.parent
while (current != null && !(current is KtLambdaExpression || current is KtAnonymousInitializer || current is KtObjectDeclaration)) {
current = current.parent
}
while (current != null && !(current is KtLambdaExpression || current is KtAnonymousInitializer || current is KtObjectDeclaration)) {
current = current.parent
return getLatestElementInScope(current)
}
return getLatestElementInScope(current)
}
protected abstract fun createChainsBuilder(): ChainBuilder
protected abstract fun createChainsBuilder(): ChainBuilder
private fun getLatestElementInScope(element: PsiElement?): PsiElement? {
var current = element
while (current != null) {
if (current is KtNamedFunction && current.hasInitializer()) {
break
}
private fun getLatestElementInScope(element: PsiElement?): PsiElement? {
var current = element
while (current != null) {
if (current is KtNamedFunction && current.hasInitializer()) {
break
}
val parent = current.parent
if (parent is KtBlockExpression || parent is KtLambdaExpression) {
break
}
val parent = current.parent
if (parent is KtBlockExpression || parent is KtLambdaExpression) {
break
}
current = parent
current = parent
}
return current
}
return current
}
protected abstract class ExistenceChecker : MyTreeVisitor() {
private var myIsFound: Boolean = false
fun isFound(): Boolean = myIsFound
fun reset() = setFound(false)
protected fun fireElementFound() = setFound(true)
protected abstract class ExistenceChecker : MyTreeVisitor() {
private var myIsFound: Boolean = false
fun isFound(): Boolean = myIsFound
fun reset() = setFound(false)
protected fun fireElementFound() = setFound(true)
private fun setFound(value: Boolean) {
myIsFound = value
private fun setFound(value: Boolean) {
myIsFound = value
}
}
}
protected abstract class ChainBuilder : MyTreeVisitor() {
abstract fun chains(): List<List<KtCallExpression>>
}
protected abstract class ChainBuilder : MyTreeVisitor() {
abstract fun chains(): List<List<KtCallExpression>>
}
protected abstract class MyTreeVisitor : KtTreeVisitorVoid() {
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {}
override fun visitBlockExpression(expression: KtBlockExpression) {}
}
protected abstract class MyTreeVisitor : KtTreeVisitorVoid() {
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {}
override fun visitBlockExpression(expression: KtBlockExpression) {}
}
}
@@ -25,45 +25,51 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
* @author Vitaliy.Bibaev
*/
class KotlinChainTransformerImpl(private val typeExtractor: CallTypeExtractor) : ChainTransformer<KtCallExpression> {
override fun transform(callChain: List<KtCallExpression>, context: PsiElement): StreamChain {
val intermediateCalls = mutableListOf<IntermediateStreamCall>()
for (call in callChain.subList(0, callChain.size - 1)) {
val (typeBefore, typeAfter) = typeExtractor.extractIntermediateCallTypes(call)
intermediateCalls += IntermediateStreamCallImpl(call.callName(),
call.valueArguments.map { createCallArgument(call, it) }, typeBefore, typeAfter, call.textRange)
override fun transform(callChain: List<KtCallExpression>, context: PsiElement): StreamChain {
val intermediateCalls = mutableListOf<IntermediateStreamCall>()
for (call in callChain.subList(0, callChain.size - 1)) {
val (typeBefore, typeAfter) = typeExtractor.extractIntermediateCallTypes(call)
intermediateCalls += IntermediateStreamCallImpl(call.callName(),
call.valueArguments.map { createCallArgument(call, it) },
typeBefore,
typeAfter,
call.textRange
)
}
val terminationsPsiCall = callChain.last()
val (typeBeforeTerminator, resultType) = typeExtractor.extractTerminalCallTypes(terminationsPsiCall)
val terminationCall = TerminatorStreamCallImpl(
terminationsPsiCall.callName(),
terminationsPsiCall.valueArguments.map { createCallArgument(terminationsPsiCall, it) },
typeBeforeTerminator, resultType, terminationsPsiCall.textRange
)
val typeAfterQualifier =
if (intermediateCalls.isEmpty()) typeBeforeTerminator else intermediateCalls.first().typeBefore
val qualifier = createQualifier(callChain.first(), typeAfterQualifier)
return StreamChainImpl(qualifier, intermediateCalls, terminationCall, context)
}
val terminationsPsiCall = callChain.last()
val (typeBeforeTerminator, resultType) = typeExtractor.extractTerminalCallTypes(terminationsPsiCall)
val terminationCall = TerminatorStreamCallImpl(terminationsPsiCall.callName(),
terminationsPsiCall.valueArguments.map { createCallArgument(terminationsPsiCall, it) },
typeBeforeTerminator, resultType, terminationsPsiCall.textRange)
private fun createCallArgument(callExpression: KtCallExpression, arg: KtValueArgument): CallArgument {
fun KtValueArgument.toCallArgument(): CallArgument {
val argExpression = getArgumentExpression()!!
return CallArgumentImpl(KotlinPsiUtil.getTypeName(argExpression.resolveType()), this.text)
}
val typeAfterQualifier =
if (intermediateCalls.isEmpty()) typeBeforeTerminator else intermediateCalls.first().typeBefore
val qualifier = createQualifier(callChain.first(), typeAfterQualifier)
return StreamChainImpl(qualifier, intermediateCalls, terminationCall, context)
}
private fun createCallArgument(callExpression: KtCallExpression, arg: KtValueArgument): CallArgument {
fun KtValueArgument.toCallArgument(): CallArgument {
val argExpression = getArgumentExpression()!!
return CallArgumentImpl(KotlinPsiUtil.getTypeName(argExpression.resolveType()), this.text)
val bindingContext = callExpression.getResolutionFacade().analyzeWithAllCompilerChecks(listOf(callExpression)).bindingContext
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return arg.toCallArgument()
val parameter = resolvedCall.getParameterForArgument(arg) ?: return arg.toCallArgument()
return CallArgumentImpl(KotlinPsiUtil.getTypeName(parameter.type), arg.text)
}
val bindingContext = callExpression.getResolutionFacade().analyzeWithAllCompilerChecks(listOf(callExpression)).bindingContext
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return arg.toCallArgument()
val parameter = resolvedCall.getParameterForArgument(arg) ?: return arg.toCallArgument()
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
private fun createQualifier(expression: PsiElement, typeAfter: GenericType): QualifierExpression {
val parent = expression.parent as? KtDotQualifiedExpression
?: return QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfter)
val receiver = parent.receiverExpression
return QualifierExpressionImpl(receiver.text, receiver.textRange, typeAfter)
}
return QualifierExpressionImpl(receiver.text, receiver.textRange, typeAfter)
}
}
@@ -1,11 +1,11 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.impl
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
import org.jetbrains.kotlin.idea.debugger.sequence.psi.StreamCallChecker
import org.jetbrains.kotlin.idea.debugger.sequence.psi.receiverType
import org.jetbrains.kotlin.idea.debugger.sequence.psi.resolveType
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.types.KotlinType
@@ -13,27 +13,29 @@ import org.jetbrains.kotlin.types.KotlinType
* @author Vitaliy.Bibaev
*/
class PackageBasedCallChecker(private val supportedPackage: String) : StreamCallChecker {
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
return checkReceiverSupported(expression) && checkResultSupported(expression, true)
}
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
return checkReceiverSupported(expression) && checkResultSupported(expression, true)
}
override fun isTerminationCall(expression: KtCallExpression): Boolean {
return checkReceiverSupported(expression) && checkResultSupported(expression, false)
}
override fun isTerminationCall(expression: KtCallExpression): Boolean {
return checkReceiverSupported(expression) && checkResultSupported(expression, false)
}
private fun checkResultSupported(expression: KtCallExpression,
shouldSupportResult: Boolean): Boolean {
val resultType = expression.resolveType()
return shouldSupportResult == isSupportedType(resultType)
}
private fun checkResultSupported(
expression: KtCallExpression,
shouldSupportResult: Boolean
): Boolean {
val resultType = expression.resolveType()
return shouldSupportResult == isSupportedType(resultType)
}
private fun checkReceiverSupported(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType()
return receiverType != null && isSupportedType(receiverType)
}
private fun checkReceiverSupported(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType()
return receiverType != null && isSupportedType(receiverType)
}
private fun isSupportedType(type: KotlinType): Boolean {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return StringUtil.getPackageName(typeName).startsWith(supportedPackage)
}
private fun isSupportedType(type: KotlinType): Boolean {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return StringUtil.getPackageName(typeName).startsWith(supportedPackage)
}
}
@@ -1,74 +1,74 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.impl
import com.intellij.debugger.streams.psi.ChainTransformer
import org.jetbrains.kotlin.idea.debugger.sequence.psi.StreamCallChecker
import org.jetbrains.kotlin.idea.debugger.sequence.psi.previousCall
import com.intellij.debugger.streams.psi.ChainTransformer
import org.jetbrains.kotlin.psi.KtCallExpression
import java.util.*
/**
* @author Vitaliy.Bibaev
*/
open class TerminatedChainBuilder(transformer: ChainTransformer<KtCallExpression>,
private val callChecker: StreamCallChecker
)
: KotlinChainBuilderBase(transformer) {
override val existenceChecker: ExistenceChecker = MyExistenceChecker()
open class TerminatedChainBuilder(
transformer: ChainTransformer<KtCallExpression>,
private val callChecker: StreamCallChecker
) : KotlinChainBuilderBase(transformer) {
override val existenceChecker: ExistenceChecker = MyExistenceChecker()
override fun createChainsBuilder(): ChainBuilder = MyBuilderVisitor()
override fun createChainsBuilder(): ChainBuilder = MyBuilderVisitor()
private inner class MyExistenceChecker : ExistenceChecker() {
override fun visitCallExpression(expression: KtCallExpression) {
if (callChecker.isTerminationCall(expression)) {
fireElementFound()
} else {
super.visitCallExpression(expression)
}
}
}
private inner class MyBuilderVisitor : ChainBuilder() {
private val myTerminationCalls = mutableSetOf<KtCallExpression>()
private val myPreviousCalls = mutableMapOf<KtCallExpression, KtCallExpression>()
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
if (!myPreviousCalls.containsKey(expression) && callChecker.isStreamCall(expression)) {
updateCallTree(expression)
}
private inner class MyExistenceChecker : ExistenceChecker() {
override fun visitCallExpression(expression: KtCallExpression) {
if (callChecker.isTerminationCall(expression)) {
fireElementFound()
} else {
super.visitCallExpression(expression)
}
}
}
private fun updateCallTree(expression: KtCallExpression) {
if (callChecker.isTerminationCall(expression)) {
myTerminationCalls.add(expression)
}
private inner class MyBuilderVisitor : ChainBuilder() {
private val myTerminationCalls = mutableSetOf<KtCallExpression>()
private val myPreviousCalls = mutableMapOf<KtCallExpression, KtCallExpression>()
val parentCall = expression.previousCall()
if (parentCall is KtCallExpression && callChecker.isStreamCall(parentCall)) {
myPreviousCalls.put(expression, parentCall)
updateCallTree(parentCall)
}
}
override fun chains(): List<List<KtCallExpression>> {
val chains = ArrayList<List<KtCallExpression>>()
for (terminationCall in myTerminationCalls) {
val chain = ArrayList<KtCallExpression>()
var current: KtCallExpression? = terminationCall
while (current != null) {
if (!callChecker.isStreamCall(current)) {
break
}
chain.add(current)
current = myPreviousCalls[current]
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
if (!myPreviousCalls.containsKey(expression) && callChecker.isStreamCall(expression)) {
updateCallTree(expression)
}
}
Collections.reverse(chain)
chains.add(chain)
}
private fun updateCallTree(expression: KtCallExpression) {
if (callChecker.isTerminationCall(expression)) {
myTerminationCalls.add(expression)
}
return chains
val parentCall = expression.previousCall()
if (parentCall is KtCallExpression && callChecker.isStreamCall(parentCall)) {
myPreviousCalls.put(expression, parentCall)
updateCallTree(parentCall)
}
}
override fun chains(): List<List<KtCallExpression>> {
val chains = ArrayList<List<KtCallExpression>>()
for (terminationCall in myTerminationCalls) {
val chain = ArrayList<KtCallExpression>()
var current: KtCallExpression? = terminationCall
while (current != null) {
if (!callChecker.isStreamCall(current)) {
break
}
chain.add(current)
current = myPreviousCalls[current]
}
Collections.reverse(chain)
chains.add(chain)
}
return chains
}
}
}
}
@@ -1,12 +1,12 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.java
import org.jetbrains.kotlin.idea.debugger.sequence.psi.CallTypeExtractor
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import com.intellij.debugger.streams.trace.impl.handler.type.ClassTypeImpl
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import com.intellij.psi.CommonClassNames
import org.jetbrains.kotlin.idea.debugger.sequence.psi.CallTypeExtractor
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
@@ -14,19 +14,19 @@ import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
* @author Vitaliy.Bibaev
*/
class JavaStreamChainTypeExtractor : CallTypeExtractor.Base() {
override fun extractItemsType(type: KotlinType?): GenericType {
if (type == null) {
return KotlinTypes.NULLABLE_ANY
override fun extractItemsType(type: KotlinType?): GenericType {
if (type == null) {
return KotlinTypes.NULLABLE_ANY
}
return when (KotlinPsiUtil.getTypeWithoutTypeParameters(type)) {
CommonClassNames.JAVA_UTIL_STREAM_INT_STREAM -> KotlinTypes.INT
CommonClassNames.JAVA_UTIL_STREAM_DOUBLE_STREAM -> KotlinTypes.DOUBLE
CommonClassNames.JAVA_UTIL_STREAM_LONG_STREAM -> KotlinTypes.LONG
CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM -> KotlinTypes.NULLABLE_ANY
else -> extractItemsType(type.getImmediateSuperclassNotAny())
}
}
return when (KotlinPsiUtil.getTypeWithoutTypeParameters(type)) {
CommonClassNames.JAVA_UTIL_STREAM_INT_STREAM -> KotlinTypes.INT
CommonClassNames.JAVA_UTIL_STREAM_DOUBLE_STREAM -> KotlinTypes.DOUBLE
CommonClassNames.JAVA_UTIL_STREAM_LONG_STREAM -> KotlinTypes.LONG
CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM -> KotlinTypes.NULLABLE_ANY
else -> extractItemsType(type.getImmediateSuperclassNotAny())
}
}
override fun getResultType(type: KotlinType): GenericType = ClassTypeImpl(KotlinPsiUtil.getTypeName(type))
override fun getResultType(type: KotlinType): GenericType = ClassTypeImpl(KotlinPsiUtil.getTypeName(type))
}
@@ -13,19 +13,19 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
* @author Vitaliy.Bibaev
*/
class SequenceCallChecker : StreamCallChecker {
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType() ?: return false
return isSequenceInheritor(receiverType) && isSequenceInheritor(expression.resolveType())
}
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType() ?: return false
return isSequenceInheritor(receiverType) && isSequenceInheritor(expression.resolveType())
}
override fun isTerminationCall(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType() ?: return false
return isSequenceInheritor(receiverType) && !isSequenceInheritor(expression.resolveType())
}
override fun isTerminationCall(expression: KtCallExpression): Boolean {
val receiverType = expression.receiverType() ?: return false
return isSequenceInheritor(receiverType) && !isSequenceInheritor(expression.resolveType())
}
private fun isSequenceInheritor(type: KotlinType): Boolean =
isSequenceType(type) || type.supertypes().any(this::isSequenceType)
private fun isSequenceInheritor(type: KotlinType): Boolean =
isSequenceType(type) || type.supertypes().any(this::isSequenceType)
private fun isSequenceType(type: KotlinType): Boolean =
"kotlin.sequences.Sequence" == KotlinPsiUtil.getTypeWithoutTypeParameters(type)
private fun isSequenceType(type: KotlinType): Boolean =
"kotlin.sequences.Sequence" == KotlinPsiUtil.getTypeWithoutTypeParameters(type)
}
@@ -1,12 +1,12 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.psi.CallTypeExtractor
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import com.intellij.debugger.streams.trace.impl.handler.type.ClassTypeImpl
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.idea.debugger.sequence.psi.CallTypeExtractor
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.supertypes
@@ -14,40 +14,40 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
* @author Vitaliy.Bibaev
*/
class SequenceTypeExtractor : CallTypeExtractor.Base() {
private companion object {
val LOG = Logger.getInstance(SequenceTypeExtractor::class.java)
}
override fun extractItemsType(type: KotlinType?): GenericType {
if (type == null) return KotlinTypes.NULLABLE_ANY
return tryToFindElementType(type) ?: defaultType(type)
}
override fun getResultType(type: KotlinType): GenericType {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return KotlinTypes.primitiveTypeByName(typeName)
?: KotlinTypes.primitiveArrayByName(typeName)
?: ClassTypeImpl(KotlinPsiUtil.getTypeName(type))
}
private fun tryToFindElementType(type: KotlinType): GenericType? {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
if (typeName == "kotlin.sequences.Sequence") {
if (type.arguments.isEmpty()) return KotlinTypes.NULLABLE_ANY
val itemsType = type.arguments.single().type
if (itemsType.isMarkedNullable) return KotlinTypes.NULLABLE_ANY
val primitiveType = KotlinTypes.primitiveTypeByName(KotlinPsiUtil.getTypeWithoutTypeParameters(itemsType))
return primitiveType ?: KotlinTypes.ANY
private companion object {
val LOG = Logger.getInstance(SequenceTypeExtractor::class.java)
}
return type.supertypes().asSequence()
.map(this::tryToFindElementType)
.firstOrNull()
}
override fun extractItemsType(type: KotlinType?): GenericType {
if (type == null) return KotlinTypes.NULLABLE_ANY
private fun defaultType(type: KotlinType): GenericType {
LOG.warn("Could not find type of items for type ${KotlinPsiUtil.getTypeName(type)}")
return if (type.isMarkedNullable) KotlinTypes.NULLABLE_ANY else KotlinTypes.ANY
}
return tryToFindElementType(type) ?: defaultType(type)
}
override fun getResultType(type: KotlinType): GenericType {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return KotlinTypes.primitiveTypeByName(typeName)
?: KotlinTypes.primitiveArrayByName(typeName)
?: ClassTypeImpl(KotlinPsiUtil.getTypeName(type))
}
private fun tryToFindElementType(type: KotlinType): GenericType? {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
if (typeName == "kotlin.sequences.Sequence") {
if (type.arguments.isEmpty()) return KotlinTypes.NULLABLE_ANY
val itemsType = type.arguments.single().type
if (itemsType.isMarkedNullable) return KotlinTypes.NULLABLE_ANY
val primitiveType = KotlinTypes.primitiveTypeByName(KotlinPsiUtil.getTypeWithoutTypeParameters(itemsType))
return primitiveType ?: KotlinTypes.ANY
}
return type.supertypes().asSequence()
.map(this::tryToFindElementType)
.firstOrNull()
}
private fun defaultType(type: KotlinType): GenericType {
LOG.warn("Could not find type of items for type ${KotlinPsiUtil.getTypeName(type)}")
return if (type.isMarkedNullable) KotlinTypes.NULLABLE_ANY else KotlinTypes.ANY
}
}
@@ -9,31 +9,31 @@ import com.intellij.debugger.streams.trace.TraceInfo
* @author Vitaliy.Bibaev
*/
class ChunkedResolver : ValuesOrderResolver {
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
val beforeIndex = info.valuesOrderBefore
val afterIndex = info.valuesOrderAfter
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
val beforeIndex = info.valuesOrderBefore
val afterIndex = info.valuesOrderAfter
val invertedOrder = mutableMapOf<Int, MutableList<Int>>()
val beforeTimes = beforeIndex.keys.sorted().toTypedArray()
val afterTimes = afterIndex.keys.sorted().toTypedArray()
val invertedOrder = mutableMapOf<Int, MutableList<Int>>()
val beforeTimes = beforeIndex.keys.sorted().toTypedArray()
val afterTimes = afterIndex.keys.sorted().toTypedArray()
var beforeIx = 0
for (afterTime in afterTimes) {
while (beforeIx < beforeTimes.size && beforeTimes[beforeIx] < afterTime) {
invertedOrder.computeIfAbsent(afterTime, { _ -> mutableListOf() }).add(beforeTimes[beforeIx])
beforeIx += 1
}
var beforeIx = 0
for (afterTime in afterTimes) {
while (beforeIx < beforeTimes.size && beforeTimes[beforeIx] < afterTime) {
invertedOrder.computeIfAbsent(afterTime, { _ -> mutableListOf() }).add(beforeTimes[beforeIx])
beforeIx += 1
}
}
val direct = mutableMapOf<TraceElement, List<TraceElement>>()
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
for ((timeAfter, elementAfter) in afterIndex) {
val before: List<Int> = invertedOrder[timeAfter] ?: emptyList()
val beforeElements = before.map { beforeIndex[it]!! }
beforeElements.forEach { direct[it] = listOf(elementAfter) }
reverse[elementAfter] = beforeElements
}
return ValuesOrderResolver.Result.of(direct, reverse)
}
val direct = mutableMapOf<TraceElement, List<TraceElement>>()
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
for ((timeAfter, elementAfter) in afterIndex) {
val before: List<Int> = invertedOrder[timeAfter] ?: emptyList()
val beforeElements = before.map { beforeIndex[it]!! }
beforeElements.forEach { direct[it] = listOf(elementAfter) }
reverse[elementAfter] = beforeElements
}
return ValuesOrderResolver.Result.of(direct, reverse)
}
}
@@ -9,32 +9,32 @@ import com.intellij.debugger.streams.trace.TraceInfo
* @author Vitaliy.Bibaev
*/
class FilteredMapResolver : ValuesOrderResolver {
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
val before = info.valuesOrderBefore
val after = info.valuesOrderAfter
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
val before = info.valuesOrderBefore
val after = info.valuesOrderAfter
val invertedOrder = mutableMapOf<Int, Int>()
val beforeTimes = before.keys.sorted().toIntArray()
val afterTimes = after.keys.sorted().toIntArray()
var beforeIndex = 0
for (afterTime in afterTimes) {
while (beforeIndex < beforeTimes.size && afterTime > beforeTimes[beforeIndex]) beforeIndex += 1
val beforeTime = beforeTimes[beforeIndex - 1]
if (beforeTime < afterTime) {
invertedOrder[afterTime] = beforeTime
}
val invertedOrder = mutableMapOf<Int, Int>()
val beforeTimes = before.keys.sorted().toIntArray()
val afterTimes = after.keys.sorted().toIntArray()
var beforeIndex = 0
for (afterTime in afterTimes) {
while (beforeIndex < beforeTimes.size && afterTime > beforeTimes[beforeIndex]) beforeIndex += 1
val beforeTime = beforeTimes[beforeIndex - 1]
if (beforeTime < afterTime) {
invertedOrder[afterTime] = beforeTime
}
}
val direct = mutableMapOf<TraceElement, List<TraceElement>>()
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
for ((afterTime, beforeTime) in invertedOrder) {
val beforeElement = before.getValue(beforeTime)
val afterElement = after.getValue(afterTime)
direct[beforeElement] = listOf(afterElement)
reverse[afterElement] = listOf(beforeElement)
}
return ValuesOrderResolver.Result.of(direct, reverse)
}
val direct = mutableMapOf<TraceElement, List<TraceElement>>()
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
for ((afterTime, beforeTime) in invertedOrder) {
val beforeElement = before.getValue(beforeTime)
val afterElement = after.getValue(afterTime)
direct[beforeElement] = listOf(afterElement)
reverse[afterElement] = listOf(beforeElement)
}
return ValuesOrderResolver.Result.of(direct, reverse)
}
}
@@ -9,49 +9,49 @@ import com.intellij.debugger.streams.trace.TraceInfo
* @author Vitaliy.Bibaev
*/
class WindowedResolver : ValuesOrderResolver {
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
val indexBefore = info.valuesOrderBefore
val indexAfter = info.valuesOrderAfter
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
val indexBefore = info.valuesOrderBefore
val indexAfter = info.valuesOrderAfter
val timesBefore = indexBefore.keys.sorted().toIntArray()
val timesAfter = indexAfter.keys.sorted().toIntArray()
val timesBefore = indexBefore.keys.sorted().toIntArray()
val timesAfter = indexAfter.keys.sorted().toIntArray()
if (timesAfter.isEmpty()) return emptyTransitions(indexBefore)
if (timesAfter.isEmpty()) return emptyTransitions(indexBefore)
val direct = mutableMapOf<TraceElement, MutableList<TraceElement>>()
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
val direct = mutableMapOf<TraceElement, MutableList<TraceElement>>()
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
var windowStartIndex = 0
var windowEndIndex = calcWindowSize(timesBefore, timesAfter)
for (timeAfter in timesAfter) {
if (windowEndIndex == timesAfter.size) {
windowStartIndex += 1
} else {
while (windowEndIndex < timesBefore.size && timesBefore[windowEndIndex] < timeAfter) {
windowStartIndex += 1
windowEndIndex += 1
var windowStartIndex = 0
var windowEndIndex = calcWindowSize(timesBefore, timesAfter)
for (timeAfter in timesAfter) {
if (windowEndIndex == timesAfter.size) {
windowStartIndex += 1
} else {
while (windowEndIndex < timesBefore.size && timesBefore[windowEndIndex] < timeAfter) {
windowStartIndex += 1
windowEndIndex += 1
}
}
val window = (windowStartIndex until windowEndIndex).asSequence()
.map { indexBefore[timesBefore[it]]!! }
.toList()
val mappedElement = indexAfter[timeAfter]!!
window.forEach { direct.computeIfAbsent(it, { mutableListOf() }).add(mappedElement) }
reverse[mappedElement] = window
}
}
val window = (windowStartIndex until windowEndIndex).asSequence()
.map { indexBefore[timesBefore[it]]!! }
.toList()
val mappedElement = indexAfter[timeAfter]!!
window.forEach { direct.computeIfAbsent(it, { mutableListOf() }).add(mappedElement) }
reverse[mappedElement] = window
return ValuesOrderResolver.Result.of(direct, reverse)
}
return ValuesOrderResolver.Result.of(direct, reverse)
}
private fun calcWindowSize(before: IntArray, after: IntArray): Int {
var size = 0
while (size < before.size && before[size] < after[0]) size += 1
return size
}
private fun calcWindowSize(before: IntArray, after: IntArray): Int {
var size = 0
while (size < before.size && before[size] < after[0]) size += 1
return size
}
private fun emptyTransitions(indexBefore: MutableMap<Int, TraceElement>): ValuesOrderResolver.Result {
val direct = indexBefore.asSequence().sortedBy { it.key }.associate { it.value to emptyList<TraceElement>() }
return ValuesOrderResolver.Result.of(direct, emptyMap())
}
private fun emptyTransitions(indexBefore: MutableMap<Int, TraceElement>): ValuesOrderResolver.Result {
val direct = indexBefore.asSequence().sortedBy { it.key }.associate { it.value to emptyList<TraceElement>() }
return ValuesOrderResolver.Result.of(direct, emptyMap())
}
}
@@ -9,6 +9,6 @@ import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
* @author Vitaliy.Bibaev
*/
class JavaPeekCallFactory : PeekCallFactory {
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
PeekCall(lambda, elementsType)
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
PeekCall(lambda, elementsType)
}
@@ -11,12 +11,11 @@ import com.intellij.debugger.streams.trace.impl.handler.type.ArrayType
/**
* @author Vitaliy.Bibaev
*/
class KotlinArrayVariable(override val type: ArrayType, override val name: String)
: VariableImpl(type, name), ArrayVariable {
override fun get(index: Expression): Expression = TextExpression("$name[${index.toCode()}]!!")
class KotlinArrayVariable(override val type: ArrayType, override val name: String) : VariableImpl(type, name), ArrayVariable {
override fun get(index: Expression): Expression = TextExpression("$name[${index.toCode()}]!!")
override fun set(index: Expression, value: Expression): Expression = TextExpression("$name[${index.toCode()}] = ${value.toCode()}")
override fun set(index: Expression, value: Expression): Expression = TextExpression("$name[${index.toCode()}] = ${value.toCode()}")
override fun defaultDeclaration(size: Expression): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.sizedDeclaration(size.toCode()))
override fun defaultDeclaration(size: Expression): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.sizedDeclaration(size.toCode()))
}
@@ -9,5 +9,5 @@ import com.intellij.debugger.streams.trace.dsl.impl.AssignmentStatement
* @author Vitaliy.Bibaev
*/
class KotlinAssignmentStatement(override val variable: Variable, override val expression: Expression) : AssignmentStatement {
override fun toCode(indent: Int): String = "${variable.toCode()} = ${expression.toCode()}".withIndent(indent)
override fun toCode(indent: Int): String = "${variable.toCode()} = ${expression.toCode()}".withIndent(indent)
}
@@ -9,5 +9,5 @@ import com.intellij.debugger.streams.trace.dsl.impl.LineSeparatedCodeBlock
* @author Vitaliy.Bibaev
*/
open class KotlinCodeBlock(statementFactory: StatementFactory) : LineSeparatedCodeBlock(statementFactory) {
override fun doReturn(expression: Expression) = addStatement(expression)
override fun doReturn(expression: Expression) = addStatement(expression)
}
@@ -1,14 +1,14 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.OnEachCall
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.OnEachCall
/**
* @author Vitaliy.Bibaev
*/
class KotlinCollectionsPeekCallFactory : PeekCallFactory {
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
OnEachCall(elementsType, lambda)
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
OnEachCall(elementsType, lambda)
}
@@ -9,11 +9,13 @@ import com.intellij.debugger.streams.trace.dsl.Variable
/**
* @author Vitaliy.Bibaev
*/
class KotlinForEachLoop(private val iterateVariable: Variable,
private val collection: Expression,
private val loopBody: ForLoopBody) : Convertable {
override fun toCode(indent: Int): String =
"for (${iterateVariable.name} in ${collection.toCode()}) {\n".withIndent(indent) +
loopBody.toCode(indent + 1) +
"}".withIndent(indent)
class KotlinForEachLoop(
private val iterateVariable: Variable,
private val collection: Expression,
private val loopBody: ForLoopBody
) : Convertable {
override fun toCode(indent: Int): String =
"for (${iterateVariable.name} in ${collection.toCode()}) {\n".withIndent(indent) +
loopBody.toCode(indent + 1) +
"}".withIndent(indent)
}
@@ -9,14 +9,16 @@ import com.intellij.debugger.streams.trace.dsl.VariableDeclaration
/**
* @author Vitaliy.Bibaev
*/
class KotlinForLoop(private val initialization: VariableDeclaration,
private val condition: Expression,
private val afterThought: Expression,
private val loopBody: ForLoopBody) : Convertable {
override fun toCode(indent: Int): String =
initialization.toCode(indent) + "\n" +
"while (${condition.toCode()}) {\n".withIndent(indent) +
loopBody.toCode(indent + 1) +
afterThought.toCode(indent + 1) + "\n" +
"}".withIndent(indent)
class KotlinForLoop(
private val initialization: VariableDeclaration,
private val condition: Expression,
private val afterThought: Expression,
private val loopBody: ForLoopBody
) : Convertable {
override fun toCode(indent: Int): String =
initialization.toCode(indent) + "\n" +
"while (${condition.toCode()}) {\n".withIndent(indent) +
loopBody.toCode(indent + 1) +
afterThought.toCode(indent + 1) + "\n" +
"}".withIndent(indent)
}
@@ -1,21 +1,22 @@
// 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.dsl
package org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl
import com.intellij.debugger.streams.trace.dsl.Expression
import com.intellij.debugger.streams.trace.dsl.ForLoopBody
import com.intellij.debugger.streams.trace.dsl.StatementFactory
import com.intellij.debugger.streams.trace.dsl.Variable
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCodeBlock
/**
* @author Vitaliy.Bibaev
*/
class KotlinForLoopBody(override val loopVariable: Variable,
statementFactory: StatementFactory) : KotlinCodeBlock(statementFactory), ForLoopBody {
private companion object {
val BREAK = TextExpression("break")
}
class KotlinForLoopBody(
override val loopVariable: Variable,
statementFactory: StatementFactory
) : KotlinCodeBlock(statementFactory), ForLoopBody {
private companion object {
val BREAK = TextExpression("break")
}
override fun breakIteration(): Expression = BREAK
override fun breakIteration(): Expression = BREAK
}
@@ -9,19 +9,19 @@ import com.intellij.debugger.streams.trace.dsl.impl.common.IfBranchBase
/**
* @author Vitaliy.Bibaev
*/
class KotlinIfBranch(condition: Expression, thenBlock: CodeBlock, statementFactory: StatementFactory)
: IfBranchBase(condition, thenBlock, statementFactory) {
override fun toCode(indent: Int): String {
val elseBlockVar = elseBlock
val ifThen = "if (${condition.toCode(0)}) {\n".withIndent(indent) +
thenBlock.toCode(indent + 1) +
"}".withIndent(indent)
if (elseBlockVar != null) {
return ifThen + " else { \n" +
elseBlockVar.toCode(indent + 1) +
"}".withIndent(indent)
}
class KotlinIfBranch(condition: Expression, thenBlock: CodeBlock, statementFactory: StatementFactory) :
IfBranchBase(condition, thenBlock, statementFactory) {
override fun toCode(indent: Int): String {
val elseBlockVar = elseBlock
val ifThen = "if (${condition.toCode(0)}) {\n".withIndent(indent) +
thenBlock.toCode(indent + 1) +
"}".withIndent(indent)
if (elseBlockVar != null) {
return ifThen + " else { \n" +
elseBlockVar.toCode(indent + 1) +
"}".withIndent(indent)
}
return ifThen
}
return ifThen
}
}
@@ -10,10 +10,10 @@ import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
* @author Vitaliy.Bibaev
*/
class KotlinLambda(override val variableName: String, override val body: CodeBlock) : Lambda {
override fun call(callName: String, vararg args: Expression): Expression = TextExpression("(${toCode()})").call(callName, *args)
override fun call(callName: String, vararg args: Expression): Expression = TextExpression("(${toCode()})").call(callName, *args)
override fun toCode(indent: Int): String =
"{ $variableName ->\n".withIndent(indent) +
body.toCode(indent + 1) +
"}"
override fun toCode(indent: Int): String =
"{ $variableName ->\n".withIndent(indent) +
body.toCode(indent + 1) +
"}"
}
@@ -4,10 +4,9 @@ package org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl
import com.intellij.debugger.streams.trace.dsl.Expression
import com.intellij.debugger.streams.trace.dsl.LambdaBody
import com.intellij.debugger.streams.trace.dsl.StatementFactory
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCodeBlock
/**
* @author Vitaliy.Bibaev
*/
class KotlinLambdaBody(override val lambdaArg: Expression, statementFactory: StatementFactory)
: KotlinCodeBlock(statementFactory), LambdaBody
class KotlinLambdaBody(override val lambdaArg: Expression, statementFactory: StatementFactory) : KotlinCodeBlock(statementFactory),
LambdaBody
@@ -10,16 +10,15 @@ import com.intellij.debugger.streams.trace.impl.handler.type.ListType
/**
* @author Vitaliy.Bibaev
*/
class KotlinListVariable(override val type: ListType, name: String)
: VariableImpl(type, name), ListVariable {
override fun get(index: Expression): Expression = call("get", index)
override fun set(index: Expression, newValue: Expression): Expression = call("set", index, newValue)
override fun add(element: Expression): Expression = call("add", element)
class KotlinListVariable(override val type: ListType, name: String) : VariableImpl(type, name), ListVariable {
override fun get(index: Expression): Expression = call("get", index)
override fun set(index: Expression, newValue: Expression): Expression = call("set", index, newValue)
override fun add(element: Expression): Expression = call("add", element)
override fun contains(element: Expression): Expression = call("contains", element)
override fun contains(element: Expression): Expression = call("contains", element)
override fun size(): Expression = property("size")
override fun size(): Expression = property("size")
override fun defaultDeclaration(): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.defaultValue)
override fun defaultDeclaration(): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.defaultValue)
}
@@ -1,7 +1,9 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl
import com.intellij.debugger.streams.trace.dsl.*
import com.intellij.debugger.streams.trace.dsl.Expression
import com.intellij.debugger.streams.trace.dsl.Lambda
import com.intellij.debugger.streams.trace.dsl.VariableDeclaration
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
import com.intellij.debugger.streams.trace.dsl.impl.common.MapVariableBase
import com.intellij.debugger.streams.trace.impl.handler.type.MapType
@@ -10,20 +12,20 @@ import com.intellij.debugger.streams.trace.impl.handler.type.MapType
* @author Vitaliy.Bibaev
*/
class KotlinMapVariable(type: MapType, name: String) : MapVariableBase(type, name) {
override fun get(key: Expression): Expression = this.call("getValue", key)
override fun get(key: Expression): Expression = this.call("getValue", key)
override fun set(key: Expression, newValue: Expression): Expression =
TextExpression("${toCode()}[${key.toCode()}] = ${newValue.toCode()}")
override fun set(key: Expression, newValue: Expression): Expression =
TextExpression("${toCode()}[${key.toCode()}] = ${newValue.toCode()}")
override fun contains(key: Expression): Expression = TextExpression("(${key.toCode()} in ${toCode()})")
override fun contains(key: Expression): Expression = TextExpression("(${key.toCode()} in ${toCode()})")
override fun size(): Expression = TextExpression("${toCode()}.size")
override fun size(): Expression = TextExpression("${toCode()}.size")
override fun keys(): Expression = TextExpression("${toCode()}.keys")
override fun keys(): Expression = TextExpression("${toCode()}.keys")
override fun computeIfAbsent(key: Expression, supplier: Lambda): Expression =
TextExpression("${toCode()}.computeIfAbsent(${key.toCode()}, ${supplier.toCode()})")
override fun computeIfAbsent(key: Expression, supplier: Lambda): Expression =
TextExpression("${toCode()}.computeIfAbsent(${key.toCode()}, ${supplier.toCode()})")
override fun defaultDeclaration(isMutable: Boolean): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.defaultValue)
override fun defaultDeclaration(isMutable: Boolean): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.defaultValue)
}
@@ -1,7 +1,6 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl
import com.intellij.debugger.streams.kotlin.trace.dsl.*
import com.intellij.debugger.streams.trace.dsl.*
import com.intellij.debugger.streams.trace.dsl.impl.AssignmentStatement
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
@@ -13,96 +12,99 @@ import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
* @author Vitaliy.Bibaev
*/
class KotlinStatementFactory(private val peekCallFactory: PeekCallFactory) : StatementFactory {
override fun createNewListExpression(elementType: GenericType, vararg args: Expression): Expression =
TextExpression("kotlin.collections.mutableListOf<${elementType.genericTypeName}>(${StatementFactory.commaSeparate(*args)})")
override fun createNewListExpression(elementType: GenericType, vararg args: Expression): Expression =
TextExpression("kotlin.collections.mutableListOf<${elementType.genericTypeName}>(${StatementFactory.commaSeparate(*args)})")
override fun createListVariable(elementType: GenericType, name: String): ListVariable = KotlinListVariable(types.list(elementType), name)
override fun createListVariable(elementType: GenericType, name: String): ListVariable =
KotlinListVariable(types.list(elementType), name)
override fun not(expression: Expression): Expression = TextExpression("!${expression.toCode()}")
override fun not(expression: Expression): Expression = TextExpression("!${expression.toCode()}")
override val types: Types = KotlinTypes
override val types: Types = KotlinTypes
override fun createEmptyCompositeCodeBlock(): CompositeCodeBlock = KotlinCodeBlock(this)
override fun createEmptyCompositeCodeBlock(): CompositeCodeBlock = KotlinCodeBlock(this)
override fun createEmptyCodeBlock(): CodeBlock = KotlinCodeBlock(this)
override fun createEmptyCodeBlock(): CodeBlock = KotlinCodeBlock(this)
override fun createVariableDeclaration(variable: Variable, isMutable: Boolean): VariableDeclaration =
KotlinVariableDeclaration(variable, isMutable)
override fun createVariableDeclaration(variable: Variable, isMutable: Boolean): VariableDeclaration =
KotlinVariableDeclaration(variable, isMutable)
override fun createVariableDeclaration(variable: Variable, init: Expression, isMutable: Boolean): VariableDeclaration =
KotlinVariableDeclaration(variable, isMutable, init.toCode())
override fun createVariableDeclaration(variable: Variable, init: Expression, isMutable: Boolean): VariableDeclaration =
KotlinVariableDeclaration(variable, isMutable, init.toCode())
override fun createEmptyForLoopBody(iterateVariable: Variable): ForLoopBody = KotlinForLoopBody(iterateVariable, this)
override fun createEmptyForLoopBody(iterateVariable: Variable): ForLoopBody = KotlinForLoopBody(iterateVariable, this)
override fun createForEachLoop(iterateVariable: Variable, collection: Expression, loopBody: ForLoopBody): Convertable =
KotlinForEachLoop(iterateVariable, collection, loopBody)
override fun createForEachLoop(iterateVariable: Variable, collection: Expression, loopBody: ForLoopBody): Convertable =
KotlinForEachLoop(iterateVariable, collection, loopBody)
override fun createForLoop(initialization: VariableDeclaration, condition: Expression,
afterThought: Expression, loopBody: ForLoopBody): Convertable =
KotlinForLoop(initialization, condition, afterThought, loopBody)
override fun createForLoop(
initialization: VariableDeclaration, condition: Expression,
afterThought: Expression, loopBody: ForLoopBody
): Convertable =
KotlinForLoop(initialization, condition, afterThought, loopBody)
override fun createEmptyLambdaBody(argName: String): LambdaBody = KotlinLambdaBody(TextExpression(argName), this)
override fun createEmptyLambdaBody(argName: String): LambdaBody = KotlinLambdaBody(TextExpression(argName), this)
override fun createLambda(argName: String, lambdaBody: LambdaBody): Lambda = KotlinLambda(argName, lambdaBody)
override fun createLambda(argName: String, lambdaBody: LambdaBody): Lambda = KotlinLambda(argName, lambdaBody)
override fun createVariable(type: GenericType, name: String): Variable = VariableImpl(type, name)
override fun createVariable(type: GenericType, name: String): Variable = VariableImpl(type, name)
override fun and(left: Expression, right: Expression): Expression = TextExpression("${left.toCode()} && ${right.toCode()}")
override fun and(left: Expression, right: Expression): Expression = TextExpression("${left.toCode()} && ${right.toCode()}")
override fun equals(left: Expression, right: Expression): Expression = TextExpression("${left.toCode()} == ${right.toCode()}")
override fun equals(left: Expression, right: Expression): Expression = TextExpression("${left.toCode()} == ${right.toCode()}")
override fun same(left: Expression, right: Expression): Expression = TextExpression("${left.toCode()} === ${right.toCode()}")
override fun same(left: Expression, right: Expression): Expression = TextExpression("${left.toCode()} === ${right.toCode()}")
override fun createIfBranch(condition: Expression, thenBlock: CodeBlock): IfBranch =
KotlinIfBranch(condition, thenBlock, this)
override fun createIfBranch(condition: Expression, thenBlock: CodeBlock): IfBranch =
KotlinIfBranch(condition, thenBlock, this)
override fun createAssignmentStatement(variable: Variable, expression: Expression): AssignmentStatement =
KotlinAssignmentStatement(variable, expression)
override fun createAssignmentStatement(variable: Variable, expression: Expression): AssignmentStatement =
KotlinAssignmentStatement(variable, expression)
override fun createMapVariable(keyType: GenericType, valueType: GenericType, name: String, linked: Boolean): MapVariable =
KotlinMapVariable(if (linked) types.linkedMap(keyType, valueType) else types.map(keyType, valueType), name)
override fun createMapVariable(keyType: GenericType, valueType: GenericType, name: String, linked: Boolean): MapVariable =
KotlinMapVariable(if (linked) types.linkedMap(keyType, valueType) else types.map(keyType, valueType), name)
override fun createArrayVariable(elementType: GenericType, name: String): ArrayVariable =
KotlinArrayVariable(types.array(elementType), name)
override fun createArrayVariable(elementType: GenericType, name: String): ArrayVariable =
KotlinArrayVariable(types.array(elementType), name)
override fun createScope(codeBlock: CodeBlock): Convertable =
object : Convertable {
override fun toCode(indent: Int): String =
"run {\n".withIndent(indent) +
codeBlock.toCode(indent + 1) +
"}".withIndent(indent)
override fun createScope(codeBlock: CodeBlock): Convertable =
object : Convertable {
override fun toCode(indent: Int): String =
"run {\n".withIndent(indent) +
codeBlock.toCode(indent + 1) +
"}".withIndent(indent)
}
override fun createTryBlock(block: CodeBlock): TryBlock = KotlinTryBlock(block, this)
override fun createTimeVariableDeclaration(): VariableDeclaration =
KotlinVariableDeclaration(createVariable(types.TIME, "time"), false, types.TIME.defaultValue)
override fun currentTimeExpression(): Expression = TextExpression("time.get()")
override fun updateCurrentTimeExpression(): Expression = TextExpression("time.incrementAndGet()")
override fun createNewArrayExpression(elementType: GenericType, vararg args: Expression): Expression {
val arguments = args.joinToString { it.toCode() }
val text = when (elementType) {
types.BOOLEAN -> "kotlin.booleanArrayOf($arguments)"
KotlinTypes.BYTE -> "kotlin.byteArrayOf($arguments)"
KotlinTypes.SHORT -> "kotlin.shortArrayOf($arguments)"
KotlinTypes.CHAR -> "kotlin.charArrayOf($arguments)"
types.INT -> "kotlin.intArrayOf($arguments)"
types.LONG -> "kotlin.longArrayOf($arguments)"
KotlinTypes.FLOAT -> "kotlin.floatArrayOf($arguments)"
types.DOUBLE -> "kotlin.doubleArrayOf($arguments)"
else -> "kotlin.arrayOf<${types.nullable { elementType }.genericTypeName}>($arguments)"
}
return TextExpression(text)
}
override fun createTryBlock(block: CodeBlock): TryBlock = KotlinTryBlock(block, this)
override fun createTimeVariableDeclaration(): VariableDeclaration =
KotlinVariableDeclaration(createVariable(types.TIME, "time"), false, types.TIME.defaultValue)
override fun currentTimeExpression(): Expression = TextExpression("time.get()")
override fun updateCurrentTimeExpression(): Expression = TextExpression("time.incrementAndGet()")
override fun createNewArrayExpression(elementType: GenericType, vararg args: Expression): Expression {
val arguments = args.joinToString { it.toCode() }
val text = when (elementType) {
types.BOOLEAN -> "kotlin.booleanArrayOf($arguments)"
KotlinTypes.BYTE -> "kotlin.byteArrayOf($arguments)"
KotlinTypes.SHORT -> "kotlin.shortArrayOf($arguments)"
KotlinTypes.CHAR -> "kotlin.charArrayOf($arguments)"
types.INT -> "kotlin.intArrayOf($arguments)"
types.LONG -> "kotlin.longArrayOf($arguments)"
KotlinTypes.FLOAT -> "kotlin.floatArrayOf($arguments)"
types.DOUBLE -> "kotlin.doubleArrayOf($arguments)"
else -> "kotlin.arrayOf<${types.nullable { elementType }.genericTypeName}>($arguments)"
}
return TextExpression(text)
}
override fun createNewSizedArray(elementType: GenericType, size: Expression): Expression =
TextExpression(types.array(elementType).sizedDeclaration(size.toCode()))
override fun createNewSizedArray(elementType: GenericType, size: Expression): Expression =
TextExpression(types.array(elementType).sizedDeclaration(size.toCode()))
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
peekCallFactory.createPeekCall(elementsType, lambda)
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
peekCallFactory.createPeekCall(elementsType, lambda)
}
@@ -9,12 +9,12 @@ import com.intellij.debugger.streams.trace.dsl.impl.common.TryBlockBase
* @author Vitaliy.Bibaev
*/
class KotlinTryBlock(private val block: CodeBlock, statementFactory: StatementFactory) : TryBlockBase(statementFactory) {
override fun toCode(indent: Int): String {
val descriptor = myCatchDescriptor ?: error("catch block must be specified")
return "try {\n".withIndent(indent) +
block.toCode(indent + 1) +
"} catch(${descriptor.variable.name} : ${descriptor.variable.type.variableTypeName}) {\n" +
descriptor.block.toCode(indent + 1) +
"}".withIndent(indent)
}
override fun toCode(indent: Int): String {
val descriptor = myCatchDescriptor ?: error("catch block must be specified")
return "try {\n".withIndent(indent) +
block.toCode(indent + 1) +
"} catch(${descriptor.variable.name} : ${descriptor.variable.type.variableTypeName}) {\n" +
descriptor.block.toCode(indent + 1) +
"}".withIndent(indent)
}
}
@@ -8,76 +8,84 @@ import com.intellij.debugger.streams.trace.impl.handler.type.*
* @author Vitaliy.Bibaev
*/
object KotlinTypes : Types {
override val ANY: GenericType = ClassTypeImpl("kotlin.Any", "kotlin.Any()")
override val ANY: GenericType = ClassTypeImpl("kotlin.Any", "kotlin.Any()")
override val BOOLEAN: GenericType = ClassTypeImpl("kotlin.Boolean", "false")
val BYTE: GenericType = ClassTypeImpl("kotlin.Byte", "0")
val SHORT: GenericType = ClassTypeImpl("kotlin.Short", "0")
val CHAR: GenericType = ClassTypeImpl("kotlin.Char", "0.toChar()")
override val INT: GenericType = ClassTypeImpl("kotlin.Int", "0")
override val LONG: GenericType = ClassTypeImpl("kotlin.Long", "0L")
val FLOAT: GenericType = ClassTypeImpl("kotlin.Float", "0.0f")
override val DOUBLE: GenericType = ClassTypeImpl("kotlin.Double", "0.0")
override val STRING: GenericType = ClassTypeImpl("kotlin.String", "\"\"")
override val EXCEPTION: GenericType = ClassTypeImpl("kotlin.Throwable", "kotlin.Throwable()")
override val VOID: GenericType = ClassTypeImpl("kotlin.Unit", "Unit")
override val BOOLEAN: GenericType = ClassTypeImpl("kotlin.Boolean", "false")
val BYTE: GenericType = ClassTypeImpl("kotlin.Byte", "0")
val SHORT: GenericType = ClassTypeImpl("kotlin.Short", "0")
val CHAR: GenericType = ClassTypeImpl("kotlin.Char", "0.toChar()")
override val INT: GenericType = ClassTypeImpl("kotlin.Int", "0")
override val LONG: GenericType = ClassTypeImpl("kotlin.Long", "0L")
val FLOAT: GenericType = ClassTypeImpl("kotlin.Float", "0.0f")
override val DOUBLE: GenericType = ClassTypeImpl("kotlin.Double", "0.0")
override val STRING: GenericType = ClassTypeImpl("kotlin.String", "\"\"")
override val EXCEPTION: GenericType = ClassTypeImpl("kotlin.Throwable", "kotlin.Throwable()")
override val VOID: GenericType = ClassTypeImpl("kotlin.Unit", "Unit")
val NULLABLE_ANY: GenericType = nullable { ANY }
val NULLABLE_ANY: GenericType = nullable { ANY }
override val TIME: GenericType = ClassTypeImpl("java.util.concurrent.atomic.AtomicInteger",
"java.util.concurrent.atomic.AtomicInteger()")
override val TIME: GenericType = ClassTypeImpl(
"java.util.concurrent.atomic.AtomicInteger",
"java.util.concurrent.atomic.AtomicInteger()"
)
override fun list(elementsType: GenericType): ListType =
ListTypeImpl(elementsType, { "kotlin.collections.MutableList<$it>" }, "kotlin.collections.mutableListOf()")
override fun list(elementsType: GenericType): ListType =
ListTypeImpl(elementsType, { "kotlin.collections.MutableList<$it>" }, "kotlin.collections.mutableListOf()")
override fun array(elementType: GenericType): ArrayType = when (elementType) {
BOOLEAN -> ArrayTypeImpl(BOOLEAN, { "kotlin.BooleanArray" }, { "kotlin.BooleanArray($it)" })
BYTE -> ArrayTypeImpl(BYTE, { "kotlin.ByteArray" }, { "kotlin.ByteArray($it)" })
SHORT -> ArrayTypeImpl(SHORT, { "kotlin.ShortArray" }, { "kotlin.ShortArray($it)" })
CHAR -> ArrayTypeImpl(CHAR, { "kotlin.CharArray" }, { "kotlin.CharArray($it)" })
INT -> ArrayTypeImpl(INT, { "kotlin.IntArray" }, { "kotlin.IntArray($it)" })
LONG -> ArrayTypeImpl(LONG, { "kotlin.LongArray" }, { "kotlin.LongArray($it)" })
FLOAT -> ArrayTypeImpl(FLOAT, { "kotlin.FloatArray" }, { "kotlin.FloatArray($it)" })
DOUBLE -> ArrayTypeImpl(DOUBLE, { "kotlin.DoubleArray" }, { "kotlin.DoubleArray($it)" })
else -> ArrayTypeImpl(nullable { elementType }, { "kotlin.Array<$it>" },
{ "kotlin.arrayOfNulls<${elementType.genericTypeName}>($it)" })
}
override fun map(keyType: GenericType, valueType: GenericType): MapType =
MapTypeImpl(keyType, valueType,
{ keys, values -> "kotlin.collections.MutableMap<$keys, $values>" },
"kotlin.collections.mutableMapOf()")
override fun linkedMap(keyType: GenericType, valueType: GenericType): MapType =
MapTypeImpl(keyType, valueType,
{ keys, values -> "kotlin.collections.MutableMap<$keys, $values>" },
"kotlin.collections.linkedMapOf()")
override fun nullable(typeSelector: Types.() -> GenericType): GenericType {
val type = this.typeSelector()
if (type.genericTypeName.last() == '?') return type
return when (type) {
is ArrayType -> ArrayTypeImpl(type.elementType, { "kotlin.Array<$it>?" }, { type.sizedDeclaration(it) })
is ListType -> ListTypeImpl(type.elementType, { "kotlin.collections.MutableList<$it>?" }, type.defaultValue)
is MapType -> MapTypeImpl(type.keyType, type.valueType, { keys, values -> "kotlin.collections.MutableMap<$keys, $values>?" },
type.defaultValue)
else -> ClassTypeImpl(type.genericTypeName + '?', type.defaultValue)
override fun array(elementType: GenericType): ArrayType = when (elementType) {
BOOLEAN -> ArrayTypeImpl(BOOLEAN, { "kotlin.BooleanArray" }, { "kotlin.BooleanArray($it)" })
BYTE -> ArrayTypeImpl(BYTE, { "kotlin.ByteArray" }, { "kotlin.ByteArray($it)" })
SHORT -> ArrayTypeImpl(SHORT, { "kotlin.ShortArray" }, { "kotlin.ShortArray($it)" })
CHAR -> ArrayTypeImpl(CHAR, { "kotlin.CharArray" }, { "kotlin.CharArray($it)" })
INT -> ArrayTypeImpl(INT, { "kotlin.IntArray" }, { "kotlin.IntArray($it)" })
LONG -> ArrayTypeImpl(LONG, { "kotlin.LongArray" }, { "kotlin.LongArray($it)" })
FLOAT -> ArrayTypeImpl(FLOAT, { "kotlin.FloatArray" }, { "kotlin.FloatArray($it)" })
DOUBLE -> ArrayTypeImpl(DOUBLE, { "kotlin.DoubleArray" }, { "kotlin.DoubleArray($it)" })
else -> ArrayTypeImpl(nullable { elementType }, { "kotlin.Array<$it>" },
{ "kotlin.arrayOfNulls<${elementType.genericTypeName}>($it)" })
}
}
private val primitiveTypesIndex: Map<String, GenericType> =
listOf(
BOOLEAN, BYTE, INT, SHORT,
CHAR, LONG, FLOAT, DOUBLE
)
.associate { it.genericTypeName to it }
override fun map(keyType: GenericType, valueType: GenericType): MapType =
MapTypeImpl(
keyType, valueType,
{ keys, values -> "kotlin.collections.MutableMap<$keys, $values>" },
"kotlin.collections.mutableMapOf()"
)
private val primitiveArraysIndex: Map<String, ArrayType> = primitiveTypesIndex.asSequence()
.map { array(it.value) }
.associate { it.genericTypeName to it }
override fun linkedMap(keyType: GenericType, valueType: GenericType): MapType =
MapTypeImpl(
keyType, valueType,
{ keys, values -> "kotlin.collections.MutableMap<$keys, $values>" },
"kotlin.collections.linkedMapOf()"
)
fun primitiveTypeByName(typeName: String): GenericType? = primitiveTypesIndex[typeName]
override fun nullable(typeSelector: Types.() -> GenericType): GenericType {
val type = this.typeSelector()
if (type.genericTypeName.last() == '?') return type
return when (type) {
is ArrayType -> ArrayTypeImpl(type.elementType, { "kotlin.Array<$it>?" }, { type.sizedDeclaration(it) })
is ListType -> ListTypeImpl(type.elementType, { "kotlin.collections.MutableList<$it>?" }, type.defaultValue)
is MapType -> MapTypeImpl(
type.keyType, type.valueType, { keys, values -> "kotlin.collections.MutableMap<$keys, $values>?" },
type.defaultValue
)
else -> ClassTypeImpl(type.genericTypeName + '?', type.defaultValue)
}
}
fun primitiveArrayByName(typeName: String): ArrayType? = primitiveArraysIndex[typeName]
private val primitiveTypesIndex: Map<String, GenericType> =
listOf(
BOOLEAN, BYTE, INT, SHORT,
CHAR, LONG, FLOAT, DOUBLE
)
.associate { it.genericTypeName to it }
private val primitiveArraysIndex: Map<String, ArrayType> = primitiveTypesIndex.asSequence()
.map { array(it.value) }
.associate { it.genericTypeName to it }
fun primitiveTypeByName(typeName: String): GenericType? = primitiveTypesIndex[typeName]
fun primitiveArrayByName(typeName: String): ArrayType? = primitiveArraysIndex[typeName]
}
@@ -7,12 +7,14 @@ import com.intellij.debugger.streams.trace.dsl.VariableDeclaration
/**
* @author Vitaliy.Bibaev
*/
class KotlinVariableDeclaration(override val variable: Variable,
override val isMutable: Boolean,
private val init: String = "") : VariableDeclaration {
override fun toCode(indent: Int): String {
val prefix = if (isMutable) "var" else "val"
val suffix = if (init.trim().isEmpty()) "" else " = $init"
return "$prefix ${variable.name}: ${variable.type.variableTypeName}$suffix".withIndent(indent)
}
class KotlinVariableDeclaration(
override val variable: Variable,
override val isMutable: Boolean,
private val init: String = ""
) : VariableDeclaration {
override fun toCode(indent: Int): String {
val prefix = if (isMutable) "var" else "val"
val suffix = if (init.trim().isEmpty()) "" else " = $init"
return "$prefix ${variable.name}: ${variable.type.variableTypeName}$suffix".withIndent(indent)
}
}
@@ -8,5 +8,5 @@ import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
* @author Vitaliy.Bibaev
*/
interface PeekCallFactory {
fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall
fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall
}
@@ -11,19 +11,19 @@ import com.intellij.openapi.diagnostic.Logger
* @author Vitaliy.Bibaev
*/
class KotlinTraceExpressionBuilder(dsl: Dsl, handlerFactory: HandlerFactory) : TraceExpressionBuilderBase(dsl, handlerFactory) {
private companion object {
private val LOG = Logger.getInstance(KotlinTraceExpressionBuilder::class.java)
}
private companion object {
private val LOG = Logger.getInstance(KotlinTraceExpressionBuilder::class.java)
}
override fun createTraceExpression(chain: StreamChain): String {
val expression = super.createTraceExpression(chain)
val resultDeclaration = dsl.declaration(dsl.variable(dsl.types.nullable { ANY }, resultVariableName), dsl.nullExpression, true)
val result = "${resultDeclaration.toCode()}\n " +
"$expression\n" +
resultVariableName
override fun createTraceExpression(chain: StreamChain): String {
val expression = super.createTraceExpression(chain)
val resultDeclaration = dsl.declaration(dsl.variable(dsl.types.nullable { ANY }, resultVariableName), dsl.nullExpression, true)
val result = "${resultDeclaration.toCode()}\n " +
"$expression\n" +
resultVariableName
LOG.info("trace expression: \n$result")
LOG.info("trace expression: \n$result")
return result
}
return result
}
}
@@ -1,33 +1,33 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import com.intellij.debugger.streams.wrapper.CallArgument
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
import com.intellij.debugger.streams.wrapper.StreamCallType
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
/**
* @author Vitaliy.Bibaev
*/
class OnEachCall(private val elementsType: GenericType, lambda: String) : IntermediateStreamCall {
private val args: List<CallArgument>
private val args: List<CallArgument>
init {
args = listOf(CallArgumentImpl(KotlinTypes.ANY.genericTypeName, lambda))
}
init {
args = listOf(CallArgumentImpl(KotlinTypes.ANY.genericTypeName, lambda))
}
override fun getArguments(): List<CallArgument> = args
override fun getArguments(): List<CallArgument> = args
override fun getName(): String = "onEach"
override fun getName(): String = "onEach"
override fun getType(): StreamCallType = StreamCallType.INTERMEDIATE
override fun getType(): StreamCallType = StreamCallType.INTERMEDIATE
override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE
override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE
override fun getTypeBefore(): GenericType = elementsType
override fun getTypeBefore(): GenericType = elementsType
override fun getTypeAfter(): GenericType = elementsType
override fun getTypeAfter(): GenericType = elementsType
}
@@ -14,9 +14,9 @@ import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
* @author Vitaliy.Bibaev
*/
class BothSemanticHandlerWrapper(private val handler: BothSemanticsHandler) {
fun createIntermediateHandler(order: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
CollectionIntermediateHandler(order, call, dsl, handler)
fun createIntermediateHandler(order: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
CollectionIntermediateHandler(order, call, dsl, handler)
fun createTerminatorHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
CollectionTerminatorHandler(call, resultExpression, dsl, handler)
fun createTerminatorHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
CollectionTerminatorHandler(call, resultExpression, dsl, handler)
}
@@ -10,17 +10,17 @@ import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
* @author Vitaliy.Bibaev
*/
interface BothSemanticsHandler {
fun variablesDeclaration(call: StreamCall, order: Int, dsl: Dsl): List<VariableDeclaration>
fun variablesDeclaration(call: StreamCall, order: Int, dsl: Dsl): List<VariableDeclaration>
fun prepareResult(dsl: Dsl, variables: List<Variable>): CodeBlock
fun prepareResult(dsl: Dsl, variables: List<Variable>): CodeBlock
fun additionalCallsBefore(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall>
fun additionalCallsBefore(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall>
fun additionalCallsAfter(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall>
fun additionalCallsAfter(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall>
fun transformAsIntermediateCall(call: IntermediateStreamCall, variables: List<Variable>, dsl: Dsl): IntermediateStreamCall
fun transformAsIntermediateCall(call: IntermediateStreamCall, variables: List<Variable>, dsl: Dsl): IntermediateStreamCall
fun transformAsTerminalCall(call: TerminatorStreamCall, variables: List<Variable>, dsl: Dsl): TerminatorStreamCall
fun transformAsTerminalCall(call: TerminatorStreamCall, variables: List<Variable>, dsl: Dsl): TerminatorStreamCall
fun getResultExpression(call: StreamCall, dsl: Dsl, variables: List<Variable>): Expression
fun getResultExpression(call: StreamCall, dsl: Dsl, variables: List<Variable>): Expression
}
@@ -11,14 +11,14 @@ import com.intellij.debugger.streams.wrapper.StreamCall
/**
* @author Vitaliy.Bibaev
*/
abstract class CollectionHandlerBase(order: Int, private val dsl: Dsl,
private val call: StreamCall, private val internalHandler: BothSemanticsHandler
)
: TraceHandler {
private val declarations: List<VariableDeclaration> = internalHandler.variablesDeclaration(call, order, dsl)
protected val variables: List<Variable> = declarations.map(VariableDeclaration::variable)
abstract class CollectionHandlerBase(
order: Int, private val dsl: Dsl,
private val call: StreamCall, private val internalHandler: BothSemanticsHandler
) : TraceHandler {
private val declarations: List<VariableDeclaration> = internalHandler.variablesDeclaration(call, order, dsl)
protected val variables: List<Variable> = declarations.map(VariableDeclaration::variable)
override fun additionalVariablesDeclaration(): List<VariableDeclaration> = declarations
override fun additionalVariablesDeclaration(): List<VariableDeclaration> = declarations
override fun getResultExpression(): Expression = internalHandler.getResultExpression(call, dsl, variables)
override fun getResultExpression(): Expression = internalHandler.getResultExpression(call, dsl, variables)
}
@@ -2,7 +2,9 @@
package org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections
import com.intellij.debugger.streams.trace.IntermediateCallHandler
import com.intellij.debugger.streams.trace.dsl.*
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.wrapper.IntermediateStreamCall
/**
@@ -13,26 +15,25 @@ class CollectionIntermediateHandler(
private val call: IntermediateStreamCall,
private val dsl: Dsl,
private val internalHandler: BothSemanticsHandler
)
: IntermediateCallHandler, CollectionHandlerBase(order, dsl, call, internalHandler) {
) : IntermediateCallHandler, CollectionHandlerBase(order, dsl, call, internalHandler) {
override fun prepareResult(): CodeBlock {
return internalHandler.prepareResult(dsl, variables)
}
override fun prepareResult(): CodeBlock {
return internalHandler.prepareResult(dsl, variables)
}
override fun additionalCallsBefore(): List<IntermediateStreamCall> {
return internalHandler.additionalCallsBefore(call, dsl)
}
override fun additionalCallsBefore(): List<IntermediateStreamCall> {
return internalHandler.additionalCallsBefore(call, dsl)
}
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
return internalHandler.additionalCallsAfter(call, dsl)
}
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
return internalHandler.additionalCallsAfter(call, dsl)
}
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
return internalHandler.transformAsIntermediateCall(call, variables, dsl)
}
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
return internalHandler.transformAsIntermediateCall(call, variables, dsl)
}
override fun getResultExpression(): Expression {
return internalHandler.getResultExpression(call, dsl, variables)
}
override fun getResultExpression(): Expression {
return internalHandler.getResultExpression(call, dsl, variables)
}
}
@@ -8,46 +8,44 @@ import com.intellij.debugger.streams.trace.dsl.Expression
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections.BothSemanticsHandler
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections.CollectionHandlerBase
/**
* @author Vitaliy.Bibaev
*/
class CollectionTerminatorHandler(private val call: TerminatorStreamCall,
private val resultExpression: String,
private val dsl: Dsl,
private val internalHandler: BothSemanticsHandler
)
: TerminatorCallHandler, CollectionHandlerBase(Int.MAX_VALUE, dsl, call, internalHandler) {
class CollectionTerminatorHandler(
private val call: TerminatorStreamCall,
private val resultExpression: String,
private val dsl: Dsl,
private val internalHandler: BothSemanticsHandler
) : TerminatorCallHandler, CollectionHandlerBase(Int.MAX_VALUE, dsl, call, internalHandler) {
override fun prepareResult(): CodeBlock {
val prepareResult = internalHandler.prepareResult(dsl, variables)
val additionalCallsAfter = internalHandler.additionalCallsAfter(call, dsl)
if (additionalCallsAfter.isEmpty()) {
return prepareResult
override fun prepareResult(): CodeBlock {
val prepareResult = internalHandler.prepareResult(dsl, variables)
val additionalCallsAfter = internalHandler.additionalCallsAfter(call, dsl)
if (additionalCallsAfter.isEmpty()) {
return prepareResult
}
return dsl.block {
+createCallAfterExpression(additionalCallsAfter)
add(prepareResult)
}
}
return dsl.block {
+createCallAfterExpression(additionalCallsAfter)
add(prepareResult)
}
}
override fun additionalCallsBefore(): List<IntermediateStreamCall> =
internalHandler.additionalCallsBefore(call, dsl)
override fun additionalCallsBefore(): List<IntermediateStreamCall> =
internalHandler.additionalCallsBefore(call, dsl)
override fun transformCall(call: TerminatorStreamCall): TerminatorStreamCall {
return internalHandler.transformAsTerminalCall(call, variables, dsl)
}
private fun createCallAfterExpression(additionalCallsAfter: List<IntermediateStreamCall>): Expression {
var result: Expression = TextExpression(resultExpression)
for (call in additionalCallsAfter) {
val args = call.arguments.map { TextExpression(it.text) }.toTypedArray()
result = result.call(call.name, *args)
override fun transformCall(call: TerminatorStreamCall): TerminatorStreamCall {
return internalHandler.transformAsTerminalCall(call, variables, dsl)
}
return result
}
private fun createCallAfterExpression(additionalCallsAfter: List<IntermediateStreamCall>): Expression {
var result: Expression = TextExpression(resultExpression)
for (call in additionalCallsAfter) {
val args = call.arguments.map { TextExpression(it.text) }.toTypedArray()
result = result.call(call.name, *args)
}
return result
}
}
@@ -16,65 +16,67 @@ import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.withArgs
* @author Vitaliy.Bibaev
*/
class FilterCallHandler : BothSemanticsHandler {
private companion object {
val VALUES_ARRAY_NAME = "objectsInPredicate"
val PREDICATE_RESULT_ARRAY_NAME = "filteringResults"
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))
fun oldPredicateVariableName(order: Int): String = "filterPredicate" + order
}
}
override fun additionalCallsBefore(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
override fun variablesDeclaration(call: StreamCall, order: Int, dsl: Dsl): List<VariableDeclaration> {
val types = dsl.types
override fun additionalCallsAfter(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
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))
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))
}
return listOf(
timeToObjectMap.defaultDeclaration(), predicateResultMap.defaultDeclaration(),
dsl.declaration(oldFilterPredicate, TextExpression(predicate.text), false)
)
}
override fun transformAsIntermediateCall(call: IntermediateStreamCall, variables: List<Variable>, dsl: Dsl): IntermediateStreamCall {
return call.withArgs(listOf(createNewPredicate(variables, dsl)))
}
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 transformAsTerminalCall(call: TerminatorStreamCall, variables: List<Variable>, dsl: Dsl): TerminatorStreamCall {
return call.withArgs(listOf(createNewPredicate(variables, dsl)))
}
override fun additionalCallsBefore(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
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)
+dsl.updateTime() // reserve unique time for mapped value
doReturn(filterResult)
}.toCode()
override fun additionalCallsAfter(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
return CallArgumentImpl(oldPredicate.type.genericTypeName, newPredicate)
}
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)
+dsl.updateTime() // reserve unique time for mapped value
doReturn(filterResult)
}.toCode()
return CallArgumentImpl(oldPredicate.type.genericTypeName, newPredicate)
}
}
@@ -1,7 +1,6 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.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
@@ -13,65 +12,66 @@ 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
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
/**
* @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
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)
}
override fun additionalCallsBefore(): List<IntermediateStreamCall> = peekHandler.additionalCallsBefore()
private val filterHandler = createHandler(num, call, dsl)
override fun additionalVariablesDeclaration(): List<VariableDeclaration> =
peekHandler.additionalVariablesDeclaration()
// use explicit delegation to avoid issues with navigation
override fun getResultExpression(): Expression = peekHandler.resultExpression
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)
override fun prepareResult(): CodeBlock = peekHandler.prepareResult()
/*
* 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 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)
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"
}
}
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"
}
}
}
@@ -1,7 +1,6 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
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
@@ -11,113 +10,117 @@ 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 org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
/**
* Based on com.intellij.debugger.streams.trace.impl.handler.unified.DistinctByKeyHandler
* @author Vitaliy.Bibaev
*/
class KotlinDistinctByHandler(callNumber: Int, private val call: IntermediateStreamCall, dsl: Dsl)
: HandlerBase.Intermediate(dsl) {
private companion object {
val KEY_EXTRACTOR_VARIABLE_PREFIX = "keyExtractor"
val TRANSITIONS_ARRAY_NAME = "transitionsArray"
}
private val peekHandler = PeekTraceHandler(callNumber, "distinctBy", call.typeBefore, call.typeAfter, dsl)
private val keyExtractor: CallArgument
private val extractorVariable: Variable
private val beforeTimes = dsl.list(dsl.types.INT, call.name + callNumber + "BeforeTimes")
private val beforeValues = dsl.list(call.typeBefore, call.name + callNumber + "BeforeValues")
private val keys = dsl.list(KotlinTypes.NULLABLE_ANY, call.name + callNumber + "Keys")
private val time2ValueAfter = dsl.linkedMap(dsl.types.INT, call.typeAfter, call.name + callNumber + "after")
init {
val arguments = call.arguments
assert(arguments.isNotEmpty(), { "Key extractor is not specified" })
keyExtractor = arguments.first()
extractorVariable = dsl.variable(ClassTypeImpl(keyExtractor.type), KEY_EXTRACTOR_VARIABLE_PREFIX + callNumber)
}
override fun additionalVariablesDeclaration(): List<VariableDeclaration> {
val extractor = dsl.declaration(extractorVariable, TextExpression(keyExtractor.text), false)
val variables =
mutableListOf(extractor, beforeTimes.defaultDeclaration(), beforeValues.defaultDeclaration(),
time2ValueAfter.defaultDeclaration(), keys.defaultDeclaration())
variables.addAll(peekHandler.additionalVariablesDeclaration())
return variables
}
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
val newKeyExtractor = dsl.lambda("x") {
val key = dsl.variable(KotlinTypes.NULLABLE_ANY, "key")
declare(key, extractorVariable.call("invoke", lambdaArg), false)
statement { beforeTimes.add(dsl.currentTime()) }
statement { beforeValues.add(lambdaArg) }
statement { keys.add(key) }
doReturn(key)
}.toCode()
return call.updateArguments(listOf(CallArgumentImpl(keyExtractor.type, newKeyExtractor)))
}
override fun prepareResult(): CodeBlock {
val keys2TimesBefore = dsl.map(KotlinTypes.NULLABLE_ANY, dsl.types.list(dsl.types.INT), "keys2Times")
val transitions = dsl.map(dsl.types.INT, dsl.types.INT, "transitionsMap")
return dsl.block {
add(peekHandler.prepareResult())
declare(keys2TimesBefore.defaultDeclaration())
declare(transitions.defaultDeclaration())
integerIteration(keys.size(), block@ this) {
val key = declare(variable(KotlinTypes.NULLABLE_ANY, "key"), keys.get(loopVariable), false)
val lst = list(dsl.types.INT, "lst")
declare(lst, keys2TimesBefore.computeIfAbsent(key, lambda("k") {
doReturn(newList(types.INT))
}), false)
statement { lst.add(beforeTimes.get(loopVariable)) }
}
forEachLoop(variable(types.INT, "afterTime"), time2ValueAfter.keys()) {
val afterTime = loopVariable
val valueAfter = declare(variable(call.typeAfter, "valueAfter"), time2ValueAfter.get(loopVariable), false)
val key = declare(variable(KotlinTypes.NULLABLE_ANY, "key"), nullExpression, true)
integerIteration(beforeTimes.size(), forEachLoop@ this) {
ifBranch((valueAfter same beforeValues.get(loopVariable)) and !transitions.contains(beforeTimes.get(loopVariable))) {
key assign keys.get(loopVariable)
statement { breakIteration() }
}
}
forEachLoop(variable(types.INT, "beforeTime"), keys2TimesBefore.get(key)) {
statement { transitions.set(loopVariable, afterTime) }
}
}
add(transitions.convertToArray(this, "transitionsArray"))
}
}
override fun getResultExpression(): Expression =
dsl.newArray(dsl.types.ANY, peekHandler.resultExpression, TextExpression(TRANSITIONS_ARRAY_NAME))
override fun additionalCallsBefore(): List<IntermediateStreamCall> = peekHandler.additionalCallsBefore()
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
val callsAfter = ArrayList(peekHandler.additionalCallsAfter())
val lambda = dsl.lambda("x") {
doReturn(time2ValueAfter.set(dsl.currentTime(), lambdaArg))
class KotlinDistinctByHandler(callNumber: Int, private val call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
private companion object {
val KEY_EXTRACTOR_VARIABLE_PREFIX = "keyExtractor"
val TRANSITIONS_ARRAY_NAME = "transitionsArray"
}
callsAfter.add(dsl.createPeekCall(call.typeAfter, lambda.toCode()))
return callsAfter
}
private val peekHandler = PeekTraceHandler(callNumber, "distinctBy", call.typeBefore, call.typeAfter, dsl)
private val keyExtractor: CallArgument
private val extractorVariable: Variable
private val beforeTimes = dsl.list(dsl.types.INT, call.name + callNumber + "BeforeTimes")
private val beforeValues = dsl.list(call.typeBefore, call.name + callNumber + "BeforeValues")
private val keys = dsl.list(KotlinTypes.NULLABLE_ANY, call.name + callNumber + "Keys")
private val time2ValueAfter = dsl.linkedMap(dsl.types.INT, call.typeAfter, call.name + callNumber + "after")
private fun CodeContext.integerIteration(border: Expression, block: CodeBlock, init: ForLoopBody.() -> Unit) {
block.forLoop(declaration(variable(types.INT, "i"), TextExpression("0"), true),
TextExpression("i < ${border.toCode()}"),
TextExpression("i = i + 1"), init)
}
init {
val arguments = call.arguments
assert(arguments.isNotEmpty(), { "Key extractor is not specified" })
keyExtractor = arguments.first()
extractorVariable = dsl.variable(ClassTypeImpl(keyExtractor.type), KEY_EXTRACTOR_VARIABLE_PREFIX + callNumber)
}
private fun IntermediateStreamCall.updateArguments(args: List<CallArgument>): IntermediateStreamCall =
IntermediateStreamCallImpl("distinctBy", args, typeBefore, typeAfter, textRange)
override fun additionalVariablesDeclaration(): List<VariableDeclaration> {
val extractor = dsl.declaration(extractorVariable, TextExpression(keyExtractor.text), false)
val variables =
mutableListOf(
extractor, beforeTimes.defaultDeclaration(), beforeValues.defaultDeclaration(),
time2ValueAfter.defaultDeclaration(), keys.defaultDeclaration()
)
variables.addAll(peekHandler.additionalVariablesDeclaration())
return variables
}
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
val newKeyExtractor = dsl.lambda("x") {
val key = dsl.variable(KotlinTypes.NULLABLE_ANY, "key")
declare(key, extractorVariable.call("invoke", lambdaArg), false)
statement { beforeTimes.add(dsl.currentTime()) }
statement { beforeValues.add(lambdaArg) }
statement { keys.add(key) }
doReturn(key)
}.toCode()
return call.updateArguments(listOf(CallArgumentImpl(keyExtractor.type, newKeyExtractor)))
}
override fun prepareResult(): CodeBlock {
val keys2TimesBefore = dsl.map(KotlinTypes.NULLABLE_ANY, dsl.types.list(dsl.types.INT), "keys2Times")
val transitions = dsl.map(dsl.types.INT, dsl.types.INT, "transitionsMap")
return dsl.block {
add(peekHandler.prepareResult())
declare(keys2TimesBefore.defaultDeclaration())
declare(transitions.defaultDeclaration())
integerIteration(keys.size(), block@ this) {
val key = declare(variable(KotlinTypes.NULLABLE_ANY, "key"), keys.get(loopVariable), false)
val lst = list(dsl.types.INT, "lst")
declare(lst, keys2TimesBefore.computeIfAbsent(key, lambda("k") {
doReturn(newList(types.INT))
}), false)
statement { lst.add(beforeTimes.get(loopVariable)) }
}
forEachLoop(variable(types.INT, "afterTime"), time2ValueAfter.keys()) {
val afterTime = loopVariable
val valueAfter = declare(variable(call.typeAfter, "valueAfter"), time2ValueAfter.get(loopVariable), false)
val key = declare(variable(KotlinTypes.NULLABLE_ANY, "key"), nullExpression, true)
integerIteration(beforeTimes.size(), forEachLoop@ this) {
ifBranch((valueAfter same beforeValues.get(loopVariable)) and !transitions.contains(beforeTimes.get(loopVariable))) {
key assign keys.get(loopVariable)
statement { breakIteration() }
}
}
forEachLoop(variable(types.INT, "beforeTime"), keys2TimesBefore.get(key)) {
statement { transitions.set(loopVariable, afterTime) }
}
}
add(transitions.convertToArray(this, "transitionsArray"))
}
}
override fun getResultExpression(): Expression =
dsl.newArray(dsl.types.ANY, peekHandler.resultExpression, TextExpression(TRANSITIONS_ARRAY_NAME))
override fun additionalCallsBefore(): List<IntermediateStreamCall> = peekHandler.additionalCallsBefore()
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
val callsAfter = ArrayList(peekHandler.additionalCallsAfter())
val lambda = dsl.lambda("x") {
doReturn(time2ValueAfter.set(dsl.currentTime(), lambdaArg))
}
callsAfter.add(dsl.createPeekCall(call.typeAfter, lambda.toCode()))
return callsAfter
}
private fun CodeContext.integerIteration(border: Expression, block: CodeBlock, init: ForLoopBody.() -> Unit) {
block.forLoop(
declaration(variable(types.INT, "i"), TextExpression("0"), true),
TextExpression("i < ${border.toCode()}"),
TextExpression("i = i + 1"), init
)
}
private fun IntermediateStreamCall.updateArguments(args: List<CallArgument>): IntermediateStreamCall =
IntermediateStreamCallImpl("distinctBy", args, typeBefore, typeAfter, textRange)
}
@@ -16,52 +16,52 @@ import com.sun.jdi.Value
* @author Vitaliy.Bibaev
*/
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 before = resolveValuesBefore(value.getValue(0))
val filteringMap = value.getValue(1)
val after = resolveValuesAfter(before, filteringMap)
override fun resolve(call: StreamCall, value: Value): TraceInfo {
if (value !is ArrayReference) throw UnexpectedValueTypeException("array reference excepted, but actual: ${value.type().name()}")
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<Int, TraceElement> {
val (keys, objects) = InterpreterUtil.extractMap(map)
val result: MutableList<TraceElement> = 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 ValuesOrder(call, before, after)
}
return InterpreterUtil.createIndexByTime(result)
}
private fun resolveValuesBefore(map: Value): Map<Int, TraceElement> {
val (keys, objects) = InterpreterUtil.extractMap(map)
val result: MutableList<TraceElement> = 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))
}
private fun resolveValuesAfter(before: Map<Int, TraceElement>, filteringMap: Value): Map<Int, TraceElement> {
val predicateValues = extractPredicateValues(filteringMap)
val result = linkedMapOf<Int, TraceElement>()
for ((beforeTime, element) in before) {
val predicateValue = predicateValues[beforeTime]
if (predicateValue == predicateValueToAccept) {
result[beforeTime + 1] = TraceElementImpl(beforeTime + 1, element.value)
}
return InterpreterUtil.createIndexByTime(result)
}
return result
}
private fun resolveValuesAfter(before: Map<Int, TraceElement>, filteringMap: Value): Map<Int, TraceElement> {
val predicateValues = extractPredicateValues(filteringMap)
val result = linkedMapOf<Int, TraceElement>()
for ((beforeTime, element) in before) {
val predicateValue = predicateValues[beforeTime]
if (predicateValue == predicateValueToAccept) {
result[beforeTime + 1] = TraceElementImpl(beforeTime + 1, element.value)
}
}
private fun extractPredicateValues(filteringMap: Value): Map<Int, Boolean> {
val (keys, values) = InterpreterUtil.extractMap(filteringMap)
val result = mutableMapOf<Int, Boolean>()
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
}
return result
}
private fun extractPredicateValues(filteringMap: Value): Map<Int, Boolean> {
val (keys, values) = InterpreterUtil.extractMap(filteringMap)
val result = mutableMapOf<Int, Boolean>()
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
}
}
@@ -11,23 +11,23 @@ import com.sun.jdi.Value
*/
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")
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)
}
val keys = value.getValue(0)
val values = value.getValue(1)
fun createIndexByTime(elements: List<TraceElement>): Map<Int, TraceElement> =
elements.associate { elem -> elem.time to elem }
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<TraceElement>): Map<Int, TraceElement> =
elements.associate { elem -> elem.time to elem }
data class MapRepresentation(val keys: ArrayReference, val values: ArrayReference)
data class MapRepresentation(val keys: ArrayReference, val values: ArrayReference)
}
@@ -8,17 +8,18 @@ import com.intellij.debugger.streams.wrapper.StreamCall
/**
* @author Vitaliy.Bibaev
*/
class ValuesOrder(private val call: StreamCall,
private val before: Map<Int, TraceElement>,
private val after: Map<Int, TraceElement>)
: TraceInfo {
override fun getValuesOrderBefore(): Map<Int, TraceElement> = before
class ValuesOrder(
private val call: StreamCall,
private val before: Map<Int, TraceElement>,
private val after: Map<Int, TraceElement>
) : TraceInfo {
override fun getValuesOrderBefore(): Map<Int, TraceElement> = before
override fun getCall(): StreamCall = call
override fun getCall(): StreamCall = call
override fun getValuesOrderAfter(): Map<Int, TraceElement> = after
override fun getValuesOrderAfter(): Map<Int, TraceElement> = after
override fun getDirectTrace(): MutableMap<TraceElement, MutableList<TraceElement>>? = null
override fun getDirectTrace(): MutableMap<TraceElement, MutableList<TraceElement>>? = null
override fun getReverseTrace(): MutableMap<TraceElement, MutableList<TraceElement>>? = null
override fun getReverseTrace(): MutableMap<TraceElement, MutableList<TraceElement>>? = null
}
@@ -29,85 +29,93 @@ import java.util.*
* @author Vitaliy.Bibaev
*/
abstract class KotlinPsiChainBuilderTestCase(private val relativePath: String) : StreamChainBuilderTestCase() {
override fun getTestDataPath(): String =
Paths.get(File("").absolutePath, "idea/testData/debugger/sequence/psi/$relativeTestPath/").toString()
override fun getFileExtension(): String = ".kt"
abstract val kotlinChainBuilder: StreamChainBuilder
override fun getChainBuilder(): StreamChainBuilder = kotlinChainBuilder
private val stdLibName = "kotlin-stdlib"
override fun getTestDataPath(): String =
Paths.get(File("").absolutePath, "idea/testData/debugger/sequence/psi/$relativeTestPath/").toString()
protected abstract fun doTest()
override fun getFileExtension(): String = ".kt"
abstract val kotlinChainBuilder: StreamChainBuilder
override fun getChainBuilder(): StreamChainBuilder = kotlinChainBuilder
private val stdLibName = "kotlin-stdlib"
override fun tearDown() {
doKotlinTearDown(LightPlatformTestCase.getProject(), { super.tearDown() })
}
protected abstract fun doTest()
override final fun getRelativeTestPath(): String = relativePath
override fun setUp() {
super.setUp()
ApplicationManager.getApplication().runWriteAction {
if (ProjectLibraryTable.getInstance(LightPlatformTestCase.getProject()).getLibraryByName(stdLibName) == null) {
val stdLibPath = ForTestCompileRuntime.runtimeJarForTests()
PsiTestUtil.addLibrary(testRootDisposable, LightPlatformTestCase.getModule(), stdLibName, stdLibPath.parent, stdLibPath.name)
}
}
LibraryModificationTracker.getInstance(LightPlatformTestCase.getProject()).incModificationCount()
}
override fun getProjectJDK(): Sdk {
return PluginTestCaseBase.mockJdk9()
}
private fun doKotlinTearDown(project: Project, runnable: () -> Unit) {
unInvalidateBuiltinsAndStdLib(project) {
runnable()
}
}
private fun unInvalidateBuiltinsAndStdLib(project: Project, runnable: () -> Unit) {
val stdLibViewProviders = HashSet<KotlinDecompiledFileViewProvider>()
val vFileToViewProviderMap = ((PsiManager.getInstance(project) as PsiManagerEx).fileManager as FileManagerImpl).vFileToViewProviderMap
for ((file, viewProvider) in vFileToViewProviderMap) {
if (file.isStdLibFile && viewProvider is KotlinDecompiledFileViewProvider) {
stdLibViewProviders.add(viewProvider)
}
override fun tearDown() {
doKotlinTearDown(LightPlatformTestCase.getProject(), { super.tearDown() })
}
runnable()
override final fun getRelativeTestPath(): String = relativePath
// Base tearDown() invalidates builtins and std-lib files. Restore them with brute force.
fun unInvalidateFile(file: PsiFileImpl) {
val field = PsiFileImpl::class.java.getDeclaredField("myInvalidated")!!
field.isAccessible = true
field.set(file, false)
override fun setUp() {
super.setUp()
ApplicationManager.getApplication().runWriteAction {
if (ProjectLibraryTable.getInstance(LightPlatformTestCase.getProject()).getLibraryByName(stdLibName) == null) {
val stdLibPath = ForTestCompileRuntime.runtimeJarForTests()
PsiTestUtil.addLibrary(
testRootDisposable,
LightPlatformTestCase.getModule(),
stdLibName,
stdLibPath.parent,
stdLibPath.name
)
}
}
LibraryModificationTracker.getInstance(LightPlatformTestCase.getProject()).incModificationCount()
}
stdLibViewProviders.forEach {
it.allFiles.forEach { unInvalidateFile(it as KtDecompiledFile) }
vFileToViewProviderMap[it.virtualFile] = it
}
}
private val VirtualFile.isStdLibFile: Boolean get() = presentableUrl.contains("kotlin-runtime.jar")
abstract class Positive(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
override fun doTest() {
val chains = buildChains()
checkChains(chains)
override fun getProjectJDK(): Sdk {
return PluginTestCaseBase.mockJdk9()
}
protected fun checkChains(chains: MutableList<StreamChain>) {
TestCase.assertFalse(chains.isEmpty())
private fun doKotlinTearDown(project: Project, runnable: () -> Unit) {
unInvalidateBuiltinsAndStdLib(project) {
runnable()
}
}
}
abstract class Negative(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
override fun doTest() {
val elementAtCaret = configureAndGetElementAtCaret()
TestCase.assertFalse(chainBuilder.isChainExists(elementAtCaret))
TestCase.assertTrue(chainBuilder.build(elementAtCaret).isEmpty())
private fun unInvalidateBuiltinsAndStdLib(project: Project, runnable: () -> Unit) {
val stdLibViewProviders = HashSet<KotlinDecompiledFileViewProvider>()
val vFileToViewProviderMap =
((PsiManager.getInstance(project) as PsiManagerEx).fileManager as FileManagerImpl).vFileToViewProviderMap
for ((file, viewProvider) in vFileToViewProviderMap) {
if (file.isStdLibFile && viewProvider is KotlinDecompiledFileViewProvider) {
stdLibViewProviders.add(viewProvider)
}
}
runnable()
// Base tearDown() invalidates builtins and std-lib files. Restore them with brute force.
fun unInvalidateFile(file: PsiFileImpl) {
val field = PsiFileImpl::class.java.getDeclaredField("myInvalidated")!!
field.isAccessible = true
field.set(file, false)
}
stdLibViewProviders.forEach {
it.allFiles.forEach { unInvalidateFile(it as KtDecompiledFile) }
vFileToViewProviderMap[it.virtualFile] = it
}
}
private val VirtualFile.isStdLibFile: Boolean get() = presentableUrl.contains("kotlin-runtime.jar")
abstract class Positive(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
override fun doTest() {
val chains = buildChains()
checkChains(chains)
}
protected fun checkChains(chains: MutableList<StreamChain>) {
TestCase.assertFalse(chains.isEmpty())
}
}
abstract class Negative(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
override fun doTest() {
val elementAtCaret = configureAndGetElementAtCaret()
TestCase.assertFalse(chainBuilder.isChainExists(elementAtCaret))
TestCase.assertTrue(chainBuilder.build(elementAtCaret).isEmpty())
}
}
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.idea.debugger.sequence.lib.collections.KotlinCollect
/**
* @author Vitaliy.Bibaev
*/
@Suppress("unused")
abstract class AbstractCollectionTraceTestCase : KotlinTraceTestCase() {
override val librarySupportProvider: LibrarySupportProvider = KotlinCollectionSupportProvider()
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibraryS
/**
* @author Vitaliy.Bibaev
*/
abstract class AbstractJavaStreamTraceTestCase: KotlinTraceTestCase() {
@Suppress("unused")
abstract class AbstractJavaStreamTraceTestCase : KotlinTraceTestCase() {
override val librarySupportProvider: LibrarySupportProvider = JavaStandardLibrarySupportProvider()
}
@@ -15,7 +15,9 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
/**
* This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY
*/
@SuppressWarnings("all")
@TestMetadata("idea/testData/debugger/tinyApp/src/streams/sequence")
@TestDataPath("$PROJECT_ROOT")
@@ -26,7 +28,8 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInSequence() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true, "terminal");
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true, "terminal");
}
@TestMetadata("idea/testData/debugger/tinyApp/src/streams/sequence/append")
@@ -38,7 +41,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInAppend() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/append"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(),
new File("idea/testData/debugger/tinyApp/src/streams/sequence/append"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("PlusArray.kt")
@@ -71,7 +76,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInDistinct() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/distinct"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(),
new File("idea/testData/debugger/tinyApp/src/streams/sequence/distinct"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Distinct.kt")
@@ -119,7 +126,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInFilter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/filter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(),
new File("idea/testData/debugger/tinyApp/src/streams/sequence/filter"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Drop.kt")
@@ -182,7 +191,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInFlatMap() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/flatMap"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(),
new File("idea/testData/debugger/tinyApp/src/streams/sequence/flatMap"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("FlatMap.kt")
@@ -205,7 +216,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInMap() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/map"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils
.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/map"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Map.kt")
@@ -238,7 +251,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInMisc() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/misc"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils
.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/misc"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("AsSequence.kt")
@@ -326,7 +341,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
}
public void testAllFilesPresentInSort() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/sort"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
KotlinTestUtils
.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/streams/sequence/sort"),
Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Sorted.kt")
@@ -1,42 +1,44 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi
import org.jetbrains.kotlin.idea.debugger.sequence.KotlinPsiChainBuilderTestCase
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
import org.jetbrains.kotlin.idea.debugger.sequence.KotlinPsiChainBuilderTestCase
/**
* @author Vitaliy.Bibaev
*/
abstract class TypedChainTestCase(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
protected fun doTest(producerAfterType: GenericType,
vararg intermediateAfterTypes: GenericType) {
val elementAtCaret = configureAndGetElementAtCaret()
assertNotNull(elementAtCaret)
val chains = chainBuilder.build(elementAtCaret)
assertFalse(chains.isEmpty())
val chain = chains[0]
val intermediateCalls = chain.intermediateCalls
assertEquals(intermediateAfterTypes.size, intermediateCalls.size)
assertEquals(producerAfterType, chain.qualifierExpression.typeAfter)
protected fun doTest(
producerAfterType: GenericType,
vararg intermediateAfterTypes: GenericType
) {
val elementAtCaret = configureAndGetElementAtCaret()
assertNotNull(elementAtCaret)
val chains = chainBuilder.build(elementAtCaret)
assertFalse(chains.isEmpty())
val chain = chains[0]
val intermediateCalls = chain.intermediateCalls
assertEquals(intermediateAfterTypes.size, intermediateCalls.size)
assertEquals(producerAfterType, chain.qualifierExpression.typeAfter)
if (intermediateAfterTypes.isNotEmpty()) {
assertEquals(producerAfterType, intermediateCalls[0].typeBefore)
for (i in 0 until intermediateAfterTypes.size - 1) {
assertEquals(intermediateAfterTypes[i], intermediateCalls[i].typeAfter)
assertEquals(intermediateAfterTypes[i], intermediateCalls[i + 1].typeBefore)
}
if (intermediateAfterTypes.isNotEmpty()) {
assertEquals(producerAfterType, intermediateCalls[0].typeBefore)
for (i in 0 until intermediateAfterTypes.size - 1) {
assertEquals(intermediateAfterTypes[i], intermediateCalls[i].typeAfter)
assertEquals(intermediateAfterTypes[i], intermediateCalls[i + 1].typeBefore)
}
val lastAfterType = intermediateAfterTypes[intermediateAfterTypes.size - 1]
assertEquals(lastAfterType, chain.terminationCall.typeBefore)
val lastCall = intermediateCalls[intermediateCalls.size - 1]
assertEquals(lastAfterType, lastCall.typeAfter)
} else {
assertEquals(producerAfterType, chain.terminationCall.typeBefore)
val lastAfterType = intermediateAfterTypes[intermediateAfterTypes.size - 1]
assertEquals(lastAfterType, chain.terminationCall.typeBefore)
val lastCall = intermediateCalls[intermediateCalls.size - 1]
assertEquals(lastAfterType, lastCall.typeAfter)
} else {
assertEquals(producerAfterType, chain.terminationCall.typeBefore)
}
}
}
override fun doTest() {
fail("Use doTest(producerAfterType, vararg intermediateAfterTypes)")
}
override fun doTest() {
fail("Use doTest(producerAfterType, vararg intermediateAfterTypes)")
}
}
@@ -1,18 +1,18 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.collection
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.KotlinPsiChainBuilderTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.lib.collections.KotlinCollectionSupportProvider
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
/**
* @author Vitaliy.Bibaev
*/
class PositiveCollectionBuildTest : KotlinPsiChainBuilderTestCase.Positive("collection/positive") {
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
fun testIntermediateIsLastCall() = doTest()
fun testOnlyFilterCall() = doTest()
fun testTerminationCallUsed() = doTest()
fun testOnlyTerminationCallUsed() = doTest()
fun testIntermediateIsLastCall() = doTest()
fun testOnlyFilterCall() = doTest()
fun testTerminationCallUsed() = doTest()
fun testOnlyTerminationCallUsed() = doTest()
}
@@ -1,53 +1,53 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.collection
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.lib.collections.KotlinCollectionSupportProvider
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
/**
* @author Vitaliy.Bibaev
*/
class TypedCollectionChainTest : TypedChainTestCase("collection/positive/types") {
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
fun testAny() = doTest(KotlinTypes.ANY)
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
fun testAny() = doTest(KotlinTypes.ANY)
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
fun testByte() = doTest(KotlinTypes.BYTE)
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
fun testByte() = doTest(KotlinTypes.BYTE)
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
fun testShort() = doTest(KotlinTypes.SHORT)
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
fun testShort() = doTest(KotlinTypes.SHORT)
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
fun testInt() = doTest(KotlinTypes.INT)
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
fun testInt() = doTest(KotlinTypes.INT)
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
fun testLong() = doTest(KotlinTypes.LONG)
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
fun testLong() = doTest(KotlinTypes.LONG)
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
fun testFloat() = doTest(KotlinTypes.FLOAT)
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
fun testFloat() = doTest(KotlinTypes.FLOAT)
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
fun testDouble() = doTest(KotlinTypes.DOUBLE)
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
fun testDouble() = doTest(KotlinTypes.DOUBLE)
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
fun testChar() = doTest(KotlinTypes.CHAR)
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
fun testChar() = doTest(KotlinTypes.CHAR)
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
}
@@ -5,29 +5,29 @@ package org.jetbrains.kotlin.idea.debugger.sequence.psi.java
* @author Vitaliy.Bibaev
*/
class AmbiguousChainsTest : PositiveJavaStreamTest("ambiguous") {
fun testSimpleExpression() = doTest(2)
fun testSimpleExpression() = doTest(2)
fun testNestedExpression() = doTest(3)
fun testSimpleFunctionParameter() = doTest(2)
fun testNestedFunctionParameters() = doTest(3)
fun testNestedFunctionParametersReversed() = doTest(3)
fun testNestedExpression() = doTest(3)
fun testSimpleFunctionParameter() = doTest(2)
fun testNestedFunctionParameters() = doTest(3)
fun testNestedFunctionParametersReversed() = doTest(3)
fun testStreamProducerParameter() = doTest(2)
fun testStreamIntermediateCallParameter() = doTest(2)
fun testStreamTerminatorParameter() = doTest(2)
fun testStreamAllPositions() = doTest(4)
fun testStreamProducerParameter() = doTest(2)
fun testStreamIntermediateCallParameter() = doTest(2)
fun testStreamTerminatorParameter() = doTest(2)
fun testStreamAllPositions() = doTest(4)
fun testNestedStreamProducerParameter() = doTest(3)
fun testNestedStreamIntermediateCallParameter() = doTest(3)
fun testNestedStreamTerminatorCallParameter() = doTest(3)
fun testNestedStreamProducerParameter() = doTest(3)
fun testNestedStreamIntermediateCallParameter() = doTest(3)
fun testNestedStreamTerminatorCallParameter() = doTest(3)
fun testNestedCallInLambda() = doTest(2)
fun testNestedCallInAnonymous() = doTest(2)
fun testNestedCallInLambda() = doTest(2)
fun testNestedCallInAnonymous() = doTest(2)
fun testLinkedChain() = doTest(3)
fun testLinkedChain() = doTest(3)
private fun doTest(chainsCount: Int) {
val chains = buildChains()
assertEquals(chainsCount, chains.size)
}
private fun doTest(chainsCount: Int) {
val chains = buildChains()
assertEquals(chainsCount, chains.size)
}
}
@@ -5,37 +5,37 @@ package org.jetbrains.kotlin.idea.debugger.sequence.psi.java
* @author Vitaliy.Bibaev
*/
class LocationPositiveChainTest : PositiveJavaStreamTest("location") {
fun testAnonymousBody() = doTest()
fun testAnonymousBody() = doTest()
fun testAssignExpression() = doTest()
fun testAssignExpression() = doTest()
fun testFirstParameterOfFunction() = doTest()
fun testLambdaBody() = doTest()
fun testFirstParameterOfFunction() = doTest()
fun testLambdaBody() = doTest()
fun testParameterInAssignExpression() = doTest()
fun testParameterInReturnExpression() = doTest()
fun testParameterInAssignExpression() = doTest()
fun testParameterInReturnExpression() = doTest()
fun testReturnExpression() = doTest()
fun testReturnExpression() = doTest()
fun testSecondParameterOfFunction() = doTest()
fun testSecondParameterOfFunction() = doTest()
fun testSingleExpression() = doTest()
fun testSingleExpression() = doTest()
fun testBeforeStatement() = doTest()
fun testBeforeStatement() = doTest()
fun testBetweenChainCallsBeforeDot() = doTest()
fun testBetweenChainCallsAfterDot() = doTest()
fun testBetweenChainCallsBeforeDot() = doTest()
fun testBetweenChainCallsAfterDot() = doTest()
fun testInEmptyParameterList() = doTest()
fun testInEmptyParameterList() = doTest()
fun testBetweenParametersBeforeComma() = doTest()
fun testBetweenParametersAfterComma() = doTest()
fun testBetweenParametersBeforeComma() = doTest()
fun testBetweenParametersAfterComma() = doTest()
fun testInAnyLambda() = doTest()
fun testInAnyAnonymous() = doTest()
fun testInString() = doTest()
fun testInVariableName() = doTest()
fun testInMethodReference() = doTest()
fun testInAnyLambda() = doTest()
fun testInAnyAnonymous() = doTest()
fun testInString() = doTest()
fun testInVariableName() = doTest()
fun testInMethodReference() = doTest()
fun testAsMethodExpression() = doTest()
fun testAsMethodExpression() = doTest()
}
@@ -1,35 +1,35 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.java
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.KotlinPsiChainBuilderTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
/**
* @author Vitaliy.Bibaev
*/
class NegativeJavaStreamTest : KotlinPsiChainBuilderTestCase.Negative("streams/negative") {
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
fun testFakeStream() = doTest()
fun testFakeStream() = doTest()
fun testWithoutTerminalOperation() = doTest()
fun testWithoutTerminalOperation() = doTest()
fun testNoBreakpoint() = doTest()
fun testNoBreakpoint() = doTest()
fun testBreakpointOnMethod() = doTest()
fun testBreakpointOnIfCondition() = doTest()
fun testBreakpointOnNewScope() = doTest()
fun testBreakpointOnElseBranch() = doTest()
fun testBreakpointOnMethod() = doTest()
fun testBreakpointOnIfCondition() = doTest()
fun testBreakpointOnNewScope() = doTest()
fun testBreakpointOnElseBranch() = doTest()
fun testInLambda() = doTest()
fun testInLambdaWithBody() = doTest()
fun testInAnonymous() = doTest()
fun testInLambda() = doTest()
fun testInLambdaWithBody() = doTest()
fun testInAnonymous() = doTest()
fun testAfterStatement() = doTest()
fun testAfterStatement() = doTest()
fun testInPreviousStatement() = doTest()
fun testInNextStatement() = doTest()
fun testInPreviousStatement() = doTest()
fun testInNextStatement() = doTest()
fun testIdea173415() = doTest()
fun testIdea173415() = doTest()
}
@@ -1,13 +1,13 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.java
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.KotlinPsiChainBuilderTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
/**
* @author Vitaliy.Bibaev
*/
abstract class PositiveJavaStreamTest(subDirectory: String) : KotlinPsiChainBuilderTestCase.Positive("streams/positive/$subDirectory") {
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
}
@@ -1,28 +1,28 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.java
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.DOUBLE
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.INT
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.LONG
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.NULLABLE_ANY
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
/**
* @author Vitaliy.Bibaev
*/
class TypedJavaChainTest : TypedChainTestCase("streams/positive/types") {
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
fun testOneCall() = doTest(NULLABLE_ANY)
fun testMapToSame() = doTest(NULLABLE_ANY, NULLABLE_ANY)
fun testPrimitiveOneCall() = doTest(INT)
fun testPrimitiveMapToSame() = doTest(LONG, LONG)
fun testOneCall() = doTest(NULLABLE_ANY)
fun testMapToSame() = doTest(NULLABLE_ANY, NULLABLE_ANY)
fun testPrimitiveOneCall() = doTest(INT)
fun testPrimitiveMapToSame() = doTest(LONG, LONG)
fun testMapToPrimitive() = doTest(NULLABLE_ANY, DOUBLE)
fun testMapToObj() = doTest(DOUBLE, NULLABLE_ANY)
fun testMapPrimitiveToPrimitive() = doTest(LONG, INT)
fun testMapToPrimitive() = doTest(NULLABLE_ANY, DOUBLE)
fun testMapToObj() = doTest(DOUBLE, NULLABLE_ANY)
fun testMapPrimitiveToPrimitive() = doTest(LONG, INT)
fun testFewTransitions() = doTest(NULLABLE_ANY, INT, NULLABLE_ANY, LONG, DOUBLE)
fun testFewTransitions() = doTest(NULLABLE_ANY, INT, NULLABLE_ANY, LONG, DOUBLE)
}
@@ -1,54 +1,54 @@
// 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 org.jetbrains.kotlin.idea.debugger.sequence.psi.sequence
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.lib.sequence.KotlinSequenceSupportProvider
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
/**
* @author Vitaliy.Bibaev
*/
class TypedSequenceChain : TypedChainTestCase("sequence/positive/types") {
override val kotlinChainBuilder: StreamChainBuilder = KotlinSequenceSupportProvider().chainBuilder
override val kotlinChainBuilder: StreamChainBuilder = KotlinSequenceSupportProvider().chainBuilder
fun testAny() = doTest(KotlinTypes.ANY)
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
fun testAny() = doTest(KotlinTypes.ANY)
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
fun testByte() = doTest(KotlinTypes.BYTE)
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
fun testByte() = doTest(KotlinTypes.BYTE)
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
fun testShort() = doTest(KotlinTypes.SHORT)
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
fun testShort() = doTest(KotlinTypes.SHORT)
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
fun testInt() = doTest(KotlinTypes.INT)
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
fun testInt() = doTest(KotlinTypes.INT)
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
fun testLong() = doTest(KotlinTypes.LONG)
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
fun testLong() = doTest(KotlinTypes.LONG)
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
fun testFloat() = doTest(KotlinTypes.FLOAT)
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
fun testFloat() = doTest(KotlinTypes.FLOAT)
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
fun testDouble() = doTest(KotlinTypes.DOUBLE)
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
fun testDouble() = doTest(KotlinTypes.DOUBLE)
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
fun testChar() = doTest(KotlinTypes.CHAR)
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
fun testChar() = doTest(KotlinTypes.CHAR)
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
}