New J2K: Move literal conversion internals to expression.kt

This commit is contained in:
Ilya Kirillov
2018-12-24 15:38:06 +03:00
committed by Ilya Kirillov
parent 60d498cedc
commit 84ad58b50b
2 changed files with 100 additions and 98 deletions
@@ -5,108 +5,13 @@
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.fixLiteral
import org.jetbrains.kotlin.j2k.tree.JKJavaLiteralExpression
import org.jetbrains.kotlin.j2k.tree.JKKtLiteralExpression
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.JKKtLiteralExpressionImpl
import java.math.BigInteger
class LiteralConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaLiteralExpression) return recurse(element)
return when {
element.type == DOUBLE -> convertDoubleLiteral(element.literal)
element.type == FLOAT -> convertFloatLiteral(element.literal)
element.type == LONG || element.type == INT -> convertIntegerLiteral(element)
element.type == CHAR -> convertCharLiteral(element.literal)
element.type == STRING -> convertStringLiteral(element.literal)
else -> element
}
}
private fun convertDoubleLiteral(text: String): JKKtLiteralExpression {
var newText =
text
.replace("d", "", true)
.replace(".e", "e", true)
.replace(".f", "", true)
.replace("f", "", true)
if (!newText.contains(".") && !newText.contains("e", true))
newText += "."
if (newText.endsWith("."))
newText += "0"
return JKKtLiteralExpressionImpl(
newText,
DOUBLE
)
}
private fun convertFloatLiteral(text: String): JKKtLiteralExpressionImpl {
return JKKtLiteralExpressionImpl(
text.replace(".f", "f", true)
.replace("F", "f")
.replace(".e", "e", true)
.let {
if (!it.endsWith("f")) "${it}f"
else it
},
FLOAT
)
}
private fun convertStringLiteral(text: String): JKKtLiteralExpressionImpl {
var newText = text.replace("((?:\\\\)*)\\\\([0-3]?[0-7]{1,2})".toRegex()) {
val leadingBackslashes = it.groupValues[1]
if (leadingBackslashes.length % 2 == 0) {
String.format("%s\\u%04x", leadingBackslashes, Integer.parseInt(it.groupValues[2], 8))
} else {
it.value
}
}
newText = newText.replace("\\$([A-Za-z]+|\\{)".toRegex(), "\\\\$0")
return JKKtLiteralExpressionImpl(newText, STRING)
}
private fun convertCharLiteral(text: String): JKKtLiteralExpression {
return JKKtLiteralExpressionImpl(
text.replace("\\\\([0-3]?[0-7]{1,2})".toRegex()) {
String.format("\\u%04x", Integer.parseInt(it.groupValues[1], 8))
},
CHAR
)
}
private fun convertIntegerLiteral(element: JKJavaLiteralExpression): JKKtLiteralExpression {
var text = element.literal
if (element.type == LONG) {
text = text.replace("l", "L")
}
fun isHexLiteral(text: String) = text.startsWith("0x") || text.startsWith("0X")
if ((element.type == LONG || element.type == INT) && isHexLiteral(text)) {
val v = BigInteger(text.substring(2).replace("L", ""), 16)
if (text.contains("L")) {
if (v.bitLength() > 63) {
text = "-0x${v.toLong().toString(16).substring(1)}L"
}
} else {
if (v.bitLength() > 31) {
text = "-0x${v.toInt().toString(16).substring(1)}"
}
}
} else if (element.type == INT) {
text = element.literal
}
return JKKtLiteralExpressionImpl(
text,
element.type
)
return element.fixLiteral(element.type)
}
}
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtNamedFunction
import java.math.BigInteger
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType {
val symbol =
@@ -283,4 +284,100 @@ fun JKVariable.hasWritableUsages(scope: JKTreeElement, context: ConversionContex
findUsages(scope, context).any {
it.asAssignmentFromTarget() != null
|| it.isInDecrementOrIncrement()
}
}
fun JKLiteralExpression.fixLiteral(expectedType: JKLiteralExpression.LiteralType): JKLiteralExpression =
when (expectedType) {
JKLiteralExpression.LiteralType.DOUBLE -> convertDoubleLiteral(literal)
JKLiteralExpression.LiteralType.FLOAT -> convertFloatLiteral(literal)
JKLiteralExpression.LiteralType.LONG, JKLiteralExpression.LiteralType.INT -> convertIntegerLiteral(this)
JKLiteralExpression.LiteralType.CHAR -> convertCharLiteral(literal)
JKLiteralExpression.LiteralType.STRING -> convertStringLiteral(literal)
else -> this
}
private fun convertDoubleLiteral(text: String): JKKtLiteralExpression {
var newText =
text.replace("L", "", true)
.replace("d", "", true)
.replace(".e", "e", true)
.replace(".f", "", true)
.replace("f", "", true)
if (!newText.contains(".") && !newText.contains("e", true))
newText += "."
if (newText.endsWith("."))
newText += "0"
return JKKtLiteralExpressionImpl(
newText,
JKLiteralExpression.LiteralType.DOUBLE
)
}
private fun convertFloatLiteral(text: String): JKKtLiteralExpressionImpl {
return JKKtLiteralExpressionImpl(
text.replace("L", "", true)
.replace(".f", "f", true)
.replace("F", "f")
.replace(".e", "e", true)
.let {
if (!it.endsWith("f")) "${it}f"
else it
},
JKLiteralExpression.LiteralType.FLOAT
)
}
private fun convertStringLiteral(text: String): JKKtLiteralExpressionImpl {
var newText = text.replace("((?:\\\\)*)\\\\([0-3]?[0-7]{1,2})".toRegex()) {
val leadingBackslashes = it.groupValues[1]
if (leadingBackslashes.length % 2 == 0) {
String.format("%s\\u%04x", leadingBackslashes, Integer.parseInt(it.groupValues[2], 8))
} else {
it.value
}
}
newText = newText.replace("\\$([A-Za-z]+|\\{)".toRegex(), "\\\\$0")
return JKKtLiteralExpressionImpl(newText, JKLiteralExpression.LiteralType.STRING)
}
private fun convertCharLiteral(text: String): JKKtLiteralExpression {
return JKKtLiteralExpressionImpl(
text.replace("\\\\([0-3]?[0-7]{1,2})".toRegex()) {
String.format("\\u%04x", Integer.parseInt(it.groupValues[1], 8))
},
JKLiteralExpression.LiteralType.CHAR
)
}
private fun convertIntegerLiteral(element: JKLiteralExpression): JKKtLiteralExpression {
var text = element.literal
if (element.type == JKLiteralExpression.LiteralType.LONG) {
text = text.replace("l", "L")
}
fun isHexLiteral(text: String) = text.startsWith("0x") || text.startsWith("0X")
if ((element.type == JKLiteralExpression.LiteralType.LONG || element.type == JKLiteralExpression.LiteralType.INT) && isHexLiteral(text)) {
val v = BigInteger(text.substring(2).replace("L", ""), 16)
if (text.contains("L")) {
if (v.bitLength() > 63) {
text = "-0x${v.toLong().toString(16).substring(1)}L"
}
} else {
if (v.bitLength() > 31) {
text = "-0x${v.toInt().toString(16).substring(1)}"
}
}
} else if (element.type == JKLiteralExpression.LiteralType.INT) {
text = element.literal
}
return JKKtLiteralExpressionImpl(
text,
element.type
)
}