From 92af61032291ce323a441f0a2f28146a16d4f393 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 28 Apr 2016 19:55:36 +0300 Subject: [PATCH] KT-12045 J2K: creating `Object()` instance could be converted to `Any()` #KT-12045 Fixed --- .../OnlyOneBraceFromBlock.expected.kt | 2 +- j2k/src/org/jetbrains/kotlin/j2k/Converter.kt | 13 ++++-- .../org/jetbrains/kotlin/j2k/TypeConverter.kt | 4 +- .../org/jetbrains/kotlin/j2k/TypeVisitor.kt | 41 +----------------- j2k/src/org/jetbrains/kotlin/j2k/Utils.kt | 43 +++++++++++++++++++ .../issues/doNotQualifyStatic.kt | 2 +- .../methodCallExpression/stringMethods.kt | 2 +- .../newClassExpression/javaLangObject.java | 6 +++ .../newClassExpression/javaLangObject.kt | 8 ++++ ...otlinConverterForWebDemoTestGenerated.java | 6 +++ ...otlinConverterSingleFileTestGenerated.java | 6 +++ 11 files changed, 85 insertions(+), 48 deletions(-) create mode 100644 j2k/testData/fileOrElement/newClassExpression/javaLangObject.java create mode 100644 j2k/testData/fileOrElement/newClassExpression/javaLangObject.kt diff --git a/idea/testData/copyPaste/conversion/OnlyOneBraceFromBlock.expected.kt b/idea/testData/copyPaste/conversion/OnlyOneBraceFromBlock.expected.kt index 1b35a12f474..e394a9d95cf 100644 --- a/idea/testData/copyPaste/conversion/OnlyOneBraceFromBlock.expected.kt +++ b/idea/testData/copyPaste/conversion/OnlyOneBraceFromBlock.expected.kt @@ -1,4 +1,4 @@ fun main(args: Array) { { - val a = Object() + val a = Any() } \ No newline at end of file diff --git a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt index 95ab15aaf45..8658f9d667c 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt @@ -155,7 +155,7 @@ class Converter private constructor( } private fun convertFile(javaFile: PsiJavaFile): File { - var convertedChildren = javaFile.children.mapNotNull { convertTopElement(it) } + val convertedChildren = javaFile.children.mapNotNull { convertTopElement(it) } return File(convertedChildren).assignPrototype(javaFile) } @@ -537,10 +537,10 @@ class Converter private constructor( } } - var params = convertParameterList(method, overloadReducer) + val params = convertParameterList(method, overloadReducer) val typeParameterList = convertTypeParameterList(method.typeParameterList) - var body = deferredElement { codeConverter: CodeConverter -> + val body = deferredElement { codeConverter: CodeConverter -> val body = codeConverter.withMethodReturnType(method.returnType).convertBlock(method.body) postProcessBody(body) } @@ -617,6 +617,12 @@ class Converter private constructor( fun convertCodeReferenceElement(element: PsiJavaCodeReferenceElement, hasExternalQualifier: Boolean, typeArgsConverted: List? = null): ReferenceElement { val typeArgs = typeArgsConverted ?: typeConverter.convertTypes(element.typeParameters) + val targetClass = element.resolve() as? PsiClass + if (targetClass != null) { + convertToKotlinAnalogIdentifier(targetClass.qualifiedName, Mutability.Default) + ?.let { return ReferenceElement(it, typeArgs).assignNoPrototype() } + } + if (element.isQualified) { var result = Identifier.toKotlin(element.referenceName!!) var qualifier = element.qualifier @@ -630,7 +636,6 @@ class Converter private constructor( else { if (!hasExternalQualifier) { // references to nested classes may need correction - val targetClass = element.resolve() as? PsiClass if (targetClass != null) { val identifier = constructNestedClassReferenceIdentifier(targetClass, specialContext ?: element) if (identifier != null) { diff --git a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt index f1b2d25c292..d4a841fad14 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/TypeConverter.kt @@ -374,7 +374,7 @@ class TypeConverter(val converter: Converter) { override fun fromType(type: PsiType): Mutability { val target = (type as? PsiClassType)?.resolve() ?: return Mutability.NonMutable - if (target.qualifiedName !in TypeVisitor.toKotlinMutableTypesMap.keys) return Mutability.NonMutable + if (target.qualifiedName !in toKotlinMutableTypesMap.keys) return Mutability.NonMutable return Mutability.Default } @@ -437,6 +437,6 @@ class TypeConverter(val converter: Converter) { "add", "remove", "set", "addAll", "removeAll", "retainAll", "clear", "put", "putAll", "putIfAbsent", "replace", "replaceAll", "merge", "compute", "computeIfAbsent", "computeIfPresent" ) - private val mutableKotlinClasses = TypeVisitor.toKotlinMutableTypesMap.values.toSet() + private val mutableKotlinClasses = toKotlinMutableTypesMap.values.toSet() } } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/TypeVisitor.kt b/j2k/src/org/jetbrains/kotlin/j2k/TypeVisitor.kt index 39f631e3b64..ddcd85380df 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/TypeVisitor.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/TypeVisitor.kt @@ -70,10 +70,8 @@ class TypeVisitor( val psiClass = classType.resolve() if (psiClass != null) { val javaClassName = psiClass.qualifiedName - val kotlinClassName = (if (mutability.isMutable(converter.settings)) toKotlinMutableTypesMap[javaClassName] else null) - ?: toKotlinTypesMap[javaClassName] - if (kotlinClassName != null) { - return ReferenceElement(Identifier(getShortName(kotlinClassName)).assignNoPrototype(), typeArgs).assignNoPrototype() + converter.convertToKotlinAnalogIdentifier(javaClassName, mutability)?.let { + return ReferenceElement(it, typeArgs).assignNoPrototype() } if (inAnnotationType && javaClassName == "java.lang.Class") { @@ -90,8 +88,6 @@ class TypeVisitor( return ReferenceElement(Identifier(classType.className ?: "").assignNoPrototype(), typeArgs).assignNoPrototype() } - private fun getShortName(className: String): String = className.substringAfterLast('.', className) - private fun convertTypeArgs(classType: PsiClassType): List { if (classType.parameterCount == 0) { return createTypeArgsForRawTypeUsage(classType, Mutability.Default) @@ -122,37 +118,4 @@ class TypeVisitor( override fun visitEllipsisType(ellipsisType: PsiEllipsisType): Type { return VarArgType(typeConverter.convertType(ellipsisType.componentType, inAnnotationType = inAnnotationType)) } - - companion object { - private val toKotlinTypesMap: Map = mapOf( - CommonClassNames.JAVA_LANG_OBJECT to BUILTIN_NAMES.any.asString(), - CommonClassNames.JAVA_LANG_BYTE to BUILTIN_NAMES._byte.asString(), - CommonClassNames.JAVA_LANG_CHARACTER to BUILTIN_NAMES._char.asString(), - CommonClassNames.JAVA_LANG_DOUBLE to BUILTIN_NAMES._double.asString(), - CommonClassNames.JAVA_LANG_FLOAT to BUILTIN_NAMES._float.asString(), - CommonClassNames.JAVA_LANG_INTEGER to BUILTIN_NAMES._int.asString(), - CommonClassNames.JAVA_LANG_LONG to BUILTIN_NAMES._long.asString(), - CommonClassNames.JAVA_LANG_SHORT to BUILTIN_NAMES._short.asString(), - CommonClassNames.JAVA_LANG_BOOLEAN to BUILTIN_NAMES._boolean.asString(), - CommonClassNames.JAVA_LANG_ITERABLE to BUILTIN_NAMES.iterable.asString(), - CommonClassNames.JAVA_UTIL_ITERATOR to BUILTIN_NAMES.iterator.asString(), - CommonClassNames.JAVA_UTIL_LIST to BUILTIN_NAMES.list.asString(), - CommonClassNames.JAVA_UTIL_COLLECTION to BUILTIN_NAMES.collection.asString(), - CommonClassNames.JAVA_UTIL_SET to BUILTIN_NAMES.set.asString(), - CommonClassNames.JAVA_UTIL_MAP to BUILTIN_NAMES.map.asString(), - CommonClassNames.JAVA_UTIL_MAP_ENTRY to BUILTIN_NAMES.mapEntry.asString(), - java.util.ListIterator::class.java.canonicalName to BUILTIN_NAMES.listIterator.asString() - - ) - - val toKotlinMutableTypesMap: Map = mapOf( - CommonClassNames.JAVA_UTIL_ITERATOR to BUILTIN_NAMES.mutableIterator.asString(), - CommonClassNames.JAVA_UTIL_LIST to BUILTIN_NAMES.mutableList.asString(), - CommonClassNames.JAVA_UTIL_COLLECTION to BUILTIN_NAMES.mutableCollection.asString(), - CommonClassNames.JAVA_UTIL_SET to BUILTIN_NAMES.mutableSet.asString(), - CommonClassNames.JAVA_UTIL_MAP to BUILTIN_NAMES.mutableMap.asString(), - CommonClassNames.JAVA_UTIL_MAP_ENTRY to BUILTIN_NAMES.mutableMapEntry.asString(), - java.util.ListIterator::class.java.canonicalName to BUILTIN_NAMES.mutableListIterator.asString() - ) - } } diff --git a/j2k/src/org/jetbrains/kotlin/j2k/Utils.kt b/j2k/src/org/jetbrains/kotlin/j2k/Utils.kt index b931935bb70..39d4adc7a7e 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/Utils.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.j2k import com.intellij.psi.* import com.intellij.psi.util.PsiMethodUtil import org.jetbrains.kotlin.asJava.KtLightClass +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -129,3 +130,45 @@ fun PsiExpression.isNullLiteral() = this is PsiLiteralExpression && type == PsiT // TODO: set origin for facade classes in library fun isFacadeClassFromLibrary(element: PsiElement?) = element is KtLightClass && element.kotlinOrigin == null + +fun Converter.convertToKotlinAnalog(classQualifiedName: String?, mutability: Mutability): String? { + if (classQualifiedName == null) return null + return (if (mutability.isMutable(settings)) toKotlinMutableTypesMap[classQualifiedName] else null) + ?: toKotlinTypesMap[classQualifiedName] +} + +fun Converter.convertToKotlinAnalogIdentifier(classQualifiedName: String?, mutability: Mutability): Identifier? { + val kotlinClassName = convertToKotlinAnalog(classQualifiedName, mutability) ?: return null + return Identifier(kotlinClassName.substringAfterLast('.')).assignNoPrototype() +} + +private val toKotlinTypesMap: Map = mapOf( + CommonClassNames.JAVA_LANG_OBJECT to KotlinBuiltIns.FQ_NAMES.any.asString(), + CommonClassNames.JAVA_LANG_BYTE to KotlinBuiltIns.FQ_NAMES._byte.asString(), + CommonClassNames.JAVA_LANG_CHARACTER to KotlinBuiltIns.FQ_NAMES._char.asString(), + CommonClassNames.JAVA_LANG_DOUBLE to KotlinBuiltIns.FQ_NAMES._double.asString(), + CommonClassNames.JAVA_LANG_FLOAT to KotlinBuiltIns.FQ_NAMES._float.asString(), + CommonClassNames.JAVA_LANG_INTEGER to KotlinBuiltIns.FQ_NAMES._int.asString(), + CommonClassNames.JAVA_LANG_LONG to KotlinBuiltIns.FQ_NAMES._long.asString(), + CommonClassNames.JAVA_LANG_SHORT to KotlinBuiltIns.FQ_NAMES._short.asString(), + CommonClassNames.JAVA_LANG_BOOLEAN to KotlinBuiltIns.FQ_NAMES._boolean.asString(), + CommonClassNames.JAVA_LANG_ITERABLE to KotlinBuiltIns.FQ_NAMES.iterable.asString(), + CommonClassNames.JAVA_UTIL_ITERATOR to KotlinBuiltIns.FQ_NAMES.iterator.asString(), + CommonClassNames.JAVA_UTIL_LIST to KotlinBuiltIns.FQ_NAMES.list.asString(), + CommonClassNames.JAVA_UTIL_COLLECTION to KotlinBuiltIns.FQ_NAMES.collection.asString(), + CommonClassNames.JAVA_UTIL_SET to KotlinBuiltIns.FQ_NAMES.set.asString(), + CommonClassNames.JAVA_UTIL_MAP to KotlinBuiltIns.FQ_NAMES.map.asString(), + CommonClassNames.JAVA_UTIL_MAP_ENTRY to KotlinBuiltIns.FQ_NAMES.mapEntry.asString(), + java.util.ListIterator::class.java.canonicalName to KotlinBuiltIns.FQ_NAMES.listIterator.asString() + +) + +val toKotlinMutableTypesMap: Map = mapOf( + CommonClassNames.JAVA_UTIL_ITERATOR to KotlinBuiltIns.FQ_NAMES.mutableIterator.asString(), + CommonClassNames.JAVA_UTIL_LIST to KotlinBuiltIns.FQ_NAMES.mutableList.asString(), + CommonClassNames.JAVA_UTIL_COLLECTION to KotlinBuiltIns.FQ_NAMES.mutableCollection.asString(), + CommonClassNames.JAVA_UTIL_SET to KotlinBuiltIns.FQ_NAMES.mutableSet.asString(), + CommonClassNames.JAVA_UTIL_MAP to KotlinBuiltIns.FQ_NAMES.mutableMap.asString(), + CommonClassNames.JAVA_UTIL_MAP_ENTRY to KotlinBuiltIns.FQ_NAMES.mutableMapEntry.asString(), + java.util.ListIterator::class.java.canonicalName to KotlinBuiltIns.FQ_NAMES.mutableListIterator.asString() +) diff --git a/j2k/testData/fileOrElement/issues/doNotQualifyStatic.kt b/j2k/testData/fileOrElement/issues/doNotQualifyStatic.kt index f559b9177ce..e749d37eacf 100644 --- a/j2k/testData/fileOrElement/issues/doNotQualifyStatic.kt +++ b/j2k/testData/fileOrElement/issues/doNotQualifyStatic.kt @@ -1,5 +1,5 @@ internal object Outer { - var o: Any? = Object() + var o: Any? = Any() class Nested { fun foo() { diff --git a/j2k/testData/fileOrElement/methodCallExpression/stringMethods.kt b/j2k/testData/fileOrElement/methodCallExpression/stringMethods.kt index 6621286cf07..060ec957d16 100644 --- a/j2k/testData/fileOrElement/methodCallExpression/stringMethods.kt +++ b/j2k/testData/fileOrElement/methodCallExpression/stringMethods.kt @@ -103,7 +103,7 @@ internal class A { true.toString() 1.11f.toString() 3.14.toString() - Object().toString() + Any().toString() String.format(Locale.FRENCH, "Je ne mange pas %d jours", 6) String.format("Operation completed with %s", "success") diff --git a/j2k/testData/fileOrElement/newClassExpression/javaLangObject.java b/j2k/testData/fileOrElement/newClassExpression/javaLangObject.java new file mode 100644 index 00000000000..ae8f34f8892 --- /dev/null +++ b/j2k/testData/fileOrElement/newClassExpression/javaLangObject.java @@ -0,0 +1,6 @@ +class C { + void foo() { + Object o1 = new Object() {}; + Object o2 = new Object(); + } +} diff --git a/j2k/testData/fileOrElement/newClassExpression/javaLangObject.kt b/j2k/testData/fileOrElement/newClassExpression/javaLangObject.kt new file mode 100644 index 00000000000..19828ea2875 --- /dev/null +++ b/j2k/testData/fileOrElement/newClassExpression/javaLangObject.kt @@ -0,0 +1,8 @@ +internal class C { + fun foo() { + val o1 = object : Any() { + + } + val o2 = Any() + } +} diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index 31f2ee9dcb6..e1b2ec362ee 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -3460,6 +3460,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("javaLangObject.java") + public void testJavaLangObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/newClassExpression/javaLangObject.java"); + doTest(fileName); + } + @TestMetadata("lineBreaks.java") public void testLineBreaks() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/newClassExpression/lineBreaks.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 6de10f5b4b2..d737c4fd99a 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -3460,6 +3460,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("javaLangObject.java") + public void testJavaLangObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/newClassExpression/javaLangObject.java"); + doTest(fileName); + } + @TestMetadata("lineBreaks.java") public void testLineBreaks() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/newClassExpression/lineBreaks.java");