New J2K: move type calculation to expression node

This commit is contained in:
Ilya Kirillov
2019-09-09 09:55:28 +03:00
parent be94eb5405
commit b2002d56bd
20 changed files with 159 additions and 174 deletions
@@ -60,8 +60,10 @@ class JavaToJKTreeBuilder constructor(
converterServices: NewJavaToKotlinServices, converterServices: NewJavaToKotlinServices,
private val importStorage: ImportStorage private val importStorage: ImportStorage
) { ) {
private fun PsiType.toJK() = private fun PsiType?.toJK(): JKType {
typeFactory.fromPsiType(this) if (this == null) return JKNoType
return typeFactory.fromPsiType(this)
}
private val expressionTreeMapper = ExpressionTreeMapper() private val expressionTreeMapper = ExpressionTreeMapper()
@@ -128,14 +130,19 @@ class JavaToJKTreeBuilder constructor(
is PsiInstanceOfExpression -> toJK() is PsiInstanceOfExpression -> toJK()
is PsiThisExpression -> is PsiThisExpression ->
JKThisExpression( JKThisExpression(
qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty() qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty(),
type.toJK()
) )
is PsiSuperExpression -> is PsiSuperExpression ->
JKSuperExpression( JKSuperExpression(
qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty() qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty(),
type.toJK()
) )
is PsiConditionalExpression -> JKIfElseExpression( is PsiConditionalExpression -> JKIfElseExpression(
condition.toJK(), thenExpression.toJK(), elseExpression.toJK() condition.toJK(),
thenExpression.toJK(),
elseExpression.toJK(),
type.toJK()
) )
is PsiPolyadicExpression -> { is PsiPolyadicExpression -> {
val token = JKOperatorToken.fromElementType(operationTokenType) val token = JKOperatorToken.fromElementType(operationTokenType)
@@ -175,7 +182,7 @@ class JavaToJKTreeBuilder constructor(
} }
fun PsiInstanceOfExpression.toJK(): JKIsExpression = fun PsiInstanceOfExpression.toJK(): JKIsExpression =
JKIsExpression(operand.toJK(), JKTypeElement(checkType?.type?.toJK() ?: JKNoTypeImpl)) JKIsExpression(operand.toJK(), JKTypeElement(checkType?.type?.toJK() ?: JKNoType))
.also { .also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -293,8 +300,8 @@ class JavaToJKTreeBuilder constructor(
return when { return when {
methodExpression.referenceNameElement is PsiKeyword -> { methodExpression.referenceNameElement is PsiKeyword -> {
val callee = when ((methodExpression.referenceNameElement as PsiKeyword).tokenType) { val callee = when ((methodExpression.referenceNameElement as PsiKeyword).tokenType) {
SUPER_KEYWORD -> JKSuperExpression() SUPER_KEYWORD -> JKSuperExpression(JKLabelEmpty(), JKNoType)
THIS_KEYWORD -> JKThisExpression(JKLabelEmpty()) THIS_KEYWORD -> JKThisExpression(JKLabelEmpty(), JKNoType)
else -> throwCanNotConvertError("unknown keyword in callee position") else -> throwCanNotConvertError("unknown keyword in callee position")
} }
JKDelegationConstructorCall(symbol as JKMethodSymbol, callee, arguments.toJK()) JKDelegationConstructorCall(symbol as JKMethodSymbol, callee, arguments.toJK())
@@ -337,7 +344,7 @@ class JavaToJKTreeBuilder constructor(
propertyAccessExpression propertyAccessExpression
) )
else propertyAccessExpression else propertyAccessExpression
} else propertyAccessExpression.qualified(qualifier) as JKExpression } else propertyAccessExpression.qualified(qualifier)
when (if (isExtension) parameterCount - 1 else parameterCount) { when (if (isExtension) parameterCount - 1 else parameterCount) {
0 /* getter */ -> 0 /* getter */ ->
@@ -383,7 +390,7 @@ class JavaToJKTreeBuilder constructor(
}?.takeUnless { type -> }?.takeUnless { type ->
type.isKotlinFunctionalType type.isKotlinFunctionalType
}?.toJK() }?.toJK()
?.asTypeElement() ?: JKTypeElement(JKNoTypeImpl) ?.asTypeElement() ?: JKTypeElement(JKNoType)
fun PsiMethodReferenceExpression.toJK(): JKMethodReferenceExpression { fun PsiMethodReferenceExpression.toJK(): JKMethodReferenceExpression {
val symbol = symbolProvider.provideSymbolForReference<JKSymbol>(this).let { symbol -> val symbol = symbolProvider.provideSymbolForReference<JKSymbol>(this).let { symbol ->
@@ -494,14 +501,15 @@ class JavaToJKTreeBuilder constructor(
} }
fun PsiArrayAccessExpression.toJK(): JKExpression { fun PsiArrayAccessExpression.toJK(): JKExpression =
return JKArrayAccessExpression( arrayExpression.toJK()
arrayExpression.toJK(), .callOn(
indexExpression?.toJK() ?: throwCanNotConvertError() symbolProvider.provideMethodSymbol("kotlin.Array.get"),
).also { arguments = listOf(indexExpression?.toJK() ?: JKStubExpression())
it.assignNonCodeElements(this) ).also {
} it.assignNonCodeElements(this)
} }
fun PsiTypeCastExpression.toJK(): JKExpression { fun PsiTypeCastExpression.toJK(): JKExpression {
return JKTypeCastExpression( return JKTypeCastExpression(
@@ -622,7 +630,7 @@ class JavaToJKTreeBuilder constructor(
with(expressionTreeMapper) { argumentList?.toJK() ?: JKArgumentList() }, with(expressionTreeMapper) { argumentList?.toJK() ?: JKArgumentList() },
initializingClass?.createClassBody() ?: JKClassBody(), initializingClass?.createClassBody() ?: JKClassBody(),
JKTypeElement( JKTypeElement(
JKClassTypeImpl( JKClassType(
symbolProvider.provideDirectSymbol(containingClass ?: throwCanNotConvertError()) as JKClassSymbol, symbolProvider.provideDirectSymbol(containingClass ?: throwCanNotConvertError()) as JKClassSymbol,
emptyList() emptyList()
) )
@@ -784,7 +792,6 @@ class JavaToJKTreeBuilder constructor(
).also { ).also {
symbolProvider.provideUniverseSymbol(this, it) symbolProvider.provideUniverseSymbol(this, it)
it.psi = this it.psi = this
}.also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
} }
@@ -904,7 +904,7 @@ private class JKPrinter(
} }
fun renderType(type: JKType, owner: JKTreeElement?) { fun renderType(type: JKType, owner: JKTreeElement?) {
if (type is JKNoTypeImpl) return if (type is JKNoType) return
if (type is JKCapturedType) { if (type is JKCapturedType) {
when (val wildcard = type.wildcardType) { when (val wildcard = type.wildcardType) {
is JKVarianceTypeParameterType -> { is JKVarianceTypeParameterType -> {
@@ -75,13 +75,13 @@ class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApp
JKTypeArgumentList(listOf(JKTypeElement(arrayType))) JKTypeArgumentList(listOf(JKTypeElement(arrayType)))
) )
} }
var resultType = JKClassTypeImpl( var resultType = JKClassType(
symbolProvider.provideClassSymbol(type.arrayFqName()), symbolProvider.provideClassSymbol(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type), if (type is JKJavaPrimitiveType) emptyList() else listOf(type),
Nullability.Default Nullability.Default
) )
for (i in 0 until dimensions.size - 2) { for (i in 0 until dimensions.size - 2) {
resultType = JKClassTypeImpl( resultType = JKClassType(
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()), symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()),
listOf(resultType), listOf(resultType),
Nullability.Default Nullability.Default
@@ -13,9 +13,7 @@ package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseFieldSymbol import org.jetbrains.kotlin.nj2k.symbols.JKUniverseFieldSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.nj2k.types.type
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -34,7 +32,7 @@ class ArrayOperationsConversion(context: NewJ2kConverterContext) : RecursiveAppl
} }
private fun JKExpression.isArrayOrVarargTypeParameter(): Boolean { private fun JKExpression.isArrayOrVarargTypeParameter(): Boolean {
if (type(typeFactory) is JKJavaArrayType) return true if (calculateType(typeFactory) is JKJavaArrayType) return true
val parameter = val parameter =
safeAs<JKFieldAccessExpression>() safeAs<JKFieldAccessExpression>()
?.identifier ?.identifier
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.nj2k.symbols.deepestFqName
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.isArrayType import org.jetbrains.kotlin.nj2k.types.isArrayType
import org.jetbrains.kotlin.nj2k.types.isStringType import org.jetbrains.kotlin.nj2k.types.isStringType
import org.jetbrains.kotlin.nj2k.types.type
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -268,7 +267,7 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
Method("java.lang.String.indexOf") convertTo Method("kotlin.text.indexOf"), Method("java.lang.String.indexOf") convertTo Method("kotlin.text.indexOf"),
Method("java.lang.String.lastIndexOf") convertTo Method("kotlin.text.lastIndexOf"), Method("java.lang.String.lastIndexOf") convertTo Method("kotlin.text.lastIndexOf"),
Method("java.lang.String.getBytes") convertTo Method("kotlin.text.toByteArray") Method("java.lang.String.getBytes") convertTo Method("kotlin.text.toByteArray")
withByArgumentsFilter { it.singleOrNull()?.type(typeFactory)?.isStringType() == true } withByArgumentsFilter { it.singleOrNull()?.calculateType(typeFactory)?.isStringType() == true }
withArgumentsProvider { arguments -> withArgumentsProvider { arguments ->
val argument = arguments.arguments.single()::value.detached() val argument = arguments.arguments.single()::value.detached()
val call = JKCallExpressionImpl( val call = JKCallExpressionImpl(
@@ -281,7 +280,7 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
Method("java.lang.String.valueOf") Method("java.lang.String.valueOf")
convertTo ExtensionMethod("kotlin.Any.toString") convertTo ExtensionMethod("kotlin.Any.toString")
withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER
withByArgumentsFilter { it.isNotEmpty() && it.first().type(typeFactory)?.isArrayType() == false }, withByArgumentsFilter { it.isNotEmpty() && it.first().calculateType(typeFactory)?.isArrayType() == false },
Method("java.lang.String.getChars") Method("java.lang.String.getChars")
convertTo Method("kotlin.text.toCharArray") convertTo Method("kotlin.text.toCharArray")
@@ -297,12 +296,12 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
Method("java.lang.String.valueOf") Method("java.lang.String.valueOf")
convertTo Method("kotlin.String") convertTo Method("kotlin.String")
withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER
withByArgumentsFilter { it.isNotEmpty() && it.first().type(typeFactory)?.isArrayType() == true }, withByArgumentsFilter { it.isNotEmpty() && it.first().calculateType(typeFactory)?.isArrayType() == true },
Method("java.lang.String.copyValueOf") Method("java.lang.String.copyValueOf")
convertTo Method("kotlin.String") convertTo Method("kotlin.String")
withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER
withByArgumentsFilter { it.isNotEmpty() && it.first().type(typeFactory)?.isArrayType() == true }, withByArgumentsFilter { it.isNotEmpty() && it.first().calculateType(typeFactory)?.isArrayType() == true },
Method("java.lang.String.replaceAll") Method("java.lang.String.replaceAll")
convertTo Method("kotlin.text.replace") convertTo Method("kotlin.text.replace")
@@ -16,8 +16,7 @@ import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl import org.jetbrains.kotlin.nj2k.types.JKNoType
import org.jetbrains.kotlin.nj2k.types.type
import kotlin.math.abs import kotlin.math.abs
@@ -136,11 +135,11 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
KtTokens.EXCLEQ -> false KtTokens.EXCLEQ -> false
else -> return null else -> return null
} }
val range = forIterationRange(start, right, reversed, inclusive, loopVarPsi) val range = forIterationRange(start, right, reversed, inclusive)
val explicitType = val explicitType =
if (context.converter.settings.specifyLocalVariableTypeByDefault) if (context.converter.settings.specifyLocalVariableTypeByDefault)
JKJavaPrimitiveType.INT JKJavaPrimitiveType.INT
else JKNoTypeImpl else JKNoType
val loopVarDeclaration = val loopVarDeclaration =
JKForLoopVariable( JKForLoopVariable(
JKTypeElement(explicitType), JKTypeElement(explicitType),
@@ -169,8 +168,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
start: JKExpression, start: JKExpression,
bound: JKExpression, bound: JKExpression,
reversed: Boolean, reversed: Boolean,
inclusiveComparison: Boolean, inclusiveComparison: Boolean
psiContext: PsiElement
): JKExpression { ): JKExpression {
indicesIterationRange(start, bound, reversed, inclusiveComparison)?.also { return it } indicesIterationRange(start, bound, reversed, inclusiveComparison)?.also { return it }
return when { return when {
@@ -262,7 +260,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
private fun indicesByArrayLength(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? { private fun indicesByArrayLength(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? {
val methodCall = javaSizeCall.selector as? JKFieldAccessExpression ?: return null val methodCall = javaSizeCall.selector as? JKFieldAccessExpression ?: return null
val receiverType = javaSizeCall.receiver.type(typeFactory) val receiverType = javaSizeCall.receiver.calculateType(typeFactory)
if (methodCall.identifier.name == "length" && receiverType is JKJavaArrayType) { if (methodCall.identifier.name == "length" && receiverType is JKJavaArrayType) {
return toIndicesCall(javaSizeCall) return toIndicesCall(javaSizeCall)
} }
@@ -149,6 +149,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
) )
} }
private fun JKExpression.castTo(toType: JKType, strict: Boolean = false): JKExpression? { private fun JKExpression.castTo(toType: JKType, strict: Boolean = false): JKExpression? {
val expressionType = calculateType(typeFactory) val expressionType = calculateType(typeFactory)
if (expressionType == toType) return null if (expressionType == toType) return null
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedClassSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKClassType import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKClassTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKJavaVoidType import org.jetbrains.kotlin.nj2k.types.JKJavaVoidType
import org.jetbrains.kotlin.nj2k.types.updateNullability import org.jetbrains.kotlin.nj2k.types.updateNullability
@@ -36,7 +35,7 @@ class JavaStandardMethodsConversion(context: NewJ2kConverterContext) : Recursive
if (hasNoCloneableInSuperClasses) { if (hasNoCloneableInSuperClasses) {
element.inheritance.implements += element.inheritance.implements +=
JKTypeElement( JKTypeElement(
JKClassTypeImpl( JKClassType(
JKUnresolvedClassSymbol("Cloneable", typeFactory), JKUnresolvedClassSymbol("Cloneable", typeFactory),
emptyList(), Nullability.NotNull emptyList(), Nullability.NotNull
) )
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.nj2k.conversions package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.lang.jvm.JvmModifier import com.intellij.lang.jvm.JvmModifier
import com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.codegen.kotlinType import org.jetbrains.kotlin.codegen.kotlinType
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.nj2k.qualified
import org.jetbrains.kotlin.nj2k.symbols.* import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.* import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -37,7 +39,7 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
?.let { classAccessExpression -> ?.let { classAccessExpression ->
JKParameter( JKParameter(
JKTypeElement( JKTypeElement(
parametersTypesByFunctionalInterface?.firstOrNull() ?: JKClassTypeImpl(classAccessExpression.identifier) parametersTypesByFunctionalInterface?.firstOrNull() ?: JKClassType(classAccessExpression.identifier)
), ),
JKNameIdentifier(RECEIVER_NAME), JKNameIdentifier(RECEIVER_NAME),
isVarArgs = false isVarArgs = false
@@ -90,8 +92,8 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
element::functionalType.detached(), element::functionalType.detached(),
JKTypeElement( JKTypeElement(
when (symbol) { when (symbol) {
is JKMethodSymbol -> symbol.returnType ?: JKNoTypeImpl is JKMethodSymbol -> symbol.returnType ?: JKNoType
is JKClassSymbol -> JKClassTypeImpl(symbol) is JKClassSymbol -> JKClassType(symbol)
is JKUnresolvedSymbol -> return recurse(element) is JKUnresolvedSymbol -> return recurse(element)
else -> error("Symbol should be either method symbol or class symbol, but it is ${symbol::class}") else -> error("Symbol should be either method symbol or class symbol, but it is ${symbol::class}")
} }
@@ -127,6 +129,26 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
} }
} }
private val JKMethodSymbol.isStatic: Boolean
get() = when (this) {
is JKMultiverseFunctionSymbol -> target.parent is KtObjectDeclaration
is JKMultiverseMethodSymbol -> target.hasModifierProperty(PsiModifier.STATIC)
is JKUniverseMethodSymbol -> target.parent?.parent?.safeAs<JKClass>()?.classKind == JKClass.ClassKind.COMPANION
is JKUnresolvedMethod -> false
}
private val JKMethodSymbol.parameterNames: List<String>?
get() {
return when (this) {
is JKMultiverseFunctionSymbol -> target.valueParameters.map { it.name ?: return null }
is JKMultiverseMethodSymbol -> target.parameters.map { it.name ?: return null }
is JKUniverseMethodSymbol -> target.parameters.map { it.name.value }
is JKUnresolvedMethod -> null
}
}
companion object { companion object {
private const val RECEIVER_NAME = "obj" //name taken from old j2k private const val RECEIVER_NAME = "obj" //name taken from old j2k
} }
@@ -9,15 +9,14 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.callOn import org.jetbrains.kotlin.nj2k.callOn
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.isStringType import org.jetbrains.kotlin.nj2k.types.isStringType
import org.jetbrains.kotlin.nj2k.types.type
class AnyWithStringConcatenationConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class AnyWithStringConcatenationConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKBinaryExpression) return recurse(element) if (element !is JKBinaryExpression) return recurse(element)
if (element.operator.token == JKOperatorToken.PLUS if (element.operator.token == JKOperatorToken.PLUS
&& element.right.type(typeFactory)?.isStringType() == true && element.right.calculateType(typeFactory).isStringType()
&& element.left.type(typeFactory)?.isStringType() == false && !element.left.calculateType(typeFactory).isStringType()
) { ) {
return recurse( return recurse(
JKBinaryExpression( JKBinaryExpression(
@@ -20,7 +20,7 @@ class ParameterModificationInMethodCallsConversion(context: NewJ2kConverterConte
if (parameter.hasWritableUsages(element.block, context)) { if (parameter.hasWritableUsages(element.block, context)) {
val parameterType = val parameterType =
if (parameter.isVarArgs) { if (parameter.isVarArgs) {
JKClassTypeImpl( JKClassType(
symbolProvider.provideClassSymbol(parameter.type.type.arrayFqName()), symbolProvider.provideClassSymbol(parameter.type.type.arrayFqName()),
if (parameter.type.type is JKJavaPrimitiveType) emptyList() if (parameter.type.type is JKJavaPrimitiveType) emptyList()
else listOf( else listOf(
@@ -74,7 +74,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
is JKJavaVoidType -> typeFactory.types.unit is JKJavaVoidType -> typeFactory.types.unit
is JKJavaArrayType -> is JKJavaArrayType ->
JKClassTypeImpl( JKClassType(
symbolProvider.provideClassSymbol(type.arrayFqName()), symbolProvider.provideClassSymbol(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type.mapType(typeElement)), if (type is JKJavaPrimitiveType) emptyList() else listOf(type.mapType(typeElement)),
nullability nullability
@@ -102,7 +102,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
} }
private fun JKClassType.mapClassType(): JKClassType = private fun JKClassType.mapClassType(): JKClassType =
JKClassTypeImpl( JKClassType(
classReference.mapClassSymbol(), classReference.mapClassSymbol(),
parameters.map { it.mapType(null) }, parameters.map { it.mapType(null) },
nullability nullability
@@ -123,7 +123,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
if (this is JKClassType && parameters.isEmpty()) { if (this is JKClassType && parameters.isEmpty()) {
val parametersCount = classReference.expectedTypeParametersCount() val parametersCount = classReference.expectedTypeParametersCount()
val typeParameters = List(parametersCount) { typeParameter } val typeParameters = List(parametersCount) { typeParameter }
JKClassTypeImpl( JKClassType(
classReference, classReference,
typeParameters, typeParameters,
nullability nullability
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.nj2k.conversions.RecursiveApplicableConversionBase
import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedMethod import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedMethod
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKNoType import org.jetbrains.kotlin.nj2k.types.JKNoType
import org.jetbrains.kotlin.nj2k.types.JKType import org.jetbrains.kotlin.nj2k.types.JKType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
@@ -7,13 +7,9 @@ package org.jetbrains.kotlin.nj2k.symbols
import com.intellij.psi.PsiVariable import com.intellij.psi.PsiVariable
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.tree.JKVariable import org.jetbrains.kotlin.nj2k.tree.JKVariable
import org.jetbrains.kotlin.nj2k.types.toJK import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.nj2k.types.JKClassTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.containingClass
@@ -22,7 +18,7 @@ sealed class JKFieldSymbol : JKSymbol {
abstract val fieldType: JKType? abstract val fieldType: JKType?
} }
class JKUniverseFieldSymbol( override val typeFactory: JKTypeFactory) : JKFieldSymbol(), JKUniverseSymbol<JKVariable> { class JKUniverseFieldSymbol(override val typeFactory: JKTypeFactory) : JKFieldSymbol(), JKUniverseSymbol<JKVariable> {
override val fieldType: JKType override val fieldType: JKType
get() = target.type.type get() = target.type.type
@@ -50,7 +46,7 @@ class JKMultiverseKtEnumEntrySymbol(
override val typeFactory: JKTypeFactory override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> { ) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> {
override val fieldType: JKType? override val fieldType: JKType?
get() = JKClassTypeImpl( get() = JKClassType(
symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol, symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol,
emptyList(), emptyList(),
Nullability.NotNull Nullability.NotNull
@@ -62,6 +58,6 @@ class JKUnresolvedField(
override val typeFactory: JKTypeFactory override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKUnresolvedSymbol { ) : JKFieldSymbol(), JKUnresolvedSymbol {
override val fieldType: JKType override val fieldType: JKType
get() = JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()), emptyList()) get() = typeFactory.types.nullableAny
} }
@@ -16,8 +16,8 @@ import org.jetbrains.kotlin.nj2k.tree.JKClass
import org.jetbrains.kotlin.nj2k.tree.JKMethod import org.jetbrains.kotlin.nj2k.tree.JKMethod
import org.jetbrains.kotlin.nj2k.types.asType import org.jetbrains.kotlin.nj2k.types.asType
import org.jetbrains.kotlin.nj2k.types.toJK import org.jetbrains.kotlin.nj2k.types.toJK
import org.jetbrains.kotlin.nj2k.types.JKClassTypeImpl import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl import org.jetbrains.kotlin.nj2k.types.JKNoType
import org.jetbrains.kotlin.nj2k.types.JKType import org.jetbrains.kotlin.nj2k.types.JKType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
@@ -32,7 +32,7 @@ sealed class JKMethodSymbol : JKSymbol {
class JKUniverseMethodSymbol(override val typeFactory: JKTypeFactory) : JKMethodSymbol(), JKUniverseSymbol<JKMethod> { class JKUniverseMethodSymbol(override val typeFactory: JKTypeFactory) : JKMethodSymbol(), JKUniverseSymbol<JKMethod> {
override val receiverType: JKType? override val receiverType: JKType?
get() = target.parent.safeAs<JKClass>()?.let { get() = target.parent.safeAs<JKClass>()?.let {
JKClassTypeImpl(symbolProvider.provideUniverseSymbol(it), emptyList()/*TODO*/) JKClassType(symbolProvider.provideUniverseSymbol(it), emptyList())
} }
override val parameterTypes: List<JKType> override val parameterTypes: List<JKType>
get() = target.parameters.map { it.type.type } get() = target.parameters.map { it.type.type }
@@ -48,7 +48,7 @@ class JKMultiverseMethodSymbol(
) : JKMethodSymbol(), JKMultiverseSymbol<PsiMethod> { ) : JKMethodSymbol(), JKMultiverseSymbol<PsiMethod> {
override val receiverType: JKType? override val receiverType: JKType?
get() = target.containingClass?.let { get() = target.containingClass?.let {
JKClassTypeImpl(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList()/*TODO*/) JKClassType(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList())
} }
override val parameterTypes: List<JKType> override val parameterTypes: List<JKType>
get() = target.parameterList.parameters.map { typeFactory.fromPsiType(it.type) } get() = target.parameterList.parameters.map { typeFactory.fromPsiType(it.type) }
@@ -76,7 +76,7 @@ class JKMultiverseFunctionSymbol(
val type = parameter.typeReference?.toJK(typeFactory) val type = parameter.typeReference?.toJK(typeFactory)
type?.let { type?.let {
if (parameter.isVarArg) { if (parameter.isVarArg) {
JKClassTypeImpl( JKClassType(
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()), symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()),
listOf(it) listOf(it)
) )
@@ -91,12 +91,12 @@ class JKMultiverseFunctionSymbol(
class JKUnresolvedMethod( class JKUnresolvedMethod(
override val target: String, override val target: String,
override val typeFactory: JKTypeFactory, override val typeFactory: JKTypeFactory,
override val returnType: JKType = JKNoTypeImpl override val returnType: JKType = JKNoType
) : JKMethodSymbol(), JKUnresolvedSymbol { ) : JKMethodSymbol(), JKUnresolvedSymbol {
constructor(target: PsiReference, typeFactory: JKTypeFactory) : this(target.canonicalText, typeFactory) constructor(target: PsiReference, typeFactory: JKTypeFactory) : this(target.canonicalText, typeFactory)
override val receiverType: JKType? override val receiverType: JKType?
get() = null get() = typeFactory.types.nullableAny
override val parameterTypes: List<JKType> override val parameterTypes: List<JKType>
get() = emptyList() get() = emptyList()
} }
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.nj2k.tree package org.jetbrains.kotlin.nj2k.tree
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl import org.jetbrains.kotlin.nj2k.types.JKNoType
abstract class JKDeclaration : JKTreeElement(), PsiOwner by PsiOwnerImpl() { abstract class JKDeclaration : JKTreeElement(), PsiOwner by PsiOwnerImpl() {
abstract val name: JKNameIdentifier abstract val name: JKNameIdentifier
@@ -168,15 +168,13 @@ class JKConstructorImpl(
visibilityElement: JKVisibilityModifierElement, visibilityElement: JKVisibilityModifierElement,
modalityElement: JKModalityModifierElement modalityElement: JKModalityModifierElement
) : JKConstructor() { ) : JKConstructor() {
override var returnType: JKTypeElement by child(JKTypeElement(JKNoTypeImpl)) override var returnType: JKTypeElement by child(JKTypeElement(JKNoType))
override var name: JKNameIdentifier by child(name) override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters) override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(block) override var block: JKBlock by child(block)
override var delegationCall: JKExpression by child(delegationCall) override var delegationCall: JKExpression by child(delegationCall)
override var typeParameterList: JKTypeParameterList by child(JKTypeParameterList()) override var typeParameterList: JKTypeParameterList by child(JKTypeParameterList())
override var annotationList: JKAnnotationList by child(annotationList) override var annotationList: JKAnnotationList by child(annotationList)
override var otherModifierElements by children(otherModifierElements) override var otherModifierElements by children(otherModifierElements)
override var visibilityElement by child(visibilityElement) override var visibilityElement by child(visibilityElement)
override var modalityElement by child(modalityElement) override var modalityElement by child(modalityElement)
@@ -194,8 +192,7 @@ class JKKtPrimaryConstructor(
visibilityElement: JKVisibilityModifierElement, visibilityElement: JKVisibilityModifierElement,
modalityElement: JKModalityModifierElement modalityElement: JKModalityModifierElement
) : JKConstructor() { ) : JKConstructor() {
override var returnType: JKTypeElement by child(JKTypeElement(JKNoTypeImpl)) override var returnType: JKTypeElement by child(JKTypeElement(JKNoType))
override var name: JKNameIdentifier by child(name) override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters) override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(JKBodyStub) override var block: JKBlock by child(JKBodyStub)
@@ -9,14 +9,16 @@ import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.nj2k.types.JKContextType import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKType
abstract class JKExpression : JKAnnotationMemberValue(), PsiOwner by PsiOwnerImpl() abstract class JKExpression : JKAnnotationMemberValue(), PsiOwner by PsiOwnerImpl() {
// we don't need exact type here (eg with substituted type parameters)
abstract fun calculateType(typeFactory: JKTypeFactory): JKType
}
abstract class JKOperatorExpression : JKExpression() { abstract class JKOperatorExpression : JKExpression() {
abstract var operator: JKOperator abstract var operator: JKOperator
override fun calculateType(typeFactory: JKTypeFactory) = operator.returnType
} }
class JKBinaryExpression( class JKBinaryExpression(
@@ -50,31 +52,20 @@ class JKQualifiedExpression(
) : JKExpression() { ) : JKExpression() {
var receiver: JKExpression by child(receiver) var receiver: JKExpression by child(receiver)
var selector: JKExpression by child(selector) var selector: JKExpression by child(selector)
override fun calculateType(typeFactory: JKTypeFactory) = selector.calculateType(typeFactory)
override fun accept(visitor: JKVisitor) = visitor.visitQualifiedExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitQualifiedExpression(this)
} }
class JKArrayAccessExpression(
expression: JKExpression,
indexExpression: JKExpression
) : JKExpression() {
var expression: JKExpression by child(expression)
var indexExpression: JKExpression by child(indexExpression)
override fun accept(visitor: JKVisitor) = visitor.visitArrayAccessExpression(this)
}
class JKParenthesizedExpression(expression: JKExpression) : JKExpression() { class JKParenthesizedExpression(expression: JKExpression) : JKExpression() {
var expression: JKExpression by child(expression) var expression: JKExpression by child(expression)
override fun calculateType(typeFactory: JKTypeFactory) = expression.calculateType(typeFactory)
override fun accept(visitor: JKVisitor) = visitor.visitParenthesizedExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitParenthesizedExpression(this)
} }
class JKTypeCastExpression(expression: JKExpression, type: JKTypeElement) : JKExpression() { class JKTypeCastExpression(expression: JKExpression, type: JKTypeElement) : JKExpression() {
var expression by child(expression) var expression by child(expression)
var type by child(type) var type by child(type)
override fun calculateType(typeFactory: JKTypeFactory) = type.type
override fun accept(visitor: JKVisitor) = visitor.visitTypeCastExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitTypeCastExpression(this)
} }
@@ -84,38 +75,57 @@ class JKLiteralExpression(
) : JKExpression() { ) : JKExpression() {
override fun accept(visitor: JKVisitor) = visitor.visitLiteralExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitLiteralExpression(this)
override fun calculateType(typeFactory: JKTypeFactory) = when (type) {
LiteralType.CHAR -> typeFactory.types.char
LiteralType.BOOLEAN -> typeFactory.types.boolean
LiteralType.INT -> typeFactory.types.int
LiteralType.LONG -> typeFactory.types.long
LiteralType.FLOAT -> typeFactory.types.float
LiteralType.DOUBLE -> typeFactory.types.double
LiteralType.NULL -> typeFactory.types.nullableAny
LiteralType.STRING -> typeFactory.types.string
}
enum class LiteralType { enum class LiteralType {
STRING, CHAR, BOOLEAN, NULL, INT, LONG, FLOAT, DOUBLE STRING, CHAR, BOOLEAN, NULL, INT, LONG, FLOAT, DOUBLE
} }
} }
class JKStubExpression : JKExpression() { class JKStubExpression : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitStubExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitStubExpression(this)
} }
class JKThisExpression(qualifierLabel: JKLabel) : JKExpression() { class JKThisExpression(qualifierLabel: JKLabel, private val type: JKType) : JKExpression() {
var qualifierLabel: JKLabel by child(qualifierLabel) var qualifierLabel: JKLabel by child(qualifierLabel)
override fun calculateType(typeFactory: JKTypeFactory) = type
override fun accept(visitor: JKVisitor) = visitor.visitThisExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitThisExpression(this)
} }
class JKSuperExpression(qualifierLabel: JKLabel = JKLabelEmpty()) : JKExpression() { class JKSuperExpression(qualifierLabel: JKLabel, private val type: JKType) : JKExpression() {
var qualifierLabel: JKLabel by child(qualifierLabel) var qualifierLabel: JKLabel by child(qualifierLabel)
override fun calculateType(typeFactory: JKTypeFactory) = type
override fun accept(visitor: JKVisitor) = visitor.visitSuperExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitSuperExpression(this)
} }
class JKIfElseExpression(condition: JKExpression, thenBranch: JKExpression, elseBranch: JKExpression) : JKExpression() { class JKIfElseExpression(
condition: JKExpression,
thenBranch: JKExpression,
elseBranch: JKExpression,
private val type: JKType
) : JKExpression() {
var condition by child(condition) var condition by child(condition)
var thenBranch by child(thenBranch) var thenBranch by child(thenBranch)
var elseBranch by child(elseBranch) var elseBranch by child(elseBranch)
override fun calculateType(typeFactory: JKTypeFactory): JKType = type
override fun accept(visitor: JKVisitor) = visitor.visitIfElseExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitIfElseExpression(this)
} }
class JKLambdaExpression( class JKLambdaExpression(
statement: JKStatement, statement: JKStatement,
parameters: List<JKParameter>, parameters: List<JKParameter>,
functionalType: JKTypeElement = JKTypeElement(JKNoTypeImpl), functionalType: JKTypeElement = JKTypeElement(JKNoType),
returnType: JKTypeElement = JKTypeElement(JKContextType) returnType: JKTypeElement = JKTypeElement(JKContextType)
) : JKExpression() { ) : JKExpression() {
var statement by child(statement) var statement by child(statement)
@@ -123,6 +133,7 @@ class JKLambdaExpression(
var functionalType by child(functionalType) var functionalType by child(functionalType)
val returnType by child(returnType) val returnType by child(returnType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitLambdaExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitLambdaExpression(this)
} }
@@ -130,6 +141,7 @@ class JKLambdaExpression(
abstract class JKCallExpression : JKExpression(), JKTypeArgumentListOwner { abstract class JKCallExpression : JKExpression(), JKTypeArgumentListOwner {
abstract val identifier: JKMethodSymbol abstract val identifier: JKMethodSymbol
abstract var arguments: JKArgumentList abstract var arguments: JKArgumentList
override fun calculateType(typeFactory: JKTypeFactory): JKType = identifier.returnType ?: JKNoType
} }
class JKDelegationConstructorCall( class JKDelegationConstructorCall(
@@ -140,7 +152,6 @@ class JKDelegationConstructorCall(
override var typeArgumentList: JKTypeArgumentList by child(JKTypeArgumentList()) override var typeArgumentList: JKTypeArgumentList by child(JKTypeArgumentList())
val expression: JKExpression by child(expression) val expression: JKExpression by child(expression)
override var arguments: JKArgumentList by child(arguments) override var arguments: JKArgumentList by child(arguments)
override fun accept(visitor: JKVisitor) = visitor.visitDelegationConstructorCall(this) override fun accept(visitor: JKVisitor) = visitor.visitDelegationConstructorCall(this)
} }
@@ -164,20 +175,24 @@ class JKNewExpression(
var typeArgumentList by child(typeArgumentList) var typeArgumentList by child(typeArgumentList)
var arguments by child(arguments) var arguments by child(arguments)
var classBody by child(classBody) var classBody by child(classBody)
override fun calculateType(typeFactory: JKTypeFactory) = classSymbol.asType()
override fun accept(visitor: JKVisitor) = visitor.visitNewExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitNewExpression(this)
} }
class JKFieldAccessExpression(var identifier: JKFieldSymbol) : JKExpression() { class JKFieldAccessExpression(var identifier: JKFieldSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = identifier.fieldType ?: JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitFieldAccessExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitFieldAccessExpression(this)
} }
class JKPackageAccessExpression(var identifier: JKPackageSymbol) : JKExpression() { class JKPackageAccessExpression(var identifier: JKPackageSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitPackageAccessExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitPackageAccessExpression(this)
} }
class JKClassAccessExpression(var identifier: JKClassSymbol) : JKExpression() { class JKClassAccessExpression(var identifier: JKClassSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitClassAccessExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitClassAccessExpression(this)
} }
@@ -189,7 +204,7 @@ class JKMethodReferenceExpression(
) : JKExpression() { ) : JKExpression() {
val qualifier by child(qualifier) val qualifier by child(qualifier)
val functionalType by child(functionalType) val functionalType by child(functionalType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitMethodReferenceExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitMethodReferenceExpression(this)
} }
@@ -197,6 +212,7 @@ class JKMethodReferenceExpression(
class JKLabeledExpression(statement: JKStatement, labels: List<JKNameIdentifier>) : JKExpression() { class JKLabeledExpression(statement: JKStatement, labels: List<JKNameIdentifier>) : JKExpression() {
var statement: JKStatement by child(statement) var statement: JKStatement by child(statement)
val labels: List<JKNameIdentifier> by children(labels) val labels: List<JKNameIdentifier> by children(labels)
override fun calculateType(typeFactory: JKTypeFactory) = typeFactory.types.unit
override fun accept(visitor: JKVisitor) = visitor.visitLabeledExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitLabeledExpression(this)
} }
@@ -205,6 +221,10 @@ class JKClassLiteralExpression(
var literalType: ClassLiteralType var literalType: ClassLiteralType
) : JKExpression() { ) : JKExpression() {
val classType: JKTypeElement by child(classType) val classType: JKTypeElement by child(classType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = when (literalType) {
ClassLiteralType.KOTLIN_CLASS -> typeFactory.types.kotlinClass
else -> typeFactory.types.javaKlass
}
override fun accept(visitor: JKVisitor) = visitor.visitClassLiteralExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitClassLiteralExpression(this)
@@ -221,6 +241,7 @@ abstract class JKKtAssignmentChainLink : JKExpression() {
abstract val receiver: JKExpression abstract val receiver: JKExpression
abstract val assignmentStatement: JKKtAssignmentStatement abstract val assignmentStatement: JKKtAssignmentStatement
abstract val field: JKExpression abstract val field: JKExpression
override fun calculateType(typeFactory: JKTypeFactory) = field.calculateType(typeFactory)
} }
class JKAssignmentChainAlsoLink( class JKAssignmentChainAlsoLink(
@@ -231,7 +252,6 @@ class JKAssignmentChainAlsoLink(
override val receiver by child(receiver) override val receiver by child(receiver)
override val assignmentStatement by child(assignmentStatement) override val assignmentStatement by child(assignmentStatement)
override val field by child(field) override val field by child(field)
override fun accept(visitor: JKVisitor) = visitor.visitAssignmentChainAlsoLink(this) override fun accept(visitor: JKVisitor) = visitor.visitAssignmentChainAlsoLink(this)
} }
@@ -243,7 +263,6 @@ class JKAssignmentChainLetLink(
override val receiver by child(receiver) override val receiver by child(receiver)
override val assignmentStatement by child(assignmentStatement) override val assignmentStatement by child(assignmentStatement)
override val field by child(field) override val field by child(field)
override fun accept(visitor: JKVisitor) = visitor.visitAssignmentChainLetLink(this) override fun accept(visitor: JKVisitor) = visitor.visitAssignmentChainLetLink(this)
} }
@@ -251,16 +270,18 @@ class JKAssignmentChainLetLink(
class JKIsExpression(expression: JKExpression, type: JKTypeElement) : JKExpression() { class JKIsExpression(expression: JKExpression, type: JKTypeElement) : JKExpression() {
var type by child(type) var type by child(type)
var expression by child(expression) var expression by child(expression)
override fun calculateType(typeFactory: JKTypeFactory) = typeFactory.types.boolean
override fun accept(visitor: JKVisitor) = visitor.visitIsExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitIsExpression(this)
} }
class JKKtThrowExpression(exception: JKExpression) : JKExpression() { class JKKtThrowExpression(exception: JKExpression) : JKExpression() {
var exception: JKExpression by child(exception) var exception: JKExpression by child(exception)
override fun calculateType(typeFactory: JKTypeFactory) = typeFactory.types.nothing
override fun accept(visitor: JKVisitor) = visitor.visitKtThrowExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitKtThrowExpression(this)
} }
class JKKtItExpression(val type: JKType) : JKExpression() { class JKKtItExpression(val type: JKType) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = type
override fun accept(visitor: JKVisitor) = visitor.visitKtItExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitKtItExpression(this)
} }
@@ -268,6 +289,7 @@ class JKKtAnnotationArrayInitializerExpression(initializers: List<JKAnnotationMe
constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList()) constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList())
val initializers: List<JKAnnotationMemberValue> by children(initializers) val initializers: List<JKAnnotationMemberValue> by children(initializers)
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitKtAnnotationArrayInitializerExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitKtAnnotationArrayInitializerExpression(this)
} }
@@ -279,27 +301,23 @@ class JKKtTryExpression(
var tryBlock: JKBlock by child(tryBlock) var tryBlock: JKBlock by child(tryBlock)
var finallyBlock: JKBlock by child(finallyBlock) var finallyBlock: JKBlock by child(finallyBlock)
var catchSections: List<JKKtTryCatchSection> by children(catchSections) var catchSections: List<JKKtTryCatchSection> by children(catchSections)
override fun accept(visitor: JKVisitor) = visitor.visitKtTryExpression(this) override fun calculateType(typeFactory: JKTypeFactory) =
} typeFactory.types.unit // as converted from Java try statement
class JKKtTryCatchSection( override fun accept(visitor: JKVisitor) = visitor.visitKtTryExpression(this)
parameter: JKParameter,
block: JKBlock
) : JKTreeElement() {
var parameter: JKParameter by child(parameter)
var block: JKBlock by child(block)
override fun accept(visitor: JKVisitor) = visitor.visitKtTryCatchSection(this)
} }
class JKJavaNewEmptyArray(initializer: List<JKExpression>, type: JKTypeElement) : JKExpression() { class JKJavaNewEmptyArray(initializer: List<JKExpression>, type: JKTypeElement) : JKExpression() {
val type by child(type) val type by child(type)
var initializer by children(initializer) var initializer by children(initializer)
override fun calculateType(typeFactory: JKTypeFactory) = type.type
override fun accept(visitor: JKVisitor) = visitor.visitJavaNewEmptyArray(this) override fun accept(visitor: JKVisitor) = visitor.visitJavaNewEmptyArray(this)
} }
class JKJavaNewArray(initializer: List<JKExpression>, type: JKTypeElement) : JKExpression() { class JKJavaNewArray(initializer: List<JKExpression>, type: JKTypeElement) : JKExpression() {
val type by child(type) val type by child(type)
var initializer by children(initializer) var initializer by children(initializer)
override fun calculateType(typeFactory: JKTypeFactory) = type.type
override fun accept(visitor: JKVisitor) = visitor.visitJavaNewArray(this) override fun accept(visitor: JKVisitor) = visitor.visitJavaNewArray(this)
} }
@@ -311,5 +329,6 @@ class JKJavaAssignmentExpression(
) : JKExpression() { ) : JKExpression() {
var field by child(field) var field by child(field)
var expression by child(expression) var expression by child(expression)
override fun calculateType(typeFactory: JKTypeFactory) = field.calculateType(typeFactory)
override fun accept(visitor: JKVisitor) = visitor.visitJavaAssignmentExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitJavaAssignmentExpression(this)
} }
@@ -51,6 +51,9 @@ class JKTypeFactory(val symbolProvider: JKSymbolProvider) {
val unit = typeByFqName(KotlinBuiltIns.FQ_NAMES.unit) val unit = typeByFqName(KotlinBuiltIns.FQ_NAMES.unit)
val nothing = typeByFqName(KotlinBuiltIns.FQ_NAMES.nothing) val nothing = typeByFqName(KotlinBuiltIns.FQ_NAMES.nothing)
val nullableAny = typeByFqName(KotlinBuiltIns.FQ_NAMES.any, nullability = Nullability.Nullable) val nullableAny = typeByFqName(KotlinBuiltIns.FQ_NAMES.any, nullability = Nullability.Nullable)
val javaKlass = typeByFqName(FqNameUnsafe(CommonClassNames.JAVA_LANG_CLASS))
val kotlinClass = typeByFqName(KotlinBuiltIns.FQ_NAMES.kClass)
} }
fun fromPrimitiveType(primitiveType: JKJavaPrimitiveType) = when (primitiveType.jvmPrimitiveType) { fun fromPrimitiveType(primitiveType: JKJavaPrimitiveType) = when (primitiveType.jvmPrimitiveType) {
@@ -16,31 +16,24 @@ interface JKType {
interface JKWildCardType : JKType interface JKWildCardType : JKType
interface JKNoType : JKType
interface JKParametrizedType : JKType { interface JKParametrizedType : JKType {
val parameters: List<JKType> val parameters: List<JKType>
} }
interface JKClassType : JKParametrizedType {
val classReference: JKClassSymbol
override val nullability: Nullability
}
interface JKStarProjectionType : JKWildCardType { interface JKStarProjectionType : JKWildCardType {
override val nullability: Nullability override val nullability: Nullability
get() = Nullability.NotNull get() = Nullability.NotNull
} }
object JKNoTypeImpl : JKNoType { object JKNoType : JKType {
override val nullability: Nullability = Nullability.NotNull override val nullability: Nullability = Nullability.NotNull
} }
data class JKClassTypeImpl( data class JKClassType(
override val classReference: JKClassSymbol, val classReference: JKClassSymbol,
override val parameters: List<JKType> = emptyList(), override val parameters: List<JKType> = emptyList(),
override val nullability: Nullability = Nullability.Default override val nullability: Nullability = Nullability.Default
) : JKClassType ) : JKParametrizedType
object JKStarProjectionTypeImpl : JKStarProjectionType object JKStarProjectionTypeImpl : JKStarProjectionType
@@ -16,9 +16,7 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.JKSymbolProvider import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.toJkType
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
@@ -26,57 +24,11 @@ import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun JKExpression.type(typeFactory: JKTypeFactory): JKType? =
when (this) {
is JKLiteralExpression -> type.toJkType(typeFactory)
is JKOperatorExpression -> {
when (val operator = operator) {
is JKKtOperatorImpl -> operator.returnType
is JKKtSpreadOperator -> (this as JKPrefixExpression).expression.type(typeFactory)//TODO ger real type
else -> error("Cannot get type of ${operator::class}, it should be first converted to KtOperator")
}
}
is JKCallExpression -> identifier.returnType
is JKFieldAccessExpression -> identifier.fieldType
is JKQualifiedExpression -> selector.type(typeFactory)
is JKKtThrowExpression -> typeFactory.types.nothing
is JKClassAccessExpression ->
JKClassTypeImpl(identifier, emptyList(), Nullability.NotNull)
is JKIsExpression -> typeFactory.types.boolean
is JKParenthesizedExpression -> expression.type(typeFactory)
is JKTypeCastExpression -> type.type
is JKThisExpression -> null// TODO return actual type
is JKSuperExpression -> null// TODO return actual type
is JKStubExpression -> null
is JKIfElseExpression -> thenBranch.type(typeFactory)// TODO return actual type
is JKArrayAccessExpression ->
(expression.type(typeFactory) as? JKParametrizedType)?.parameters?.lastOrNull()
is JKClassLiteralExpression -> {
val symbol = when (literalType) {
JKClassLiteralExpression.ClassLiteralType.KOTLIN_CLASS ->
typeFactory.symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe())
JKClassLiteralExpression.ClassLiteralType.JAVA_CLASS,
JKClassLiteralExpression.ClassLiteralType.JAVA_PRIMITIVE_CLASS, JKClassLiteralExpression.ClassLiteralType.JAVA_VOID_TYPE ->
typeFactory.symbolProvider.provideClassSymbol("java.lang.Class")
}
JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull)
}
is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO
is JKLambdaExpression -> returnType.type
is JKLabeledExpression -> typeFactory.types.unit
is JKMethodReferenceExpression -> JKNoTypeImpl //TODO
is JKAssignmentChainAlsoLink -> receiver.type(typeFactory)
is JKAssignmentChainLetLink -> field.type(typeFactory)
is JKKtItExpression -> type
is JKNewExpression -> JKClassTypeImpl(classSymbol)
else -> TODO(this::class.java.toString())
}
fun JKType.asTypeElement() = fun JKType.asTypeElement() =
JKTypeElement(this) JKTypeElement(this)
fun JKClassSymbol.asType(nullability: Nullability = Nullability.Default): JKClassType = fun JKClassSymbol.asType(nullability: Nullability = Nullability.Default): JKClassType =
JKClassTypeImpl(this, emptyList(), nullability) JKClassType(this, emptyList(), nullability)
val PsiType.isKotlinFunctionalType: Boolean val PsiType.isKotlinFunctionalType: Boolean
get() { get() {
@@ -112,8 +64,8 @@ private val jvmPrimitiveTypesPriority =
fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType = fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType =
transform(this) ?: when (this) { transform(this) ?: when (this) {
is JKTypeParameterType -> this is JKTypeParameterType -> this
is JKClassTypeImpl -> is JKClassType ->
JKClassTypeImpl( JKClassType(
classReference, classReference,
parameters.map { it.applyRecursive(transform) }, parameters.map { it.applyRecursive(transform) },
nullability nullability
@@ -133,7 +85,7 @@ inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability)
if (nullability == newNullability) this if (nullability == newNullability) this
else when (this) { else when (this) {
is JKTypeParameterType -> JKTypeParameterType(identifier, newNullability) is JKTypeParameterType -> JKTypeParameterType(identifier, newNullability)
is JKClassTypeImpl -> JKClassTypeImpl(classReference, parameters, newNullability) is JKClassType -> JKClassType(classReference, parameters, newNullability)
is JKNoType -> this is JKNoType -> this
is JKJavaVoidType -> this is JKJavaVoidType -> this
is JKJavaPrimitiveType -> this is JKJavaPrimitiveType -> this
@@ -148,8 +100,8 @@ fun <T : JKType> T.updateNullabilityRecursively(newNullability: Nullability): T
applyRecursive { applyRecursive {
when (it) { when (it) {
is JKTypeParameterType -> JKTypeParameterType(it.identifier, newNullability) is JKTypeParameterType -> JKTypeParameterType(it.identifier, newNullability)
is JKClassTypeImpl -> is JKClassType ->
JKClassTypeImpl( JKClassType(
it.classReference, it.classReference,
it.parameters.map { it.updateNullabilityRecursively(newNullability) }, it.parameters.map { it.updateNullabilityRecursively(newNullability) },
newNullability newNullability
@@ -271,7 +223,7 @@ fun JKType.isInterface(): Boolean =
fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType = fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType =
applyRecursive { type -> applyRecursive { type ->
if (type is JKClassType && type.classReference.fqName == "java.lang.Class") { if (type is JKClassType && type.classReference.fqName == "java.lang.Class") {
JKClassTypeImpl( JKClassType(
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()), symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()),
type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) }, type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) },
Nullability.NotNull Nullability.NotNull