New J2K: introduce TypeFactory for creating J2K types

This commit is contained in:
Ilya Kirillov
2019-09-03 16:37:53 +03:00
parent 047bb07727
commit c93d810685
38 changed files with 426 additions and 353 deletions
@@ -6,12 +6,17 @@
package org.jetbrains.kotlin.nj2k package org.jetbrains.kotlin.nj2k
import org.jetbrains.kotlin.nj2k.tree.JKTreeElement import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
interface Conversion { interface Conversion {
val context: NewJ2kConverterContext val context: NewJ2kConverterContext
val symbolProvider
val symbolProvider: JKSymbolProvider
get() = context.symbolProvider get() = context.symbolProvider
val typeFactory: JKTypeFactory
get() = context.typeFactory
fun runConversion(treeRoots: List<JKTreeElement>, context: NewJ2kConverterContext): Boolean fun runConversion(treeRoots: List<JKTreeElement>, context: NewJ2kConverterContext): Boolean
} }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.nj2k.conversions.JKResolver import org.jetbrains.kotlin.nj2k.conversions.JKResolver
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.JKTypeFactory
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -24,6 +25,7 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
private val resolver = JKResolver(project, module, contextElement) private val resolver = JKResolver(project, module, contextElement)
private val elementVisitor = ElementVisitor() private val elementVisitor = ElementVisitor()
lateinit var typeFactory: JKTypeFactory
fun preBuildTree(inputElements: List<PsiElement>) { fun preBuildTree(inputElements: List<PsiElement>) {
inputElements.forEach { it.accept(elementVisitor) } inputElements.forEach { it.accept(elementVisitor) }
@@ -31,19 +33,19 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
private fun symbolForNonKotlinElement(psi: PsiElement) = private fun symbolForNonKotlinElement(psi: PsiElement) =
when (psi) { when (psi) {
is PsiTypeParameter -> JKMultiverseTypeParameterSymbol(psi, this) is PsiTypeParameter -> JKMultiverseTypeParameterSymbol(psi, typeFactory)
is KtTypeParameter -> JKMultiverseKtTypeParameterSymbol(psi, this) is KtTypeParameter -> JKMultiverseKtTypeParameterSymbol(psi, typeFactory)
is KtEnumEntry -> JKMultiverseKtEnumEntrySymbol(psi, this) is KtEnumEntry -> JKMultiverseKtEnumEntrySymbol(psi, typeFactory)
is PsiClass -> JKMultiverseClassSymbol(psi, this) is PsiClass -> JKMultiverseClassSymbol(psi, typeFactory)
is KtClassOrObject -> JKMultiverseKtClassSymbol(psi, this) is KtClassOrObject -> JKMultiverseKtClassSymbol(psi, typeFactory)
is PsiMethod -> JKMultiverseMethodSymbol(psi, this) is PsiMethod -> JKMultiverseMethodSymbol(psi, typeFactory)
is PsiField -> JKMultiverseFieldSymbol(psi, this) is PsiField -> JKMultiverseFieldSymbol(psi, typeFactory)
is KtFunction -> JKMultiverseFunctionSymbol(psi, this) is KtFunction -> JKMultiverseFunctionSymbol(psi, typeFactory)
is KtProperty -> JKMultiversePropertySymbol(psi, this) is KtProperty -> JKMultiversePropertySymbol(psi, typeFactory)
is KtParameter -> JKMultiversePropertySymbol(psi, this) is KtParameter -> JKMultiversePropertySymbol(psi, typeFactory)
is PsiParameter -> JKMultiverseFieldSymbol(psi, this) is PsiParameter -> JKMultiverseFieldSymbol(psi, typeFactory)
is PsiLocalVariable -> JKMultiverseFieldSymbol(psi, this) is PsiLocalVariable -> JKMultiverseFieldSymbol(psi, typeFactory)
is PsiPackage -> JKMultiversePackageSymbol(psi, this) is PsiPackage -> JKMultiversePackageSymbol(psi, typeFactory)
else -> TODO(psi::class.toString()) else -> TODO(psi::class.toString())
} }
@@ -62,8 +64,8 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
if (target != null) return provideDirectSymbol(target) as T if (target != null) return provideDirectSymbol(target) as T
return (if (isAssignable<T, JKUnresolvedField>()) JKUnresolvedField( return (if (isAssignable<T, JKUnresolvedField>()) JKUnresolvedField(
reference.canonicalText, reference.canonicalText,
this typeFactory
) else JKUnresolvedMethod(reference)) as T ) else JKUnresolvedMethod(reference, typeFactory)) as T
} }
fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also { fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also {
@@ -79,10 +81,10 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
fun provideUniverseSymbol(psi: PsiElement): JKSymbol = fun provideUniverseSymbol(psi: PsiElement): JKSymbol =
symbolsByPsi.getOrPut(psi) { symbolsByPsi.getOrPut(psi) {
when (psi) { when (psi) {
is PsiVariable -> JKUniverseFieldSymbol(this) is PsiVariable -> JKUniverseFieldSymbol(typeFactory)
is PsiMethod -> JKUniverseMethodSymbol(this) is PsiMethod -> JKUniverseMethodSymbol(typeFactory)
is PsiTypeParameter -> JKUniverseTypeParameterSymbol(this) is PsiTypeParameter -> JKUniverseTypeParameterSymbol(typeFactory)
is PsiClass -> JKUniverseClassSymbol(this) is PsiClass -> JKUniverseClassSymbol(typeFactory)
else -> TODO() else -> TODO()
} }
} }
@@ -95,15 +97,15 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
} }
fun provideUniverseSymbol(jk: JKClass): JKClassSymbol = symbolsByJK.getOrPut(jk) { fun provideUniverseSymbol(jk: JKClass): JKClassSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseClassSymbol(this).also { it.target = jk } JKUniverseClassSymbol(typeFactory).also { it.target = jk }
} as JKClassSymbol } as JKClassSymbol
fun provideUniverseSymbol(jk: JKVariable): JKFieldSymbol = symbolsByJK.getOrPut(jk) { fun provideUniverseSymbol(jk: JKVariable): JKFieldSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseFieldSymbol(this).also { it.target = jk } JKUniverseFieldSymbol(typeFactory).also { it.target = jk }
} as JKFieldSymbol } as JKFieldSymbol
fun provideUniverseSymbol(jk: JKMethod): JKMethodSymbol = symbolsByJK.getOrPut(jk) { fun provideUniverseSymbol(jk: JKMethod): JKMethodSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseMethodSymbol(this).also { it.target = jk } JKUniverseMethodSymbol(typeFactory).also { it.target = jk }
} as JKMethodSymbol } as JKMethodSymbol
@@ -112,7 +114,7 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
resolver.resolveClass(fqName)?.let { resolver.resolveClass(fqName)?.let {
provideDirectSymbol(it) as? JKClassSymbol provideDirectSymbol(it) as? JKClassSymbol
} }
} as? JKClassSymbol ?: JKUnresolvedClassSymbol(fqName.asString()) } as? JKClassSymbol ?: JKUnresolvedClassSymbol(fqName.asString(), typeFactory)
fun provideClassSymbol(fqName: String): JKClassSymbol = fun provideClassSymbol(fqName: String): JKClassSymbol =
provideClassSymbol(FqName(fqName.asSafeFqNameString())) provideClassSymbol(FqName(fqName.asSafeFqNameString()))
@@ -125,7 +127,7 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
resolver.resolveMethod(fqName)?.let { resolver.resolveMethod(fqName)?.let {
provideDirectSymbol(it) as? JKMethodSymbol provideDirectSymbol(it) as? JKMethodSymbol
} }
} as? JKMethodSymbol ?: JKUnresolvedMethod(fqName.asString()) } as? JKMethodSymbol ?: JKUnresolvedMethod(fqName.asString(), typeFactory)
fun provideMethodSymbol(fqName: String): JKMethodSymbol = fun provideMethodSymbol(fqName: String): JKMethodSymbol =
provideMethodSymbol(FqName(fqName.asSafeFqNameString())) provideMethodSymbol(FqName(fqName.asSafeFqNameString()))
@@ -135,7 +137,7 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem
resolver.resolveField(fqName)?.let { resolver.resolveField(fqName)?.let {
provideDirectSymbol(it) as? JKFieldSymbol provideDirectSymbol(it) as? JKFieldSymbol
} }
} as? JKFieldSymbol ?: JKUnresolvedField(fqName.asString(), this) } as? JKFieldSymbol ?: JKUnresolvedField(fqName.asString(), typeFactory)
fun provideFieldSymbol(fqName: String): JKFieldSymbol = fun provideFieldSymbol(fqName: String): JKFieldSymbol =
provideFieldSymbol(FqName(fqName.asSafeFqNameString())) provideFieldSymbol(FqName(fqName.asSafeFqNameString()))
@@ -45,6 +45,9 @@ import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.* import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
@@ -53,10 +56,13 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JavaToJKTreeBuilder constructor( class JavaToJKTreeBuilder constructor(
var symbolProvider: JKSymbolProvider, private val symbolProvider: JKSymbolProvider,
private val typeFactory: JKTypeFactory,
converterServices: NewJavaToKotlinServices, converterServices: NewJavaToKotlinServices,
private val importStorage: ImportStorage private val importStorage: ImportStorage
) { ) {
private fun PsiType.toJK() =
typeFactory.fromPsiType(this)
private val expressionTreeMapper = ExpressionTreeMapper() private val expressionTreeMapper = ExpressionTreeMapper()
@@ -153,7 +159,7 @@ class JavaToJKTreeBuilder constructor(
} }
fun PsiClassObjectAccessExpressionImpl.toJK(): JKClassLiteralExpression { fun PsiClassObjectAccessExpressionImpl.toJK(): JKClassLiteralExpression {
val type = operand.type.toJK(symbolProvider).updateNullabilityRecursively(Nullability.NotNull) val type = operand.type.toJK().updateNullabilityRecursively(Nullability.NotNull)
return JKClassLiteralExpressionImpl( return JKClassLiteralExpressionImpl(
JKTypeElementImpl(type), JKTypeElementImpl(type),
when (type) { when (type) {
@@ -167,7 +173,7 @@ class JavaToJKTreeBuilder constructor(
} }
fun PsiInstanceOfExpression.toJK(): JKKtIsExpression = fun PsiInstanceOfExpression.toJK(): JKKtIsExpression =
JKKtIsExpressionImpl(operand.toJK(), JKTypeElementImpl(checkType?.type?.toJK(symbolProvider) ?: JKNoTypeImpl)) JKKtIsExpressionImpl(operand.toJK(), JKTypeElementImpl(checkType?.type?.toJK() ?: JKNoTypeImpl))
.also { .also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -270,7 +276,7 @@ class JavaToJKTreeBuilder constructor(
val target = methodExpression.resolve() val target = methodExpression.resolve()
val symbol = target?.let { val symbol = target?.let {
symbolProvider.provideDirectSymbol(it) symbolProvider.provideDirectSymbol(it)
} ?: JKUnresolvedMethod(methodExpression) } ?: JKUnresolvedMethod(methodExpression, typeFactory)
return when { return when {
methodExpression.referenceNameElement is PsiKeyword -> { methodExpression.referenceNameElement is PsiKeyword -> {
@@ -340,7 +346,7 @@ class JavaToJKTreeBuilder constructor(
else -> { else -> {
JKJavaMethodCallExpressionImpl( JKJavaMethodCallExpressionImpl(
JKMultiverseMethodSymbol(target, symbolProvider), JKMultiverseMethodSymbol(target, typeFactory),
arguments.toJK(), arguments.toJK(),
typeArguments typeArguments
).qualified(qualifier) ).qualified(qualifier)
@@ -365,14 +371,14 @@ class JavaToJKTreeBuilder constructor(
type.safeAs<PsiClassType>()?.parameters?.any { it is PsiCapturedWildcardType } == true type.safeAs<PsiClassType>()?.parameters?.any { it is PsiCapturedWildcardType } == true
}?.takeUnless { type -> }?.takeUnless { type ->
type.isKotlinFunctionalType type.isKotlinFunctionalType
}?.toJK(symbolProvider) }?.toJK()
?.asTypeElement() ?: JKTypeElementImpl(JKNoTypeImpl) ?.asTypeElement() ?: JKTypeElementImpl(JKNoTypeImpl)
fun PsiMethodReferenceExpression.toJK(): JKMethodReferenceExpression { fun PsiMethodReferenceExpression.toJK(): JKMethodReferenceExpression {
val symbol = symbolProvider.provideSymbolForReference<JKSymbol>(this).let { symbol -> val symbol = symbolProvider.provideSymbolForReference<JKSymbol>(this).let { symbol ->
when { when {
symbol.isUnresolved && isConstructor -> JKUnresolvedClassSymbol(qualifier?.text ?: text) symbol.isUnresolved && isConstructor -> JKUnresolvedClassSymbol(qualifier?.text ?: text, typeFactory)
symbol.isUnresolved && !isConstructor -> JKUnresolvedMethod(referenceName ?: text) symbol.isUnresolved && !isConstructor -> JKUnresolvedMethod(referenceName ?: text, typeFactory)
else -> symbol else -> symbol
} }
} }
@@ -412,7 +418,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiArrayInitializerExpression.toJK(): JKExpression { fun PsiArrayInitializerExpression.toJK(): JKExpression {
return JKJavaNewArrayImpl( return JKJavaNewArrayImpl(
initializers.map { it.toJK() }, initializers.map { it.toJK() },
JKTypeElementImpl(type?.toJK(symbolProvider).safeAs<JKJavaArrayType>()?.type ?: JKContextType) JKTypeElementImpl(type?.toJK().safeAs<JKJavaArrayType>()?.type ?: JKContextType)
).also { ).also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -438,7 +444,7 @@ class JavaToJKTreeBuilder constructor(
} }
JKJavaNewEmptyArrayImpl( JKJavaNewEmptyArrayImpl(
dimensions.map { it?.toJK() ?: JKStubExpressionImpl() }, dimensions.map { it?.toJK() ?: JKStubExpressionImpl() },
JKTypeElementImpl(generateSequence(type?.toJK(symbolProvider)) { it.safeAs<JKJavaArrayType>()?.type }.last()) JKTypeElementImpl(generateSequence(type?.toJK()) { it.safeAs<JKJavaArrayType>()?.type }.last())
).also { ).also {
it.psi = this it.psi = this
} }
@@ -447,14 +453,17 @@ class JavaToJKTreeBuilder constructor(
val classSymbol = val classSymbol =
classOrAnonymousClassReference?.resolve()?.let { classOrAnonymousClassReference?.resolve()?.let {
symbolProvider.provideDirectSymbol(it) as JKClassSymbol symbolProvider.provideDirectSymbol(it) as JKClassSymbol
} ?: JKUnresolvedClassSymbol(classOrAnonymousClassReference?.referenceName ?: throwCanNotConvertError()) } ?: JKUnresolvedClassSymbol(
classOrAnonymousClassReference?.referenceName ?: throwCanNotConvertError(),
typeFactory
)
val typeArgumentList = val typeArgumentList =
this.typeArgumentList.toJK() this.typeArgumentList.toJK()
.takeIf { it.typeArguments.isNotEmpty() } .takeIf { it.typeArguments.isNotEmpty() }
?: classOrAnonymousClassReference ?: classOrAnonymousClassReference
?.typeParameters ?.typeParameters
?.let { typeParameters -> ?.let { typeParameters ->
JKTypeArgumentListImpl(typeParameters.map { JKTypeElementImpl(it.toJK(symbolProvider)) }) JKTypeArgumentListImpl(typeParameters.map { JKTypeElementImpl(it.toJK()) })
} ?: JKTypeArgumentListImpl() } ?: JKTypeArgumentListImpl()
JKJavaNewExpressionImpl( JKJavaNewExpressionImpl(
classSymbol, classSymbol,
@@ -469,7 +478,7 @@ class JavaToJKTreeBuilder constructor(
} }
fun PsiReferenceParameterList.toJK(): JKTypeArgumentList = fun PsiReferenceParameterList.toJK(): JKTypeArgumentList =
JKTypeArgumentListImpl(this.typeArguments.map { JKTypeElementImpl(it.toJK(symbolProvider)) }) JKTypeArgumentListImpl(this.typeArguments.map { JKTypeElementImpl(it.toJK()) })
.also { .also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -487,7 +496,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiTypeCastExpression.toJK(): JKExpression { fun PsiTypeCastExpression.toJK(): JKExpression {
return JKTypeCastExpressionImpl( return JKTypeCastExpressionImpl(
operand?.toJK() ?: throwCanNotConvertError(), operand?.toJK() ?: throwCanNotConvertError(),
castType?.type?.toJK(symbolProvider)?.asTypeElement() ?: throwCanNotConvertError() castType?.type?.toJK()?.asTypeElement() ?: throwCanNotConvertError()
).also { ).also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -535,7 +544,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiTypeParameter.toJK(): JKTypeParameter = fun PsiTypeParameter.toJK(): JKTypeParameter =
JKTypeParameterImpl( JKTypeParameterImpl(
nameIdentifier.toJK(), nameIdentifier.toJK(),
extendsListTypes.map { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.Default)) } extendsListTypes.map { JKTypeElementImpl(it.toJK()) }
).also { ).also {
symbolProvider.provideUniverseSymbol(this, it) symbolProvider.provideUniverseSymbol(this, it)
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
@@ -562,9 +571,9 @@ class JavaToJKTreeBuilder constructor(
fun PsiClass.inheritanceInfo(): JKInheritanceInfo { fun PsiClass.inheritanceInfo(): JKInheritanceInfo {
val implTypes = val implTypes =
implementsList?.referencedTypes?.map { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.Default)) }.orEmpty() implementsList?.referencedTypes?.map { JKTypeElementImpl(it.toJK()) }.orEmpty()
val extensionType = val extensionType =
extendsList?.referencedTypes?.map { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.Default)) }.orEmpty() extendsList?.referencedTypes?.map { JKTypeElementImpl(it.toJK()) }.orEmpty()
return JKInheritanceInfoImpl(extensionType, implTypes) return JKInheritanceInfoImpl(extensionType, implTypes)
.also { .also {
if (implementsList != null) { if (implementsList != null) {
@@ -645,7 +654,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiField.toJK(): JKJavaField { fun PsiField.toJK(): JKJavaField {
return JKJavaFieldImpl( return JKJavaFieldImpl(
JKTypeElementImpl(type.toJK(symbolProvider)).withAssignedNonCodeElements(typeElement), JKTypeElementImpl(type.toJK()).withAssignedNonCodeElements(typeElement),
nameIdentifier.toJK(), nameIdentifier.toJK(),
with(expressionTreeMapper) { initializer.toJK() }, with(expressionTreeMapper) { initializer.toJK() },
annotationList(this), annotationList(this),
@@ -676,7 +685,7 @@ class JavaToJKTreeBuilder constructor(
symbolProvider.provideSymbolForReference<JKSymbol>( symbolProvider.provideSymbolForReference<JKSymbol>(
nameReferenceElement ?: throwCanNotConvertError() nameReferenceElement ?: throwCanNotConvertError()
).safeAs<JKClassSymbol>() ).safeAs<JKClassSymbol>()
?: JKUnresolvedClassSymbol(nameReferenceElement?.text ?: throwCanNotConvertError()), ?: JKUnresolvedClassSymbol(nameReferenceElement?.text ?: throwCanNotConvertError(), typeFactory),
parameterList.attributes.map { parameter -> parameterList.attributes.map { parameter ->
if (parameter.nameIdentifier != null) { if (parameter.nameIdentifier != null) {
JKAnnotationNameParameterImpl( JKAnnotationNameParameterImpl(
@@ -698,7 +707,7 @@ class JavaToJKTreeBuilder constructor(
JKAnnotationImpl( JKAnnotationImpl(
symbolProvider.provideClassSymbol("kotlin.Deprecated"), symbolProvider.provideClassSymbol("kotlin.Deprecated"),
listOf( listOf(
JKAnnotationParameterImpl(stringLiteral(tag.content(), symbolProvider)) JKAnnotationParameterImpl(stringLiteral(tag.content(), typeFactory))
) )
) )
} }
@@ -718,7 +727,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod = fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod =
JKJavaAnnotationMethodImpl( JKJavaAnnotationMethodImpl(
returnType?.toJK(symbolProvider)?.asTypeElement() returnType?.toJK()?.asTypeElement()
?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor } ?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor }
?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"), ?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"),
nameIdentifier.toJK(), nameIdentifier.toJK(),
@@ -733,7 +742,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiMethod.toJK(): JKJavaMethod { fun PsiMethod.toJK(): JKJavaMethod {
return JKJavaMethodImpl( return JKJavaMethodImpl(
returnType?.toJK(symbolProvider)?.asTypeElement() returnType?.toJK()?.asTypeElement()
?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor } ?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor }
?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"), ?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"),
nameIdentifier.toJK(), nameIdentifier.toJK(),
@@ -741,7 +750,7 @@ class JavaToJKTreeBuilder constructor(
body?.toJK() ?: JKBodyStubImpl, body?.toJK() ?: JKBodyStubImpl,
typeParameterList?.toJK() ?: JKTypeParameterListImpl(), typeParameterList?.toJK() ?: JKTypeParameterListImpl(),
annotationList(this), annotationList(this),
throwsList.referencedTypes.map { JKTypeElementImpl(it.toJK(symbolProvider)) }, throwsList.referencedTypes.map { JKTypeElementImpl(it.toJK()) },
otherModifiers(), otherModifiers(),
visibility(), visibility(),
modality() modality()
@@ -758,7 +767,7 @@ class JavaToJKTreeBuilder constructor(
} }
fun PsiParameter.toJK(): JKParameter { fun PsiParameter.toJK(): JKParameter {
val rawType = type.toJK(symbolProvider) val rawType = type.toJK()
val type = val type =
if (isVarArgs && rawType is JKJavaArrayType) JKTypeElementImpl(rawType.type) if (isVarArgs && rawType is JKJavaArrayType) JKTypeElementImpl(rawType.type)
else rawType.asTypeElement() else rawType.asTypeElement()
@@ -786,7 +795,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiLocalVariable.toJK(): JKLocalVariable = fun PsiLocalVariable.toJK(): JKLocalVariable =
JKLocalVariableImpl( JKLocalVariableImpl(
JKTypeElementImpl(type.toJK(symbolProvider)).withAssignedNonCodeElements(typeElement), JKTypeElementImpl(type.toJK()).withAssignedNonCodeElements(typeElement),
nameIdentifier.toJK(), nameIdentifier.toJK(),
with(expressionTreeMapper) { initializer.toJK() }, with(expressionTreeMapper) { initializer.toJK() },
JKMutabilityModifierElementImpl( JKMutabilityModifierElementImpl(
@@ -944,7 +953,7 @@ class JavaToJKTreeBuilder constructor(
if (psi.parent is PsiReferenceList) { if (psi.parent is PsiReferenceList) {
val factory = JavaPsiFacade.getInstance(psi.project).elementFactory val factory = JavaPsiFacade.getInstance(psi.project).elementFactory
val type = factory.createType(psi) val type = factory.createType(psi)
JKTypeElementImpl(type.toJK(symbolProvider).updateNullabilityRecursively(Nullability.NotNull)) JKTypeElementImpl(type.toJK().updateNullabilityRecursively(Nullability.NotNull))
} else null } else null
else -> null else -> null
}?.let { JKTreeRootImpl(it) } }?.let { JKTreeRootImpl(it) }
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.nj2k.symbols.getDisplayName
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitorWithCommentsPrinting import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitorWithCommentsPrinting
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.nj2k
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
data class NewJ2kConverterContext( data class NewJ2kConverterContext(
val symbolProvider: JKSymbolProvider, val symbolProvider: JKSymbolProvider,
val typeFactory: JKTypeFactory,
val converter: NewJavaToKotlinConverter, val converter: NewJavaToKotlinConverter,
val inConversionContext: (PsiElement) -> Boolean, val inConversionContext: (PsiElement) -> Boolean,
val importStorage: ImportStorage, val importStorage: ImportStorage,
@@ -35,6 +35,7 @@ import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jetbrains.kotlin.idea.core.util.EDT import org.jetbrains.kotlin.idea.core.util.EDT
import org.jetbrains.kotlin.j2k.* import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtPsiFactory
class NewJavaToKotlinConverter( class NewJavaToKotlinConverter(
@@ -106,9 +107,11 @@ class NewJavaToKotlinConverter(
val module = targetModule ?: error("Module should not be null for new J2K") val module = targetModule ?: error("Module should not be null for new J2K")
val contextElement = inputElements.firstOrNull() ?: return Result(emptyList(), null, null) val contextElement = inputElements.firstOrNull() ?: return Result(emptyList(), null, null)
val symbolProvider = JKSymbolProvider(project, module, contextElement) val symbolProvider = JKSymbolProvider(project, module, contextElement)
val typeFactory = JKTypeFactory(symbolProvider)
symbolProvider.typeFactory = typeFactory
symbolProvider.preBuildTree(inputElements) symbolProvider.preBuildTree(inputElements)
val importStorage = ImportStorage() val importStorage = ImportStorage()
val treeBuilder = JavaToJKTreeBuilder(symbolProvider, converterServices, importStorage) val treeBuilder = JavaToJKTreeBuilder(symbolProvider, typeFactory, converterServices, importStorage)
val asts = processor.process { val asts = processor.process {
inputElements.mapIndexed { i, element -> inputElements.mapIndexed { i, element ->
processor.updateState(i, 1, phaseDescription) processor.updateState(i, 1, phaseDescription)
@@ -118,6 +121,7 @@ class NewJavaToKotlinConverter(
val context = NewJ2kConverterContext( val context = NewJ2kConverterContext(
symbolProvider, symbolProvider,
typeFactory,
this, this,
{ it.containingFile in inputElements }, { it.containingFile in inputElements },
importStorage, importStorage,
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.nj2k.symbols.JKUniverseMethodSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKCapturedType import org.jetbrains.kotlin.nj2k.tree.impl.JKCapturedType
import org.jetbrains.kotlin.nj2k.tree.impl.psi import org.jetbrains.kotlin.nj2k.tree.impl.psi
import org.jetbrains.kotlin.nj2k.types.JKParametrizedType
import org.jetbrains.kotlin.nj2k.types.JKStarProjectionType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class AddElementsInfoConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class AddElementsInfoConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.toExpression import org.jetbrains.kotlin.nj2k.toExpression
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
class AnnotationClassConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class AnnotationClassConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.toArgumentList import org.jetbrains.kotlin.nj2k.toArgumentList
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
@@ -14,6 +14,7 @@ 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.tree.impl.JKFieldAccessExpressionImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKFieldAccessExpressionImpl
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -32,7 +33,7 @@ class ArrayOperationsConversion(context: NewJ2kConverterContext) : RecursiveAppl
} }
private fun JKExpression.isArrayOrVarargTypeParameter(): Boolean { private fun JKExpression.isArrayOrVarargTypeParameter(): Boolean {
if (type(symbolProvider) is JKJavaArrayType) return true if (type(typeFactory) is JKJavaArrayType) return true
val parameter = val parameter =
safeAs<JKFieldAccessExpression>() safeAs<JKFieldAccessExpression>()
?.identifier ?.identifier
@@ -29,7 +29,7 @@ class AssertStatementConversion(context: NewJ2kConverterContext) : RecursiveAppl
kotlinAssert( kotlinAssert(
element::condition.detached(), element::condition.detached(),
messageExpression, messageExpression,
symbolProvider typeFactory
) )
) )
) )
@@ -267,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(symbolProvider)?.isStringType() == true } withByArgumentsFilter { it.singleOrNull()?.type(typeFactory)?.isStringType() == true }
withArgumentsProvider { arguments -> withArgumentsProvider { arguments ->
val argument = arguments.arguments.single()::value.detached() val argument = arguments.arguments.single()::value.detached()
val call = JKKtCallExpressionImpl( val call = JKKtCallExpressionImpl(
@@ -280,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(symbolProvider)?.isArrayType() == false }, withByArgumentsFilter { it.isNotEmpty() && it.first().type(typeFactory)?.isArrayType() == false },
Method("java.lang.String.getChars") Method("java.lang.String.getChars")
convertTo Method("kotlin.text.toCharArray") convertTo Method("kotlin.text.toCharArray")
@@ -296,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(symbolProvider)?.isArrayType() == true }, withByArgumentsFilter { it.isNotEmpty() && it.first().type(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(symbolProvider)?.isArrayType() == true }, withByArgumentsFilter { it.isNotEmpty() && it.first().type(typeFactory)?.isArrayType() == true },
Method("java.lang.String.replaceAll") Method("java.lang.String.replaceAll")
convertTo Method("kotlin.text.replace") convertTo Method("kotlin.text.replace")
@@ -370,7 +370,7 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
firstArgument, firstArgument,
secondArgument, secondArgument,
KtTokens.PLUS, KtTokens.PLUS,
symbolProvider typeFactory
) )
} withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER, } withReplaceType ReplaceType.REPLACE_WITH_QUALIFIER,
@@ -397,7 +397,7 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
JKFieldAccessExpressionImpl( JKFieldAccessExpressionImpl(
JKUnresolvedField(//TODO replace with `it` parameter JKUnresolvedField(//TODO replace with `it` parameter
"it", "it",
symbolProvider typeFactory
) )
).callOn(symbolProvider.provideMethodSymbol("kotlin.text.isEmpty")) ).callOn(symbolProvider.provideMethodSymbol("kotlin.text.isEmpty"))
.asStatement(), .asStatement(),
@@ -432,12 +432,12 @@ class BuiltinMembersConversion(context: NewJ2kConverterContext) : RecursiveAppli
JKFieldAccessExpressionImpl( JKFieldAccessExpressionImpl(
JKUnresolvedField(//TODO replace with `it` parameter JKUnresolvedField(//TODO replace with `it` parameter
"it", "it",
symbolProvider typeFactory
) )
), ),
JKKtLiteralExpressionImpl("' '", JKLiteralExpression.LiteralType.CHAR), JKKtLiteralExpressionImpl("' '", JKLiteralExpression.LiteralType.CHAR),
KtTokens.LTEQ, KtTokens.LTEQ,
symbolProvider typeFactory
) )
), ),
emptyList() emptyList()
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.symbols.JKSymbol import org.jetbrains.kotlin.nj2k.symbols.JKSymbol
import org.jetbrains.kotlin.nj2k.symbols.fqNameToImport import org.jetbrains.kotlin.nj2k.symbols.fqNameToImport
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -23,7 +23,7 @@ class EqualsOperatorConversion(context: NewJ2kConverterContext) : RecursiveAppli
equalsExpression( equalsExpression(
element::receiver.detached(), element::receiver.detached(),
argument::value.detached(), argument::value.detached(),
symbolProvider typeFactory
) )
) )
) )
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.nj2k.*
import org.jetbrains.kotlin.nj2k.symbols.deepestFqName import org.jetbrains.kotlin.nj2k.symbols.deepestFqName
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import kotlin.math.abs import kotlin.math.abs
@@ -185,7 +186,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
start, start,
convertBound(bound, if (inclusiveComparison) 0 else -1), convertBound(bound, if (inclusiveComparison) 0 else -1),
JKKtSingleValueOperatorToken(KtTokens.RANGE), JKKtSingleValueOperatorToken(KtTokens.RANGE),
symbolProvider typeFactory
) )
} }
} }
@@ -203,7 +204,7 @@ class ForConversion(context: NewJ2kConverterContext) : RecursiveApplicableConver
bound, bound,
JKKtLiteralExpressionImpl(abs(correction).toString(), JKLiteralExpression.LiteralType.INT), JKKtLiteralExpressionImpl(abs(correction).toString(), JKLiteralExpression.LiteralType.INT),
JKKtSingleValueOperatorToken(sign), JKKtSingleValueOperatorToken(sign),
symbolProvider typeFactory
) )
} }
@@ -255,7 +256,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(symbolProvider) val receiverType = javaSizeCall.receiver.type(typeFactory)
if (methodCall.identifier.name == "length" && receiverType is JKJavaArrayType) { if (methodCall.identifier.name == "length" && receiverType is JKJavaArrayType) {
return toIndicesCall(javaSizeCall) return toIndicesCall(javaSizeCall)
} }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.nj2k.symbols.isUnresolved
import org.jetbrains.kotlin.nj2k.symbols.parameterTypesWithUnfoldedVarargs import org.jetbrains.kotlin.nj2k.symbols.parameterTypesWithUnfoldedVarargs
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -30,8 +31,8 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
private fun convertBinaryExpression(binaryExpression: JKBinaryExpression): JKExpression { private fun convertBinaryExpression(binaryExpression: JKBinaryExpression): JKExpression {
fun JKBinaryExpression.convertBinaryOperationWithChar(): JKBinaryExpression { fun JKBinaryExpression.convertBinaryOperationWithChar(): JKBinaryExpression {
val leftType = left.type(symbolProvider)?.asPrimitiveType() ?: return this val leftType = left.type(typeFactory)?.asPrimitiveType() ?: return this
val rightType = right.type(symbolProvider)?.asPrimitiveType() ?: return this val rightType = right.type(typeFactory)?.asPrimitiveType() ?: return this
val leftOperandCastedCasted by lazy { val leftOperandCastedCasted by lazy {
JKBinaryExpressionImpl( JKBinaryExpressionImpl(
@@ -72,7 +73,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
} }
private fun convertAssignmentStatement(statement: JKKtAssignmentStatement) { private fun convertAssignmentStatement(statement: JKKtAssignmentStatement) {
val expressionType = statement.field.type(symbolProvider) ?: return val expressionType = statement.field.type(typeFactory) ?: return
statement.expression.castTo(expressionType)?.also { statement.expression.castTo(expressionType)?.also {
statement.expression = it statement.expression = it
} }
@@ -99,7 +100,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
private fun JKExpression.castStringToRegex(toType: JKType): JKExpression? { private fun JKExpression.castStringToRegex(toType: JKType): JKExpression? {
if (toType.safeAs<JKClassType>()?.classReference?.fqName != "java.util.regex.Pattern") return null if (toType.safeAs<JKClassType>()?.classReference?.fqName != "java.util.regex.Pattern") return null
val expressionType = type(symbolProvider) ?: return null val expressionType = type(typeFactory) ?: return null
if (!expressionType.isStringType()) return null if (!expressionType.isStringType()) return null
return JKQualifiedExpressionImpl( return JKQualifiedExpressionImpl(
copyTreeAndDetach().parenthesizeIfBinaryExpression(), copyTreeAndDetach().parenthesizeIfBinaryExpression(),
@@ -120,7 +121,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
val casted = expression.castToAsPrimitiveTypes(toType, strict) ?: return null val casted = expression.castToAsPrimitiveTypes(toType, strict) ?: return null
return JKPrefixExpressionImpl(casted, operator) return JKPrefixExpressionImpl(casted, operator)
} }
val expressionTypeAsPrimitive = type(symbolProvider)?.asPrimitiveType() ?: return null val expressionTypeAsPrimitive = type(typeFactory)?.asPrimitiveType() ?: return null
val toTypeAsPrimitive = toType.asPrimitiveType() ?: return null val toTypeAsPrimitive = toType.asPrimitiveType() ?: return null
if (toTypeAsPrimitive == expressionTypeAsPrimitive) return null if (toTypeAsPrimitive == expressionTypeAsPrimitive) return null
@@ -155,7 +156,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 = type(symbolProvider) val expressionType = type(typeFactory)
if (expressionType == toType) return null if (expressionType == toType) return null
castToAsPrimitiveTypes(toType, strict)?.also { return it } castToAsPrimitiveTypes(toType, strict)?.also { return it }
castStringToRegex(toType)?.also { return it } castStringToRegex(toType)?.also { return it }
@@ -13,6 +13,9 @@ import org.jetbrains.kotlin.nj2k.tree.impl.JKBooleanLiteral
import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaLiteralExpressionImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaLiteralExpressionImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaPrimitiveTypeImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaPrimitiveTypeImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKNullLiteral import org.jetbrains.kotlin.nj2k.tree.impl.JKNullLiteral
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.nj2k.types.JKTypeParameterType
class ImplicitInitializerConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class ImplicitInitializerConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKUniverseClassSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKClassType
class InsertDefaultPrimaryConstructorConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class InsertDefaultPrimaryConstructorConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedClassSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKClassType
class JavaStandardMethodsConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class JavaStandardMethodsConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
@@ -31,7 +32,7 @@ class JavaStandardMethodsConversion(context: NewJ2kConverterContext) : Recursive
element.inheritance.implements += element.inheritance.implements +=
JKTypeElementImpl( JKTypeElementImpl(
JKClassTypeImpl( JKClassTypeImpl(
JKUnresolvedClassSymbol("Cloneable"), JKUnresolvedClassSymbol("Cloneable", typeFactory),
emptyList(), Nullability.NotNull emptyList(), Nullability.NotNull
) )
) )
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKAnnotationImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKAnnotationImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaArrayTypeImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaArrayTypeImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKTypeElementImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKTypeElementImpl
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
//TODO temporary //TODO temporary
@@ -6,12 +6,17 @@
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 org.jetbrains.kotlin.codegen.kotlinType
import org.jetbrains.kotlin.codegen.optimization.common.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.nullIfStubExpression import org.jetbrains.kotlin.nj2k.nullIfStubExpression
import org.jetbrains.kotlin.nj2k.qualified 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.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKTypeParameterType
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
@@ -111,12 +116,12 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
.firstOrNull { !it.hasModifier(JvmModifier.STATIC) } .firstOrNull { !it.hasModifier(JvmModifier.STATIC) }
?.parameterList ?.parameterList
?.parameters ?.parameters
?.map { it.type.toJK(symbolProvider).substituteTypeParameters(this) } ?.map { typeFactory.fromPsiType(it.type).substituteTypeParameters(this) }
is JKMultiverseKtClassSymbol -> reference.target.body is JKMultiverseKtClassSymbol -> reference.target.body
?.functions ?.functions
?.singleOrNull() ?.singleOrNull()
?.valueParameters ?.valueParameters
?.map { it.typeReference?.toJK(symbolProvider)?.substituteTypeParameters(this) ?: return null } ?.map { typeFactory.fromKotlinType(it.kotlinType(it.analyze()) ?: return null).substituteTypeParameters(this) }
is JKUniverseClassSymbol -> reference.target.classBody.declarations.firstIsInstanceOrNull<JKMethod>() is JKUniverseClassSymbol -> reference.target.classBody.declarations.firstIsInstanceOrNull<JKMethod>()
?.parameters ?.parameters
?.map { it.type.type.substituteTypeParameters(this) } ?.map { it.type.type.substituteTypeParameters(this) }
@@ -34,7 +34,7 @@ class OperatorExpressionConversion(context: NewJ2kConverterContext) : RecursiveA
is JKPostfixExpression -> { is JKPostfixExpression -> {
val operatorToken = operator.token.toKtToken() val operatorToken = operator.token.toKtToken()
val operand = applyToElement(element::expression.detached()) as JKExpression val operand = applyToElement(element::expression.detached()) as JKExpression
recurse(kotlinPostfixExpression(operand, operatorToken, symbolProvider)) recurse(kotlinPostfixExpression(operand, operatorToken, typeFactory))
} }
else -> TODO(element.javaClass.toString()) else -> TODO(element.javaClass.toString())
}.withNonCodeElementsFrom(element) }.withNonCodeElementsFrom(element)
@@ -43,7 +43,7 @@ class OperatorExpressionConversion(context: NewJ2kConverterContext) : RecursiveA
private fun convertPrefixExpression(operand: JKExpression, javaOperator: JKJavaOperatorImpl) = private fun convertPrefixExpression(operand: JKExpression, javaOperator: JKJavaOperatorImpl) =
convertTildeExpression(operand, javaOperator) convertTildeExpression(operand, javaOperator)
?: kotlinPrefixExpression(operand, javaOperator.token.toKtToken(), symbolProvider) ?: kotlinPrefixExpression(operand, javaOperator.token.toKtToken(), typeFactory)
private fun convertTildeExpression(operand: JKExpression, javaOperator: JKJavaOperatorImpl): JKExpression? = private fun convertTildeExpression(operand: JKExpression, javaOperator: JKJavaOperatorImpl): JKExpression? =
if (javaOperator.token.psiToken == JavaTokenType.TILDE) { if (javaOperator.token.psiToken == JavaTokenType.TILDE) {
@@ -61,14 +61,14 @@ class OperatorExpressionConversion(context: NewJ2kConverterContext) : RecursiveA
private fun convertBinaryExpression(left: JKExpression, right: JKExpression, token: JKKtOperatorToken): JKBinaryExpression = private fun convertBinaryExpression(left: JKExpression, right: JKExpression, token: JKKtOperatorToken): JKBinaryExpression =
convertStringImplicitConcatenation(left, right, token) convertStringImplicitConcatenation(left, right, token)
?: kotlinBinaryExpression(left, right, token, symbolProvider) ?: kotlinBinaryExpression(left, right, token, typeFactory)
private fun convertStringImplicitConcatenation(left: JKExpression, right: JKExpression, token: JKKtOperatorToken): JKBinaryExpression? = private fun convertStringImplicitConcatenation(left: JKExpression, right: JKExpression, token: JKKtOperatorToken): JKBinaryExpression? =
if (token is JKKtSingleValueOperatorToken if (token is JKKtSingleValueOperatorToken
&& token.psiToken == KtTokens.PLUS && token.psiToken == KtTokens.PLUS
&& right.type(symbolProvider)?.isStringType() == true && right.type(typeFactory)?.isStringType() == true
&& left.type(symbolProvider)?.isStringType() == false && left.type(typeFactory)?.isStringType() == false
) { ) {
val toStringCall = val toStringCall =
JKKtCallExpressionImpl( JKKtCallExpressionImpl(
@@ -76,6 +76,6 @@ class OperatorExpressionConversion(context: NewJ2kConverterContext) : RecursiveA
JKArgumentListImpl() JKArgumentListImpl()
) )
val qualifiedCall = JKQualifiedExpressionImpl(left, JKKtQualifierImpl.DOT, toStringCall) val qualifiedCall = JKQualifiedExpressionImpl(left, JKKtQualifierImpl.DOT, toStringCall)
kotlinBinaryExpression(qualifiedCall, right, KtTokens.PLUS, symbolProvider) kotlinBinaryExpression(qualifiedCall, right, KtTokens.PLUS, typeFactory)
} else null } else null
} }
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.hasWritableUsages import org.jetbrains.kotlin.nj2k.hasWritableUsages
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.nj2k.types.JKVarianceTypeParameterType
class ParameterModificationInMethodCallsConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class ParameterModificationInMethodCallsConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.copyTreeAndDetach import org.jetbrains.kotlin.nj2k.copyTreeAndDetach
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKJavaDisjunctionType
import org.jetbrains.kotlin.nj2k.useExpression import org.jetbrains.kotlin.nj2k.useExpression
@@ -5,17 +5,18 @@
package org.jetbrains.kotlin.nj2k.conversions package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.toKotlinMutableTypesMap import org.jetbrains.kotlin.j2k.toKotlinMutableTypesMap
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.kotlinTypeByName
import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKUniverseClassSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.psi.KtClass
class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
@@ -49,13 +50,7 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
return when (val typeParametersCount = classSymbol.expectedTypeParametersCount()) { return when (val typeParametersCount = classSymbol.expectedTypeParametersCount()) {
0 -> this 0 -> this
else -> JKTypeArgumentListImpl(List(typeParametersCount) { else -> JKTypeArgumentListImpl(List(typeParametersCount) {
JKTypeElementImpl( JKTypeElementImpl(typeFactory.types.nullableAny)
kotlinTypeByName(
KotlinBuiltIns.FQ_NAMES.any.toSafe().asString(),
symbolProvider,
Nullability.Nullable
)
)
}) })
} }
} }
@@ -65,26 +60,20 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
when (typeElement?.parent) { when (typeElement?.parent) {
is JKClassLiteralExpression -> this is JKClassLiteralExpression -> this
is JKKtIsExpression -> is JKKtIsExpression ->
addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl()) addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl)
.updateNullability(Nullability.NotNull) .updateNullability(Nullability.NotNull)
is JKTypeCastExpression -> is JKTypeCastExpression ->
addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl()) addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl)
else -> else ->
addTypeParametersToRawProjectionType( addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl)
JKStarProjectionTypeImpl()
)
} }
private fun JKType.mapType(typeElement: JKTypeElement?): JKType = private fun JKType.mapType(typeElement: JKTypeElement?): JKType =
when (this) { when (this) {
is JKJavaPrimitiveType -> mapPrimitiveType() is JKJavaPrimitiveType -> mapPrimitiveType()
is JKClassType -> mapClassType(typeElement) is JKClassType -> mapClassType(typeElement)
is JKJavaVoidType -> is JKJavaVoidType -> typeFactory.types.unit
kotlinTypeByName(
KotlinBuiltIns.FQ_NAMES.unit.toSafe().asString(),
symbolProvider,
Nullability.NotNull
)
is JKJavaArrayType -> is JKJavaArrayType ->
JKClassTypeImpl( JKClassTypeImpl(
symbolProvider.provideClassSymbol(type.arrayFqName()), symbolProvider.provideClassSymbol(type.arrayFqName()),
@@ -137,6 +126,25 @@ class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicab
) )
} }
private inline fun <reified T : JKType> T.addTypeParametersToRawProjectionType(typeParameter: JKType): T =
if (this is JKClassType && parameters.isEmpty()) {
val parametersCount = classReference.expectedTypeParametersCount()
val typeParameters = List(parametersCount) { typeParameter }
JKClassTypeImpl(
classReference,
typeParameters,
nullability
) as T
} else this
private fun JKClassSymbol.expectedTypeParametersCount(): Int =
when (val resolvedClass = target) {
is PsiClass -> resolvedClass.typeParameters.size
is KtClass -> resolvedClass.typeParameters.size
is JKClass -> resolvedClass.typeParameterList.typeParameters.size
else -> 0
}
companion object { companion object {
private val ktFunctionRegex = "kotlin\\.jvm\\.functions\\.Function\\d+".toRegex() private val ktFunctionRegex = "kotlin\\.jvm\\.functions\\.Function\\d+".toRegex()
private fun isKtFunction(fqName: String) = private fun isKtFunction(fqName: String) =
@@ -8,54 +8,48 @@ package org.jetbrains.kotlin.nj2k
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import com.intellij.psi.tree.TokenSet import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.nj2k.conversions.RecursiveApplicableConversionBase import org.jetbrains.kotlin.nj2k.conversions.RecursiveApplicableConversionBase
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.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.JKClassType
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.nj2k.types.JKTypeParameterType
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
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
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType = private fun JKType.classSymbol(typeFactory: JKTypeFactory) = when (this) {
JKClassTypeImpl( is JKClassType -> classReference
symbolProvider.provideClassSymbol(name), is JKJavaPrimitiveType -> typeFactory.fromPrimitiveType(this).classReference
emptyList(), else -> null
nullability }
)
private fun JKType.classSymbol(symbolProvider: JKSymbolProvider) =
when (this) {
is JKClassType -> classReference
is JKJavaPrimitiveType ->
symbolProvider.provideClassSymbol(jvmPrimitiveType.primitiveType.typeFqName)
else -> null
}
private fun JKKtOperatorToken.arithmeticMethodType( private fun JKKtOperatorToken.arithmeticMethodType(
leftType: JKType, leftType: JKType,
rightType: JKType, rightType: JKType,
symbolProvider: JKSymbolProvider typeFactory: JKTypeFactory
): JKType? { ): JKType? {
val symbolProvider = typeFactory.symbolProvider
fun PsiClass.methodReturnType() = fun PsiClass.methodReturnType() =
allMethods allMethods
.filter { it.name == operatorName } .filter { it.name == operatorName }
.firstOrNull { .firstOrNull {
it.parameterList.parameters.singleOrNull()?.takeIf { parameter -> it.parameterList.parameters.singleOrNull()?.takeIf { parameter ->
val type = parameter.type.toJK(symbolProvider) val type = typeFactory.fromPsiType(parameter.type)
if (type !is JKTypeParameterType) rightType.isSubtypeOf(type, symbolProvider) if (type !is JKTypeParameterType) rightType.isSubtypeOf(type, typeFactory)
else true//TODO check for type bounds else true//TODO check for type bounds
} != null } != null
}?.let { it.returnType?.toJK(symbolProvider) } }?.returnType?.let { typeFactory.fromPsiType(it) }
val classSymbol = val classSymbol =
if (leftType.isStringType()) symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.string.toSafe()) if (leftType.isStringType()) symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.string.toSafe())
else leftType.classSymbol(symbolProvider) else leftType.classSymbol(typeFactory)
return when (classSymbol) { return when (classSymbol) {
is JKMultiverseKtClassSymbol -> is JKMultiverseKtClassSymbol ->
@@ -64,7 +58,7 @@ private fun JKKtOperatorToken.arithmeticMethodType(
.filterIsInstance<KtNamedFunction>() .filterIsInstance<KtNamedFunction>()
.filter { it.name == operatorName } .filter { it.name == operatorName }
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol } .mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
.firstOrNull { it.parameterTypes?.singleOrNull()?.takeIf { rightType.isSubtypeOf(it, symbolProvider) } != null } .firstOrNull { it.parameterTypes?.singleOrNull()?.takeIf { rightType.isSubtypeOf(it, typeFactory) } != null }
?.returnType ?.returnType
is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodReturnType() is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodReturnType()
is JKMultiverseClassSymbol -> classSymbol.target.methodReturnType() is JKMultiverseClassSymbol -> classSymbol.target.methodReturnType()
@@ -114,7 +108,7 @@ private val arithmeticOperators = TokenSet.create(
KtTokens.PERC KtTokens.PERC
) )
private fun JKKtOperatorToken.defaultReturnType(leftType: JKType?, rightType: JKType?, symbolProvider: JKSymbolProvider): JKType? { private fun JKKtOperatorToken.defaultReturnType(leftType: JKType?): JKType? {
if (this is JKKtSingleValueOperatorToken && psiToken in arithmeticOperators) return leftType if (this is JKKtSingleValueOperatorToken && psiToken in arithmeticOperators) return leftType
return null return null
} }
@@ -123,21 +117,22 @@ fun kotlinBinaryExpression(
left: JKExpression, left: JKExpression,
right: JKExpression, right: JKExpression,
token: JKKtOperatorToken, token: JKKtOperatorToken,
symbolProvider: JKSymbolProvider typeFactory: JKTypeFactory
): JKBinaryExpression { ): JKBinaryExpression {
val symbolProvider = typeFactory.symbolProvider
val returnType = val returnType =
when { when {
token is JKKtSingleValueOperatorToken && token.psiToken in booleanOperators -> token is JKKtSingleValueOperatorToken && token.psiToken in booleanOperators ->
JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES._boolean.toSafe())) JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES._boolean.toSafe()))
else -> { else -> {
val leftType = left.type(symbolProvider) val leftType = left.type(typeFactory)
val rightType = right.type(symbolProvider) val rightType = right.type(typeFactory)
leftType?.let { l -> leftType?.let { l ->
rightType?.let { r -> rightType?.let { r ->
token.arithmeticMethodType(l, r, symbolProvider) token.arithmeticMethodType(l, r, typeFactory)
} }
} ?: token.defaultReturnType(leftType, rightType, symbolProvider) } ?: token.defaultReturnType(leftType)
?: symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()).asType() ?: typeFactory.types.nothing
} }
} }
return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, returnType)) return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, returnType))
@@ -147,30 +142,30 @@ fun kotlinBinaryExpression(
left: JKExpression, left: JKExpression,
right: JKExpression, right: JKExpression,
token: KtSingleValueToken, token: KtSingleValueToken,
symbolProvider: JKSymbolProvider typeFactory: JKTypeFactory
): JKBinaryExpression = ): JKBinaryExpression =
kotlinBinaryExpression( kotlinBinaryExpression(
left, left,
right, right,
JKKtSingleValueOperatorToken(token), JKKtSingleValueOperatorToken(token),
symbolProvider typeFactory
) )
fun kotlinPrefixExpression( fun kotlinPrefixExpression(
operand: JKExpression, operand: JKExpression,
token: JKKtOperatorToken, token: JKKtOperatorToken,
symbolProvider: JKSymbolProvider typeFactory: JKTypeFactory
): JKPrefixExpression { ): JKPrefixExpression {
val operandType = operand.type(symbolProvider) ?: JKNoTypeImpl val operandType = operand.type(typeFactory) ?: JKNoTypeImpl
return JKPrefixExpressionImpl(operand, JKKtOperatorImpl(token, operandType)) return JKPrefixExpressionImpl(operand, JKKtOperatorImpl(token, operandType))
} }
fun kotlinPostfixExpression( fun kotlinPostfixExpression(
operand: JKExpression, operand: JKExpression,
token: JKKtOperatorToken, token: JKKtOperatorToken,
symbolProvider: JKSymbolProvider typeFactory: JKTypeFactory
): JKPostfixExpression { ): JKPostfixExpression {
val operandType = operand.type(symbolProvider) ?: JKNoTypeImpl val operandType = operand.type(typeFactory) ?: JKNoTypeImpl
return JKPostfixExpressionImpl(operand, JKKtOperatorImpl(token, operandType)) return JKPostfixExpressionImpl(operand, JKKtOperatorImpl(token, operandType))
} }
@@ -248,11 +243,12 @@ fun useExpression(
return JKQualifiedExpressionImpl(receiver, JKKtQualifierImpl.DOT, methodCall) return JKQualifiedExpressionImpl(receiver, JKKtQualifierImpl.DOT, methodCall)
} }
fun kotlinAssert(assertion: JKExpression, message: JKExpression?, symbolProvider: JKSymbolProvider) = fun kotlinAssert(assertion: JKExpression, message: JKExpression?, typeFactory: JKTypeFactory) =
JKKtCallExpressionImpl( JKKtCallExpressionImpl(
JKUnresolvedMethod(//TODO resolve assert JKUnresolvedMethod(//TODO resolve assert
"assert", "assert",
kotlinTypeByName(KotlinBuiltIns.FQ_NAMES.unit.asString(), symbolProvider) typeFactory,
typeFactory.types.unit
), ),
(listOfNotNull(assertion, message)).toArgumentList() (listOfNotNull(assertion, message)).toArgumentList()
) )
@@ -275,20 +271,20 @@ fun throwAnnotation(throws: List<JKType>, symbolProvider: JKSymbolProvider) =
fun JKAnnotationList.annotationByFqName(fqName: String): JKAnnotation? = fun JKAnnotationList.annotationByFqName(fqName: String): JKAnnotation? =
annotations.firstOrNull { it.classSymbol.fqName == fqName } annotations.firstOrNull { it.classSymbol.fqName == fqName }
fun stringLiteral(content: String, symbolProvider: JKSymbolProvider): JKExpression { fun stringLiteral(content: String, typeFactory: JKTypeFactory): JKExpression {
val lines = content.split('\n') val lines = content.split('\n')
return lines.mapIndexed { i, line -> return lines.mapIndexed { i, line ->
val newlineSeparator = if (i == lines.size - 1) "" else "\\n" val newlineSeparator = if (i == lines.size - 1) "" else "\\n"
JKKtLiteralExpressionImpl("\"$line$newlineSeparator\"", JKLiteralExpression.LiteralType.STRING) JKKtLiteralExpressionImpl("\"$line$newlineSeparator\"", JKLiteralExpression.LiteralType.STRING)
}.reduce { acc: JKExpression, literalExpression: JKKtLiteralExpression -> }.reduce { acc: JKExpression, literalExpression: JKKtLiteralExpression ->
kotlinBinaryExpression(acc, literalExpression, JKKtSingleValueOperatorToken(KtTokens.PLUS), symbolProvider) kotlinBinaryExpression(acc, literalExpression, JKKtSingleValueOperatorToken(KtTokens.PLUS), typeFactory)
} }
} }
fun JKVariable.findUsages(scope: JKTreeElement, context: NewJ2kConverterContext): List<JKFieldAccessExpression> { fun JKVariable.findUsages(scope: JKTreeElement, context: NewJ2kConverterContext): List<JKFieldAccessExpression> {
val symbol = context.symbolProvider.provideUniverseSymbol(this) val symbol = context.symbolProvider.provideUniverseSymbol(this)
val usages = mutableListOf<JKFieldAccessExpression>() val usages = mutableListOf<JKFieldAccessExpression>()
val searcher = object : RecursiveApplicableConversionBase() { val searcher = object : RecursiveApplicableConversionBase(context) {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKExpression) { if (element is JKExpression) {
element.unboxFieldReference()?.also { element.unboxFieldReference()?.also {
@@ -323,12 +319,12 @@ fun JKVariable.hasWritableUsages(scope: JKTreeElement, context: NewJ2kConverterC
|| it.isInDecrementOrIncrement() || it.isInDecrementOrIncrement()
} }
fun equalsExpression(left: JKExpression, right: JKExpression, symbolProvider: JKSymbolProvider) = fun equalsExpression(left: JKExpression, right: JKExpression, typeFactory: JKTypeFactory) =
kotlinBinaryExpression( kotlinBinaryExpression(
left, left,
right, right,
KtTokens.EQEQ, KtTokens.EQEQ,
symbolProvider typeFactory
) )
fun createCompanion(declarations: List<JKDeclaration>): JKClass = fun createCompanion(declarations: List<JKDeclaration>): JKClass =
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.nj2k.symbols
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.nj2k.JKSymbolProvider import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.tree.JKClass import org.jetbrains.kotlin.nj2k.tree.JKClass
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
sealed class JKClassSymbol : JKSymbol sealed class JKClassSymbol : JKSymbol
class JKUniverseClassSymbol(override val symbolProvider: JKSymbolProvider) : JKClassSymbol(), JKUniverseSymbol<JKClass> { class JKUniverseClassSymbol(override val typeFactory: JKTypeFactory) : JKClassSymbol(), JKUniverseSymbol<JKClass> {
override lateinit var target: JKClass override lateinit var target: JKClass
override val name: String override val name: String
get() = target.name.value get() = target.name.value
@@ -21,12 +22,15 @@ class JKUniverseClassSymbol(override val symbolProvider: JKSymbolProvider) : JKC
class JKMultiverseClassSymbol( class JKMultiverseClassSymbol(
override val target: PsiClass, override val target: PsiClass,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKClassSymbol(), JKMultiverseSymbol<PsiClass> ) : JKClassSymbol(), JKMultiverseSymbol<PsiClass>
class JKMultiverseKtClassSymbol( class JKMultiverseKtClassSymbol(
override val target: KtClassOrObject, override val target: KtClassOrObject,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKClassSymbol(), JKMultiverseKtSymbol<KtClassOrObject> ) : JKClassSymbol(), JKMultiverseKtSymbol<KtClassOrObject>
class JKUnresolvedClassSymbol(override val target: String) : JKClassSymbol(), JKUnresolvedSymbol class JKUnresolvedClassSymbol(
override val target: String,
override val typeFactory: JKTypeFactory
) : JKClassSymbol(), JKUnresolvedSymbol
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.nj2k.tree.JKType
import org.jetbrains.kotlin.nj2k.tree.JKVariable import org.jetbrains.kotlin.nj2k.tree.JKVariable
import org.jetbrains.kotlin.nj2k.tree.impl.JKClassTypeImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKClassTypeImpl
import org.jetbrains.kotlin.nj2k.tree.toJK import org.jetbrains.kotlin.nj2k.tree.toJK
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 +23,7 @@ sealed class JKFieldSymbol : JKSymbol {
abstract val fieldType: JKType? abstract val fieldType: JKType?
} }
class JKUniverseFieldSymbol(override val symbolProvider: JKSymbolProvider) : 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
@@ -31,23 +32,23 @@ class JKUniverseFieldSymbol(override val symbolProvider: JKSymbolProvider) : JKF
class JKMultiverseFieldSymbol( class JKMultiverseFieldSymbol(
override val target: PsiVariable, override val target: PsiVariable,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseSymbol<PsiVariable> { ) : JKFieldSymbol(), JKMultiverseSymbol<PsiVariable> {
override val fieldType: JKType override val fieldType: JKType
get() = target.type.toJK(symbolProvider) get() = typeFactory.fromPsiType(target.type)
} }
class JKMultiversePropertySymbol( class JKMultiversePropertySymbol(
override val target: KtCallableDeclaration, override val target: KtCallableDeclaration,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseKtSymbol<KtCallableDeclaration> { ) : JKFieldSymbol(), JKMultiverseKtSymbol<KtCallableDeclaration> {
override val fieldType: JKType? override val fieldType: JKType?
get() = target.typeReference?.toJK(symbolProvider) get() = target.typeReference?.toJK(typeFactory)
} }
class JKMultiverseKtEnumEntrySymbol( class JKMultiverseKtEnumEntrySymbol(
override val target: KtEnumEntry, override val target: KtEnumEntry,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> { ) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> {
override val fieldType: JKType? override val fieldType: JKType?
get() = JKClassTypeImpl( get() = JKClassTypeImpl(
@@ -59,10 +60,9 @@ class JKMultiverseKtEnumEntrySymbol(
class JKUnresolvedField( class JKUnresolvedField(
override val target: String, override val target: String,
private val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKUnresolvedSymbol { ) : JKFieldSymbol(), JKUnresolvedSymbol {
override val fieldType: JKType override val fieldType: JKType
get() = get() = JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()), emptyList())
JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()), emptyList())
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKClassTypeImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKClassTypeImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKNoTypeImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKNoTypeImpl
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -24,7 +25,7 @@ sealed class JKMethodSymbol : JKSymbol {
abstract val returnType: JKType? abstract val returnType: JKType?
} }
class JKUniverseMethodSymbol(override val symbolProvider: JKSymbolProvider) : 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*/) JKClassTypeImpl(symbolProvider.provideUniverseSymbol(it), emptyList()/*TODO*/)
@@ -39,16 +40,16 @@ class JKUniverseMethodSymbol(override val symbolProvider: JKSymbolProvider) : JK
class JKMultiverseMethodSymbol( class JKMultiverseMethodSymbol(
override val target: PsiMethod, override val target: PsiMethod,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : 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*/) JKClassTypeImpl(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList()/*TODO*/)
} }
override val parameterTypes: List<JKType> override val parameterTypes: List<JKType>
get() = target.parameterList.parameters.map { it.type.toJK(symbolProvider) } get() = target.parameterList.parameters.map { typeFactory.fromPsiType(it.type) }
override val returnType: JKType override val returnType: JKType
get() = target.returnType?.toJK(symbolProvider) // null for constructor call get() = target.returnType?.let { typeFactory.fromPsiType(it) } // null for constructor call
?: symbolProvider.provideClassSymbol(target.getKotlinFqName()!!).asType(Nullability.NotNull) ?: symbolProvider.provideClassSymbol(target.getKotlinFqName()!!).asType(Nullability.NotNull)
override val fqName: String override val fqName: String
@@ -60,15 +61,15 @@ class JKMultiverseMethodSymbol(
class JKMultiverseFunctionSymbol( class JKMultiverseFunctionSymbol(
override val target: KtFunction, override val target: KtFunction,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKMethodSymbol(), JKMultiverseKtSymbol<KtFunction> { ) : JKMethodSymbol(), JKMultiverseKtSymbol<KtFunction> {
override val receiverType: JKType? override val receiverType: JKType?
get() = target.receiverTypeReference?.toJK(symbolProvider) get() = target.receiverTypeReference?.toJK(typeFactory)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override val parameterTypes: List<JKType>? override val parameterTypes: List<JKType>?
get() = target.valueParameters.map { parameter -> get() = target.valueParameters.map { parameter ->
val type = parameter.typeReference?.toJK(symbolProvider) val type = parameter.typeReference?.toJK(typeFactory)
type?.let { type?.let {
if (parameter.isVarArg) { if (parameter.isVarArg) {
JKClassTypeImpl( JKClassTypeImpl(
@@ -80,14 +81,15 @@ class JKMultiverseFunctionSymbol(
}.takeIf { parameters -> parameters.all { it != null } } as? List<JKType> }.takeIf { parameters -> parameters.all { it != null } } as? List<JKType>
override val returnType: JKType? override val returnType: JKType?
get() = target.typeReference?.toJK(symbolProvider) get() = target.typeReference?.toJK(typeFactory)
} }
class JKUnresolvedMethod( class JKUnresolvedMethod(
override val target: String, override val target: String,
override val typeFactory: JKTypeFactory,
override val returnType: JKType = JKNoTypeImpl override val returnType: JKType = JKNoTypeImpl
) : JKMethodSymbol(), JKUnresolvedSymbol { ) : JKMethodSymbol(), JKUnresolvedSymbol {
constructor(target: PsiReference) : this(target.canonicalText) constructor(target: PsiReference, typeFactory: JKTypeFactory) : this(target.canonicalText, typeFactory)
override val receiverType: JKType? override val receiverType: JKType?
get() = null get() = null
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.nj2k.symbols
import com.intellij.psi.PsiPackage import com.intellij.psi.PsiPackage
import org.jetbrains.kotlin.nj2k.JKSymbolProvider import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
sealed class JKPackageSymbol : JKSymbol { sealed class JKPackageSymbol : JKSymbol {
@@ -15,5 +16,5 @@ sealed class JKPackageSymbol : JKSymbol {
class JKMultiversePackageSymbol( class JKMultiversePackageSymbol(
override val target: PsiPackage, override val target: PsiPackage,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKPackageSymbol(), JKMultiverseSymbol<PsiPackage> ) : JKPackageSymbol(), JKMultiverseSymbol<PsiPackage>
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.tree.JKDeclaration import org.jetbrains.kotlin.nj2k.tree.JKDeclaration
import org.jetbrains.kotlin.nj2k.tree.JKFile import org.jetbrains.kotlin.nj2k.tree.JKFile
import org.jetbrains.kotlin.nj2k.tree.parentOfType import org.jetbrains.kotlin.nj2k.tree.parentOfType
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
@@ -22,10 +23,14 @@ interface JKSymbol {
val declaredIn: JKSymbol? val declaredIn: JKSymbol?
val fqName: String val fqName: String
val name: String val name: String
val typeFactory: JKTypeFactory
val symbolProvider: JKSymbolProvider
get() = typeFactory.symbolProvider
} }
interface JKUniverseSymbol<T : JKDeclaration> : JKSymbol { interface JKUniverseSymbol<T : JKDeclaration> : JKSymbol {
val symbolProvider: JKSymbolProvider
override var target: T override var target: T
override val fqName: String override val fqName: String
get() { get() {
@@ -47,8 +52,6 @@ interface JKUniverseSymbol<T : JKDeclaration> : JKSymbol {
} }
interface JKMultiverseSymbol<T> : JKSymbol where T : PsiNamedElement, T : PsiElement { interface JKMultiverseSymbol<T> : JKSymbol where T : PsiNamedElement, T : PsiElement {
val symbolProvider: JKSymbolProvider
override val target: T override val target: T
override val declaredIn: JKSymbol? override val declaredIn: JKSymbol?
get() = target.getStrictParentOfType<PsiMember>()?.let { symbolProvider.provideDirectSymbol(it) } get() = target.getStrictParentOfType<PsiMember>()?.let { symbolProvider.provideDirectSymbol(it) }
@@ -59,8 +62,6 @@ interface JKMultiverseSymbol<T> : JKSymbol where T : PsiNamedElement, T : PsiEle
} }
interface JKMultiverseKtSymbol<T : KtNamedDeclaration> : JKSymbol { interface JKMultiverseKtSymbol<T : KtNamedDeclaration> : JKSymbol {
val symbolProvider: JKSymbolProvider
override val target: T override val target: T
override val name: String override val name: String
get() = target.name!! get() = target.name!!
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiTypeParameter
import org.jetbrains.kotlin.nj2k.JKSymbolProvider import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.tree.JKTypeParameter import org.jetbrains.kotlin.nj2k.tree.JKTypeParameter
import org.jetbrains.kotlin.nj2k.tree.JKTypeParameterListOwner import org.jetbrains.kotlin.nj2k.tree.JKTypeParameterListOwner
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtTypeParameter import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -20,14 +21,14 @@ sealed class JKTypeParameterSymbol : JKSymbol {
class JKMultiverseTypeParameterSymbol( class JKMultiverseTypeParameterSymbol(
override val target: PsiTypeParameter, override val target: PsiTypeParameter,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKTypeParameterSymbol(), JKMultiverseSymbol<PsiTypeParameter> { ) : JKTypeParameterSymbol(), JKMultiverseSymbol<PsiTypeParameter> {
override val index: Int override val index: Int
get() = target.index get() = target.index
} }
class JKUniverseTypeParameterSymbol( class JKUniverseTypeParameterSymbol(
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKTypeParameterSymbol(), JKUniverseSymbol<JKTypeParameter> { ) : JKTypeParameterSymbol(), JKUniverseSymbol<JKTypeParameter> {
override val index: Int override val index: Int
get() = declaredIn?.safeAs<JKTypeParameterListOwner>()?.typeParameterList?.typeParameters?.indexOf(target) ?: -1 get() = declaredIn?.safeAs<JKTypeParameterListOwner>()?.typeParameterList?.typeParameters?.indexOf(target) ?: -1
@@ -36,7 +37,7 @@ class JKUniverseTypeParameterSymbol(
class JKMultiverseKtTypeParameterSymbol( class JKMultiverseKtTypeParameterSymbol(
override val target: KtTypeParameter, override val target: KtTypeParameter,
override val symbolProvider: JKSymbolProvider override val typeFactory: JKTypeFactory
) : JKTypeParameterSymbol(), JKMultiverseKtSymbol<KtTypeParameter> { ) : JKTypeParameterSymbol(), JKMultiverseKtSymbol<KtTypeParameter> {
override val index: Int override val index: Int
get() = target.getParentOfType<KtTypeParameterListOwner>(strict = false)?.typeParameters?.indexOf(target) ?: -1 get() = target.getParentOfType<KtTypeParameterListOwner>(strict = false)?.typeParameters?.indexOf(target) ?: -1
@@ -24,9 +24,8 @@ import org.jetbrains.kotlin.nj2k.JKSymbolProvider
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.tree.JKLiteralExpression.LiteralType import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType
import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.BOOLEAN
import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.NULL
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.nj2k.types.*
class JKTreeRootImpl(element: JKTreeElement) : JKTreeRoot, JKBranchElementBase() { class JKTreeRootImpl(element: JKTreeElement) : JKTreeRoot, JKBranchElementBase() {
override var element by child(element) override var element by child(element)
@@ -211,7 +210,7 @@ object JKNoTypeImpl : JKNoType {
override val nullability: Nullability = Nullability.NotNull override val nullability: Nullability = Nullability.NotNull
} }
class JKStarProjectionTypeImpl : JKStarProjectionType object JKStarProjectionTypeImpl : JKStarProjectionType
val JKType.fqName: String? val JKType.fqName: String?
get() = when (this) { get() = when (this) {
@@ -224,7 +223,7 @@ class JKNullLiteral : JKLiteralExpression, JKElementBase(), PsiOwner by PsiOwner
override val literal: String override val literal: String
get() = "null" get() = "null"
override val type: LiteralType override val type: LiteralType
get() = NULL get() = LiteralType.NULL
override fun accept(visitor: JKVisitor) = visitor.visitLiteralExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitLiteralExpression(this)
} }
@@ -233,29 +232,20 @@ class JKBooleanLiteral(val value: Boolean) : JKLiteralExpression, JKElementBase(
override val literal: String override val literal: String
get() = value.toString() get() = value.toString()
override val type: LiteralType override val type: LiteralType
get() = BOOLEAN get() = LiteralType.BOOLEAN
override fun accept(visitor: JKVisitor) = visitor.visitLiteralExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitLiteralExpression(this)
} }
fun JKLiteralExpression.LiteralType.toJkType(symbolProvider: JKSymbolProvider): JKType { fun LiteralType.toJkType(typeFactory: JKTypeFactory): JKType = when (this) {
fun defaultTypeByName(name: String) = LiteralType.CHAR -> typeFactory.types.char
JKClassTypeImpl( LiteralType.BOOLEAN -> typeFactory.types.boolean
symbolProvider.provideClassSymbol("kotlin.$name"), emptyList(), Nullability.NotNull LiteralType.INT -> typeFactory.types.int
) LiteralType.LONG -> typeFactory.types.long
LiteralType.FLOAT -> typeFactory.types.float
return when (this) { LiteralType.DOUBLE -> typeFactory.types.double
JKLiteralExpression.LiteralType.CHAR -> defaultTypeByName("Char") LiteralType.NULL -> typeFactory.types.nullableAny
JKLiteralExpression.LiteralType.BOOLEAN -> defaultTypeByName("Boolean") LiteralType.STRING -> typeFactory.types.string
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( class JKLocalVariableImpl(
@@ -553,7 +543,7 @@ class JKAnnotationImpl(
class JKTypeArgumentListImpl(typeArguments: List<JKTypeElement> = emptyList()) : JKTypeArgumentList, JKBranchElementBase(), class JKTypeArgumentListImpl(typeArguments: List<JKTypeElement> = emptyList()) : JKTypeArgumentList, JKBranchElementBase(),
PsiOwner by PsiOwnerImpl() { PsiOwner by PsiOwnerImpl() {
override val typeArguments: List<JKTypeElement> by children(typeArguments) override var typeArguments: List<JKTypeElement> by children(typeArguments)
override fun accept(visitor: JKVisitor) = visitor.visitTypeArgumentList(this) override fun accept(visitor: JKVisitor) = visitor.visitTypeArgumentList(this)
} }
@@ -26,6 +26,9 @@ import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.* import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.nj2k.types.JKJavaArrayType
import org.jetbrains.kotlin.nj2k.types.JKJavaDisjunctionType
import org.jetbrains.kotlin.nj2k.types.JKJavaPrimitiveType
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
class JKJavaFieldImpl( class JKJavaFieldImpl(
@@ -288,7 +291,8 @@ object JKJavaVoidType : JKType {
set(it) {} set(it) {}
} }
data class JKJavaArrayTypeImpl(override val type: JKType, override var nullability: Nullability = Nullability.Default) : JKJavaArrayType { data class JKJavaArrayTypeImpl(override val type: JKType, override var nullability: Nullability = Nullability.Default) :
JKJavaArrayType {
} }
class JKJavaDisjunctionTypeImpl( class JKJavaDisjunctionTypeImpl(
@@ -44,7 +44,7 @@ abstract class JKEmptyClassBody : JKClassBody() {
} }
interface JKJavaNewExpression : JKExpression, JKTypeArgumentListOwner, PsiOwner { interface JKJavaNewExpression : JKExpression, JKTypeArgumentListOwner, PsiOwner {
val classSymbol: JKClassSymbol var classSymbol: JKClassSymbol
var arguments: JKArgumentList var arguments: JKArgumentList
var classBody: JKClassBody var classBody: JKClassBody
} }
@@ -5,159 +5,88 @@
package org.jetbrains.kotlin.nj2k.tree package org.jetbrains.kotlin.nj2k.tree
import com.intellij.psi.* import com.intellij.psi.CommonClassNames
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName 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.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.nj2k.JKSymbolProvider import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.kotlinTypeByName import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.* import org.jetbrains.kotlin.nj2k.symbols.JKMultiverseClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKMultiverseKtClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseClassSymbol
import org.jetbrains.kotlin.nj2k.tree.impl.* import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType 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.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun JKExpression.type(symbolProvider: JKSymbolProvider): JKType? = fun JKExpression.type(typeFactory: JKTypeFactory): JKType? =
when (this) { when (this) {
is JKLiteralExpression -> type.toJkType(symbolProvider) is JKLiteralExpression -> type.toJkType(typeFactory)
is JKOperatorExpression -> { is JKOperatorExpression -> {
val operator = operator when (val operator = operator) {
when (operator) {
is JKKtOperatorImpl -> operator.returnType is JKKtOperatorImpl -> operator.returnType
is JKKtSpreadOperator -> (this as JKPrefixExpression).expression.type(symbolProvider)//TODO ger real type 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") else -> error("Cannot get type of ${operator::class}, it should be first converted to KtOperator")
} }
} }
is JKMethodCallExpression -> identifier.returnType is JKMethodCallExpression -> identifier.returnType
is JKFieldAccessExpressionImpl -> identifier.fieldType is JKFieldAccessExpressionImpl -> identifier.fieldType
is JKQualifiedExpressionImpl -> selector.type(symbolProvider) is JKQualifiedExpressionImpl -> selector.type(typeFactory)
is JKKtThrowExpression -> kotlinTypeByName(KotlinBuiltIns.FQ_NAMES.nothing.asString(), symbolProvider) is JKKtThrowExpression -> typeFactory.types.nothing
is JKClassAccessExpression -> is JKClassAccessExpression ->
JKClassTypeImpl(identifier, emptyList(), Nullability.NotNull) JKClassTypeImpl(identifier, emptyList(), Nullability.NotNull)
is JKJavaNewExpression -> JKClassTypeImpl(classSymbol) is JKJavaNewExpression -> JKClassTypeImpl(classSymbol)
is JKKtIsExpression -> kotlinTypeByName(KotlinBuiltIns.FQ_NAMES._boolean.asString(), symbolProvider) is JKKtIsExpression -> typeFactory.types.boolean
is JKParenthesizedExpression -> expression.type(symbolProvider) is JKParenthesizedExpression -> expression.type(typeFactory)
is JKTypeCastExpression -> type.type is JKTypeCastExpression -> type.type
is JKThisExpression -> null// TODO return actual type is JKThisExpression -> null// TODO return actual type
is JKSuperExpression -> null// TODO return actual type is JKSuperExpression -> null// TODO return actual type
is JKStubExpression -> null is JKStubExpression -> null
is JKIfElseExpression -> thenBranch.type(symbolProvider)// TODO return actual type is JKIfElseExpression -> thenBranch.type(typeFactory)// TODO return actual type
is JKArrayAccessExpression -> is JKArrayAccessExpression ->
(expression.type(symbolProvider) as? JKParametrizedType)?.parameters?.lastOrNull() (expression.type(typeFactory) as? JKParametrizedType)?.parameters?.lastOrNull()
is JKClassLiteralExpression -> { is JKClassLiteralExpression -> {
val symbol = when (literalType) { val symbol = when (literalType) {
JKClassLiteralExpression.LiteralType.KOTLIN_CLASS -> JKClassLiteralExpression.LiteralType.KOTLIN_CLASS ->
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()) typeFactory.symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe())
JKClassLiteralExpression.LiteralType.JAVA_CLASS, JKClassLiteralExpression.LiteralType.JAVA_CLASS,
JKClassLiteralExpression.LiteralType.JAVA_PRIMITIVE_CLASS, JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE -> JKClassLiteralExpression.LiteralType.JAVA_PRIMITIVE_CLASS, JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE ->
symbolProvider.provideClassSymbol("java.lang.Class") typeFactory.symbolProvider.provideClassSymbol("java.lang.Class")
} }
JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull) JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull)
} }
is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO
is JKLambdaExpression -> returnType.type is JKLambdaExpression -> returnType.type
is JKLabeledStatement -> is JKLabeledStatement ->
statement.safeAs<JKExpressionStatement>()?.expression?.type(symbolProvider) statement.safeAs<JKExpressionStatement>()?.expression?.type(typeFactory)
is JKMethodReferenceExpression -> JKNoTypeImpl //TODO is JKMethodReferenceExpression -> JKNoTypeImpl //TODO
else -> TODO(this::class.java.toString()) else -> TODO(this::class.java.toString())
} }
fun ClassId.toKtClassType(
symbolProvider: JKSymbolProvider,
nullability: Nullability = Nullability.Default
): JKType =
JKClassTypeImpl(symbolProvider.provideClassSymbol(asSingleFqName()), 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) }
when (target) {
null ->
JKClassTypeImpl(JKUnresolvedClassSymbol(rawType().canonicalText), parameters, nullability)
is PsiTypeParameter ->
JKTypeParameterTypeImpl(symbolProvider.provideDirectSymbol(target) as JKTypeParameterSymbol)
else -> {
JKClassTypeImpl(
target.let { symbolProvider.provideDirectSymbol(it) as JKClassSymbol },
parameters,
nullability
)
}
}
}
is PsiArrayType -> JKJavaArrayTypeImpl(componentType.toJK(symbolProvider, nullability), nullability)
is PsiPrimitiveType -> JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE[presentableText]
?: error("Invalid primitive type $presentableText")
is PsiDisjunctionType ->
JKJavaDisjunctionTypeImpl(disjunctions.map { it.toJK(symbolProvider) })
is PsiWildcardType ->
when {
isExtends ->
JKVarianceTypeParameterTypeImpl(
JKVarianceTypeParameterType.Variance.OUT,
extendsBound.toJK(symbolProvider)
)
isSuper ->
JKVarianceTypeParameterTypeImpl(
JKVarianceTypeParameterType.Variance.IN,
superBound.toJK(symbolProvider)
)
else -> JKStarProjectionTypeImpl()
}
is PsiCapturedWildcardType ->
JKCapturedType(
wildcard.toJK(symbolProvider, nullability) as JKWildCardType,
nullability
)
else -> throw Exception("Invalid PSI ${this::class.java}")
}
}
fun JKType.asTypeElement() = fun JKType.asTypeElement() =
JKTypeElementImpl(this) JKTypeElementImpl(this)
fun JKClassSymbol.asType(nullability: Nullability = Nullability.Default): JKClassType = fun JKClassSymbol.asType(nullability: Nullability = Nullability.Default): JKClassType =
JKClassTypeImpl(this, emptyList(), nullability) JKClassTypeImpl(this, emptyList(), nullability)
fun JKType.isSubtypeOf(other: JKType, symbolProvider: JKSymbolProvider): Boolean = fun JKType.isSubtypeOf(other: JKType, typeFactory: JKTypeFactory): Boolean =
other.toKtType(symbolProvider) other.toKtType(typeFactory)
?.let { otherType -> this.toKtType(symbolProvider)?.isSubtypeOf(otherType) } == true ?.let { otherType -> this.toKtType(typeFactory)?.isSubtypeOf(otherType) } == true
fun KotlinType.toJK(symbolProvider: JKSymbolProvider): JKType {
return when (val descriptor = constructor.declarationDescriptor) {
is TypeParameterDescriptor ->
JKTypeParameterTypeImpl(
symbolProvider.provideDirectSymbol(descriptor.findPsi() as? KtTypeParameter ?: return JKNoTypeImpl) as JKTypeParameterSymbol
)
else -> JKClassTypeImpl(
symbolProvider.provideClassSymbol(getJetTypeFqName(false)),
arguments.map { it.type.toJK(symbolProvider) },
if (isNullable()) Nullability.Nullable else Nullability.NotNull
)
}
}
val PsiType.isKotlinFunctionalType: Boolean val PsiType.isKotlinFunctionalType: Boolean
get() { get() {
val fqName = safeAs<PsiClassType>()?.resolve()?.getKotlinFqName() ?: return false val fqName = safeAs<PsiClassType>()?.resolve()?.getKotlinFqName() ?: return false
@@ -168,22 +97,17 @@ val PsiType.isKotlinFunctionalType: Boolean
private val functionalTypeRegex = """(kotlin\.jvm\.functions|kotlin)\.Function[\d+]""".toRegex() private val functionalTypeRegex = """(kotlin\.jvm\.functions|kotlin)\.Function[\d+]""".toRegex()
fun KtTypeReference.toJK(symbolProvider: JKSymbolProvider): JKType? = fun KtTypeReference.toJK(typeFactory: JKTypeFactory): JKType? =
analyze(BodyResolveMode.PARTIAL) analyze(BodyResolveMode.PARTIAL)
.get(BindingContext.TYPE, this) .get(BindingContext.TYPE, this)
?.toJK(symbolProvider) ?.let { typeFactory.fromKotlinType(it) }
fun JKType.toKtType(symbolProvider: JKSymbolProvider): KotlinType? = fun JKType.toKtType(typeFactory: JKTypeFactory): KotlinType? = when (this) {
when (this) { is JKClassType -> classReference.toKtType()
is JKClassType -> classReference.toKtType() is JKJavaPrimitiveType -> typeFactory.fromPrimitiveType(this).toKtType(typeFactory)
is JKJavaPrimitiveType -> else -> null
kotlinTypeByName( }
jvmPrimitiveType.primitiveType.typeFqName.asString(),
symbolProvider
).toKtType(symbolProvider)
else -> null
}
infix fun JKJavaPrimitiveType.isStrongerThan(other: JKJavaPrimitiveType) = infix fun JKJavaPrimitiveType.isStrongerThan(other: JKJavaPrimitiveType) =
jvmPrimitiveTypesPriority.getValue(this.jvmPrimitiveType.primitiveType) > jvmPrimitiveTypesPriority.getValue(this.jvmPrimitiveType.primitiveType) >
@@ -274,27 +198,15 @@ fun JKClassSymbol.isStringType(): Boolean =
fqName == CommonClassNames.JAVA_LANG_STRING fqName == CommonClassNames.JAVA_LANG_STRING
|| fqName == KotlinBuiltIns.FQ_NAMES.string.asString() || fqName == KotlinBuiltIns.FQ_NAMES.string.asString()
fun JKLiteralExpression.LiteralType.toPrimitiveType(): JKJavaPrimitiveType? =
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
JKLiteralExpression.LiteralType.STRING -> null
JKLiteralExpression.LiteralType.NULL -> null
}
fun JKJavaPrimitiveType.toLiteralType(): JKLiteralExpression.LiteralType? = fun JKJavaPrimitiveType.toLiteralType(): JKLiteralExpression.LiteralType? =
when (this) { when (this) {
JKJavaPrimitiveTypeImpl.CHAR -> JKLiteralExpression.LiteralType.CHAR JKJavaPrimitiveType.CHAR -> JKLiteralExpression.LiteralType.CHAR
JKJavaPrimitiveTypeImpl.BOOLEAN -> JKLiteralExpression.LiteralType.BOOLEAN JKJavaPrimitiveType.BOOLEAN -> JKLiteralExpression.LiteralType.BOOLEAN
JKJavaPrimitiveTypeImpl.INT -> JKLiteralExpression.LiteralType.INT JKJavaPrimitiveType.INT -> JKLiteralExpression.LiteralType.INT
JKJavaPrimitiveTypeImpl.LONG -> JKLiteralExpression.LiteralType.LONG JKJavaPrimitiveType.LONG -> JKLiteralExpression.LiteralType.LONG
JKJavaPrimitiveTypeImpl.CHAR -> JKLiteralExpression.LiteralType.CHAR JKJavaPrimitiveType.CHAR -> JKLiteralExpression.LiteralType.CHAR
JKJavaPrimitiveTypeImpl.DOUBLE -> JKLiteralExpression.LiteralType.DOUBLE JKJavaPrimitiveType.DOUBLE -> JKLiteralExpression.LiteralType.DOUBLE
JKJavaPrimitiveTypeImpl.FLOAT -> JKLiteralExpression.LiteralType.FLOAT JKJavaPrimitiveType.FLOAT -> JKLiteralExpression.LiteralType.FLOAT
else -> null else -> null
} }
@@ -314,29 +226,10 @@ fun JKType.asPrimitiveType(): JKJavaPrimitiveType? =
} }
fun JKJavaPrimitiveType.isNumberType() = fun JKJavaPrimitiveType.isNumberType() =
this == JKJavaPrimitiveTypeImpl.INT || this == JKJavaPrimitiveType.INT ||
this == JKJavaPrimitiveTypeImpl.LONG || this == JKJavaPrimitiveType.LONG ||
this == JKJavaPrimitiveTypeImpl.FLOAT || this == JKJavaPrimitiveType.FLOAT ||
this == JKJavaPrimitiveTypeImpl.DOUBLE this == JKJavaPrimitiveType.DOUBLE
inline fun <reified T : JKType> T.addTypeParametersToRawProjectionType(typeParameter: JKType): T =
if (this is JKClassType && parameters.isEmpty()) {
val parametersCount = classReference.expectedTypeParametersCount()
val typeParameters = List(parametersCount) { typeParameter }
JKClassTypeImpl(
classReference,
typeParameters,
nullability
) as T
} else this
fun JKClassSymbol.expectedTypeParametersCount(): Int =
when (val resolvedClass = target) {
is PsiClass -> resolvedClass.typeParameters.size
is KtClass -> resolvedClass.typeParameters.size
is JKClass -> resolvedClass.typeParameterList.typeParameters.size
else -> 0
}
val primitiveTypes = val primitiveTypes =
@@ -0,0 +1,126 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.nj2k.types
import com.intellij.psi.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.nj2k.JKSymbolProvider
import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKTypeParameterSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedClassSymbol
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isNullable
class JKTypeFactory(val symbolProvider: JKSymbolProvider) {
fun fromPsiType(type: PsiType): JKType = createPsiType(type)
fun fromKotlinType(type: KotlinType): JKType = createKotlinType(type)
inner class DefaultTypes {
private fun typeByFqName(
fqName: FqNameUnsafe,
typeArguments: List<JKType> = emptyList(),
nullability: Nullability = Nullability.NotNull
) = JKClassType(
symbolProvider.provideClassSymbol(fqName),
typeArguments,
nullability
)
val boolean = typeByFqName(KotlinBuiltIns.FQ_NAMES._boolean)
val char = typeByFqName(KotlinBuiltIns.FQ_NAMES._char)
val byte = typeByFqName(KotlinBuiltIns.FQ_NAMES._byte)
val short = typeByFqName(KotlinBuiltIns.FQ_NAMES._short)
val int = typeByFqName(KotlinBuiltIns.FQ_NAMES._int)
val float = typeByFqName(KotlinBuiltIns.FQ_NAMES._float)
val long = typeByFqName(KotlinBuiltIns.FQ_NAMES._long)
val double = typeByFqName(KotlinBuiltIns.FQ_NAMES._double)
val string = typeByFqName(KotlinBuiltIns.FQ_NAMES.string)
val possiblyNullString = typeByFqName(KotlinBuiltIns.FQ_NAMES.string, nullability = Nullability.Default)
val unit = typeByFqName(KotlinBuiltIns.FQ_NAMES.unit)
val nothing = typeByFqName(KotlinBuiltIns.FQ_NAMES.nothing)
val nullableAny = typeByFqName(KotlinBuiltIns.FQ_NAMES.any, nullability = Nullability.Nullable)
}
fun fromPrimitiveType(primitiveType: JKJavaPrimitiveType) = when (primitiveType.jvmPrimitiveType) {
JvmPrimitiveType.BOOLEAN -> types.boolean
JvmPrimitiveType.CHAR -> types.char
JvmPrimitiveType.BYTE -> types.byte
JvmPrimitiveType.SHORT -> types.short
JvmPrimitiveType.INT -> types.int
JvmPrimitiveType.FLOAT -> types.float
JvmPrimitiveType.LONG -> types.long
JvmPrimitiveType.DOUBLE -> types.double
}
val types by lazy(LazyThreadSafetyMode.NONE) { DefaultTypes() }
private fun createPsiType(type: PsiType): JKType = when (type) {
is PsiClassType -> {
val target = type.resolve()
val parameters = type.parameters.map { fromPsiType(it) }
when (target) {
null ->
JKClassType(JKUnresolvedClassSymbol(type.rawType().canonicalText, this), parameters)
is PsiTypeParameter ->
JKTypeParameterType(symbolProvider.provideDirectSymbol(target) as JKTypeParameterSymbol)
else -> {
JKClassType(
target.let { symbolProvider.provideDirectSymbol(it) as JKClassSymbol },
parameters
)
}
}
}
is PsiArrayType -> JKJavaArrayType(fromPsiType(type.componentType))
is PsiPrimitiveType -> JKJavaPrimitiveType.KEYWORD_TO_INSTANCE[type.presentableText]
?: error("Invalid primitive type ${type.presentableText}")
is PsiDisjunctionType ->
JKJavaDisjunctionType(type.disjunctions.map { fromPsiType(it) })
is PsiWildcardType ->
when {
type.isExtends ->
JKVarianceTypeParameterType(
JKVarianceTypeParameterType.Variance.OUT,
fromPsiType(type.extendsBound)
)
type.isSuper ->
JKVarianceTypeParameterType(
JKVarianceTypeParameterType.Variance.IN,
fromPsiType(type.superBound)
)
else -> JKStarProjectionTypeImpl
}
is PsiCapturedWildcardType ->
JKCapturedType(fromPsiType(type.wildcard) as JKWildCardType)
else -> throw Exception("Invalid PSI ${this::class.java}")
}
private fun createKotlinType(type: KotlinType): JKType {
return when (val descriptor = type.constructor.declarationDescriptor) {
is TypeParameterDescriptor ->
JKTypeParameterType(
symbolProvider.provideDirectSymbol(
descriptor.findPsi() as? KtTypeParameter ?: return JKNoType
) as JKTypeParameterSymbol
)
else -> JKClassType(
symbolProvider.provideClassSymbol(type.getJetTypeFqName(false)),//TODO constructor fqName
type.arguments.map { fromKotlinType(it.type) },
if (type.isNullable()) Nullability.Nullable else Nullability.NotNull
)
}
}
}
@@ -3,11 +3,12 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.nj2k.tree package org.jetbrains.kotlin.nj2k.types
import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
import org.jetbrains.kotlin.nj2k.symbols.JKTypeParameterSymbol import org.jetbrains.kotlin.nj2k.symbols.JKTypeParameterSymbol
import org.jetbrains.kotlin.nj2k.tree.JKType
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
interface JKWildCardType : JKType interface JKWildCardType : JKType