New J2K: Fix support of kotlin method calls

This commit is contained in:
Ilya Kirillov
2019-01-28 12:07:44 +03:00
committed by Ilya Kirillov
parent 9a8f8fbfe0
commit 8b12a9f723
4 changed files with 44 additions and 17 deletions
@@ -94,6 +94,7 @@ object NewJ2KPostProcessingRegistrarImpl : J2KPostProcessingRegistrar {
SingleProcessing(RemoveExplicitTypeArgumentsProcessing()), SingleProcessing(RemoveExplicitTypeArgumentsProcessing()),
SingleProcessing(RemoveRedundantOverrideVisibilityProcessing()), SingleProcessing(RemoveRedundantOverrideVisibilityProcessing()),
registerInspectionBasedProcessing(MoveLambdaOutsideParenthesesInspection()), registerInspectionBasedProcessing(MoveLambdaOutsideParenthesesInspection()),
registerGeneralInspectionBasedProcessing(RedundantCompanionReferenceInspection()),
SingleProcessing(FixObjectStringConcatenationProcessing()), SingleProcessing(FixObjectStringConcatenationProcessing()),
SingleProcessing(ConvertToStringTemplateProcessing()), SingleProcessing(ConvertToStringTemplateProcessing()),
SingleProcessing(UsePropertyAccessSyntaxProcessing()), SingleProcessing(UsePropertyAccessSyntaxProcessing()),
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.j2k package org.jetbrains.kotlin.j2k
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.j2k.conversions.multiResolveFqName import org.jetbrains.kotlin.j2k.conversions.multiResolveFqName
import org.jetbrains.kotlin.j2k.conversions.resolveFqName import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.j2k.tree.*
@@ -30,6 +32,7 @@ class JKSymbolProvider {
fun provideDirectSymbol(psi: PsiElement): JKSymbol { fun provideDirectSymbol(psi: PsiElement): JKSymbol {
return symbolsByPsi.getOrPut(psi) { return symbolsByPsi.getOrPut(psi) {
when (psi) { when (psi) {
is KtLightDeclaration<*, *> -> provideDirectSymbol(psi.kotlinOrigin!!)
is PsiClass -> JKMultiverseClassSymbol(psi) is PsiClass -> JKMultiverseClassSymbol(psi)
is KtClassOrObject -> JKMultiverseKtClassSymbol(psi) is KtClassOrObject -> JKMultiverseKtClassSymbol(psi)
is PsiMethod -> JKMultiverseMethodSymbol(psi, this) is PsiMethod -> JKMultiverseMethodSymbol(psi, this)
@@ -27,6 +27,7 @@ import com.intellij.psi.tree.IElementType
import com.intellij.psi.util.InheritanceUtil import com.intellij.psi.util.InheritanceUtil
import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.PsiUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.j2k.content import org.jetbrains.kotlin.idea.j2k.content
import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.ast.Nullability
@@ -202,17 +203,19 @@ class JavaToJKTreeBuilder(
} }
private fun JKExpression.qualified(qualifier: JKExpression?) = private fun JKExpression.qualified(qualifier: JKExpression?) =
if (qualifier != null) { if (qualifier != null && qualifier !is JKStubExpression) {
JKQualifiedExpressionImpl(qualifier, JKJavaQualifierImpl.DOT, this) JKQualifiedExpressionImpl(qualifier, JKJavaQualifierImpl.DOT, this)
} else this } else this
//TODO mostly copied from old j2k, refactor //TODO mostly copied from old j2k, refactor
fun PsiMethodCallExpression.toJK(): JKExpression { fun PsiMethodCallExpression.toJK(): JKExpression {
val arguments = argumentList.toJK() val arguments = argumentList
val typeArguments = typeArgumentList.toJK() val typeArguments = typeArgumentList.toJK()
val qualifier = methodExpression.qualifierExpression?.toJK() val qualifier = methodExpression.qualifierExpression?.toJK()
val target = methodExpression.resolve() val target = methodExpression.resolve()
val symbol = symbolProvider.provideSymbol<JKMethodSymbol>(methodExpression as PsiReferenceExpressionImpl) val symbol = target?.let {
symbolProvider.provideDirectSymbol(it)
} ?: JKUnresolvedMethod(methodExpression)
return when { return when {
methodExpression.referenceNameElement is PsiKeyword -> { methodExpression.referenceNameElement is PsiKeyword -> {
@@ -221,7 +224,7 @@ class JavaToJKTreeBuilder(
THIS_KEYWORD -> JKThisExpressionImpl(JKLabelEmptyImpl()) THIS_KEYWORD -> JKThisExpressionImpl(JKLabelEmptyImpl())
else -> error("Unknown keyword in callee position") else -> error("Unknown keyword in callee position")
} }
JKDelegationConstructorCallImpl(symbol, callee, arguments) JKDelegationConstructorCallImpl(symbol as JKMethodSymbol, callee, arguments.toJK())
} }
target is KtLightMethod -> { target is KtLightMethod -> {
@@ -229,16 +232,16 @@ class JavaToJKTreeBuilder(
when (origin) { when (origin) {
is KtNamedFunction -> { is KtNamedFunction -> {
if (origin.isExtensionDeclaration()) { if (origin.isExtensionDeclaration()) {
val receiver = arguments.expressions.firstOrNull() val receiver = arguments.expressions.firstOrNull()?.toJK()?.parenthesizeIfBinaryExpression()
JKJavaMethodCallExpressionImpl( JKJavaMethodCallExpressionImpl(
symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol, symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol,
arguments.also { it.expressions = it.expressions.drop(1) }, arguments.expressions.drop(1).map { it.toJK() }.toExpressionList(),
typeArguments typeArguments
).qualified(receiver) ).qualified(receiver)
} else { } else {
JKJavaMethodCallExpressionImpl( JKJavaMethodCallExpressionImpl(
symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol, symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol,
arguments, arguments.expressions.map { it.toJK() }.toExpressionList(),
typeArguments typeArguments
).qualified(qualifier) ).qualified(qualifier)
} }
@@ -254,7 +257,7 @@ class JavaToJKTreeBuilder(
val isTopLevel = origin.getStrictParentOfType<KtClassOrObject>() == null val isTopLevel = origin.getStrictParentOfType<KtClassOrObject>() == null
val propertyAccess = if (isTopLevel) { val propertyAccess = if (isTopLevel) {
if (isExtension) JKQualifiedExpressionImpl( if (isExtension) JKQualifiedExpressionImpl(
arguments.expressions.first().detached(arguments), arguments.expressions.first().toJK(),
JKJavaQualifierImpl.DOT, JKJavaQualifierImpl.DOT,
propertyAccessExpression propertyAccessExpression
) )
@@ -266,7 +269,7 @@ class JavaToJKTreeBuilder(
propertyAccess propertyAccess
1 /* setter */ -> { 1 /* setter */ -> {
val argument = (arguments.expressions[if (isExtension) 1 else 0]).detached(arguments) val argument = (arguments.expressions[if (isExtension) 1 else 0]).toJK()
JKJavaAssignmentExpressionImpl( JKJavaAssignmentExpressionImpl(
propertyAccess, propertyAccess,
argument, argument,
@@ -281,23 +284,31 @@ class JavaToJKTreeBuilder(
} }
} }
target is PsiMethod -> symbol is JKMethodSymbol ->
JKJavaMethodCallExpressionImpl(symbol, arguments, typeArguments) JKJavaMethodCallExpressionImpl(symbol, arguments.toJK(), typeArguments)
.qualified(qualifier)
else ->
JKJavaMethodCallExpressionImpl(symbol, arguments, typeArguments)
.qualified(qualifier) .qualified(qualifier)
symbol is JKFieldSymbol ->
JKFieldAccessExpressionImpl(symbol).qualified(qualifier)
else -> TODO(text)
} }
} }
fun PsiReferenceExpression.toJK(): JKExpression { fun PsiReferenceExpression.toJK(): JKExpression {
val target = resolve()
if (target is KtLightClassForFacade) return JKStubExpressionImpl()
if (target is KtLightField
&& target.name == "INSTANCE"
&& target.containingClass.kotlinOrigin is KtObjectDeclaration
) {
return qualifierExpression?.toJK() ?: JKStubExpressionImpl()
}
val symbol = symbolProvider.provideSymbol(this) val symbol = symbolProvider.provideSymbol(this)
val access = when (symbol) { return when (symbol) {
is JKClassSymbol -> JKClassAccessExpressionImpl(symbol) is JKClassSymbol -> JKClassAccessExpressionImpl(symbol)
is JKFieldSymbol -> JKFieldAccessExpressionImpl(symbol) is JKFieldSymbol -> JKFieldAccessExpressionImpl(symbol)
else -> TODO() else -> TODO()
} }.qualified(qualifierExpression?.toJK())
return qualifierExpression?.let { JKQualifiedExpressionImpl(it.toJK(), JKJavaQualifierImpl.DOT, access) } ?: access
} }
fun PsiArrayInitializerExpression.toJK(): JKExpression { fun PsiArrayInitializerExpression.toJK(): JKExpression {
@@ -221,6 +221,15 @@ fun downToExpression(
psiContext psiContext
) )
fun List<JKExpression>.toExpressionList() =
JKExpressionListImpl(this)
fun JKExpression.parenthesizeIfBinaryExpression() =
when (this) {
is JKBinaryExpression -> JKParenthesizedExpressionImpl(this)
else -> this
}
fun rangeExpression( fun rangeExpression(
from: JKExpression, from: JKExpression,
to: JKExpression, to: JKExpression,
@@ -237,6 +246,9 @@ fun rangeExpression(
fun blockStatement(vararg statements: JKStatement) = fun blockStatement(vararg statements: JKStatement) =
JKBlockStatementImpl(JKBlockImpl(statements.toList())) JKBlockStatementImpl(JKBlockImpl(statements.toList()))
fun blockStatement(statements: List<JKStatement>) =
JKBlockStatementImpl(JKBlockImpl(statements))
fun useExpression( fun useExpression(
receiver: JKExpression, receiver: JKExpression,
variableIdentifier: JKNameIdentifier, variableIdentifier: JKNameIdentifier,