New J2K: Add calculating type for binary expressions & building binary expression with correct return type

This commit is contained in:
Ilya Kirillov
2018-10-30 13:57:23 +03:00
committed by Ilya Kirillov
parent 5e4b39f10f
commit cd2a17ae56
10 changed files with 205 additions and 119 deletions
@@ -23,6 +23,7 @@ object ConversionsRunner {
private fun createRootConversion(context: ConversionContext) =
batchPipe {
+BinaryExpressionConversion(context)
+ArrayInitializerConversion(context)
+ModalityConversion(context)
+ImplicitInitializerConversion()
@@ -47,7 +48,6 @@ object ConversionsRunner {
+StaticsToCompanionExtractConversion()
+ClassToObjectPromotionConversion()
+PolyadicExpressionConversion()
+BinaryExpressionConversion()
+SwitchStatementConversion(context)
+InstanceofConversion()
+ForConversion(context)
@@ -36,7 +36,7 @@ class JKSymbolProvider {
is KtClassOrObject -> JKMultiverseKtClassSymbol(psi)
is PsiMethod -> JKMultiverseMethodSymbol(psi, this)
is PsiField -> JKMultiverseFieldSymbol(psi)
is KtNamedFunction -> JKMultiverseFunctionSymbol(psi)
is KtNamedFunction -> JKMultiverseFunctionSymbol(psi, this)
is KtProperty -> JKMultiversePropertySymbol(psi)
else -> TODO(psi::class.toString())
}
@@ -167,7 +167,7 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
fun PsiArrayInitializerExpression.toJK(): JKExpression {
return JKJavaNewArrayImpl(
initializers.map { it.toJK() },
JKTypeElementImpl(type?.toJK().safeAs<JKJavaArrayType>()?.type ?: JKContextType)
JKTypeElementImpl(type?.toJK(symbolProvider).safeAs<JKJavaArrayType>()?.type ?: JKContextType)
)
}
@@ -190,7 +190,7 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
}
JKJavaNewEmptyArrayImpl(
dimensions.map { it?.toJK() ?: JKStubExpressionImpl() },
JKTypeElementImpl(generateSequence(type?.toJK()) { it.safeAs<JKJavaArrayType>()?.type }.last())
JKTypeElementImpl(generateSequence(type?.toJK(symbolProvider)) { it.safeAs<JKJavaArrayType>()?.type }.last())
)
}
}
@@ -226,32 +226,10 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
}
fun PsiTypeElement.toJK(): JKTypeElement {
return JKTypeElementImpl(type.toJK()).also {
return JKTypeElementImpl(type.toJK(symbolProvider)).also {
backAnnotation[it] = this
}
}
fun PsiType.toJK(nullability: Nullability = Nullability.Default): JKType {
return when (this) {
is PsiClassType -> {
val target = resolve()
val parameters = parameters.map { it.toJK() }
if (target != null) {
JKClassTypeImpl(
target.let { symbolProvider.provideDirectSymbol(it) as JKClassSymbol },
parameters,
nullability
)
} else {
JKUnresolvedClassType(this.rawType().canonicalText, parameters, nullability)
}
}
is PsiArrayType -> JKJavaArrayTypeImpl(componentType.toJK(), nullability)
is PsiPrimitiveType -> JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE[presentableText]
?: error("Invalid primitive type $presentableText")
else -> throw Exception("Invalid PSI")
}
}
}
private inner class DeclarationMapper(val expressionTreeMapper: ExpressionTreeMapper) {
@@ -264,7 +242,7 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
}
fun PsiReferenceList.mapTypes() =
this.referencedTypes.map { with(expressionTreeMapper) { JKTypeElementImpl(it.toJK(Nullability.NotNull)) } }
this.referencedTypes.map { with(expressionTreeMapper) { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.NotNull)) } }
val implTypes = this.implementsList?.mapTypes().orEmpty()
val extTypes = this.extendsList?.mapTypes().orEmpty()
@@ -16,16 +16,17 @@ import org.jetbrains.kotlin.lexer.KtTokens
class AssignmentStatementOperatorConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKKtAssignmentStatement) return recurse(element)
val newOperator = JKKtOperatorImpl.javaToKotlinOperator[element.operator] ?: return recurse(element)
if (newOperator is JKKtWordOperatorImpl) {
element.operator = JKKtOperatorImpl.tokenToOperator[KtTokens.EQ] ?: return recurse(element)
val expr = element.expression
element.expression = JKStubExpressionImpl()
element.expression = JKBinaryExpressionImpl(element.field.copyTree(), expr, newOperator)
} else {
element.operator = newOperator
}
//todo fix
// if (element !is JKKtAssignmentStatement) return recurse(element)
// val newOperator = JKKtOperatorImpl.javaToKotlinOperator[element.operator] ?: return recurse(element)
// if (newOperator is JKKtWordOperatorImpl) {
// element.operator = JKKtOperatorImpl.tokenToOperator[KtTokens.EQ] ?: return recurse(element)
// val expr = element.expression
// element.expression = JKStubExpressionImpl()
// element.expression = JKBinaryExpressionImpl(element.field.copyTree(), expr, newOperator)
// } else {
// element.operator = newOperator
// }
return recurse(element)
}
}
@@ -5,15 +5,25 @@
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKBinaryExpression
import org.jetbrains.kotlin.j2k.tree.JKBranchElement
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.JKKtOperatorImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKBinaryExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKJavaOperatorImpl
import org.jetbrains.kotlin.j2k.tree.impl.toKtToken
class BinaryExpressionConversion : RecursiveApplicableConversionBase() {
class BinaryExpressionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKBinaryExpression)
element.operator = JKKtOperatorImpl.javaToKotlinOperator[element.operator] ?: element.operator
return recurse(element)
if (element !is JKBinaryExpression) return recurse(element)
val ktOperator = (element.operator as? JKJavaOperatorImpl)?.toKtToken() ?: return recurse(element)
val left = recurse(element.left)
val right = recurse(element.right)
(element as? JKBranchElement)?.invalidate()
val ktBinaryExpression = JKBinaryExpressionImpl.createKotlinBinaryExpression(left, right, ktOperator, context)
?: return JKBinaryExpressionImpl(left, right, element.operator)
return recurse(ktBinaryExpression)
}
}
@@ -157,11 +157,12 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
context,
psiContext
)
else -> JKBinaryExpressionImpl(
else -> JKBinaryExpressionImpl.createKotlinBinaryExpression(
start,
convertBound(bound, if (inclusiveComparison) 0 else -1),
JKKtOperatorImpl.tokenToOperator[KtTokens.RANGE]!!
)
KtTokens.RANGE,
context
)!!
}
}
@@ -174,11 +175,11 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
}
val sign = if (correction > 0) KtTokens.PLUS else KtTokens.MINUS
return JKBinaryExpressionImpl(
return JKBinaryExpressionImpl.createKotlinBinaryExpression(
bound,
JKKtLiteralExpressionImpl(Math.abs(correction).toString(), JKLiteralExpression.LiteralType.INT),
JKKtOperatorImpl.tokenToOperator[sign]!!
)
sign,
context)!!
}
private fun indicesIterationRange(
@@ -18,16 +18,21 @@ package org.jetbrains.kotlin.j2k.tree.impl
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.ast.Mutability
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.BOOLEAN
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.NULL
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.types.expressions.OperatorConventions
class JKFileImpl : JKFile, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitFile(this, data)
@@ -104,7 +109,7 @@ class JKBlockImpl(statements: List<JKStatement> = emptyList()) : JKBlock, JKBran
override var statements by children(statements)
}
//todo split to java and kt sbinary expression
class JKBinaryExpressionImpl(
left: JKExpression,
right: JKExpression,
@@ -112,11 +117,61 @@ class JKBinaryExpressionImpl(
) : JKBinaryExpression,
JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBinaryExpression(this, data)
override var right by child(right)
override var left by child(left)
companion object {
private fun methodSymbolForToken(
token: KtSingleValueToken,
leftType: JKType,
rightType: JKType,
symbolProvider: JKSymbolProvider
): JKMethodSymbol {
val classSymbol =
when (leftType) {
is JKClassType -> leftType.classReference as JKMultiverseKtClassSymbol
is JKJavaPrimitiveType -> {
val psiClass = resolveFqName(
ClassId.fromString(leftType.jvmPrimitiveType.primitiveType.typeFqName.asString()),
symbolProvider.symbolsByPsi.keys.first()
)!!
symbolProvider.provideDirectSymbol(psiClass) as JKMultiverseKtClassSymbol
}
else ->
TODO(leftType::class.java.toString())
}
return classSymbol.target.declarations// todo look for extensions
.asSequence()
.filterIsInstance<KtNamedFunction>()
.filter { it.name == operatorName }
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
.firstOrNull { it.parameterTypes.singleOrNull()?.takeIf { it.isSubtypeOf(rightType, symbolProvider) } != null }!!
}
fun createKotlinBinaryExpression(
left: JKExpression,
right: JKExpression,
token: KtSingleValueToken,
context: ConversionContext
): JKBinaryExpression? {
val leftType = left.type(context)
val rightType = right.type(context)
val methodSymbol = methodSymbolForToken(token, leftType, rightType, context.symbolProvider)
return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, methodSymbol))
}
}
}
infix fun JKType?.equalsIgnoreMutability(other: JKType?) =
when {
(this is JKClassTypeImpl && other is JKClassTypeImpl) ->
this.classReference == other.classReference && this.parameters == other.parameters
else -> TODO("No comparation for $this and $other")
}
class JKPrefixExpressionImpl(expression: JKExpression, override var operator: JKOperator) : JKPrefixExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitPrefixExpression(this, data)
@@ -236,19 +291,27 @@ class JKBooleanLiteral(val value: Boolean) : JKLiteralExpression, JKElementBase(
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLiteralExpression(this, data)
}
fun JKLiteralExpression.LiteralType.toJkType(symbolProvider: JKSymbolProvider): JKType =
when (this) {
JKLiteralExpression.LiteralType.CHAR -> JKJavaPrimitiveTypeImpl.CHAR
JKLiteralExpression.LiteralType.BOOLEAN -> JKJavaPrimitiveTypeImpl.BOOLEAN
JKLiteralExpression.LiteralType.INT -> JKJavaPrimitiveTypeImpl.INT
JKLiteralExpression.LiteralType.LONG -> JKJavaPrimitiveTypeImpl.LONG
JKLiteralExpression.LiteralType.FLOAT -> JKJavaPrimitiveTypeImpl.FLOAT
JKLiteralExpression.LiteralType.DOUBLE -> JKJavaPrimitiveTypeImpl.DOUBLE
fun JKLiteralExpression.LiteralType.toJkType(symbolProvider: JKSymbolProvider): JKType {
fun defaultTypeByName(name: String) =
JKClassTypeImpl(
symbolProvider.provideDirectSymbol(
resolveFqName(ClassId.fromString("kotlin.$name"), symbolProvider.symbolsByPsi.keys.first())!!
) as JKClassSymbol, emptyList(), Nullability.NotNull
)
return when (this) {
JKLiteralExpression.LiteralType.CHAR -> defaultTypeByName("Char")
JKLiteralExpression.LiteralType.BOOLEAN -> defaultTypeByName("Boolean")
JKLiteralExpression.LiteralType.INT -> defaultTypeByName("Int")
JKLiteralExpression.LiteralType.LONG -> defaultTypeByName("Long")
JKLiteralExpression.LiteralType.FLOAT -> defaultTypeByName("Float")
JKLiteralExpression.LiteralType.DOUBLE -> defaultTypeByName("Double")
JKLiteralExpression.LiteralType.NULL ->
ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.unit.toSafe()).toKtClassType(symbolProvider)
JKLiteralExpression.LiteralType.STRING ->
ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.string.toSafe()).toKtClassType(symbolProvider)
}
}
class JKLocalVariableImpl(modifierList: JKModifierList, type: JKTypeElement, name: JKNameIdentifier, initializer: JKExpression) :
JKLocalVariable, JKBranchElementBase() {
@@ -83,56 +83,27 @@ class JKKtLiteralExpressionImpl(
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtLiteralExpression(this, data)
}
class JKKtOperatorImpl private constructor(val token: KtSingleValueToken) : JKOperator, JKElementBase() {
fun JKJavaOperatorImpl.toKtToken(): KtSingleValueToken =
when (this.token) {
JavaTokenType.DIV -> KtTokens.DIV
JavaTokenType.MINUS -> KtTokens.MINUS
JavaTokenType.ANDAND -> KtTokens.ANDAND
JavaTokenType.OROR -> KtTokens.OROR
JavaTokenType.PLUS -> KtTokens.PLUS
JavaTokenType.ASTERISK -> KtTokens.MUL
JavaTokenType.GT -> KtTokens.GT
JavaTokenType.GE -> KtTokens.GTEQ
JavaTokenType.LT -> KtTokens.LT
JavaTokenType.LE -> KtTokens.LTEQ
JavaTokenType.PERC -> KtTokens.PERC
else -> TODO(this.token::class.java.toString())
}
class JKKtOperatorImpl(val token: KtSingleValueToken, val methodSymbol: JKMethodSymbol) : JKOperator, JKElementBase() {
override val precedence: Int
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val operatorText: String
get() = token.value
companion object {
val tokenToOperator = KtTokens.OPERATIONS.types.filter { it is KtSingleValueToken }.associate {
it to JKKtOperatorImpl(it as KtSingleValueToken)
}
val javaToKotlinOperator = mutableMapOf<JKOperator, JKOperator>()
init {
javaToKotlinOperator.apply {
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.DIV]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.DIV]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.MINUS]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.MINUS]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.ANDAND]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.ANDAND]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.OROR]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.OROR]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.PLUS]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.PLUS]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.ASTERISK]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.MUL]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.GT]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.GT]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.GE]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.GTEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.LT]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.LT]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.LE]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.LTEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.PERC]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.PERC]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.EQ]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.EQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.PLUSEQ]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.PLUSEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.MINUSEQ]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.MINUSEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.ASTERISKEQ]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.MULTEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.DIVEQ]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.DIVEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.PERCEQ]!!] = JKKtOperatorImpl.tokenToOperator[KtTokens.PERCEQ]!!
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.AND]!!] = JKKtWordOperatorImpl("and")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.OR]!!] = JKKtWordOperatorImpl("or")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.XOR]!!] = JKKtWordOperatorImpl("xor")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.GTGTGT]!!] = JKKtWordOperatorImpl("ushr")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.GTGT]!!] = JKKtWordOperatorImpl("shr")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.LTLT]!!] = JKKtWordOperatorImpl("shl")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.OREQ]!!] = JKKtWordOperatorImpl("or")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.ANDEQ]!!] = JKKtWordOperatorImpl("and")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.XOREQ]!!] = JKKtWordOperatorImpl("xor")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.GTGTGTEQ]!!] = JKKtWordOperatorImpl("ushr")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.GTGTEQ]!!] = JKKtWordOperatorImpl("shr")
this[JKJavaOperatorImpl.tokenToOperator[JavaTokenType.LTLTEQ]!!] = JKKtWordOperatorImpl("shl")
}
}
}
}
class JKKtWordOperatorImpl constructor(override val operatorText: String) : JKOperator, JKElementBase() {
@@ -11,13 +11,11 @@ import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.conversions.parentOfType
import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKField
import org.jetbrains.kotlin.j2k.tree.JKMethod
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.getValueParameterList
interface JKSymbol {
val target: Any
@@ -37,6 +35,9 @@ interface JKClassSymbol : JKNamedSymbol
interface JKMethodSymbol : JKNamedSymbol {
override val fqName: String
val recivierType: JKType?
val parameterTypes: List<JKType>
val returnType: JKType
}
interface JKFieldSymbol : JKNamedSymbol {
@@ -75,6 +76,14 @@ class JKMultiverseKtClassSymbol(override val target: KtClassOrObject) : JKClassS
}
class JKUniverseMethodSymbol(private val symbolProvider: JKSymbolProvider) : JKMethodSymbol, JKUniverseSymbol<JKMethod> {
override val recivierType: JKType?
get() = (target.parent as? JKClass)?.let {
JKClassTypeImpl(symbolProvider.provideUniverseSymbol(it), emptyList()/*TODO*/)
}
override val parameterTypes: List<JKType>
get() = target.parameters.map { it.type.type }
override val returnType: JKType
get() = target.returnType.type
override val name: String
get() = target.name.value
override lateinit var target: JKMethod
@@ -85,6 +94,14 @@ class JKUniverseMethodSymbol(private val symbolProvider: JKSymbolProvider) : JKM
}
class JKMultiverseMethodSymbol(override val target: PsiMethod, private val symbolProvider: JKSymbolProvider) : JKMethodSymbol {
override val recivierType: JKType?
get() = target.containingClass?.let {
JKClassTypeImpl(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList()/*TODO*/)
}
override val parameterTypes: List<JKType>
get() = target.parameterList.parameters.map { it.type.toJK(symbolProvider) }
override val returnType: JKType
get() = target.returnType!!.toJK(symbolProvider)
override val name: String
get() = target.name
override val declaredIn: JKSymbol?
@@ -93,7 +110,13 @@ class JKMultiverseMethodSymbol(override val target: PsiMethod, private val symbo
get() = target.name // TODO("Fix this")
}
class JKMultiverseFunctionSymbol(override val target: KtNamedFunction) : JKMethodSymbol {
class JKMultiverseFunctionSymbol(override val target: KtNamedFunction, private val symbolProvider: JKSymbolProvider) : JKMethodSymbol {
override val recivierType: JKType?
get() = target.receiverTypeReference?.typeElement?.toJK(symbolProvider)
override val parameterTypes: List<JKType>
get() = target.valueParameters.map { it.typeReference!!.typeElement!!.toJK(symbolProvider) }
override val returnType: JKType
get() = target.typeReference!!.typeElement!!.toJK(symbolProvider)
override val name: String
get() = target.name!!
override val declaredIn: JKSymbol
@@ -146,7 +169,12 @@ class JKUnresolvedMethod(override val target: String) : JKMethodSymbol {
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String = target
override val recivierType: JKType?
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val parameterTypes: List<JKType>
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val returnType: JKType
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val name: String
get() = target
}
@@ -5,23 +5,22 @@
package org.jetbrains.kotlin.j2k.tree
import com.intellij.psi.PsiCatchSection
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol
import org.jetbrains.kotlin.j2k.tree.impl.JKClassTypeImpl
import org.jetbrains.kotlin.j2k.tree.impl.toJkType
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtTypeElement
import org.jetbrains.kotlin.psi.KtUserType
fun JKExpression.type(context: ConversionContext): JKType =
when (this) {
is JKLiteralExpression -> this.type.toJkType(context.symbolProvider)
else -> TODO(this.toString())
is JKLiteralExpression -> type.toJkType(context.symbolProvider)
is JKBinaryExpression -> (operator as JKKtOperatorImpl).methodSymbol.returnType
else -> TODO(this::class.java.toString())
}
fun ClassId.toKtClassType(
@@ -33,3 +32,38 @@ fun ClassId.toKtClassType(
return JKClassTypeImpl(typeSymbol, emptyList(), nullability)
}
fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Default): JKType {
return when (this) {
is PsiClassType -> {
val target = resolve()
val parameters = parameters.map { it.toJK(symbolProvider, nullability) }
if (target != null) {
JKClassTypeImpl(
target.let { symbolProvider.provideDirectSymbol(it) as JKClassSymbol },
parameters,
nullability
)
} else {
JKUnresolvedClassType(this.rawType().canonicalText, parameters, nullability)
}
}
is PsiArrayType -> JKJavaArrayTypeImpl(componentType.toJK(symbolProvider, nullability), nullability)
is PsiPrimitiveType -> JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE[presentableText]
?: error("Invalid primitive type $presentableText")
else -> throw Exception("Invalid PSI")
}
}
fun KtTypeElement.toJK(symbolProvider: JKSymbolProvider): JKType =
when (this) {
is KtUserType -> {
val qualifiedName = qualifier?.text?.let { it + "." }.orEmpty() + referencedName
val typeParameters = typeArguments.map { it.typeReference!!.typeElement!!.toJK(symbolProvider) }
val symbol = symbolProvider.provideDirectSymbol(
resolveFqName(ClassId.fromString(qualifiedName), this)!!
) as JKClassSymbol
JKClassTypeImpl(symbol, typeParameters)
}
else -> TODO(this::class.java.toString())
}