New J2K: Fix NPE in a case of unresolved symbols
This commit is contained in:
committed by
Ilya Kirillov
parent
410000f94c
commit
db8beab499
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.j2k.ast.Nullability
|
||||
@@ -42,36 +43,50 @@ private fun JKKtOperatorToken.binaryExpressionMethodSymbol(
|
||||
rightType: JKType,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKMethodSymbol {
|
||||
val operatorNames =
|
||||
if (operatorName == "equals") listOf("equals", "compareTo")
|
||||
else listOf(operatorName)
|
||||
|
||||
fun PsiClass.methodSymbol() =
|
||||
allMethods
|
||||
.filter { it.name in operatorNames }
|
||||
.filter { it.name == operatorName }
|
||||
.firstOrNull {
|
||||
it.parameterList.parameters.singleOrNull()?.takeIf {
|
||||
rightType.isSubtypeOf(
|
||||
it.type.toJK(symbolProvider),
|
||||
symbolProvider
|
||||
)
|
||||
it.parameterList.parameters.singleOrNull()?.takeIf { parameter ->
|
||||
val type = parameter.type.toJK(symbolProvider)
|
||||
if (type !is JKTypeParameterType) rightType.isSubtypeOf(type, symbolProvider)
|
||||
else true//TODO check for type bounds
|
||||
} != null
|
||||
}?.let { symbolProvider.provideDirectSymbol(it) as JKMethodSymbol }
|
||||
|
||||
|
||||
val classSymbol = leftType.classSymbol(symbolProvider)
|
||||
val classSymbol =
|
||||
if (leftType.isStringType()) symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.string.toSafe())
|
||||
else leftType.classSymbol(symbolProvider)
|
||||
|
||||
|
||||
val defaultClassSymbol by lazy {
|
||||
when (text) {
|
||||
"<", ">", "<=", ">=", "==", "!=", "&&", "||" ->
|
||||
JKUnresolvedMethod(
|
||||
text,
|
||||
kotlinTypeByName(
|
||||
KotlinBuiltIns.FQ_NAMES._boolean.toSafe().asString(),
|
||||
symbolProvider,
|
||||
Nullability.NotNull
|
||||
)
|
||||
)
|
||||
"+", "-", "*", "/" -> JKUnresolvedMethod(text, leftType)//TODO fix that
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
return when (classSymbol) {
|
||||
is JKMultiverseKtClassSymbol ->
|
||||
classSymbol.target.declarations
|
||||
.asSequence()
|
||||
.filterIsInstance<KtNamedFunction>()
|
||||
.filter { it.name in operatorNames }
|
||||
.filter { it.name == operatorName }
|
||||
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
|
||||
.firstOrNull { it.parameterTypes.singleOrNull()?.takeIf { rightType.isSubtypeOf(it, symbolProvider) } != null }!!
|
||||
is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodSymbol()!!
|
||||
is JKMultiverseClassSymbol -> classSymbol.target.methodSymbol()!!
|
||||
|
||||
else -> TODO(classSymbol::class.toString())
|
||||
.firstOrNull { it.parameterTypes.singleOrNull()?.takeIf { rightType.isSubtypeOf(it, symbolProvider) } != null }
|
||||
?: defaultClassSymbol
|
||||
is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodSymbol() ?: defaultClassSymbol
|
||||
is JKMultiverseClassSymbol -> classSymbol.target.methodSymbol() ?: defaultClassSymbol
|
||||
else -> defaultClassSymbol
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +139,6 @@ fun kotlinPostfixExpression(
|
||||
return JKPostfixExpressionImpl(operand, JKKtOperatorImpl(token, methodSymbol))
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun untilToExpression(
|
||||
from: JKExpression,
|
||||
to: JKExpression,
|
||||
@@ -207,6 +220,7 @@ fun kotlinAssert(assertion: JKExpression, message: JKExpression?, symbolProvider
|
||||
),
|
||||
JKExpressionListImpl(listOfNotNull(assertion, message))
|
||||
)
|
||||
|
||||
fun jvmAnnotation(name: String, symbolProvider: JKSymbolProvider) =
|
||||
JKAnnotationImpl(
|
||||
symbolProvider.provideByFqName("kotlin.annotation.AnnotationTarget.$name")
|
||||
|
||||
@@ -46,6 +46,8 @@ fun JKExpression.type(context: ConversionContext): JKType? =
|
||||
is JKJavaInstanceOfExpression -> kotlinTypeByName(KotlinBuiltIns.FQ_NAMES._boolean.asString(), context.symbolProvider)
|
||||
is JKParenthesizedExpression -> expression.type(context)
|
||||
is JKTypeCastExpression -> type.type
|
||||
is JKThisExpression -> null// TODO return actual type
|
||||
is JKSuperExpression -> null// TODO return actual type
|
||||
else -> TODO(this::class.java.toString())
|
||||
}
|
||||
|
||||
@@ -101,7 +103,9 @@ fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nu
|
||||
}
|
||||
|
||||
fun JKType.isSubtypeOf(other: JKType, symbolProvider: JKSymbolProvider): Boolean =
|
||||
toKtType(symbolProvider).isSubtypeOf(other.toKtType(symbolProvider))
|
||||
other.toKtType(symbolProvider)
|
||||
?.let { otherType -> this.toKtType(symbolProvider)?.isSubtypeOf(otherType) } == true
|
||||
|
||||
|
||||
fun KtTypeElement.toJK(symbolProvider: JKSymbolProvider): JKType =
|
||||
when (this) {
|
||||
@@ -119,31 +123,32 @@ fun KtTypeElement.toJK(symbolProvider: JKSymbolProvider): JKType =
|
||||
else -> TODO(this::class.java.toString())
|
||||
}
|
||||
|
||||
fun JKType.toKtType(symbolProvider: JKSymbolProvider): KotlinType =
|
||||
fun JKType.toKtType(symbolProvider: JKSymbolProvider): KotlinType? =
|
||||
when (this) {
|
||||
is JKClassType -> classReference!!.toKtType(symbolProvider)
|
||||
is JKClassType -> classReference.toKtType()
|
||||
is JKJavaPrimitiveType ->
|
||||
kotlinTypeByName(
|
||||
jvmPrimitiveType.primitiveType.typeFqName.asString(),
|
||||
symbolProvider
|
||||
).toKtType(symbolProvider)
|
||||
else -> TODO(this::class.java.toString())
|
||||
else -> null
|
||||
// else -> TODO(this::class.java.toString())
|
||||
}
|
||||
|
||||
|
||||
fun JKClassSymbol.toKtType(symbolProvider: JKSymbolProvider): KotlinType {
|
||||
fun JKClassSymbol.toKtType(): KotlinType? {
|
||||
val classDescriptor = when (this) {
|
||||
is JKMultiverseKtClassSymbol -> {
|
||||
val bindingContext = target.analyze()
|
||||
bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, target] as ClassDescriptor
|
||||
}
|
||||
is JKMultiverseClassSymbol ->
|
||||
target.getJavaClassDescriptor()!!
|
||||
target.getJavaClassDescriptor()
|
||||
is JKUniverseClassSymbol ->
|
||||
target.psi<PsiClass>()?.getJavaClassDescriptor()!!
|
||||
target.psi<PsiClass>()?.getJavaClassDescriptor()//TODO null in case of a fake package
|
||||
else -> TODO(this::class.java.toString())
|
||||
}
|
||||
return classDescriptor.defaultType
|
||||
return classDescriptor?.defaultType
|
||||
}
|
||||
|
||||
inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability): T =
|
||||
|
||||
Reference in New Issue
Block a user