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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
object LibraryUtil {
|
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.
|
// 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
|
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.IntermediateOperation
|
||||||
import com.intellij.debugger.streams.lib.TerminalOperation
|
import com.intellij.debugger.streams.lib.TerminalOperation
|
||||||
import com.intellij.debugger.streams.lib.impl.LibrarySupportBase
|
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.BothSemanticHandlerWrapper
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections.BothSemanticsHandler
|
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.handler.collections.FilterCallHandler
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.interpret.FilterTraceInterpreter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinCollectionLibrarySupport : LibrarySupportBase() {
|
class KotlinCollectionLibrarySupport : LibrarySupportBase() {
|
||||||
init {
|
init {
|
||||||
addOperation(FilterOperation("filter", FilterCallHandler(), true))
|
addOperation(FilterOperation("filter", FilterCallHandler(), true))
|
||||||
addOperation(FilterOperation("filterNot", FilterCallHandler(), false))
|
addOperation(FilterOperation("filterNot", FilterCallHandler(), false))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addOperation(operation: CollectionOperation) {
|
private fun addOperation(operation: CollectionOperation) {
|
||||||
addIntermediateOperationsSupport(operation)
|
addIntermediateOperationsSupport(operation)
|
||||||
addTerminationOperationsSupport(operation)
|
addTerminationOperationsSupport(operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class CollectionOperation(override val name: String,
|
private abstract class CollectionOperation(
|
||||||
handler: BothSemanticsHandler
|
override val name: String,
|
||||||
)
|
handler: BothSemanticsHandler
|
||||||
: IntermediateOperation, TerminalOperation {
|
) : IntermediateOperation, TerminalOperation {
|
||||||
|
|
||||||
private val wrapper = BothSemanticHandlerWrapper(handler)
|
private val wrapper = BothSemanticHandlerWrapper(handler)
|
||||||
|
|
||||||
override fun getTraceHandler(callOrder: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
|
override fun getTraceHandler(callOrder: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
|
||||||
wrapper.createIntermediateHandler(callOrder, call, dsl)
|
wrapper.createIntermediateHandler(callOrder, call, dsl)
|
||||||
|
|
||||||
override fun getTraceHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
|
override fun getTraceHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
|
||||||
wrapper.createTerminatorHandler(call, resultExpression, dsl)
|
wrapper.createTerminatorHandler(call, resultExpression, dsl)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FilterOperation(name: String, handler: BothSemanticsHandler, valueToAccept: Boolean)
|
private class FilterOperation(name: String, handler: BothSemanticsHandler, valueToAccept: Boolean) :
|
||||||
: CollectionOperation(name, handler) {
|
CollectionOperation(name, handler) {
|
||||||
override val traceInterpreter: CallTraceInterpreter = FilterTraceInterpreter(valueToAccept)
|
override val traceInterpreter: CallTraceInterpreter = FilterTraceInterpreter(valueToAccept)
|
||||||
override val valuesOrderResolver: ValuesOrderResolver = FilterResolver()
|
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.
|
// 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
|
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.LibrarySupport
|
||||||
import com.intellij.debugger.streams.lib.LibrarySupportProvider
|
import com.intellij.debugger.streams.lib.LibrarySupportProvider
|
||||||
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
|
import com.intellij.debugger.streams.trace.TraceExpressionBuilder
|
||||||
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
|
import com.intellij.debugger.streams.trace.dsl.impl.DslImpl
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
||||||
import com.intellij.openapi.project.Project
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinCollectionSupportProvider : LibrarySupportProvider {
|
class KotlinCollectionSupportProvider : LibrarySupportProvider {
|
||||||
private companion object {
|
private companion object {
|
||||||
val builder: StreamChainBuilder = KotlinCollectionChainBuilder()
|
val builder: StreamChainBuilder = KotlinCollectionChainBuilder()
|
||||||
val support: LibrarySupport = KotlinCollectionLibrarySupport()
|
val support: LibrarySupport = KotlinCollectionLibrarySupport()
|
||||||
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
|
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
|
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder =
|
||||||
= KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
|
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.
|
// 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
|
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.lib.LibraryUtil
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
|
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.PackageBasedCallChecker
|
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.JavaPeekCallFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class JavaStandardLibrarySupportProvider : LibrarySupportProvider {
|
class JavaStandardLibrarySupportProvider : LibrarySupportProvider {
|
||||||
private companion object {
|
private companion object {
|
||||||
val builder = TerminatedChainBuilder(
|
val builder = TerminatedChainBuilder(
|
||||||
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
|
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
|
||||||
PackageBasedCallChecker("java.util.stream")
|
PackageBasedCallChecker("java.util.stream")
|
||||||
)
|
)
|
||||||
val support = StandardLibrarySupport()
|
val support = StandardLibrarySupport()
|
||||||
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
|
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 =
|
override fun getExpressionBuilder(project: Project): TraceExpressionBuilder =
|
||||||
KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
|
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.
|
// 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
|
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.lib.LibraryUtil
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
|
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.PackageBasedCallChecker
|
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.JavaPeekCallFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class StreamExLibrarySupportProvider : LibrarySupportProvider {
|
class StreamExLibrarySupportProvider : LibrarySupportProvider {
|
||||||
private companion object {
|
private companion object {
|
||||||
val streamChainBuilder = TerminatedChainBuilder(
|
val streamChainBuilder = TerminatedChainBuilder(
|
||||||
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
|
KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()),
|
||||||
PackageBasedCallChecker("one.util.streamex")
|
PackageBasedCallChecker("one.util.streamex")
|
||||||
)
|
)
|
||||||
val support = StreamExLibrarySupport()
|
val support = StreamExLibrarySupport()
|
||||||
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
|
val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory()))
|
||||||
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
|
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.
|
// 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
|
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.lib.LibraryUtil
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
|
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.KotlinChainTransformerImpl
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.impl.TerminatedChainBuilder
|
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.KotlinCollectionsPeekCallFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinStatementFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpressionBuilder
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinSequenceSupportProvider : LibrarySupportProvider {
|
class KotlinSequenceSupportProvider : LibrarySupportProvider {
|
||||||
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
|
override fun getLanguageId(): String = LibraryUtil.KOTLIN_LANGUAGE_ID
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val builder: StreamChainBuilder = TerminatedChainBuilder(
|
val builder: StreamChainBuilder = TerminatedChainBuilder(
|
||||||
KotlinChainTransformerImpl(SequenceTypeExtractor()),
|
KotlinChainTransformerImpl(SequenceTypeExtractor()),
|
||||||
SequenceCallChecker()
|
SequenceCallChecker()
|
||||||
)
|
)
|
||||||
val support = KotlinSequencesSupport()
|
val support = KotlinSequencesSupport()
|
||||||
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
|
val dsl = DslImpl(KotlinStatementFactory(KotlinCollectionsPeekCallFactory()))
|
||||||
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
|
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.
|
// 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
|
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.IntermediateOperation
|
||||||
import com.intellij.debugger.streams.lib.impl.*
|
import com.intellij.debugger.streams.lib.impl.*
|
||||||
import com.intellij.debugger.streams.resolve.AppendResolver
|
import com.intellij.debugger.streams.resolve.AppendResolver
|
||||||
import com.intellij.debugger.streams.resolve.PairMapResolver
|
import com.intellij.debugger.streams.resolve.PairMapResolver
|
||||||
import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHandler
|
import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHandler
|
||||||
import com.intellij.debugger.streams.trace.impl.interpret.SimplePeekCallTraceInterpreter
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinSequencesSupport : LibrarySupportBase() {
|
class KotlinSequencesSupport : LibrarySupportBase() {
|
||||||
init {
|
init {
|
||||||
addIntermediateOperationsSupport(*filterOperations("filter", "filterNot", "filterIndexed",
|
addIntermediateOperationsSupport(
|
||||||
"drop", "dropWhile", "minus", "minusElement", "take", "takeWhile", "onEach", "asSequence"))
|
*filterOperations(
|
||||||
|
"filter", "filterNot", "filterIndexed",
|
||||||
|
"drop", "dropWhile", "minus", "minusElement", "take", "takeWhile", "onEach", "asSequence"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
addIntermediateOperationsSupport(FilterIsInstanceOperationHandler())
|
addIntermediateOperationsSupport(FilterIsInstanceOperationHandler())
|
||||||
|
|
||||||
addIntermediateOperationsSupport(*mapOperations("map", "mapIndexed", "requireNoNulls", "withIndex",
|
addIntermediateOperationsSupport(
|
||||||
"zip", "constrainOnce"))
|
*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("distinct", ::DistinctTraceHandler))
|
||||||
addIntermediateOperationsSupport(DistinctOperation("distinctBy", ::KotlinDistinctByHandler))
|
addIntermediateOperationsSupport(DistinctOperation("distinctBy", ::KotlinDistinctByHandler))
|
||||||
|
|
||||||
addIntermediateOperationsSupport(ConcatOperation("plus", AppendResolver()))
|
addIntermediateOperationsSupport(ConcatOperation("plus", AppendResolver()))
|
||||||
addIntermediateOperationsSupport(ConcatOperation("plusElement", AppendResolver()))
|
addIntermediateOperationsSupport(ConcatOperation("plusElement", AppendResolver()))
|
||||||
|
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("zipWithNext", PairMapResolver()))
|
||||||
|
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", FilteredMapResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("mapNotNull", FilteredMapResolver()))
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("chunked", ChunkedResolver()))
|
||||||
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
|
addIntermediateOperationsSupport(OrderBasedOperation("windowed", WindowedResolver()))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filterOperations(vararg names: String): Array<IntermediateOperation> =
|
private fun filterOperations(vararg names: String): Array<IntermediateOperation> =
|
||||||
names.map { FilterOperation(it) }.toTypedArray()
|
names.map { FilterOperation(it) }.toTypedArray()
|
||||||
|
|
||||||
private fun mapOperations(vararg names: String): Array<IntermediateOperation> =
|
private fun mapOperations(vararg names: String): Array<IntermediateOperation> =
|
||||||
names.map { MappingOperation(it) }.toTypedArray()
|
names.map { MappingOperation(it) }.toTypedArray()
|
||||||
|
|
||||||
private fun flatMapOperations(vararg names: String): Array<IntermediateOperation> =
|
private fun flatMapOperations(vararg names: String): Array<IntermediateOperation> =
|
||||||
names.map { FlatMappingOperation(it) }.toTypedArray()
|
names.map { FlatMappingOperation(it) }.toTypedArray()
|
||||||
|
|
||||||
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
|
private fun sortedOperations(vararg names: String): Array<IntermediateOperation> =
|
||||||
names.map { SortedOperation(it) }.toTypedArray()
|
names.map { SortedOperation(it) }.toTypedArray()
|
||||||
|
|
||||||
private class FilterIsInstanceOperationHandler()
|
private class FilterIsInstanceOperationHandler() : IntermediateOperationBase(
|
||||||
: IntermediateOperationBase("filterIsInstance", ::FilterIsInstanceHandler,
|
"filterIsInstance", ::FilterIsInstanceHandler,
|
||||||
SimplePeekCallTraceInterpreter(), FilteredMapResolver()
|
SimplePeekCallTraceInterpreter(), FilteredMapResolver()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+12
-12
@@ -9,23 +9,23 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
interface CallTypeExtractor {
|
interface CallTypeExtractor {
|
||||||
fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes
|
fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes
|
||||||
fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes
|
fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes
|
||||||
|
|
||||||
data class IntermediateCallTypes(val typeBefore: GenericType, val typeAfter: GenericType)
|
data class IntermediateCallTypes(val typeBefore: GenericType, val typeAfter: GenericType)
|
||||||
data class TerminatorCallTypes(val typeBefore: GenericType, val resultType: GenericType)
|
data class TerminatorCallTypes(val typeBefore: GenericType, val resultType: GenericType)
|
||||||
|
|
||||||
abstract class Base : CallTypeExtractor {
|
abstract class Base : CallTypeExtractor {
|
||||||
override fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes =
|
override fun extractIntermediateCallTypes(call: KtCallExpression): IntermediateCallTypes =
|
||||||
IntermediateCallTypes(extractItemsType(call.receiverType()), extractItemsType(call.resolveType()))
|
IntermediateCallTypes(extractItemsType(call.receiverType()), extractItemsType(call.resolveType()))
|
||||||
|
|
||||||
|
|
||||||
override fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes =
|
override fun extractTerminalCallTypes(call: KtCallExpression): TerminatorCallTypes =
|
||||||
TerminatorCallTypes(extractItemsType(call.receiverType()), getResultType(call.resolveType()))
|
TerminatorCallTypes(extractItemsType(call.receiverType()), getResultType(call.resolveType()))
|
||||||
|
|
||||||
|
|
||||||
protected abstract fun extractItemsType(type: KotlinType?): GenericType
|
protected abstract fun extractItemsType(type: KotlinType?): GenericType
|
||||||
protected abstract fun getResultType(type: KotlinType): GenericType
|
protected abstract fun getResultType(type: KotlinType): GenericType
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+18
-18
@@ -18,20 +18,20 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
object KotlinPsiUtil {
|
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 {
|
fun getTypeName(type: KotlinType): String {
|
||||||
if (type is FlexibleType) {
|
if (type is FlexibleType) {
|
||||||
return WITH_TYPES_RENDERER.renderType(type.approximateFlexibleTypes())
|
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 =
|
fun KtExpression.resolveType(): KotlinType =
|
||||||
@@ -40,16 +40,16 @@ fun KtExpression.resolveType(): KotlinType =
|
|||||||
fun KtCallExpression.callName(): String = this.calleeExpression!!.text
|
fun KtCallExpression.callName(): String = this.calleeExpression!!.text
|
||||||
|
|
||||||
fun KtCallExpression.receiver(): ReceiverValue? {
|
fun KtCallExpression.receiver(): ReceiverValue? {
|
||||||
val resolvedCall = getResolvedCall(analyze()) ?: return null
|
val resolvedCall = getResolvedCall(analyze()) ?: return null
|
||||||
return resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver
|
return resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtCallExpression.previousCall(): KtCallExpression? {
|
fun KtCallExpression.previousCall(): KtCallExpression? {
|
||||||
val parent = this.parent as? KtDotQualifiedExpression ?: return null
|
val parent = this.parent as? KtDotQualifiedExpression ?: return null
|
||||||
val receiverExpression = parent.receiverExpression
|
val receiverExpression = parent.receiverExpression
|
||||||
if (receiverExpression is KtCallExpression) return receiverExpression
|
if (receiverExpression is KtCallExpression) return receiverExpression
|
||||||
if (receiverExpression is KtDotQualifiedExpression) return receiverExpression.selectorExpression as? KtCallExpression
|
if (receiverExpression is KtDotQualifiedExpression) return receiverExpression.selectorExpression as? KtCallExpression
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtCallExpression.receiverType(): KotlinType? = receiver()?.type
|
fun KtCallExpression.receiverType(): KotlinType? = receiver()?.type
|
||||||
|
|||||||
+3
-3
@@ -7,8 +7,8 @@ import org.jetbrains.kotlin.psi.KtCallExpression
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
interface StreamCallChecker {
|
interface StreamCallChecker {
|
||||||
fun isIntermediateCall(expression: KtCallExpression): Boolean
|
fun isIntermediateCall(expression: KtCallExpression): Boolean
|
||||||
fun isTerminationCall(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.
|
// 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
|
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.psi.ChainTransformer
|
||||||
import com.intellij.debugger.streams.wrapper.QualifierExpression
|
import com.intellij.debugger.streams.wrapper.QualifierExpression
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChain
|
import com.intellij.debugger.streams.wrapper.StreamChain
|
||||||
import com.intellij.debugger.streams.wrapper.impl.StreamChainImpl
|
import com.intellij.debugger.streams.wrapper.impl.StreamChainImpl
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
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.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
@@ -16,30 +16,29 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class CollectionChainTransformer : ChainTransformer<KtCallExpression> {
|
class CollectionChainTransformer : ChainTransformer<KtCallExpression> {
|
||||||
private val transformer = KotlinChainTransformerImpl(KotlinCollectionsTypeExtractor())
|
private val transformer = KotlinChainTransformerImpl(KotlinCollectionsTypeExtractor())
|
||||||
|
|
||||||
override fun transform(chainCalls: List<KtCallExpression>, context: PsiElement): StreamChain {
|
override fun transform(chainCalls: List<KtCallExpression>, context: PsiElement): StreamChain {
|
||||||
val chain = transformer.transform(chainCalls, context)
|
val chain = transformer.transform(chainCalls, context)
|
||||||
|
|
||||||
if (chainCalls.first().resolveType().isArray) {
|
if (chainCalls.first().resolveType().isArray) {
|
||||||
val qualifier = WrappedQualifier(chain.qualifierExpression)
|
val qualifier = WrappedQualifier(chain.qualifierExpression)
|
||||||
return StreamChainImpl(qualifier, chain.intermediateCalls, chain.terminationCall, chain.context)
|
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()"
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
private val KotlinType.isArray: Boolean
|
||||||
* Kotlin arrays have not {@code onEach} extension. But current implementation uses onEach to increment a time counter.
|
get() = KotlinBuiltIns.isArray(this) || KotlinBuiltIns.isPrimitiveArray(this)
|
||||||
* 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)
|
|
||||||
}
|
}
|
||||||
+54
-52
@@ -13,64 +13,66 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinCollectionChainBuilder
|
class KotlinCollectionChainBuilder
|
||||||
: KotlinChainBuilderBase(CollectionChainTransformer()) {
|
: KotlinChainBuilderBase(CollectionChainTransformer()) {
|
||||||
private companion object {
|
private companion object {
|
||||||
// TODO: Avoid enumeration of all available types
|
// TODO: Avoid enumeration of all available types
|
||||||
val SUPPORTED_RECEIVERS = setOf("kotlin.collections.Iterable", "kotlin.CharSequence", "kotlin.Array",
|
val SUPPORTED_RECEIVERS = setOf(
|
||||||
"kotlin.BooleanArray", "kotlin.ByteArray", "kotlin.ShortArray", "kotlin.CharArray", "kotlin.IntArray",
|
"kotlin.collections.Iterable", "kotlin.CharSequence", "kotlin.Array",
|
||||||
"kotlin.LongArray", "kotlin.DoubleArray", "kotlin.FloatArray")
|
"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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun createChainsBuilder(): ChainBuilder = object : ChainBuilder() {
|
private fun isCollectionTransformationCall(expression: KtCallExpression): Boolean {
|
||||||
private val previousCalls: MutableMap<KtCallExpression, KtCallExpression> = mutableMapOf()
|
val receiverType = expression.receiverType() ?: return false
|
||||||
private val visitedCalls: MutableSet<KtCallExpression> = mutableSetOf()
|
if (isTypeSuitable(receiverType)) return true
|
||||||
|
return receiverType.supertypes().any { isTypeSuitable(it) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitCallExpression(expression: KtCallExpression) {
|
override val existenceChecker: ExistenceChecker = object : ExistenceChecker() {
|
||||||
super.visitCallExpression(expression)
|
override fun visitCallExpression(expression: KtCallExpression) {
|
||||||
if (isCollectionTransformationCall(expression)) {
|
if (isFound()) return
|
||||||
visitedCalls.add(expression)
|
if (isCollectionTransformationCall(expression)) {
|
||||||
val previous = expression.previousCall()
|
fireElementFound()
|
||||||
if (previous != null && isCollectionTransformationCall(previous)) {
|
} else {
|
||||||
previousCalls[expression] = previous
|
super.visitCallExpression(expression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chains(): List<List<KtCallExpression>> {
|
override fun createChainsBuilder(): ChainBuilder = object : ChainBuilder() {
|
||||||
val notLastCalls: Set<KtCallExpression> = previousCalls.values.toSet()
|
private val previousCalls: MutableMap<KtCallExpression, KtCallExpression> = mutableMapOf()
|
||||||
return visitedCalls.filter { it !in notLastCalls }.map { buildPsiChain(it) }
|
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> {
|
private fun isTypeSuitable(type: KotlinType): Boolean =
|
||||||
val result = mutableListOf<KtCallExpression>()
|
SUPPORTED_RECEIVERS.contains(KotlinPsiUtil.getTypeWithoutTypeParameters(type))
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
+37
-37
@@ -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.
|
// 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
|
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.CallTypeExtractor
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.KotlinPsiUtil
|
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
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.ANY
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.ANY
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.NULLABLE_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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||||
|
|
||||||
@@ -15,45 +15,45 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinCollectionsTypeExtractor : CallTypeExtractor.Base() {
|
class KotlinCollectionsTypeExtractor : CallTypeExtractor.Base() {
|
||||||
private companion object {
|
private companion object {
|
||||||
val LOG = Logger.getInstance(KotlinCollectionsTypeExtractor::class.java)
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
return tryToFindElementType(type) ?: defaultType(type)
|
||||||
if (primitiveArray != null) return primitiveArray.elementType
|
}
|
||||||
|
|
||||||
return type.supertypes().asSequence()
|
override fun getResultType(type: KotlinType): GenericType {
|
||||||
.map(this::tryToFindElementType)
|
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
|
||||||
.firstOrNull()
|
return KotlinTypes.primitiveTypeByName(typeName) ?: KotlinTypes.primitiveArrayByName(typeName) ?: getAny(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun defaultType(type: KotlinType): GenericType {
|
private fun tryToFindElementType(type: KotlinType): GenericType? {
|
||||||
LOG.warn("Could not find type of items for type ${KotlinPsiUtil.getTypeName(type)}")
|
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
|
||||||
return getAny(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 fun getAny(type: KotlinType): GenericType = if (type.isMarkedNullable) NULLABLE_ANY else 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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
abstract class KotlinChainBuilderBase(private val transformer: ChainTransformer<KtCallExpression>) : StreamChainBuilder {
|
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 {
|
override fun isChainExists(startElement: PsiElement): Boolean {
|
||||||
val start = if (startElement is PsiWhiteSpace) PsiUtil.ignoreWhiteSpaces(startElement) else startElement
|
val start = if (startElement is PsiWhiteSpace) PsiUtil.ignoreWhiteSpaces(startElement) else startElement
|
||||||
var element = getLatestElementInScope(start)
|
var element = getLatestElementInScope(start)
|
||||||
existenceChecker.reset()
|
existenceChecker.reset()
|
||||||
while (element != null && !existenceChecker.isFound()) {
|
while (element != null && !existenceChecker.isFound()) {
|
||||||
existenceChecker.reset()
|
existenceChecker.reset()
|
||||||
element.accept(existenceChecker)
|
element.accept(existenceChecker)
|
||||||
element = toUpperLevel(element)
|
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> {
|
return visitor.chains().map { transformer.transform(it, startElement) }
|
||||||
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) }
|
private fun toUpperLevel(element: PsiElement): PsiElement? {
|
||||||
}
|
var current = element.parent
|
||||||
|
|
||||||
private fun toUpperLevel(element: PsiElement): PsiElement? {
|
while (current != null && !(current is KtLambdaExpression || current is KtAnonymousInitializer || current is KtObjectDeclaration)) {
|
||||||
var current = element.parent
|
current = current.parent
|
||||||
|
}
|
||||||
|
|
||||||
while (current != null && !(current is KtLambdaExpression || current is KtAnonymousInitializer || current is KtObjectDeclaration)) {
|
return getLatestElementInScope(current)
|
||||||
current = current.parent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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? {
|
val parent = current.parent
|
||||||
var current = element
|
if (parent is KtBlockExpression || parent is KtLambdaExpression) {
|
||||||
while (current != null) {
|
break
|
||||||
if (current is KtNamedFunction && current.hasInitializer()) {
|
}
|
||||||
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 fun setFound(value: Boolean) {
|
||||||
private var myIsFound: Boolean = false
|
myIsFound = value
|
||||||
fun isFound(): Boolean = myIsFound
|
}
|
||||||
fun reset() = setFound(false)
|
|
||||||
protected fun fireElementFound() = setFound(true)
|
|
||||||
|
|
||||||
private fun setFound(value: Boolean) {
|
|
||||||
myIsFound = value
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract class ChainBuilder : MyTreeVisitor() {
|
protected abstract class ChainBuilder : MyTreeVisitor() {
|
||||||
abstract fun chains(): List<List<KtCallExpression>>
|
abstract fun chains(): List<List<KtCallExpression>>
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract class MyTreeVisitor : KtTreeVisitorVoid() {
|
protected abstract class MyTreeVisitor : KtTreeVisitorVoid() {
|
||||||
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {}
|
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {}
|
||||||
override fun visitBlockExpression(expression: KtBlockExpression) {}
|
override fun visitBlockExpression(expression: KtBlockExpression) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+41
-35
@@ -25,45 +25,51 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinChainTransformerImpl(private val typeExtractor: CallTypeExtractor) : ChainTransformer<KtCallExpression> {
|
class KotlinChainTransformerImpl(private val typeExtractor: CallTypeExtractor) : ChainTransformer<KtCallExpression> {
|
||||||
override fun transform(callChain: List<KtCallExpression>, context: PsiElement): StreamChain {
|
override fun transform(callChain: List<KtCallExpression>, context: PsiElement): StreamChain {
|
||||||
val intermediateCalls = mutableListOf<IntermediateStreamCall>()
|
val intermediateCalls = mutableListOf<IntermediateStreamCall>()
|
||||||
for (call in callChain.subList(0, callChain.size - 1)) {
|
for (call in callChain.subList(0, callChain.size - 1)) {
|
||||||
val (typeBefore, typeAfter) = typeExtractor.extractIntermediateCallTypes(call)
|
val (typeBefore, typeAfter) = typeExtractor.extractIntermediateCallTypes(call)
|
||||||
intermediateCalls += IntermediateStreamCallImpl(call.callName(),
|
intermediateCalls += IntermediateStreamCallImpl(call.callName(),
|
||||||
call.valueArguments.map { createCallArgument(call, it) }, typeBefore, typeAfter, call.textRange)
|
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()
|
private fun createCallArgument(callExpression: KtCallExpression, arg: KtValueArgument): CallArgument {
|
||||||
val (typeBeforeTerminator, resultType) = typeExtractor.extractTerminalCallTypes(terminationsPsiCall)
|
fun KtValueArgument.toCallArgument(): CallArgument {
|
||||||
val terminationCall = TerminatorStreamCallImpl(terminationsPsiCall.callName(),
|
val argExpression = getArgumentExpression()!!
|
||||||
terminationsPsiCall.valueArguments.map { createCallArgument(terminationsPsiCall, it) },
|
return CallArgumentImpl(KotlinPsiUtil.getTypeName(argExpression.resolveType()), this.text)
|
||||||
typeBeforeTerminator, resultType, terminationsPsiCall.textRange)
|
}
|
||||||
|
|
||||||
val typeAfterQualifier =
|
val bindingContext = callExpression.getResolutionFacade().analyzeWithAllCompilerChecks(listOf(callExpression)).bindingContext
|
||||||
if (intermediateCalls.isEmpty()) typeBeforeTerminator else intermediateCalls.first().typeBefore
|
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return arg.toCallArgument()
|
||||||
|
val parameter = resolvedCall.getParameterForArgument(arg) ?: return arg.toCallArgument()
|
||||||
val qualifier = createQualifier(callChain.first(), typeAfterQualifier)
|
return CallArgumentImpl(KotlinPsiUtil.getTypeName(parameter.type), arg.text)
|
||||||
|
|
||||||
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
|
private fun createQualifier(expression: PsiElement, typeAfter: GenericType): QualifierExpression {
|
||||||
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return arg.toCallArgument()
|
val parent = expression.parent as? KtDotQualifiedExpression
|
||||||
val parameter = resolvedCall.getParameterForArgument(arg) ?: return arg.toCallArgument()
|
?: return QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfter)
|
||||||
return CallArgumentImpl(KotlinPsiUtil.getTypeName(parameter.type), arg.text)
|
val receiver = parent.receiverExpression
|
||||||
}
|
|
||||||
|
|
||||||
private fun createQualifier(expression: PsiElement, typeAfter: GenericType): QualifierExpression {
|
return QualifierExpressionImpl(receiver.text, receiver.textRange, typeAfter)
|
||||||
val parent = expression.parent as? KtDotQualifiedExpression
|
}
|
||||||
?: return QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfter)
|
|
||||||
val receiver = parent.receiverExpression
|
|
||||||
|
|
||||||
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.
|
// 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
|
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.KotlinPsiUtil
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.StreamCallChecker
|
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.receiverType
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.resolveType
|
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.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
@@ -13,27 +13,29 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class PackageBasedCallChecker(private val supportedPackage: String) : StreamCallChecker {
|
class PackageBasedCallChecker(private val supportedPackage: String) : StreamCallChecker {
|
||||||
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
|
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
|
||||||
return checkReceiverSupported(expression) && checkResultSupported(expression, true)
|
return checkReceiverSupported(expression) && checkResultSupported(expression, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isTerminationCall(expression: KtCallExpression): Boolean {
|
override fun isTerminationCall(expression: KtCallExpression): Boolean {
|
||||||
return checkReceiverSupported(expression) && checkResultSupported(expression, false)
|
return checkReceiverSupported(expression) && checkResultSupported(expression, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkResultSupported(expression: KtCallExpression,
|
private fun checkResultSupported(
|
||||||
shouldSupportResult: Boolean): Boolean {
|
expression: KtCallExpression,
|
||||||
val resultType = expression.resolveType()
|
shouldSupportResult: Boolean
|
||||||
return shouldSupportResult == isSupportedType(resultType)
|
): Boolean {
|
||||||
}
|
val resultType = expression.resolveType()
|
||||||
|
return shouldSupportResult == isSupportedType(resultType)
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkReceiverSupported(expression: KtCallExpression): Boolean {
|
private fun checkReceiverSupported(expression: KtCallExpression): Boolean {
|
||||||
val receiverType = expression.receiverType()
|
val receiverType = expression.receiverType()
|
||||||
return receiverType != null && isSupportedType(receiverType)
|
return receiverType != null && isSupportedType(receiverType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSupportedType(type: KotlinType): Boolean {
|
private fun isSupportedType(type: KotlinType): Boolean {
|
||||||
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
|
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
|
||||||
return StringUtil.getPackageName(typeName).startsWith(supportedPackage)
|
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.
|
// 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
|
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.StreamCallChecker
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.previousCall
|
import org.jetbrains.kotlin.idea.debugger.sequence.psi.previousCall
|
||||||
import com.intellij.debugger.streams.psi.ChainTransformer
|
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
open class TerminatedChainBuilder(transformer: ChainTransformer<KtCallExpression>,
|
open class TerminatedChainBuilder(
|
||||||
private val callChecker: StreamCallChecker
|
transformer: ChainTransformer<KtCallExpression>,
|
||||||
)
|
private val callChecker: StreamCallChecker
|
||||||
: KotlinChainBuilderBase(transformer) {
|
) : KotlinChainBuilderBase(transformer) {
|
||||||
override val existenceChecker: ExistenceChecker = MyExistenceChecker()
|
override val existenceChecker: ExistenceChecker = MyExistenceChecker()
|
||||||
|
|
||||||
override fun createChainsBuilder(): ChainBuilder = MyBuilderVisitor()
|
override fun createChainsBuilder(): ChainBuilder = MyBuilderVisitor()
|
||||||
|
|
||||||
private inner class MyExistenceChecker : ExistenceChecker() {
|
private inner class MyExistenceChecker : ExistenceChecker() {
|
||||||
override fun visitCallExpression(expression: KtCallExpression) {
|
override fun visitCallExpression(expression: KtCallExpression) {
|
||||||
if (callChecker.isTerminationCall(expression)) {
|
if (callChecker.isTerminationCall(expression)) {
|
||||||
fireElementFound()
|
fireElementFound()
|
||||||
} else {
|
} else {
|
||||||
super.visitCallExpression(expression)
|
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 fun updateCallTree(expression: KtCallExpression) {
|
private inner class MyBuilderVisitor : ChainBuilder() {
|
||||||
if (callChecker.isTerminationCall(expression)) {
|
private val myTerminationCalls = mutableSetOf<KtCallExpression>()
|
||||||
myTerminationCalls.add(expression)
|
private val myPreviousCalls = mutableMapOf<KtCallExpression, KtCallExpression>()
|
||||||
}
|
|
||||||
|
|
||||||
val parentCall = expression.previousCall()
|
override fun visitCallExpression(expression: KtCallExpression) {
|
||||||
if (parentCall is KtCallExpression && callChecker.isStreamCall(parentCall)) {
|
super.visitCallExpression(expression)
|
||||||
myPreviousCalls.put(expression, parentCall)
|
if (!myPreviousCalls.containsKey(expression) && callChecker.isStreamCall(expression)) {
|
||||||
updateCallTree(parentCall)
|
updateCallTree(expression)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
private fun updateCallTree(expression: KtCallExpression) {
|
||||||
chains.add(chain)
|
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.
|
// 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
|
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.ClassTypeImpl
|
||||||
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
|
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
|
||||||
import com.intellij.psi.CommonClassNames
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
|
import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
|
||||||
|
|
||||||
@@ -14,19 +14,19 @@ import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class JavaStreamChainTypeExtractor : CallTypeExtractor.Base() {
|
class JavaStreamChainTypeExtractor : CallTypeExtractor.Base() {
|
||||||
override fun extractItemsType(type: KotlinType?): GenericType {
|
override fun extractItemsType(type: KotlinType?): GenericType {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
return KotlinTypes.NULLABLE_ANY
|
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)) {
|
override fun getResultType(type: KotlinType): GenericType = ClassTypeImpl(KotlinPsiUtil.getTypeName(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))
|
|
||||||
}
|
}
|
||||||
+12
-12
@@ -13,19 +13,19 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class SequenceCallChecker : StreamCallChecker {
|
class SequenceCallChecker : StreamCallChecker {
|
||||||
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
|
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
|
||||||
val receiverType = expression.receiverType() ?: return false
|
val receiverType = expression.receiverType() ?: return false
|
||||||
return isSequenceInheritor(receiverType) && isSequenceInheritor(expression.resolveType())
|
return isSequenceInheritor(receiverType) && isSequenceInheritor(expression.resolveType())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isTerminationCall(expression: KtCallExpression): Boolean {
|
override fun isTerminationCall(expression: KtCallExpression): Boolean {
|
||||||
val receiverType = expression.receiverType() ?: return false
|
val receiverType = expression.receiverType() ?: return false
|
||||||
return isSequenceInheritor(receiverType) && !isSequenceInheritor(expression.resolveType())
|
return isSequenceInheritor(receiverType) && !isSequenceInheritor(expression.resolveType())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSequenceInheritor(type: KotlinType): Boolean =
|
private fun isSequenceInheritor(type: KotlinType): Boolean =
|
||||||
isSequenceType(type) || type.supertypes().any(this::isSequenceType)
|
isSequenceType(type) || type.supertypes().any(this::isSequenceType)
|
||||||
|
|
||||||
private fun isSequenceType(type: KotlinType): Boolean =
|
private fun isSequenceType(type: KotlinType): Boolean =
|
||||||
"kotlin.sequences.Sequence" == KotlinPsiUtil.getTypeWithoutTypeParameters(type)
|
"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.
|
// 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
|
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.ClassTypeImpl
|
||||||
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
|
import com.intellij.debugger.streams.trace.impl.handler.type.GenericType
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||||
|
|
||||||
@@ -14,40 +14,40 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class SequenceTypeExtractor : CallTypeExtractor.Base() {
|
class SequenceTypeExtractor : CallTypeExtractor.Base() {
|
||||||
private companion object {
|
private companion object {
|
||||||
val LOG = Logger.getInstance(SequenceTypeExtractor::class.java)
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type.supertypes().asSequence()
|
override fun extractItemsType(type: KotlinType?): GenericType {
|
||||||
.map(this::tryToFindElementType)
|
if (type == null) return KotlinTypes.NULLABLE_ANY
|
||||||
.firstOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun defaultType(type: KotlinType): GenericType {
|
return tryToFindElementType(type) ?: defaultType(type)
|
||||||
LOG.warn("Could not find type of items for type ${KotlinPsiUtil.getTypeName(type)}")
|
}
|
||||||
return if (type.isMarkedNullable) KotlinTypes.NULLABLE_ANY else KotlinTypes.ANY
|
|
||||||
}
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class ChunkedResolver : ValuesOrderResolver {
|
class ChunkedResolver : ValuesOrderResolver {
|
||||||
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
||||||
val beforeIndex = info.valuesOrderBefore
|
val beforeIndex = info.valuesOrderBefore
|
||||||
val afterIndex = info.valuesOrderAfter
|
val afterIndex = info.valuesOrderAfter
|
||||||
|
|
||||||
val invertedOrder = mutableMapOf<Int, MutableList<Int>>()
|
val invertedOrder = mutableMapOf<Int, MutableList<Int>>()
|
||||||
val beforeTimes = beforeIndex.keys.sorted().toTypedArray()
|
val beforeTimes = beforeIndex.keys.sorted().toTypedArray()
|
||||||
val afterTimes = afterIndex.keys.sorted().toTypedArray()
|
val afterTimes = afterIndex.keys.sorted().toTypedArray()
|
||||||
|
|
||||||
var beforeIx = 0
|
var beforeIx = 0
|
||||||
for (afterTime in afterTimes) {
|
for (afterTime in afterTimes) {
|
||||||
while (beforeIx < beforeTimes.size && beforeTimes[beforeIx] < afterTime) {
|
while (beforeIx < beforeTimes.size && beforeTimes[beforeIx] < afterTime) {
|
||||||
invertedOrder.computeIfAbsent(afterTime, { _ -> mutableListOf() }).add(beforeTimes[beforeIx])
|
invertedOrder.computeIfAbsent(afterTime, { _ -> mutableListOf() }).add(beforeTimes[beforeIx])
|
||||||
beforeIx += 1
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class FilteredMapResolver : ValuesOrderResolver {
|
class FilteredMapResolver : ValuesOrderResolver {
|
||||||
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
||||||
val before = info.valuesOrderBefore
|
val before = info.valuesOrderBefore
|
||||||
val after = info.valuesOrderAfter
|
val after = info.valuesOrderAfter
|
||||||
|
|
||||||
val invertedOrder = mutableMapOf<Int, Int>()
|
val invertedOrder = mutableMapOf<Int, Int>()
|
||||||
val beforeTimes = before.keys.sorted().toIntArray()
|
val beforeTimes = before.keys.sorted().toIntArray()
|
||||||
val afterTimes = after.keys.sorted().toIntArray()
|
val afterTimes = after.keys.sorted().toIntArray()
|
||||||
var beforeIndex = 0
|
var beforeIndex = 0
|
||||||
for (afterTime in afterTimes) {
|
for (afterTime in afterTimes) {
|
||||||
while (beforeIndex < beforeTimes.size && afterTime > beforeTimes[beforeIndex]) beforeIndex += 1
|
while (beforeIndex < beforeTimes.size && afterTime > beforeTimes[beforeIndex]) beforeIndex += 1
|
||||||
val beforeTime = beforeTimes[beforeIndex - 1]
|
val beforeTime = beforeTimes[beforeIndex - 1]
|
||||||
if (beforeTime < afterTime) {
|
if (beforeTime < afterTime) {
|
||||||
invertedOrder[afterTime] = beforeTime
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class WindowedResolver : ValuesOrderResolver {
|
class WindowedResolver : ValuesOrderResolver {
|
||||||
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
override fun resolve(info: TraceInfo): ValuesOrderResolver.Result {
|
||||||
val indexBefore = info.valuesOrderBefore
|
val indexBefore = info.valuesOrderBefore
|
||||||
val indexAfter = info.valuesOrderAfter
|
val indexAfter = info.valuesOrderAfter
|
||||||
|
|
||||||
val timesBefore = indexBefore.keys.sorted().toIntArray()
|
val timesBefore = indexBefore.keys.sorted().toIntArray()
|
||||||
val timesAfter = indexAfter.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 direct = mutableMapOf<TraceElement, MutableList<TraceElement>>()
|
||||||
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
|
val reverse = mutableMapOf<TraceElement, List<TraceElement>>()
|
||||||
|
|
||||||
var windowStartIndex = 0
|
var windowStartIndex = 0
|
||||||
var windowEndIndex = calcWindowSize(timesBefore, timesAfter)
|
var windowEndIndex = calcWindowSize(timesBefore, timesAfter)
|
||||||
for (timeAfter in timesAfter) {
|
for (timeAfter in timesAfter) {
|
||||||
if (windowEndIndex == timesAfter.size) {
|
if (windowEndIndex == timesAfter.size) {
|
||||||
windowStartIndex += 1
|
windowStartIndex += 1
|
||||||
} else {
|
} else {
|
||||||
while (windowEndIndex < timesBefore.size && timesBefore[windowEndIndex] < timeAfter) {
|
while (windowEndIndex < timesBefore.size && timesBefore[windowEndIndex] < timeAfter) {
|
||||||
windowStartIndex += 1
|
windowStartIndex += 1
|
||||||
windowEndIndex += 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()
|
return ValuesOrderResolver.Result.of(direct, reverse)
|
||||||
.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)
|
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 {
|
private fun emptyTransitions(indexBefore: MutableMap<Int, TraceElement>): ValuesOrderResolver.Result {
|
||||||
var size = 0
|
val direct = indexBefore.asSequence().sortedBy { it.key }.associate { it.value to emptyList<TraceElement>() }
|
||||||
while (size < before.size && before[size] < after[0]) size += 1
|
return ValuesOrderResolver.Result.of(direct, emptyMap())
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -9,6 +9,6 @@ import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class JavaPeekCallFactory : PeekCallFactory {
|
class JavaPeekCallFactory : PeekCallFactory {
|
||||||
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
|
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
|
||||||
PeekCall(lambda, elementsType)
|
PeekCall(lambda, elementsType)
|
||||||
}
|
}
|
||||||
+5
-6
@@ -11,12 +11,11 @@ import com.intellij.debugger.streams.trace.impl.handler.type.ArrayType
|
|||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinArrayVariable(override val type: ArrayType, override val name: String)
|
class KotlinArrayVariable(override val type: ArrayType, override val name: String) : VariableImpl(type, name), ArrayVariable {
|
||||||
: VariableImpl(type, name), ArrayVariable {
|
override fun get(index: Expression): Expression = TextExpression("$name[${index.toCode()}]!!")
|
||||||
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 =
|
override fun defaultDeclaration(size: Expression): VariableDeclaration =
|
||||||
KotlinVariableDeclaration(this, false, type.sizedDeclaration(size.toCode()))
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinAssignmentStatement(override val variable: Variable, override val expression: Expression) : AssignmentStatement {
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
open class KotlinCodeBlock(statementFactory: StatementFactory) : LineSeparatedCodeBlock(statementFactory) {
|
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.
|
// 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
|
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.trace.impl.handler.type.GenericType
|
||||||
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.OnEachCall
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinCollectionsPeekCallFactory : PeekCallFactory {
|
class KotlinCollectionsPeekCallFactory : PeekCallFactory {
|
||||||
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
|
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
|
||||||
OnEachCall(elementsType, lambda)
|
OnEachCall(elementsType, lambda)
|
||||||
}
|
}
|
||||||
+9
-7
@@ -9,11 +9,13 @@ import com.intellij.debugger.streams.trace.dsl.Variable
|
|||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinForEachLoop(private val iterateVariable: Variable,
|
class KotlinForEachLoop(
|
||||||
private val collection: Expression,
|
private val iterateVariable: Variable,
|
||||||
private val loopBody: ForLoopBody) : Convertable {
|
private val collection: Expression,
|
||||||
override fun toCode(indent: Int): String =
|
private val loopBody: ForLoopBody
|
||||||
"for (${iterateVariable.name} in ${collection.toCode()}) {\n".withIndent(indent) +
|
) : Convertable {
|
||||||
loopBody.toCode(indent + 1) +
|
override fun toCode(indent: Int): String =
|
||||||
"}".withIndent(indent)
|
"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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinForLoop(private val initialization: VariableDeclaration,
|
class KotlinForLoop(
|
||||||
private val condition: Expression,
|
private val initialization: VariableDeclaration,
|
||||||
private val afterThought: Expression,
|
private val condition: Expression,
|
||||||
private val loopBody: ForLoopBody) : Convertable {
|
private val afterThought: Expression,
|
||||||
override fun toCode(indent: Int): String =
|
private val loopBody: ForLoopBody
|
||||||
initialization.toCode(indent) + "\n" +
|
) : Convertable {
|
||||||
"while (${condition.toCode()}) {\n".withIndent(indent) +
|
override fun toCode(indent: Int): String =
|
||||||
loopBody.toCode(indent + 1) +
|
initialization.toCode(indent) + "\n" +
|
||||||
afterThought.toCode(indent + 1) + "\n" +
|
"while (${condition.toCode()}) {\n".withIndent(indent) +
|
||||||
"}".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.
|
// 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.Expression
|
||||||
import com.intellij.debugger.streams.trace.dsl.ForLoopBody
|
import com.intellij.debugger.streams.trace.dsl.ForLoopBody
|
||||||
import com.intellij.debugger.streams.trace.dsl.StatementFactory
|
import com.intellij.debugger.streams.trace.dsl.StatementFactory
|
||||||
import com.intellij.debugger.streams.trace.dsl.Variable
|
import com.intellij.debugger.streams.trace.dsl.Variable
|
||||||
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCodeBlock
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinForLoopBody(override val loopVariable: Variable,
|
class KotlinForLoopBody(
|
||||||
statementFactory: StatementFactory) : KotlinCodeBlock(statementFactory), ForLoopBody {
|
override val loopVariable: Variable,
|
||||||
private companion object {
|
statementFactory: StatementFactory
|
||||||
val BREAK = TextExpression("break")
|
) : 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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinIfBranch(condition: Expression, thenBlock: CodeBlock, statementFactory: StatementFactory)
|
class KotlinIfBranch(condition: Expression, thenBlock: CodeBlock, statementFactory: StatementFactory) :
|
||||||
: IfBranchBase(condition, thenBlock, statementFactory) {
|
IfBranchBase(condition, thenBlock, statementFactory) {
|
||||||
override fun toCode(indent: Int): String {
|
override fun toCode(indent: Int): String {
|
||||||
val elseBlockVar = elseBlock
|
val elseBlockVar = elseBlock
|
||||||
val ifThen = "if (${condition.toCode(0)}) {\n".withIndent(indent) +
|
val ifThen = "if (${condition.toCode(0)}) {\n".withIndent(indent) +
|
||||||
thenBlock.toCode(indent + 1) +
|
thenBlock.toCode(indent + 1) +
|
||||||
"}".withIndent(indent)
|
"}".withIndent(indent)
|
||||||
if (elseBlockVar != null) {
|
if (elseBlockVar != null) {
|
||||||
return ifThen + " else { \n" +
|
return ifThen + " else { \n" +
|
||||||
elseBlockVar.toCode(indent + 1) +
|
elseBlockVar.toCode(indent + 1) +
|
||||||
"}".withIndent(indent)
|
"}".withIndent(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifThen
|
return ifThen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-5
@@ -10,10 +10,10 @@ import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinLambda(override val variableName: String, override val body: CodeBlock) : Lambda {
|
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 =
|
override fun toCode(indent: Int): String =
|
||||||
"{ $variableName ->\n".withIndent(indent) +
|
"{ $variableName ->\n".withIndent(indent) +
|
||||||
body.toCode(indent + 1) +
|
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.Expression
|
||||||
import com.intellij.debugger.streams.trace.dsl.LambdaBody
|
import com.intellij.debugger.streams.trace.dsl.LambdaBody
|
||||||
import com.intellij.debugger.streams.trace.dsl.StatementFactory
|
import com.intellij.debugger.streams.trace.dsl.StatementFactory
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinCodeBlock
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinLambdaBody(override val lambdaArg: Expression, statementFactory: StatementFactory)
|
class KotlinLambdaBody(override val lambdaArg: Expression, statementFactory: StatementFactory) : KotlinCodeBlock(statementFactory),
|
||||||
: KotlinCodeBlock(statementFactory), LambdaBody
|
LambdaBody
|
||||||
|
|||||||
+8
-9
@@ -10,16 +10,15 @@ import com.intellij.debugger.streams.trace.impl.handler.type.ListType
|
|||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinListVariable(override val type: ListType, name: String)
|
class KotlinListVariable(override val type: ListType, name: String) : VariableImpl(type, name), ListVariable {
|
||||||
: VariableImpl(type, name), ListVariable {
|
override fun get(index: Expression): Expression = call("get", index)
|
||||||
override fun get(index: Expression): Expression = call("get", index)
|
override fun set(index: Expression, newValue: Expression): Expression = call("set", index, newValue)
|
||||||
override fun set(index: Expression, newValue: Expression): Expression = call("set", index, newValue)
|
override fun add(element: Expression): Expression = call("add", element)
|
||||||
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 =
|
override fun defaultDeclaration(): VariableDeclaration =
|
||||||
KotlinVariableDeclaration(this, false, type.defaultValue)
|
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.
|
// 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
|
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.TextExpression
|
||||||
import com.intellij.debugger.streams.trace.dsl.impl.common.MapVariableBase
|
import com.intellij.debugger.streams.trace.dsl.impl.common.MapVariableBase
|
||||||
import com.intellij.debugger.streams.trace.impl.handler.type.MapType
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinMapVariable(type: MapType, name: String) : MapVariableBase(type, name) {
|
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 =
|
override fun set(key: Expression, newValue: Expression): Expression =
|
||||||
TextExpression("${toCode()}[${key.toCode()}] = ${newValue.toCode()}")
|
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 =
|
override fun computeIfAbsent(key: Expression, supplier: Lambda): Expression =
|
||||||
TextExpression("${toCode()}.computeIfAbsent(${key.toCode()}, ${supplier.toCode()})")
|
TextExpression("${toCode()}.computeIfAbsent(${key.toCode()}, ${supplier.toCode()})")
|
||||||
|
|
||||||
override fun defaultDeclaration(isMutable: Boolean): VariableDeclaration =
|
override fun defaultDeclaration(isMutable: Boolean): VariableDeclaration =
|
||||||
KotlinVariableDeclaration(this, false, type.defaultValue)
|
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.
|
// 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
|
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.*
|
||||||
import com.intellij.debugger.streams.trace.dsl.impl.AssignmentStatement
|
import com.intellij.debugger.streams.trace.dsl.impl.AssignmentStatement
|
||||||
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
||||||
@@ -13,96 +12,99 @@ import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinStatementFactory(private val peekCallFactory: PeekCallFactory) : StatementFactory {
|
class KotlinStatementFactory(private val peekCallFactory: PeekCallFactory) : StatementFactory {
|
||||||
override fun createNewListExpression(elementType: GenericType, vararg args: Expression): Expression =
|
override fun createNewListExpression(elementType: GenericType, vararg args: Expression): Expression =
|
||||||
TextExpression("kotlin.collections.mutableListOf<${elementType.genericTypeName}>(${StatementFactory.commaSeparate(*args)})")
|
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 =
|
override fun createVariableDeclaration(variable: Variable, isMutable: Boolean): VariableDeclaration =
|
||||||
KotlinVariableDeclaration(variable, isMutable)
|
KotlinVariableDeclaration(variable, isMutable)
|
||||||
|
|
||||||
override fun createVariableDeclaration(variable: Variable, init: Expression, isMutable: Boolean): VariableDeclaration =
|
override fun createVariableDeclaration(variable: Variable, init: Expression, isMutable: Boolean): VariableDeclaration =
|
||||||
KotlinVariableDeclaration(variable, isMutable, init.toCode())
|
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 =
|
override fun createForEachLoop(iterateVariable: Variable, collection: Expression, loopBody: ForLoopBody): Convertable =
|
||||||
KotlinForEachLoop(iterateVariable, collection, loopBody)
|
KotlinForEachLoop(iterateVariable, collection, loopBody)
|
||||||
|
|
||||||
override fun createForLoop(initialization: VariableDeclaration, condition: Expression,
|
override fun createForLoop(
|
||||||
afterThought: Expression, loopBody: ForLoopBody): Convertable =
|
initialization: VariableDeclaration, condition: Expression,
|
||||||
KotlinForLoop(initialization, condition, afterThought, loopBody)
|
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 =
|
override fun createIfBranch(condition: Expression, thenBlock: CodeBlock): IfBranch =
|
||||||
KotlinIfBranch(condition, thenBlock, this)
|
KotlinIfBranch(condition, thenBlock, this)
|
||||||
|
|
||||||
override fun createAssignmentStatement(variable: Variable, expression: Expression): AssignmentStatement =
|
override fun createAssignmentStatement(variable: Variable, expression: Expression): AssignmentStatement =
|
||||||
KotlinAssignmentStatement(variable, expression)
|
KotlinAssignmentStatement(variable, expression)
|
||||||
|
|
||||||
override fun createMapVariable(keyType: GenericType, valueType: GenericType, name: String, linked: Boolean): MapVariable =
|
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)
|
KotlinMapVariable(if (linked) types.linkedMap(keyType, valueType) else types.map(keyType, valueType), name)
|
||||||
|
|
||||||
override fun createArrayVariable(elementType: GenericType, name: String): ArrayVariable =
|
override fun createArrayVariable(elementType: GenericType, name: String): ArrayVariable =
|
||||||
KotlinArrayVariable(types.array(elementType), name)
|
KotlinArrayVariable(types.array(elementType), name)
|
||||||
|
|
||||||
override fun createScope(codeBlock: CodeBlock): Convertable =
|
override fun createScope(codeBlock: CodeBlock): Convertable =
|
||||||
object : Convertable {
|
object : Convertable {
|
||||||
override fun toCode(indent: Int): String =
|
override fun toCode(indent: Int): String =
|
||||||
"run {\n".withIndent(indent) +
|
"run {\n".withIndent(indent) +
|
||||||
codeBlock.toCode(indent + 1) +
|
codeBlock.toCode(indent + 1) +
|
||||||
"}".withIndent(indent)
|
"}".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 createNewSizedArray(elementType: GenericType, size: Expression): Expression =
|
||||||
|
TextExpression(types.array(elementType).sizedDeclaration(size.toCode()))
|
||||||
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 createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
|
override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall =
|
||||||
peekCallFactory.createPeekCall(elementsType, lambda)
|
peekCallFactory.createPeekCall(elementsType, lambda)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -9,12 +9,12 @@ import com.intellij.debugger.streams.trace.dsl.impl.common.TryBlockBase
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinTryBlock(private val block: CodeBlock, statementFactory: StatementFactory) : TryBlockBase(statementFactory) {
|
class KotlinTryBlock(private val block: CodeBlock, statementFactory: StatementFactory) : TryBlockBase(statementFactory) {
|
||||||
override fun toCode(indent: Int): String {
|
override fun toCode(indent: Int): String {
|
||||||
val descriptor = myCatchDescriptor ?: error("catch block must be specified")
|
val descriptor = myCatchDescriptor ?: error("catch block must be specified")
|
||||||
return "try {\n".withIndent(indent) +
|
return "try {\n".withIndent(indent) +
|
||||||
block.toCode(indent + 1) +
|
block.toCode(indent + 1) +
|
||||||
"} catch(${descriptor.variable.name} : ${descriptor.variable.type.variableTypeName}) {\n" +
|
"} catch(${descriptor.variable.name} : ${descriptor.variable.type.variableTypeName}) {\n" +
|
||||||
descriptor.block.toCode(indent + 1) +
|
descriptor.block.toCode(indent + 1) +
|
||||||
"}".withIndent(indent)
|
"}".withIndent(indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+69
-61
@@ -8,76 +8,84 @@ import com.intellij.debugger.streams.trace.impl.handler.type.*
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
object KotlinTypes : Types {
|
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")
|
override val BOOLEAN: GenericType = ClassTypeImpl("kotlin.Boolean", "false")
|
||||||
val BYTE: GenericType = ClassTypeImpl("kotlin.Byte", "0")
|
val BYTE: GenericType = ClassTypeImpl("kotlin.Byte", "0")
|
||||||
val SHORT: GenericType = ClassTypeImpl("kotlin.Short", "0")
|
val SHORT: GenericType = ClassTypeImpl("kotlin.Short", "0")
|
||||||
val CHAR: GenericType = ClassTypeImpl("kotlin.Char", "0.toChar()")
|
val CHAR: GenericType = ClassTypeImpl("kotlin.Char", "0.toChar()")
|
||||||
override val INT: GenericType = ClassTypeImpl("kotlin.Int", "0")
|
override val INT: GenericType = ClassTypeImpl("kotlin.Int", "0")
|
||||||
override val LONG: GenericType = ClassTypeImpl("kotlin.Long", "0L")
|
override val LONG: GenericType = ClassTypeImpl("kotlin.Long", "0L")
|
||||||
val FLOAT: GenericType = ClassTypeImpl("kotlin.Float", "0.0f")
|
val FLOAT: GenericType = ClassTypeImpl("kotlin.Float", "0.0f")
|
||||||
override val DOUBLE: GenericType = ClassTypeImpl("kotlin.Double", "0.0")
|
override val DOUBLE: GenericType = ClassTypeImpl("kotlin.Double", "0.0")
|
||||||
override val STRING: GenericType = ClassTypeImpl("kotlin.String", "\"\"")
|
override val STRING: GenericType = ClassTypeImpl("kotlin.String", "\"\"")
|
||||||
override val EXCEPTION: GenericType = ClassTypeImpl("kotlin.Throwable", "kotlin.Throwable()")
|
override val EXCEPTION: GenericType = ClassTypeImpl("kotlin.Throwable", "kotlin.Throwable()")
|
||||||
override val VOID: GenericType = ClassTypeImpl("kotlin.Unit", "Unit")
|
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",
|
override val TIME: GenericType = ClassTypeImpl(
|
||||||
"java.util.concurrent.atomic.AtomicInteger()")
|
"java.util.concurrent.atomic.AtomicInteger",
|
||||||
|
"java.util.concurrent.atomic.AtomicInteger()"
|
||||||
|
)
|
||||||
|
|
||||||
override fun list(elementsType: GenericType): ListType =
|
override fun list(elementsType: GenericType): ListType =
|
||||||
ListTypeImpl(elementsType, { "kotlin.collections.MutableList<$it>" }, "kotlin.collections.mutableListOf()")
|
ListTypeImpl(elementsType, { "kotlin.collections.MutableList<$it>" }, "kotlin.collections.mutableListOf()")
|
||||||
|
|
||||||
override fun array(elementType: GenericType): ArrayType = when (elementType) {
|
override fun array(elementType: GenericType): ArrayType = when (elementType) {
|
||||||
BOOLEAN -> ArrayTypeImpl(BOOLEAN, { "kotlin.BooleanArray" }, { "kotlin.BooleanArray($it)" })
|
BOOLEAN -> ArrayTypeImpl(BOOLEAN, { "kotlin.BooleanArray" }, { "kotlin.BooleanArray($it)" })
|
||||||
BYTE -> ArrayTypeImpl(BYTE, { "kotlin.ByteArray" }, { "kotlin.ByteArray($it)" })
|
BYTE -> ArrayTypeImpl(BYTE, { "kotlin.ByteArray" }, { "kotlin.ByteArray($it)" })
|
||||||
SHORT -> ArrayTypeImpl(SHORT, { "kotlin.ShortArray" }, { "kotlin.ShortArray($it)" })
|
SHORT -> ArrayTypeImpl(SHORT, { "kotlin.ShortArray" }, { "kotlin.ShortArray($it)" })
|
||||||
CHAR -> ArrayTypeImpl(CHAR, { "kotlin.CharArray" }, { "kotlin.CharArray($it)" })
|
CHAR -> ArrayTypeImpl(CHAR, { "kotlin.CharArray" }, { "kotlin.CharArray($it)" })
|
||||||
INT -> ArrayTypeImpl(INT, { "kotlin.IntArray" }, { "kotlin.IntArray($it)" })
|
INT -> ArrayTypeImpl(INT, { "kotlin.IntArray" }, { "kotlin.IntArray($it)" })
|
||||||
LONG -> ArrayTypeImpl(LONG, { "kotlin.LongArray" }, { "kotlin.LongArray($it)" })
|
LONG -> ArrayTypeImpl(LONG, { "kotlin.LongArray" }, { "kotlin.LongArray($it)" })
|
||||||
FLOAT -> ArrayTypeImpl(FLOAT, { "kotlin.FloatArray" }, { "kotlin.FloatArray($it)" })
|
FLOAT -> ArrayTypeImpl(FLOAT, { "kotlin.FloatArray" }, { "kotlin.FloatArray($it)" })
|
||||||
DOUBLE -> ArrayTypeImpl(DOUBLE, { "kotlin.DoubleArray" }, { "kotlin.DoubleArray($it)" })
|
DOUBLE -> ArrayTypeImpl(DOUBLE, { "kotlin.DoubleArray" }, { "kotlin.DoubleArray($it)" })
|
||||||
else -> ArrayTypeImpl(nullable { elementType }, { "kotlin.Array<$it>" },
|
else -> ArrayTypeImpl(nullable { elementType }, { "kotlin.Array<$it>" },
|
||||||
{ "kotlin.arrayOfNulls<${elementType.genericTypeName}>($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)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private val primitiveTypesIndex: Map<String, GenericType> =
|
override fun map(keyType: GenericType, valueType: GenericType): MapType =
|
||||||
listOf(
|
MapTypeImpl(
|
||||||
BOOLEAN, BYTE, INT, SHORT,
|
keyType, valueType,
|
||||||
CHAR, LONG, FLOAT, DOUBLE
|
{ keys, values -> "kotlin.collections.MutableMap<$keys, $values>" },
|
||||||
)
|
"kotlin.collections.mutableMapOf()"
|
||||||
.associate { it.genericTypeName to it }
|
)
|
||||||
|
|
||||||
private val primitiveArraysIndex: Map<String, ArrayType> = primitiveTypesIndex.asSequence()
|
override fun linkedMap(keyType: GenericType, valueType: GenericType): MapType =
|
||||||
.map { array(it.value) }
|
MapTypeImpl(
|
||||||
.associate { it.genericTypeName to it }
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinVariableDeclaration(override val variable: Variable,
|
class KotlinVariableDeclaration(
|
||||||
override val isMutable: Boolean,
|
override val variable: Variable,
|
||||||
private val init: String = "") : VariableDeclaration {
|
override val isMutable: Boolean,
|
||||||
override fun toCode(indent: Int): String {
|
private val init: String = ""
|
||||||
val prefix = if (isMutable) "var" else "val"
|
) : VariableDeclaration {
|
||||||
val suffix = if (init.trim().isEmpty()) "" else " = $init"
|
override fun toCode(indent: Int): String {
|
||||||
return "$prefix ${variable.name}: ${variable.type.variableTypeName}$suffix".withIndent(indent)
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
interface PeekCallFactory {
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinTraceExpressionBuilder(dsl: Dsl, handlerFactory: HandlerFactory) : TraceExpressionBuilderBase(dsl, handlerFactory) {
|
class KotlinTraceExpressionBuilder(dsl: Dsl, handlerFactory: HandlerFactory) : TraceExpressionBuilderBase(dsl, handlerFactory) {
|
||||||
private companion object {
|
private companion object {
|
||||||
private val LOG = Logger.getInstance(KotlinTraceExpressionBuilder::class.java)
|
private val LOG = Logger.getInstance(KotlinTraceExpressionBuilder::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createTraceExpression(chain: StreamChain): String {
|
override fun createTraceExpression(chain: StreamChain): String {
|
||||||
val expression = super.createTraceExpression(chain)
|
val expression = super.createTraceExpression(chain)
|
||||||
val resultDeclaration = dsl.declaration(dsl.variable(dsl.types.nullable { ANY }, resultVariableName), dsl.nullExpression, true)
|
val resultDeclaration = dsl.declaration(dsl.variable(dsl.types.nullable { ANY }, resultVariableName), dsl.nullExpression, true)
|
||||||
val result = "${resultDeclaration.toCode()}\n " +
|
val result = "${resultDeclaration.toCode()}\n " +
|
||||||
"$expression\n" +
|
"$expression\n" +
|
||||||
resultVariableName
|
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.
|
// 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
|
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.trace.impl.handler.type.GenericType
|
||||||
import com.intellij.debugger.streams.wrapper.CallArgument
|
import com.intellij.debugger.streams.wrapper.CallArgument
|
||||||
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
||||||
import com.intellij.debugger.streams.wrapper.StreamCallType
|
import com.intellij.debugger.streams.wrapper.StreamCallType
|
||||||
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
|
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class OnEachCall(private val elementsType: GenericType, lambda: String) : IntermediateStreamCall {
|
class OnEachCall(private val elementsType: GenericType, lambda: String) : IntermediateStreamCall {
|
||||||
private val args: List<CallArgument>
|
private val args: List<CallArgument>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
args = listOf(CallArgumentImpl(KotlinTypes.ANY.genericTypeName, lambda))
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class BothSemanticHandlerWrapper(private val handler: BothSemanticsHandler) {
|
class BothSemanticHandlerWrapper(private val handler: BothSemanticsHandler) {
|
||||||
fun createIntermediateHandler(order: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
|
fun createIntermediateHandler(order: Int, call: IntermediateStreamCall, dsl: Dsl): IntermediateCallHandler =
|
||||||
CollectionIntermediateHandler(order, call, dsl, handler)
|
CollectionIntermediateHandler(order, call, dsl, handler)
|
||||||
|
|
||||||
fun createTerminatorHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
|
fun createTerminatorHandler(call: TerminatorStreamCall, resultExpression: String, dsl: Dsl): TerminatorCallHandler =
|
||||||
CollectionTerminatorHandler(call, resultExpression, dsl, handler)
|
CollectionTerminatorHandler(call, resultExpression, dsl, handler)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -10,17 +10,17 @@ import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
interface BothSemanticsHandler {
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
abstract class CollectionHandlerBase(order: Int, private val dsl: Dsl,
|
abstract class CollectionHandlerBase(
|
||||||
private val call: StreamCall, private val internalHandler: BothSemanticsHandler
|
order: Int, private val dsl: Dsl,
|
||||||
)
|
private val call: StreamCall, private val internalHandler: BothSemanticsHandler
|
||||||
: TraceHandler {
|
) : TraceHandler {
|
||||||
private val declarations: List<VariableDeclaration> = internalHandler.variablesDeclaration(call, order, dsl)
|
private val declarations: List<VariableDeclaration> = internalHandler.variablesDeclaration(call, order, dsl)
|
||||||
protected val variables: List<Variable> = declarations.map(VariableDeclaration::variable)
|
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
|
package org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.handler.collections
|
||||||
|
|
||||||
import com.intellij.debugger.streams.trace.IntermediateCallHandler
|
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
|
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,26 +15,25 @@ class CollectionIntermediateHandler(
|
|||||||
private val call: IntermediateStreamCall,
|
private val call: IntermediateStreamCall,
|
||||||
private val dsl: Dsl,
|
private val dsl: Dsl,
|
||||||
private val internalHandler: BothSemanticsHandler
|
private val internalHandler: BothSemanticsHandler
|
||||||
)
|
) : IntermediateCallHandler, CollectionHandlerBase(order, dsl, call, internalHandler) {
|
||||||
: IntermediateCallHandler, CollectionHandlerBase(order, dsl, call, internalHandler) {
|
|
||||||
|
|
||||||
override fun prepareResult(): CodeBlock {
|
override fun prepareResult(): CodeBlock {
|
||||||
return internalHandler.prepareResult(dsl, variables)
|
return internalHandler.prepareResult(dsl, variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun additionalCallsBefore(): List<IntermediateStreamCall> {
|
override fun additionalCallsBefore(): List<IntermediateStreamCall> {
|
||||||
return internalHandler.additionalCallsBefore(call, dsl)
|
return internalHandler.additionalCallsBefore(call, dsl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
|
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
|
||||||
return internalHandler.additionalCallsAfter(call, dsl)
|
return internalHandler.additionalCallsAfter(call, dsl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
|
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall {
|
||||||
return internalHandler.transformAsIntermediateCall(call, variables, dsl)
|
return internalHandler.transformAsIntermediateCall(call, variables, dsl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getResultExpression(): Expression {
|
override fun getResultExpression(): Expression {
|
||||||
return internalHandler.getResultExpression(call, dsl, variables)
|
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.trace.dsl.impl.TextExpression
|
||||||
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
import com.intellij.debugger.streams.wrapper.IntermediateStreamCall
|
||||||
import com.intellij.debugger.streams.wrapper.TerminatorStreamCall
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class CollectionTerminatorHandler(private val call: TerminatorStreamCall,
|
class CollectionTerminatorHandler(
|
||||||
private val resultExpression: String,
|
private val call: TerminatorStreamCall,
|
||||||
private val dsl: Dsl,
|
private val resultExpression: String,
|
||||||
private val internalHandler: BothSemanticsHandler
|
private val dsl: Dsl,
|
||||||
)
|
private val internalHandler: BothSemanticsHandler
|
||||||
: TerminatorCallHandler, CollectionHandlerBase(Int.MAX_VALUE, dsl, call, internalHandler) {
|
) : TerminatorCallHandler, CollectionHandlerBase(Int.MAX_VALUE, dsl, call, internalHandler) {
|
||||||
|
|
||||||
override fun prepareResult(): CodeBlock {
|
override fun prepareResult(): CodeBlock {
|
||||||
val prepareResult = internalHandler.prepareResult(dsl, variables)
|
val prepareResult = internalHandler.prepareResult(dsl, variables)
|
||||||
val additionalCallsAfter = internalHandler.additionalCallsAfter(call, dsl)
|
val additionalCallsAfter = internalHandler.additionalCallsAfter(call, dsl)
|
||||||
if (additionalCallsAfter.isEmpty()) {
|
if (additionalCallsAfter.isEmpty()) {
|
||||||
return prepareResult
|
return prepareResult
|
||||||
|
}
|
||||||
|
|
||||||
|
return dsl.block {
|
||||||
|
+createCallAfterExpression(additionalCallsAfter)
|
||||||
|
add(prepareResult)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dsl.block {
|
override fun additionalCallsBefore(): List<IntermediateStreamCall> =
|
||||||
+createCallAfterExpression(additionalCallsAfter)
|
internalHandler.additionalCallsBefore(call, dsl)
|
||||||
add(prepareResult)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun additionalCallsBefore(): List<IntermediateStreamCall> =
|
override fun transformCall(call: TerminatorStreamCall): TerminatorStreamCall {
|
||||||
internalHandler.additionalCallsBefore(call, dsl)
|
return internalHandler.transformAsTerminalCall(call, variables, 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class FilterCallHandler : BothSemanticsHandler {
|
class FilterCallHandler : BothSemanticsHandler {
|
||||||
private companion object {
|
private companion object {
|
||||||
val VALUES_ARRAY_NAME = "objectsInPredicate"
|
val VALUES_ARRAY_NAME = "objectsInPredicate"
|
||||||
val PREDICATE_RESULT_ARRAY_NAME = "filteringResults"
|
val PREDICATE_RESULT_ARRAY_NAME = "filteringResults"
|
||||||
|
|
||||||
fun oldPredicateVariableName(order: Int): String = "filterPredicate" + order
|
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))
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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 listOf(
|
||||||
return dsl.newArray(dsl.types.ANY, TextExpression(VALUES_ARRAY_NAME), TextExpression(PREDICATE_RESULT_ARRAY_NAME))
|
timeToObjectMap.defaultDeclaration(), predicateResultMap.defaultDeclaration(),
|
||||||
}
|
dsl.declaration(oldFilterPredicate, TextExpression(predicate.text), false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun transformAsIntermediateCall(call: IntermediateStreamCall, variables: List<Variable>, dsl: Dsl): IntermediateStreamCall {
|
override fun prepareResult(dsl: Dsl, variables: List<Variable>): CodeBlock {
|
||||||
return call.withArgs(listOf(createNewPredicate(variables, dsl)))
|
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 {
|
override fun additionalCallsBefore(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
|
||||||
return call.withArgs(listOf(createNewPredicate(variables, dsl)))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createNewPredicate(variables: List<Variable>, dsl: Dsl): CallArgument {
|
override fun additionalCallsAfter(call: StreamCall, dsl: Dsl): List<IntermediateStreamCall> = emptyList()
|
||||||
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)
|
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.
|
// 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
|
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.CodeBlock
|
||||||
import com.intellij.debugger.streams.trace.dsl.Dsl
|
import com.intellij.debugger.streams.trace.dsl.Dsl
|
||||||
import com.intellij.debugger.streams.trace.dsl.Expression
|
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.CallArgumentImpl
|
||||||
import com.intellij.debugger.streams.wrapper.impl.IntermediateStreamCallImpl
|
import com.intellij.debugger.streams.wrapper.impl.IntermediateStreamCallImpl
|
||||||
import com.intellij.openapi.util.TextRange.EMPTY_RANGE
|
import com.intellij.openapi.util.TextRange.EMPTY_RANGE
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class FilterIsInstanceHandler(num: Int, call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
|
class FilterIsInstanceHandler(num: Int, call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
|
||||||
private companion object {
|
private companion object {
|
||||||
fun createHandler(num: Int, call: IntermediateStreamCall, dsl: Dsl): HandlerBase.Intermediate =
|
fun createHandler(num: Int, call: IntermediateStreamCall, dsl: Dsl): HandlerBase.Intermediate =
|
||||||
if (call.arguments.isEmpty()) MyWithGenericsHandler(num, call, dsl)
|
if (call.arguments.isEmpty()) MyWithGenericsHandler(num, call, dsl)
|
||||||
else PeekTraceHandler(num, call.name, call.typeBefore, call.typeAfter, dsl)
|
else PeekTraceHandler(num, call.name, call.typeBefore, call.typeAfter, dsl)
|
||||||
}
|
|
||||||
|
|
||||||
private val filterHandler = createHandler(num, call, dsl)
|
|
||||||
|
|
||||||
// use explicit delegation to avoid issues with navigation
|
|
||||||
|
|
||||||
override fun additionalCallsAfter(): MutableList<IntermediateStreamCall> = filterHandler.additionalCallsAfter()
|
|
||||||
override fun additionalCallsBefore(): List<IntermediateStreamCall> = filterHandler.additionalCallsBefore()
|
|
||||||
override fun additionalVariablesDeclaration(): List<VariableDeclaration> = filterHandler.additionalVariablesDeclaration()
|
|
||||||
override fun getResultExpression(): Expression = filterHandler.resultExpression
|
|
||||||
override fun prepareResult(): CodeBlock = filterHandler.prepareResult()
|
|
||||||
override fun transformCall(call: IntermediateStreamCall): IntermediateStreamCall = filterHandler.transformCall(call)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transforms filterIsInstance<ClassName> -> filter { it is ClassName }.map { it as ClassName }
|
|
||||||
*/
|
|
||||||
private class MyWithGenericsHandler(num: Int, private val call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
|
|
||||||
private val peekHandler = PeekTraceHandler(num, "filterIsInstance", call.typeBefore, call.typeAfter, dsl)
|
|
||||||
override fun additionalCallsAfter(): List<IntermediateStreamCall> {
|
|
||||||
val mapperType = functionalType(call.typeBefore.genericTypeName, call.typeAfter.genericTypeName)
|
|
||||||
val mapper = CallArgumentImpl(mapperType, "{ x -> x as ${call.typeAfter.genericTypeName} }")
|
|
||||||
val result: MutableList<IntermediateStreamCall> = mutableListOf(syntheticMapCall(mapper))
|
|
||||||
result.addAll(peekHandler.additionalCallsAfter())
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun additionalCallsBefore(): List<IntermediateStreamCall> = peekHandler.additionalCallsBefore()
|
private val filterHandler = createHandler(num, call, dsl)
|
||||||
|
|
||||||
override fun additionalVariablesDeclaration(): List<VariableDeclaration> =
|
// use explicit delegation to avoid issues with navigation
|
||||||
peekHandler.additionalVariablesDeclaration()
|
|
||||||
|
|
||||||
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 {
|
override fun additionalCallsBefore(): List<IntermediateStreamCall> = peekHandler.additionalCallsBefore()
|
||||||
val typeAfter = call.typeAfter.genericTypeName
|
|
||||||
val predicateType = functionalType(typeAfter, KotlinTypes.BOOLEAN.genericTypeName)
|
override fun additionalVariablesDeclaration(): List<VariableDeclaration> =
|
||||||
val predicate = CallArgumentImpl(predicateType, " { x -> x is $typeAfter} ")
|
peekHandler.additionalVariablesDeclaration()
|
||||||
return syntheticFilterCall(predicate)
|
|
||||||
|
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.
|
// 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
|
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.*
|
||||||
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
import com.intellij.debugger.streams.trace.dsl.impl.TextExpression
|
||||||
import com.intellij.debugger.streams.trace.impl.handler.type.ClassTypeImpl
|
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.IntermediateStreamCall
|
||||||
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
|
import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl
|
||||||
import com.intellij.debugger.streams.wrapper.impl.IntermediateStreamCallImpl
|
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
|
* Based on com.intellij.debugger.streams.trace.impl.handler.unified.DistinctByKeyHandler
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class KotlinDistinctByHandler(callNumber: Int, private val call: IntermediateStreamCall, dsl: Dsl)
|
class KotlinDistinctByHandler(callNumber: Int, private val call: IntermediateStreamCall, dsl: Dsl) : HandlerBase.Intermediate(dsl) {
|
||||||
: HandlerBase.Intermediate(dsl) {
|
private companion object {
|
||||||
private companion object {
|
val KEY_EXTRACTOR_VARIABLE_PREFIX = "keyExtractor"
|
||||||
val KEY_EXTRACTOR_VARIABLE_PREFIX = "keyExtractor"
|
val TRANSITIONS_ARRAY_NAME = "transitionsArray"
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callsAfter.add(dsl.createPeekCall(call.typeAfter, lambda.toCode()))
|
private val peekHandler = PeekTraceHandler(callNumber, "distinctBy", call.typeBefore, call.typeAfter, dsl)
|
||||||
return callsAfter
|
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) {
|
init {
|
||||||
block.forLoop(declaration(variable(types.INT, "i"), TextExpression("0"), true),
|
val arguments = call.arguments
|
||||||
TextExpression("i < ${border.toCode()}"),
|
assert(arguments.isNotEmpty(), { "Key extractor is not specified" })
|
||||||
TextExpression("i = i + 1"), init)
|
keyExtractor = arguments.first()
|
||||||
}
|
extractorVariable = dsl.variable(ClassTypeImpl(keyExtractor.type), KEY_EXTRACTOR_VARIABLE_PREFIX + callNumber)
|
||||||
|
}
|
||||||
|
|
||||||
private fun IntermediateStreamCall.updateArguments(args: List<CallArgument>): IntermediateStreamCall =
|
override fun additionalVariablesDeclaration(): List<VariableDeclaration> {
|
||||||
IntermediateStreamCallImpl("distinctBy", args, typeBefore, typeAfter, textRange)
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class FilterTraceInterpreter(private val predicateValueToAccept: Boolean) : CallTraceInterpreter {
|
class FilterTraceInterpreter(private val predicateValueToAccept: Boolean) : CallTraceInterpreter {
|
||||||
override fun resolve(call: StreamCall, value: Value): TraceInfo {
|
override fun resolve(call: StreamCall, value: Value): TraceInfo {
|
||||||
if (value !is ArrayReference) throw UnexpectedValueTypeException("array reference excepted, but actual: ${value.type().name()}")
|
if (value !is ArrayReference) throw UnexpectedValueTypeException("array reference excepted, but actual: ${value.type().name()}")
|
||||||
val before = resolveValuesBefore(value.getValue(0))
|
val before = resolveValuesBefore(value.getValue(0))
|
||||||
val filteringMap = value.getValue(1)
|
val filteringMap = value.getValue(1)
|
||||||
val after = resolveValuesAfter(before, filteringMap)
|
val after = resolveValuesAfter(before, filteringMap)
|
||||||
|
|
||||||
return ValuesOrder(call, before, after)
|
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 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> {
|
return InterpreterUtil.createIndexByTime(result)
|
||||||
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 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> {
|
return result
|
||||||
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
|
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 {
|
object InterpreterUtil {
|
||||||
|
|
||||||
fun extractMap(value: Value): MapRepresentation {
|
fun extractMap(value: Value): MapRepresentation {
|
||||||
if (value !is ArrayReference || value.length() != 2) {
|
if (value !is ArrayReference || value.length() != 2) {
|
||||||
throw UnexpectedValueException("Map should be represented by array with two nested arrays: keys and values")
|
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)
|
fun createIndexByTime(elements: List<TraceElement>): Map<Int, TraceElement> =
|
||||||
val values = value.getValue(1)
|
elements.associate { elem -> elem.time to elem }
|
||||||
|
|
||||||
if (keys !is ArrayReference || values !is ArrayReference || keys.length() != values.length()) {
|
data class MapRepresentation(val keys: ArrayReference, val values: ArrayReference)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-9
@@ -8,17 +8,18 @@ import com.intellij.debugger.streams.wrapper.StreamCall
|
|||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class ValuesOrder(private val call: StreamCall,
|
class ValuesOrder(
|
||||||
private val before: Map<Int, TraceElement>,
|
private val call: StreamCall,
|
||||||
private val after: Map<Int, TraceElement>)
|
private val before: Map<Int, TraceElement>,
|
||||||
: TraceInfo {
|
private val after: Map<Int, TraceElement>
|
||||||
override fun getValuesOrderBefore(): Map<Int, TraceElement> = before
|
) : 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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
abstract class KotlinPsiChainBuilderTestCase(private val relativePath: String) : StreamChainBuilderTestCase() {
|
abstract class KotlinPsiChainBuilderTestCase(private val relativePath: String) : StreamChainBuilderTestCase() {
|
||||||
override fun getTestDataPath(): String =
|
override fun getTestDataPath(): String =
|
||||||
Paths.get(File("").absolutePath, "idea/testData/debugger/sequence/psi/$relativeTestPath/").toString()
|
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"
|
|
||||||
|
|
||||||
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() {
|
protected abstract fun doTest()
|
||||||
doKotlinTearDown(LightPlatformTestCase.getProject(), { super.tearDown() })
|
|
||||||
}
|
|
||||||
|
|
||||||
override final fun getRelativeTestPath(): String = relativePath
|
override fun tearDown() {
|
||||||
|
doKotlinTearDown(LightPlatformTestCase.getProject(), { super.tearDown() })
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runnable()
|
override final fun getRelativeTestPath(): String = relativePath
|
||||||
|
|
||||||
// Base tearDown() invalidates builtins and std-lib files. Restore them with brute force.
|
override fun setUp() {
|
||||||
fun unInvalidateFile(file: PsiFileImpl) {
|
super.setUp()
|
||||||
val field = PsiFileImpl::class.java.getDeclaredField("myInvalidated")!!
|
ApplicationManager.getApplication().runWriteAction {
|
||||||
field.isAccessible = true
|
if (ProjectLibraryTable.getInstance(LightPlatformTestCase.getProject()).getLibraryByName(stdLibName) == null) {
|
||||||
field.set(file, false)
|
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")
|
override fun getProjectJDK(): Sdk {
|
||||||
|
return PluginTestCaseBase.mockJdk9()
|
||||||
abstract class Positive(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
|
|
||||||
override fun doTest() {
|
|
||||||
val chains = buildChains()
|
|
||||||
checkChains(chains)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun checkChains(chains: MutableList<StreamChain>) {
|
private fun doKotlinTearDown(project: Project, runnable: () -> Unit) {
|
||||||
TestCase.assertFalse(chains.isEmpty())
|
unInvalidateBuiltinsAndStdLib(project) {
|
||||||
|
runnable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Negative(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
|
private fun unInvalidateBuiltinsAndStdLib(project: Project, runnable: () -> Unit) {
|
||||||
override fun doTest() {
|
val stdLibViewProviders = HashSet<KotlinDecompiledFileViewProvider>()
|
||||||
val elementAtCaret = configureAndGetElementAtCaret()
|
val vFileToViewProviderMap =
|
||||||
TestCase.assertFalse(chainBuilder.isChainExists(elementAtCaret))
|
((PsiManager.getInstance(project) as PsiManagerEx).fileManager as FileManagerImpl).vFileToViewProviderMap
|
||||||
TestCase.assertTrue(chainBuilder.build(elementAtCaret).isEmpty())
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
abstract class AbstractCollectionTraceTestCase : KotlinTraceTestCase() {
|
abstract class AbstractCollectionTraceTestCase : KotlinTraceTestCase() {
|
||||||
override val librarySupportProvider: LibrarySupportProvider = KotlinCollectionSupportProvider()
|
override val librarySupportProvider: LibrarySupportProvider = KotlinCollectionSupportProvider()
|
||||||
}
|
}
|
||||||
+2
-1
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibraryS
|
|||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
abstract class AbstractJavaStreamTraceTestCase: KotlinTraceTestCase() {
|
@Suppress("unused")
|
||||||
|
abstract class AbstractJavaStreamTraceTestCase : KotlinTraceTestCase() {
|
||||||
override val librarySupportProvider: LibrarySupportProvider = JavaStandardLibrarySupportProvider()
|
override val librarySupportProvider: LibrarySupportProvider = JavaStandardLibrarySupportProvider()
|
||||||
}
|
}
|
||||||
Generated
+26
-9
@@ -15,7 +15,9 @@ import org.junit.runner.RunWith;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.regex.Pattern;
|
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")
|
@SuppressWarnings("all")
|
||||||
@TestMetadata("idea/testData/debugger/tinyApp/src/streams/sequence")
|
@TestMetadata("idea/testData/debugger/tinyApp/src/streams/sequence")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@@ -26,7 +28,8 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInSequence() throws Exception {
|
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")
|
@TestMetadata("idea/testData/debugger/tinyApp/src/streams/sequence/append")
|
||||||
@@ -38,7 +41,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInAppend() throws Exception {
|
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")
|
@TestMetadata("PlusArray.kt")
|
||||||
@@ -71,7 +76,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInDistinct() throws Exception {
|
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")
|
@TestMetadata("Distinct.kt")
|
||||||
@@ -119,7 +126,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInFilter() throws Exception {
|
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")
|
@TestMetadata("Drop.kt")
|
||||||
@@ -182,7 +191,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInFlatMap() throws Exception {
|
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")
|
@TestMetadata("FlatMap.kt")
|
||||||
@@ -205,7 +216,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInMap() throws Exception {
|
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")
|
@TestMetadata("Map.kt")
|
||||||
@@ -238,7 +251,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInMisc() throws Exception {
|
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")
|
@TestMetadata("AsSequence.kt")
|
||||||
@@ -326,7 +341,9 @@ public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInSort() throws Exception {
|
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")
|
@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.
|
// 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
|
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 com.intellij.debugger.streams.trace.impl.handler.type.GenericType
|
||||||
|
import org.jetbrains.kotlin.idea.debugger.sequence.KotlinPsiChainBuilderTestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
abstract class TypedChainTestCase(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
|
abstract class TypedChainTestCase(relativePath: String) : KotlinPsiChainBuilderTestCase(relativePath) {
|
||||||
|
|
||||||
protected fun doTest(producerAfterType: GenericType,
|
protected fun doTest(
|
||||||
vararg intermediateAfterTypes: GenericType) {
|
producerAfterType: GenericType,
|
||||||
val elementAtCaret = configureAndGetElementAtCaret()
|
vararg intermediateAfterTypes: GenericType
|
||||||
assertNotNull(elementAtCaret)
|
) {
|
||||||
val chains = chainBuilder.build(elementAtCaret)
|
val elementAtCaret = configureAndGetElementAtCaret()
|
||||||
assertFalse(chains.isEmpty())
|
assertNotNull(elementAtCaret)
|
||||||
val chain = chains[0]
|
val chains = chainBuilder.build(elementAtCaret)
|
||||||
val intermediateCalls = chain.intermediateCalls
|
assertFalse(chains.isEmpty())
|
||||||
assertEquals(intermediateAfterTypes.size, intermediateCalls.size)
|
val chain = chains[0]
|
||||||
assertEquals(producerAfterType, chain.qualifierExpression.typeAfter)
|
val intermediateCalls = chain.intermediateCalls
|
||||||
|
assertEquals(intermediateAfterTypes.size, intermediateCalls.size)
|
||||||
|
assertEquals(producerAfterType, chain.qualifierExpression.typeAfter)
|
||||||
|
|
||||||
if (intermediateAfterTypes.isNotEmpty()) {
|
if (intermediateAfterTypes.isNotEmpty()) {
|
||||||
assertEquals(producerAfterType, intermediateCalls[0].typeBefore)
|
assertEquals(producerAfterType, intermediateCalls[0].typeBefore)
|
||||||
for (i in 0 until intermediateAfterTypes.size - 1) {
|
for (i in 0 until intermediateAfterTypes.size - 1) {
|
||||||
assertEquals(intermediateAfterTypes[i], intermediateCalls[i].typeAfter)
|
assertEquals(intermediateAfterTypes[i], intermediateCalls[i].typeAfter)
|
||||||
assertEquals(intermediateAfterTypes[i], intermediateCalls[i + 1].typeBefore)
|
assertEquals(intermediateAfterTypes[i], intermediateCalls[i + 1].typeBefore)
|
||||||
}
|
}
|
||||||
|
|
||||||
val lastAfterType = intermediateAfterTypes[intermediateAfterTypes.size - 1]
|
val lastAfterType = intermediateAfterTypes[intermediateAfterTypes.size - 1]
|
||||||
assertEquals(lastAfterType, chain.terminationCall.typeBefore)
|
assertEquals(lastAfterType, chain.terminationCall.typeBefore)
|
||||||
val lastCall = intermediateCalls[intermediateCalls.size - 1]
|
val lastCall = intermediateCalls[intermediateCalls.size - 1]
|
||||||
assertEquals(lastAfterType, lastCall.typeAfter)
|
assertEquals(lastAfterType, lastCall.typeAfter)
|
||||||
} else {
|
} else {
|
||||||
assertEquals(producerAfterType, chain.terminationCall.typeBefore)
|
assertEquals(producerAfterType, chain.terminationCall.typeBefore)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun doTest() {
|
override fun doTest() {
|
||||||
fail("Use doTest(producerAfterType, vararg intermediateAfterTypes)")
|
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.
|
// 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
|
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.KotlinPsiChainBuilderTestCase
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.lib.collections.KotlinCollectionSupportProvider
|
import org.jetbrains.kotlin.idea.debugger.sequence.lib.collections.KotlinCollectionSupportProvider
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class PositiveCollectionBuildTest : KotlinPsiChainBuilderTestCase.Positive("collection/positive") {
|
class PositiveCollectionBuildTest : KotlinPsiChainBuilderTestCase.Positive("collection/positive") {
|
||||||
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
|
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
|
||||||
|
|
||||||
fun testIntermediateIsLastCall() = doTest()
|
fun testIntermediateIsLastCall() = doTest()
|
||||||
fun testOnlyFilterCall() = doTest()
|
fun testOnlyFilterCall() = doTest()
|
||||||
fun testTerminationCallUsed() = doTest()
|
fun testTerminationCallUsed() = doTest()
|
||||||
fun testOnlyTerminationCallUsed() = 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.
|
// 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
|
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.lib.collections.KotlinCollectionSupportProvider
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
|
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class TypedCollectionChainTest : TypedChainTestCase("collection/positive/types") {
|
class TypedCollectionChainTest : TypedChainTestCase("collection/positive/types") {
|
||||||
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
|
override val kotlinChainBuilder: StreamChainBuilder = KotlinCollectionSupportProvider().chainBuilder
|
||||||
|
|
||||||
fun testAny() = doTest(KotlinTypes.ANY)
|
fun testAny() = doTest(KotlinTypes.ANY)
|
||||||
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
|
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
|
||||||
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testByte() = doTest(KotlinTypes.BYTE)
|
fun testByte() = doTest(KotlinTypes.BYTE)
|
||||||
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testShort() = doTest(KotlinTypes.SHORT)
|
fun testShort() = doTest(KotlinTypes.SHORT)
|
||||||
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testInt() = doTest(KotlinTypes.INT)
|
fun testInt() = doTest(KotlinTypes.INT)
|
||||||
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testLong() = doTest(KotlinTypes.LONG)
|
fun testLong() = doTest(KotlinTypes.LONG)
|
||||||
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testFloat() = doTest(KotlinTypes.FLOAT)
|
fun testFloat() = doTest(KotlinTypes.FLOAT)
|
||||||
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testDouble() = doTest(KotlinTypes.DOUBLE)
|
fun testDouble() = doTest(KotlinTypes.DOUBLE)
|
||||||
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testChar() = doTest(KotlinTypes.CHAR)
|
fun testChar() = doTest(KotlinTypes.CHAR)
|
||||||
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
|
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
|
||||||
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
|
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
|
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
|
||||||
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
|
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
|
||||||
|
|
||||||
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
||||||
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
|
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
||||||
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
|
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
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class AmbiguousChainsTest : PositiveJavaStreamTest("ambiguous") {
|
class AmbiguousChainsTest : PositiveJavaStreamTest("ambiguous") {
|
||||||
fun testSimpleExpression() = doTest(2)
|
fun testSimpleExpression() = doTest(2)
|
||||||
|
|
||||||
fun testNestedExpression() = doTest(3)
|
fun testNestedExpression() = doTest(3)
|
||||||
fun testSimpleFunctionParameter() = doTest(2)
|
fun testSimpleFunctionParameter() = doTest(2)
|
||||||
fun testNestedFunctionParameters() = doTest(3)
|
fun testNestedFunctionParameters() = doTest(3)
|
||||||
fun testNestedFunctionParametersReversed() = doTest(3)
|
fun testNestedFunctionParametersReversed() = doTest(3)
|
||||||
|
|
||||||
fun testStreamProducerParameter() = doTest(2)
|
fun testStreamProducerParameter() = doTest(2)
|
||||||
fun testStreamIntermediateCallParameter() = doTest(2)
|
fun testStreamIntermediateCallParameter() = doTest(2)
|
||||||
fun testStreamTerminatorParameter() = doTest(2)
|
fun testStreamTerminatorParameter() = doTest(2)
|
||||||
fun testStreamAllPositions() = doTest(4)
|
fun testStreamAllPositions() = doTest(4)
|
||||||
|
|
||||||
fun testNestedStreamProducerParameter() = doTest(3)
|
fun testNestedStreamProducerParameter() = doTest(3)
|
||||||
fun testNestedStreamIntermediateCallParameter() = doTest(3)
|
fun testNestedStreamIntermediateCallParameter() = doTest(3)
|
||||||
fun testNestedStreamTerminatorCallParameter() = doTest(3)
|
fun testNestedStreamTerminatorCallParameter() = doTest(3)
|
||||||
|
|
||||||
fun testNestedCallInLambda() = doTest(2)
|
fun testNestedCallInLambda() = doTest(2)
|
||||||
fun testNestedCallInAnonymous() = doTest(2)
|
fun testNestedCallInAnonymous() = doTest(2)
|
||||||
|
|
||||||
fun testLinkedChain() = doTest(3)
|
fun testLinkedChain() = doTest(3)
|
||||||
|
|
||||||
private fun doTest(chainsCount: Int) {
|
private fun doTest(chainsCount: Int) {
|
||||||
val chains = buildChains()
|
val chains = buildChains()
|
||||||
assertEquals(chainsCount, chains.size)
|
assertEquals(chainsCount, chains.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+21
-21
@@ -5,37 +5,37 @@ package org.jetbrains.kotlin.idea.debugger.sequence.psi.java
|
|||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class LocationPositiveChainTest : PositiveJavaStreamTest("location") {
|
class LocationPositiveChainTest : PositiveJavaStreamTest("location") {
|
||||||
fun testAnonymousBody() = doTest()
|
fun testAnonymousBody() = doTest()
|
||||||
|
|
||||||
fun testAssignExpression() = doTest()
|
fun testAssignExpression() = doTest()
|
||||||
|
|
||||||
fun testFirstParameterOfFunction() = doTest()
|
fun testFirstParameterOfFunction() = doTest()
|
||||||
fun testLambdaBody() = doTest()
|
fun testLambdaBody() = doTest()
|
||||||
|
|
||||||
fun testParameterInAssignExpression() = doTest()
|
fun testParameterInAssignExpression() = doTest()
|
||||||
fun testParameterInReturnExpression() = 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 testBetweenChainCallsBeforeDot() = doTest()
|
||||||
fun testBetweenChainCallsAfterDot() = doTest()
|
fun testBetweenChainCallsAfterDot() = doTest()
|
||||||
|
|
||||||
fun testInEmptyParameterList() = doTest()
|
fun testInEmptyParameterList() = doTest()
|
||||||
|
|
||||||
fun testBetweenParametersBeforeComma() = doTest()
|
fun testBetweenParametersBeforeComma() = doTest()
|
||||||
fun testBetweenParametersAfterComma() = doTest()
|
fun testBetweenParametersAfterComma() = doTest()
|
||||||
|
|
||||||
fun testInAnyLambda() = doTest()
|
fun testInAnyLambda() = doTest()
|
||||||
fun testInAnyAnonymous() = doTest()
|
fun testInAnyAnonymous() = doTest()
|
||||||
fun testInString() = doTest()
|
fun testInString() = doTest()
|
||||||
fun testInVariableName() = doTest()
|
fun testInVariableName() = doTest()
|
||||||
fun testInMethodReference() = 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.
|
// 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
|
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.KotlinPsiChainBuilderTestCase
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
|
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class NegativeJavaStreamTest : KotlinPsiChainBuilderTestCase.Negative("streams/negative") {
|
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 testBreakpointOnMethod() = doTest()
|
||||||
fun testBreakpointOnIfCondition() = doTest()
|
fun testBreakpointOnIfCondition() = doTest()
|
||||||
fun testBreakpointOnNewScope() = doTest()
|
fun testBreakpointOnNewScope() = doTest()
|
||||||
fun testBreakpointOnElseBranch() = doTest()
|
fun testBreakpointOnElseBranch() = doTest()
|
||||||
|
|
||||||
fun testInLambda() = doTest()
|
fun testInLambda() = doTest()
|
||||||
fun testInLambdaWithBody() = doTest()
|
fun testInLambdaWithBody() = doTest()
|
||||||
fun testInAnonymous() = doTest()
|
fun testInAnonymous() = doTest()
|
||||||
|
|
||||||
fun testAfterStatement() = doTest()
|
fun testAfterStatement() = doTest()
|
||||||
|
|
||||||
fun testInPreviousStatement() = doTest()
|
fun testInPreviousStatement() = doTest()
|
||||||
fun testInNextStatement() = 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.
|
// 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
|
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.KotlinPsiChainBuilderTestCase
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
|
import org.jetbrains.kotlin.idea.debugger.sequence.lib.java.JavaStandardLibrarySupportProvider
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
abstract class PositiveJavaStreamTest(subDirectory: String) : KotlinPsiChainBuilderTestCase.Positive("streams/positive/$subDirectory") {
|
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.
|
// 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
|
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.lib.java.JavaStandardLibrarySupportProvider
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
|
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.DOUBLE
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.INT
|
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.LONG
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.NULLABLE_ANY
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes.NULLABLE_ANY
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class TypedJavaChainTest : TypedChainTestCase("streams/positive/types") {
|
class TypedJavaChainTest : TypedChainTestCase("streams/positive/types") {
|
||||||
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
|
override val kotlinChainBuilder: StreamChainBuilder = JavaStandardLibrarySupportProvider().chainBuilder
|
||||||
|
|
||||||
fun testOneCall() = doTest(NULLABLE_ANY)
|
fun testOneCall() = doTest(NULLABLE_ANY)
|
||||||
fun testMapToSame() = doTest(NULLABLE_ANY, NULLABLE_ANY)
|
fun testMapToSame() = doTest(NULLABLE_ANY, NULLABLE_ANY)
|
||||||
fun testPrimitiveOneCall() = doTest(INT)
|
fun testPrimitiveOneCall() = doTest(INT)
|
||||||
fun testPrimitiveMapToSame() = doTest(LONG, LONG)
|
fun testPrimitiveMapToSame() = doTest(LONG, LONG)
|
||||||
|
|
||||||
fun testMapToPrimitive() = doTest(NULLABLE_ANY, DOUBLE)
|
fun testMapToPrimitive() = doTest(NULLABLE_ANY, DOUBLE)
|
||||||
fun testMapToObj() = doTest(DOUBLE, NULLABLE_ANY)
|
fun testMapToObj() = doTest(DOUBLE, NULLABLE_ANY)
|
||||||
fun testMapPrimitiveToPrimitive() = doTest(LONG, INT)
|
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.
|
// 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
|
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.lib.sequence.KotlinSequenceSupportProvider
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
|
import org.jetbrains.kotlin.idea.debugger.sequence.psi.TypedChainTestCase
|
||||||
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
|
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinTypes
|
||||||
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vitaliy.Bibaev
|
* @author Vitaliy.Bibaev
|
||||||
*/
|
*/
|
||||||
class TypedSequenceChain : TypedChainTestCase("sequence/positive/types") {
|
class TypedSequenceChain : TypedChainTestCase("sequence/positive/types") {
|
||||||
override val kotlinChainBuilder: StreamChainBuilder = KotlinSequenceSupportProvider().chainBuilder
|
override val kotlinChainBuilder: StreamChainBuilder = KotlinSequenceSupportProvider().chainBuilder
|
||||||
|
|
||||||
fun testAny() = doTest(KotlinTypes.ANY)
|
fun testAny() = doTest(KotlinTypes.ANY)
|
||||||
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableAny() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
|
fun testBoolean() = doTest(KotlinTypes.BOOLEAN)
|
||||||
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableBoolean() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testByte() = doTest(KotlinTypes.BYTE)
|
fun testByte() = doTest(KotlinTypes.BYTE)
|
||||||
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableByte() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testShort() = doTest(KotlinTypes.SHORT)
|
fun testShort() = doTest(KotlinTypes.SHORT)
|
||||||
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableShort() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testInt() = doTest(KotlinTypes.INT)
|
fun testInt() = doTest(KotlinTypes.INT)
|
||||||
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableInt() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testLong() = doTest(KotlinTypes.LONG)
|
fun testLong() = doTest(KotlinTypes.LONG)
|
||||||
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableLong() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testFloat() = doTest(KotlinTypes.FLOAT)
|
fun testFloat() = doTest(KotlinTypes.FLOAT)
|
||||||
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableFloat() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testDouble() = doTest(KotlinTypes.DOUBLE)
|
fun testDouble() = doTest(KotlinTypes.DOUBLE)
|
||||||
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableDouble() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testChar() = doTest(KotlinTypes.CHAR)
|
fun testChar() = doTest(KotlinTypes.CHAR)
|
||||||
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
|
fun testNullableChar() = doTest(KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
|
fun testNullableAnyToPrimitive() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.BOOLEAN)
|
||||||
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
|
fun testPrimitiveToNullableAny() = doTest(KotlinTypes.INT, KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
|
fun testAnyToPrimitive() = doTest(KotlinTypes.ANY, KotlinTypes.INT)
|
||||||
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
|
fun testPrimitiveToAny() = doTest(KotlinTypes.INT, KotlinTypes.ANY)
|
||||||
|
|
||||||
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
fun testNullableToNotNull() = doTest(KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
||||||
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
|
fun testNotNullToNullable() = doTest(KotlinTypes.DOUBLE, KotlinTypes.NULLABLE_ANY)
|
||||||
|
|
||||||
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
fun testFewTransitions1() = doTest(KotlinTypes.BYTE, KotlinTypes.ANY, KotlinTypes.NULLABLE_ANY, KotlinTypes.INT)
|
||||||
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
|
fun testFewTransitions2() = doTest(KotlinTypes.CHAR, KotlinTypes.BOOLEAN, KotlinTypes.DOUBLE, KotlinTypes.ANY)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user