From cb4474b9a462323d28a499cfa74762fe061f57b1 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 29 May 2018 19:07:19 +0300 Subject: [PATCH] New J2K: Add literal conversion --- .../jetbrains/kotlin/j2k/ConversionsRunner.kt | 6 +- .../j2k/conversions/LiteralConversion.kt | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/LiteralConversion.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index 3523e3f23bc..467ba6e0b0d 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.j2k -import org.jetbrains.kotlin.j2k.conversions.AssignmentAsExpressionToAlsoConversion -import org.jetbrains.kotlin.j2k.conversions.FieldToPropertyConversion -import org.jetbrains.kotlin.j2k.conversions.JavaMethodToKotlinFunctionConversion -import org.jetbrains.kotlin.j2k.conversions.TypeMappingConversion +import org.jetbrains.kotlin.j2k.conversions.* import org.jetbrains.kotlin.j2k.tree.JKTreeElement object ConversionsRunner { @@ -31,6 +28,7 @@ object ConversionsRunner { TypeMappingConversion(context).runConversion(it, context) AssignmentAsExpressionToAlsoConversion(context).runConversion(it, context) JavaMethodToKotlinFunctionConversion().runConversion(it, context) + LiteralConversion().runConversion(it, context) } } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/LiteralConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/LiteralConversion.kt new file mode 100644 index 00000000000..863e521ae2e --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/LiteralConversion.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.j2k.conversions + +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) + + 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), + 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 + ) + } + +}