Move stream call checks into separate class

This commit is contained in:
Vitaliy.Bibaev
2017-10-14 17:19:34 +03:00
committed by Yan Zhulanow
parent 64f399235e
commit 6d395dffbb
5 changed files with 34 additions and 31 deletions
@@ -1,6 +1,7 @@
package com.intellij.debugger.streams.kotlin.lib
import com.intellij.debugger.streams.kotlin.psi.impl.KotlinJavaStreamChainBuilder
import com.intellij.debugger.streams.kotlin.psi.impl.PackageBasedCallChecker
import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinStatementFactory
import com.intellij.debugger.streams.kotlin.trace.impl.KotlinTraceExpressionBuilder
import com.intellij.debugger.streams.lib.LibrarySupport
@@ -16,7 +17,7 @@ import com.intellij.openapi.project.Project
*/
class JavaStandardLibrarySupportProvider : LibrarySupportProvider {
private companion object {
val builder = KotlinJavaStreamChainBuilder()
val builder = KotlinJavaStreamChainBuilder(PackageBasedCallChecker("java.util.stream"))
val support = StandardLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory())
}
@@ -1,6 +1,7 @@
package com.intellij.debugger.streams.kotlin.lib
import com.intellij.debugger.streams.kotlin.psi.impl.KotlinJavaStreamChainBuilder
import com.intellij.debugger.streams.kotlin.psi.impl.PackageBasedCallChecker
import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinStatementFactory
import com.intellij.debugger.streams.kotlin.trace.impl.KotlinTraceExpressionBuilder
import com.intellij.debugger.streams.lib.LibrarySupport
@@ -16,7 +17,7 @@ import com.intellij.openapi.project.Project
*/
class StreamExLibrarySupportProvider : LibrarySupportProvider {
private companion object {
val streamChainBuilder = KotlinJavaStreamChainBuilder()
val streamChainBuilder = KotlinJavaStreamChainBuilder(PackageBasedCallChecker("one.util.streamex"))
val support = StreamExLibrarySupport()
val dsl = DslImpl(KotlinStatementFactory())
val expressionBuilder = KotlinTraceExpressionBuilder(dsl, support.createHandlerFactory(dsl))
@@ -0,0 +1,13 @@
package com.intellij.debugger.streams.kotlin.psi
import org.jetbrains.kotlin.psi.KtCallExpression
/**
* @author Vitaliy.Bibaev
*/
interface StreamCallChecker {
fun isIntermediateCall(expression: KtCallExpression): Boolean
fun isTerminationCall(expression: KtCallExpression): Boolean
fun isStreamCall(expression: KtCallExpression): Boolean = isIntermediateCall(expression) || isTerminationCall(expression)
}
@@ -15,10 +15,7 @@
*/
package com.intellij.debugger.streams.kotlin.psi.impl
import com.intellij.debugger.streams.kotlin.psi.StreamApiUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import com.intellij.debugger.streams.kotlin.psi.StreamCallChecker
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import java.util.*
@@ -26,42 +23,38 @@ import java.util.*
/**
* @author Vitaliy.Bibaev
*/
class KotlinJavaStreamChainBuilder : KotlinChainBuilderBase(KotlinChainTransformerImpl()) {
class KotlinJavaStreamChainBuilder(private val callChecker: StreamCallChecker) : KotlinChainBuilderBase(KotlinChainTransformerImpl()) {
override val existenceChecker: ExistenceChecker = MyExistenceChecker()
override fun createChainsBuilder(): ChainBuilder = MyBuilderVisitor()
private class MyExistenceChecker : ExistenceChecker() {
private inner class MyExistenceChecker : ExistenceChecker() {
override fun visitCallExpression(expression: KtCallExpression) {
// TODO: make the check more sophisticated
val type = expression.analyze().getType(expression) ?: return
val name = type.getJetTypeFqName(false)
if (StringUtil.getPackageName(name).startsWith("java.util.stream")) {
if (callChecker.isTerminationCall(expression)) {
fireElementFound()
}
}
}
private class MyBuilderVisitor : ChainBuilder() {
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) && StreamApiUtil.isStreamCall(expression)) {
if (!myPreviousCalls.containsKey(expression) && callChecker.isStreamCall(expression)) {
updateCallTree(expression)
}
}
private fun updateCallTree(expression: KtCallExpression) {
if (StreamApiUtil.isTerminationStreamCall(expression)) {
if (callChecker.isTerminationCall(expression)) {
myTerminationCalls.add(expression)
}
val parent = expression.parent as? KtDotQualifiedExpression ?: return
val parentCall = (parent.receiverExpression as? KtDotQualifiedExpression)?.selectorExpression
if (parentCall is KtCallExpression && StreamApiUtil.isStreamCall(parentCall)) {
if (parentCall is KtCallExpression && callChecker.isStreamCall(parentCall)) {
myPreviousCalls.put(expression, parentCall)
updateCallTree(parentCall)
}
@@ -73,7 +66,7 @@ class KotlinJavaStreamChainBuilder : KotlinChainBuilderBase(KotlinChainTransform
val chain = ArrayList<KtCallExpression>()
var current: KtCallExpression? = terminationCall
while (current != null) {
if (StreamApiUtil.isProducerStreamCall(current)) {
if (!callChecker.isStreamCall(current)) {
break
}
chain.add(current)
@@ -1,5 +1,8 @@
package com.intellij.debugger.streams.kotlin.psi
package com.intellij.debugger.streams.kotlin.psi.impl
import com.intellij.debugger.streams.kotlin.psi.StreamCallChecker
import com.intellij.debugger.streams.kotlin.psi.receiverType
import com.intellij.debugger.streams.kotlin.psi.resolveType
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.psi.KtCallExpression
@@ -8,20 +11,12 @@ import org.jetbrains.kotlin.types.KotlinType
/**
* @author Vitaliy.Bibaev
*/
object StreamApiUtil {
fun isStreamCall(expression: KtCallExpression): Boolean {
return isIntermediateStreamCall(expression) || isProducerStreamCall(expression) || isTerminationStreamCall(expression)
}
fun isProducerStreamCall(expression: KtCallExpression): Boolean {
return checkCallSupported(expression, false, true)
}
private fun isIntermediateStreamCall(expression: KtCallExpression): Boolean {
class PackageBasedCallChecker(private val supportedPackage: String) : StreamCallChecker {
override fun isIntermediateCall(expression: KtCallExpression): Boolean {
return checkCallSupported(expression, true, true)
}
fun isTerminationStreamCall(expression: KtCallExpression): Boolean {
override fun isTerminationCall(expression: KtCallExpression): Boolean {
return checkCallSupported(expression, true, false)
}
@@ -41,6 +36,6 @@ object StreamApiUtil {
}
val typeName = type.getJetTypeFqName(false)
return StringUtil.getPackageName(typeName).startsWith("java.util.stream")
return StringUtil.getPackageName(typeName).startsWith(supportedPackage)
}
}