New J2K: external annotations support for nullability analysis

This commit is contained in:
Ilya Kirillov
2019-04-18 15:13:43 +03:00
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