diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/KotlinPsiUtil.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/KotlinPsiUtil.kt new file mode 100644 index 00000000000..aed190eea59 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/KotlinPsiUtil.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.psi + +import com.intellij.openapi.util.text.StringUtil +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtValueArgument +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.types.KotlinType + +/** + * @author Vitaliy.Bibaev + */ + +fun KtExpression.resolveType(): KotlinType = + this.analyze().getType(this)!! + +fun KtValueArgument.resolveType(): KotlinType = getArgumentExpression()!!.resolveType() + +fun KotlinType.getPackage(withGenerics: Boolean): String = StringUtil.getPackageName(getJetTypeFqName(withGenerics)) + +fun KtCallExpression.callName(): String = this.calleeExpression!!.text + +fun KtCallExpression.receiverType(): KotlinType? { + val resolvedCall = getResolvedCall(analyze()) + return resolvedCall?.dispatchReceiver?.type +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/StreamApiUtil.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/StreamApiUtil.kt new file mode 100644 index 00000000000..668437c0d81 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/StreamApiUtil.kt @@ -0,0 +1,46 @@ +package com.intellij.debugger.streams.kotlin.psi + +import com.intellij.openapi.util.text.StringUtil +import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName +import org.jetbrains.kotlin.psi.KtCallExpression +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 { + return checkCallSupported(expression, true, true) + } + + fun isTerminationStreamCall(expression: KtCallExpression): Boolean { + return checkCallSupported(expression, true, false) + } + + private fun checkCallSupported(expression: KtCallExpression, + shouldSupportReceiver: Boolean, + shouldSupportResult: Boolean): Boolean { + val receiverType = expression.receiverType() + val resultType = expression.resolveType() + + return (receiverType == null || // there is no producer or producer is a static method + shouldSupportReceiver == isSupportedType(receiverType)) && shouldSupportResult == isSupportedType(resultType) + } + + private fun isSupportedType(type: KotlinType?): Boolean { + if (type == null) { + return false + } + + val typeName = type.getJetTypeFqName(false) + return StringUtil.getPackageName(typeName).startsWith("java.util.stream") + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinChainBuilderBase.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinChainBuilderBase.kt new file mode 100644 index 00000000000..dcc91e8c5e6 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinChainBuilderBase.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.psi.impl + +import com.intellij.debugger.streams.psi.ChainTransformer +import com.intellij.debugger.streams.psi.PsiUtil +import com.intellij.debugger.streams.wrapper.StreamChain +import com.intellij.debugger.streams.wrapper.StreamChainBuilder +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.psi.* + +/** + * @author Vitaliy.Bibaev + */ +abstract class KotlinChainBuilderBase(private val transformer: ChainTransformer) : StreamChainBuilder { + protected abstract val existenceChecker: ExistenceChecker + + override fun isChainExists(startElement: PsiElement): Boolean { + var element: PsiElement? = PsiUtil.ignoreWhiteSpaces(startElement) + while (element != null && !existenceChecker.isFound()) { + existenceChecker.reset() + element.accept(existenceChecker) + element = toUpperLevel(element) + } + + return existenceChecker.isFound() + } + + override fun build(startElement: PsiElement): List { + val visitor = createChainsBuilder() + var element = getLatestElementInScope(PsiUtil.ignoreWhiteSpaces(startElement)) + while (element != null) { + element.accept(visitor) + element = getLatestElementInScope(toUpperLevel(element)) + } + + return visitor.chains().map { transformer.transform(it, startElement) } + } + + private fun toUpperLevel(element: PsiElement): PsiElement? { + var current = element.parent + + while (current != null && !(current is KtLambdaExpression || current is KtAnonymousInitializer)) { + current = current.parent + } + + return current + } + + protected abstract fun createChainsBuilder(): ChainBuilder + + private fun getLatestElementInScope(element: PsiElement?): PsiElement? { + var current = element + while (current != null) { + val parent = current.parent + if (parent is KtBlockExpression || parent is KtLambdaExpression || parent is KtStatementExpression) { + break + } + + current = parent + } + + 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) + + private fun setFound(value: Boolean) { + myIsFound = value + } + } + + protected abstract class ChainBuilder : MyTreeVisitor() { + abstract fun chains(): List> + } + + protected abstract class MyTreeVisitor : KtTreeVisitorVoid() { + override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {} + override fun visitBlockExpression(expression: KtBlockExpression) {} + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinChainTransformerImpl.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinChainTransformerImpl.kt new file mode 100644 index 00000000000..633d8bbc475 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinChainTransformerImpl.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.psi.impl + +import com.intellij.debugger.streams.kotlin.psi.callName +import com.intellij.debugger.streams.kotlin.psi.getPackage +import com.intellij.debugger.streams.kotlin.psi.receiverType +import com.intellij.debugger.streams.kotlin.psi.resolveType +import com.intellij.debugger.streams.psi.* +import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinTypes +import com.intellij.debugger.streams.wrapper.CallArgument +import com.intellij.debugger.streams.wrapper.IntermediateStreamCall +import com.intellij.debugger.streams.wrapper.StreamChain +import com.intellij.debugger.streams.wrapper.impl.* +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtValueArgument + +/** + * @author Vitaliy.Bibaev + */ +class KotlinChainTransformerImpl : ChainTransformer { + override fun transform(callChain: List, context: PsiElement): StreamChain { + val firstCall = callChain.first() + val parent = firstCall.parent + val qualifier = if (parent is KtDotQualifiedExpression) + QualifierExpressionImpl(parent.receiverExpression.text, parent.receiverExpression.textRange, KotlinTypes.ANY) + else + QualifierExpressionImpl("", TextRange.EMPTY_RANGE, KotlinTypes.ANY) // This possible only when this inherits Stream + + val intermediateCalls = mutableListOf() + for (call in callChain.subList(0, callChain.size - 1)) { + intermediateCalls += IntermediateStreamCallImpl(call.callName(), + call.valueArguments.map { it.toCallArgument() }, + KotlinTypes.ANY, KotlinTypes.ANY, + call.textRange, + call.receiverType()!!.getPackage(false)) + } + + val terminationsPsiCall = callChain.last() + // TODO: infer true types + val terminationCall = TerminatorStreamCallImpl(terminationsPsiCall.callName(), emptyList(), + KotlinTypes.ANY, KotlinTypes.ANY, + terminationsPsiCall.textRange, + terminationsPsiCall.receiverType()!!.getPackage(false)) + + return StreamChainImpl(qualifier, intermediateCalls, terminationCall, context) + } + + private fun KtValueArgument.toCallArgument(): CallArgument { + val argExpression = getArgumentExpression()!! + return CallArgumentImpl(argExpression.resolveType().getJetTypeFqName(true), argExpression.text) + } +} diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinCollectionChainBuilder.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinCollectionChainBuilder.kt new file mode 100644 index 00000000000..d64230f15a4 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinCollectionChainBuilder.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.psi.impl + +import com.intellij.debugger.streams.kotlin.psi.impl.KotlinChainBuilderBase + +/** + * @author Vitaliy.Bibaev + */ +class KotlinCollectionChainBuilder : KotlinChainBuilderBase(TODO("transmit here a correct transformer")) { + override val existenceChecker: ExistenceChecker + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + + override fun createChainsBuilder(): ChainBuilder { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinJavaStreamChainBuilder.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinJavaStreamChainBuilder.kt new file mode 100644 index 00000000000..f122c90b63a --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinJavaStreamChainBuilder.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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 org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import java.util.* + +/** + * @author Vitaliy.Bibaev + */ +class KotlinJavaStreamChainBuilder : KotlinChainBuilderBase(KotlinChainTransformerImpl()) { + override val existenceChecker: ExistenceChecker = MyExistenceChecker() + + override fun createChainsBuilder(): ChainBuilder = MyBuilderVisitor() + + private 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")) { + fireElementFound() + } + } + } + + private class MyBuilderVisitor : ChainBuilder() { + private val myTerminationCalls = mutableSetOf() + private val myPreviousCalls = mutableMapOf() + + override fun visitCallExpression(expression: KtCallExpression) { + super.visitCallExpression(expression) + if (!myPreviousCalls.containsKey(expression) && StreamApiUtil.isStreamCall(expression)) { + updateCallTree(expression) + } + } + + private fun updateCallTree(expression: KtCallExpression) { + if (StreamApiUtil.isTerminationStreamCall(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)) { + myPreviousCalls.put(expression, parentCall) + updateCallTree(parentCall) + } + } + + override fun chains(): List> { + val chains = ArrayList>() + for (terminationCall in myTerminationCalls) { + val chain = ArrayList() + var current: KtCallExpression? = terminationCall + while (current != null) { + if (StreamApiUtil.isProducerStreamCall(current)) { + break + } + chain.add(current) + current = myPreviousCalls[current] + } + + Collections.reverse(chain) + chains.add(chain) + } + + return chains + } + } +} diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinSequenceChainBuilder.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinSequenceChainBuilder.kt new file mode 100644 index 00000000000..3659ab152c5 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/psi/impl/KotlinSequenceChainBuilder.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.psi.impl + +import com.intellij.debugger.streams.kotlin.psi.impl.KotlinChainBuilderBase + +/** + * @author Vitaliy.Bibaev + */ +class KotlinSequenceChainBuilder : KotlinChainBuilderBase(TODO("transmit here a correct transformer")) { + override fun createChainsBuilder(): ChainBuilder { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override val existenceChecker: ExistenceChecker + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinArrayVariable.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinArrayVariable.kt new file mode 100644 index 00000000000..2d9fec262e1 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinArrayVariable.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinVariableDeclaration +import com.intellij.debugger.streams.trace.dsl.ArrayVariable +import com.intellij.debugger.streams.trace.dsl.Expression +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.VariableImpl +import com.intellij.debugger.streams.trace.impl.handler.type.ArrayType + +/** + * @author Vitaliy.Bibaev + */ +class KotlinArrayVariable(override val type: ArrayType, override val name: String) + : VariableImpl(type, name), ArrayVariable { + override fun get(index: Expression): Expression = TextExpression("$name[${index.toCode()}]!!") + + override fun set(index: Expression, value: Expression): Expression = TextExpression("$name[${index.toCode()}] = ${value.toCode()}") + + override fun defaultDeclaration(size: Expression): VariableDeclaration = + KotlinVariableDeclaration(this, false, type.sizedDeclaration(size.toCode())) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinAssignmentStatement.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinAssignmentStatement.kt new file mode 100644 index 00000000000..47cf7229b6c --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinAssignmentStatement.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.Variable +import com.intellij.debugger.streams.trace.dsl.impl.AssignmentStatement + +/** + * @author Vitaliy.Bibaev + */ +class KotlinAssignmentStatement(override val variable: Variable, override val expression: Expression) : AssignmentStatement { + override fun toCode(indent: Int): String = "${variable.toCode()} = ${expression.toCode()}".withIndent(indent) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinCodeBlock.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinCodeBlock.kt new file mode 100644 index 00000000000..6de00d82a65 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinCodeBlock.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.StatementFactory +import com.intellij.debugger.streams.trace.dsl.impl.LineSeparatedCodeBlock + +/** + * @author Vitaliy.Bibaev + */ +open class KotlinCodeBlock(statementFactory: StatementFactory) : LineSeparatedCodeBlock(statementFactory) { + override fun doReturn(expression: Expression) = addStatement(expression) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForEachLoop.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForEachLoop.kt new file mode 100644 index 00000000000..f2aab4b7478 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForEachLoop.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.* + +/** + * @author Vitaliy.Bibaev + */ +class KotlinForEachLoop(private val iterateVariable: Variable, + private val collection: Expression, + private val loopBody: ForLoopBody) : Convertable { + override fun toCode(indent: Int): String = + "for (${iterateVariable.name} in ${collection.toCode()}) {\n".withIndent(indent) + + loopBody.toCode(indent + 1) + + "}".withIndent(indent) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForLoop.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForLoop.kt new file mode 100644 index 00000000000..80f172bd6b7 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForLoop.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.* + +/** + * @author Vitaliy.Bibaev + */ +class KotlinForLoop(private val initialization: VariableDeclaration, + private val condition: Expression, + private val afterThought: Expression, + private val loopBody: ForLoopBody) : Convertable { + override fun toCode(indent: Int): String = + initialization.toCode(indent) + "\n" + + "while (${condition.toCode()}) {\n".withIndent(indent) + + loopBody.toCode(indent + 1) + + afterThought.toCode(indent + 1) + "\n" + + "}".withIndent(indent) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForLoopBody.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForLoopBody.kt new file mode 100644 index 00000000000..9861e2cc1ab --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinForLoopBody.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.* +import com.intellij.debugger.streams.trace.dsl.impl.TextExpression + +/** + * @author Vitaliy.Bibaev + */ +class KotlinForLoopBody(override val loopVariable: Variable, + statementFactory: StatementFactory) : KotlinCodeBlock(statementFactory), ForLoopBody { + private companion object { + val BREAK = TextExpression("break") + } + + override fun breakIteration(): Expression = BREAK +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinIfBranch.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinIfBranch.kt new file mode 100644 index 00000000000..3c5bb1ecf4c --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinIfBranch.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.CodeBlock +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.StatementFactory +import com.intellij.debugger.streams.trace.dsl.impl.common.IfBranchBase + +/** + * @author Vitaliy.Bibaev + */ +class KotlinIfBranch(condition: Expression, thenBlock: CodeBlock, statementFactory: StatementFactory) + : IfBranchBase(condition, thenBlock, statementFactory) { + override fun toCode(indent: Int): String { + val elseBlockVar = elseBlock + val ifThen = "if (${condition.toCode(0)}) {\n".withIndent(indent) + + thenBlock.toCode(indent + 1) + + "}".withIndent(indent) + if (elseBlockVar != null) { + return ifThen + " else { \n" + + elseBlockVar.toCode(indent + 1) + + "}".withIndent(indent) + } + + return ifThen + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinLambda.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinLambda.kt new file mode 100644 index 00000000000..46e8d780ff8 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinLambda.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.CodeBlock +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.Lambda +import com.intellij.debugger.streams.trace.dsl.impl.TextExpression + +/** + * @author Vitaliy.Bibaev + */ +class KotlinLambda(override val variableName: String, override val body: CodeBlock) : Lambda { + override fun call(callName: String, vararg args: Expression): Expression = TextExpression("(${toCode()})").call(callName, *args) + + override fun toCode(indent: Int): String = + "{ $variableName -> \n".withIndent(indent) + + body.toCode(indent + 1) + + "}" +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinLambdaBody.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinLambdaBody.kt new file mode 100644 index 00000000000..5bc374e5d8c --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinLambdaBody.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinCodeBlock +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.LambdaBody +import com.intellij.debugger.streams.trace.dsl.StatementFactory + +/** + * @author Vitaliy.Bibaev + */ +class KotlinLambdaBody(override val lambdaArg: Expression, statementFactory: StatementFactory) + : KotlinCodeBlock(statementFactory), LambdaBody diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinListVariable.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinListVariable.kt new file mode 100644 index 00000000000..98faf643e3a --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinListVariable.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.kotlin.trace.dsl.KotlinVariableDeclaration +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.ListVariable +import com.intellij.debugger.streams.trace.dsl.VariableDeclaration +import com.intellij.debugger.streams.trace.dsl.impl.VariableImpl +import com.intellij.debugger.streams.trace.impl.handler.type.ListType + +/** + * @author Vitaliy.Bibaev + */ +class KotlinListVariable(override val type: ListType, name: String) + : VariableImpl(type, name), ListVariable { + override fun get(index: Expression): Expression = call("get", index) + override fun set(index: Expression, newValue: Expression): Expression = call("set", index, newValue) + override fun add(element: Expression): Expression = call("add", element) + + override fun contains(element: Expression): Expression = call("contains", element) + + override fun size(): Expression = property("size") + + override fun defaultDeclaration(): VariableDeclaration = + KotlinVariableDeclaration(this, false, type.defaultValue) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinMapVariable.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinMapVariable.kt new file mode 100644 index 00000000000..42c478a84a6 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinMapVariable.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.Expression +import com.intellij.debugger.streams.trace.dsl.Lambda +import com.intellij.debugger.streams.trace.dsl.VariableDeclaration +import com.intellij.debugger.streams.trace.dsl.impl.TextExpression +import com.intellij.debugger.streams.trace.dsl.impl.common.MapVariableBase +import com.intellij.debugger.streams.trace.impl.handler.type.MapType + +/** + * @author Vitaliy.Bibaev + */ +class KotlinMapVariable(type: MapType, name: String) : MapVariableBase(type, name) { + override fun get(key: Expression): Expression = TextExpression("${toCode()}[${key.toCode()}]") + + override fun set(key: Expression, newValue: Expression): Expression = + TextExpression("${toCode()}[${key.toCode()}] = ${newValue.toCode()}") + + override fun contains(key: Expression): Expression = TextExpression("${key.toCode()} in ${toCode()}") + + override fun size(): Expression = TextExpression("${toCode()}.size") + + override fun keys(): Expression = TextExpression("${toCode()}.keys") + + override fun computeIfAbsent(key: Expression, supplier: Lambda): Expression = + TextExpression("${toCode()}.getOrPut(${key.toCode()}, ${supplier.toCode()}") + + override fun defaultDeclaration(isMutable: Boolean): VariableDeclaration = + KotlinVariableDeclaration(this, false, type.defaultValue) +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinStatementFactory.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinStatementFactory.kt new file mode 100644 index 00000000000..44cceb50767 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinStatementFactory.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.* +import com.intellij.debugger.streams.trace.dsl.impl.AssignmentStatement +import com.intellij.debugger.streams.trace.dsl.impl.TextExpression +import com.intellij.debugger.streams.trace.dsl.impl.VariableImpl +import com.intellij.debugger.streams.trace.impl.handler.PeekCall +import com.intellij.debugger.streams.trace.impl.handler.type.GenericType +import com.intellij.debugger.streams.wrapper.IntermediateStreamCall + +/** + * @author Vitaliy.Bibaev + */ +class KotlinStatementFactory : StatementFactory { + override fun createNewListExpression(elementType: GenericType, vararg args: Expression): Expression = + TextExpression("kotlin.collections.mutableListOf<${elementType.genericTypeName}>(${StatementFactory.commaSeparate(*args)})") + + override fun createListVariable(elementType: GenericType, name: String): ListVariable = KotlinListVariable(types.list(elementType), name) + + override fun not(expression: Expression): Expression = TextExpression("!${expression.toCode()}") + + override val types: Types = KotlinTypes + + override fun createEmptyCompositeCodeBlock(): CompositeCodeBlock = KotlinCodeBlock(this) + + override fun createEmptyCodeBlock(): CodeBlock = KotlinCodeBlock(this) + + override fun createVariableDeclaration(variable: Variable, isMutable: Boolean): VariableDeclaration = + KotlinVariableDeclaration(variable, isMutable) + + override fun createVariableDeclaration(variable: Variable, init: Expression, isMutable: Boolean): VariableDeclaration = + KotlinVariableDeclaration(variable, isMutable, init.toCode()) + + override fun createEmptyForLoopBody(iterateVariable: Variable): ForLoopBody = KotlinForLoopBody(iterateVariable, this) + + override fun createForEachLoop(iterateVariable: Variable, collection: Expression, loopBody: ForLoopBody): Convertable = + KotlinForEachLoop(iterateVariable, collection, loopBody) + + override fun createForLoop(initialization: VariableDeclaration, condition: Expression, + afterThought: Expression, loopBody: ForLoopBody): Convertable = + KotlinForLoop(initialization, condition, afterThought, loopBody) + + override fun createEmptyLambdaBody(argName: String): LambdaBody = KotlinLambdaBody(TextExpression(argName), this) + + override fun createLambda(argName: String, lambdaBody: LambdaBody): Lambda = KotlinLambda(argName, lambdaBody) + + 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 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 createIfBranch(condition: Expression, thenBlock: CodeBlock): IfBranch = + KotlinIfBranch(condition, thenBlock, this) + + override fun createAssignmentStatement(variable: Variable, expression: Expression): AssignmentStatement = + KotlinAssignmentStatement(variable, expression) + + override fun createMapVariable(keyType: GenericType, valueType: GenericType, name: String, linked: Boolean): MapVariable = + KotlinMapVariable(if (linked) types.linkedMap(keyType, valueType) else types.map(keyType, valueType), name) + + override fun createArrayVariable(elementType: GenericType, name: String): ArrayVariable = + KotlinArrayVariable(types.array(elementType), name) + + override fun createScope(codeBlock: CodeBlock): Convertable = + object : Convertable { + override fun toCode(indent: Int): String = + "run {\n".withIndent(indent) + + codeBlock.toCode(indent + 1) + + "}".withIndent(indent) + } + + override fun 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() } + return when (elementType) { + types.INT -> TextExpression("kotlin.intArrayOf($arguments)") + types.LONG -> TextExpression("kotlin.longArrayOf($arguments)") + types.DOUBLE -> TextExpression("kotlin.doubleArrayOf($arguments)") + else -> TextExpression("kotlin.arrayOf<${types.nullable { elementType }.genericTypeName}>($arguments)") + } + } + + override fun createNewSizedArray(elementType: GenericType, size: Expression): Expression = + TextExpression("arrayOfNulls<${elementType.genericTypeName}>(${size.toCode()})") + + override fun createPeekCall(elementsType: GenericType, lambda: String): IntermediateStreamCall = PeekCall(lambda, elementsType) +} diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinTryBlock.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinTryBlock.kt new file mode 100644 index 00000000000..4c2e3ee3f98 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinTryBlock.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.CodeBlock +import com.intellij.debugger.streams.trace.dsl.StatementFactory +import com.intellij.debugger.streams.trace.dsl.impl.common.TryBlockBase + +/** + * @author Vitaliy.Bibaev + */ +class KotlinTryBlock(private val block: CodeBlock, statementFactory: StatementFactory) : TryBlockBase(statementFactory) { + override fun toCode(indent: Int): String { + val descriptor = myCatchDescriptor ?: error("catch block must be specified") + return "try {\n".withIndent(indent) + + block.toCode(indent + 1) + + "} catch(${descriptor.variable.name} : ${descriptor.variable.type.variableTypeName}) {\n" + + descriptor.block.toCode(indent + 1) + + "}".withIndent(indent) + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinTypes.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinTypes.kt new file mode 100644 index 00000000000..cd85f7d85fa --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinTypes.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.Types +import com.intellij.debugger.streams.trace.impl.handler.type.* +/** + * @author Vitaliy.Bibaev + */ +object KotlinTypes : Types { + override val ANY: GenericType = ClassTypeImpl("kotlin.Any", "kotlin.Any()") + override val INT: GenericType = ClassTypeImpl("kotlin.Int", "0") + override val LONG: GenericType = ClassTypeImpl("kotlin.Long", "0L") + override val BOOLEAN: GenericType = ClassTypeImpl("kotlin.Boolean", "false") + override val DOUBLE: GenericType = ClassTypeImpl("kotlin.Double", "0.") + override val STRING: GenericType = ClassTypeImpl("kotlin.String", "\"\"") + override val EXCEPTION: GenericType = ClassTypeImpl("kotlin.Throwable", "kotlin.Throwable()") + override val VOID: GenericType = ClassTypeImpl("kotlin.Unit", "Unit") + + override val TIME: GenericType = ClassTypeImpl("java.util.concurrent.atomic.AtomicInteger", + "java.util.concurrent.atomic.AtomicInteger()") + + override fun list(elementsType: GenericType): ListType = + ListTypeImpl(elementsType, { "kotlin.collections.MutableList<$it>" }, "kotlin.collections.mutableListOf()") + + override fun array(elementType: GenericType): ArrayType = when (elementType) { + INT -> ArrayTypeImpl(INT, { "kotlin.IntArray" }, { "kotlin.IntArray($it)" }) + LONG -> ArrayTypeImpl(LONG, { "kotlin.LongArray" }, { "kotlin.LongArray($it)" }) + DOUBLE -> ArrayTypeImpl(DOUBLE, { "kotlin.DoubleArray" }, { "kotlin.DoubleArray($it)" }) + else -> ArrayTypeImpl(nullable { elementType }, { "kotlin.Array<$it>" }, { "kotlin.arrayOfNulls($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) + } + } +} + diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinVariableDeclaration.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinVariableDeclaration.kt new file mode 100644 index 00000000000..5eeac2aa19c --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/dsl/KotlinVariableDeclaration.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.dsl + +import com.intellij.debugger.streams.trace.dsl.Variable +import com.intellij.debugger.streams.trace.dsl.VariableDeclaration + +/** + * @author Vitaliy.Bibaev + */ +class KotlinVariableDeclaration(override val variable: Variable, + override val isMutable: Boolean, + private val init: String = "") : VariableDeclaration { + override fun toCode(indent: Int): String { + val prefix = if (isMutable) "var" else "val" + val suffix = if (init.trim().isEmpty()) "" else " = $init" + return "$prefix ${variable.name}: ${variable.type.variableTypeName}$suffix".withIndent(indent) + } +} \ No newline at end of file diff --git a/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/KotlinTraceExpressionBuilder.kt b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/KotlinTraceExpressionBuilder.kt new file mode 100644 index 00000000000..7ea63ccc052 --- /dev/null +++ b/idea/idea-jvm/src/com/intellij/debugger/streams/kotlin/trace/impl/KotlinTraceExpressionBuilder.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.streams.kotlin.trace.impl + +import com.intellij.debugger.streams.lib.HandlerFactory +import com.intellij.debugger.streams.trace.dsl.Dsl +import com.intellij.debugger.streams.trace.impl.TraceExpressionBuilderBase +import com.intellij.debugger.streams.wrapper.StreamChain +import com.intellij.openapi.diagnostic.Logger + +/** + * @author Vitaliy.Bibaev + */ +class KotlinTraceExpressionBuilder(dsl: Dsl, handlerFactory: HandlerFactory) : TraceExpressionBuilderBase(dsl, handlerFactory) { + private companion object { + private val LOG = Logger.getInstance(KotlinTraceExpressionBuilder::class.java) + } + + override fun createTraceExpression(chain: StreamChain): String { + val expression = super.createTraceExpression(chain) + val resultDeclaration = dsl.declaration(dsl.variable(dsl.types.nullable { ANY }, resultVariableName), dsl.nullExpression, true) + val result = "${resultDeclaration.toCode()}\n " + + "$expression\n" + + resultVariableName + + LOG.info("trace expression: \n$result") + + return result + } +} \ No newline at end of file