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
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
@@ -56,7 +57,8 @@ fun legacyCalcTypeForIeee754ArithmeticIfNeeded(
)
}
val dataFlow = DataFlowValueFactory.createDataFlowValue(
// NB. Using DataFlowValueFactoryImpl is a hack, but it is ok for 'legacy'
val dataFlow = DataFlowValueFactoryImpl().createDataFlowValue(
expression!!,
ktType,
bindingContext,
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.*
@@ -92,7 +91,7 @@ class RuntimeAssertionsDataFlowExtras(
private val expression: KtExpression
) : RuntimeAssertionInfo.DataFlowExtras {
private val dataFlowValue by lazy(LazyThreadSafetyMode.PUBLICATION) {
DataFlowValueFactory.createDataFlowValue(expression, expressionType, c)
c.dataFlowValueFactory.createDataFlowValue(expression, expressionType, c)
}
override val canBeNull: Boolean
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
@@ -44,7 +43,7 @@ class JavaNullabilityChecker : AdditionalTypeChecker {
doCheckType(
expressionType,
c.expectedType,
{ DataFlowValueFactory.createDataFlowValue(expression, expressionType, c) } ,
{ c.dataFlowValueFactory.createDataFlowValue(expression, expressionType, c) } ,
c.dataFlowInfo
) { expectedMustNotBeNull, actualMayBeNull ->
c.trace.report(ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.on(expression, expectedMustNotBeNull, actualMayBeNull))
@@ -61,7 +60,7 @@ class JavaNullabilityChecker : AdditionalTypeChecker {
val context = c.trace.bindingContext
if (WhenChecker.getEnumMissingCases(expression, context, enumClassDescriptor).isEmpty()
&& !WhenChecker.containsNullCase(expression, context)) {
val subjectDataFlowValue = DataFlowValueFactory.createDataFlowValue(subjectExpression, type, c)
val subjectDataFlowValue = c.dataFlowValueFactory.createDataFlowValue(subjectExpression, type, c)
val dataFlowInfo = c.trace[BindingContext.EXPRESSION_TYPE_INFO, subjectExpression]?.dataFlowInfo
if (dataFlowInfo != null && !dataFlowInfo.getStableNullability(subjectDataFlowValue).canBeNull()) {
return
@@ -77,7 +76,7 @@ class JavaNullabilityChecker : AdditionalTypeChecker {
val baseExpressionType = c.trace.getType(baseExpression) ?: return
doIfNotNull(
baseExpressionType,
{ DataFlowValueFactory.createDataFlowValue(baseExpression, baseExpressionType, c) },
{ c.dataFlowValueFactory.createDataFlowValue(baseExpression, baseExpressionType, c) },
c
) {
c.trace.report(Errors.UNNECESSARY_NOT_NULL_ASSERTION.on(expression.operationReference, baseExpressionType))
@@ -105,7 +104,7 @@ class JavaNullabilityChecker : AdditionalTypeChecker {
override fun checkReceiver(receiverParameter: ReceiverParameterDescriptor, receiverArgument: ReceiverValue, safeAccess: Boolean, c: CallResolutionContext<*>) {
val dataFlowValue by lazy(LazyThreadSafetyMode.NONE) {
DataFlowValueFactory.createDataFlowValue(receiverArgument, c)
c.dataFlowValueFactory.createDataFlowValue(receiverArgument, c)
}
if (safeAccess) {
@@ -59,7 +59,7 @@ object JvmArrayVariableInLoopAssignmentChecker : AdditionalTypeChecker {
if (!isOuterForLoopRangeVariable(expression, variableDescriptor, c)) return
val dataFlowValueKind = DataFlowValueFactory.createDataFlowValue(lhsExpression, variableType, c).kind
val dataFlowValueKind = c.dataFlowValueFactory.createDataFlowValue(lhsExpression, variableType, c).kind
if (dataFlowValueKind != DataFlowValue.Kind.STABLE_VARIABLE) return
c.trace.report(ErrorsJvm.ASSIGNMENT_TO_ARRAY_LOOP_VARIABLE.on(lhsExpression))
@@ -49,7 +49,7 @@ object ProtectedSyntheticExtensionCallChecker : CallChecker {
val receiverValue = resolvedCall.extensionReceiver as ReceiverValue
val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getStableTypes(
DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor),
context.dataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor),
context.languageVersionSettings
)
@@ -37,8 +37,9 @@ import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.ConditionalDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
class EffectSystem(val languageVersionSettings: LanguageVersionSettings, val dataFlowValueFactory: DataFlowValueFactory) {
fun getDataFlowInfoForFinishedCall(
resolvedCall: ResolvedCall<*>,
@@ -120,7 +121,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
}
private fun getNonTrivialComputation(expression: KtExpression, trace: BindingTrace, moduleDescriptor: ModuleDescriptor): Computation? {
val computation = EffectsExtractingVisitor(trace, moduleDescriptor).extractOrGetCached(expression)
val computation = EffectsExtractingVisitor(trace, moduleDescriptor, dataFlowValueFactory).extractOrGetCached(expression)
return if (computation == UNKNOWN_COMPUTATION) null else computation
}
}
@@ -51,7 +51,8 @@ import org.jetbrains.kotlin.utils.addIfNotNull
*/
class EffectsExtractingVisitor(
private val trace: BindingTrace,
private val moduleDescriptor: ModuleDescriptor
private val moduleDescriptor: ModuleDescriptor,
private val dataFlowValueFactory: DataFlowValueFactory
) : KtVisitor<Computation, Unit>() {
fun extractOrGetCached(element: KtElement): Computation {
trace[BindingContext.EXPRESSION_EFFECTS, element]?.let { return it }
@@ -143,7 +144,7 @@ class EffectsExtractingVisitor(
}
private fun KtExpression.createDataFlowValue(): DataFlowValue? {
return DataFlowValueFactory.createDataFlowValue(
return dataFlowValueFactory.createDataFlowValue(
expression = this,
type = trace.getType(this) ?: return null,
bindingContext = trace.bindingContext,
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.lazy.*
@@ -64,6 +65,7 @@ fun StorageComponentContainer.configureModule(
private fun StorageComponentContainer.configurePlatformIndependentComponents() {
useImpl<SupertypeLoopCheckerImpl>()
useImpl<KotlinResolutionStatelessCallbacksImpl>()
useImpl<DataFlowValueFactoryImpl>()
useImpl<ExperimentalUsageChecker>()
useImpl<ExperimentalUsageChecker.Overrides>()
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.toHandle
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.ScopeUtils
@@ -63,7 +64,8 @@ class DelegatedPropertyResolver(
private val builtIns: KotlinBuiltIns,
private val fakeCallResolver: FakeCallResolver,
private val expressionTypingServices: ExpressionTypingServices,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory
) {
fun resolvePropertyDelegate(
@@ -314,7 +316,7 @@ class DelegatedPropertyResolver(
else
TypeUtils.NO_EXPECTED_TYPE
val context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType, languageVersionSettings)
val context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType, languageVersionSettings, dataFlowValueFactory)
val hasThis = propertyDescriptor.extensionReceiverParameter != null || propertyDescriptor.dispatchReceiverParameter != null
@@ -352,7 +354,7 @@ class DelegatedPropertyResolver(
initializerScope: LexicalScope,
dataFlowInfo: DataFlowInfo
): OverloadResolutionResults<FunctionDescriptor> {
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, NO_EXPECTED_TYPE, languageVersionSettings)
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory)
return getProvideDelegateMethod(propertyDescriptor, delegateExpression, delegateExpressionType, context)
}
@@ -573,7 +575,7 @@ class DelegatedPropertyResolver(
val contextForProvideDelegate = ExpressionTypingContext.newContext(
traceToResolveConventionMethods, scopeForDelegate, delegateTypeInfo.dataFlowInfo,
NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE,
languageVersionSettings
languageVersionSettings, dataFlowValueFactory
)
val delegateTypeConstructor = delegateTypeInfo.type?.constructor
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
@@ -88,6 +89,7 @@ public class DescriptorResolver {
private final SyntheticResolveExtension syntheticResolveExtension;
private final TypeApproximator typeApproximator;
private final DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer;
private final DataFlowValueFactory dataFlowValueFactory;
public DescriptorResolver(
@NotNull AnnotationResolver annotationResolver,
@@ -105,7 +107,8 @@ public class DescriptorResolver {
@NotNull WrappedTypeFactory wrappedTypeFactory,
@NotNull Project project,
@NotNull TypeApproximator approximator,
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
this.annotationResolver = annotationResolver;
this.builtIns = builtIns;
@@ -123,6 +126,7 @@ public class DescriptorResolver {
this.syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project);
typeApproximator = approximator;
this.declarationReturnTypeSanitizer = declarationReturnTypeSanitizer;
this.dataFlowValueFactory = dataFlowValueFactory;
}
public List<KotlinType> resolveSupertypes(
@@ -340,7 +344,8 @@ public class DescriptorResolver {
scope,
destructuringDeclaration, new TransientReceiver(type), /* initializer = */ null,
ExpressionTypingContext.newContext(
trace, scopeForDestructuring, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings
trace, scopeForDestructuring, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE,
languageVersionSettings, dataFlowValueFactory
)
);
@@ -785,7 +790,7 @@ public class DescriptorResolver {
KtExpression initializer = destructuringDeclaration.getInitializer();
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace, scopeForDeclarationResolution, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings
trace, scopeForDeclarationResolution, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory
);
ExpressionReceiver receiver = createReceiverForDestructuringDeclaration(destructuringDeclaration, context);
@@ -48,7 +48,8 @@ class LocalVariableResolver(
private val annotationResolver: AnnotationResolver,
private val variableTypeAndInitializerResolver: VariableTypeAndInitializerResolver,
private val delegatedPropertyResolver: DelegatedPropertyResolver,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory
) {
fun process(
@@ -108,7 +109,7 @@ class LocalVariableResolver(
val dataFlowInfo = typeInfo.dataFlowInfo
val type = typeInfo.type
if (type != null) {
val initializerDataFlowValue = DataFlowValueFactory.createDataFlowValue(initializer, type, context)
val initializerDataFlowValue = dataFlowValueFactory.createDataFlowValue(initializer, type, context)
if (!propertyDescriptor.isVar && initializerDataFlowValue.canBeBound) {
context.trace.record(BindingContext.BOUND_INITIALIZER_VALUE, propertyDescriptor, initializerDataFlowValue)
}
@@ -116,7 +117,7 @@ class LocalVariableResolver(
// We can comment this condition to take them into account, like here: var s: String? = "xyz"
// In this case s will be not-nullable until it is changed
if (property.typeReference == null) {
val variableDataFlowValue = DataFlowValueFactory.createDataFlowValueForProperty(
val variableDataFlowValue = dataFlowValueFactory.createDataFlowValueForProperty(
property, propertyDescriptor, context.trace.bindingContext,
DescriptorUtils.getContainingModuleOrNull(scope.ownerDescriptor)
)
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSaf
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
@@ -61,7 +62,8 @@ class CallCompleter(
private val callCheckers: Iterable<CallChecker>,
private val moduleDescriptor: ModuleDescriptor,
private val deprecationResolver: DeprecationResolver,
private val effectSystem: EffectSystem
private val effectSystem: EffectSystem,
private val dataFlowValueFactory: DataFlowValueFactory
) {
fun <D : CallableDescriptor> completeCall(
context: BasicCallResolutionContext,
@@ -73,7 +73,8 @@ class CallExpressionResolver(
private val dataFlowAnalyzer: DataFlowAnalyzer,
private val builtIns: KotlinBuiltIns,
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory
) {
private lateinit var expressionTypingServices: ExpressionTypingServices
@@ -343,7 +344,7 @@ class CallExpressionResolver(
private fun getSafeOrUnsafeSelectorTypeInfo(receiver: Receiver, element: CallExpressionElement, context: ExpressionTypingContext):
KotlinTypeInfo {
var initialDataFlowInfoForArguments = context.dataFlowInfo
val receiverDataFlowValue = (receiver as? ReceiverValue)?.let { DataFlowValueFactory.createDataFlowValue(it, context) }
val receiverDataFlowValue = (receiver as? ReceiverValue)?.let { dataFlowValueFactory.createDataFlowValue(it, context) }
val receiverCanBeNull = receiverDataFlowValue != null &&
initialDataFlowInfoForArguments.getStableNullability(receiverDataFlowValue).canBeNull()
if (receiverDataFlowValue != null && element.safe) {
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.calls.tasks.*;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference;
import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver;
@@ -76,6 +77,7 @@ public class CallResolver {
private SyntheticScopes syntheticScopes;
private NewResolutionOldInference newResolutionOldInference;
private PSICallResolver PSICallResolver;
private final DataFlowValueFactory dataFlowValueFactory;
private final KotlinBuiltIns builtIns;
private final LanguageVersionSettings languageVersionSettings;
@@ -83,10 +85,12 @@ public class CallResolver {
public CallResolver(
@NotNull KotlinBuiltIns builtIns,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
this.builtIns = builtIns;
this.languageVersionSettings = languageVersionSettings;
this.dataFlowValueFactory = dataFlowValueFactory;
}
// component dependency cycle
@@ -303,7 +307,7 @@ public class CallResolver {
return resolveFunctionCall(
BasicCallResolutionContext.create(
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
isAnnotationContext, languageVersionSettings
isAnnotationContext, languageVersionSettings, dataFlowValueFactory
)
);
}
@@ -430,7 +434,8 @@ public class CallResolver {
NO_EXPECTED_TYPE,
dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
false,
languageVersionSettings);
languageVersionSettings,
dataFlowValueFactory);
if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
@@ -61,7 +61,8 @@ class CandidateResolver(
private val genericCandidateResolver: GenericCandidateResolver,
private val reflectionTypes: ReflectionTypes,
private val additionalTypeCheckers: Iterable<AdditionalTypeChecker>,
private val smartCastManager: SmartCastManager
private val smartCastManager: SmartCastManager,
private val dataFlowValueFactory: DataFlowValueFactory
) {
fun <D : CallableDescriptor> performResolutionForCandidateCall(
context: CallCandidateResolutionContext<D>,
@@ -384,7 +385,7 @@ class CandidateResolver(
val spreadElement = argument.getSpreadElement()
if (spreadElement != null && !type.isFlexible() && type.isMarkedNullable) {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression, type, context)
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(
dataFlowValue, expectedType, expression, context,
call = null, recordExpressionType = false
@@ -530,7 +531,7 @@ class CandidateResolver(
if (implicitInvokeCheck && call is CallForImplicitInvoke && call.isSafeCall()) {
val outerCallReceiver = call.outerCall.explicitReceiver
if (outerCallReceiver != call.explicitReceiver && outerCallReceiver is ReceiverValue) {
val outerReceiverDataFlowValue = DataFlowValueFactory.createDataFlowValue(outerCallReceiver, this)
val outerReceiverDataFlowValue = dataFlowValueFactory.createDataFlowValue(outerCallReceiver, this)
val outerReceiverNullability = dataFlowInfo.getStableNullability(outerReceiverDataFlowValue)
if (outerReceiverNullability.canBeNull() && !TypeUtils.isNullableType(expectedReceiverParameterType)) {
nullableImplicitInvokeReceiver = true
@@ -539,7 +540,7 @@ class CandidateResolver(
}
}
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, this)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverArgument, this)
val nullability = dataFlowInfo.getStableNullability(dataFlowValue)
val expression = (receiverArgument as? ExpressionReceiver)?.expression
if (nullability.canBeNull() && !nullability.canBeNonNull()) {
@@ -29,7 +29,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class DiagnosticReporterByTrackingStrategy(
val constantExpressionEvaluator: ConstantExpressionEvaluator,
val context: BasicCallResolutionContext,
val psiKotlinCall: PSIKotlinCall
val psiKotlinCall: PSIKotlinCall,
val dataFlowValueFactory: DataFlowValueFactory
) : DiagnosticReporter {
private val trace = context.trace as TrackingBindingTrace
private val tracingStrategy: TracingStrategy get() = psiKotlinCall.tracingStrategy
@@ -162,7 +163,7 @@ class DiagnosticReporterByTrackingStrategy(
expressionArgument.valueArgument.getArgumentExpression(),
context.statementFilter
)
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context)
SmartCastManager.checkAndRecordPossibleCast(
dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call,
recordExpressionType = true
@@ -171,7 +172,7 @@ class DiagnosticReporterByTrackingStrategy(
is ReceiverExpressionKotlinCallArgument -> {
trace.markAsReported()
val receiverValue = expressionArgument.receiver.receiverValue
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, context)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, context)
SmartCastManager.checkAndRecordPossibleCast(
dataFlowValue, smartCastDiagnostic.smartCastType, (receiverValue as? ExpressionReceiver)?.expression, context, call,
recordExpressionType = true
@@ -68,7 +68,8 @@ private val SPECIAL_FUNCTION_NAMES = ResolveConstruct.values().map { it.specialF
class GenericCandidateResolver(
private val argumentTypeResolver: ArgumentTypeResolver,
private val coroutineInferenceSupport: CoroutineInferenceSupport,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory
) {
fun <D : CallableDescriptor> inferTypeArguments(context: CallCandidateResolutionContext<D>): ResolutionStatus {
val candidateCall = context.candidateCall
@@ -328,7 +329,7 @@ class GenericCandidateResolver(
val deparenthesizedArgument = KtPsiUtil.getLastElementDeparenthesized(argumentExpression, context.statementFilter)
if (deparenthesizedArgument == null || type == null) return type
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
if (!dataFlowValue.isStable) return type
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.DeprecationResolver
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.checkers.CheckerContext
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.types.DeferredType
@@ -52,6 +53,9 @@ class CallCheckerContext @JvmOverloads constructor(
val isAnnotationContext: Boolean
get() = resolutionContext.isAnnotationContext
val dataFlowValueFactory: DataFlowValueFactory
get() = resolutionContext.dataFlowValueFactory
override val languageVersionSettings: LanguageVersionSettings
get() = resolutionContext.languageVersionSettings
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.StatementFilter;
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.KotlinType;
@@ -46,11 +47,12 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates,
callPosition, expressionContextProvider, languageVersionSettings);
callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
@@ -63,12 +65,14 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull ContextDependency contextDependency,
@NotNull CheckArgumentTypesMode checkArguments,
boolean isAnnotationContext,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return new BasicCallResolutionContext(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
new ResolutionResultsCacheImpl(), null,
StatementFilter.NONE, isAnnotationContext, false, false,
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings);
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings,
dataFlowValueFactory);
}
@NotNull
@@ -80,7 +84,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
context.trace, context.scope, call, context.expectedType, context.dataFlowInfo, context.contextDependency, checkArguments,
context.resolutionResultsCache, dataFlowInfoForArguments,
context.statementFilter, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
context.callPosition, context.expressionContextProvider, context.languageVersionSettings, context.dataFlowValueFactory);
}
@NotNull
@@ -102,12 +106,13 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return new BasicCallResolutionContext(
trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates,
callPosition, expressionContextProvider, languageVersionSettings);
callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
@@ -115,6 +120,6 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
return new BasicCallResolutionContext(
trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates,
callPosition, expressionContextProvider, languageVersionSettings);
callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.StatementFilter;
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.KotlinType;
@@ -59,11 +60,12 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
this.candidateCall = candidateCall;
this.tracing = tracing;
this.candidateResolveMode = candidateResolveMode;
@@ -80,7 +82,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
context.resolutionResultsCache, context.dataFlowInfoForArguments,
context.statementFilter,
candidateResolveMode, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
context.callPosition, context.expressionContextProvider, context.languageVersionSettings, context.dataFlowValueFactory);
}
@NotNull
@@ -92,7 +94,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache,
context.dataFlowInfoForArguments, context.statementFilter,
CandidateResolveMode.FULLY, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
context.callPosition, context.expressionContextProvider, context.languageVersionSettings, context.dataFlowValueFactory);
}
@Override
@@ -107,12 +109,13 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return new CallCandidateResolutionContext<>(
candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
resolutionResultsCache, dataFlowInfoForArguments, statementFilter,
candidateResolveMode, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider,
languageVersionSettings);
languageVersionSettings, dataFlowValueFactory);
}
}
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.StatementFilter;
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.KotlinType;
@@ -55,10 +56,12 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache,
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings,
dataFlowValueFactory);
this.call = call;
this.checkArguments = checkArguments;
if (dataFlowInfoForArguments != null) {
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.StatementFilter;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
@@ -64,6 +65,9 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
@NotNull
public final LanguageVersionSettings languageVersionSettings;
@NotNull
public final DataFlowValueFactory dataFlowValueFactory;
/**
* Used for analyzing expression in the given context.
* Should be used for going through parents to find containing function, loop etc.
@@ -89,7 +93,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory factory
) {
this.trace = trace;
this.scope = scope;
@@ -104,6 +109,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
this.callPosition = callPosition;
this.expressionContextProvider = expressionContextProvider;
this.languageVersionSettings = languageVersionSettings;
this.dataFlowValueFactory = factory;
}
protected abstract Context create(
@@ -117,7 +123,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
);
@NotNull
@@ -130,14 +137,14 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
public Context replaceBindingTrace(@NotNull BindingTrace trace) {
if (this.trace == trace) return self();
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
if (newDataFlowInfo == dataFlowInfo) return self();
return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
@@ -145,28 +152,28 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
if (expectedType == newExpectedType) return self();
return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceScope(@NotNull LexicalScope newScope) {
if (newScope == scope) return self();
return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
if (newContextDependency == contextDependency) return self();
return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
if (newResolutionResultsCache == resolutionResultsCache) return self();
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
@@ -177,25 +184,25 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
@NotNull
public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
newCollectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
newCollectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) {
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceCallPosition(@NotNull CallPosition callPosition) {
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
public Context replaceExpressionContextProvider(@NotNull Function1<KtExpression, KtExpression> expressionContextProvider) {
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
}
@Nullable
@@ -89,7 +89,7 @@ fun ResolvedCall<*>.getImplicitReceivers(): Collection<ReceiverValue> =
private fun ResolvedCall<*>.hasSafeNullableReceiver(context: CallResolutionContext<*>): Boolean {
if (!call.isSafeCall()) return false
val receiverValue = getExplicitReceiverValue()?.let { DataFlowValueFactory.createDataFlowValue(it, context) }
val receiverValue = getExplicitReceiverValue()?.let { context.dataFlowValueFactory.createDataFlowValue(it, context) }
?: return false
return context.dataFlowInfo.getStableNullability(receiverValue).canBeNull()
}
@@ -50,13 +50,47 @@ import org.jetbrains.kotlin.types.isError
* This class is intended to create data flow values for different kind of expressions.
* Then data flow values serve as keys to obtain data flow information for these expressions.
*/
object DataFlowValueFactory {
@JvmStatic
interface DataFlowValueFactory {
fun createDataFlowValue(
expression: KtExpression,
type: KotlinType,
resolutionContext: ResolutionContext<*>
): DataFlowValue
fun createDataFlowValue(
expression: KtExpression,
type: KotlinType,
bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor
): DataFlowValue
fun createDataFlowValueForStableReceiver(receiver: ReceiverValue): DataFlowValue
fun createDataFlowValue(
receiverValue: ReceiverValue,
resolutionContext: ResolutionContext<*>
): DataFlowValue
fun createDataFlowValue(
receiverValue: ReceiverValue,
bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor
): DataFlowValue
fun createDataFlowValueForProperty(
property: KtProperty,
variableDescriptor: VariableDescriptor,
bindingContext: BindingContext,
usageContainingModule: ModuleDescriptor?
): DataFlowValue
}
class DataFlowValueFactoryImpl : DataFlowValueFactory {
override fun createDataFlowValue(
expression: KtExpression,
type: KotlinType,
resolutionContext: ResolutionContext<*>
) = createDataFlowValue(expression, type, resolutionContext.trace.bindingContext, resolutionContext.scope.ownerDescriptor)
private fun isComplexExpression(expression: KtExpression): Boolean = when (expression) {
@@ -69,8 +103,7 @@ object DataFlowValueFactory {
else -> false
}
@JvmStatic
fun createDataFlowValue(
override fun createDataFlowValue(
expression: KtExpression,
type: KotlinType,
bindingContext: BindingContext,
@@ -107,17 +140,14 @@ object DataFlowValueFactory {
return DataFlowValue(if (result === IdentifierInfo.NO) ExpressionIdentifierInfo(expression) else result, type)
}
@JvmStatic
fun createDataFlowValueForStableReceiver(receiver: ReceiverValue) = DataFlowValue(IdentifierInfo.Receiver(receiver), receiver.type)
override fun createDataFlowValueForStableReceiver(receiver: ReceiverValue) = DataFlowValue(IdentifierInfo.Receiver(receiver), receiver.type)
@JvmStatic
fun createDataFlowValue(
override fun createDataFlowValue(
receiverValue: ReceiverValue,
resolutionContext: ResolutionContext<*>
) = createDataFlowValue(receiverValue, resolutionContext.trace.bindingContext, resolutionContext.scope.ownerDescriptor)
@JvmStatic
fun createDataFlowValue(
override fun createDataFlowValue(
receiverValue: ReceiverValue,
bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor
@@ -132,8 +162,7 @@ object DataFlowValueFactory {
else -> throw UnsupportedOperationException("Unsupported receiver value: " + receiverValue::class.java.name)
}
@JvmStatic
fun createDataFlowValueForProperty(
override fun createDataFlowValueForProperty(
property: KtProperty,
variableDescriptor: VariableDescriptor,
bindingContext: BindingContext,
@@ -351,19 +380,6 @@ object DataFlowValueFactory {
return true
}
private fun propertyKind(propertyDescriptor: PropertyDescriptor, usageModule: ModuleDescriptor?): Kind {
if (propertyDescriptor.isVar) return MUTABLE_PROPERTY
if (propertyDescriptor.isOverridable) return PROPERTY_WITH_GETTER
if (!hasDefaultGetter(propertyDescriptor)) return PROPERTY_WITH_GETTER
if (!invisibleFromOtherModules(propertyDescriptor)) {
val declarationModule = DescriptorUtils.getContainingModule(propertyDescriptor)
if (usageModule == null || usageModule != declarationModule) {
return ALIEN_PUBLIC_PROPERTY
}
}
return STABLE_VALUE
}
private fun variableKind(
variableDescriptor: VariableDescriptor,
usageModule: ModuleDescriptor?,
@@ -407,41 +423,56 @@ object DataFlowValueFactory {
CAPTURED_VARIABLE
}
/**
* Determines whether a variable with a given descriptor is stable or not at the given usage place.
*
*
* Stable means that the variable value cannot change. The simple (non-property) variable is considered stable if it's immutable (val).
*
*
* If the variable is a property, it's considered stable if it's immutable (val) AND it's final (not open) AND
* the default getter is in use (otherwise nobody can guarantee that a getter is consistent) AND
* (it's private OR internal OR used at the same module where it's defined).
* The last check corresponds to a risk of changing property definition in another module, e.g. from "val" to "var".
companion object {
/**
* Determines whether a variable with a given descriptor is stable or not at the given usage place.
*
*
* Stable means that the variable value cannot change. The simple (non-property) variable is considered stable if it's immutable (val).
*
*
* If the variable is a property, it's considered stable if it's immutable (val) AND it's final (not open) AND
* the default getter is in use (otherwise nobody can guarantee that a getter is consistent) AND
* (it's private OR internal OR used at the same module where it's defined).
* The last check corresponds to a risk of changing property definition in another module, e.g. from "val" to "var".
* @param variableDescriptor descriptor of a considered variable
* *
* @param usageModule a module with a considered usage place, or null if it's not known (not recommended)
* *
* @return true if variable is stable, false otherwise
*/
fun isStableValue(
variableDescriptor: VariableDescriptor,
usageModule: ModuleDescriptor?
): Boolean {
if (variableDescriptor.isVar) return false
return variableDescriptor !is PropertyDescriptor || propertyKind(variableDescriptor, usageModule) === STABLE_VALUE
}
* @param variableDescriptor descriptor of a considered variable
* *
* @param usageModule a module with a considered usage place, or null if it's not known (not recommended)
* *
* @return true if variable is stable, false otherwise
*/
fun isStableValue(
variableDescriptor: VariableDescriptor,
usageModule: ModuleDescriptor?
): Boolean {
if (variableDescriptor.isVar) return false
return variableDescriptor !is PropertyDescriptor || propertyKind(variableDescriptor, usageModule) === STABLE_VALUE
}
private fun invisibleFromOtherModules(descriptor: DeclarationDescriptorWithVisibility): Boolean {
if (Visibilities.INVISIBLE_FROM_OTHER_MODULES.contains(descriptor.visibility)) return true
private fun propertyKind(propertyDescriptor: PropertyDescriptor, usageModule: ModuleDescriptor?): Kind {
if (propertyDescriptor.isVar) return MUTABLE_PROPERTY
if (propertyDescriptor.isOverridable) return PROPERTY_WITH_GETTER
if (!hasDefaultGetter(propertyDescriptor)) return PROPERTY_WITH_GETTER
if (!invisibleFromOtherModules(propertyDescriptor)) {
val declarationModule = DescriptorUtils.getContainingModule(propertyDescriptor)
if (usageModule == null || usageModule != declarationModule) {
return ALIEN_PUBLIC_PROPERTY
}
}
return STABLE_VALUE
}
val containingDeclaration = descriptor.containingDeclaration
return containingDeclaration is DeclarationDescriptorWithVisibility && invisibleFromOtherModules(containingDeclaration)
}
private fun hasDefaultGetter(propertyDescriptor: PropertyDescriptor): Boolean {
val getter = propertyDescriptor.getter
return getter == null || getter.isDefault
}
private fun hasDefaultGetter(propertyDescriptor: PropertyDescriptor): Boolean {
val getter = propertyDescriptor.getter
return getter == null || getter.isDefault
private fun invisibleFromOtherModules(descriptor: DeclarationDescriptorWithVisibility): Boolean {
if (Visibilities.INVISIBLE_FROM_OTHER_MODULES.contains(descriptor.visibility)) return true
val containingDeclaration = descriptor.containingDeclaration
return containingDeclaration is DeclarationDescriptorWithVisibility && invisibleFromOtherModules(containingDeclaration)
}
}
}
@@ -41,10 +41,11 @@ class SmartCastManager {
bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): List<KotlinType> {
val variants = getSmartCastVariantsExcludingReceiver(
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings, dataFlowValueFactory
)
val result = ArrayList<KotlinType>(variants.size + 1)
result.add(receiverToCast.type)
@@ -64,7 +65,8 @@ class SmartCastManager {
context.scope.ownerDescriptor,
context.dataFlowInfo,
receiverToCast,
context.languageVersionSettings
context.languageVersionSettings,
context.dataFlowValueFactory
)
}
@@ -76,9 +78,10 @@ class SmartCastManager {
containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo,
receiverToCast: ReceiverValue,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): Collection<KotlinType> {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule)
return dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings)
}
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ReceiverKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
@@ -61,7 +62,8 @@ class KotlinResolutionCallbacksImpl(
val argumentTypeResolver: ArgumentTypeResolver,
val languageVersionSettings: LanguageVersionSettings,
val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
val constantExpressionEvaluator: ConstantExpressionEvaluator
val constantExpressionEvaluator: ConstantExpressionEvaluator,
val dataFlowValueFactory: DataFlowValueFactory
) : KotlinResolutionCallbacks {
val trace: BindingTrace = topLevelCallContext.trace
@@ -87,7 +89,8 @@ class KotlinResolutionCallbacksImpl(
fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) =
createSimplePSICallArgument(
trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings,
dataFlowValueFactory
)
val lambdaInfo = LambdaInfo(
@@ -168,7 +171,7 @@ class KotlinResolutionCallbacksImpl(
trace.bindingContext,
psiKotlinCall.resultDataFlowInfo,
ExpressionReceiver.create(expression, returnType, trace.bindingContext),
languageVersionSettings
languageVersionSettings, dataFlowValueFactory
)
}
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSafeReceiver
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
@@ -66,7 +67,8 @@ class KotlinToResolvedCallTransformer(
private val expressionTypingServices: ExpressionTypingServices,
private val doubleColonExpressionResolver: DoubleColonExpressionResolver,
private val additionalDiagnosticReporter: AdditionalDiagnosticReporter,
private val moduleDescriptor: ModuleDescriptor
private val moduleDescriptor: ModuleDescriptor,
private val dataFlowValueFactory: DataFlowValueFactory
) {
companion object {
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
@@ -99,7 +101,7 @@ class KotlinToResolvedCallTransformer(
val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor()
val ktPrimitiveCompleter = ResolvedAtomCompleter(
resultSubstitutor, context.trace, context, this, expressionTypingServices, argumentTypeResolver,
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, dataFlowValueFactory
)
for (subKtPrimitive in candidate.subResolvedAtoms) {
@@ -347,7 +349,7 @@ class KotlinToResolvedCallTransformer(
val trackingTrace = TrackingBindingTrace(trace)
val newContext = context.replaceBindingTrace(trackingTrace)
val diagnosticReporter =
DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall)
DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall, context.dataFlowValueFactory)
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics)
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.UnwrappedType
@@ -210,7 +211,8 @@ internal fun createSimplePSICallArgument(
contextForArgument.trace.bindingContext, contextForArgument.statementFilter,
contextForArgument.scope.ownerDescriptor, valueArgument,
contextForArgument.dataFlowInfo, typeInfoForArgument,
contextForArgument.languageVersionSettings
contextForArgument.languageVersionSettings,
contextForArgument.dataFlowValueFactory
)
internal fun createSimplePSICallArgument(
@@ -220,7 +222,8 @@ internal fun createSimplePSICallArgument(
valueArgument: ValueArgument,
dataFlowInfoBeforeThisArgument: DataFlowInfo,
typeInfoForArgument: KotlinTypeInfo,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): SimplePSIKotlinCallArgument? {
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
@@ -235,7 +238,8 @@ internal fun createSimplePSICallArgument(
ownerDescriptor, bindingContext,
typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x }
ExpressionReceiver.create(ktExpression, baseType, bindingContext),
languageVersionSettings
languageVersionSettings,
dataFlowValueFactory
).let {
if (onlyResolvedCall == null) it.prepareReceiverRegardingCaptureTypes() else it
}
@@ -528,16 +528,17 @@ class NewResolutionOldInference(
}
fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) =
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings)
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings, dataFlowValueFactory)
fun transformToReceiverWithSmartCastInfo(
containingDescriptor: DeclarationDescriptor,
bindingContext: BindingContext,
dataFlowInfo: DataFlowInfo,
receiver: ReceiverValue,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): ReceiverValueWithSmartCastInfo {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
return ReceiverValueWithSmartCastInfo(
receiver,
dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings),
@@ -61,7 +61,8 @@ class PSICallResolver(
private val typeApproximator: TypeApproximator,
private val argumentTypeResolver: ArgumentTypeResolver,
private val effectSystem: EffectSystem,
private val constantExpressionEvaluator: ConstantExpressionEvaluator
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
private val dataFlowValueFactory: DataFlowValueFactory
) {
private val GIVEN_CANDIDATES_NAME = Name.special("<given candidates>")
@@ -152,7 +153,7 @@ class PSICallResolver(
KotlinResolutionCallbacksImpl(
context, expressionTypingServices, typeApproximator,
argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
constantExpressionEvaluator
constantExpressionEvaluator, dataFlowValueFactory
)
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
@@ -423,7 +424,7 @@ class PSICallResolver(
temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor)
val dataFlowValue =
DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
dataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
return ReceiverValueWithSmartCastInfo(
variableReceiver,
context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings),
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
@@ -44,7 +45,8 @@ class ResolvedAtomCompleter(
private val argumentTypeResolver: ArgumentTypeResolver,
private val doubleColonExpressionResolver: DoubleColonExpressionResolver,
deprecationResolver: DeprecationResolver,
moduleDescriptor: ModuleDescriptor
moduleDescriptor: ModuleDescriptor,
private val dataFlowValueFactory: DataFlowValueFactory
) {
private val callCheckerContext = CallCheckerContext(topLevelCallContext, deprecationResolver, moduleDescriptor)
@@ -83,7 +83,7 @@ object PrimitiveNumericComparisonCallChecker : CallChecker {
private fun CallCheckerContext.getStableTypesForExpression(expression: KtExpression): List<KotlinType> {
val type = trace.bindingContext.getType(expression) ?: return emptyList()
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(
expression, type, trace.bindingContext, resolutionContext.scope.ownerDescriptor
)
val dataFlowInfo = trace.get(BindingContext.EXPRESSION_TYPE_INFO, expression)?.dataFlowInfo ?: return emptyList()
@@ -55,7 +55,6 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability;
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
@@ -87,7 +86,6 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
import static org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
@@ -139,14 +137,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return false;
}
private static void checkNull(
private void checkNull(
@NotNull KtSimpleNameExpression expression,
@NotNull ExpressionTypingContext context,
@Nullable KotlinType type
) {
// Receivers are normally analyzed at resolve, with an exception of KT-10175
if (type != null && !KotlinTypeKt.isError(type) && !isLValueOrUnsafeReceiver(expression)) {
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context);
DataFlowValue dataFlowValue = components.dataFlowValueFactory.createDataFlowValue(expression, type, context);
Nullability nullability = context.dataFlowInfo.getStableNullability(dataFlowValue);
if (!nullability.canBeNonNull() && nullability.canBeNull()) {
if (isDangerousWithNull(expression, context)) {
@@ -182,8 +180,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
KotlinTypeInfo result = facade.getTypeInfo(innerExpression, context);
KotlinType resultType = result.getType();
if (resultType != null) {
DataFlowValue innerValue = DataFlowValueFactory.createDataFlowValue(innerExpression, resultType, context);
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, resultType, context);
DataFlowValue innerValue = components.dataFlowValueFactory.createDataFlowValue(innerExpression, resultType, context);
DataFlowValue resultValue = components.dataFlowValueFactory.createDataFlowValue(expression, resultType, context);
result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(resultValue, innerValue,
components.languageVersionSettings));
}
@@ -321,7 +319,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
checkBinaryWithTypeRHS(expression, context, targetType, subjectType);
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
if (operationType == AS_KEYWORD) {
DataFlowValue value = createDataFlowValue(left, subjectType, context);
DataFlowValue value = components.dataFlowValueFactory.createDataFlowValue(left, subjectType, context);
typeInfo = typeInfo.replaceDataFlowInfo(dataFlowInfo.establishSubtyping(value, targetType,
components.languageVersionSettings));
}
@@ -789,7 +787,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
checkLValue(context.trace, context, baseExpression, stubExpression, expression);
}
// x++ type is x type, but ++x type is x.inc() type
DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue(
DataFlowValue receiverValue = components.dataFlowValueFactory.createDataFlowValue(
(ReceiverValue) call.getExplicitReceiver(), contextWithExpectedType);
if (expression instanceof KtPrefixExpression) {
result = returnType;
@@ -797,7 +795,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
else {
result = receiverType;
// Also record data flow information for x++ value (= x)
DataFlowValue returnValue = DataFlowValueFactory.createDataFlowValue(expression, receiverType, contextWithExpectedType);
DataFlowValue returnValue = components.dataFlowValueFactory.createDataFlowValue(expression, receiverType, contextWithExpectedType);
typeInfo = typeInfo.replaceDataFlowInfo(typeInfo.getDataFlowInfo().assign(returnValue, receiverValue,
components.languageVersionSettings));
}
@@ -854,7 +852,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, TypeUtils.makeNotNullable(baseType)));
}
else {
DataFlowValue value = createDataFlowValue(baseExpression, baseType, context);
DataFlowValue value = components.dataFlowValueFactory.createDataFlowValue(baseExpression, baseType, context);
baseTypeInfo = baseTypeInfo.replaceDataFlowInfo(dataFlowInfo.disequate(value, DataFlowValue.nullValue(components.builtIns),
components.languageVersionSettings));
}
@@ -896,7 +894,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
// Returns `true` if warnings should be reported for left-hand side of elvis and not-null (!!) assertion
private static boolean isKnownToBeNotNull(
private boolean isKnownToBeNotNull(
@NotNull KtExpression expression,
@Nullable KotlinType ktType,
@NotNull ExpressionTypingContext context
@@ -907,7 +905,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (!TypeUtils.isNullableType(ktType)) return true;
DataFlowValue dataFlowValue = createDataFlowValue(expression, ktType, context);
DataFlowValue dataFlowValue = components.dataFlowValueFactory.createDataFlowValue(expression, ktType, context);
return context.dataFlowInfo.getStableNullability(dataFlowValue) == Nullability.NOT_NULL;
}
@@ -1287,7 +1285,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
leftType == null && KotlinBuiltIns.isNothing(rightType)) return TypeInfoFactoryKt.noTypeInfo(dataFlowInfo);
if (leftType != null) {
DataFlowValue leftValue = createDataFlowValue(left, leftType, context);
DataFlowValue leftValue = components.dataFlowValueFactory.createDataFlowValue(left, leftType, context);
DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
boolean jumpInRight = KotlinBuiltIns.isNothing(rightType);
DataFlowValue nullValue = DataFlowValue.nullValue(components.builtIns);
@@ -1299,12 +1297,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
components.languageVersionSettings);
}
}
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, type, context);
DataFlowValue resultValue = components.dataFlowValueFactory.createDataFlowValue(expression, type, context);
dataFlowInfo =
dataFlowInfo.assign(resultValue, leftValue, components.languageVersionSettings)
.disequate(resultValue, nullValue, components.languageVersionSettings);
if (!jumpInRight) {
DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
DataFlowValue rightValue = components.dataFlowValueFactory.createDataFlowValue(right, rightType, context);
rightDataFlowInfo = rightDataFlowInfo.assign(resultValue, rightValue, components.languageVersionSettings);
dataFlowInfo = dataFlowInfo.or(rightDataFlowInfo);
}
@@ -1327,7 +1325,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
@NotNull
private static DataFlowInfo establishSubtypingForTypeRHS(
private DataFlowInfo establishSubtypingForTypeRHS(
@NotNull KtBinaryExpressionWithTypeRHS left,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ExpressionTypingContext context,
@@ -1338,7 +1336,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
KtExpression underSafeAs = left.getLeft();
KotlinType underSafeAsType = context.trace.getType(underSafeAs);
if (underSafeAsType != null) {
DataFlowValue underSafeAsValue = createDataFlowValue(underSafeAs, underSafeAsType, context);
DataFlowValue underSafeAsValue = components.dataFlowValueFactory.createDataFlowValue(underSafeAs, underSafeAsType, context);
KotlinType targetType = context.trace.get(BindingContext.TYPE, left.getRight());
if (targetType != null) {
return dataFlowInfo.establishSubtyping(underSafeAsValue, targetType, languageVersionSettings);
@@ -185,10 +185,10 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
if (resultType != null && thenType != null && elseType != null) {
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
DataFlowValue resultValue = components.dataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = components.dataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue, components.languageVersionSettings);
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
DataFlowValue elseValue = components.dataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue, components.languageVersionSettings);
}
@@ -60,6 +60,7 @@ public class DataFlowAnalyzer {
private final ExpressionTypingFacade facade;
private final LanguageVersionSettings languageVersionSettings;
private final EffectSystem effectSystem;
private final DataFlowValueFactory dataFlowValueFactory;
public DataFlowAnalyzer(
@NotNull Iterable<AdditionalTypeChecker> additionalTypeCheckers,
@@ -68,7 +69,8 @@ public class DataFlowAnalyzer {
@NotNull KotlinBuiltIns builtIns,
@NotNull ExpressionTypingFacade facade,
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull EffectSystem effectSystem
@NotNull EffectSystem effectSystem,
@NotNull DataFlowValueFactory factory
) {
this.additionalTypeCheckers = additionalTypeCheckers;
this.constantExpressionEvaluator = constantExpressionEvaluator;
@@ -77,11 +79,12 @@ public class DataFlowAnalyzer {
this.facade = facade;
this.languageVersionSettings = languageVersionSettings;
this.effectSystem = effectSystem;
this.dataFlowValueFactory = factory;
}
// NB: use this method only for functions from 'Any'
@Nullable
private static FunctionDescriptor getOverriddenDescriptorFromClass(@NotNull FunctionDescriptor descriptor) {
private FunctionDescriptor getOverriddenDescriptorFromClass(@NotNull FunctionDescriptor descriptor) {
if (descriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return descriptor;
Collection<? extends FunctionDescriptor> overriddenDescriptors = descriptor.getOverriddenDescriptors();
if (overriddenDescriptors.isEmpty()) return descriptor;
@@ -95,7 +98,7 @@ public class DataFlowAnalyzer {
return null;
}
private static boolean typeHasOverriddenEquals(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
private boolean typeHasOverriddenEquals(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
Collection<SimpleFunctionDescriptor> members = type.getMemberScope().getContributedFunctions(
OperatorNameConventions.EQUALS, new KotlinLookupLocation(lookupElement));
for (FunctionDescriptor member : members) {
@@ -114,7 +117,7 @@ public class DataFlowAnalyzer {
}
// Returns true if we can prove that 'type' has equals method from 'Any' base type
public static boolean typeHasEqualsFromAny(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
public boolean typeHasEqualsFromAny(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
TypeConstructor constructor = type.getConstructor();
// Subtypes can override equals for non-final types
if (!constructor.isFinal()) return false;
@@ -171,8 +174,8 @@ public class DataFlowAnalyzer {
KotlinType rhsType = context.trace.getBindingContext().getType(right);
if (rhsType == null) return;
DataFlowValue leftValue = DataFlowValueFactory.createDataFlowValue(left, lhsType, context);
DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rhsType, context);
DataFlowValue leftValue = dataFlowValueFactory.createDataFlowValue(left, lhsType, context);
DataFlowValue rightValue = dataFlowValueFactory.createDataFlowValue(right, rhsType, context);
Boolean equals = null;
if (operationToken == KtTokens.EQEQ || operationToken == KtTokens.EQEQEQ) {
@@ -338,12 +341,12 @@ public class DataFlowAnalyzer {
}
@Nullable
public static SmartCastResult checkPossibleCast(
public SmartCastResult checkPossibleCast(
@NotNull KotlinType expressionType,
@NotNull KtExpression expression,
@NotNull ResolutionContext c
) {
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, expressionType, c);
DataFlowValue dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression, expressionType, c);
return SmartCastManager.Companion.checkAndRecordPossibleCast(dataFlowValue, c.expectedType, expression, c, null, false);
}
@@ -366,7 +369,7 @@ public class DataFlowAnalyzer {
}
@NotNull
public static KotlinTypeInfo illegalStatementType(@NotNull KtExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
public KotlinTypeInfo illegalStatementType(@NotNull KtExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
facade.checkStatementType(
expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
@@ -379,7 +382,7 @@ public class DataFlowAnalyzer {
@NotNull KotlinType type,
@NotNull ResolutionContext c
) {
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c);
DataFlowValue dataFlowValue = c.dataFlowValueFactory.createDataFlowValue(expression, type, c);
return getAllPossibleTypes(type, c, dataFlowValue, c.languageVersionSettings);
}
@@ -93,7 +93,8 @@ class DoubleColonExpressionResolver(
val reflectionTypes: ReflectionTypes,
val typeResolver: TypeResolver,
val languageVersionSettings: LanguageVersionSettings,
val additionalCheckers: Iterable<ClassLiteralChecker>
val additionalCheckers: Iterable<ClassLiteralChecker>,
val dataFlowValueFactory: DataFlowValueFactory
) {
private lateinit var expressionTypingServices: ExpressionTypingServices
@@ -112,7 +113,7 @@ class DoubleColonExpressionResolver(
if (result != null && !result.type.isError) {
val inherentType = result.type
val dataFlowInfo = (result as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression.receiverExpression!!, inherentType, c)
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression.receiverExpression!!, inherentType, c)
val type =
if (!dataFlowInfo.getStableNullability(dataFlowValue).canBeNull()) inherentType.makeNotNullable()
else inherentType
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
import org.jetbrains.kotlin.resolve.calls.CallResolver;
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
import org.jetbrains.kotlin.resolve.calls.checkers.RttiExpressionChecker;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.types.WrappedTypeFactory;
@@ -70,6 +71,7 @@ public class ExpressionTypingComponents {
/*package*/ DeprecationResolver deprecationResolver;
/*package*/ EffectSystem effectSystem;
/*package*/ ContractParsingServices contractParsingServices;
/*package*/ DataFlowValueFactory dataFlowValueFactory;
@Inject
public void setGlobalContext(@NotNull GlobalContext globalContext) {
@@ -240,4 +242,9 @@ public class ExpressionTypingComponents {
public void setContractParsingServices(@NotNull ContractParsingServices contractParsingServices) {
this.contractParsingServices = contractParsingServices;
}
@Inject
public void setDataFlowValueFactory(@NotNull DataFlowValueFactory dataFlowValueFactory) {
this.dataFlowValueFactory = dataFlowValueFactory;
}
}
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.StatementFilter;
import org.jetbrains.kotlin.resolve.calls.context.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.KotlinType;
@@ -35,9 +36,10 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
@NotNull LexicalScope scope,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull KotlinType expectedType,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return newContext(trace, scope, dataFlowInfo, expectedType, ContextDependency.INDEPENDENT, StatementFilter.NONE, languageVersionSettings);
return newContext(trace, scope, dataFlowInfo, expectedType, ContextDependency.INDEPENDENT, StatementFilter.NONE, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
@@ -48,10 +50,11 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
@NotNull KotlinType expectedType,
@NotNull ContextDependency contextDependency,
@NotNull StatementFilter statementFilter,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return newContext(trace, scope, dataFlowInfo, expectedType, contextDependency,
new ResolutionResultsCacheImpl(), statementFilter, false, languageVersionSettings);
new ResolutionResultsCacheImpl(), statementFilter, false, languageVersionSettings, dataFlowValueFactory);
}
@NotNull
@@ -61,7 +64,8 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
context.contextDependency, context.resolutionResultsCache,
context.statementFilter,
context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
context.callPosition, context.expressionContextProvider, context.languageVersionSettings,
context.dataFlowValueFactory);
}
@NotNull
@@ -72,7 +76,8 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
context.statementFilter,
context.isAnnotationContext, isDebuggerContext, context.collectAllCandidates,
context.callPosition, context.expressionContextProvider,
context.languageVersionSettings);
context.languageVersionSettings,
context.dataFlowValueFactory);
}
@NotNull
@@ -85,12 +90,13 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
@NotNull ResolutionResultsCache resolutionResultsCache,
@NotNull StatementFilter statementFilter,
boolean isAnnotationContext,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return new ExpressionTypingContext(
trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache,
statementFilter, isAnnotationContext, false, false,
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings);
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings, dataFlowValueFactory);
}
private ExpressionTypingContext(
@@ -106,11 +112,12 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache,
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider,
languageVersionSettings);
languageVersionSettings, dataFlowValueFactory);
}
@Override
@@ -125,12 +132,13 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
boolean collectAllCandidates,
@NotNull CallPosition callPosition,
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
@NotNull LanguageVersionSettings languageVersionSettings
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull DataFlowValueFactory dataFlowValueFactory
) {
return new ExpressionTypingContext(trace, scope, dataFlowInfo,
expectedType, contextDependency, resolutionResultsCache,
statementFilter, isAnnotationContext, isDebuggerContext,
collectAllCandidates, callPosition, expressionContextProvider,
languageVersionSettings);
languageVersionSettings, dataFlowValueFactory);
}
}
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
@@ -115,7 +114,8 @@ public class ExpressionTypingServices {
@NotNull ContextDependency contextDependency
) {
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace, scope, dataFlowInfo, expectedType, contextDependency, statementFilter, getLanguageVersionSettings()
trace, scope, dataFlowInfo, expectedType, contextDependency, statementFilter, getLanguageVersionSettings(),
expressionTypingComponents.dataFlowValueFactory
);
if (contextExpression != expression) {
context = context.replaceExpressionContextProvider(arg -> arg == expression ? contextExpression : null);
@@ -157,7 +157,8 @@ public class ExpressionTypingServices {
}
checkFunctionReturnType(function, ExpressionTypingContext.newContext(
trace,
functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, getLanguageVersionSettings()
functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, getLanguageVersionSettings(),
expressionTypingComponents.dataFlowValueFactory
));
}
@@ -225,7 +226,8 @@ public class ExpressionTypingServices {
expressionTypingComponents.overloadChecker);
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, getLanguageVersionSettings()
trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, getLanguageVersionSettings(),
expressionTypingComponents.dataFlowValueFactory
);
KotlinTypeInfo typeInfo = expressionTypingFacade.getTypeInfo(bodyExpression, context, function.hasBlockBody());
@@ -285,9 +287,9 @@ public class ExpressionTypingServices {
statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression,
blockLevelVisitor);
if (result.getType() != null && statementExpression.getParent() instanceof KtBlockExpression) {
DataFlowValue lastExpressionValue = DataFlowValueFactory.createDataFlowValue(
DataFlowValue lastExpressionValue = expressionTypingComponents.dataFlowValueFactory.createDataFlowValue(
statementExpression, result.getType(), context);
DataFlowValue blockExpressionValue = DataFlowValueFactory.createDataFlowValue(
DataFlowValue blockExpressionValue = expressionTypingComponents.dataFlowValueFactory.createDataFlowValue(
(KtBlockExpression) statementExpression.getParent(), result.getType(), context);
result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue,
expressionTypingComponents.languageVersionSettings));
@@ -352,8 +352,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
dataFlowInfo = resultInfo.getDataFlowInfo();
KotlinType rightType = resultInfo.getType();
if (left != null && expectedType != null && rightType != null) {
DataFlowValue leftValue = DataFlowValueFactory.createDataFlowValue(left, expectedType, context);
DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
DataFlowValue leftValue = components.dataFlowValueFactory.createDataFlowValue(left, expectedType, context);
DataFlowValue rightValue = components.dataFlowValueFactory.createDataFlowValue(right, rightType, context);
// We cannot say here anything new about rightValue except it has the same value as leftValue
resultInfo = resultInfo.replaceDataFlowInfo(dataFlowInfo.assign(leftValue, rightValue, components.languageVersionSettings));
}
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT
import org.jetbrains.kotlin.resolve.calls.smartcasts.ConditionalDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
import org.jetbrains.kotlin.resolve.checkers.PrimitiveNumericComparisonCallChecker
import org.jetbrains.kotlin.types.*
@@ -53,7 +52,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
val knownType = typeInfo.type
val typeReference = expression.typeReference
if (typeReference != null && knownType != null) {
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(leftHandSide, knownType, context)
val dataFlowValue = components.dataFlowValueFactory.createDataFlowValue(leftHandSide, knownType, context)
val conditionInfo = checkTypeForIs(context, expression, expression.isNegated, knownType, typeReference, dataFlowValue).thenInfo
val newDataFlowInfo = conditionInfo.and(typeInfo.dataFlowInfo)
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo)
@@ -104,7 +103,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
val subjectType = subjectTypeInfo?.type ?: ErrorUtils.createErrorType("Unknown type")
val jumpOutPossibleInSubject: Boolean = subjectTypeInfo?.jumpOutPossible ?: false
val subjectDataFlowValue = subjectExpression?.let {
DataFlowValueFactory.createDataFlowValue(it, subjectType, contextAfterSubject)
facade.components.dataFlowValueFactory.createDataFlowValue(it, subjectType, contextAfterSubject)
} ?: DataFlowValue.nullValue(components.builtIns)
val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(
@@ -114,7 +113,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
val whenReturnType = inferTypeForWhenExpression(expression, contextWithExpectedType, contextAfterSubject, dataFlowInfoForEntries)
val whenResultValue = whenReturnType?.let { DataFlowValueFactory.createDataFlowValue(expression, it, contextAfterSubject) }
val whenResultValue = whenReturnType?.let { facade.components.dataFlowValueFactory.createDataFlowValue(expression, it, contextAfterSubject) }
val branchesTypeInfo =
joinWhenExpressionBranches(expression, contextAfterSubject, whenReturnType, jumpOutPossibleInSubject, whenResultValue)
@@ -223,7 +222,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
val entryDataFlowInfo =
if (whenResultValue != null && entryType != null) {
val entryValue = DataFlowValueFactory.createDataFlowValue(entryExpression, entryType, contextAfterSubject)
val entryValue = facade.components.dataFlowValueFactory.createDataFlowValue(entryExpression, entryType, contextAfterSubject)
entryTypeInfo.dataFlowInfo.assign(whenResultValue, entryValue, components.languageVersionSettings)
} else {
entryTypeInfo.dataFlowInfo
@@ -288,7 +287,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
): Boolean {
val trace = TemporaryBindingTrace.create(contextBeforeSubject.trace, "Temporary trace for when subject nullability")
val subjectContext = contextBeforeSubject.replaceExpectedType(expectedType).replaceBindingTrace(trace)
val castResult = DataFlowAnalyzer.checkPossibleCast(
val castResult = facade.components.dataFlowAnalyzer.checkPossibleCast(
subjectType, KtPsiUtil.safeDeparenthesize(subjectExpression), subjectContext
)
if (castResult != null && castResult.isCorrect) {
@@ -428,7 +427,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
}
checkTypeCompatibility(newContext, type, subjectType, expression)
val expressionDataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, newContext)
val expressionDataFlowValue = facade.components.dataFlowValueFactory.createDataFlowValue(expression, type, newContext)
val subjectStableTypes =
listOf(subjectType) + context.dataFlowInfo.getStableTypes(subjectDataFlowValue, components.languageVersionSettings)
@@ -445,7 +444,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
return ConditionalDataFlowInfo(
result.thenInfo.equate(
subjectDataFlowValue, expressionDataFlowValue,
identityEquals = DataFlowAnalyzer.typeHasEqualsFromAny(subjectType, expression),
identityEquals = facade.components.dataFlowAnalyzer.typeHasEqualsFromAny(subjectType, expression),
languageVersionSettings = components.languageVersionSettings
),
result.elseInfo.disequate(
@@ -49,7 +49,7 @@ object SenselessComparisonChecker {
if (type == null || type.isError) return
val operationSign = expression.operationReference
val value = DataFlowValueFactory.createDataFlowValue(expr, type, context)
val value = context.dataFlowValueFactory.createDataFlowValue(expr, type, context)
val equality =
operationSign.getReferencedNameElementType() == KtTokens.EQEQ || operationSign.getReferencedNameElementType() == KtTokens.EQEQEQ
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorResolver
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
@@ -35,7 +36,8 @@ import org.jetbrains.kotlin.types.isError
class ValueParameterResolver(
private val expressionTypingServices: ExpressionTypingServices,
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory
) {
fun resolveValueParameters(
valueParameters: List<KtParameter>,
@@ -49,7 +51,7 @@ class ValueParameterResolver(
val contextForDefaultValue = ExpressionTypingContext.newContext(
trace, scopeForDefaultValue, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE,
languageVersionSettings
languageVersionSettings, dataFlowValueFactory
)
for ((descriptor, parameter) in valueParameterDescriptors.zip(valueParameters)) {
@@ -33,6 +33,8 @@ import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.ImportingScope;
@@ -154,7 +156,7 @@ public class ExpectedResolveDataUtil {
LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(environment.getConfiguration());
ExpressionTypingContext context = ExpressionTypingContext.newContext(
new BindingTraceContext(), lexicalScope,
DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings);
DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, new DataFlowValueFactoryImpl());
KtExpression callElement = KtPsiFactory(project).createExpression(name);
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DeprecationResolver
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.scopes.*
@@ -182,7 +183,8 @@ class ReferenceVariantsHelper(
bindingContext,
containingDeclaration,
dataFlowInfo,
resolutionFacade.frontendService<LanguageVersionSettings>()
resolutionFacade.frontendService<LanguageVersionSettings>(),
resolutionFacade.frontendService<DataFlowValueFactory>()
)
}.toSet()
@@ -246,7 +246,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
is DoubleColonLHS.Expression -> {
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext,
moduleDescriptor, stableSmartCastsOnly, languageVersionSettings)
moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
resolutionFacade.frontendService<DataFlowValueFactory>())
.map { ReceiverType(it, 0) }
}
}
@@ -304,7 +305,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
var receiverIndex = 0
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings)
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
resolutionFacade.frontendService<DataFlowValueFactory>())
types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) }
receiverIndex++
}
@@ -323,16 +325,18 @@ private fun receiverValueTypes(
bindingContext: BindingContext,
moduleDescriptor: ModuleDescriptor,
stableSmartCastsOnly: Boolean,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): 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
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(
receiverValue,
bindingContext,
moduleDescriptor,
dataFlowInfo,
languageVersionSettings
languageVersionSettings,
dataFlowValueFactory
)
}
else {
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -207,7 +208,8 @@ class ShadowedDeclarationsFilter(
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
val context = BasicCallResolutionContext.create(bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
false, /* languageVersionSettings */ resolutionFacade.frontendService())
false, /* languageVersionSettings */ resolutionFacade.frontendService(),
resolutionFacade.frontendService<DataFlowValueFactory>())
val callResolver = resolutionFacade.frontendService<CallResolver>()
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor }
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.FlexibleType
@@ -59,9 +60,10 @@ fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory
): List<KotlinType> {
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings)
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings, dataFlowValueFactory)
return variants.filter { type ->
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } }
}
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
@@ -338,6 +339,7 @@ object IDELightClassContexts {
private val codegenAffectingAnnotations: CodegenAffectingAnnotations,
private val callResolver: CallResolver,
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory,
constantExpressionEvaluator: ConstantExpressionEvaluator,
storageManager: StorageManager
) : AnnotationResolverImpl(callResolver, constantExpressionEvaluator, storageManager) {
@@ -361,7 +363,8 @@ object IDELightClassContexts {
BasicCallResolutionContext.create(
trace, scope, CallMaker.makeCall(null, null, annotationEntry), TypeUtils.NO_EXPECTED_TYPE,
DataFlowInfoFactory.EMPTY, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
true, languageVersionSettings
true, languageVersionSettings,
dataFlowValueFactory
),
annotationEntry.calleeExpression!!.constructorReferenceExpression!!,
annotationConstructor.returnType
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
@@ -40,7 +41,8 @@ import java.util.*
class IterableTypesDetection(
private val project: Project,
private val forLoopConventionsChecker: ForLoopConventionsChecker,
private val languageVersionSettings: LanguageVersionSettings
private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory
) {
companion object {
private val iteratorName = Name.identifier("iterator")
@@ -78,7 +80,7 @@ class IterableTypesDetection(
val expression = KtPsiFactory(project).createExpression("fake")
val context = ExpressionTypingContext.newContext(
BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings)
BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory)
val expressionReceiver = ExpressionReceiver.create(expression, type.type, context.trace.bindingContext)
val elementType = forLoopConventionsChecker.checkIterableConvention(expressionReceiver, context)
return elementType?.let { it.toFuzzyType(type.freeParameters) }
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.psi.KtExpression
@@ -43,6 +44,8 @@ class SmartCastCalculator(
receiver: KtExpression?,
resolutionFacade: ResolutionFacade
) {
private val dataFlowValueFactory = resolutionFacade.frontendService<DataFlowValueFactory>()
// keys are VariableDescriptor's and ThisReceiver's
private val entityToSmartCastInfo: Map<Any, SmartCastInfo> = processDataFlowInfo(
bindingContext.getDataFlowInfoBefore(contextElement),
@@ -82,7 +85,7 @@ class SmartCastCalculator(
val dataFlowValueToEntity: (DataFlowValue) -> Any?
if (receiver != null) {
val receiverType = bindingContext.getType(receiver) ?: return emptyMap()
val receiverIdentifierInfo = DataFlowValueFactory.createDataFlowValue(
val receiverIdentifierInfo = dataFlowValueFactory.createDataFlowValue(
receiver, receiverType, bindingContext, containingDeclarationOrModule
).identifierInfo
dataFlowValueToEntity = { value ->
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWithSmartCast
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.types.KotlinType
@@ -120,7 +121,8 @@ fun Call.resolveCandidates(
val callResolutionContext = BasicCallResolutionContext.create(
bindingTrace, resolutionScope, this, expectedType, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
false, resolutionFacade.frontendService<LanguageVersionSettings>()
false, resolutionFacade.frontendService<LanguageVersionSettings>(),
resolutionFacade.frontendService<DataFlowValueFactory>()
).replaceCollectAllCandidates(true)
val callResolver = resolutionFacade.frontendService<CallResolver>()
@@ -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
@@ -30,14 +30,13 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
abstract class AbstractDataFlowValueRenderingTest: KotlinLightCodeInsightFixtureTestCase() {
private fun IdentifierInfo.render(): String? = when (this) {
is DataFlowValueFactory.ExpressionIdentifierInfo -> expression.text
is IdentifierInfo.Expression -> expression.text
is IdentifierInfo.Receiver -> (value as? ImplicitReceiver)?.declarationDescriptor?.name?.let { "this@$it" }
is IdentifierInfo.Variable -> variable.name.asString()
is IdentifierInfo.PackageOrClass -> (descriptor as? PackageViewDescriptor)?.let { it.fqName.asString() }
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
@@ -52,6 +53,7 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
private val type: KotlinType?
private val uniqueConstants = mutableSetOf<Any>()
private val uniqueEnumNames = mutableSetOf<String>()
private val dataFlowValueFactory: DataFlowValueFactory = DataFlowValueFactoryImpl()
private val isExhaustive: Boolean
get() {
@@ -124,7 +126,7 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
val ktSubject = whenExpression.subjectExpression ?: return null
val subjectType = bindingContext().getType(ktSubject) ?: return null
val dataFlow = DataFlowValueFactory.createDataFlowValue(
val dataFlow = dataFlowValueFactory.createDataFlowValue(
ktSubject, subjectType, bindingContext(), context().declarationDescriptor ?: context().currentModule)
val languageVersionSettings = context().config.configuration.languageVersionSettings
val expectedTypes = bindingContext().getDataFlowInfoBefore(ktSubject).getStableTypes(dataFlow, languageVersionSettings) +
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -112,7 +112,7 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory {
val descriptor = context.declarationDescriptor ?: context.currentModule
val ktType = bindingContext.getType(expression) ?: return null
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression, ktType, bindingContext, descriptor)
val dataFlow = DataFlowValueFactoryImpl().createDataFlowValue(expression, ktType, bindingContext, descriptor)
val isPrimitiveFn = KotlinBuiltIns::isPrimitiveTypeOrNullablePrimitiveType
val languageVersionSettings = context.config.configuration.languageVersionSettings