diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ieee754.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ieee754.kt index 706e7cbe2fd..5ada2ef3cb4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ieee754.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ieee754.kt @@ -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, diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/RuntimeAssertions.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/RuntimeAssertions.kt index 310d2514b5d..2bfcab3ac0b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/RuntimeAssertions.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/RuntimeAssertions.kt @@ -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 diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt index cc5d09b759d..09b251793bc 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt @@ -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) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmArrayVariableInLoopAssignmentChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmArrayVariableInLoopAssignmentChecker.kt index de22323ee70..9ee8e379abf 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmArrayVariableInLoopAssignmentChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmArrayVariableInLoopAssignmentChecker.kt @@ -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)) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt index 1eb98ebf7c5..ec5c6d4d817 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt @@ -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 ) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectSystem.kt b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectSystem.kt index 9c30803fae4..882a55d2e2a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectSystem.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectSystem.kt @@ -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 } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt index 6c6fb0dd1f0..cae15b7248a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/contracts/EffectsExtractingVisitor.kt @@ -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() { 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, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index de0695ef5c9..48796d5dd30 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -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() useImpl() + useImpl() useImpl() useImpl() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt index e0ed66b400a..695cbae3b53 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.kt @@ -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 { - 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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 9bdaf28dc86..76643b5984f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -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 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); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt index 540cb070286..984ce27be53 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt @@ -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) ) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index 27a2acb537e..840743e1329 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -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, private val moduleDescriptor: ModuleDescriptor, private val deprecationResolver: DeprecationResolver, - private val effectSystem: EffectSystem + private val effectSystem: EffectSystem, + private val dataFlowValueFactory: DataFlowValueFactory ) { fun completeCall( context: BasicCallResolutionContext, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt index 23821605311..3c41fc42f7e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallExpressionResolver.kt @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index d634859d680..c2c7d382b5d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index b8aa75f997a..2572992aa19 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -61,7 +61,8 @@ class CandidateResolver( private val genericCandidateResolver: GenericCandidateResolver, private val reflectionTypes: ReflectionTypes, private val additionalTypeCheckers: Iterable, - private val smartCastManager: SmartCastManager + private val smartCastManager: SmartCastManager, + private val dataFlowValueFactory: DataFlowValueFactory ) { fun performResolutionForCandidateCall( context: CallCandidateResolutionContext, @@ -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()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index acef4dd8b11..9054764a095 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index 37ca11c27f4..fc596e8c6af 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -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 inferTypeArguments(context: CallCandidateResolutionContext): 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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt index 95c1c5c5a97..0d6866a746d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt @@ -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 } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java index 6fc61856d21..d876f139dd1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java @@ -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 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 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 boolean collectAllCandidates, @NotNull CallPosition callPosition, @NotNull Function1 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 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 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 boolean collectAllCandidates, @NotNull CallPosition callPosition, @NotNull Function1 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); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java index affdd873e56..73c98747ce6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java @@ -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 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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java index 82f90579bfb..e15d10aace3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/ResolutionContext.java @@ -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 expressionContextProvider, - @NotNull LanguageVersionSettings languageVersionSettings + @NotNull LanguageVersionSettings languageVersionSettings, + @NotNull DataFlowValueFactory factory ) { this.trace = trace; this.scope = scope; @@ -104,6 +109,7 @@ public abstract class ResolutionContext expressionContextProvider, - @NotNull LanguageVersionSettings languageVersionSettings + @NotNull LanguageVersionSettings languageVersionSettings, + @NotNull DataFlowValueFactory dataFlowValueFactory ); @NotNull @@ -130,14 +137,14 @@ public abstract class ResolutionContext expressionContextProvider) { return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter, - collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings); + collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory); } @Nullable diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt index 30537cbc23f..59140edfad0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/resolvedCallUtil.kt @@ -89,7 +89,7 @@ fun ResolvedCall<*>.getImplicitReceivers(): Collection = 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() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowValueFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowValueFactory.kt index 22a32a167c4..8552bf4efbf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowValueFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowValueFactory.kt @@ -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) + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt index 2419a6817e5..226efdab34e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt @@ -41,10 +41,11 @@ class SmartCastManager { bindingContext: BindingContext, containingDeclarationOrModule: DeclarationDescriptor, dataFlowInfo: DataFlowInfo, - languageVersionSettings: LanguageVersionSettings + languageVersionSettings: LanguageVersionSettings, + dataFlowValueFactory: DataFlowValueFactory ): List { val variants = getSmartCastVariantsExcludingReceiver( - bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings + bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings, dataFlowValueFactory ) val result = ArrayList(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 { - val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule) + val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule) return dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index 89498a745b5..8dd46acd1ef 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -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 ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index f277a5d31db..715aa32f98e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index 1a058645832..dc44ccd80f1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -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 } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index fbd14e1115d..0409d211494 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -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), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index d1970f025f2..77b33ad8f61 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -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("") @@ -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), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index eee735d7ea7..2f673b0453f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PrimitiveNumericComparisonCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PrimitiveNumericComparisonCallChecker.kt index 4b73347c8ce..9364471d1d0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PrimitiveNumericComparisonCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PrimitiveNumericComparisonCallChecker.kt @@ -83,7 +83,7 @@ object PrimitiveNumericComparisonCallChecker : CallChecker { private fun CallCheckerContext.getStableTypesForExpression(expression: KtExpression): List { 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() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index eaa4d19fb2e..2656993543f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java index 1d680be354b..b511aa08d31 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java index ffe01d572e7..619ea700236 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java @@ -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 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 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 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); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 65f5d9f90a9..7e4cdd50249 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -93,7 +93,8 @@ class DoubleColonExpressionResolver( val reflectionTypes: ReflectionTypes, val typeResolver: TypeResolver, val languageVersionSettings: LanguageVersionSettings, - val additionalCheckers: Iterable + val additionalCheckers: Iterable, + 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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index 825e4669f03..dd6ca3eb37c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -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; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java index 5c418cfe0b2..feabfb30ffa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java @@ -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 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 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); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java index 5178722d4cc..0e97ff7c83f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingServices.java @@ -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)); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java index 310689519e1..a0941eed1ee 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java @@ -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)); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt index 7d406ce28b1..6b854fc8990 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt @@ -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( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt index 451a09b4af8..7cd27ca323e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt index 15dca7c8981..647b24057f9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ValueParameterResolver.kt @@ -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, @@ -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)) { diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java index 21a5a706f8e..a4f602f4119 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java @@ -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); diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt index 2cc56d348e7..9b37eeb1cd0 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt @@ -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() + resolutionFacade.frontendService(), + resolutionFacade.frontendService() ) }.toSet() diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt index 9f43fc0ef85..26879cf0934 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt @@ -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()) .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()) 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 { - 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 { diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt index c4dc9e1b312..0ae2478ecff 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt @@ -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()) val callResolver = resolutionFacade.frontendService() val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context) val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt index f804278e9dc..589ddc45c52 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt @@ -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 { - 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 } } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt index 08061f141a7..79cb1ea3826 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/lightClasses/IDELightClassContexts.kt @@ -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 diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt index 705a48ea404..01a1f1c017c 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/IterableTypesDetection.kt @@ -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) } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/SmartCastCalculator.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/SmartCastCalculator.kt index 3c246bff45b..099d56ae544 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/SmartCastCalculator.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/SmartCastCalculator.kt @@ -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() + // keys are VariableDescriptor's and ThisReceiver's private val entityToSmartCastInfo: Map = 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 -> diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt index 3395c737dcc..33c4bc7b35c 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt @@ -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() + false, resolutionFacade.frontendService(), + resolutionFacade.frontendService() ).replaceCollectAllCandidates(true) val callResolver = resolutionFacade.frontendService() diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt index fc0d0805165..6d811c34f11 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt @@ -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() { 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() + 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 + ")" diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt index 723d39a7406..02e5a0ff2d6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt @@ -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()) + false, facade.frontendService(), + facade.frontendService()) val callResolver = facade.frontendService() val result = callResolver.resolveSimpleProperty(context) return result.isSuccess && result.resultingDescriptor.original == property diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt index a17c647f9b3..3baf5190157 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt @@ -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( diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFixes.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFixes.kt index aff6f4653fd..f9e4551c166 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFixes.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ExclExclCallFixes.kt @@ -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() + 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 } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt index cd75b8317fc..731cf9db5f9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt @@ -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() + val dataFlowValue = dataFlowValueFactory.createDataFlowValue(this, theType1, context, module) + + val possibleTypes = dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings) return if (possibleTypes.isNotEmpty()) possibleTypes.toTypedArray() else arrayOf(theType1) } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt index f0172b4d4a0..f6a4a0fd1d7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt @@ -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 { + val dataFlowValueFactory = expression.getResolutionFacade().frontendService() 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) } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt index 1f491d66a2b..ee79035cec7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt @@ -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() val possibleTypes = dataFlowInfo.getCollectedTypes( - DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract), - callElement.languageVersionSettings + dataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract), + callElement.languageVersionSettings ) if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null } else null diff --git a/idea/tests/org/jetbrains/kotlin/DataFlowValueRenderingTest.kt b/idea/tests/org/jetbrains/kotlin/DataFlowValueRenderingTest.kt index e7c80750c32..8ef7b334723 100644 --- a/idea/tests/org/jetbrains/kotlin/DataFlowValueRenderingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/DataFlowValueRenderingTest.kt @@ -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() } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt index 82b9f7ab00e..f5897b15c38 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt @@ -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() private val uniqueEnumNames = mutableSetOf() + 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) + diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt index 9f816e491a7..989a86394f7 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt @@ -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