New J2K: Add resolving for kotlin properties and object members calls
This commit is contained in:
committed by
Ilya Kirillov
parent
db8beab499
commit
5fc9ca8fc7
@@ -21,10 +21,17 @@ import com.intellij.psi.JavaTokenType.SUPER_KEYWORD
|
|||||||
import com.intellij.psi.JavaTokenType.THIS_KEYWORD
|
import com.intellij.psi.JavaTokenType.THIS_KEYWORD
|
||||||
import com.intellij.psi.impl.source.tree.ChildRole
|
import com.intellij.psi.impl.source.tree.ChildRole
|
||||||
import com.intellij.psi.impl.source.tree.java.*
|
import com.intellij.psi.impl.source.tree.java.*
|
||||||
import org.jetbrains.kotlin.j2k.ast.Nullability
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.j2k.ast.*
|
||||||
|
import org.jetbrains.kotlin.j2k.ast.LiteralExpression.NullLiteral.isNullable
|
||||||
import org.jetbrains.kotlin.j2k.tree.*
|
import org.jetbrains.kotlin.j2k.tree.*
|
||||||
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
|
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
|
||||||
|
import org.jetbrains.kotlin.j2k.tree.Mutability
|
||||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
|
|
||||||
@@ -44,12 +51,14 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
|
|||||||
private fun PsiPackageStatement.toJK(): JKPackageDeclaration =
|
private fun PsiPackageStatement.toJK(): JKPackageDeclaration =
|
||||||
JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName))
|
JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName))
|
||||||
|
|
||||||
private fun PsiImportStatement.toJK() =
|
private fun PsiImportStatement.toJK(): JKImportStatementImpl {
|
||||||
JKImportStatementImpl(
|
val target = resolve()
|
||||||
JKNameIdentifierImpl(
|
val rawName = text.substringAfter("import").substringBeforeLast(";").trim()
|
||||||
text.substringAfter("import").substringBeforeLast(";").trim()
|
val name =
|
||||||
)
|
if (target is KtLightClassForFacade) rawName.replaceAfterLast('.', "*")
|
||||||
)
|
else rawName
|
||||||
|
return JKImportStatementImpl(JKNameIdentifierImpl(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private inner class ExpressionTreeMapper {
|
private inner class ExpressionTreeMapper {
|
||||||
@@ -165,24 +174,92 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun JKExpression.qualified(qualifier: JKExpression?) =
|
||||||
|
if (qualifier != null) {
|
||||||
|
JKQualifiedExpressionImpl(qualifier, JKJavaQualifierImpl.DOT, this)
|
||||||
|
} else this
|
||||||
|
|
||||||
|
//TODO mostly copied from old j2k, refactor
|
||||||
fun PsiMethodCallExpression.toJK(): JKExpression {
|
fun PsiMethodCallExpression.toJK(): JKExpression {
|
||||||
val method = methodExpression as PsiReferenceExpressionImpl
|
val arguments = argumentList.toJK()
|
||||||
val referenceNameElement = methodExpression.referenceNameElement
|
val typeArguments = typeArgumentList.toJK()
|
||||||
val symbol = symbolProvider.provideSymbol<JKMethodSymbol>(method)
|
val qualifier = methodExpression.qualifierExpression?.toJK()
|
||||||
return if (referenceNameElement is PsiKeyword) {
|
val target = methodExpression.resolve()
|
||||||
val callee = when (referenceNameElement.tokenType) {
|
val symbol = symbolProvider.provideSymbol<JKMethodSymbol>(methodExpression as PsiReferenceExpressionImpl)
|
||||||
SUPER_KEYWORD -> JKSuperExpressionImpl()
|
|
||||||
THIS_KEYWORD -> JKThisExpressionImpl(JKLabelEmptyImpl())
|
return when {
|
||||||
else -> error("Unknown keyword in callee position")
|
methodExpression.referenceNameElement is PsiKeyword -> {
|
||||||
|
val callee = when ((methodExpression.referenceNameElement as PsiKeyword).tokenType) {
|
||||||
|
SUPER_KEYWORD -> JKSuperExpressionImpl()
|
||||||
|
THIS_KEYWORD -> JKThisExpressionImpl(JKLabelEmptyImpl())
|
||||||
|
else -> error("Unknown keyword in callee position")
|
||||||
|
}
|
||||||
|
JKDelegationConstructorCallImpl(symbol, callee, arguments)
|
||||||
}
|
}
|
||||||
JKDelegationConstructorCallImpl(symbol, callee, argumentList.toJK())
|
|
||||||
} else {
|
target is KtLightMethod -> {
|
||||||
val call = JKJavaMethodCallExpressionImpl(symbol, argumentList.toJK(), typeArgumentList.toJK())
|
val origin = target.kotlinOrigin
|
||||||
if (method.findChildByRole(ChildRole.DOT) != null) {
|
when (origin) {
|
||||||
JKQualifiedExpressionImpl((method.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, call)
|
is KtNamedFunction -> {
|
||||||
} else {
|
if (origin.isExtensionDeclaration()) {
|
||||||
call
|
val receiver = arguments.expressions.firstOrNull()
|
||||||
|
JKJavaMethodCallExpressionImpl(
|
||||||
|
symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol,
|
||||||
|
arguments.also { it.expressions = it.expressions.drop(1) },
|
||||||
|
typeArguments
|
||||||
|
).qualified(receiver)
|
||||||
|
} else {
|
||||||
|
JKJavaMethodCallExpressionImpl(
|
||||||
|
symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol,
|
||||||
|
arguments,
|
||||||
|
typeArguments
|
||||||
|
).qualified(qualifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is KtProperty, is KtPropertyAccessor, is KtParameter -> {
|
||||||
|
val property =
|
||||||
|
if (origin is KtPropertyAccessor) origin.parent as KtProperty
|
||||||
|
else origin as KtNamedDeclaration
|
||||||
|
val parameterCount = target.parameterList.parameters.size
|
||||||
|
val propertyAccessExpression =
|
||||||
|
JKFieldAccessExpressionImpl(symbolProvider.provideDirectSymbol(property) as JKFieldSymbol)
|
||||||
|
val isExtension = property.isExtensionDeclaration()
|
||||||
|
val isTopLevel = origin.getStrictParentOfType<KtClassOrObject>() == null
|
||||||
|
val propertyAccess = if (isTopLevel) {
|
||||||
|
if (isExtension) JKQualifiedExpressionImpl(
|
||||||
|
arguments.expressions.first().detached(arguments),
|
||||||
|
JKJavaQualifierImpl.DOT,
|
||||||
|
propertyAccessExpression
|
||||||
|
)
|
||||||
|
else propertyAccessExpression
|
||||||
|
} else propertyAccessExpression.qualified(qualifier) as JKAssignableExpression
|
||||||
|
|
||||||
|
when (if (isExtension) parameterCount - 1 else parameterCount) {
|
||||||
|
0 /* getter */ ->
|
||||||
|
propertyAccess
|
||||||
|
|
||||||
|
1 /* setter */ -> {
|
||||||
|
val argument = (arguments.expressions[if (isExtension) 1 else 0]).detached(arguments)
|
||||||
|
JKJavaAssignmentExpressionImpl(
|
||||||
|
propertyAccess,
|
||||||
|
argument,
|
||||||
|
JKJavaOperatorImpl.tokenToOperator[JavaTokenType.EQ]!!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target is PsiMethod ->
|
||||||
|
JKJavaMethodCallExpressionImpl(symbol, arguments, typeArguments)
|
||||||
|
.qualified(qualifier)
|
||||||
|
else ->
|
||||||
|
JKJavaMethodCallExpressionImpl(symbol, arguments, typeArguments)
|
||||||
|
.qualified(qualifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,14 @@ class ImportStatementConversion : RecursiveApplicableConversionBase() {
|
|||||||
unfilteredCollectedFqNames += classType.classReference.fqName!!
|
unfilteredCollectedFqNames += classType.classReference.fqName!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) {
|
||||||
|
unfilteredCollectedFqNames += fieldAccessExpression.identifier.fqName
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
|
||||||
|
unfilteredCollectedFqNames += methodCallExpression.identifier.fqName
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) {
|
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) {
|
||||||
val type = classLiteralExpression.classType.type
|
val type = classLiteralExpression.classType.type
|
||||||
if (type is JKClassType) {
|
if (type is JKClassType) {
|
||||||
|
|||||||
Reference in New Issue
Block a user