[NI] Use definitely not-null types for smartcasts

This commit is contained in:
Mikhail Zarechenskiy
2017-11-28 16:16:59 +03:00
parent 64f0688b71
commit 7f0cca52ca
23 changed files with 154 additions and 113 deletions
@@ -3389,7 +3389,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
} }
private TypeAndNullability calcTypeForIEEE754ArithmeticIfNeeded(@Nullable KtExpression expression) { private TypeAndNullability calcTypeForIEEE754ArithmeticIfNeeded(@Nullable KtExpression expression) {
return CodegenUtilKt.calcTypeForIEEE754ArithmeticIfNeeded(expression, bindingContext, context.getFunctionDescriptor()); return CodegenUtilKt.calcTypeForIEEE754ArithmeticIfNeeded(
expression, bindingContext, context.getFunctionDescriptor(), state.getLanguageVersionSettings());
} }
private StackValue generateAssignmentExpression(KtBinaryExpression expression) { private StackValue generateAssignmentExpression(KtBinaryExpression expression) {
@@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
@@ -277,7 +278,12 @@ fun Collection<VariableDescriptor>.filterOutDescriptorsWithSpecialNames() = filt
class TypeAndNullability(@JvmField val type: Type, @JvmField val isNullable: Boolean) class TypeAndNullability(@JvmField val type: Type, @JvmField val isNullable: Boolean)
fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingContext: BindingContext, descriptor: DeclarationDescriptor): TypeAndNullability? { fun calcTypeForIEEE754ArithmeticIfNeeded(
expression: KtExpression?,
bindingContext: BindingContext,
descriptor: DeclarationDescriptor,
languageVersionSettings: LanguageVersionSettings
): TypeAndNullability? {
val ktType = expression.kotlinType(bindingContext) ?: return null val ktType = expression.kotlinType(bindingContext) ?: return null
if (KotlinBuiltIns.isDoubleOrNullableDouble(ktType)) { if (KotlinBuiltIns.isDoubleOrNullableDouble(ktType)) {
@@ -289,7 +295,7 @@ fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingConte
} }
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor) val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor)
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow) val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow, languageVersionSettings)
return stableTypes.firstNotNullResult { return stableTypes.firstNotNullResult {
when { when {
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it)) KotlinBuiltIns.isDoubleOrNullableDouble(it) -> TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
@@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -49,7 +49,8 @@ object ProtectedSyntheticExtensionCallChecker : CallChecker {
val receiverValue = resolvedCall.extensionReceiver as ReceiverValue val receiverValue = resolvedCall.extensionReceiver as ReceiverValue
val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getStableTypes( val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getStableTypes(
DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor) DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor),
context.languageVersionSettings
) )
if (receiverTypes.none { Visibilities.isVisible(getReceiverValueWithSmartCast(null, it), sourceFunction, from) }) { if (receiverTypes.none { Visibilities.isVisible(getReceiverValueWithSmartCast(null, it), sourceFunction, from) }) {
@@ -331,7 +331,7 @@ class GenericCandidateResolver(
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context) val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
if (!dataFlowValue.isStable) return type if (!dataFlowValue.isStable) return type
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue) val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings)
if (possibleTypes.isEmpty()) return type if (possibleTypes.isEmpty()) return type
return TypeIntersector.intersectTypes(possibleTypes + type) return TypeIntersector.intersectTypes(possibleTypes + 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ interface DataFlowInfo {
* are NOT included. So it's quite possible to get an empty set here. * are NOT included. So it's quite possible to get an empty set here.
* Also, type order in the result set MAKES SENSE so keep it stable and do not change without reason * Also, type order in the result set MAKES SENSE so keep it stable and do not change without reason
*/ */
fun getCollectedTypes(key: DataFlowValue): Set<KotlinType> fun getCollectedTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set<KotlinType>
/** /**
* Returns possible types for the given value if it's stable. * Returns possible types for the given value if it's stable.
@@ -58,7 +58,7 @@ interface DataFlowInfo {
* are NOT included. So it's quite possible to get an empty set here. * are NOT included. So it's quite possible to get an empty set here.
* Also, type order in the result set MAKES SENSE so keep it stable and do not change without reason * Also, type order in the result set MAKES SENSE so keep it stable and do not change without reason
*/ */
fun getStableTypes(key: DataFlowValue): Set<KotlinType> fun getStableTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set<KotlinType>
/** /**
* Call this function to clear all data flow information about * Call this function to clear all data flow information about
@@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,20 +16,17 @@
package org.jetbrains.kotlin.resolve.calls.smartcasts package org.jetbrains.kotlin.resolve.calls.smartcasts
import com.google.common.collect.SetMultimap
import com.google.common.collect.LinkedHashMultimap import com.google.common.collect.LinkedHashMultimap
import com.google.common.collect.SetMultimap
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
import java.util.* import java.util.*
internal class DelegatingDataFlowInfo private constructor( internal class DelegatingDataFlowInfo private constructor(
@@ -141,10 +138,15 @@ internal class DelegatingDataFlowInfo private constructor(
return nullability != getCollectedNullability(value) return nullability != getCollectedNullability(value)
} }
override fun getCollectedTypes(key: DataFlowValue) = getCollectedTypes(key, true) override fun getCollectedTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings) =
getCollectedTypes(key, true, languageVersionSettings)
private fun getCollectedTypes(key: DataFlowValue, enrichWithNotNull: Boolean): Set<KotlinType> { private fun getCollectedTypes(
val types = collectTypesFromMeAndParents(key) key: DataFlowValue,
enrichWithNotNull: Boolean,
languageVersionSettings: LanguageVersionSettings
): Set<KotlinType> {
val types = collectTypesFromMeAndParents(key, languageVersionSettings)
if (!enrichWithNotNull || getCollectedNullability(key).canBeNull()) { if (!enrichWithNotNull || getCollectedNullability(key).canBeNull()) {
return types return types
} }
@@ -152,20 +154,34 @@ internal class DelegatingDataFlowInfo private constructor(
val enrichedTypes = newLinkedHashSetWithExpectedSize<KotlinType>(types.size + 1) val enrichedTypes = newLinkedHashSetWithExpectedSize<KotlinType>(types.size + 1)
val originalType = key.type val originalType = key.type
for (type in types) { for (type in types) {
enrichedTypes.add(TypeUtils.makeNotNullable(type)) enrichedTypes.add(type.makeReallyNotNullIfNeeded(languageVersionSettings))
} }
if (originalType.isMarkedNullable) { if (originalType.canBeDefinitelyNotNullOrNotNull(languageVersionSettings)) {
enrichedTypes.add(TypeUtils.makeNotNullable(originalType)) enrichedTypes.add(originalType.makeReallyNotNullIfNeeded(languageVersionSettings))
} }
return enrichedTypes return enrichedTypes
} }
override fun getStableTypes(key: DataFlowValue) = getStableTypes(key, true) override fun getStableTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings) =
getStableTypes(key, true, languageVersionSettings)
private fun getStableTypes(key: DataFlowValue, enrichWithNotNull: Boolean) = private fun getStableTypes(key: DataFlowValue, enrichWithNotNull: Boolean, languageVersionSettings: LanguageVersionSettings) =
if (!key.isStable) LinkedHashSet() else getCollectedTypes(key, enrichWithNotNull) if (!key.isStable) LinkedHashSet() else getCollectedTypes(key, enrichWithNotNull, languageVersionSettings)
private fun KotlinType.canBeDefinitelyNotNullOrNotNull(settings: LanguageVersionSettings): Boolean {
return if (settings.supportsFeature(LanguageFeature.NewInference))
this.isMarkedNullable || DefinitelyNotNullType.makesSenseToBeDefinitelyNotNull(this.unwrap())
else
this.isMarkedNullable
}
private fun KotlinType.makeReallyNotNullIfNeeded(settings: LanguageVersionSettings): KotlinType {
return if (settings.supportsFeature(LanguageFeature.NewInference))
this.unwrap().makeDefinitelyNotNullOrNotNull()
else
TypeUtils.makeNotNullable(this)
}
/** /**
* Call this function to clear all data flow information about * Call this function to clear all data flow information about
* the given data flow value. * the given data flow value.
@@ -184,7 +200,7 @@ internal class DelegatingDataFlowInfo private constructor(
putNullabilityAndTypeInfo(nullability, a, nullabilityOfB, languageVersionSettings, affectReceiver = false) putNullabilityAndTypeInfo(nullability, a, nullabilityOfB, languageVersionSettings, affectReceiver = false)
val newTypeInfo = newTypeInfo() val newTypeInfo = newTypeInfo()
var typesForB = getStableTypes(b) var typesForB = getStableTypes(b, languageVersionSettings)
// Own type of B must be recorded separately, e.g. for a constant // Own type of B must be recorded separately, e.g. for a constant
// But if its type is the same as A, there is no reason to do it // But if its type is the same as A, there is no reason to do it
// because own type is not saved in this set // because own type is not saved in this set
@@ -211,8 +227,8 @@ internal class DelegatingDataFlowInfo private constructor(
// NB: == has no guarantees of type equality, see KT-11280 for the example // NB: == has no guarantees of type equality, see KT-11280 for the example
if (identityEquals || !nullabilityOfA.canBeNonNull() || !nullabilityOfB.canBeNonNull()) { if (identityEquals || !nullabilityOfA.canBeNonNull() || !nullabilityOfB.canBeNonNull()) {
newTypeInfo.putAll(a, getStableTypes(b, false)) newTypeInfo.putAll(a, getStableTypes(b, false, languageVersionSettings))
newTypeInfo.putAll(b, getStableTypes(a, false)) newTypeInfo.putAll(b, getStableTypes(a, false, languageVersionSettings))
if (a.type != b.type) { if (a.type != b.type) {
// To avoid recording base types of own type // To avoid recording base types of own type
if (!a.type.isSubtypeOf(b.type)) { if (!a.type.isSubtypeOf(b.type)) {
@@ -228,7 +244,7 @@ internal class DelegatingDataFlowInfo private constructor(
return if (changed) create(this, resultNullabilityInfo, if (newTypeInfo.isEmpty) EMPTY_TYPE_INFO else newTypeInfo) else this return if (changed) create(this, resultNullabilityInfo, if (newTypeInfo.isEmpty) EMPTY_TYPE_INFO else newTypeInfo) else this
} }
private fun collectTypesFromMeAndParents(value: DataFlowValue): Set<KotlinType> { private fun collectTypesFromMeAndParents(value: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set<KotlinType> {
val types = LinkedHashSet<KotlinType>() val types = LinkedHashSet<KotlinType>()
var current: DataFlowInfo? = this var current: DataFlowInfo? = this
@@ -238,7 +254,7 @@ internal class DelegatingDataFlowInfo private constructor(
current = if (value == current.valueWithGivenTypeInfo) null else current.parent current = if (value == current.valueWithGivenTypeInfo) null else current.parent
} }
else { else {
types.addAll(current.getCollectedTypes(value)) types.addAll(current.getCollectedTypes(value, languageVersionSettings))
break break
} }
} }
@@ -266,7 +282,7 @@ internal class DelegatingDataFlowInfo private constructor(
value: DataFlowValue, type: KotlinType, languageVersionSettings: LanguageVersionSettings value: DataFlowValue, type: KotlinType, languageVersionSettings: LanguageVersionSettings
): DataFlowInfo { ): DataFlowInfo {
if (value.type == type) return this if (value.type == type) return this
if (getCollectedTypes(value).contains(type)) return this if (getCollectedTypes(value, languageVersionSettings).contains(type)) return this
if (!value.type.isFlexible() && value.type.isSubtypeOf(type)) return this if (!value.type.isFlexible() && value.type.isSubtypeOf(type)) return this
val newTypeInfo = newTypeInfo() val newTypeInfo = newTypeInfo()
newTypeInfo.put(value, type) newTypeInfo.put(value, type)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.calls.smartcasts package org.jetbrains.kotlin.resolve.calls.smartcasts
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors.SMARTCAST_IMPOSSIBLE import org.jetbrains.kotlin.diagnostics.Errors.SMARTCAST_IMPOSSIBLE
import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.Call
@@ -39,9 +40,11 @@ class SmartCastManager {
receiverToCast: ReceiverValue, receiverToCast: ReceiverValue,
bindingContext: BindingContext, bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor, containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo dataFlowInfo: DataFlowInfo,
languageVersionSettings: LanguageVersionSettings
): List<KotlinType> { ): List<KotlinType> {
val variants = getSmartCastVariantsExcludingReceiver(bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast) val variants = getSmartCastVariantsExcludingReceiver(
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings)
val result = ArrayList<KotlinType>(variants.size + 1) val result = ArrayList<KotlinType>(variants.size + 1)
result.add(receiverToCast.type) result.add(receiverToCast.type)
result.addAll(variants) result.addAll(variants)
@@ -58,7 +61,8 @@ class SmartCastManager {
return getSmartCastVariantsExcludingReceiver(context.trace.bindingContext, return getSmartCastVariantsExcludingReceiver(context.trace.bindingContext,
context.scope.ownerDescriptor, context.scope.ownerDescriptor,
context.dataFlowInfo, context.dataFlowInfo,
receiverToCast) receiverToCast,
context.languageVersionSettings)
} }
/** /**
@@ -68,10 +72,11 @@ class SmartCastManager {
bindingContext: BindingContext, bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor, containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo, dataFlowInfo: DataFlowInfo,
receiverToCast: ReceiverValue receiverToCast: ReceiverValue,
languageVersionSettings: LanguageVersionSettings
): Collection<KotlinType> { ): Collection<KotlinType> {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule) val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule)
return dataFlowInfo.getCollectedTypes(dataFlowValue) return dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings)
} }
fun getSmartCastReceiverResult( fun getSmartCastReceiverResult(
@@ -163,7 +168,7 @@ class SmartCastManager {
recordExpressionType: Boolean recordExpressionType: Boolean
): SmartCastResult? { ): SmartCastResult? {
val calleeExpression = call?.calleeExpression val calleeExpression = call?.calleeExpression
for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue)) { for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings)) {
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType) && (additionalPredicate == null || additionalPredicate(possibleType))) { if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType) && (additionalPredicate == null || additionalPredicate(possibleType))) {
if (expression != null) { if (expression != null) {
recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType) recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType)
@@ -79,7 +79,7 @@ class KotlinResolutionCallbacksImpl(
fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) = fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) =
createSimplePSICallArgument(trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor, createSimplePSICallArgument(trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo) CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings)
val lambdaInfo = LambdaInfo(expectedReturnType ?: TypeUtils.NO_EXPECTED_TYPE, val lambdaInfo = LambdaInfo(expectedReturnType ?: TypeUtils.NO_EXPECTED_TYPE,
if (expectedReturnType == null) ContextDependency.DEPENDENT else ContextDependency.INDEPENDENT) if (expectedReturnType == null) ContextDependency.DEPENDENT else ContextDependency.INDEPENDENT)
@@ -156,7 +156,8 @@ class KotlinResolutionCallbacksImpl(
resolvedAtom.candidateDescriptor, resolvedAtom.candidateDescriptor,
trace.bindingContext, trace.bindingContext,
psiKotlinCall.resultDataFlowInfo, psiKotlinCall.resultDataFlowInfo,
ExpressionReceiver.create(expression, returnType, trace.bindingContext) ExpressionReceiver.create(expression, returnType, trace.bindingContext),
languageVersionSettings
) )
} }
} }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -199,7 +200,8 @@ internal fun createSimplePSICallArgument(
typeInfoForArgument: KotlinTypeInfo typeInfoForArgument: KotlinTypeInfo
) = createSimplePSICallArgument(contextForArgument.trace.bindingContext, contextForArgument.statementFilter, ) = createSimplePSICallArgument(contextForArgument.trace.bindingContext, contextForArgument.statementFilter,
contextForArgument.scope.ownerDescriptor, valueArgument, contextForArgument.scope.ownerDescriptor, valueArgument,
contextForArgument.dataFlowInfo, typeInfoForArgument) contextForArgument.dataFlowInfo, typeInfoForArgument,
contextForArgument.languageVersionSettings)
internal fun createSimplePSICallArgument( internal fun createSimplePSICallArgument(
bindingContext: BindingContext, bindingContext: BindingContext,
@@ -207,7 +209,8 @@ internal fun createSimplePSICallArgument(
ownerDescriptor: DeclarationDescriptor, ownerDescriptor: DeclarationDescriptor,
valueArgument: ValueArgument, valueArgument: ValueArgument,
dataFlowInfoBeforeThisArgument: DataFlowInfo, dataFlowInfoBeforeThisArgument: DataFlowInfo,
typeInfoForArgument: KotlinTypeInfo typeInfoForArgument: KotlinTypeInfo,
languageVersionSettings: LanguageVersionSettings
): SimplePSIKotlinCallArgument? { ): SimplePSIKotlinCallArgument? {
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
@@ -223,7 +226,8 @@ internal fun createSimplePSICallArgument(
val receiverToCast = transformToReceiverWithSmartCastInfo( val receiverToCast = transformToReceiverWithSmartCastInfo(
ownerDescriptor, bindingContext, ownerDescriptor, bindingContext,
typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x } typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x }
ExpressionReceiver.create(ktExpression, baseType, bindingContext) ExpressionReceiver.create(ktExpression, baseType, bindingContext),
languageVersionSettings
).let { ).let {
if (onlyResolvedCall == null) it.prepareReceiverRegardingCaptureTypes() else it if (onlyResolvedCall == null) it.prepareReceiverRegardingCaptureTypes() else it
} }
@@ -491,16 +491,21 @@ class NewResolutionOldInference(
} }
fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) = fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) =
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver) transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings)
fun transformToReceiverWithSmartCastInfo( fun transformToReceiverWithSmartCastInfo(
containingDescriptor: DeclarationDescriptor, containingDescriptor: DeclarationDescriptor,
bindingContext: BindingContext, bindingContext: BindingContext,
dataFlowInfo: DataFlowInfo, dataFlowInfo: DataFlowInfo,
receiver: ReceiverValue receiver: ReceiverValue,
languageVersionSettings: LanguageVersionSettings
): ReceiverValueWithSmartCastInfo { ): ReceiverValueWithSmartCastInfo {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor) val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
return ReceiverValueWithSmartCastInfo(receiver, dataFlowInfo.getCollectedTypes(dataFlowValue), dataFlowValue.isStable) return ReceiverValueWithSmartCastInfo(
receiver,
dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings),
dataFlowValue.isStable
)
} }
@Deprecated("Temporary error") @Deprecated("Temporary error")
@@ -372,7 +372,11 @@ class PSICallResolver(
temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor) temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor)
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor) val dataFlowValue = DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
return ReceiverValueWithSmartCastInfo(variableReceiver, context.dataFlowInfo.getCollectedTypes(dataFlowValue), dataFlowValue.isStable) return ReceiverValueWithSmartCastInfo(
variableReceiver,
context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings),
dataFlowValue.isStable
)
} }
} }
@@ -381,17 +381,18 @@ public class DataFlowAnalyzer {
@NotNull ResolutionContext c @NotNull ResolutionContext c
) { ) {
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c); DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c);
return getAllPossibleTypes(type, c, dataFlowValue); return getAllPossibleTypes(type, c, dataFlowValue, c.languageVersionSettings);
} }
@NotNull @NotNull
public static Collection<KotlinType> getAllPossibleTypes( public static Collection<KotlinType> getAllPossibleTypes(
@NotNull KotlinType type, @NotNull KotlinType type,
@NotNull ResolutionContext c, @NotNull ResolutionContext c,
@NotNull DataFlowValue dataFlowValue @NotNull DataFlowValue dataFlowValue,
@NotNull LanguageVersionSettings languageVersionSettings
) { ) {
Collection<KotlinType> possibleTypes = Sets.newHashSet(type); Collection<KotlinType> possibleTypes = Sets.newHashSet(type);
possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue)); possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue, languageVersionSettings));
return possibleTypes; return possibleTypes;
} }
@@ -102,7 +102,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
DataFlowValueFactory.createDataFlowValue(it, subjectType, contextAfterSubject) DataFlowValueFactory.createDataFlowValue(it, subjectType, contextAfterSubject)
} ?: DataFlowValue.nullValue(components.builtIns) } ?: DataFlowValue.nullValue(components.builtIns)
val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(subjectDataFlowValue) ?: emptySet() val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(
subjectDataFlowValue, components.languageVersionSettings) ?: emptySet()
checkSmartCastsInSubjectIfRequired(expression, contextBeforeSubject, subjectType, possibleTypesForSubject) checkSmartCastsInSubjectIfRequired(expression, contextBeforeSubject, subjectType, possibleTypesForSubject)
val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType) val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
@@ -463,7 +464,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
) { ) {
if (subjectType.containsError() || targetType.containsError()) return if (subjectType.containsError() || targetType.containsError()) return
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue) val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue, context.languageVersionSettings)
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, false)) { if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, false)) {
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated)) context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
} }
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.codeInsight package org.jetbrains.kotlin.idea.codeInsight
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.resolve.frontendService
@@ -176,7 +177,13 @@ class ReferenceVariantsHelper(
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>() val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
val implicitReceiverTypes = resolutionScope.getImplicitReceiversWithInstance().flatMap { val implicitReceiverTypes = resolutionScope.getImplicitReceiversWithInstance().flatMap {
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, bindingContext, containingDeclaration, dataFlowInfo) smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
it.value,
bindingContext,
containingDeclaration,
dataFlowInfo,
resolutionFacade.frontendService<LanguageVersionSettings>()
)
}.toSet() }.toSet()
val descriptors = LinkedHashSet<DeclarationDescriptor>() val descriptors = LinkedHashSet<DeclarationDescriptor>()
@@ -17,8 +17,10 @@
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* 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.types.expressions.DoubleColonLHS
import org.jetbrains.kotlin.util.supertypesWithAny import org.jetbrains.kotlin.util.supertypesWithAny
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.lang.RuntimeException
import java.util.* import java.util.*
sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) { sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
@@ -232,6 +233,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
stableSmartCastsOnly: Boolean, stableSmartCastsOnly: Boolean,
withImplicitReceiversWhenExplicitPresent: Boolean = false withImplicitReceiversWhenExplicitPresent: Boolean = false
): Collection<ReceiverType>? { ): Collection<ReceiverType>? {
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val receiverExpression: KtExpression? val receiverExpression: KtExpression?
when (this) { when (this) {
is CallTypeAndReceiver.CALLABLE_REFERENCE -> { is CallTypeAndReceiver.CALLABLE_REFERENCE -> {
@@ -242,7 +245,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
is DoubleColonLHS.Expression -> { is DoubleColonLHS.Expression -> {
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext) 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) } .map { ReceiverType(it, 0) }
} }
} }
@@ -300,7 +304,7 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
var receiverIndex = 0 var receiverIndex = 0
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) { 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) } types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) }
receiverIndex++ receiverIndex++
} }
@@ -318,11 +322,18 @@ private fun receiverValueTypes(
dataFlowInfo: DataFlowInfo, dataFlowInfo: DataFlowInfo,
bindingContext: BindingContext, bindingContext: BindingContext,
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
stableSmartCastsOnly: Boolean stableSmartCastsOnly: Boolean,
languageVersionSettings: LanguageVersionSettings
): List<KotlinType> { ): List<KotlinType> {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor) 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 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 { else {
listOf(receiverValue.type) 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -57,9 +58,10 @@ fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
receiverToCast: ReceiverValue, receiverToCast: ReceiverValue,
bindingContext: BindingContext, bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor, containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo dataFlowInfo: DataFlowInfo,
languageVersionSettings: LanguageVersionSettings
): List<KotlinType> { ): List<KotlinType> {
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo) val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings)
return variants.filter { type -> return variants.filter { type ->
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtThisExpression import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.resolve.BindingContext 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.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue 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.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.nullability 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( fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
receiverTypes: Collection<KotlinType>, receiverTypes: Collection<KotlinType>,
callType: CallType<*> 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor 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.idea.references.mainReference
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector 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 result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown"
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor()) 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()) { if (!types.isEmpty()) {
return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")" return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")"
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.cfg.pseudocode.* import org.jetbrains.kotlin.cfg.pseudocode.*
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.project.builtIns 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.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -149,7 +150,8 @@ fun KtExpression.guessTypes(
val theType1 = context.getType(this) val theType1 = context.getType(this)
if (theType1 != null && isAcceptable(theType1)) { if (theType1 != null && isAcceptable(theType1)) {
val dataFlowInfo = context.getDataFlowInfoAfter(this) 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) return if (possibleTypes.isNotEmpty()) possibleTypes.toTypedArray() else arrayOf(theType1)
} }
@@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.util.PsiTreeUtil 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.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.compareDescriptors 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.extractableSubstringInfo import org.jetbrains.kotlin.idea.refactoring.introduce.extractableSubstringInfo
import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis
@@ -183,13 +185,13 @@ data class ExtractionData(
val dataFlowInfo = context.getDataFlowInfoAfter(expression) val dataFlowInfo = context.getDataFlowInfoAfter(expression)
resolvedCall?.getImplicitReceiverValue()?.let { 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 type = resolvedCall?.resultingDescriptor?.returnType ?: return emptySet()
val containingDescriptor = expression.getResolutionScope(context, expression.getResolutionFacade()).ownerDescriptor 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) return dataFlowInfo.getCollectedTypes(dataFlowValue, expression.languageVersionSettings)
} }
fun getBrokenReferencesInfo(body: KtBlockExpression): List<ResolvedReferenceInfo> { fun getBrokenReferencesInfo(body: KtBlockExpression): List<ResolvedReferenceInfo> {
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator 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.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -325,8 +326,12 @@ private fun suggestParameterType(
receiverToExtract is ImplicitReceiver -> { receiverToExtract is ImplicitReceiver -> {
val typeByDataFlowInfo = if (useSmartCastsIfPossible) { val typeByDataFlowInfo = if (useSmartCastsIfPossible) {
val dataFlowInfo = bindingContext.getDataFlowInfoAfter(resolvedCall!!.call.callElement) val callElement = resolvedCall!!.call.callElement
val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract)) val dataFlowInfo = bindingContext.getDataFlowInfoAfter(callElement)
val possibleTypes = dataFlowInfo.getCollectedTypes(
DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract),
callElement.languageVersionSettings
)
if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null
} else null } else null
typeByDataFlowInfo ?: receiverToExtract.type typeByDataFlowInfo ?: receiverToExtract.type
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.translate.expression
import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
@@ -125,7 +126,9 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
val dataFlow = DataFlowValueFactory.createDataFlowValue( val dataFlow = DataFlowValueFactory.createDataFlowValue(
ktSubject, subjectType, bindingContext(), context().declarationDescriptor ?: context().currentModule) ktSubject, subjectType, bindingContext(), context().declarationDescriptor ?: context().currentModule)
val expectedTypes = bindingContext().getDataFlowInfoBefore(ktSubject).getStableTypes(dataFlow) + setOf(subjectType) val languageVersionSettings = context().config.configuration.languageVersionSettings
val expectedTypes = bindingContext().getDataFlowInfoBefore(ktSubject).getStableTypes(dataFlow, languageVersionSettings) +
setOf(subjectType)
val subject = expressionToMatch ?: return null val subject = expressionToMatch ?: return null
var subjectSupplier = { subject } var subjectSupplier = { subject }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.translate.intrinsic.operation
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperator import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperator
@@ -114,7 +115,8 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory {
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression, ktType, bindingContext, descriptor) val dataFlow = DataFlowValueFactory.createDataFlowValue(expression, ktType, bindingContext, descriptor)
val isPrimitiveFn = KotlinBuiltIns::isPrimitiveTypeOrNullablePrimitiveType val isPrimitiveFn = KotlinBuiltIns::isPrimitiveTypeOrNullablePrimitiveType
return bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow).find(isPrimitiveFn) ?: // Smart-casts val languageVersionSettings = context.config.configuration.languageVersionSettings
return bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow, languageVersionSettings).find(isPrimitiveFn) ?: // Smart-casts
TypeUtils.getAllSupertypes(ktType).find(isPrimitiveFn) ?: // Generic super-types TypeUtils.getAllSupertypes(ktType).find(isPrimitiveFn) ?: // Generic super-types
ktType // Default ktType // Default
} }