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