New J2K: Add operator tokens

This commit is contained in:
Ilya Kirillov
2018-10-30 15:36:03 +03:00
committed by Ilya Kirillov
parent cd2a17ae56
commit 71b3fe33a3
8 changed files with 145 additions and 61 deletions
@@ -278,7 +278,7 @@ class NewCodeBuilder {
override fun visitBinaryExpression(binaryExpression: JKBinaryExpression) {
binaryExpression.left.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(binaryExpression.operator.operatorText)
printer.printWithNoIndent(binaryExpression.operator.token.text)
printer.printWithNoIndent(" ")
binaryExpression.right.accept(this)
}
@@ -288,7 +288,7 @@ class NewCodeBuilder {
}
override fun visitPrefixExpression(prefixExpression: JKPrefixExpression) {
printer.printWithNoIndent(prefixExpression.operator.operatorText)
printer.printWithNoIndent(prefixExpression.operator.token.text)
prefixExpression.expression.accept(this)
}
@@ -329,7 +329,7 @@ class NewCodeBuilder {
override fun visitPostfixExpression(postfixExpression: JKPostfixExpression) {
postfixExpression.expression.accept(this)
printer.printWithNoIndent(postfixExpression.operator.operatorText)
printer.printWithNoIndent(postfixExpression.operator.token.text)
}
override fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression) {
@@ -553,7 +553,7 @@ class NewCodeBuilder {
override fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement) {
ktAssignmentStatement.field.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(ktAssignmentStatement.operator.operatorText)
printer.printWithNoIndent(ktAssignmentStatement.operator.token.text)
printer.printWithNoIndent(" ")
ktAssignmentStatement.expression.accept(this)
}
@@ -5,28 +5,39 @@
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.copyTree
import com.intellij.psi.JavaTokenType
import org.jetbrains.kotlin.j2k.copyTreeAndDetach
import org.jetbrains.kotlin.j2k.tree.JKKtAssignmentStatement
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.JKBinaryExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtOperatorImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtWordOperatorImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKStubExpressionImpl
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.j2k.tree.detached
import org.jetbrains.kotlin.j2k.tree.impl.*
class AssignmentStatementOperatorConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
//todo fix
// if (element !is JKKtAssignmentStatement) return recurse(element)
// val newOperator = JKKtOperatorImpl.javaToKotlinOperator[element.operator] ?: return recurse(element)
// if (newOperator is JKKtWordOperatorImpl) {
// element.operator = JKKtOperatorImpl.tokenToOperator[KtTokens.EQ] ?: return recurse(element)
// val expr = element.expression
// element.expression = JKStubExpressionImpl()
// element.expression = JKBinaryExpressionImpl(element.field.copyTree(), expr, newOperator)
// } else {
// element.operator = newOperator
// }
if (element !is JKKtAssignmentStatement) return recurse(element)
val operator = element.operator as? JKJavaOperatorImpl ?: return recurse(element)
operator.token.correnspondingBinaryOperation()
?.apply {
val expression = element.expression.copyTreeAndDetach()
element.expression =
JKBinaryExpressionImpl(
element.field.copyTreeAndDetach(),
expression,
this
)
element.operator = JKJavaOperatorImpl.tokenToOperator[JavaTokenType.EQ]!!
}
return recurse(element)
}
private fun JKJavaOperatorToken.correnspondingBinaryOperation() =
when (psiToken) {
JavaTokenType.OREQ -> JavaTokenType.OR
JavaTokenType.ANDEQ -> JavaTokenType.AND
JavaTokenType.LTLTEQ -> JavaTokenType.LTLT
JavaTokenType.GTGTEQ -> JavaTokenType.GTGT
JavaTokenType.GTGTGTEQ -> JavaTokenType.GTGTGT
JavaTokenType.XOREQ -> JavaTokenType.XOR
else -> null
}?.let { JKJavaOperatorImpl.tokenToOperator[it] }
}
@@ -17,11 +17,11 @@ import org.jetbrains.kotlin.j2k.tree.impl.toKtToken
class BinaryExpressionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKBinaryExpression) return recurse(element)
val ktOperator = (element.operator as? JKJavaOperatorImpl)?.toKtToken() ?: return recurse(element)
val ktOperatorToken = (element.operator as? JKJavaOperatorImpl)?.token?.toKtToken() ?: return recurse(element)
val left = recurse(element.left)
val right = recurse(element.right)
(element as? JKBranchElement)?.invalidate()
val ktBinaryExpression = JKBinaryExpressionImpl.createKotlinBinaryExpression(left, right, ktOperator, context)
val ktBinaryExpression = JKBinaryExpressionImpl.createKotlinBinaryExpression(left, right, ktOperatorToken, context)
?: return JKBinaryExpressionImpl(left, right, element.operator)
return recurse(ktBinaryExpression)
}
@@ -97,7 +97,7 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
val start = loopVar.initializer
val operationType =
(loopStatement.updater as? JKExpressionStatement)?.expression?.isVariableIncrementOrDecrement(loopVar)
val reversed = when ((operationType as? JKJavaOperatorImpl)?.token) {
val reversed = when ((operationType as? JKJavaOperatorImpl)?.token?.token) {
JavaTokenType.PLUSPLUS -> false
JavaTokenType.MINUSMINUS -> true
else -> return null
@@ -160,7 +160,7 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
else -> JKBinaryExpressionImpl.createKotlinBinaryExpression(
start,
convertBound(bound, if (inclusiveComparison) 0 else -1),
KtTokens.RANGE,
JKKtSingleValueOperatorToken(KtTokens.RANGE),
context
)!!
}
@@ -178,8 +178,9 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
return JKBinaryExpressionImpl.createKotlinBinaryExpression(
bound,
JKKtLiteralExpressionImpl(Math.abs(correction).toString(), JKLiteralExpression.LiteralType.INT),
sign,
context)!!
JKKtSingleValueOperatorToken(sign),
context
)!!
}
private fun indicesIterationRange(
@@ -64,19 +64,88 @@ class JKJavaModifierImpl(override val type: JKJavaModifier.JavaModifierType) : J
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaModifier(this, data)
}
class JKJavaOperatorImpl private constructor(val token: IElementType) : JKOperator {
override val operatorText: String
class JKJavaOperatorToken(val token: IElementType) : JKOperatorToken {
override val text: String
get() = when (token) {
JavaTokenType.MINUSMINUS -> "--"
JavaTokenType.PLUSPLUS -> "++"
JavaTokenType.EXCL -> "!"
JavaTokenType.ASTERISKEQ -> "*="
JavaTokenType.EQ -> "="
JavaTokenType.EQEQ -> "=="
else -> TODO("TODO $token")
JavaTokenType.NE -> "!="
JavaTokenType.ANDAND -> "&&"
JavaTokenType.OROR -> "||"
JavaTokenType.GT -> ">"
JavaTokenType.LT -> "<"
JavaTokenType.GE -> ">="
JavaTokenType.LE -> "<="
JavaTokenType.EXCL -> "!"
JavaTokenType.PLUS -> "+"
JavaTokenType.MINUS -> "-"
JavaTokenType.ASTERISK -> "*"
JavaTokenType.DIV -> "/"
JavaTokenType.PERC -> "%"
JavaTokenType.PLUSEQ -> "+="
JavaTokenType.MINUSEQ -> "-="
JavaTokenType.ASTERISKEQ -> "*="
JavaTokenType.DIVEQ -> "/="
JavaTokenType.PERCEQ -> "%="
JavaTokenType.GTGT -> "shr"
JavaTokenType.LTLT -> "shl"
JavaTokenType.XOR -> "xor"
JavaTokenType.AND -> "and"
JavaTokenType.OR -> "or"
JavaTokenType.GTGTGT -> "ushr"
JavaTokenType.GTGTEQ -> "shr"
JavaTokenType.LTLTEQ -> "shl"
JavaTokenType.XOREQ -> "xor"
JavaTokenType.ANDEQ -> "and"
JavaTokenType.OREQ -> "or"
JavaTokenType.GTGTGTEQ -> "ushr"
JavaTokenType.PLUSPLUS -> "++"
JavaTokenType.MINUSMINUS -> "--"
else -> TODO(token.toString())
}
}
fun JKJavaOperatorToken.toKtToken(): JKKtOperatorToken =
when (this.token) {
JavaTokenType.DIV -> JKKtSingleValueOperatorToken(KtTokens.DIV)
JavaTokenType.MINUS -> JKKtSingleValueOperatorToken(KtTokens.MINUS)
JavaTokenType.ANDAND -> JKKtSingleValueOperatorToken(KtTokens.ANDAND)
JavaTokenType.OROR -> JKKtSingleValueOperatorToken(KtTokens.OROR)
JavaTokenType.PLUS -> JKKtSingleValueOperatorToken(KtTokens.PLUS)
JavaTokenType.ASTERISK -> JKKtSingleValueOperatorToken(KtTokens.MUL)
JavaTokenType.GT -> JKKtSingleValueOperatorToken(KtTokens.GT)
JavaTokenType.GE -> JKKtSingleValueOperatorToken(KtTokens.GTEQ)
JavaTokenType.LT -> JKKtSingleValueOperatorToken(KtTokens.LT)
JavaTokenType.LE -> JKKtSingleValueOperatorToken(KtTokens.LTEQ)
JavaTokenType.PERC -> JKKtSingleValueOperatorToken(KtTokens.PERC)
JavaTokenType.EQ -> JKKtSingleValueOperatorToken(KtTokens.EQ)
JavaTokenType.PLUSEQ -> JKKtSingleValueOperatorToken(KtTokens.PLUSEQ)
JavaTokenType.MINUSEQ -> JKKtSingleValueOperatorToken(KtTokens.MINUSEQ)
JavaTokenType.AND -> JKKtWordOperatorToken("and")
JavaTokenType.OR -> JKKtWordOperatorToken("or")
JavaTokenType.XOR -> JKKtWordOperatorToken("xor")
JavaTokenType.GTGTGT -> JKKtWordOperatorToken("ushr")
JavaTokenType.GTGT -> JKKtWordOperatorToken("shr")
JavaTokenType.LTLT -> JKKtWordOperatorToken("shl")
JavaTokenType.OREQ -> JKKtWordOperatorToken("or")
JavaTokenType.ANDEQ -> JKKtWordOperatorToken("and")
JavaTokenType.LTLTEQ -> JKKtWordOperatorToken("shl")
JavaTokenType.GTGTEQ -> JKKtWordOperatorToken("shr")
JavaTokenType.GTGTGTEQ -> JKKtWordOperatorToken("ushr")
JavaTokenType.XOREQ -> JKKtWordOperatorToken("xor")
else -> TODO(this.token::class.java.toString())
}
class JKJavaOperatorImpl private constructor(psiToken: IElementType) : JKOperator {
override val token: JKJavaOperatorToken = JKJavaOperatorToken(psiToken)
override val precedence: Int
get() = when (token) {
get() = when (token.token) {
JavaTokenType.ASTERISK, JavaTokenType.DIV, JavaTokenType.PERC -> 3
JavaTokenType.PLUS, JavaTokenType.MINUS -> 4
KtTokens.ELVIS -> 7
@@ -122,7 +122,7 @@ class JKBinaryExpressionImpl(
companion object {
private fun methodSymbolForToken(
token: KtSingleValueToken,
token: JKKtOperatorToken,
leftType: JKType,
rightType: JKType,
symbolProvider: JKSymbolProvider
@@ -143,7 +143,7 @@ class JKBinaryExpressionImpl(
return classSymbol.target.declarations// todo look for extensions
.asSequence()
.filterIsInstance<KtNamedFunction>()
.filter { it.name == operatorName }
.filter { it.name == token.operatorName }
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
.firstOrNull { it.parameterTypes.singleOrNull()?.takeIf { it.isSubtypeOf(rightType, symbolProvider) } != null }!!
}
@@ -152,7 +152,7 @@ class JKBinaryExpressionImpl(
fun createKotlinBinaryExpression(
left: JKExpression,
right: JKExpression,
token: KtSingleValueToken,
token: JKKtOperatorToken,
context: ConversionContext
): JKBinaryExpression? {
val leftType = left.type(context)
@@ -18,10 +18,12 @@ package org.jetbrains.kotlin.j2k.tree.impl
import com.intellij.psi.JavaTokenType
import org.jetbrains.kotlin.j2k.ast.Nullability
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -83,34 +85,27 @@ class JKKtLiteralExpressionImpl(
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtLiteralExpression(this, data)
}
fun JKJavaOperatorImpl.toKtToken(): KtSingleValueToken =
when (this.token) {
JavaTokenType.DIV -> KtTokens.DIV
JavaTokenType.MINUS -> KtTokens.MINUS
JavaTokenType.ANDAND -> KtTokens.ANDAND
JavaTokenType.OROR -> KtTokens.OROR
JavaTokenType.PLUS -> KtTokens.PLUS
JavaTokenType.ASTERISK -> KtTokens.MUL
JavaTokenType.GT -> KtTokens.GT
JavaTokenType.GE -> KtTokens.GTEQ
JavaTokenType.LT -> KtTokens.LT
JavaTokenType.LE -> KtTokens.LTEQ
JavaTokenType.PERC -> KtTokens.PERC
else -> TODO(this.token::class.java.toString())
}
class JKKtOperatorImpl(val token: KtSingleValueToken, val methodSymbol: JKMethodSymbol) : JKOperator, JKElementBase() {
override val precedence: Int
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val operatorText: String
get() = token.value
class JKKtSingleValueOperatorToken(val token: KtSingleValueToken) : JKKtOperatorToken {
override val operatorName: String
get() = OperatorConventions.BINARY_OPERATION_NAMES[token]?.identifier!!
override val text: String = token.value
}
class JKKtWordOperatorImpl constructor(override val operatorText: String) : JKOperator, JKElementBase() {
class JKKtWordOperatorToken(override val text: String) : JKKtOperatorToken {
override val operatorName: String = text
}
class JKKtOperatorImpl(override val token: JKKtOperatorToken, val methodSymbol: JKMethodSymbol) : JKOperator, JKElementBase() {
constructor(singleValueToken: KtSingleValueToken, methodSymbol: JKMethodSymbol) : this(
JKKtSingleValueOperatorToken(singleValueToken),
methodSymbol
)
override val precedence: Int
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
}
class JKKtModifierImpl(override val type: JKKtModifier.KtModifierType) : JKKtModifier, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtModifier(this, data)
}
@@ -21,10 +21,18 @@ import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
interface JKOperator {
val operatorText: String
val token: JKOperatorToken
val precedence: Int
}
interface JKOperatorToken {
val text: String
}
interface JKKtOperatorToken : JKOperatorToken {
val operatorName: String
}
interface JKQualifier
interface JKElement {