New J2K: use KotlinExceptionWithAttachments to report tree building errors

Also, try not to throw exceptions when possible
This commit is contained in:
Ilya Kirillov
2019-09-25 17:40:48 +03:00
parent 3e2dac6586
commit 392a75e6b8
18 changed files with 93 additions and 74 deletions
@@ -206,7 +206,7 @@ open class BoundTypeCalculatorImpl(
arguments.mapIndexed { i, argument ->
TypeParameter(
argument.type.boundTypeUnenhanced(
typeVariable?.typeParameters?.get(i)?.boundType?.label?.safeAs<TypeVariableLabel>()?.typeVariable,
typeVariable?.typeParameters?.getOrNull(i)?.boundType?.label?.safeAs<TypeVariableLabel>()?.typeVariable,
contextBoundType,
call,
isImplicitReceiver,
@@ -77,7 +77,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
?.returnedExpression
?.unpackedReferenceToProperty()
?.takeIf {
it.type() == this.type()!!
it.type() == type() ?: return@takeIf false
}
return RealGetter(this, target, name)
}
@@ -184,7 +184,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
ktSetter.filterModifiers()
if (setter is RealSetter) {
setter.function.forAllUsages { usage ->
val callExpression = usage.getStrictParentOfType<KtCallExpression>()!!
val callExpression = usage.getStrictParentOfType<KtCallExpression>() ?: return@forAllUsages
val qualifier = callExpression.getQualifiedExpressionForSelector()
val newValue = callExpression.valueArguments.single()
if (qualifier != null) {
@@ -85,7 +85,7 @@ val removeUselessCastDiagnosticBasedProcessing =
val removeInnecessaryNotNullAssertionDiagnosticBasedProcessing =
diagnosticBasedProcessing<KtSimpleNameExpression>(Errors.UNNECESSARY_NOT_NULL_ASSERTION) { element, _ ->
val exclExclExpr = element.parent as KtUnaryExpression
val baseExpression = exclExclExpr.baseExpression!!
val baseExpression = exclExclExpr.baseExpression ?: return@diagnosticBasedProcessing
val context = baseExpression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
if (context.diagnostics.forElement(element).any { it.factory == Errors.UNNECESSARY_NOT_NULL_ASSERTION }) {
exclExclExpr.replace(baseExpression)
@@ -82,7 +82,7 @@ class RemoveRedundantNullabilityProcessing : InspectionLikeProcessingForElement<
override fun apply(element: KtProperty) {
val typeElement = element.typeReference?.typeElement
typeElement?.replace(typeElement.cast<KtNullableType>().innerType!!)
typeElement?.replace(typeElement.safeAs<KtNullableType>()?.innerType ?: return)
}
}
@@ -269,8 +269,8 @@ class JavaObjectEqualsToEqOperatorProcessing : InspectionLikeProcessingForElemen
element.getQualifiedExpressionForSelectorOrThis().replace(
factory.createExpressionByPattern(
"($0 == $1)",
element.valueArguments[0].getArgumentExpression()!!,
element.valueArguments[1].getArgumentExpression()!!
element.valueArguments[0].getArgumentExpression() ?: return,
element.valueArguments[1].getArgumentExpression() ?: return
)
)
}
@@ -312,7 +312,7 @@ class RemoveRedundantModalityModifierProcessing : InspectionLikeProcessingForEle
}
override fun apply(element: KtDeclaration) {
element.removeModifier(element.modalityModifierType()!!)
element.removeModifier(element.modalityModifierType() ?: return)
}
}
@@ -329,7 +329,7 @@ class RemoveRedundantVisibilityModifierProcessing : InspectionLikeProcessingForE
}
override fun apply(element: KtDeclaration) {
element.removeModifier(element.visibilityModifierType()!!)
element.removeModifier(element.visibilityModifierType() ?: return)
}
}
@@ -41,16 +41,17 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.j2k.ReferenceSearcher
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -249,7 +250,7 @@ class JavaToJKTreeBuilder constructor(
JavaTokenType.LONG_LITERAL -> JKLiteralExpression(text, LONG)
JavaTokenType.FLOAT_LITERAL -> JKLiteralExpression(text, FLOAT)
JavaTokenType.DOUBLE_LITERAL -> JKLiteralExpression(text, DOUBLE)
else -> error("Unknown literal element type: ${this.literalElementType}")
else -> throwCanNotConvertError("Unknown literal element type: $literalElementType")
}.also {
it.assignNonCodeElements(this)
}
@@ -531,7 +532,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiTypeCastExpression.toJK(): JKExpression {
return JKTypeCastExpression(
operand?.toJK() ?: throwCanNotConvertError(),
castType?.type?.toJK()?.asTypeElement() ?: throwCanNotConvertError()
(castType?.type?.toJK() ?: JKNoType).asTypeElement()
).also {
it.assignNonCodeElements(this)
}
@@ -647,10 +648,12 @@ class JavaToJKTreeBuilder constructor(
with(expressionTreeMapper) { argumentList?.toJK() ?: JKArgumentList() },
initializingClass?.createClassBody() ?: JKClassBody(),
JKTypeElement(
JKClassType(
symbolProvider.provideDirectSymbol(containingClass ?: throwCanNotConvertError()) as JKClassSymbol,
emptyList()
)
containingClass?.let { klass ->
JKClassType(
symbolProvider.provideDirectSymbol(klass) as JKClassSymbol,
emptyList()
)
} ?: JKNoType
)
).also {
symbolProvider.provideUniverseSymbol(this, it)
@@ -701,15 +704,18 @@ class JavaToJKTreeBuilder constructor(
}
fun <T : PsiModifierListOwner> T.annotationList(docCommentOwner: PsiDocCommentOwner?): JKAnnotationList {
val plainAnnotations = annotations.map { it.cast<PsiAnnotation>().toJK() }
val deprecatedAnnotation = docCommentOwner?.docComment?.deprecatedAnnotation() ?: return JKAnnotationList(plainAnnotations)
return JKAnnotationList(
plainAnnotations.mapNotNull { annotation ->
if (annotation.classSymbol.fqName == "java.lang.Deprecated") null else annotation
} + deprecatedAnnotation
)
val deprecatedAnnotation = docCommentOwner?.docComment?.deprecatedAnnotation()
val plainAnnotations = annotations.mapNotNull { annotation ->
when {
annotation !is PsiAnnotation -> null
annotation.qualifiedName == DEPRECATED_ANNOTAION_FQ_NAME && deprecatedAnnotation != null -> null
else -> annotation.toJK()
}
}
return JKAnnotationList(plainAnnotations + listOfNotNull(deprecatedAnnotation))
}
fun PsiAnnotation.toJK(): JKAnnotation =
JKAnnotation(
symbolProvider.provideSymbolForReference<JKSymbol>(
@@ -755,9 +761,10 @@ class JavaToJKTreeBuilder constructor(
fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod =
JKJavaAnnotationMethod(
returnType?.toJK()?.asTypeElement()
?: JKTypeElement(JKJavaVoidType).takeIf { isConstructor }
?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"),
JKTypeElement(
returnType?.toJK()
?: JKJavaVoidType.takeIf { isConstructor }
?: JKNoType),
nameIdentifier.toJK(),
defaultValue?.toJK() ?: JKStubExpression(),
otherModifiers(),
@@ -772,9 +779,10 @@ class JavaToJKTreeBuilder constructor(
fun PsiMethod.toJK(): JKMethod {
return JKMethodImpl(
returnType?.toJK()?.asTypeElement()
?: JKTypeElement(JKJavaVoidType).takeIf { isConstructor }
?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"),
JKTypeElement(
returnType?.toJK()
?: JKJavaVoidType.takeIf { isConstructor }
?: JKNoType),
nameIdentifier.toJK(),
parameterList.parameters.map { it.toJK() },
body?.toJK() ?: JKBodyStub,
@@ -845,11 +853,11 @@ class JavaToJKTreeBuilder constructor(
is PsiExpressionStatement -> JKExpressionStatement(with(expressionTreeMapper) { expression.toJK() })
is PsiReturnStatement -> JKReturnStatement(with(expressionTreeMapper) { returnValue.toJK() })
is PsiDeclarationStatement ->
JKDeclarationStatement(declaredElements.map {
JKDeclarationStatement(declaredElements.mapNotNull {
when (it) {
is PsiClass -> it.toJK()
is PsiLocalVariable -> it.toJK()
else -> it.throwCanNotConvertError()
else -> null
}
})
is PsiAssertStatement ->
@@ -993,7 +1001,7 @@ class JavaToJKTreeBuilder constructor(
this is PsiWhiteSpace -> JKSpaceElement(text)
text == ";" -> null
text == "" -> null
else -> error("Token should be either token or whitespace")
else -> null
} ?: return null
tokenCache[this] = token
return token
@@ -1054,8 +1062,13 @@ class JavaToJKTreeBuilder constructor(
also { it.assignNonCodeElements(psi) }
private fun PsiElement.throwCanNotConvertError(message: String? = null): Nothing {
error("Cannot convert the following Java element ${this::class} with text `$text`" + message?.let { " due to `$it`" }.orEmpty())
throw KotlinExceptionWithAttachments("Cannot convert the following Java element ${this::class}" + message?.let { " due to `$it`" })
.withAttachment("elementText", text)
.withAttachment("file", containingFile?.text)
}
companion object {
private const val DEPRECATED_ANNOTAION_FQ_NAME = "java.lang.Deprecated"
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.declarationList
import org.jetbrains.kotlin.nj2k.getCompanion
@@ -70,6 +71,8 @@ class ClassToObjectPromotionConversion(context: NewJ2kConverterContext) : Recurs
}
}
private fun JKClass.hasInheritors() =
context.converter.converterServices.oldServices.referenceSearcher.hasInheritors(psi()!!)
private fun JKClass.hasInheritors(): Boolean {
val psi = psi<PsiClass>() ?: return false
return context.converter.converterServices.oldServices.referenceSearcher.hasInheritors(psi)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.nj2k.*
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseMethodSymbol
import org.jetbrains.kotlin.nj2k.tree.*
@@ -22,7 +23,7 @@ class DefaultArgumentsConversion(context: NewJ2kConverterContext) : RecursiveApp
|| hasOtherModifier(OtherModifier.OVERRIDE)
|| hasOtherModifier(OtherModifier.NATIVE)
|| hasOtherModifier(OtherModifier.SYNCHRONIZED)
|| context.converter.converterServices.oldServices.referenceSearcher.hasOverrides(psi()!!)
|| psi<PsiMethod>()?.let { context.converter.converterServices.oldServices.referenceSearcher.hasOverrides(it) } == true
|| annotationList.annotations.isNotEmpty()
|| canBeGetterOrSetter()
@@ -28,14 +28,15 @@ class EnumFieldAccessConversion(context: NewJ2kConverterContext) : RecursiveAppl
)
}
private fun JKFieldSymbol.enumClassSymbol(): JKClassSymbol? =
when {
private fun JKFieldSymbol.enumClassSymbol(): JKClassSymbol? {
return when {
this is JKMultiverseFieldSymbol && target is PsiEnumConstant ->
symbolProvider.provideDirectSymbol(target.containingClass!!) as JKClassSymbol
symbolProvider.provideDirectSymbol(target.containingClass ?: return null) as? JKClassSymbol
this is JKMultiverseKtEnumEntrySymbol ->
symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol
symbolProvider.provideDirectSymbol(target.containingClass() ?: return null) as? JKClassSymbol
this is JKUniverseFieldSymbol && target is JKEnumConstant ->
symbolProvider.provideUniverseSymbol(target.parentOfType<JKClass>()!!)
symbolProvider.provideUniverseSymbol(target.parentOfType<JKClass>() ?: return null)
else -> null
}
}
}
@@ -30,8 +30,8 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
private fun convertBinaryExpression(binaryExpression: JKBinaryExpression): JKExpression {
fun JKBinaryExpression.convertBinaryOperationWithChar(): JKBinaryExpression {
val leftType = left.calculateType(typeFactory).asPrimitiveType() ?: return this
val rightType = right.calculateType(typeFactory).asPrimitiveType() ?: return this
val leftType = left.calculateType(typeFactory)?.asPrimitiveType() ?: return this
val rightType = right.calculateType(typeFactory)?.asPrimitiveType() ?: return this
val leftOperandCastedCasted by lazy(LazyThreadSafetyMode.NONE) {
JKBinaryExpression(
@@ -97,7 +97,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
private fun JKExpression.castStringToRegex(toType: JKType): JKExpression? {
if (toType.safeAs<JKClassType>()?.classReference?.fqName != "java.util.regex.Pattern") return null
val expressionType = calculateType(typeFactory)
val expressionType = calculateType(typeFactory) ?: return null
if (!expressionType.isStringType()) return null
return JKQualifiedExpression(
copyTreeAndDetach().parenthesizeIfBinaryExpression(),
@@ -117,7 +117,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
val casted = expression.castToAsPrimitiveTypes(toType, strict) ?: return null
return JKPrefixExpression(casted, operator)
}
val expressionTypeAsPrimitive = calculateType(typeFactory).asPrimitiveType() ?: return null
val expressionTypeAsPrimitive = calculateType(typeFactory)?.asPrimitiveType() ?: return null
val toTypeAsPrimitive = toType.asPrimitiveType() ?: return null
if (toTypeAsPrimitive == expressionTypeAsPrimitive) return null
@@ -67,7 +67,7 @@ class ImplicitInitializerConversion(context: NewJ2kConverterContext) : Recursive
.toMap()
.toMutableMap()
val constructorsWithInitializers = findUsages(parentOfType<JKClass>()!!, context).mapNotNull { usage ->
val constructorsWithInitializers = findUsages(containingClass, context).mapNotNull { usage ->
val parent = usage.parent
val assignmentStatement =
when {
@@ -75,8 +75,7 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
JKArgumentList(arguments)
)
is JKClassSymbol -> JKNewExpression(symbol, JKArgumentList(), JKTypeArgumentList())
is JKUnresolvedSymbol -> return recurse(element)
else -> error("Symbol should be either method symbol or class symbol, but it is ${symbol::class}")
else -> return recurse(element)
}
val qualifier = when {
receiverParameter != null ->
@@ -94,8 +93,7 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
when (symbol) {
is JKMethodSymbol -> symbol.returnType ?: JKNoType
is JKClassSymbol -> JKClassType(symbol)
is JKUnresolvedSymbol -> return recurse(element)
else -> error("Symbol should be either method symbol or class symbol, but it is ${symbol::class}")
else -> return recurse(element)
}
)
)
@@ -15,8 +15,8 @@ class AnyWithStringConcatenationConversion(context: NewJ2kConverterContext) : Re
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKBinaryExpression) return recurse(element)
if (element.operator.token == JKOperatorToken.PLUS
&& element.right.calculateType(typeFactory).isStringType()
&& !element.left.calculateType(typeFactory).isStringType()
&& element.right.calculateType(typeFactory)?.isStringType() == true
&& element.left.calculateType(typeFactory)?.isStringType() == false
) {
return recurse(
JKBinaryExpression(
@@ -115,7 +115,7 @@ class SwitchStatementConversion(context: NewJ2kConverterContext) : RecursiveAppl
this is JKIfElseStatement ||
this is JKJavaSwitchStatement ||
this is JKKtWhenStatement ->
this.psi!!.canCompleteNormally()
psi?.canCompleteNormally() == true
else -> true
}
@@ -46,11 +46,13 @@ class JKMultiverseKtEnumEntrySymbol(
override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> {
override val fieldType: JKType?
get() = JKClassType(
symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol,
emptyList(),
Nullability.NotNull
)
get() = target.containingClass()?.let { klass ->
JKClassType(
symbolProvider.provideDirectSymbol(klass) as? JKClassSymbol ?: return@let null,
emptyList(),
Nullability.NotNull
)
}
}
class JKUnresolvedField(
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.nj2k.types.*
abstract class JKExpression : JKAnnotationMemberValue(), PsiOwner by PsiOwnerImpl() {
// we don't need exact type here (eg with substituted type parameters)
abstract fun calculateType(typeFactory: JKTypeFactory): JKType
abstract fun calculateType(typeFactory: JKTypeFactory): JKType?
}
abstract class JKOperatorExpression : JKExpression() {
@@ -92,7 +92,7 @@ class JKLiteralExpression(
}
class JKStubExpression : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitStubExpression(this)
}
@@ -118,7 +118,7 @@ class JKIfElseExpression(
var thenBranch by child(thenBranch)
var elseBranch by child(elseBranch)
override fun calculateType(typeFactory: JKTypeFactory): JKType = type
override fun calculateType(typeFactory: JKTypeFactory): JKType? = type
override fun accept(visitor: JKVisitor) = visitor.visitIfElseExpression(this)
}
@@ -133,7 +133,7 @@ class JKLambdaExpression(
var functionalType by child(functionalType)
val returnType by child(returnType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitLambdaExpression(this)
}
@@ -141,7 +141,7 @@ class JKLambdaExpression(
abstract class JKCallExpression : JKExpression(), JKTypeArgumentListOwner {
abstract val identifier: JKMethodSymbol
abstract var arguments: JKArgumentList
override fun calculateType(typeFactory: JKTypeFactory): JKType = identifier.returnType ?: JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = identifier.returnType
}
class JKDelegationConstructorCall(
@@ -181,18 +181,18 @@ class JKNewExpression(
class JKFieldAccessExpression(var identifier: JKFieldSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = identifier.fieldType ?: JKNoType
override fun calculateType(typeFactory: JKTypeFactory) = identifier.fieldType
override fun accept(visitor: JKVisitor) = visitor.visitFieldAccessExpression(this)
}
class JKPackageAccessExpression(var identifier: JKPackageSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitPackageAccessExpression(this)
}
class JKClassAccessExpression(var identifier: JKClassSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitClassAccessExpression(this)
}
@@ -204,7 +204,7 @@ class JKMethodReferenceExpression(
) : JKExpression() {
val qualifier by child(qualifier)
val functionalType by child(functionalType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitMethodReferenceExpression(this)
}
@@ -221,7 +221,7 @@ class JKClassLiteralExpression(
var literalType: ClassLiteralType
) : JKExpression() {
val classType: JKTypeElement by child(classType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = when (literalType) {
override fun calculateType(typeFactory: JKTypeFactory): JKType? = when (literalType) {
ClassLiteralType.KOTLIN_CLASS -> typeFactory.types.kotlinClass
else -> typeFactory.types.javaKlass
}
@@ -289,7 +289,7 @@ class JKKtAnnotationArrayInitializerExpression(initializers: List<JKAnnotationMe
constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList())
val initializers: List<JKAnnotationMemberValue> by children(initializers)
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType
override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitKtAnnotationArrayInitializerExpression(this)
}
@@ -43,7 +43,7 @@ enum class OtherModifier(override val text: String) : Modifier {
VOLATILE("volatile")
}
abstract class JKModifierElement : JKTreeElement()
sealed class JKModifierElement : JKTreeElement()
interface JKOtherModifiersOwner : JKModifiersListOwner {
@@ -131,7 +131,6 @@ val JKModifierElement.modifier: Modifier
is JKModalityModifierElement -> modality
is JKVisibilityModifierElement -> visibility
is JKOtherModifierElement -> otherModifier
else -> error("")
}
@@ -107,7 +107,9 @@ class JKTypeFactory(val symbolProvider: JKSymbolProvider) {
}
is PsiCapturedWildcardType ->
JKCapturedType(fromPsiType(type.wildcard) as JKWildCardType)
else -> throw Exception("Invalid PSI ${this::class.java}")
is PsiIntersectionType -> // TODO what to do with intersection types? old j2k just took the first conjunct
fromPsiType(type.representative)
else -> throw Exception("Invalid PSI ${type::class.java}")
}
private fun createKotlinType(type: KotlinType): JKType {
@@ -78,7 +78,7 @@ fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType =
is JKJavaDisjunctionType ->
JKJavaDisjunctionType(disjunctions.map { it.applyRecursive(transform) }, nullability)
is JKStarProjectionType -> this
else -> TODO(this::class.toString())
else -> this
}
inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability): T =
@@ -92,7 +92,7 @@ inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability)
is JKJavaArrayType -> JKJavaArrayType(type, newNullability)
is JKContextType -> JKContextType
is JKJavaDisjunctionType -> this
else -> TODO(this::class.toString())
else -> this
} as T
@Suppress("UNCHECKED_CAST")