diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt index 9c04b83453b..765d264e86d 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.inference.common import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.nj2k.inference.common.collectors.ConstraintsCollector -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtImportDirective import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ASTWalk.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ASTWalk.kt deleted file mode 100644 index edc9c2a9013..00000000000 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ASTWalk.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2010-2018 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.conversions - -import org.jetbrains.kotlin.nj2k.tree.JKElement - -inline fun JKElement.parentOfType(): T? { - return generateSequence(parent) { it.parent }.filterIsInstance().firstOrNull() -} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/BlockToRunConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/BlockToRunConversion.kt index 811ebf0c460..9d01171fc70 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/BlockToRunConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/BlockToRunConversion.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.nj2k.conversions import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.* diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ConstructorConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ConstructorConversion.kt index 911d2ecdf2e..ee3ee939b11 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ConstructorConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ConstructorConversion.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.nj2k.conversions import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.JKKtConstructorImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKStubExpressionImpl diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt index 6b0b7fcdf71..263c0e7783b 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions import com.intellij.psi.PsiEnumConstant import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.symbols.* import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.JKClassAccessExpressionImpl diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ImplicitInitializerConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ImplicitInitializerConversion.kt index b7ac8500890..5344615e7cb 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ImplicitInitializerConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ImplicitInitializerConversion.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.findUsages -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.JKBooleanLiteral diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/InternalDeclarationConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/InternalDeclarationConversion.kt index f8aa0285be2..5a9999a5ca1 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/InternalDeclarationConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/InternalDeclarationConversion.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions import com.intellij.psi.PsiMember import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.psi import org.jetbrains.kotlin.nj2k.visibility diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ModalityConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ModalityConversion.kt index 654c71b0891..d42b2482be3 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ModalityConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ModalityConversion.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.nj2k.conversions import com.intellij.psi.PsiClass import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.JKOtherModifierElementImpl import org.jetbrains.kotlin.nj2k.tree.impl.psi diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveWrongExtraModifiersForSingleFunctionsConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveWrongExtraModifiersForSingleFunctionsConversion.kt index 5b5f8b90057..a697772d11f 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveWrongExtraModifiersForSingleFunctionsConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveWrongExtraModifiersForSingleFunctionsConversion.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.nj2k.conversions -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.tree.* class RemoveWrongExtraModifiersForSingleFunctionsConversion : RecursiveApplicableConversionBase() { diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt index 6fa918aea2a..c294710325e 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/ReturnStatementInLambdaExpressionConversion.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions import org.jetbrains.kotlin.nj2k.asStatement import org.jetbrains.kotlin.nj2k.copyTreeAndDetach -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.impl.JKLabelTextImpl import org.jetbrains.kotlin.nj2k.tree.impl.JKLabeledStatementImpl diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt index 87f9d300183..fb419271f58 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.j2k.getContainingClass import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.asQualifierWithThisAsSelector import org.jetbrains.kotlin.nj2k.copyTreeAndDetach -import org.jetbrains.kotlin.nj2k.parentOfType import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol import org.jetbrains.kotlin.nj2k.symbols.JKSymbol import org.jetbrains.kotlin.nj2k.tree.* diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt index 2b4f463ce10..37705ce5e02 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt @@ -10,9 +10,9 @@ import com.intellij.psi.PsiMember import com.intellij.psi.PsiNamedElement import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.nj2k.JKSymbolProvider -import org.jetbrains.kotlin.nj2k.parentOfType 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.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/base.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/base.kt new file mode 100644 index 00000000000..86b2f8b6d2b --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/base.kt @@ -0,0 +1,43 @@ +/* + * 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.tree + +import org.jetbrains.kotlin.j2k.ast.Nullability + +interface JKOperator { + val token: JKOperatorToken + val precedence: Int +} + +interface JKOperatorToken { + val text: String +} + +interface JKKtOperatorToken : JKOperatorToken { + val operatorName: String +} + +interface JKQualifier + +interface JKElement { + val parent: JKElement? + + fun detach(from: JKElement) + + fun attach(to: JKElement) +} + + +interface JKBranchElement : JKElement { + val children: List + + val valid: Boolean + fun invalidate() +} + +interface JKType { + val nullability: Nullability +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/jk.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/javaAndKotlinElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/jk.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/javaAndKotlinElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/j.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/javaElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/j.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/javaElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/k.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/kotlinElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/k.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/kotlinElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/tokens.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/tokenElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/tokens.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/impl/tokenElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/jk.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/javaAndKotlinElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/jk.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/javaAndKotlinElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/j.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/javaElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/j.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/javaElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/k.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/kotlinElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/k.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/kotlinElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/tokens.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/tokensElements.kt similarity index 100% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/tokens.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/tokensElements.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/markers.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/treeUtils.kt similarity index 61% rename from nj2k/src/org/jetbrains/kotlin/nj2k/tree/markers.kt rename to nj2k/src/org/jetbrains/kotlin/nj2k/tree/treeUtils.kt index aa846e6edfe..35c40b639fb 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/markers.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/treeUtils.kt @@ -16,105 +16,13 @@ package org.jetbrains.kotlin.nj2k.tree -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.impl.JKBranchElementBase -import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import kotlin.jvm.internal.CallableReference import kotlin.reflect.KProperty0 -interface JKOperator { - val token: JKOperatorToken - val precedence: Int -} -interface JKOperatorToken { - val text: String -} - -interface JKKtOperatorToken : JKOperatorToken { - val operatorName: String -} - -interface JKQualifier - -interface JKElement { - val parent: JKElement? - - fun detach(from: JKElement) - - fun attach(to: JKElement) -} - -interface JKBranchElement : JKElement { - val children: List - - val valid: Boolean - fun invalidate() -} - -interface JKType { - val nullability: Nullability -} - -fun JKType.isNullable(): Boolean = - nullability != Nullability.NotNull - -interface JKWildCardType : JKType - -interface JKVarianceTypeParameterType : JKWildCardType { - val variance: Variance - val boundType: JKType - override val nullability: Nullability - get() = Nullability.Default - - enum class Variance { - IN, OUT - } -} - -interface JKTypeParameterType : JKType { - val identifier: JKTypeParameterSymbol -} - -interface JKNoType : JKType - -interface JKParametrizedType : JKType { - val parameters: List -} - -interface JKClassType : JKParametrizedType { - val classReference: JKClassSymbol - override val nullability: Nullability -} - -interface JKJavaPrimitiveType : JKType { - val jvmPrimitiveType: JvmPrimitiveType - override val nullability: Nullability - get() = Nullability.NotNull -} - -interface JKJavaArrayType : JKType { - val type: JKType -} - -interface JKStarProjectionType : JKWildCardType { - override val nullability: Nullability - get() = Nullability.NotNull -} - -interface JKJavaDisjunctionType : JKType { - val disjunctions: List -} - -inline fun JKElement.getParentOfType(): T? { - var p = parent - while (true) { - if (p is T || p == null) - return p as? T - p = p.parent - } +inline fun JKElement.parentOfType(): T? { + return generateSequence(parent) { it.parent }.filterIsInstance().firstOrNull() } private fun KProperty0.detach(element: T) { @@ -126,6 +34,7 @@ private fun KProperty0.detach(element: T) { element.detach(boundReceiver) } + fun KProperty0.detached(): T = get().also { detach(it) } @@ -138,7 +47,6 @@ fun T.detached(from: JKElement): T = fun T.invalidated(): T = also { it.invalidate() } - fun applyRecursive( element: R, data: T, diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/types.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/types.kt index fde74d94d82..fc8a3b3d0eb 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/types.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/types.kt @@ -1,406 +1,58 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.tree -import com.intellij.psi.* -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.tree.impl.* -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.nj2k.symbols.JKClassSymbol +import org.jetbrains.kotlin.nj2k.symbols.JKTypeParameterSymbol 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? = - when (this) { - is JKLiteralExpression -> type.toJkType(symbolProvider) - is JKOperatorExpression -> { - val operator = operator - when (operator) { - is JKKtOperatorImpl -> operator.returnType - is JKKtSpreadOperator -> (this as JKPrefixExpression).expression.type(symbolProvider)//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 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 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 JKArrayAccessExpression -> - (expression.type(symbolProvider) as? JKParametrizedType)?.parameters?.lastOrNull() - is JKClassLiteralExpression -> { - val symbol = when (literalType) { - JKClassLiteralExpression.LiteralType.KOTLIN_CLASS -> - 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") - } - JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull) - } - is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO - is JKLambdaExpression -> returnType.type - is JKLabeledStatement -> - statement.safeAs()?.expression?.type(symbolProvider) - is JKMethodReferenceExpression -> JKNoTypeImpl //TODO - else -> TODO(this::class.java.toString()) - } +interface JKWildCardType : JKType -fun ClassId.toKtClassType( - symbolProvider: JKSymbolProvider, - nullability: Nullability = Nullability.Default -): JKType = - JKClassTypeImpl(symbolProvider.provideClassSymbol(asSingleFqName()), emptyList(), nullability) +interface JKVarianceTypeParameterType : JKWildCardType { + val variance: Variance + val boundType: JKType + override val nullability: Nullability + get() = Nullability.Default - -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}") + enum class Variance { + IN, OUT } } - -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 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 - ) - } +interface JKTypeParameterType : JKType { + val identifier: JKTypeParameterSymbol } -val PsiType.isKotlinFunctionalType: Boolean - get() { - val fqName = safeAs()?.resolve()?.getKotlinFqName() ?: return false - return functionalTypeRegex.matches(fqName.asString()) - } +interface JKNoType : JKType - -private val functionalTypeRegex = """(kotlin\.jvm\.functions|kotlin)\.Function[\d+]""".toRegex() - - -fun KtTypeReference.toJK(symbolProvider: JKSymbolProvider): JKType? = - analyze(BodyResolveMode.PARTIAL) - .get(BindingContext.TYPE, this) - ?.toJK(symbolProvider) - - -fun JKType.toKtType(symbolProvider: JKSymbolProvider): KotlinType? = - when (this) { - is JKClassType -> classReference.toKtType() - is JKJavaPrimitiveType -> - kotlinTypeByName( - jvmPrimitiveType.primitiveType.typeFqName.asString(), - symbolProvider - ).toKtType(symbolProvider) - else -> null - } - -infix fun JKJavaPrimitiveType.isStrongerThan(other: JKJavaPrimitiveType) = - jvmPrimitiveTypesPriority.getValue(this.jvmPrimitiveType.primitiveType) > - jvmPrimitiveTypesPriority.getValue(other.jvmPrimitiveType.primitiveType) - -private val jvmPrimitiveTypesPriority = - mapOf( - PrimitiveType.BOOLEAN to -1, - PrimitiveType.CHAR to 0, - PrimitiveType.BYTE to 1, - PrimitiveType.SHORT to 2, - PrimitiveType.INT to 3, - PrimitiveType.LONG to 4, - PrimitiveType.FLOAT to 5, - PrimitiveType.DOUBLE to 6 - ) - - -fun JKClassSymbol.toKtType(): KotlinType? { - val classDescriptor = when (this) { - is JKMultiverseKtClassSymbol -> { - val bindingContext = target.analyze() - bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, target] as ClassDescriptor - } - is JKMultiverseClassSymbol -> - target.getJavaClassDescriptor() - is JKUniverseClassSymbol -> - target.psi()?.getJavaClassDescriptor()//TODO null in case of a fake package - else -> TODO(this::class.java.toString()) - } - return classDescriptor?.defaultType +interface JKParametrizedType : JKType { + val parameters: List } -fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType = - transform(this) ?: when (this) { - is JKTypeParameterTypeImpl -> this - is JKClassTypeImpl -> - JKClassTypeImpl( - classReference, - parameters.map { it.applyRecursive(transform) }, - nullability - ) - is JKNoType -> this - is JKJavaVoidType -> this - is JKJavaPrimitiveType -> this - is JKJavaArrayType -> JKJavaArrayTypeImpl(type.applyRecursive(transform), nullability) - is JKContextType -> JKContextType - is JKJavaDisjunctionType -> - JKJavaDisjunctionTypeImpl(disjunctions.map { it.applyRecursive(transform) }, nullability) - is JKStarProjectionType -> this - else -> TODO(this::class.toString()) - } - -inline fun T.updateNullability(newNullability: Nullability): T = - if (nullability == newNullability) this - else when (this) { - is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(identifier, newNullability) - is JKClassTypeImpl -> JKClassTypeImpl(classReference, parameters, newNullability) - is JKNoType -> this - is JKJavaVoidType -> this - is JKJavaPrimitiveType -> this - is JKJavaArrayType -> JKJavaArrayTypeImpl(type, newNullability) - is JKContextType -> JKContextType - is JKJavaDisjunctionType -> this - else -> TODO(this::class.toString()) - } as T - -@Suppress("UNCHECKED_CAST") -fun T.updateNullabilityRecursively(newNullability: Nullability): T = - applyRecursive { - when (it) { - is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(it.identifier, newNullability) - is JKClassTypeImpl -> - JKClassTypeImpl( - it.classReference, - it.parameters.map { it.updateNullabilityRecursively(newNullability) }, - newNullability - ) - is JKJavaArrayType -> JKJavaArrayTypeImpl(it.type.updateNullabilityRecursively(newNullability), newNullability) - else -> null - } - } as T - -fun JKType.isStringType(): Boolean = - (this as? JKClassType)?.classReference?.isStringType() == true - -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 - else -> null - } - - -fun JKType.asPrimitiveType(): JKJavaPrimitiveType? = - if (this is JKJavaPrimitiveType) this - else when ((this as? JKClassType)?.classReference?.fqName) { - KotlinBuiltIns.FQ_NAMES._char.asString(), CommonClassNames.JAVA_LANG_CHARACTER -> JKJavaPrimitiveTypeImpl.CHAR - KotlinBuiltIns.FQ_NAMES._boolean.asString(), CommonClassNames.JAVA_LANG_BOOLEAN -> JKJavaPrimitiveTypeImpl.BOOLEAN - KotlinBuiltIns.FQ_NAMES._int.asString(), CommonClassNames.JAVA_LANG_INTEGER -> JKJavaPrimitiveTypeImpl.INT - KotlinBuiltIns.FQ_NAMES._long.asString(), CommonClassNames.JAVA_LANG_LONG -> JKJavaPrimitiveTypeImpl.LONG - KotlinBuiltIns.FQ_NAMES._float.asString(), CommonClassNames.JAVA_LANG_FLOAT -> JKJavaPrimitiveTypeImpl.FLOAT - KotlinBuiltIns.FQ_NAMES._double.asString(), CommonClassNames.JAVA_LANG_DOUBLE -> JKJavaPrimitiveTypeImpl.DOUBLE - KotlinBuiltIns.FQ_NAMES._byte.asString(), CommonClassNames.JAVA_LANG_BYTE -> JKJavaPrimitiveTypeImpl.BYTE - KotlinBuiltIns.FQ_NAMES._short.asString(), CommonClassNames.JAVA_LANG_SHORT -> JKJavaPrimitiveTypeImpl.SHORT - else -> null - } - -fun JKJavaPrimitiveType.isNumberType() = - this == JKJavaPrimitiveTypeImpl.INT || - this == JKJavaPrimitiveTypeImpl.LONG || - this == JKJavaPrimitiveTypeImpl.FLOAT || - this == JKJavaPrimitiveTypeImpl.DOUBLE - -inline fun 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 = - listOf( - JvmPrimitiveType.BOOLEAN, - JvmPrimitiveType.CHAR, - JvmPrimitiveType.BYTE, - JvmPrimitiveType.SHORT, - JvmPrimitiveType.INT, - JvmPrimitiveType.FLOAT, - JvmPrimitiveType.LONG, - JvmPrimitiveType.DOUBLE - ) - -fun JKType.arrayFqName(): String = - if (this is JKJavaPrimitiveType) - PrimitiveType.valueOf(jvmPrimitiveType.name).arrayTypeFqName.asString() - else KotlinBuiltIns.FQ_NAMES.array.asString() - -fun JKClassSymbol.isArrayType(): Boolean = - fqName in - JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE.values - .filterIsInstance() - .map { PrimitiveType.valueOf(it.jvmPrimitiveType.name).arrayTypeFqName.asString() } + - KotlinBuiltIns.FQ_NAMES.array.asString() - -fun JKType.isArrayType() = - when (this) { - is JKClassType -> classReference.isArrayType() - is JKJavaArrayType -> true - else -> false - } - - -fun JKType.arrayInnerType(): JKType? = - when (this) { - is JKJavaArrayType -> type - is JKClassType -> - if (this.classReference.isArrayType()) this.parameters.singleOrNull() - else null - else -> null - } - -fun JKClassSymbol.isInterface(): Boolean { - val target = target - return when (target) { - is PsiClass -> target.isInterface - is KtClass -> target.isInterface() - is JKClass -> target.classKind == JKClass.ClassKind.INTERFACE - else -> false - } +interface JKClassType : JKParametrizedType { + val classReference: JKClassSymbol + override val nullability: Nullability } -fun JKType.isInterface(): Boolean = - (this as? JKClassType)?.classReference?.isInterface() ?: false +interface JKJavaPrimitiveType : JKType { + val jvmPrimitiveType: JvmPrimitiveType + override val nullability: Nullability + get() = Nullability.NotNull +} +interface JKJavaArrayType : JKType { + val type: JKType +} -fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType = - applyRecursive { type -> - if (type is JKClassType && type.classReference.fqName == "java.lang.Class") { - JKClassTypeImpl( - symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()), - type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) }, - Nullability.NotNull - ) - } else null - } +interface JKStarProjectionType : JKWildCardType { + override val nullability: Nullability + get() = Nullability.NotNull +} + +interface JKJavaDisjunctionType : JKType { + val disjunctions: List +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/typesUtils.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/typesUtils.kt new file mode 100644 index 00000000000..fde74d94d82 --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/typesUtils.kt @@ -0,0 +1,406 @@ +/* + * Copyright 2010-2018 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.tree + +import com.intellij.psi.* +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.tree.impl.* +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? = + when (this) { + is JKLiteralExpression -> type.toJkType(symbolProvider) + is JKOperatorExpression -> { + val operator = operator + when (operator) { + is JKKtOperatorImpl -> operator.returnType + is JKKtSpreadOperator -> (this as JKPrefixExpression).expression.type(symbolProvider)//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 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 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 JKArrayAccessExpression -> + (expression.type(symbolProvider) as? JKParametrizedType)?.parameters?.lastOrNull() + is JKClassLiteralExpression -> { + val symbol = when (literalType) { + JKClassLiteralExpression.LiteralType.KOTLIN_CLASS -> + 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") + } + JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull) + } + is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO + is JKLambdaExpression -> returnType.type + is JKLabeledStatement -> + statement.safeAs()?.expression?.type(symbolProvider) + 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 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()?.resolve()?.getKotlinFqName() ?: return false + return functionalTypeRegex.matches(fqName.asString()) + } + + +private val functionalTypeRegex = """(kotlin\.jvm\.functions|kotlin)\.Function[\d+]""".toRegex() + + +fun KtTypeReference.toJK(symbolProvider: JKSymbolProvider): JKType? = + analyze(BodyResolveMode.PARTIAL) + .get(BindingContext.TYPE, this) + ?.toJK(symbolProvider) + + +fun JKType.toKtType(symbolProvider: JKSymbolProvider): KotlinType? = + when (this) { + is JKClassType -> classReference.toKtType() + is JKJavaPrimitiveType -> + kotlinTypeByName( + jvmPrimitiveType.primitiveType.typeFqName.asString(), + symbolProvider + ).toKtType(symbolProvider) + else -> null + } + +infix fun JKJavaPrimitiveType.isStrongerThan(other: JKJavaPrimitiveType) = + jvmPrimitiveTypesPriority.getValue(this.jvmPrimitiveType.primitiveType) > + jvmPrimitiveTypesPriority.getValue(other.jvmPrimitiveType.primitiveType) + +private val jvmPrimitiveTypesPriority = + mapOf( + PrimitiveType.BOOLEAN to -1, + PrimitiveType.CHAR to 0, + PrimitiveType.BYTE to 1, + PrimitiveType.SHORT to 2, + PrimitiveType.INT to 3, + PrimitiveType.LONG to 4, + PrimitiveType.FLOAT to 5, + PrimitiveType.DOUBLE to 6 + ) + + +fun JKClassSymbol.toKtType(): KotlinType? { + val classDescriptor = when (this) { + is JKMultiverseKtClassSymbol -> { + val bindingContext = target.analyze() + bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, target] as ClassDescriptor + } + is JKMultiverseClassSymbol -> + target.getJavaClassDescriptor() + is JKUniverseClassSymbol -> + target.psi()?.getJavaClassDescriptor()//TODO null in case of a fake package + else -> TODO(this::class.java.toString()) + } + return classDescriptor?.defaultType +} + +fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType = + transform(this) ?: when (this) { + is JKTypeParameterTypeImpl -> this + is JKClassTypeImpl -> + JKClassTypeImpl( + classReference, + parameters.map { it.applyRecursive(transform) }, + nullability + ) + is JKNoType -> this + is JKJavaVoidType -> this + is JKJavaPrimitiveType -> this + is JKJavaArrayType -> JKJavaArrayTypeImpl(type.applyRecursive(transform), nullability) + is JKContextType -> JKContextType + is JKJavaDisjunctionType -> + JKJavaDisjunctionTypeImpl(disjunctions.map { it.applyRecursive(transform) }, nullability) + is JKStarProjectionType -> this + else -> TODO(this::class.toString()) + } + +inline fun T.updateNullability(newNullability: Nullability): T = + if (nullability == newNullability) this + else when (this) { + is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(identifier, newNullability) + is JKClassTypeImpl -> JKClassTypeImpl(classReference, parameters, newNullability) + is JKNoType -> this + is JKJavaVoidType -> this + is JKJavaPrimitiveType -> this + is JKJavaArrayType -> JKJavaArrayTypeImpl(type, newNullability) + is JKContextType -> JKContextType + is JKJavaDisjunctionType -> this + else -> TODO(this::class.toString()) + } as T + +@Suppress("UNCHECKED_CAST") +fun T.updateNullabilityRecursively(newNullability: Nullability): T = + applyRecursive { + when (it) { + is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(it.identifier, newNullability) + is JKClassTypeImpl -> + JKClassTypeImpl( + it.classReference, + it.parameters.map { it.updateNullabilityRecursively(newNullability) }, + newNullability + ) + is JKJavaArrayType -> JKJavaArrayTypeImpl(it.type.updateNullabilityRecursively(newNullability), newNullability) + else -> null + } + } as T + +fun JKType.isStringType(): Boolean = + (this as? JKClassType)?.classReference?.isStringType() == true + +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 + else -> null + } + + +fun JKType.asPrimitiveType(): JKJavaPrimitiveType? = + if (this is JKJavaPrimitiveType) this + else when ((this as? JKClassType)?.classReference?.fqName) { + KotlinBuiltIns.FQ_NAMES._char.asString(), CommonClassNames.JAVA_LANG_CHARACTER -> JKJavaPrimitiveTypeImpl.CHAR + KotlinBuiltIns.FQ_NAMES._boolean.asString(), CommonClassNames.JAVA_LANG_BOOLEAN -> JKJavaPrimitiveTypeImpl.BOOLEAN + KotlinBuiltIns.FQ_NAMES._int.asString(), CommonClassNames.JAVA_LANG_INTEGER -> JKJavaPrimitiveTypeImpl.INT + KotlinBuiltIns.FQ_NAMES._long.asString(), CommonClassNames.JAVA_LANG_LONG -> JKJavaPrimitiveTypeImpl.LONG + KotlinBuiltIns.FQ_NAMES._float.asString(), CommonClassNames.JAVA_LANG_FLOAT -> JKJavaPrimitiveTypeImpl.FLOAT + KotlinBuiltIns.FQ_NAMES._double.asString(), CommonClassNames.JAVA_LANG_DOUBLE -> JKJavaPrimitiveTypeImpl.DOUBLE + KotlinBuiltIns.FQ_NAMES._byte.asString(), CommonClassNames.JAVA_LANG_BYTE -> JKJavaPrimitiveTypeImpl.BYTE + KotlinBuiltIns.FQ_NAMES._short.asString(), CommonClassNames.JAVA_LANG_SHORT -> JKJavaPrimitiveTypeImpl.SHORT + else -> null + } + +fun JKJavaPrimitiveType.isNumberType() = + this == JKJavaPrimitiveTypeImpl.INT || + this == JKJavaPrimitiveTypeImpl.LONG || + this == JKJavaPrimitiveTypeImpl.FLOAT || + this == JKJavaPrimitiveTypeImpl.DOUBLE + +inline fun 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 = + listOf( + JvmPrimitiveType.BOOLEAN, + JvmPrimitiveType.CHAR, + JvmPrimitiveType.BYTE, + JvmPrimitiveType.SHORT, + JvmPrimitiveType.INT, + JvmPrimitiveType.FLOAT, + JvmPrimitiveType.LONG, + JvmPrimitiveType.DOUBLE + ) + +fun JKType.arrayFqName(): String = + if (this is JKJavaPrimitiveType) + PrimitiveType.valueOf(jvmPrimitiveType.name).arrayTypeFqName.asString() + else KotlinBuiltIns.FQ_NAMES.array.asString() + +fun JKClassSymbol.isArrayType(): Boolean = + fqName in + JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE.values + .filterIsInstance() + .map { PrimitiveType.valueOf(it.jvmPrimitiveType.name).arrayTypeFqName.asString() } + + KotlinBuiltIns.FQ_NAMES.array.asString() + +fun JKType.isArrayType() = + when (this) { + is JKClassType -> classReference.isArrayType() + is JKJavaArrayType -> true + else -> false + } + + +fun JKType.arrayInnerType(): JKType? = + when (this) { + is JKJavaArrayType -> type + is JKClassType -> + if (this.classReference.isArrayType()) this.parameters.singleOrNull() + else null + else -> null + } + +fun JKClassSymbol.isInterface(): Boolean { + val target = target + return when (target) { + is PsiClass -> target.isInterface + is KtClass -> target.isInterface() + is JKClass -> target.classKind == JKClass.ClassKind.INTERFACE + else -> false + } +} + +fun JKType.isInterface(): Boolean = + (this as? JKClassType)?.classReference?.isInterface() ?: false + + +fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType = + applyRecursive { type -> + if (type is JKClassType && type.classReference.fqName == "java.lang.Class") { + JKClassTypeImpl( + symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()), + type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) }, + Nullability.NotNull + ) + } else null + } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/utils.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/utils.kt index 8c057adefed..c85e5307d6f 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/utils.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/utils.kt @@ -5,9 +5,6 @@ package org.jetbrains.kotlin.nj2k -import com.intellij.psi.PsiElement -import com.intellij.psi.util.PsiTreeUtil -import com.intellij.psi.util.parentsOfType import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.JvmAbi @@ -19,11 +16,6 @@ fun List.replace(element: T, replacer: T): List { return mutableList } -inline fun PsiElement.parentOfType(): T? = - PsiTreeUtil.getParentOfType(this, T::class.java) - -inline fun PsiElement.parentsOfType(): Sequence = parentsOfType(T::class.java) - fun String.asGetterName() = takeIf { JvmAbi.isGetterName(it) } ?.removePrefix("get")