diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt index 1b4d9b0ff58..6b14a3c9545 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.j2k import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Errors @@ -36,6 +37,7 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getType import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.utils.mapToIndex import java.util.* @@ -60,6 +62,7 @@ object J2KPostProcessingRegistrar { _processings.add(RemoveExplicitTypeArgumentsProcessing()) _processings.add(RemoveRedundantOverrideVisibilityProcessing()) _processings.add(MoveLambdaOutsideParenthesesProcessing()) + _processings.add(FixObjectStringConcatenationProcessing()) _processings.add(ConvertToStringTemplateProcessing()) _processings.add(UsePropertyAccessSyntaxProcessing()) _processings.add(RemoveRedundantSamAdaptersProcessing()) @@ -243,4 +246,31 @@ object J2KPostProcessingRegistrar { return null } } + + private class FixObjectStringConcatenationProcessing : J2kPostProcessing { + override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { + if (element !is KtBinaryExpression || + element.operationToken != KtTokens.PLUS || + diagnostics.forElement(element.operationReference).none { + it.factory == Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER + || it.factory == Errors.NONE_APPLICABLE + }) + return null + + val bindingContext = element.analyzeAndGetResult().bindingContext + val rightType = element.right?.getType(bindingContext) ?: return null + + if (KotlinBuiltIns.isString(rightType)) { + return { + val factory = KtPsiFactory(element) + element.left!!.replace(factory.buildExpression { + appendFixedText("(") + appendExpression(element.left) + appendFixedText(").toString()") + }) + } + } + return null + } + } } \ No newline at end of file diff --git a/j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.java b/j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.java new file mode 100644 index 00000000000..d89e4301bb9 --- /dev/null +++ b/j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.java @@ -0,0 +1,22 @@ +public class Test { + public static class B { + public static class C { + + } + + public C c() { + return new C(); + } + } + + public void a() { + B b = new B(); + System.out.println(b + ""); + String a = 1 + "0"; + System.out.println(b.c() + ""); + } + + public static void main(String[] args) { + String p = new Test() + "123"; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.kt b/j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.kt new file mode 100644 index 00000000000..e2855e7f08d --- /dev/null +++ b/j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.kt @@ -0,0 +1,23 @@ +class Test { + class B { + class C + + fun c(): C { + return C() + } + } + + fun a() { + val b = B() + println(b.toString() + "") + val a = 1.toString() + "0" + println(b.c().toString() + "") + } + + companion object { + + @JvmStatic fun main(args: Array) { + val p = Test().toString() + "123" + } + } +} \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index 67a95d2be19..5729b975ddf 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -553,6 +553,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("lhsObjectPlusString.java") + public void testLhsObjectPlusString() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.java"); + doTest(fileName); + } + @TestMetadata("minus.java") public void testMinus() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/binaryExpression/minus.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 97a2bdeda73..a0a9e4b91ee 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -553,6 +553,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("lhsObjectPlusString.java") + public void testLhsObjectPlusString() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/binaryExpression/lhsObjectPlusString.java"); + doTest(fileName); + } + @TestMetadata("minus.java") public void testMinus() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/binaryExpression/minus.java");