diff --git a/plugins/stream-debugger/resources/META-INF/plugin.xml b/plugins/stream-debugger/resources/META-INF/plugin.xml index 0d9da627d4cd..1de4a6e12e87 100644 --- a/plugins/stream-debugger/resources/META-INF/plugin.xml +++ b/plugins/stream-debugger/resources/META-INF/plugin.xml @@ -65,6 +65,7 @@ + diff --git a/plugins/stream-debugger/src/com/intellij/debugger/streams/lib/impl/JBIterableSupport.kt b/plugins/stream-debugger/src/com/intellij/debugger/streams/lib/impl/JBIterableSupport.kt new file mode 100644 index 000000000000..6294f1cba3a4 --- /dev/null +++ b/plugins/stream-debugger/src/com/intellij/debugger/streams/lib/impl/JBIterableSupport.kt @@ -0,0 +1,35 @@ +// Copyright 2000-2018 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.lib.impl + +import com.intellij.debugger.streams.resolve.AppendResolver +import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctByKeyHandler +import com.intellij.debugger.streams.trace.impl.handler.unified.DistinctTraceHandler + +/** + * @author Vitaliy.Bibaev + */ +class JBIterableSupport : LibrarySupportBase() { + companion object { + fun filterOperations(vararg names: String): Array = names.map { FilterOperation(it) }.toTypedArray() + fun mapOperations(vararg names: String): Array = names.map { MappingOperation(it) }.toTypedArray() + } + + init { + addIntermediateOperationsSupport(*filterOperations("filter", "skip", "skipWhile", "take", "takeWhile")) + addIntermediateOperationsSupport(*mapOperations("map", "transform")) + addIntermediateOperationsSupport(FlatMappingOperation("flatMap"), + FlatMappingOperation("flatten")) + + addIntermediateOperationsSupport(DistinctOperation("unique") { num, call, dsl -> + val arguments = call.arguments + if (arguments.isEmpty()) { + return@DistinctOperation DistinctTraceHandler(num, call, dsl) + } + return@DistinctOperation DistinctByKeyHandler(num, call, dsl) + }) + + addIntermediateOperationsSupport(ConcatOperation("append", AppendResolver())) + + addIntermediateOperationsSupport(SortedOperation("sorted"), SortedOperation("collect")) + } +} \ No newline at end of file diff --git a/plugins/stream-debugger/src/com/intellij/debugger/streams/lib/impl/JBIterableSupportProvider.kt b/plugins/stream-debugger/src/com/intellij/debugger/streams/lib/impl/JBIterableSupportProvider.kt new file mode 100644 index 000000000000..6a9bb07ff6cb --- /dev/null +++ b/plugins/stream-debugger/src/com/intellij/debugger/streams/lib/impl/JBIterableSupportProvider.kt @@ -0,0 +1,71 @@ +// Copyright 2000-2018 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.lib.impl + +import com.intellij.debugger.streams.lib.LibrarySupport +import com.intellij.debugger.streams.lib.LibrarySupportProvider +import com.intellij.debugger.streams.psi.impl.InheritanceBasedChainDetector +import com.intellij.debugger.streams.psi.impl.JavaChainTransformerImpl +import com.intellij.debugger.streams.psi.impl.JavaStreamChainBuilder +import com.intellij.debugger.streams.trace.TraceExpressionBuilder +import com.intellij.debugger.streams.trace.dsl.Lambda +import com.intellij.debugger.streams.trace.dsl.impl.DslImpl +import com.intellij.debugger.streams.trace.dsl.impl.TextExpression +import com.intellij.debugger.streams.trace.dsl.impl.java.JavaStatementFactory +import com.intellij.debugger.streams.trace.impl.JavaTraceExpressionBuilder +import com.intellij.debugger.streams.trace.impl.handler.type.GenericType +import com.intellij.debugger.streams.wrapper.CallArgument +import com.intellij.debugger.streams.wrapper.IntermediateStreamCall +import com.intellij.debugger.streams.wrapper.StreamCallType +import com.intellij.debugger.streams.wrapper.StreamChainBuilder +import com.intellij.debugger.streams.wrapper.impl.CallArgumentImpl +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.TextRange +import com.intellij.psi.CommonClassNames + +/** + * @author Vitaliy.Bibaev + */ +class JBIterableSupportProvider : LibrarySupportProvider { + private companion object { + const val CLASS_NAME = "com.intellij.util.containers.JBIterable" + } + + private val librarySupport = JBIterableSupport() + private val dsl = DslImpl(JBIterableJavaStatementFactory()) + override fun getLanguageId(): String = "JAVA" + + override fun getChainBuilder(): StreamChainBuilder { + return JavaStreamChainBuilder(JavaChainTransformerImpl(), InheritanceBasedChainDetector(CLASS_NAME)) + } + + override fun getExpressionBuilder(project: Project): TraceExpressionBuilder { + return JavaTraceExpressionBuilder(project, librarySupport.createHandlerFactory(dsl), dsl) + } + + override fun getLibrarySupport(): LibrarySupport = librarySupport + + private class JBIterableJavaStatementFactory : JavaStatementFactory() { + override fun createPeekCall(elementsType: GenericType, lambda: Lambda): IntermediateStreamCall { + val lambdaBody = createEmptyLambdaBody(lambda.variableName).apply { + add(lambda.body) + doReturn(TextExpression("true")) + } + val newLambda = createLambda(lambda.variableName, lambdaBody) + return JBIterablePeekCall(elementsType, newLambda.toCode()) + } + } + + private class JBIterablePeekCall(private val elementsType: GenericType, private val argText: String) : IntermediateStreamCall { + override fun getName(): String = "filter" + + override fun getArguments(): List = listOf(CallArgumentImpl(CommonClassNames.JAVA_LANG_OBJECT, argText)) + + override fun getType(): StreamCallType = StreamCallType.INTERMEDIATE + + override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE + + override fun getTypeBefore(): GenericType = elementsType + + override fun getTypeAfter(): GenericType = elementsType + } +} \ No newline at end of file diff --git a/plugins/stream-debugger/src/com/intellij/debugger/streams/psi/impl/InheritanceBasedChainDetector.kt b/plugins/stream-debugger/src/com/intellij/debugger/streams/psi/impl/InheritanceBasedChainDetector.kt new file mode 100644 index 000000000000..4317ebc0e912 --- /dev/null +++ b/plugins/stream-debugger/src/com/intellij/debugger/streams/psi/impl/InheritanceBasedChainDetector.kt @@ -0,0 +1,26 @@ +// Copyright 2000-2018 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.psi.impl + +import com.intellij.debugger.streams.psi.ChainDetector +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiMethodCallExpression +import com.intellij.psi.PsiType +import com.intellij.psi.util.InheritanceUtil + +/** + * @author Vitaliy.Bibaev + */ +class InheritanceBasedChainDetector(private val baseClassName: String) : ChainDetector { + override fun isTerminationCall(callExpression: PsiMethodCallExpression): Boolean { + val method = callExpression.resolveMethod() ?: return false + return isStreamType(method.parent as? PsiClass) && !isStreamType(method.returnType) + } + + override fun isIntermediateCall(callExpression: PsiMethodCallExpression): Boolean { + return isStreamType(callExpression.resolveMethod()?.returnType) + } + + private fun isStreamType(type: PsiType?): Boolean = InheritanceUtil.isInheritor(type, baseClassName) + + private fun isStreamType(type: PsiClass?): Boolean = InheritanceUtil.isInheritor(type, baseClassName) +} \ No newline at end of file