New J2K: external annotations support for nullability analysis
This commit is contained in:
committed by
Ilya Kirillov
parent
0a88276f68
commit
2ce7dc9d19
@@ -14,8 +14,11 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||||
import org.jetbrains.kotlin.types.isNullable
|
import org.jetbrains.kotlin.resolve.jvm.checkers.mustNotBeNull
|
||||||
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.util.javaslang.getOrNull
|
import org.jetbrains.kotlin.util.javaslang.getOrNull
|
||||||
|
|
||||||
internal inline fun KtExpression.deepestReceiver(): KtExpression =
|
internal inline fun KtExpression.deepestReceiver(): KtExpression =
|
||||||
@@ -26,29 +29,32 @@ internal inline fun KtExpression.deepestReceiver(): KtExpression =
|
|||||||
internal inline fun KtExpression.isNullable(): Boolean =
|
internal inline fun KtExpression.isNullable(): Boolean =
|
||||||
getType(analyze())?.isNullable() != false
|
getType(analyze())?.isNullable() != false
|
||||||
|
|
||||||
|
|
||||||
internal inline fun KtExpression.getForcedNullability(): Nullability? {
|
internal inline fun KtExpression.getForcedNullability(): Nullability? {
|
||||||
val bindingContext = analyze()
|
val bindingContext = analyze()
|
||||||
val type = this.getType(bindingContext) ?: return null
|
val type = this.getType(bindingContext) ?: return null
|
||||||
if (!type.isNullable()) return Nullability.NOT_NULL
|
if (!type.isNullable()) return Nullability.NOT_NULL
|
||||||
|
|
||||||
//TODO better way of getting DataFlowValueFactoryImpl
|
//TODO better way of getting DataFlowValueFactoryImpl
|
||||||
val dataInfo = DataFlowValueFactoryImpl(LanguageVersionSettingsImpl.DEFAULT)
|
val dataFlowValue = DataFlowValueFactoryImpl(LanguageVersionSettingsImpl.DEFAULT)
|
||||||
.createDataFlowValue(
|
.createDataFlowValue(
|
||||||
this,
|
this,
|
||||||
type,
|
type,
|
||||||
bindingContext,
|
bindingContext,
|
||||||
getResolutionFacade().moduleDescriptor
|
getResolutionFacade().moduleDescriptor
|
||||||
)
|
)
|
||||||
val nullability =
|
val dataFlowInfo = analyze()[BindingContext.EXPRESSION_TYPE_INFO, this]?.dataFlowInfo ?: return null
|
||||||
analyze()[BindingContext.EXPRESSION_TYPE_INFO, this]?.dataFlowInfo?.completeNullabilityInfo?.get(dataInfo)?.getOrNull()
|
return when {
|
||||||
return if (nullability == org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL) {
|
dataFlowInfo.completeNullabilityInfo.get(dataFlowValue)?.getOrNull() ==
|
||||||
Nullability.NOT_NULL
|
org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL -> Nullability.NOT_NULL
|
||||||
} else null
|
type.isExternallyAnnotatedNotNull(dataFlowInfo, dataFlowValue) -> Nullability.NOT_NULL
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun KotlinType.isExternallyAnnotatedNotNull(dataFlowInfo: DataFlowInfo, dataFlowValue: DataFlowValue): Boolean=
|
||||||
|
mustNotBeNull()?.isFromJava == true && dataFlowInfo.getStableNullability(dataFlowValue).canBeNull()
|
||||||
|
|
||||||
private fun IElementType.isEqualsToken() =
|
private fun IElementType.isEqualsToken() =
|
||||||
this == KtTokens.EQEQ
|
this == KtTokens.EQEQ
|
||||||
|| this == KtTokens.EXCLEQ
|
|| this == KtTokens.EXCLEQ
|
||||||
|
|||||||
Reference in New Issue
Block a user