Refactor DataFlowValueFactory into proper component
This commit is contained in:
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
@@ -56,7 +57,8 @@ fun legacyCalcTypeForIeee754ArithmeticIfNeeded(
|
||||
)
|
||||
}
|
||||
|
||||
val dataFlow = DataFlowValueFactory.createDataFlowValue(
|
||||
// NB. Using DataFlowValueFactoryImpl is a hack, but it is ok for 'legacy'
|
||||
val dataFlow = DataFlowValueFactoryImpl().createDataFlowValue(
|
||||
expression!!,
|
||||
ktType,
|
||||
bindingContext,
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.*
|
||||
@@ -92,7 +91,7 @@ class RuntimeAssertionsDataFlowExtras(
|
||||
private val expression: KtExpression
|
||||
) : RuntimeAssertionInfo.DataFlowExtras {
|
||||
private val dataFlowValue by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
DataFlowValueFactory.createDataFlowValue(expression, expressionType, c)
|
||||
c.dataFlowValueFactory.createDataFlowValue(expression, expressionType, c)
|
||||
}
|
||||
|
||||
override val canBeNull: Boolean
|
||||
|
||||
+4
-5
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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))
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ object ProtectedSyntheticExtensionCallChecker : CallChecker {
|
||||
|
||||
val receiverValue = resolvedCall.extensionReceiver as ReceiverValue
|
||||
val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getStableTypes(
|
||||
DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor),
|
||||
context.dataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor),
|
||||
context.languageVersionSettings
|
||||
)
|
||||
|
||||
|
||||
@@ -37,8 +37,9 @@ import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.ConditionalDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
|
||||
class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
|
||||
class EffectSystem(val languageVersionSettings: LanguageVersionSettings, val dataFlowValueFactory: DataFlowValueFactory) {
|
||||
|
||||
fun getDataFlowInfoForFinishedCall(
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
@@ -120,7 +121,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
|
||||
}
|
||||
|
||||
private fun getNonTrivialComputation(expression: KtExpression, trace: BindingTrace, moduleDescriptor: ModuleDescriptor): Computation? {
|
||||
val computation = EffectsExtractingVisitor(trace, moduleDescriptor).extractOrGetCached(expression)
|
||||
val computation = EffectsExtractingVisitor(trace, moduleDescriptor, dataFlowValueFactory).extractOrGetCached(expression)
|
||||
return if (computation == UNKNOWN_COMPUTATION) null else computation
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,8 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
*/
|
||||
class EffectsExtractingVisitor(
|
||||
private val trace: BindingTrace,
|
||||
private val moduleDescriptor: ModuleDescriptor
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) : KtVisitor<Computation, Unit>() {
|
||||
fun extractOrGetCached(element: KtElement): Computation {
|
||||
trace[BindingContext.EXPRESSION_EFFECTS, element]?.let { return it }
|
||||
@@ -143,7 +144,7 @@ class EffectsExtractingVisitor(
|
||||
}
|
||||
|
||||
private fun KtExpression.createDataFlowValue(): DataFlowValue? {
|
||||
return DataFlowValueFactory.createDataFlowValue(
|
||||
return dataFlowValueFactory.createDataFlowValue(
|
||||
expression = this,
|
||||
type = trace.getType(this) ?: return null,
|
||||
bindingContext = trace.bindingContext,
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.KotlinResolutionStatelessCallbacksImpl
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||
import org.jetbrains.kotlin.resolve.lazy.*
|
||||
@@ -64,6 +65,7 @@ fun StorageComponentContainer.configureModule(
|
||||
private fun StorageComponentContainer.configurePlatformIndependentComponents() {
|
||||
useImpl<SupertypeLoopCheckerImpl>()
|
||||
useImpl<KotlinResolutionStatelessCallbacksImpl>()
|
||||
useImpl<DataFlowValueFactoryImpl>()
|
||||
|
||||
useImpl<ExperimentalUsageChecker>()
|
||||
useImpl<ExperimentalUsageChecker.Overrides>()
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.ScopeUtils
|
||||
@@ -63,7 +64,8 @@ class DelegatedPropertyResolver(
|
||||
private val builtIns: KotlinBuiltIns,
|
||||
private val fakeCallResolver: FakeCallResolver,
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
|
||||
fun resolvePropertyDelegate(
|
||||
@@ -314,7 +316,7 @@ class DelegatedPropertyResolver(
|
||||
else
|
||||
TypeUtils.NO_EXPECTED_TYPE
|
||||
|
||||
val context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType, languageVersionSettings)
|
||||
val context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType, languageVersionSettings, dataFlowValueFactory)
|
||||
|
||||
val hasThis = propertyDescriptor.extensionReceiverParameter != null || propertyDescriptor.dispatchReceiverParameter != null
|
||||
|
||||
@@ -352,7 +354,7 @@ class DelegatedPropertyResolver(
|
||||
initializerScope: LexicalScope,
|
||||
dataFlowInfo: DataFlowInfo
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, NO_EXPECTED_TYPE, languageVersionSettings)
|
||||
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory)
|
||||
return getProvideDelegateMethod(propertyDescriptor, delegateExpression, delegateExpressionType, context)
|
||||
}
|
||||
|
||||
@@ -573,7 +575,7 @@ class DelegatedPropertyResolver(
|
||||
val contextForProvideDelegate = ExpressionTypingContext.newContext(
|
||||
traceToResolveConventionMethods, scopeForDelegate, delegateTypeInfo.dataFlowInfo,
|
||||
NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE,
|
||||
languageVersionSettings
|
||||
languageVersionSettings, dataFlowValueFactory
|
||||
)
|
||||
|
||||
val delegateTypeConstructor = delegateTypeInfo.type?.constructor
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
||||
@@ -88,6 +89,7 @@ public class DescriptorResolver {
|
||||
private final SyntheticResolveExtension syntheticResolveExtension;
|
||||
private final TypeApproximator typeApproximator;
|
||||
private final DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer;
|
||||
private final DataFlowValueFactory dataFlowValueFactory;
|
||||
|
||||
public DescriptorResolver(
|
||||
@NotNull AnnotationResolver annotationResolver,
|
||||
@@ -105,7 +107,8 @@ public class DescriptorResolver {
|
||||
@NotNull WrappedTypeFactory wrappedTypeFactory,
|
||||
@NotNull Project project,
|
||||
@NotNull TypeApproximator approximator,
|
||||
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer
|
||||
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
this.annotationResolver = annotationResolver;
|
||||
this.builtIns = builtIns;
|
||||
@@ -123,6 +126,7 @@ public class DescriptorResolver {
|
||||
this.syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project);
|
||||
typeApproximator = approximator;
|
||||
this.declarationReturnTypeSanitizer = declarationReturnTypeSanitizer;
|
||||
this.dataFlowValueFactory = dataFlowValueFactory;
|
||||
}
|
||||
|
||||
public List<KotlinType> resolveSupertypes(
|
||||
@@ -340,7 +344,8 @@ public class DescriptorResolver {
|
||||
scope,
|
||||
destructuringDeclaration, new TransientReceiver(type), /* initializer = */ null,
|
||||
ExpressionTypingContext.newContext(
|
||||
trace, scopeForDestructuring, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings
|
||||
trace, scopeForDestructuring, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE,
|
||||
languageVersionSettings, dataFlowValueFactory
|
||||
)
|
||||
);
|
||||
|
||||
@@ -785,7 +790,7 @@ public class DescriptorResolver {
|
||||
KtExpression initializer = destructuringDeclaration.getInitializer();
|
||||
|
||||
ExpressionTypingContext context = ExpressionTypingContext.newContext(
|
||||
trace, scopeForDeclarationResolution, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings
|
||||
trace, scopeForDeclarationResolution, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory
|
||||
);
|
||||
|
||||
ExpressionReceiver receiver = createReceiverForDestructuringDeclaration(destructuringDeclaration, context);
|
||||
|
||||
@@ -48,7 +48,8 @@ class LocalVariableResolver(
|
||||
private val annotationResolver: AnnotationResolver,
|
||||
private val variableTypeAndInitializerResolver: VariableTypeAndInitializerResolver,
|
||||
private val delegatedPropertyResolver: DelegatedPropertyResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
|
||||
fun process(
|
||||
@@ -108,7 +109,7 @@ class LocalVariableResolver(
|
||||
val dataFlowInfo = typeInfo.dataFlowInfo
|
||||
val type = typeInfo.type
|
||||
if (type != null) {
|
||||
val initializerDataFlowValue = DataFlowValueFactory.createDataFlowValue(initializer, type, context)
|
||||
val initializerDataFlowValue = dataFlowValueFactory.createDataFlowValue(initializer, type, context)
|
||||
if (!propertyDescriptor.isVar && initializerDataFlowValue.canBeBound) {
|
||||
context.trace.record(BindingContext.BOUND_INITIALIZER_VALUE, propertyDescriptor, initializerDataFlowValue)
|
||||
}
|
||||
@@ -116,7 +117,7 @@ class LocalVariableResolver(
|
||||
// We can comment this condition to take them into account, like here: var s: String? = "xyz"
|
||||
// In this case s will be not-nullable until it is changed
|
||||
if (property.typeReference == null) {
|
||||
val variableDataFlowValue = DataFlowValueFactory.createDataFlowValueForProperty(
|
||||
val variableDataFlowValue = dataFlowValueFactory.createDataFlowValueForProperty(
|
||||
property, propertyDescriptor, context.trace.bindingContext,
|
||||
DescriptorUtils.getContainingModuleOrNull(scope.ownerDescriptor)
|
||||
)
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSaf
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -61,7 +62,8 @@ class CallCompleter(
|
||||
private val callCheckers: Iterable<CallChecker>,
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val effectSystem: EffectSystem
|
||||
private val effectSystem: EffectSystem,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
fun <D : CallableDescriptor> completeCall(
|
||||
context: BasicCallResolutionContext,
|
||||
|
||||
@@ -73,7 +73,8 @@ class CallExpressionResolver(
|
||||
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
||||
private val builtIns: KotlinBuiltIns,
|
||||
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
private lateinit var expressionTypingServices: ExpressionTypingServices
|
||||
|
||||
@@ -343,7 +344,7 @@ class CallExpressionResolver(
|
||||
private fun getSafeOrUnsafeSelectorTypeInfo(receiver: Receiver, element: CallExpressionElement, context: ExpressionTypingContext):
|
||||
KotlinTypeInfo {
|
||||
var initialDataFlowInfoForArguments = context.dataFlowInfo
|
||||
val receiverDataFlowValue = (receiver as? ReceiverValue)?.let { DataFlowValueFactory.createDataFlowValue(it, context) }
|
||||
val receiverDataFlowValue = (receiver as? ReceiverValue)?.let { dataFlowValueFactory.createDataFlowValue(it, context) }
|
||||
val receiverCanBeNull = receiverDataFlowValue != null &&
|
||||
initialDataFlowInfoForArguments.getStableNullability(receiverDataFlowValue).canBeNull()
|
||||
if (receiverDataFlowValue != null && element.safe) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference;
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.PSICallResolver;
|
||||
@@ -76,6 +77,7 @@ public class CallResolver {
|
||||
private SyntheticScopes syntheticScopes;
|
||||
private NewResolutionOldInference newResolutionOldInference;
|
||||
private PSICallResolver PSICallResolver;
|
||||
private final DataFlowValueFactory dataFlowValueFactory;
|
||||
private final KotlinBuiltIns builtIns;
|
||||
private final LanguageVersionSettings languageVersionSettings;
|
||||
|
||||
@@ -83,10 +85,12 @@ public class CallResolver {
|
||||
|
||||
public CallResolver(
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
this.builtIns = builtIns;
|
||||
this.languageVersionSettings = languageVersionSettings;
|
||||
this.dataFlowValueFactory = dataFlowValueFactory;
|
||||
}
|
||||
|
||||
// component dependency cycle
|
||||
@@ -303,7 +307,7 @@ public class CallResolver {
|
||||
return resolveFunctionCall(
|
||||
BasicCallResolutionContext.create(
|
||||
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
isAnnotationContext, languageVersionSettings
|
||||
isAnnotationContext, languageVersionSettings, dataFlowValueFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -430,7 +434,8 @@ public class CallResolver {
|
||||
NO_EXPECTED_TYPE,
|
||||
dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
false,
|
||||
languageVersionSettings);
|
||||
languageVersionSettings,
|
||||
dataFlowValueFactory);
|
||||
|
||||
if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ class CandidateResolver(
|
||||
private val genericCandidateResolver: GenericCandidateResolver,
|
||||
private val reflectionTypes: ReflectionTypes,
|
||||
private val additionalTypeCheckers: Iterable<AdditionalTypeChecker>,
|
||||
private val smartCastManager: SmartCastManager
|
||||
private val smartCastManager: SmartCastManager,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
fun <D : CallableDescriptor> performResolutionForCandidateCall(
|
||||
context: CallCandidateResolutionContext<D>,
|
||||
@@ -384,7 +385,7 @@ class CandidateResolver(
|
||||
|
||||
val spreadElement = argument.getSpreadElement()
|
||||
if (spreadElement != null && !type.isFlexible() && type.isMarkedNullable) {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression, type, context)
|
||||
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(
|
||||
dataFlowValue, expectedType, expression, context,
|
||||
call = null, recordExpressionType = false
|
||||
@@ -530,7 +531,7 @@ class CandidateResolver(
|
||||
if (implicitInvokeCheck && call is CallForImplicitInvoke && call.isSafeCall()) {
|
||||
val outerCallReceiver = call.outerCall.explicitReceiver
|
||||
if (outerCallReceiver != call.explicitReceiver && outerCallReceiver is ReceiverValue) {
|
||||
val outerReceiverDataFlowValue = DataFlowValueFactory.createDataFlowValue(outerCallReceiver, this)
|
||||
val outerReceiverDataFlowValue = dataFlowValueFactory.createDataFlowValue(outerCallReceiver, this)
|
||||
val outerReceiverNullability = dataFlowInfo.getStableNullability(outerReceiverDataFlowValue)
|
||||
if (outerReceiverNullability.canBeNull() && !TypeUtils.isNullableType(expectedReceiverParameterType)) {
|
||||
nullableImplicitInvokeReceiver = true
|
||||
@@ -539,7 +540,7 @@ class CandidateResolver(
|
||||
}
|
||||
}
|
||||
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, this)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverArgument, this)
|
||||
val nullability = dataFlowInfo.getStableNullability(dataFlowValue)
|
||||
val expression = (receiverArgument as? ExpressionReceiver)?.expression
|
||||
if (nullability.canBeNull() && !nullability.canBeNonNull()) {
|
||||
|
||||
+4
-3
@@ -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
|
||||
|
||||
+3
-2
@@ -68,7 +68,8 @@ private val SPECIAL_FUNCTION_NAMES = ResolveConstruct.values().map { it.specialF
|
||||
class GenericCandidateResolver(
|
||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||
private val coroutineInferenceSupport: CoroutineInferenceSupport,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
fun <D : CallableDescriptor> inferTypeArguments(context: CallCandidateResolutionContext<D>): ResolutionStatus {
|
||||
val candidateCall = context.candidateCall
|
||||
@@ -328,7 +329,7 @@ class GenericCandidateResolver(
|
||||
val deparenthesizedArgument = KtPsiUtil.getLastElementDeparenthesized(argumentExpression, context.statementFilter)
|
||||
if (deparenthesizedArgument == null || type == null) return type
|
||||
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
|
||||
if (!dataFlowValue.isStable) return type
|
||||
|
||||
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings)
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.checkers.CheckerContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.types.DeferredType
|
||||
@@ -52,6 +53,9 @@ class CallCheckerContext @JvmOverloads constructor(
|
||||
val isAnnotationContext: Boolean
|
||||
get() = resolutionContext.isAnnotationContext
|
||||
|
||||
val dataFlowValueFactory: DataFlowValueFactory
|
||||
get() = resolutionContext.dataFlowValueFactory
|
||||
|
||||
override val languageVersionSettings: LanguageVersionSettings
|
||||
get() = resolutionContext.languageVersionSettings
|
||||
}
|
||||
|
||||
+13
-8
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
@@ -46,11 +47,12 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates,
|
||||
callPosition, expressionContextProvider, languageVersionSettings);
|
||||
callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -63,12 +65,14 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull CheckArgumentTypesMode checkArguments,
|
||||
boolean isAnnotationContext,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return new BasicCallResolutionContext(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
new ResolutionResultsCacheImpl(), null,
|
||||
StatementFilter.NONE, isAnnotationContext, false, false,
|
||||
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings);
|
||||
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings,
|
||||
dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -80,7 +84,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
context.trace, context.scope, call, context.expectedType, context.dataFlowInfo, context.contextDependency, checkArguments,
|
||||
context.resolutionResultsCache, dataFlowInfoForArguments,
|
||||
context.statementFilter, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings, context.dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -102,12 +106,13 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return new BasicCallResolutionContext(
|
||||
trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates,
|
||||
callPosition, expressionContextProvider, languageVersionSettings);
|
||||
callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -115,6 +120,6 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
return new BasicCallResolutionContext(
|
||||
trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates,
|
||||
callPosition, expressionContextProvider, languageVersionSettings);
|
||||
callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -59,11 +60,12 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, statementFilter, isAnnotationContext, isDebuggerContext,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
this.candidateCall = candidateCall;
|
||||
this.tracing = tracing;
|
||||
this.candidateResolveMode = candidateResolveMode;
|
||||
@@ -80,7 +82,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
context.resolutionResultsCache, context.dataFlowInfoForArguments,
|
||||
context.statementFilter,
|
||||
candidateResolveMode, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings, context.dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -92,7 +94,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache,
|
||||
context.dataFlowInfoForArguments, context.statementFilter,
|
||||
CandidateResolveMode.FULLY, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings, context.dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,12 +109,13 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return new CallCandidateResolutionContext<>(
|
||||
candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
resolutionResultsCache, dataFlowInfoForArguments, statementFilter,
|
||||
candidateResolveMode, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider,
|
||||
languageVersionSettings);
|
||||
languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
@@ -55,10 +56,12 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache,
|
||||
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings,
|
||||
dataFlowValueFactory);
|
||||
this.call = call;
|
||||
this.checkArguments = checkArguments;
|
||||
if (dataFlowInfoForArguments != null) {
|
||||
|
||||
+19
-12
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
@@ -64,6 +65,9 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
@NotNull
|
||||
public final LanguageVersionSettings languageVersionSettings;
|
||||
|
||||
@NotNull
|
||||
public final DataFlowValueFactory dataFlowValueFactory;
|
||||
|
||||
/**
|
||||
* Used for analyzing expression in the given context.
|
||||
* Should be used for going through parents to find containing function, loop etc.
|
||||
@@ -89,7 +93,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory factory
|
||||
) {
|
||||
this.trace = trace;
|
||||
this.scope = scope;
|
||||
@@ -104,6 +109,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
this.callPosition = callPosition;
|
||||
this.expressionContextProvider = expressionContextProvider;
|
||||
this.languageVersionSettings = languageVersionSettings;
|
||||
this.dataFlowValueFactory = factory;
|
||||
}
|
||||
|
||||
protected abstract Context create(
|
||||
@@ -117,7 +123,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
);
|
||||
|
||||
@NotNull
|
||||
@@ -130,14 +137,14 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
public Context replaceBindingTrace(@NotNull BindingTrace trace) {
|
||||
if (this.trace == trace) return self();
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceDataFlowInfo(@NotNull DataFlowInfo newDataFlowInfo) {
|
||||
if (newDataFlowInfo == dataFlowInfo) return self();
|
||||
return create(trace, scope, newDataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -145,28 +152,28 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
if (expectedType == newExpectedType) return self();
|
||||
return create(trace, scope, dataFlowInfo, newExpectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceScope(@NotNull LexicalScope newScope) {
|
||||
if (newScope == scope) return self();
|
||||
return create(trace, newScope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceContextDependency(@NotNull ContextDependency newContextDependency) {
|
||||
if (newContextDependency == contextDependency) return self();
|
||||
return create(trace, scope, dataFlowInfo, expectedType, newContextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceResolutionResultsCache(@NotNull ResolutionResultsCache newResolutionResultsCache) {
|
||||
if (newResolutionResultsCache == resolutionResultsCache) return self();
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, newResolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -177,25 +184,25 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
@NotNull
|
||||
public Context replaceCollectAllCandidates(boolean newCollectAllCandidates) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
newCollectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
newCollectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceStatementFilter(@NotNull StatementFilter statementFilter) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceCallPosition(@NotNull CallPosition callPosition) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Context replaceExpressionContextProvider(@NotNull Function1<KtExpression, KtExpression> expressionContextProvider) {
|
||||
return create(trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, statementFilter,
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings);
|
||||
collectAllCandidates, callPosition, expressionContextProvider, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -89,7 +89,7 @@ fun ResolvedCall<*>.getImplicitReceivers(): Collection<ReceiverValue> =
|
||||
|
||||
private fun ResolvedCall<*>.hasSafeNullableReceiver(context: CallResolutionContext<*>): Boolean {
|
||||
if (!call.isSafeCall()) return false
|
||||
val receiverValue = getExplicitReceiverValue()?.let { DataFlowValueFactory.createDataFlowValue(it, context) }
|
||||
val receiverValue = getExplicitReceiverValue()?.let { context.dataFlowValueFactory.createDataFlowValue(it, context) }
|
||||
?: return false
|
||||
return context.dataFlowInfo.getStableNullability(receiverValue).canBeNull()
|
||||
}
|
||||
|
||||
+89
-58
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -41,10 +41,11 @@ class SmartCastManager {
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): List<KotlinType> {
|
||||
val variants = getSmartCastVariantsExcludingReceiver(
|
||||
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings
|
||||
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings, dataFlowValueFactory
|
||||
)
|
||||
val result = ArrayList<KotlinType>(variants.size + 1)
|
||||
result.add(receiverToCast.type)
|
||||
@@ -64,7 +65,8 @@ class SmartCastManager {
|
||||
context.scope.ownerDescriptor,
|
||||
context.dataFlowInfo,
|
||||
receiverToCast,
|
||||
context.languageVersionSettings
|
||||
context.languageVersionSettings,
|
||||
context.dataFlowValueFactory
|
||||
)
|
||||
}
|
||||
|
||||
@@ -76,9 +78,10 @@ class SmartCastManager {
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
receiverToCast: ReceiverValue,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): Collection<KotlinType> {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings)
|
||||
}
|
||||
|
||||
|
||||
+6
-3
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSafeReceiver
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
|
||||
@@ -66,7 +67,8 @@ class KotlinToResolvedCallTransformer(
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
private val doubleColonExpressionResolver: DoubleColonExpressionResolver,
|
||||
private val additionalDiagnosticReporter: AdditionalDiagnosticReporter,
|
||||
private val moduleDescriptor: ModuleDescriptor
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
companion object {
|
||||
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
|
||||
@@ -99,7 +101,7 @@ class KotlinToResolvedCallTransformer(
|
||||
val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor()
|
||||
val ktPrimitiveCompleter = ResolvedAtomCompleter(
|
||||
resultSubstitutor, context.trace, context, this, expressionTypingServices, argumentTypeResolver,
|
||||
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor
|
||||
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, dataFlowValueFactory
|
||||
)
|
||||
|
||||
for (subKtPrimitive in candidate.subResolvedAtoms) {
|
||||
@@ -347,7 +349,7 @@ class KotlinToResolvedCallTransformer(
|
||||
val trackingTrace = TrackingBindingTrace(trace)
|
||||
val newContext = context.replaceBindingTrace(trackingTrace)
|
||||
val diagnosticReporter =
|
||||
DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall)
|
||||
DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall, context.dataFlowValueFactory)
|
||||
|
||||
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
||||
additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics)
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
@@ -210,7 +211,8 @@ internal fun createSimplePSICallArgument(
|
||||
contextForArgument.trace.bindingContext, contextForArgument.statementFilter,
|
||||
contextForArgument.scope.ownerDescriptor, valueArgument,
|
||||
contextForArgument.dataFlowInfo, typeInfoForArgument,
|
||||
contextForArgument.languageVersionSettings
|
||||
contextForArgument.languageVersionSettings,
|
||||
contextForArgument.dataFlowValueFactory
|
||||
)
|
||||
|
||||
internal fun createSimplePSICallArgument(
|
||||
@@ -220,7 +222,8 @@ internal fun createSimplePSICallArgument(
|
||||
valueArgument: ValueArgument,
|
||||
dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
typeInfoForArgument: KotlinTypeInfo,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): SimplePSIKotlinCallArgument? {
|
||||
|
||||
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
|
||||
@@ -235,7 +238,8 @@ internal fun createSimplePSICallArgument(
|
||||
ownerDescriptor, bindingContext,
|
||||
typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x }
|
||||
ExpressionReceiver.create(ktExpression, baseType, bindingContext),
|
||||
languageVersionSettings
|
||||
languageVersionSettings,
|
||||
dataFlowValueFactory
|
||||
).let {
|
||||
if (onlyResolvedCall == null) it.prepareReceiverRegardingCaptureTypes() else it
|
||||
}
|
||||
|
||||
+4
-3
@@ -528,16 +528,17 @@ class NewResolutionOldInference(
|
||||
}
|
||||
|
||||
fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) =
|
||||
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings)
|
||||
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings, dataFlowValueFactory)
|
||||
|
||||
fun transformToReceiverWithSmartCastInfo(
|
||||
containingDescriptor: DeclarationDescriptor,
|
||||
bindingContext: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
receiver: ReceiverValue,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): ReceiverValueWithSmartCastInfo {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
|
||||
return ReceiverValueWithSmartCastInfo(
|
||||
receiver,
|
||||
dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings),
|
||||
|
||||
@@ -61,7 +61,8 @@ class PSICallResolver(
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||
private val effectSystem: EffectSystem,
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
private val GIVEN_CANDIDATES_NAME = Name.special("<given candidates>")
|
||||
|
||||
@@ -152,7 +153,7 @@ class PSICallResolver(
|
||||
KotlinResolutionCallbacksImpl(
|
||||
context, expressionTypingServices, typeApproximator,
|
||||
argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer,
|
||||
constantExpressionEvaluator
|
||||
constantExpressionEvaluator, dataFlowValueFactory
|
||||
)
|
||||
|
||||
private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? {
|
||||
@@ -423,7 +424,7 @@ class PSICallResolver(
|
||||
|
||||
temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor)
|
||||
val dataFlowValue =
|
||||
DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
|
||||
dataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
|
||||
return ReceiverValueWithSmartCastInfo(
|
||||
variableReceiver,
|
||||
context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings),
|
||||
|
||||
+3
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ object PrimitiveNumericComparisonCallChecker : CallChecker {
|
||||
|
||||
private fun CallCheckerContext.getStableTypesForExpression(expression: KtExpression): List<KotlinType> {
|
||||
val type = trace.bindingContext.getType(expression) ?: return emptyList()
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(
|
||||
expression, type, trace.bindingContext, resolutionContext.scope.ownerDescriptor
|
||||
)
|
||||
val dataFlowInfo = trace.get(BindingContext.EXPRESSION_TYPE_INFO, expression)?.dataFlowInfo ?: return emptyList()
|
||||
|
||||
+15
-17
@@ -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);
|
||||
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -60,6 +60,7 @@ public class DataFlowAnalyzer {
|
||||
private final ExpressionTypingFacade facade;
|
||||
private final LanguageVersionSettings languageVersionSettings;
|
||||
private final EffectSystem effectSystem;
|
||||
private final DataFlowValueFactory dataFlowValueFactory;
|
||||
|
||||
public DataFlowAnalyzer(
|
||||
@NotNull Iterable<AdditionalTypeChecker> additionalTypeCheckers,
|
||||
@@ -68,7 +69,8 @@ public class DataFlowAnalyzer {
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull ExpressionTypingFacade facade,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull EffectSystem effectSystem
|
||||
@NotNull EffectSystem effectSystem,
|
||||
@NotNull DataFlowValueFactory factory
|
||||
) {
|
||||
this.additionalTypeCheckers = additionalTypeCheckers;
|
||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||
@@ -77,11 +79,12 @@ public class DataFlowAnalyzer {
|
||||
this.facade = facade;
|
||||
this.languageVersionSettings = languageVersionSettings;
|
||||
this.effectSystem = effectSystem;
|
||||
this.dataFlowValueFactory = factory;
|
||||
}
|
||||
|
||||
// NB: use this method only for functions from 'Any'
|
||||
@Nullable
|
||||
private static FunctionDescriptor getOverriddenDescriptorFromClass(@NotNull FunctionDescriptor descriptor) {
|
||||
private FunctionDescriptor getOverriddenDescriptorFromClass(@NotNull FunctionDescriptor descriptor) {
|
||||
if (descriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) return descriptor;
|
||||
Collection<? extends FunctionDescriptor> overriddenDescriptors = descriptor.getOverriddenDescriptors();
|
||||
if (overriddenDescriptors.isEmpty()) return descriptor;
|
||||
@@ -95,7 +98,7 @@ public class DataFlowAnalyzer {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean typeHasOverriddenEquals(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
|
||||
private boolean typeHasOverriddenEquals(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
|
||||
Collection<SimpleFunctionDescriptor> members = type.getMemberScope().getContributedFunctions(
|
||||
OperatorNameConventions.EQUALS, new KotlinLookupLocation(lookupElement));
|
||||
for (FunctionDescriptor member : members) {
|
||||
@@ -114,7 +117,7 @@ public class DataFlowAnalyzer {
|
||||
}
|
||||
|
||||
// Returns true if we can prove that 'type' has equals method from 'Any' base type
|
||||
public static boolean typeHasEqualsFromAny(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
|
||||
public boolean typeHasEqualsFromAny(@NotNull KotlinType type, @NotNull KtElement lookupElement) {
|
||||
TypeConstructor constructor = type.getConstructor();
|
||||
// Subtypes can override equals for non-final types
|
||||
if (!constructor.isFinal()) return false;
|
||||
@@ -171,8 +174,8 @@ public class DataFlowAnalyzer {
|
||||
KotlinType rhsType = context.trace.getBindingContext().getType(right);
|
||||
if (rhsType == null) return;
|
||||
|
||||
DataFlowValue leftValue = DataFlowValueFactory.createDataFlowValue(left, lhsType, context);
|
||||
DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rhsType, context);
|
||||
DataFlowValue leftValue = dataFlowValueFactory.createDataFlowValue(left, lhsType, context);
|
||||
DataFlowValue rightValue = dataFlowValueFactory.createDataFlowValue(right, rhsType, context);
|
||||
|
||||
Boolean equals = null;
|
||||
if (operationToken == KtTokens.EQEQ || operationToken == KtTokens.EQEQEQ) {
|
||||
@@ -338,12 +341,12 @@ public class DataFlowAnalyzer {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SmartCastResult checkPossibleCast(
|
||||
public SmartCastResult checkPossibleCast(
|
||||
@NotNull KotlinType expressionType,
|
||||
@NotNull KtExpression expression,
|
||||
@NotNull ResolutionContext c
|
||||
) {
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, expressionType, c);
|
||||
DataFlowValue dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression, expressionType, c);
|
||||
|
||||
return SmartCastManager.Companion.checkAndRecordPossibleCast(dataFlowValue, c.expectedType, expression, c, null, false);
|
||||
}
|
||||
@@ -366,7 +369,7 @@ public class DataFlowAnalyzer {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static KotlinTypeInfo illegalStatementType(@NotNull KtExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||
public KotlinTypeInfo illegalStatementType(@NotNull KtExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) {
|
||||
facade.checkStatementType(
|
||||
expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT));
|
||||
context.trace.report(EXPRESSION_EXPECTED.on(expression, expression));
|
||||
@@ -379,7 +382,7 @@ public class DataFlowAnalyzer {
|
||||
@NotNull KotlinType type,
|
||||
@NotNull ResolutionContext c
|
||||
) {
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c);
|
||||
DataFlowValue dataFlowValue = c.dataFlowValueFactory.createDataFlowValue(expression, type, c);
|
||||
return getAllPossibleTypes(type, c, dataFlowValue, c.languageVersionSettings);
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -93,7 +93,8 @@ class DoubleColonExpressionResolver(
|
||||
val reflectionTypes: ReflectionTypes,
|
||||
val typeResolver: TypeResolver,
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
val additionalCheckers: Iterable<ClassLiteralChecker>
|
||||
val additionalCheckers: Iterable<ClassLiteralChecker>,
|
||||
val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
private lateinit var expressionTypingServices: ExpressionTypingServices
|
||||
|
||||
@@ -112,7 +113,7 @@ class DoubleColonExpressionResolver(
|
||||
if (result != null && !result.type.isError) {
|
||||
val inherentType = result.type
|
||||
val dataFlowInfo = (result as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression.receiverExpression!!, inherentType, c)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression.receiverExpression!!, inherentType, c)
|
||||
val type =
|
||||
if (!dataFlowInfo.getStableNullability(dataFlowValue).canBeNull()) inherentType.makeNotNullable()
|
||||
else inherentType
|
||||
|
||||
+7
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+20
-12
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
@@ -35,9 +36,10 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
@NotNull LexicalScope scope,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull KotlinType expectedType,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return newContext(trace, scope, dataFlowInfo, expectedType, ContextDependency.INDEPENDENT, StatementFilter.NONE, languageVersionSettings);
|
||||
return newContext(trace, scope, dataFlowInfo, expectedType, ContextDependency.INDEPENDENT, StatementFilter.NONE, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -48,10 +50,11 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
@NotNull KotlinType expectedType,
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return newContext(trace, scope, dataFlowInfo, expectedType, contextDependency,
|
||||
new ResolutionResultsCacheImpl(), statementFilter, false, languageVersionSettings);
|
||||
new ResolutionResultsCacheImpl(), statementFilter, false, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -61,7 +64,8 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
context.contextDependency, context.resolutionResultsCache,
|
||||
context.statementFilter,
|
||||
context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings);
|
||||
context.callPosition, context.expressionContextProvider, context.languageVersionSettings,
|
||||
context.dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -72,7 +76,8 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
context.statementFilter,
|
||||
context.isAnnotationContext, isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition, context.expressionContextProvider,
|
||||
context.languageVersionSettings);
|
||||
context.languageVersionSettings,
|
||||
context.dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -85,12 +90,13 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return new ExpressionTypingContext(
|
||||
trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache,
|
||||
statementFilter, isAnnotationContext, false, false,
|
||||
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings);
|
||||
CallPosition.Unknown.INSTANCE, DEFAULT_EXPRESSION_CONTEXT_PROVIDER, languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
private ExpressionTypingContext(
|
||||
@@ -106,11 +112,12 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache,
|
||||
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition, expressionContextProvider,
|
||||
languageVersionSettings);
|
||||
languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,12 +132,13 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition,
|
||||
@NotNull Function1<KtExpression, KtExpression> expressionContextProvider,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
) {
|
||||
return new ExpressionTypingContext(trace, scope, dataFlowInfo,
|
||||
expectedType, contextDependency, resolutionResultsCache,
|
||||
statementFilter, isAnnotationContext, isDebuggerContext,
|
||||
collectAllCandidates, callPosition, expressionContextProvider,
|
||||
languageVersionSettings);
|
||||
languageVersionSettings, dataFlowValueFactory);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -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));
|
||||
|
||||
+2
-2
@@ -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));
|
||||
}
|
||||
|
||||
+7
-8
@@ -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(
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+4
-2
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
@@ -35,7 +36,8 @@ import org.jetbrains.kotlin.types.isError
|
||||
class ValueParameterResolver(
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
fun resolveValueParameters(
|
||||
valueParameters: List<KtParameter>,
|
||||
@@ -49,7 +51,7 @@ class ValueParameterResolver(
|
||||
|
||||
val contextForDefaultValue = ExpressionTypingContext.newContext(
|
||||
trace, scopeForDefaultValue, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE,
|
||||
languageVersionSettings
|
||||
languageVersionSettings, dataFlowValueFactory
|
||||
)
|
||||
|
||||
for ((descriptor, parameter) in valueParameterDescriptors.zip(valueParameters)) {
|
||||
|
||||
+3
-1
@@ -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);
|
||||
|
||||
|
||||
+3
-1
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
@@ -182,7 +183,8 @@ class ReferenceVariantsHelper(
|
||||
bindingContext,
|
||||
containingDeclaration,
|
||||
dataFlowInfo,
|
||||
resolutionFacade.frontendService<LanguageVersionSettings>()
|
||||
resolutionFacade.frontendService<LanguageVersionSettings>(),
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||
)
|
||||
}.toSet()
|
||||
|
||||
|
||||
@@ -246,7 +246,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
||||
is DoubleColonLHS.Expression -> {
|
||||
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
|
||||
return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext,
|
||||
moduleDescriptor, stableSmartCastsOnly, languageVersionSettings)
|
||||
moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>())
|
||||
.map { ReceiverType(it, 0) }
|
||||
}
|
||||
}
|
||||
@@ -304,7 +305,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
||||
var receiverIndex = 0
|
||||
|
||||
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
||||
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings)
|
||||
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>())
|
||||
types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) }
|
||||
receiverIndex++
|
||||
}
|
||||
@@ -323,16 +325,18 @@ private fun receiverValueTypes(
|
||||
bindingContext: BindingContext,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
stableSmartCastsOnly: Boolean,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): List<KotlinType> {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||
return if (dataFlowValue.isStable || !stableSmartCastsOnly) { // we don't include smart cast receiver types for "unstable" receiver value to mark members grayed
|
||||
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(
|
||||
receiverValue,
|
||||
bindingContext,
|
||||
moduleDescriptor,
|
||||
dataFlowInfo,
|
||||
languageVersionSettings
|
||||
languageVersionSettings,
|
||||
dataFlowValueFactory
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -207,7 +208,8 @@ class ShadowedDeclarationsFilter(
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
|
||||
val context = BasicCallResolutionContext.create(bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
|
||||
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
false, /* languageVersionSettings */ resolutionFacade.frontendService())
|
||||
false, /* languageVersionSettings */ resolutionFacade.frontendService(),
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>())
|
||||
val callResolver = resolutionFacade.frontendService<CallResolver>()
|
||||
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
|
||||
val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor }
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.FlexibleType
|
||||
@@ -59,9 +60,10 @@ fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): List<KotlinType> {
|
||||
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings)
|
||||
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings, dataFlowValueFactory)
|
||||
return variants.filter { type ->
|
||||
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } }
|
||||
}
|
||||
|
||||
+4
-1
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
@@ -338,6 +339,7 @@ object IDELightClassContexts {
|
||||
private val codegenAffectingAnnotations: CodegenAffectingAnnotations,
|
||||
private val callResolver: CallResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory,
|
||||
constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||
storageManager: StorageManager
|
||||
) : AnnotationResolverImpl(callResolver, constantExpressionEvaluator, storageManager) {
|
||||
@@ -361,7 +363,8 @@ object IDELightClassContexts {
|
||||
BasicCallResolutionContext.create(
|
||||
trace, scope, CallMaker.makeCall(null, null, annotationEntry), TypeUtils.NO_EXPECTED_TYPE,
|
||||
DataFlowInfoFactory.EMPTY, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
true, languageVersionSettings
|
||||
true, languageVersionSettings,
|
||||
dataFlowValueFactory
|
||||
),
|
||||
annotationEntry.calleeExpression!!.constructorReferenceExpression!!,
|
||||
annotationConstructor.returnType
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
|
||||
@@ -40,7 +41,8 @@ import java.util.*
|
||||
class IterableTypesDetection(
|
||||
private val project: Project,
|
||||
private val forLoopConventionsChecker: ForLoopConventionsChecker,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val dataFlowValueFactory: DataFlowValueFactory
|
||||
) {
|
||||
companion object {
|
||||
private val iteratorName = Name.identifier("iterator")
|
||||
@@ -78,7 +80,7 @@ class IterableTypesDetection(
|
||||
|
||||
val expression = KtPsiFactory(project).createExpression("fake")
|
||||
val context = ExpressionTypingContext.newContext(
|
||||
BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings)
|
||||
BindingTraceContext(), scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE, languageVersionSettings, dataFlowValueFactory)
|
||||
val expressionReceiver = ExpressionReceiver.create(expression, type.type, context.trace.bindingContext)
|
||||
val elementType = forLoopConventionsChecker.checkIterableConvention(expressionReceiver, context)
|
||||
return elementType?.let { it.toFuzzyType(type.freeParameters) }
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
@@ -43,6 +44,8 @@ class SmartCastCalculator(
|
||||
receiver: KtExpression?,
|
||||
resolutionFacade: ResolutionFacade
|
||||
) {
|
||||
private val dataFlowValueFactory = resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||
|
||||
// keys are VariableDescriptor's and ThisReceiver's
|
||||
private val entityToSmartCastInfo: Map<Any, SmartCastInfo> = processDataFlowInfo(
|
||||
bindingContext.getDataFlowInfoBefore(contextElement),
|
||||
@@ -82,7 +85,7 @@ class SmartCastCalculator(
|
||||
val dataFlowValueToEntity: (DataFlowValue) -> Any?
|
||||
if (receiver != null) {
|
||||
val receiverType = bindingContext.getType(receiver) ?: return emptyMap()
|
||||
val receiverIdentifierInfo = DataFlowValueFactory.createDataFlowValue(
|
||||
val receiverIdentifierInfo = dataFlowValueFactory.createDataFlowValue(
|
||||
receiver, receiverType, bindingContext, containingDeclarationOrModule
|
||||
).identifierInfo
|
||||
dataFlowValueToEntity = { value ->
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWithSmartCast
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -120,7 +121,8 @@ fun Call.resolveCandidates(
|
||||
val callResolutionContext = BasicCallResolutionContext.create(
|
||||
bindingTrace, resolutionScope, this, expectedType, dataFlowInfo,
|
||||
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
false, resolutionFacade.frontendService<LanguageVersionSettings>()
|
||||
false, resolutionFacade.frontendService<LanguageVersionSettings>(),
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||
).replaceCollectAllCandidates(true)
|
||||
val callResolver = resolutionFacade.frontendService<CallResolver>()
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
@@ -111,7 +113,8 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider<KtExpression>() {
|
||||
val expressionType = element.getType(bindingContext)
|
||||
val result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown"
|
||||
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor())
|
||||
val dataFlowValueFactory = element.getResolutionFacade().frontendService<DataFlowValueFactory>()
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor())
|
||||
val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue, element.languageVersionSettings)
|
||||
if (!types.isEmpty()) {
|
||||
return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")"
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
@@ -195,7 +196,8 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
|
||||
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace")
|
||||
val context = BasicCallResolutionContext.create(bindingTrace, resolutionScope, newCall, expectedType, dataFlowInfo,
|
||||
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
false, facade.frontendService<LanguageVersionSettings>())
|
||||
false, facade.frontendService<LanguageVersionSettings>(),
|
||||
facade.frontendService<DataFlowValueFactory>())
|
||||
val callResolver = facade.frontendService<CallResolver>()
|
||||
val result = callResolver.resolveSimpleProperty(context)
|
||||
return result.isSuccess && result.resultingDescriptor.original == property
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -163,7 +163,7 @@ fun KtExpression.isStable(context: BindingContext = this.analyze()): Boolean {
|
||||
if (this is KtConstantExpression || this is KtThisExpression) return true
|
||||
val descriptor = BindingContextUtils.extractVariableDescriptorFromReference(context, this)
|
||||
return descriptor is VariableDescriptor &&
|
||||
DataFlowValueFactory.isStableValue(descriptor, DescriptorUtils.getContainingModule(descriptor))
|
||||
DataFlowValueFactoryImpl.isStableValue(descriptor, DescriptorUtils.getContainingModule(descriptor))
|
||||
}
|
||||
|
||||
data class IfThenToSelectData(
|
||||
|
||||
@@ -30,7 +30,9 @@ import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -132,9 +134,12 @@ class AddExclExclCallFix(psiElement: PsiElement, val checkImplicitReceivers: Boo
|
||||
} else {
|
||||
context[BindingContext.EXPRESSION_TYPE_INFO, psiElement]?.let {
|
||||
val type = it.type
|
||||
|
||||
val dataFlowValueFactory = psiElement.getResolutionFacade().frontendService<DataFlowValueFactory>()
|
||||
|
||||
if (type != null) {
|
||||
val nullability = it.dataFlowInfo.getStableNullability(
|
||||
DataFlowValueFactory.createDataFlowValue(psiElement, type, context, psiElement.findModuleDescriptor())
|
||||
dataFlowValueFactory.createDataFlowValue(psiElement, type, context, psiElement.findModuleDescriptor())
|
||||
)
|
||||
if (!nullability.canBeNonNull()) return null
|
||||
}
|
||||
|
||||
+6
-2
@@ -20,9 +20,11 @@ import com.intellij.refactoring.psi.SearchUtils
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.project.builtIns
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -150,8 +152,10 @@ fun KtExpression.guessTypes(
|
||||
val theType1 = context.getType(this)
|
||||
if (theType1 != null && isAcceptable(theType1)) {
|
||||
val dataFlowInfo = context.getDataFlowInfoAfter(this)
|
||||
val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValue(this, theType1, context, module),
|
||||
languageVersionSettings)
|
||||
val dataFlowValueFactory = this.getResolutionFacade().frontendService<DataFlowValueFactory>()
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(this, theType1, context, module)
|
||||
|
||||
val possibleTypes = dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings)
|
||||
return if (possibleTypes.isNotEmpty()) possibleTypes.toTypedArray() else arrayOf(theType1)
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.ExtractableSubstringInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractableSubstringInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -182,15 +183,16 @@ data class ExtractionData(
|
||||
}
|
||||
|
||||
fun getPossibleTypes(expression: KtExpression, resolvedCall: ResolvedCall<*>?, context: BindingContext): Set<KotlinType> {
|
||||
val dataFlowValueFactory = expression.getResolutionFacade().frontendService<DataFlowValueFactory>()
|
||||
val dataFlowInfo = context.getDataFlowInfoAfter(expression)
|
||||
|
||||
resolvedCall?.getImplicitReceiverValue()?.let {
|
||||
return dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(it), expression.languageVersionSettings)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValueFactory.createDataFlowValueForStableReceiver(it), expression.languageVersionSettings)
|
||||
}
|
||||
|
||||
val type = resolvedCall?.resultingDescriptor?.returnType ?: return emptySet()
|
||||
val containingDescriptor = expression.getResolutionScope(context, expression.getResolutionFacade()).ownerDescriptor
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor)
|
||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValue, expression.languageVersionSettings)
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -27,10 +27,12 @@ import org.jetbrains.kotlin.cfg.pseudocode.getExpectedTypePredicate
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithReceivers
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -328,9 +330,11 @@ private fun suggestParameterType(
|
||||
val typeByDataFlowInfo = if (useSmartCastsIfPossible) {
|
||||
val callElement = resolvedCall!!.call.callElement
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfoAfter(callElement)
|
||||
|
||||
val dataFlowValueFactory = callElement.getResolutionFacade().frontendService<DataFlowValueFactory>()
|
||||
val possibleTypes = dataFlowInfo.getCollectedTypes(
|
||||
DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract),
|
||||
callElement.languageVersionSettings
|
||||
dataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract),
|
||||
callElement.languageVersionSettings
|
||||
)
|
||||
if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null
|
||||
} else null
|
||||
|
||||
@@ -30,14 +30,13 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
|
||||
abstract class AbstractDataFlowValueRenderingTest: KotlinLightCodeInsightFixtureTestCase() {
|
||||
|
||||
private fun IdentifierInfo.render(): String? = when (this) {
|
||||
is DataFlowValueFactory.ExpressionIdentifierInfo -> expression.text
|
||||
is IdentifierInfo.Expression -> expression.text
|
||||
is IdentifierInfo.Receiver -> (value as? ImplicitReceiver)?.declarationDescriptor?.name?.let { "this@$it" }
|
||||
is IdentifierInfo.Variable -> variable.name.asString()
|
||||
is IdentifierInfo.PackageOrClass -> (descriptor as? PackageViewDescriptor)?.let { it.fqName.asString() }
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoBefore
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
@@ -52,6 +53,7 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
|
||||
private val type: KotlinType?
|
||||
private val uniqueConstants = mutableSetOf<Any>()
|
||||
private val uniqueEnumNames = mutableSetOf<String>()
|
||||
private val dataFlowValueFactory: DataFlowValueFactory = DataFlowValueFactoryImpl()
|
||||
|
||||
private val isExhaustive: Boolean
|
||||
get() {
|
||||
@@ -124,7 +126,7 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
|
||||
val ktSubject = whenExpression.subjectExpression ?: return null
|
||||
val subjectType = bindingContext().getType(ktSubject) ?: return null
|
||||
|
||||
val dataFlow = DataFlowValueFactory.createDataFlowValue(
|
||||
val dataFlow = dataFlowValueFactory.createDataFlowValue(
|
||||
ktSubject, subjectType, bindingContext(), context().declarationDescriptor ?: context().currentModule)
|
||||
val languageVersionSettings = context().config.configuration.languageVersionSettings
|
||||
val expectedTypes = bindingContext().getDataFlowInfoBefore(ktSubject).getStableTypes(dataFlow, languageVersionSettings) +
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user