J2K: convert method references according to special methods
This commit is contained in:
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.j2k
|
|||||||
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
@@ -728,14 +729,42 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val callParams = if (needThis) parameters.drop(1) else parameters
|
val callParams = if (needThis) parameters.drop(1) else parameters
|
||||||
val statement = if (expression.isConstructor) {
|
|
||||||
MethodCallExpression.build(null, convertMethodReferenceQualifier(qualifier), callParams.map { it.first }, emptyList(), false).assignNoPrototype()
|
val specialMethod = method?.let { SpecialMethod.match(it, callParams.size, converter.services) }
|
||||||
|
val statement: Statement = if (expression.isConstructor) {
|
||||||
|
MethodCallExpression.build(null, convertMethodReferenceQualifier(qualifier), callParams.map { it.first }, emptyList(), false)
|
||||||
|
}
|
||||||
|
else if (specialMethod != null) {
|
||||||
|
val factory = PsiElementFactory.SERVICE.getInstance(converter.project)
|
||||||
|
val fakeReceiver = receiver?.let {
|
||||||
|
val psiExpression = if (qualifier is PsiExpression) qualifier else factory.createExpressionFromText("fakeReceiver", null)
|
||||||
|
psiExpression.convertedExpression = it.first
|
||||||
|
psiExpression
|
||||||
|
}
|
||||||
|
val fakeParams = callParams.mapIndexed {
|
||||||
|
i, param ->
|
||||||
|
with(factory.createExpressionFromText("fake$i", null)) {
|
||||||
|
this.convertedExpression = param.first
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val patchedConverter = codeConverter.withSpecialExpressionConverter(object : SpecialExpressionConverter {
|
||||||
|
override fun convertExpression(expression: PsiExpression, codeConverter: CodeConverter): Expression? {
|
||||||
|
val convertedExpression = expression.convertedExpression
|
||||||
|
expression.convertedExpression = null
|
||||||
|
return convertedExpression
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
specialMethod.convertCall(fakeReceiver, fakeParams.toTypedArray(), emptyList(), patchedConverter)!!
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val referenceName = expression.referenceName!!
|
val referenceName = expression.referenceName!!
|
||||||
MethodCallExpression.build(receiver?.first, referenceName, callParams.map { it.first }, emptyList(), false).assignNoPrototype()
|
MethodCallExpression.build(receiver?.first, referenceName, callParams.map { it.first }, emptyList(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statement.assignNoPrototype()
|
||||||
|
|
||||||
val lambdaParameterList = ParameterList(
|
val lambdaParameterList = ParameterList(
|
||||||
if (parameters.size == 1 && !isKotlinFunctionType) {
|
if (parameters.size == 1 && !isKotlinFunctionType) {
|
||||||
// for lambdas all parameters with types should be present
|
// for lambdas all parameters with types should be present
|
||||||
@@ -766,6 +795,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var PsiExpression.convertedExpression: Expression? by UserDataProperty(Key.create("CONVERTED_EXPRESSION"))
|
||||||
|
|
||||||
private fun isFunctionType(functionalType: PsiType?) = functionalType?.canonicalText?.startsWith("kotlin.jvm.functions.Function") ?: false
|
private fun isFunctionType(functionalType: PsiType?) = functionalType?.canonicalText?.startsWith("kotlin.jvm.functions.Function") ?: false
|
||||||
|
|
||||||
private fun convertMethodReferenceQualifier(qualifier: PsiElement): String {
|
private fun convertMethodReferenceQualifier(qualifier: PsiElement): String {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// ERROR: Type inference failed: Not enough information to infer parameter T in fun <T : kotlin.Any!> emptyList(): kotlin.collections.(Mutable)List<T!>! Please specify it explicitly.
|
// ERROR: Type inference failed: Not enough information to infer parameter T in fun <T> emptyList(): kotlin.collections.List<T> Please specify it explicitly.
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
@@ -72,7 +72,7 @@ internal class Java8Class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testLibraryFunctions() {
|
fun testLibraryFunctions() {
|
||||||
val memberFunFromClass = { obj: String -> obj.length() }
|
val memberFunFromClass = { obj: String -> obj.length }
|
||||||
memberFunFromClass.invoke("str")
|
memberFunFromClass.invoke("str")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ internal class Java8Class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testGenericFunctions() {
|
fun testGenericFunctions() {
|
||||||
val emptyList = { Collections.emptyList() }
|
val emptyList = { emptyList() }
|
||||||
emptyList.invoke()
|
emptyList.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,11 +117,11 @@ internal class Java8Class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testLibraryFunctions() {
|
fun testLibraryFunctions() {
|
||||||
val memberFunFromClass = JFunction2<String, Int> { it.length() }
|
val memberFunFromClass = JFunction2<String, Int> { it.length }
|
||||||
memberFunFromClass.foo("str")
|
memberFunFromClass.foo("str")
|
||||||
|
|
||||||
Thread(Runnable { System.out.println() }).start()
|
Thread(Runnable { println() }).start()
|
||||||
Runnable { System.out.println() }.run()
|
Runnable { println() }.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testOverloads() {
|
fun testOverloads() {
|
||||||
@@ -137,10 +137,10 @@ internal class Java8Class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testGenericFunctions() {
|
fun testGenericFunctions() {
|
||||||
val emptyList = JFunction1<List<String>> { Collections.emptyList() }
|
val emptyList = JFunction1<List<String>> { emptyList() }
|
||||||
emptyList.foo()
|
emptyList.foo()
|
||||||
MethodReferenceHelperClass.staticFun1(JFunction1<List<String>> { Collections.emptyList() })
|
MethodReferenceHelperClass.staticFun1(JFunction1<List<String>> { emptyList() })
|
||||||
h.memberFun1(JFunction1<List<String>> { Collections.emptyList() })
|
h.memberFun1(JFunction1<List<String>> { emptyList() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun memberFun(): Int {
|
fun memberFun(): Int {
|
||||||
|
|||||||
Reference in New Issue
Block a user