Refactor DataFlowValueFactory into proper component

This commit is contained in:
Dmitry Savvinov
2018-02-13 13:48:08 +03:00
parent 03567a1c01
commit 0929673576
62 changed files with 397 additions and 242 deletions
@@ -26,8 +26,10 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
@@ -111,7 +113,8 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
val expressionType = element.getType(bindingContext)
val result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown"
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor())
val dataFlowValueFactory = element.getResolutionFacade().frontendService<DataFlowValueFactory>()
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor())
val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue, element.languageVersionSettings)
if (!types.isEmpty()) {
return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")"
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
@@ -195,7 +196,8 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace")
val context = BasicCallResolutionContext.create(bindingTrace, resolutionScope, newCall, expectedType, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
false, facade.frontendService<LanguageVersionSettings>())
false, facade.frontendService<LanguageVersionSettings>(),
facade.frontendService<DataFlowValueFactory>())
val callResolver = facade.frontendService<CallResolver>()
val result = callResolver.resolveSimpleProperty(context)
return result.isSuccess && result.resultingDescriptor.original == property
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.types.TypeUtils
@@ -163,7 +163,7 @@ fun KtExpression.isStable(context: BindingContext = this.analyze()): Boolean {
if (this is KtConstantExpression || this is KtThisExpression) return true
val descriptor = BindingContextUtils.extractVariableDescriptorFromReference(context, this)
return descriptor is VariableDescriptor &&
DataFlowValueFactory.isStableValue(descriptor, DescriptorUtils.getContainingModule(descriptor))
DataFlowValueFactoryImpl.isStableValue(descriptor, DescriptorUtils.getContainingModule(descriptor))
}
data class IfThenToSelectData(
@@ -30,7 +30,9 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
@@ -132,9 +134,12 @@ class AddExclExclCallFix(psiElement: PsiElement, val checkImplicitReceivers: Boo
} else {
context[BindingContext.EXPRESSION_TYPE_INFO, psiElement]?.let {
val type = it.type
val dataFlowValueFactory = psiElement.getResolutionFacade().frontendService<DataFlowValueFactory>()
if (type != null) {
val nullability = it.dataFlowInfo.getStableNullability(
DataFlowValueFactory.createDataFlowValue(psiElement, type, context, psiElement.findModuleDescriptor())
dataFlowValueFactory.createDataFlowValue(psiElement, type, context, psiElement.findModuleDescriptor())
)
if (!nullability.canBeNonNull()) return null
}
@@ -20,9 +20,11 @@ import com.intellij.refactoring.psi.SearchUtils
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.cfg.pseudocode.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.project.builtIns
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
@@ -150,8 +152,10 @@ fun KtExpression.guessTypes(
val theType1 = context.getType(this)
if (theType1 != null && isAcceptable(theType1)) {
val dataFlowInfo = context.getDataFlowInfoAfter(this)
val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValue(this, theType1, context, module),
languageVersionSettings)
val dataFlowValueFactory = this.getResolutionFacade().frontendService<DataFlowValueFactory>()
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(this, theType1, context, module)
val possibleTypes = dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings)
return if (possibleTypes.isNotEmpty()) possibleTypes.toTypedArray() else arrayOf(theType1)
}
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.refactoring.introduce.ExtractableSubstringInfo
import org.jetbrains.kotlin.idea.refactoring.introduce.extractableSubstringInfo
import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
import org.jetbrains.kotlin.psi.*
@@ -182,15 +183,16 @@ data class ExtractionData(
}
fun getPossibleTypes(expression: KtExpression, resolvedCall: ResolvedCall<*>?, context: BindingContext): Set<KotlinType> {
val dataFlowValueFactory = expression.getResolutionFacade().frontendService<DataFlowValueFactory>()
val dataFlowInfo = context.getDataFlowInfoAfter(expression)
resolvedCall?.getImplicitReceiverValue()?.let {
return dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(it), expression.languageVersionSettings)
return dataFlowInfo.getCollectedTypes(dataFlowValueFactory.createDataFlowValueForStableReceiver(it), expression.languageVersionSettings)
}
val type = resolvedCall?.resultingDescriptor?.returnType ?: return emptySet()
val containingDescriptor = expression.getResolutionScope(context, expression.getResolutionFacade()).ownerDescriptor
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor)
return dataFlowInfo.getCollectedTypes(dataFlowValue, expression.languageVersionSettings)
}
@@ -27,10 +27,12 @@ import org.jetbrains.kotlin.cfg.pseudocode.getExpectedTypePredicate
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithReceivers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.psi.*
@@ -328,9 +330,11 @@ private fun suggestParameterType(
val typeByDataFlowInfo = if (useSmartCastsIfPossible) {
val callElement = resolvedCall!!.call.callElement
val dataFlowInfo = bindingContext.getDataFlowInfoAfter(callElement)
val dataFlowValueFactory = callElement.getResolutionFacade().frontendService<DataFlowValueFactory>()
val possibleTypes = dataFlowInfo.getCollectedTypes(
DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract),
callElement.languageVersionSettings
dataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract),
callElement.languageVersionSettings
)
if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null
} else null