Add source files

This commit is contained in:
Vitaliy.Bibaev
2017-10-09 15:23:41 +03:00
committed by Yan Zhulanow
parent 8f566132e4
commit 957f9a7e14
23 changed files with 1068 additions and 0 deletions
@@ -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
}
@@ -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")
}
}
@@ -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<KtCallExpression>) : 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<StreamChain> {
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<List<KtCallExpression>>
}
protected abstract class MyTreeVisitor : KtTreeVisitorVoid() {
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {}
override fun visitBlockExpression(expression: KtBlockExpression) {}
}
}
@@ -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<KtCallExpression> {
override fun transform(callChain: List<KtCallExpression>, 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<IntermediateStreamCall>()
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)
}
}
@@ -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.
}
}
@@ -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<KtCallExpression>()
private val myPreviousCalls = mutableMapOf<KtCallExpression, KtCallExpression>()
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<List<KtCallExpression>> {
val chains = ArrayList<List<KtCallExpression>>()
for (terminationCall in myTerminationCalls) {
val chain = ArrayList<KtCallExpression>()
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
}
}
}
@@ -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.
}
@@ -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()))
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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
}
@@ -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
}
}
@@ -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) +
"}"
}
@@ -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
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
}
@@ -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)
}
}
}
@@ -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)
}
}
@@ -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
}
}