New J2K: move helper functions to corresponding files & use better names for tree nodes files
This commit is contained in:
-1
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.inference.common
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.nj2k.inference.common.collectors.ConstraintsCollector
|
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.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
|
|||||||
@@ -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 <reified T : JKElement> JKElement.parentOfType(): T? {
|
|
||||||
return generateSequence(parent) { it.parent }.filterIsInstance<T>().firstOrNull()
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.nj2k.conversions
|
package org.jetbrains.kotlin.nj2k.conversions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.*
|
import org.jetbrains.kotlin.nj2k.tree.impl.*
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.nj2k.conversions
|
package org.jetbrains.kotlin.nj2k.conversions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKKtConstructorImpl
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKKtConstructorImpl
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKStubExpressionImpl
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKStubExpressionImpl
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions
|
|||||||
|
|
||||||
import com.intellij.psi.PsiEnumConstant
|
import com.intellij.psi.PsiEnumConstant
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.symbols.*
|
import org.jetbrains.kotlin.nj2k.symbols.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKClassAccessExpressionImpl
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKClassAccessExpressionImpl
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.findUsages
|
import org.jetbrains.kotlin.nj2k.findUsages
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol
|
import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKBooleanLiteral
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKBooleanLiteral
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions
|
|||||||
|
|
||||||
import com.intellij.psi.PsiMember
|
import com.intellij.psi.PsiMember
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.psi
|
import org.jetbrains.kotlin.nj2k.tree.impl.psi
|
||||||
import org.jetbrains.kotlin.nj2k.visibility
|
import org.jetbrains.kotlin.nj2k.visibility
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.nj2k.conversions
|
|||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKOtherModifierElementImpl
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKOtherModifierElementImpl
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.psi
|
import org.jetbrains.kotlin.nj2k.tree.impl.psi
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.nj2k.conversions
|
package org.jetbrains.kotlin.nj2k.conversions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
|
|
||||||
class RemoveWrongExtraModifiersForSingleFunctionsConversion : RecursiveApplicableConversionBase() {
|
class RemoveWrongExtraModifiersForSingleFunctionsConversion : RecursiveApplicableConversionBase() {
|
||||||
|
|||||||
-1
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.nj2k.conversions
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.nj2k.asStatement
|
import org.jetbrains.kotlin.nj2k.asStatement
|
||||||
import org.jetbrains.kotlin.nj2k.copyTreeAndDetach
|
import org.jetbrains.kotlin.nj2k.copyTreeAndDetach
|
||||||
import org.jetbrains.kotlin.nj2k.parentOfType
|
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKLabelTextImpl
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKLabelTextImpl
|
||||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKLabeledStatementImpl
|
import org.jetbrains.kotlin.nj2k.tree.impl.JKLabeledStatementImpl
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.j2k.getContainingClass
|
|||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.asQualifierWithThisAsSelector
|
import org.jetbrains.kotlin.nj2k.asQualifierWithThisAsSelector
|
||||||
import org.jetbrains.kotlin.nj2k.copyTreeAndDetach
|
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.JKClassSymbol
|
||||||
import org.jetbrains.kotlin.nj2k.symbols.JKSymbol
|
import org.jetbrains.kotlin.nj2k.symbols.JKSymbol
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import com.intellij.psi.PsiMember
|
|||||||
import com.intellij.psi.PsiNamedElement
|
import com.intellij.psi.PsiNamedElement
|
||||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||||
import org.jetbrains.kotlin.nj2k.JKSymbolProvider
|
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.JKDeclaration
|
||||||
import org.jetbrains.kotlin.nj2k.tree.JKFile
|
import org.jetbrains.kotlin.nj2k.tree.JKFile
|
||||||
|
import org.jetbrains.kotlin.nj2k.tree.parentOfType
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
|||||||
@@ -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<Any>
|
||||||
|
|
||||||
|
val valid: Boolean
|
||||||
|
fun invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JKType {
|
||||||
|
val nullability: Nullability
|
||||||
|
}
|
||||||
+3
-95
@@ -16,105 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.nj2k.tree
|
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.nj2k.tree.impl.JKBranchElementBase
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
|
||||||
import kotlin.jvm.internal.CallableReference
|
import kotlin.jvm.internal.CallableReference
|
||||||
import kotlin.reflect.KProperty0
|
import kotlin.reflect.KProperty0
|
||||||
|
|
||||||
interface JKOperator {
|
|
||||||
val token: JKOperatorToken
|
|
||||||
val precedence: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
interface JKOperatorToken {
|
inline fun <reified T : JKElement> JKElement.parentOfType(): T? {
|
||||||
val text: String
|
return generateSequence(parent) { it.parent }.filterIsInstance<T>().firstOrNull()
|
||||||
}
|
|
||||||
|
|
||||||
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<Any>
|
|
||||||
|
|
||||||
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<JKType>
|
|
||||||
}
|
|
||||||
|
|
||||||
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<JKType>
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> JKElement.getParentOfType(): T? {
|
|
||||||
var p = parent
|
|
||||||
while (true) {
|
|
||||||
if (p is T || p == null)
|
|
||||||
return p as? T
|
|
||||||
p = p.parent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : JKElement> KProperty0<Any>.detach(element: T) {
|
private fun <T : JKElement> KProperty0<Any>.detach(element: T) {
|
||||||
@@ -126,6 +34,7 @@ private fun <T : JKElement> KProperty0<Any>.detach(element: T) {
|
|||||||
element.detach(boundReceiver)
|
element.detach(boundReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun <T : JKElement> KProperty0<T>.detached(): T =
|
fun <T : JKElement> KProperty0<T>.detached(): T =
|
||||||
get().also { detach(it) }
|
get().also { detach(it) }
|
||||||
|
|
||||||
@@ -138,7 +47,6 @@ fun <T : JKElement> T.detached(from: JKElement): T =
|
|||||||
fun <T : JKBranchElement> T.invalidated(): T =
|
fun <T : JKBranchElement> T.invalidated(): T =
|
||||||
also { it.invalidate() }
|
also { it.invalidate() }
|
||||||
|
|
||||||
|
|
||||||
fun <R : JKTreeElement, T> applyRecursive(
|
fun <R : JKTreeElement, T> applyRecursive(
|
||||||
element: R,
|
element: R,
|
||||||
data: T,
|
data: T,
|
||||||
@@ -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.
|
* 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.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.j2k.ast.Nullability
|
||||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.nj2k.symbols.JKTypeParameterSymbol
|
||||||
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.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? =
|
interface JKWildCardType : 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<JKExpressionStatement>()?.expression?.type(symbolProvider)
|
|
||||||
is JKMethodReferenceExpression -> JKNoTypeImpl //TODO
|
|
||||||
else -> TODO(this::class.java.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ClassId.toKtClassType(
|
interface JKVarianceTypeParameterType : JKWildCardType {
|
||||||
symbolProvider: JKSymbolProvider,
|
val variance: Variance
|
||||||
nullability: Nullability = Nullability.Default
|
val boundType: JKType
|
||||||
): JKType =
|
override val nullability: Nullability
|
||||||
JKClassTypeImpl(symbolProvider.provideClassSymbol(asSingleFqName()), emptyList(), nullability)
|
get() = Nullability.Default
|
||||||
|
|
||||||
|
enum class Variance {
|
||||||
fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Default): JKType {
|
IN, OUT
|
||||||
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}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface JKTypeParameterType : JKType {
|
||||||
fun JKType.asTypeElement() =
|
val identifier: JKTypeParameterSymbol
|
||||||
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
|
interface JKNoType : JKType
|
||||||
get() {
|
|
||||||
val fqName = safeAs<PsiClassType>()?.resolve()?.getKotlinFqName() ?: return false
|
|
||||||
return functionalTypeRegex.matches(fqName.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
interface JKParametrizedType : JKType {
|
||||||
private val functionalTypeRegex = """(kotlin\.jvm\.functions|kotlin)\.Function[\d+]""".toRegex()
|
val parameters: List<JKType>
|
||||||
|
|
||||||
|
|
||||||
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<PsiClass>()?.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 =
|
interface JKClassType : JKParametrizedType {
|
||||||
transform(this) ?: when (this) {
|
val classReference: JKClassSymbol
|
||||||
is JKTypeParameterTypeImpl -> this
|
override val nullability: Nullability
|
||||||
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 <reified T : JKType> 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 : JKType> 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 <reified T : JKType> T.addTypeParametersToRawProjectionType(typeParameter: JKType): T =
|
|
||||||
if (this is JKClassType && parameters.isEmpty()) {
|
|
||||||
val parametersCount = classReference.expectedTypeParametersCount()
|
|
||||||
val typeParameters = List(parametersCount) { typeParameter }
|
|
||||||
JKClassTypeImpl(
|
|
||||||
classReference,
|
|
||||||
typeParameters,
|
|
||||||
nullability
|
|
||||||
) as T
|
|
||||||
} else this
|
|
||||||
|
|
||||||
fun JKClassSymbol.expectedTypeParametersCount(): Int =
|
|
||||||
when (val resolvedClass = target) {
|
|
||||||
is PsiClass -> resolvedClass.typeParameters.size
|
|
||||||
is KtClass -> resolvedClass.typeParameters.size
|
|
||||||
is JKClass -> resolvedClass.typeParameterList.typeParameters.size
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val primitiveTypes =
|
|
||||||
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<JKJavaPrimitiveType>()
|
|
||||||
.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 =
|
interface JKJavaPrimitiveType : JKType {
|
||||||
(this as? JKClassType)?.classReference?.isInterface() ?: false
|
val jvmPrimitiveType: JvmPrimitiveType
|
||||||
|
override val nullability: Nullability
|
||||||
|
get() = Nullability.NotNull
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JKJavaArrayType : JKType {
|
||||||
|
val type: JKType
|
||||||
|
}
|
||||||
|
|
||||||
fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType =
|
interface JKStarProjectionType : JKWildCardType {
|
||||||
applyRecursive { type ->
|
override val nullability: Nullability
|
||||||
if (type is JKClassType && type.classReference.fqName == "java.lang.Class") {
|
get() = Nullability.NotNull
|
||||||
JKClassTypeImpl(
|
}
|
||||||
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()),
|
|
||||||
type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) },
|
interface JKJavaDisjunctionType : JKType {
|
||||||
Nullability.NotNull
|
val disjunctions: List<JKType>
|
||||||
)
|
}
|
||||||
} else null
|
|
||||||
}
|
|
||||||
@@ -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<JKExpressionStatement>()?.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<PsiClassType>()?.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<PsiClass>()?.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 <reified T : JKType> 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 : JKType> 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 <reified T : JKType> T.addTypeParametersToRawProjectionType(typeParameter: JKType): T =
|
||||||
|
if (this is JKClassType && parameters.isEmpty()) {
|
||||||
|
val parametersCount = classReference.expectedTypeParametersCount()
|
||||||
|
val typeParameters = List(parametersCount) { typeParameter }
|
||||||
|
JKClassTypeImpl(
|
||||||
|
classReference,
|
||||||
|
typeParameters,
|
||||||
|
nullability
|
||||||
|
) as T
|
||||||
|
} else this
|
||||||
|
|
||||||
|
fun JKClassSymbol.expectedTypeParametersCount(): Int =
|
||||||
|
when (val resolvedClass = target) {
|
||||||
|
is PsiClass -> resolvedClass.typeParameters.size
|
||||||
|
is KtClass -> resolvedClass.typeParameters.size
|
||||||
|
is JKClass -> resolvedClass.typeParameterList.typeParameters.size
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val primitiveTypes =
|
||||||
|
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<JKJavaPrimitiveType>()
|
||||||
|
.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
|
||||||
|
}
|
||||||
@@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.nj2k
|
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.KtKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
@@ -19,11 +16,6 @@ fun <T> List<T>.replace(element: T, replacer: T): List<T> {
|
|||||||
return mutableList
|
return mutableList
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.parentOfType(): T? =
|
|
||||||
PsiTreeUtil.getParentOfType(this, T::class.java)
|
|
||||||
|
|
||||||
inline fun <reified T : PsiElement> PsiElement.parentsOfType(): Sequence<T> = parentsOfType(T::class.java)
|
|
||||||
|
|
||||||
fun String.asGetterName() =
|
fun String.asGetterName() =
|
||||||
takeIf { JvmAbi.isGetterName(it) }
|
takeIf { JvmAbi.isGetterName(it) }
|
||||||
?.removePrefix("get")
|
?.removePrefix("get")
|
||||||
|
|||||||
Reference in New Issue
Block a user