Apply project code style settings to sequence debugger code
This commit is contained in:
committed by
Yan Zhulanow
parent
245a358ea8
commit
2d22267cf1
@@ -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"
|
||||
}
|
||||
+24
-24
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+15
-15
@@ -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))
|
||||
}
|
||||
+20
-20
@@ -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))
|
||||
}
|
||||
+20
-20
@@ -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
|
||||
}
|
||||
+19
-19
@@ -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
|
||||
|
||||
}
|
||||
+42
-34
@@ -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()
|
||||
)
|
||||
}
|
||||
+12
-12
@@ -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
-18
@@ -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
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
|
||||
+22
-23
@@ -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)
|
||||
}
|
||||
+54
-52
@@ -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))
|
||||
}
|
||||
+38
-38
@@ -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
|
||||
}
|
||||
+57
-57
@@ -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) {}
|
||||
}
|
||||
}
|
||||
+41
-35
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+22
-20
@@ -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)
|
||||
}
|
||||
}
|
||||
+53
-53
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -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))
|
||||
}
|
||||
+12
-12
@@ -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)
|
||||
}
|
||||
+36
-36
@@ -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
|
||||
}
|
||||
}
|
||||
+24
-24
@@ -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)
|
||||
}
|
||||
}
|
||||
+26
-26
@@ -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)
|
||||
}
|
||||
}
|
||||
+36
-36
@@ -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())
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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)
|
||||
}
|
||||
+5
-6
@@ -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()))
|
||||
}
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
+3
-3
@@ -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
-7
@@ -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)
|
||||
}
|
||||
+12
-10
@@ -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)
|
||||
}
|
||||
+9
-8
@@ -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
|
||||
}
|
||||
+14
-14
@@ -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
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -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) +
|
||||
"}"
|
||||
}
|
||||
+2
-3
@@ -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
|
||||
|
||||
+8
-9
@@ -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)
|
||||
}
|
||||
+13
-11
@@ -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)
|
||||
}
|
||||
+70
-68
@@ -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)
|
||||
}
|
||||
|
||||
+8
-8
@@ -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)
|
||||
}
|
||||
}
|
||||
+69
-61
@@ -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]
|
||||
}
|
||||
|
||||
|
||||
+10
-8
@@ -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)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
+12
-12
@@ -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
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -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
|
||||
}
|
||||
+4
-4
@@ -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)
|
||||
}
|
||||
|
||||
+7
-7
@@ -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
|
||||
}
|
||||
+8
-8
@@ -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)
|
||||
}
|
||||
+19
-18
@@ -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)
|
||||
}
|
||||
}
|
||||
+30
-32
@@ -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
|
||||
}
|
||||
}
|
||||
+54
-52
@@ -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)
|
||||
}
|
||||
}
|
||||
+50
-50
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
-101
@@ -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)
|
||||
}
|
||||
+39
-39
@@ -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
|
||||
}
|
||||
}
|
||||
+16
-16
@@ -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)
|
||||
}
|
||||
|
||||
+10
-9
@@ -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
|
||||
}
|
||||
+75
-67
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -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()
|
||||
}
|
||||
+2
-1
@@ -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()
|
||||
}
|
||||
Generated
+26
-9
@@ -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)")
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -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()
|
||||
}
|
||||
+28
-28
@@ -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)
|
||||
}
|
||||
+19
-19
@@ -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)
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -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()
|
||||
}
|
||||
+16
-16
@@ -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()
|
||||
}
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
+10
-10
@@ -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)
|
||||
}
|
||||
|
||||
+28
-28
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user