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

View File

@@ -60,8 +60,10 @@ class JavaToJKTreeBuilder constructor(
converterServices: NewJavaToKotlinServices,
private val importStorage: ImportStorage
) {
private fun PsiType.toJK() =
typeFactory.fromPsiType(this)
private fun PsiType?.toJK(): JKType {
if (this == null) return JKNoType
return typeFactory.fromPsiType(this)
}
private val expressionTreeMapper = ExpressionTreeMapper()
@@ -128,14 +130,19 @@ class JavaToJKTreeBuilder constructor(
is PsiInstanceOfExpression -> toJK()
is PsiThisExpression ->
JKThisExpression(
qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty()
qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty(),
type.toJK()
)
is PsiSuperExpression ->
JKSuperExpression(
qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty()
qualifier?.referenceName?.let { JKLabelText(JKNameIdentifier(it)) } ?: JKLabelEmpty(),
type.toJK()
)
is PsiConditionalExpression -> JKIfElseExpression(
condition.toJK(), thenExpression.toJK(), elseExpression.toJK()
condition.toJK(),
thenExpression.toJK(),
elseExpression.toJK(),
type.toJK()
)
is PsiPolyadicExpression -> {
val token = JKOperatorToken.fromElementType(operationTokenType)
@@ -175,7 +182,7 @@ class JavaToJKTreeBuilder constructor(
}
fun PsiInstanceOfExpression.toJK(): JKIsExpression =
JKIsExpression(operand.toJK(), JKTypeElement(checkType?.type?.toJK() ?: JKNoTypeImpl))
JKIsExpression(operand.toJK(), JKTypeElement(checkType?.type?.toJK() ?: JKNoType))
.also {
it.assignNonCodeElements(this)
}
@@ -293,8 +300,8 @@ class JavaToJKTreeBuilder constructor(
return when {
methodExpression.referenceNameElement is PsiKeyword -> {
val callee = when ((methodExpression.referenceNameElement as PsiKeyword).tokenType) {
SUPER_KEYWORD -> JKSuperExpression()
THIS_KEYWORD -> JKThisExpression(JKLabelEmpty())
SUPER_KEYWORD -> JKSuperExpression(JKLabelEmpty(), JKNoType)
THIS_KEYWORD -> JKThisExpression(JKLabelEmpty(), JKNoType)
else -> throwCanNotConvertError("unknown keyword in callee position")
}
JKDelegationConstructorCall(symbol as JKMethodSymbol, callee, arguments.toJK())
@@ -337,7 +344,7 @@ class JavaToJKTreeBuilder constructor(
propertyAccessExpression
)
else propertyAccessExpression
} else propertyAccessExpression.qualified(qualifier) as JKExpression
} else propertyAccessExpression.qualified(qualifier)
when (if (isExtension) parameterCount - 1 else parameterCount) {
0 /* getter */ ->
@@ -383,7 +390,7 @@ class JavaToJKTreeBuilder constructor(
}?.takeUnless { type ->
type.isKotlinFunctionalType
}?.toJK()
?.asTypeElement() ?: JKTypeElement(JKNoTypeImpl)
?.asTypeElement() ?: JKTypeElement(JKNoType)
fun PsiMethodReferenceExpression.toJK(): JKMethodReferenceExpression {
val symbol = symbolProvider.provideSymbolForReference<JKSymbol>(this).let { symbol ->
@@ -494,14 +501,15 @@ class JavaToJKTreeBuilder constructor(
}
fun PsiArrayAccessExpression.toJK(): JKExpression {
return JKArrayAccessExpression(
arrayExpression.toJK(),
indexExpression?.toJK() ?: throwCanNotConvertError()
).also {
it.assignNonCodeElements(this)
}
}
fun PsiArrayAccessExpression.toJK(): JKExpression =
arrayExpression.toJK()
.callOn(
symbolProvider.provideMethodSymbol("kotlin.Array.get"),
arguments = listOf(indexExpression?.toJK() ?: JKStubExpression())
).also {
it.assignNonCodeElements(this)
}
fun PsiTypeCastExpression.toJK(): JKExpression {
return JKTypeCastExpression(
@@ -622,7 +630,7 @@ class JavaToJKTreeBuilder constructor(
with(expressionTreeMapper) { argumentList?.toJK() ?: JKArgumentList() },
initializingClass?.createClassBody() ?: JKClassBody(),
JKTypeElement(
JKClassTypeImpl(
JKClassType(
symbolProvider.provideDirectSymbol(containingClass ?: throwCanNotConvertError()) as JKClassSymbol,
emptyList()
)
@@ -784,7 +792,6 @@ class JavaToJKTreeBuilder constructor(
).also {
symbolProvider.provideUniverseSymbol(this, it)
it.psi = this
}.also {
it.assignNonCodeElements(this)
}
}

View File

@@ -904,7 +904,7 @@ private class JKPrinter(
}
fun renderType(type: JKType, owner: JKTreeElement?) {
if (type is JKNoTypeImpl) return
if (type is JKNoType) return
if (type is JKCapturedType) {
when (val wildcard = type.wildcardType) {
is JKVarianceTypeParameterType -> {

View File

@@ -75,13 +75,13 @@ class ArrayInitializerConversion(context: NewJ2kConverterContext) : RecursiveApp
JKTypeArgumentList(listOf(JKTypeElement(arrayType)))
)
}
var resultType = JKClassTypeImpl(
var resultType = JKClassType(
symbolProvider.provideClassSymbol(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type),
Nullability.Default
)
for (i in 0 until dimensions.size - 2) {
resultType = JKClassTypeImpl(
resultType = JKClassType(
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()),
listOf(resultType),
Nullability.Default

View File

@@ -13,9 +13,7 @@ package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseFieldSymbol
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.nj2k.types.type
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -34,7 +32,7 @@ class ArrayOperationsConversion(context: NewJ2kConverterContext) : RecursiveAppl
}
private fun JKExpression.isArrayOrVarargTypeParameter(): Boolean {
if (type(typeFactory) is JKJavaArrayType) return true
if (calculateType(typeFactory) is JKJavaArrayType) return true
val parameter =
safeAs<JKFieldAccessExpression>()
?.identifier

View File

@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.nj2k.symbols.deepestFqName
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.isArrayType
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.safeAs
@@ -268,7 +267,7 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
Method("java.lang.String.indexOf") convertTo Method("kotlin.text.indexOf"),
Method("java.lang.String.lastIndexOf") convertTo Method("kotlin.text.lastIndexOf"),
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 ->
val argument = arguments.arguments.single()::value.detached()
val call = JKCallExpressionImpl(
@@ -281,7 +280,7 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
Method("java.lang.String.valueOf")
convertTo ExtensionMethod("kotlin.Any.toString")
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")
convertTo Method("kotlin.text.toCharArray")
@@ -297,12 +296,12 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
Method("java.lang.String.valueOf")
convertTo Method("kotlin.String")
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")
convertTo Method("kotlin.String")
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")
convertTo Method("kotlin.text.replace")

View File

@@ -16,8 +16,7 @@ import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl
import org.jetbrains.kotlin.nj2k.types.type
import org.jetbrains.kotlin.nj2k.types.JKNoType
import kotlin.math.abs
@@ -136,11 +135,11 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
KtTokens.EXCLEQ -> false
else -> return null
}
val range = forIterationRange(start, right, reversed, inclusive, loopVarPsi)
val range = forIterationRange(start, right, reversed, inclusive)
val explicitType =
if (context.converter.settings.specifyLocalVariableTypeByDefault)
JKJavaPrimitiveType.INT
else JKNoTypeImpl
else JKNoType
val loopVarDeclaration =
JKForLoopVariable(
JKTypeElement(explicitType),
@@ -169,8 +168,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
start: JKExpression,
bound: JKExpression,
reversed: Boolean,
inclusiveComparison: Boolean,
psiContext: PsiElement
inclusiveComparison: Boolean
): JKExpression {
indicesIterationRange(start, bound, reversed, inclusiveComparison)?.also { return it }
return when {
@@ -262,7 +260,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
private fun indicesByArrayLength(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? {
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) {
return toIndicesCall(javaSizeCall)
}

View File

@@ -149,6 +149,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
)
}
private fun JKExpression.castTo(toType: JKType, strict: Boolean = false): JKExpression? {
val expressionType = calculateType(typeFactory)
if (expressionType == toType) return null

View File

@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedClassSymbol
import org.jetbrains.kotlin.nj2k.tree.*
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.updateNullability
@@ -36,7 +35,7 @@ class JavaStandardMethodsConversion(context: NewJ2kConverterContext) : Recursive
if (hasNoCloneableInSuperClasses) {
element.inheritance.implements +=
JKTypeElement(
JKClassTypeImpl(
JKClassType(
JKUnresolvedClassSymbol("Cloneable", typeFactory),
emptyList(), Nullability.NotNull
)

View File

@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.lang.jvm.JvmModifier
import com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.codegen.kotlinType
import org.jetbrains.kotlin.idea.caches.resolve.analyze
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.tree.*
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.safeAs
@@ -37,7 +39,7 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
?.let { classAccessExpression ->
JKParameter(
JKTypeElement(
parametersTypesByFunctionalInterface?.firstOrNull() ?: JKClassTypeImpl(classAccessExpression.identifier)
parametersTypesByFunctionalInterface?.firstOrNull() ?: JKClassType(classAccessExpression.identifier)
),
JKNameIdentifier(RECEIVER_NAME),
isVarArgs = false
@@ -90,8 +92,8 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
element::functionalType.detached(),
JKTypeElement(
when (symbol) {
is JKMethodSymbol -> symbol.returnType ?: JKNoTypeImpl
is JKClassSymbol -> JKClassTypeImpl(symbol)
is JKMethodSymbol -> symbol.returnType ?: JKNoType
is JKClassSymbol -> JKClassType(symbol)
is JKUnresolvedSymbol -> return recurse(element)
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 {
private const val RECEIVER_NAME = "obj" //name taken from old j2k
}

View File

@@ -9,15 +9,14 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.callOn
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.isStringType
import org.jetbrains.kotlin.nj2k.types.type
class AnyWithStringConcatenationConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKBinaryExpression) return recurse(element)
if (element.operator.token == JKOperatorToken.PLUS
&& element.right.type(typeFactory)?.isStringType() == true
&& element.left.type(typeFactory)?.isStringType() == false
&& element.right.calculateType(typeFactory).isStringType()
&& !element.left.calculateType(typeFactory).isStringType()
) {
return recurse(
JKBinaryExpression(

View File

@@ -20,7 +20,7 @@ class ParameterModificationInMethodCallsConversion(context: NewJ2kConverterConte
if (parameter.hasWritableUsages(element.block, context)) {
val parameterType =
if (parameter.isVarArgs) {
JKClassTypeImpl(
JKClassType(
symbolProvider.provideClassSymbol(parameter.type.type.arrayFqName()),
if (parameter.type.type is JKJavaPrimitiveType) emptyList()
else listOf(

View File

@@ -74,7 +74,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
is JKJavaVoidType -> typeFactory.types.unit
is JKJavaArrayType ->
JKClassTypeImpl(
JKClassType(
symbolProvider.provideClassSymbol(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type.mapType(typeElement)),
nullability
@@ -102,7 +102,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
}
private fun JKClassType.mapClassType(): JKClassType =
JKClassTypeImpl(
JKClassType(
classReference.mapClassSymbol(),
parameters.map { it.mapType(null) },
nullability
@@ -123,7 +123,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
if (this is JKClassType && parameters.isEmpty()) {
val parametersCount = classReference.expectedTypeParametersCount()
val typeParameters = List(parametersCount) { typeParameter }
JKClassTypeImpl(
JKClassType(
classReference,
typeParameters,
nullability

View File

@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.nj2k.conversions.RecursiveApplicableConversionBase
import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedMethod
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKNoType
import org.jetbrains.kotlin.nj2k.types.JKType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory

View File

@@ -7,13 +7,9 @@ package org.jetbrains.kotlin.nj2k.symbols
import com.intellij.psi.PsiVariable
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.tree.JKVariable
import org.jetbrains.kotlin.nj2k.types.toJK
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.nj2k.types.*
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.psiUtil.containingClass
@@ -22,7 +18,7 @@ sealed class JKFieldSymbol : JKSymbol {
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
get() = target.type.type
@@ -50,7 +46,7 @@ class JKMultiverseKtEnumEntrySymbol(
override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> {
override val fieldType: JKType?
get() = JKClassTypeImpl(
get() = JKClassType(
symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol,
emptyList(),
Nullability.NotNull
@@ -62,6 +58,6 @@ class JKUnresolvedField(
override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKUnresolvedSymbol {
override val fieldType: JKType
get() = JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()), emptyList())
get() = typeFactory.types.nullableAny
}

View File

@@ -16,8 +16,8 @@ import org.jetbrains.kotlin.nj2k.tree.JKClass
import org.jetbrains.kotlin.nj2k.tree.JKMethod
import org.jetbrains.kotlin.nj2k.types.asType
import org.jetbrains.kotlin.nj2k.types.toJK
import org.jetbrains.kotlin.nj2k.types.JKClassTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKNoType
import org.jetbrains.kotlin.nj2k.types.JKType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtFunction
@@ -32,7 +32,7 @@ sealed class JKMethodSymbol : JKSymbol {
class JKUniverseMethodSymbol(override val typeFactory: JKTypeFactory) : JKMethodSymbol(), JKUniverseSymbol<JKMethod> {
override val receiverType: JKType?
get() = target.parent.safeAs<JKClass>()?.let {
JKClassTypeImpl(symbolProvider.provideUniverseSymbol(it), emptyList()/*TODO*/)
JKClassType(symbolProvider.provideUniverseSymbol(it), emptyList())
}
override val parameterTypes: List<JKType>
get() = target.parameters.map { it.type.type }
@@ -48,7 +48,7 @@ class JKMultiverseMethodSymbol(
) : JKMethodSymbol(), JKMultiverseSymbol<PsiMethod> {
override val receiverType: JKType?
get() = target.containingClass?.let {
JKClassTypeImpl(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList()/*TODO*/)
JKClassType(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList())
}
override val parameterTypes: List<JKType>
get() = target.parameterList.parameters.map { typeFactory.fromPsiType(it.type) }
@@ -76,7 +76,7 @@ class JKMultiverseFunctionSymbol(
val type = parameter.typeReference?.toJK(typeFactory)
type?.let {
if (parameter.isVarArg) {
JKClassTypeImpl(
JKClassType(
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()),
listOf(it)
)
@@ -91,12 +91,12 @@ class JKMultiverseFunctionSymbol(
class JKUnresolvedMethod(
override val target: String,
override val typeFactory: JKTypeFactory,
override val returnType: JKType = JKNoTypeImpl
override val returnType: JKType = JKNoType
) : JKMethodSymbol(), JKUnresolvedSymbol {
constructor(target: PsiReference, typeFactory: JKTypeFactory) : this(target.canonicalText, typeFactory)
override val receiverType: JKType?
get() = null
get() = typeFactory.types.nullableAny
override val parameterTypes: List<JKType>
get() = emptyList()
}

View File

@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.nj2k.tree
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 val name: JKNameIdentifier
@@ -168,15 +168,13 @@ class JKConstructorImpl(
visibilityElement: JKVisibilityModifierElement,
modalityElement: JKModalityModifierElement
) : 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 parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(block)
override var delegationCall: JKExpression by child(delegationCall)
override var typeParameterList: JKTypeParameterList by child(JKTypeParameterList())
override var annotationList: JKAnnotationList by child(annotationList)
override var otherModifierElements by children(otherModifierElements)
override var visibilityElement by child(visibilityElement)
override var modalityElement by child(modalityElement)
@@ -194,8 +192,7 @@ class JKKtPrimaryConstructor(
visibilityElement: JKVisibilityModifierElement,
modalityElement: JKModalityModifierElement
) : 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 parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(JKBodyStub)

View File

@@ -9,14 +9,16 @@ import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.nj2k.types.JKContextType
import org.jetbrains.kotlin.nj2k.types.JKNoTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKType
import org.jetbrains.kotlin.nj2k.types.*
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 var operator: JKOperator
override fun calculateType(typeFactory: JKTypeFactory) = operator.returnType
}
class JKBinaryExpression(
@@ -50,31 +52,20 @@ class JKQualifiedExpression(
) : JKExpression() {
var receiver: JKExpression by child(receiver)
var selector: JKExpression by child(selector)
override fun calculateType(typeFactory: JKTypeFactory) = selector.calculateType(typeFactory)
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() {
var expression: JKExpression by child(expression)
override fun calculateType(typeFactory: JKTypeFactory) = expression.calculateType(typeFactory)
override fun accept(visitor: JKVisitor) = visitor.visitParenthesizedExpression(this)
}
class JKTypeCastExpression(expression: JKExpression, type: JKTypeElement) : JKExpression() {
var expression by child(expression)
var type by child(type)
override fun calculateType(typeFactory: JKTypeFactory) = type.type
override fun accept(visitor: JKVisitor) = visitor.visitTypeCastExpression(this)
}
@@ -84,38 +75,57 @@ class JKLiteralExpression(
) : JKExpression() {
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 {
STRING, CHAR, BOOLEAN, NULL, INT, LONG, FLOAT, DOUBLE
}
}
class JKStubExpression : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
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)
override fun calculateType(typeFactory: JKTypeFactory) = type
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)
override fun calculateType(typeFactory: JKTypeFactory) = type
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 thenBranch by child(thenBranch)
var elseBranch by child(elseBranch)
override fun calculateType(typeFactory: JKTypeFactory): JKType = type
override fun accept(visitor: JKVisitor) = visitor.visitIfElseExpression(this)
}
class JKLambdaExpression(
statement: JKStatement,
parameters: List<JKParameter>,
functionalType: JKTypeElement = JKTypeElement(JKNoTypeImpl),
functionalType: JKTypeElement = JKTypeElement(JKNoType),
returnType: JKTypeElement = JKTypeElement(JKContextType)
) : JKExpression() {
var statement by child(statement)
@@ -123,6 +133,7 @@ class JKLambdaExpression(
var functionalType by child(functionalType)
val returnType by child(returnType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitLambdaExpression(this)
}
@@ -130,6 +141,7 @@ class JKLambdaExpression(
abstract class JKCallExpression : JKExpression(), JKTypeArgumentListOwner {
abstract val identifier: JKMethodSymbol
abstract var arguments: JKArgumentList
override fun calculateType(typeFactory: JKTypeFactory): JKType = identifier.returnType ?: JKNoType
}
class JKDelegationConstructorCall(
@@ -140,7 +152,6 @@ class JKDelegationConstructorCall(
override var typeArgumentList: JKTypeArgumentList by child(JKTypeArgumentList())
val expression: JKExpression by child(expression)
override var arguments: JKArgumentList by child(arguments)
override fun accept(visitor: JKVisitor) = visitor.visitDelegationConstructorCall(this)
}
@@ -164,20 +175,24 @@ class JKNewExpression(
var typeArgumentList by child(typeArgumentList)
var arguments by child(arguments)
var classBody by child(classBody)
override fun calculateType(typeFactory: JKTypeFactory) = classSymbol.asType()
override fun accept(visitor: JKVisitor) = visitor.visitNewExpression(this)
}
class JKFieldAccessExpression(var identifier: JKFieldSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = identifier.fieldType ?: JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitFieldAccessExpression(this)
}
class JKPackageAccessExpression(var identifier: JKPackageSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitPackageAccessExpression(this)
}
class JKClassAccessExpression(var identifier: JKClassSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitClassAccessExpression(this)
}
@@ -189,7 +204,7 @@ class JKMethodReferenceExpression(
) : JKExpression() {
val qualifier by child(qualifier)
val functionalType by child(functionalType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitMethodReferenceExpression(this)
}
@@ -197,6 +212,7 @@ class JKMethodReferenceExpression(
class JKLabeledExpression(statement: JKStatement, labels: List<JKNameIdentifier>) : JKExpression() {
var statement: JKStatement by child(statement)
val labels: List<JKNameIdentifier> by children(labels)
override fun calculateType(typeFactory: JKTypeFactory) = typeFactory.types.unit
override fun accept(visitor: JKVisitor) = visitor.visitLabeledExpression(this)
}
@@ -205,6 +221,10 @@ class JKClassLiteralExpression(
var literalType: ClassLiteralType
) : JKExpression() {
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)
@@ -221,6 +241,7 @@ abstract class JKKtAssignmentChainLink : JKExpression() {
abstract val receiver: JKExpression
abstract val assignmentStatement: JKKtAssignmentStatement
abstract val field: JKExpression
override fun calculateType(typeFactory: JKTypeFactory) = field.calculateType(typeFactory)
}
class JKAssignmentChainAlsoLink(
@@ -231,7 +252,6 @@ class JKAssignmentChainAlsoLink(
override val receiver by child(receiver)
override val assignmentStatement by child(assignmentStatement)
override val field by child(field)
override fun accept(visitor: JKVisitor) = visitor.visitAssignmentChainAlsoLink(this)
}
@@ -243,7 +263,6 @@ class JKAssignmentChainLetLink(
override val receiver by child(receiver)
override val assignmentStatement by child(assignmentStatement)
override val field by child(field)
override fun accept(visitor: JKVisitor) = visitor.visitAssignmentChainLetLink(this)
}
@@ -251,16 +270,18 @@ class JKAssignmentChainLetLink(
class JKIsExpression(expression: JKExpression, type: JKTypeElement) : JKExpression() {
var type by child(type)
var expression by child(expression)
override fun calculateType(typeFactory: JKTypeFactory) = typeFactory.types.boolean
override fun accept(visitor: JKVisitor) = visitor.visitIsExpression(this)
}
class JKKtThrowExpression(exception: JKExpression) : JKExpression() {
var exception: JKExpression by child(exception)
override fun calculateType(typeFactory: JKTypeFactory) = typeFactory.types.nothing
override fun accept(visitor: JKVisitor) = visitor.visitKtThrowExpression(this)
}
class JKKtItExpression(val type: JKType) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = type
override fun accept(visitor: JKVisitor) = visitor.visitKtItExpression(this)
}
@@ -268,6 +289,7 @@ class JKKtAnnotationArrayInitializerExpression(initializers: List<JKAnnotationMe
constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList())
val initializers: List<JKAnnotationMemberValue> by children(initializers)
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun accept(visitor: JKVisitor) = visitor.visitKtAnnotationArrayInitializerExpression(this)
}
@@ -279,27 +301,23 @@ class JKKtTryExpression(
var tryBlock: JKBlock by child(tryBlock)
var finallyBlock: JKBlock by child(finallyBlock)
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(
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)
override fun accept(visitor: JKVisitor) = visitor.visitKtTryExpression(this)
}
class JKJavaNewEmptyArray(initializer: List<JKExpression>, type: JKTypeElement) : JKExpression() {
val type by child(type)
var initializer by children(initializer)
override fun calculateType(typeFactory: JKTypeFactory) = type.type
override fun accept(visitor: JKVisitor) = visitor.visitJavaNewEmptyArray(this)
}
class JKJavaNewArray(initializer: List<JKExpression>, type: JKTypeElement) : JKExpression() {
val type by child(type)
var initializer by children(initializer)
override fun calculateType(typeFactory: JKTypeFactory) = type.type
override fun accept(visitor: JKVisitor) = visitor.visitJavaNewArray(this)
}
@@ -311,5 +329,6 @@ class JKJavaAssignmentExpression(
) : JKExpression() {
var field by child(field)
var expression by child(expression)
override fun calculateType(typeFactory: JKTypeFactory) = field.calculateType(typeFactory)
override fun accept(visitor: JKVisitor) = visitor.visitJavaAssignmentExpression(this)
}

View File

@@ -51,6 +51,9 @@ class JKTypeFactory(val symbolProvider: JKSymbolProvider) {
val unit = typeByFqName(KotlinBuiltIns.FQ_NAMES.unit)
val nothing = typeByFqName(KotlinBuiltIns.FQ_NAMES.nothing)
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) {

View File

@@ -16,31 +16,24 @@ interface JKType {
interface JKWildCardType : JKType
interface JKNoType : JKType
interface JKParametrizedType : JKType {
val parameters: List<JKType>
}
interface JKClassType : JKParametrizedType {
val classReference: JKClassSymbol
override val nullability: Nullability
}
interface JKStarProjectionType : JKWildCardType {
override val nullability: Nullability
get() = Nullability.NotNull
}
object JKNoTypeImpl : JKNoType {
object JKNoType : JKType {
override val nullability: Nullability = Nullability.NotNull
}
data class JKClassTypeImpl(
override val classReference: JKClassSymbol,
data class JKClassType(
val classReference: JKClassSymbol,
override val parameters: List<JKType> = emptyList(),
override val nullability: Nullability = Nullability.Default
) : JKClassType
) : JKParametrizedType
object JKStarProjectionTypeImpl : JKStarProjectionType

View File

@@ -16,9 +16,7 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.toJkType
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtTypeReference
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.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() =
JKTypeElement(this)
fun JKClassSymbol.asType(nullability: Nullability = Nullability.Default): JKClassType =
JKClassTypeImpl(this, emptyList(), nullability)
JKClassType(this, emptyList(), nullability)
val PsiType.isKotlinFunctionalType: Boolean
get() {
@@ -112,8 +64,8 @@ private val jvmPrimitiveTypesPriority =
fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType =
transform(this) ?: when (this) {
is JKTypeParameterType -> this
is JKClassTypeImpl ->
JKClassTypeImpl(
is JKClassType ->
JKClassType(
classReference,
parameters.map { it.applyRecursive(transform) },
nullability
@@ -133,7 +85,7 @@ inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability)
if (nullability == newNullability) this
else when (this) {
is JKTypeParameterType -> JKTypeParameterType(identifier, newNullability)
is JKClassTypeImpl -> JKClassTypeImpl(classReference, parameters, newNullability)
is JKClassType -> JKClassType(classReference, parameters, newNullability)
is JKNoType -> this
is JKJavaVoidType -> this
is JKJavaPrimitiveType -> this
@@ -148,8 +100,8 @@ fun <T : JKType> T.updateNullabilityRecursively(newNullability: Nullability): T
applyRecursive {
when (it) {
is JKTypeParameterType -> JKTypeParameterType(it.identifier, newNullability)
is JKClassTypeImpl ->
JKClassTypeImpl(
is JKClassType ->
JKClassType(
it.classReference,
it.parameters.map { it.updateNullabilityRecursively(newNullability) },
newNullability
@@ -271,7 +223,7 @@ fun JKType.isInterface(): Boolean =
fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType =
applyRecursive { type ->
if (type is JKClassType && type.classReference.fqName == "java.lang.Class") {
JKClassTypeImpl(
JKClassType(
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()),
type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) },
Nullability.NotNull