[NI] Use definitely not-null types for smartcasts
This commit is contained in:
+8
-1
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.idea.codeInsight
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
@@ -176,7 +177,13 @@ class ReferenceVariantsHelper(
|
||||
|
||||
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
|
||||
val implicitReceiverTypes = resolutionScope.getImplicitReceiversWithInstance().flatMap {
|
||||
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, bindingContext, containingDeclaration, dataFlowInfo)
|
||||
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
|
||||
it.value,
|
||||
bindingContext,
|
||||
containingDeclaration,
|
||||
dataFlowInfo,
|
||||
resolutionFacade.frontendService<LanguageVersionSettings>()
|
||||
)
|
||||
}.toSet()
|
||||
|
||||
val descriptors = LinkedHashSet<DeclarationDescriptor>()
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -43,7 +45,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.util.supertypesWithAny
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.lang.RuntimeException
|
||||
import java.util.*
|
||||
|
||||
sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
||||
@@ -232,6 +233,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
||||
stableSmartCastsOnly: Boolean,
|
||||
withImplicitReceiversWhenExplicitPresent: Boolean = false
|
||||
): Collection<ReceiverType>? {
|
||||
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
|
||||
|
||||
val receiverExpression: KtExpression?
|
||||
when (this) {
|
||||
is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
|
||||
@@ -242,7 +245,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
||||
|
||||
is DoubleColonLHS.Expression -> {
|
||||
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
|
||||
return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly)
|
||||
return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext,
|
||||
moduleDescriptor, stableSmartCastsOnly, languageVersionSettings)
|
||||
.map { ReceiverType(it, 0) }
|
||||
}
|
||||
}
|
||||
@@ -300,7 +304,7 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
||||
var receiverIndex = 0
|
||||
|
||||
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
||||
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly)
|
||||
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings)
|
||||
types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) }
|
||||
receiverIndex++
|
||||
}
|
||||
@@ -318,11 +322,18 @@ private fun receiverValueTypes(
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
bindingContext: BindingContext,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
stableSmartCastsOnly: Boolean
|
||||
stableSmartCastsOnly: Boolean,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): List<KotlinType> {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
return if (dataFlowValue.isStable || !stableSmartCastsOnly) { // we don't include smart cast receiver types for "unstable" receiver value to mark members grayed
|
||||
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo)
|
||||
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(
|
||||
receiverValue,
|
||||
bindingContext,
|
||||
moduleDescriptor,
|
||||
dataFlowInfo,
|
||||
languageVersionSettings
|
||||
)
|
||||
}
|
||||
else {
|
||||
listOf(receiverValue.type)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -57,9 +58,10 @@ fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
|
||||
receiverToCast: ReceiverValue,
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): List<KotlinType> {
|
||||
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo)
|
||||
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings)
|
||||
return variants.filter { type ->
|
||||
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,9 +24,6 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -35,42 +32,6 @@ import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||
|
||||
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||
receivers: Collection<ReceiverValue>,
|
||||
context: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
callType: CallType<*>,
|
||||
containingDeclarationOrModule: DeclarationDescriptor
|
||||
): Collection<TCallable> {
|
||||
val sequence = receivers.asSequence().flatMap { substituteExtensionIfCallable(it, callType, context, dataFlowInfo, containingDeclarationOrModule).asSequence() }
|
||||
return if (typeParameters.isEmpty()) { // optimization for non-generic callables
|
||||
sequence.firstOrNull()?.let { listOf(it) } ?: listOf()
|
||||
}
|
||||
else {
|
||||
sequence.toList()
|
||||
}
|
||||
}
|
||||
|
||||
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallableWithImplicitReceiver(
|
||||
scope: LexicalScope,
|
||||
context: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo
|
||||
): Collection<TCallable> {
|
||||
val receiverValues = scope.getImplicitReceiversWithInstance().map { it.value }
|
||||
return substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.DEFAULT, scope.ownerDescriptor)
|
||||
}
|
||||
|
||||
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||
receiver: ReceiverValue,
|
||||
callType: CallType<*>,
|
||||
bindingContext: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
containingDeclarationOrModule: DeclarationDescriptor
|
||||
): Collection<TCallable> {
|
||||
val types = SmartCastManager().getSmartCastVariants(receiver, bindingContext, containingDeclarationOrModule, dataFlowInfo)
|
||||
return substituteExtensionIfCallable(types, callType)
|
||||
}
|
||||
|
||||
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||
receiverTypes: Collection<KotlinType>,
|
||||
callType: CallType<*>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,6 +26,7 @@ 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.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||
@@ -111,7 +112,7 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
|
||||
val result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown"
|
||||
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor())
|
||||
val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue)
|
||||
val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue, element.languageVersionSettings)
|
||||
if (!types.isEmpty()) {
|
||||
return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")"
|
||||
}
|
||||
|
||||
+3
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
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.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -149,7 +150,8 @@ 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))
|
||||
val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValue(this, theType1, context, module),
|
||||
languageVersionSettings)
|
||||
return if (possibleTypes.isNotEmpty()) possibleTypes.toTypedArray() else arrayOf(theType1)
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,13 @@ import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.compareDescriptors
|
||||
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
|
||||
@@ -183,13 +185,13 @@ data class ExtractionData(
|
||||
val dataFlowInfo = context.getDataFlowInfoAfter(expression)
|
||||
|
||||
resolvedCall?.getImplicitReceiverValue()?.let {
|
||||
return dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(it))
|
||||
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)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValue)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValue, expression.languageVersionSettings)
|
||||
}
|
||||
|
||||
fun getBrokenReferencesInfo(body: KtBlockExpression): List<ResolvedReferenceInfo> {
|
||||
|
||||
+7
-2
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
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.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -325,8 +326,12 @@ private fun suggestParameterType(
|
||||
|
||||
receiverToExtract is ImplicitReceiver -> {
|
||||
val typeByDataFlowInfo = if (useSmartCastsIfPossible) {
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfoAfter(resolvedCall!!.call.callElement)
|
||||
val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract))
|
||||
val callElement = resolvedCall!!.call.callElement
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfoAfter(callElement)
|
||||
val possibleTypes = dataFlowInfo.getCollectedTypes(
|
||||
DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract),
|
||||
callElement.languageVersionSettings
|
||||
)
|
||||
if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null
|
||||
} else null
|
||||
typeByDataFlowInfo ?: receiverToExtract.type
|
||||
|
||||
Reference in New Issue
Block a user