New J2K: move all literal conversion stuff to LiteralConversion & add octal literals conversion
This commit is contained in:
@@ -81,6 +81,7 @@ object ConversionsRunner {
|
||||
+MethodReferenceToLambdaConversion(context)
|
||||
+BuiltinMembersConversion(context)
|
||||
+ImplicitCastsConversion(context)
|
||||
+LiteralConversion()
|
||||
|
||||
+CollectImportsConversion(context)
|
||||
+SortClassMembersConversion()
|
||||
|
||||
@@ -92,7 +92,6 @@ class ImplicitCastsConversion(private val context: NewJ2kConverterContext) : Rec
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun JKExpression.castStringToRegex(toType: JKType): JKExpression? {
|
||||
if (toType.safeAs<JKClassType>()?.classReference?.fqName != "java.util.regex.Pattern") return null
|
||||
val expressionType = type(context.symbolProvider) ?: return null
|
||||
@@ -133,7 +132,7 @@ class ImplicitCastsConversion(private val context: NewJ2kConverterContext) : Rec
|
||||
return JKJavaLiteralExpressionImpl(
|
||||
literal,
|
||||
expectedType
|
||||
).fixLiteral(expectedType)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.conversions
|
||||
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.j2k.ast.Nullability
|
||||
import org.jetbrains.kotlin.nj2k.tree.*
|
||||
import org.jetbrains.kotlin.nj2k.tree.impl.*
|
||||
|
||||
class JavaStandartMethodsConversion(private val context: NewJ2kConverterContext) : RecursiveApplicableConversionBase() {
|
||||
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||
if (element !is JKClass) return recurse(element)
|
||||
for (declaration in element.classBody.declarations) {
|
||||
if (declaration !is JKJavaMethodImpl) continue
|
||||
if (fixToStringMethod(declaration)) continue
|
||||
if (fixFinalizeMethod(declaration, element)) continue
|
||||
if (fixCloneMethod(declaration)) {
|
||||
element.inheritance.implements +=
|
||||
JKTypeElementImpl(
|
||||
JKClassTypeImpl(
|
||||
JKUnresolvedClassSymbol("Cloneable"),
|
||||
emptyList(), Nullability.NotNull
|
||||
)
|
||||
)
|
||||
continue
|
||||
}
|
||||
}
|
||||
return recurse(element)
|
||||
}
|
||||
|
||||
private fun fixToStringMethod(method: JKJavaMethodImpl): Boolean {
|
||||
if (method.name.value != "toString") return false
|
||||
if (method.parameters.isNotEmpty()) return false
|
||||
val type = (method.returnType.type as? JKClassType)
|
||||
?.takeIf { it.classReference.name == "String" }
|
||||
?.updateNullability(Nullability.NotNull) ?: return false
|
||||
method.returnType = JKTypeElementImpl(type)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun fixCloneMethod(method: JKJavaMethodImpl): Boolean {
|
||||
if (method.name.value != "clone") return false
|
||||
if (method.parameters.isNotEmpty()) return false
|
||||
val type = (method.returnType.type as? JKClassType)
|
||||
?.takeIf { it.classReference.name == "Object" }
|
||||
?.updateNullability(Nullability.NotNull) ?: return false
|
||||
method.returnType = JKTypeElementImpl(type)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun fixFinalizeMethod(method: JKJavaMethodImpl, containingClass: JKClass): Boolean {
|
||||
if (method.name.value != "finalize") return false
|
||||
if (method.parameters.isNotEmpty()) return false
|
||||
if (method.returnType.type != JKJavaVoidType) return false
|
||||
if (method.modality == Modality.OVERRIDE) {
|
||||
method.modality =
|
||||
if (containingClass.modality == Modality.OPEN) Modality.OPEN
|
||||
else Modality.FINAL
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,112 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.conversions
|
||||
|
||||
import org.jetbrains.kotlin.nj2k.fixLiteral
|
||||
import org.jetbrains.kotlin.nj2k.tree.JKJavaLiteralExpression
|
||||
import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
|
||||
import org.jetbrains.kotlin.nj2k.tree.*
|
||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKKtLiteralExpressionImpl
|
||||
import java.math.BigInteger
|
||||
|
||||
class LiteralConversion : RecursiveApplicableConversionBase() {
|
||||
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||
if (element !is JKJavaLiteralExpression) return recurse(element)
|
||||
return element.fixLiteral(element.type)
|
||||
return element.convertLiteral()
|
||||
}
|
||||
|
||||
private fun JKLiteralExpression.convertLiteral(): JKLiteralExpression =
|
||||
when (type) {
|
||||
JKLiteralExpression.LiteralType.DOUBLE -> toDoubleLiteral()
|
||||
JKLiteralExpression.LiteralType.FLOAT -> toFloatLiteral()
|
||||
JKLiteralExpression.LiteralType.LONG -> toLongLiteral()
|
||||
JKLiteralExpression.LiteralType.INT -> toIntLiteral()
|
||||
JKLiteralExpression.LiteralType.CHAR -> convertCharLiteral()
|
||||
JKLiteralExpression.LiteralType.STRING -> toStringLiteral()
|
||||
else -> this
|
||||
}.withNonCodeElementsFrom(this)
|
||||
|
||||
private fun JKLiteralExpression.toDoubleLiteral() =
|
||||
JKKtLiteralExpressionImpl(
|
||||
literal.cleanFloatAndDoubleLiterals()
|
||||
.let { text ->
|
||||
if (!text.contains(".") && !text.contains("e", true))
|
||||
"$text."
|
||||
else text
|
||||
}.let { text ->
|
||||
if (text.endsWith(".")) "${text}0" else text
|
||||
},
|
||||
JKLiteralExpression.LiteralType.DOUBLE
|
||||
)
|
||||
|
||||
|
||||
private fun JKLiteralExpression.toFloatLiteral() =
|
||||
JKKtLiteralExpressionImpl(
|
||||
literal.cleanFloatAndDoubleLiterals()
|
||||
.let { text ->
|
||||
if (!text.endsWith("f")) "${text}f"
|
||||
else text
|
||||
},
|
||||
JKLiteralExpression.LiteralType.FLOAT
|
||||
)
|
||||
|
||||
private fun JKLiteralExpression.toStringLiteral() =
|
||||
JKKtLiteralExpressionImpl(literal.replace("((?:\\\\)*)\\\\([0-3]?[0-7]{1,2})".toRegex()) { matchResult ->
|
||||
val leadingBackslashes = matchResult.groupValues[1]
|
||||
if (leadingBackslashes.length % 2 == 0)
|
||||
kotlin.String.format("%s\\u%04x", leadingBackslashes, java.lang.Integer.parseInt(matchResult.groupValues[2], 8))
|
||||
else matchResult.value
|
||||
}.replace("\\$([A-Za-z]+|\\{)".toRegex(), "\\\\$0"), JKLiteralExpression.LiteralType.STRING)
|
||||
|
||||
|
||||
private fun JKLiteralExpression.convertCharLiteral(): JKKtLiteralExpression =
|
||||
JKKtLiteralExpressionImpl(
|
||||
literal.replace("\\\\([0-3]?[0-7]{1,2})".toRegex()) {
|
||||
String.format("\\u%04x", Integer.parseInt(it.groupValues[1], 8))
|
||||
},
|
||||
JKLiteralExpression.LiteralType.CHAR
|
||||
)
|
||||
|
||||
|
||||
private fun JKLiteralExpression.toIntLiteral(): JKKtLiteralExpression =
|
||||
JKKtLiteralExpressionImpl(
|
||||
literal
|
||||
.replace("l", "", ignoreCase = true)
|
||||
.convertHexLiteral(isLongLiteral = false)
|
||||
.convertOctalLiteral(),
|
||||
JKLiteralExpression.LiteralType.INT
|
||||
)
|
||||
|
||||
|
||||
private fun JKLiteralExpression.toLongLiteral(): JKKtLiteralExpression =
|
||||
JKKtLiteralExpressionImpl(
|
||||
literal
|
||||
.replace("l", "", ignoreCase = true)
|
||||
.convertHexLiteral(isLongLiteral = true)
|
||||
.convertOctalLiteral() + "L",
|
||||
JKLiteralExpression.LiteralType.LONG
|
||||
)
|
||||
|
||||
private fun String.convertHexLiteral(isLongLiteral: Boolean): String {
|
||||
if (!startsWith("0x", ignoreCase = true)) return this
|
||||
val value = BigInteger(drop(2), 16)
|
||||
return when {
|
||||
isLongLiteral && value.bitLength() > 63 ->
|
||||
"-0x${value.toLong().toString(16).substring(1)}"
|
||||
|
||||
!isLongLiteral && value.bitLength() > 31 ->
|
||||
"-0x${value.toInt().toString(16).substring(1)}"
|
||||
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.convertOctalLiteral(): String {
|
||||
if (!startsWith("0") || length == 1 || get(1).toLowerCase() == 'x') return this
|
||||
val value = BigInteger(drop(1), 8)
|
||||
return value.toString()
|
||||
}
|
||||
|
||||
private fun String.cleanFloatAndDoubleLiterals() =
|
||||
replace("L", "", ignoreCase = true)
|
||||
.replace("d", "", ignoreCase = true)
|
||||
.replace(".e", "e", ignoreCase = true)
|
||||
.replace(".f", "", ignoreCase = true)
|
||||
.replace("f", "", ignoreCase = true)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.math.BigInteger
|
||||
|
||||
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType =
|
||||
JKClassTypeImpl(
|
||||
@@ -375,104 +374,6 @@ fun JKVariable.hasWritableUsages(scope: JKTreeElement, context: NewJ2kConverterC
|
||||
|| 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
|
||||
}.withNonCodeElementsFrom(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").let {
|
||||
if (!it.endsWith("L")) it + "L" else it
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
fun equalsExpression(left: JKExpression, right: JKExpression, symbolProvider: JKSymbolProvider) =
|
||||
kotlinBinaryExpression(
|
||||
left,
|
||||
|
||||
Reference in New Issue
Block a user