[Misc] Get rid of public Companion methods in SmartCastManager
It's necessary for type-refinement component to be injected
This commit is contained in:
committed by
Dmitry Savvinov
parent
e7d6a9508e
commit
529763b9bd
@@ -377,7 +377,7 @@ class CandidateResolver(
|
|||||||
val spreadElement = argument.getSpreadElement()
|
val spreadElement = argument.getSpreadElement()
|
||||||
if (spreadElement != null && !type.isFlexible() && type.isMarkedNullable) {
|
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(
|
val smartCastResult = smartCastManager.checkAndRecordPossibleCast(
|
||||||
dataFlowValue, expectedType, expression, context,
|
dataFlowValue, expectedType, expression, context,
|
||||||
call = null, recordExpressionType = false
|
call = null, recordExpressionType = false
|
||||||
)
|
)
|
||||||
@@ -544,11 +544,10 @@ class CandidateResolver(
|
|||||||
} else if (!nullableImplicitInvokeReceiver && smartCastNeeded) {
|
} else if (!nullableImplicitInvokeReceiver && smartCastNeeded) {
|
||||||
// Look if smart cast has some useful nullability info
|
// Look if smart cast has some useful nullability info
|
||||||
|
|
||||||
val smartCastResult = SmartCastManager.checkAndRecordPossibleCast(
|
val smartCastResult = smartCastManager.checkAndRecordPossibleCast(
|
||||||
dataFlowValue, expectedReceiverParameterType,
|
dataFlowValue, expectedReceiverParameterType,
|
||||||
{ possibleSmartCast -> isCandidateVisibleOrExtensionReceiver(receiverArgument, possibleSmartCast, isDispatchReceiver) },
|
|
||||||
expression, this, candidateCall.call, recordExpressionType = true
|
expression, this, candidateCall.call, recordExpressionType = true
|
||||||
)
|
) { possibleSmartCast -> isCandidateVisibleOrExtensionReceiver(receiverArgument, possibleSmartCast, isDispatchReceiver) }
|
||||||
|
|
||||||
if (smartCastResult == null) {
|
if (smartCastResult == null) {
|
||||||
if (notNullReceiverExpected) {
|
if (notNullReceiverExpected) {
|
||||||
|
|||||||
+5
-5
@@ -39,7 +39,8 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
val context: BasicCallResolutionContext,
|
val context: BasicCallResolutionContext,
|
||||||
val psiKotlinCall: PSIKotlinCall,
|
val psiKotlinCall: PSIKotlinCall,
|
||||||
val dataFlowValueFactory: DataFlowValueFactory,
|
val dataFlowValueFactory: DataFlowValueFactory,
|
||||||
val allDiagnostics: List<KotlinCallDiagnostic>
|
val allDiagnostics: List<KotlinCallDiagnostic>,
|
||||||
|
private val smartCastManager: SmartCastManager
|
||||||
) : DiagnosticReporter {
|
) : DiagnosticReporter {
|
||||||
private val trace = context.trace as TrackingBindingTrace
|
private val trace = context.trace as TrackingBindingTrace
|
||||||
private val tracingStrategy: TracingStrategy get() = psiKotlinCall.tracingStrategy
|
private val tracingStrategy: TracingStrategy get() = psiKotlinCall.tracingStrategy
|
||||||
@@ -195,7 +196,7 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
)
|
)
|
||||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context)
|
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context)
|
||||||
val call = if (call.callElement is KtBinaryExpression) null else call
|
val call = if (call.callElement is KtBinaryExpression) null else call
|
||||||
SmartCastManager.checkAndRecordPossibleCast(
|
smartCastManager.checkAndRecordPossibleCast(
|
||||||
dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call,
|
dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call,
|
||||||
recordExpressionType = true
|
recordExpressionType = true
|
||||||
)
|
)
|
||||||
@@ -204,7 +205,7 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
trace.markAsReported()
|
trace.markAsReported()
|
||||||
val receiverValue = expressionArgument.receiver.receiverValue
|
val receiverValue = expressionArgument.receiver.receiverValue
|
||||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, context)
|
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, context)
|
||||||
SmartCastManager.checkAndRecordPossibleCast(
|
smartCastManager.checkAndRecordPossibleCast(
|
||||||
dataFlowValue, smartCastDiagnostic.smartCastType, (receiverValue as? ExpressionReceiver)?.expression, context, call,
|
dataFlowValue, smartCastDiagnostic.smartCastType, (receiverValue as? ExpressionReceiver)?.expression, context, call,
|
||||||
recordExpressionType = true
|
recordExpressionType = true
|
||||||
)
|
)
|
||||||
@@ -340,6 +341,5 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val NewConstraintError.upperKotlinType get() = upperType as KotlinType
|
val NewConstraintError.upperKotlinType get() = upperType as KotlinType
|
||||||
val NewConstraintError.lowerKotlinType get() = lowerType as KotlinType
|
val NewConstraintError.lowerKotlinType get() = lowerType as KotlinType
|
||||||
|
|||||||
+77
-88
@@ -119,13 +119,89 @@ class SmartCastManager {
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun checkAndRecordPossibleCast(
|
||||||
|
dataFlowValue: DataFlowValue,
|
||||||
|
expectedType: KotlinType,
|
||||||
|
expression: KtExpression?,
|
||||||
|
c: ResolutionContext<*>,
|
||||||
|
call: Call?,
|
||||||
|
recordExpressionType: Boolean,
|
||||||
|
additionalPredicate: ((KotlinType) -> Boolean)? = null
|
||||||
|
): SmartCastResult? {
|
||||||
|
val calleeExpression = call?.calleeExpression
|
||||||
|
val expectedTypes = if (c.languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
|
||||||
|
expectedType.expandIntersectionTypeIfNecessary()
|
||||||
|
else
|
||||||
|
listOf(expectedType)
|
||||||
|
|
||||||
|
for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings)) {
|
||||||
|
if (expectedTypes.any { ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, it) } &&
|
||||||
|
(additionalPredicate == null || additionalPredicate(possibleType))
|
||||||
|
) {
|
||||||
|
if (expression != null) {
|
||||||
|
recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType)
|
||||||
|
} else if (calleeExpression != null && dataFlowValue.isStable) {
|
||||||
|
val receiver = (dataFlowValue.identifierInfo as? IdentifierInfo.Receiver)?.value
|
||||||
|
if (receiver is ImplicitReceiver) {
|
||||||
|
val oldSmartCasts = c.trace[IMPLICIT_RECEIVER_SMARTCAST, calleeExpression]
|
||||||
|
val newSmartCasts = ImplicitSmartCasts(receiver, possibleType)
|
||||||
|
if (oldSmartCasts != null) {
|
||||||
|
val oldType = oldSmartCasts.receiverTypes[receiver]
|
||||||
|
if (oldType != null && oldType != possibleType) {
|
||||||
|
throw AssertionError(
|
||||||
|
"Rewriting key $receiver for implicit smart cast on ${calleeExpression.text}: " +
|
||||||
|
"was $oldType, now $possibleType"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.trace.record(IMPLICIT_RECEIVER_SMARTCAST, calleeExpression,
|
||||||
|
oldSmartCasts?.let { it + newSmartCasts } ?: newSmartCasts)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SmartCastResult(possibleType, dataFlowValue.isStable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c.dataFlowInfo.getCollectedNullability(dataFlowValue).canBeNull() && !expectedType.isMarkedNullable) {
|
||||||
|
// Handling cases like:
|
||||||
|
// fun bar(x: Any) {}
|
||||||
|
// fun <T : Any?> foo(x: T) {
|
||||||
|
// if (x != null) {
|
||||||
|
// bar(x) // Should be allowed with smart cast
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// It doesn't handled by lower code with getPossibleTypes because smart cast of T after `x != null` is still has same type T.
|
||||||
|
// But at the same time we're sure that `x` can't be null and just check for such cases manually
|
||||||
|
|
||||||
|
// E.g. in case x!! when x has type of T where T is type parameter with nullable upper bounds
|
||||||
|
// x!! is immanently not null (see DataFlowValueFactory.createDataFlowValue for expression)
|
||||||
|
val immanentlyNotNull = !dataFlowValue.immanentNullability.canBeNull()
|
||||||
|
val nullableExpectedType = TypeUtils.makeNullable(expectedType)
|
||||||
|
|
||||||
|
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(dataFlowValue.type, nullableExpectedType) &&
|
||||||
|
(additionalPredicate == null || additionalPredicate(dataFlowValue.type))
|
||||||
|
) {
|
||||||
|
if (!immanentlyNotNull && expression != null) {
|
||||||
|
recordCastOrError(expression, dataFlowValue.type, c.trace, dataFlowValue, call, recordExpressionType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return SmartCastResult(dataFlowValue.type, immanentlyNotNull || dataFlowValue.isStable)
|
||||||
|
}
|
||||||
|
return checkAndRecordPossibleCast(dataFlowValue, nullableExpectedType, expression, c, call, recordExpressionType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
enum class ReceiverSmartCastResult {
|
enum class ReceiverSmartCastResult {
|
||||||
OK,
|
OK,
|
||||||
SMARTCAST_NEEDED_OR_NOT_NULL_EXPECTED
|
SMARTCAST_NEEDED_OR_NOT_NULL_EXPECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
// REVIEW: make it non-static too?
|
||||||
private fun recordCastOrError(
|
private fun recordCastOrError(
|
||||||
expression: KtExpression,
|
expression: KtExpression,
|
||||||
type: KotlinType,
|
type: KotlinType,
|
||||||
@@ -158,92 +234,5 @@ class SmartCastManager {
|
|||||||
trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.text, dataFlowValue.kind.description))
|
trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.text, dataFlowValue.kind.description))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkAndRecordPossibleCast(
|
|
||||||
dataFlowValue: DataFlowValue,
|
|
||||||
expectedType: KotlinType,
|
|
||||||
expression: KtExpression?,
|
|
||||||
c: ResolutionContext<*>,
|
|
||||||
call: Call?,
|
|
||||||
recordExpressionType: Boolean
|
|
||||||
): SmartCastResult? {
|
|
||||||
return checkAndRecordPossibleCast(dataFlowValue, expectedType, null, expression, c, call, recordExpressionType)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkAndRecordPossibleCast(
|
|
||||||
dataFlowValue: DataFlowValue,
|
|
||||||
expectedType: KotlinType,
|
|
||||||
additionalPredicate: ((KotlinType) -> Boolean)?,
|
|
||||||
expression: KtExpression?,
|
|
||||||
c: ResolutionContext<*>,
|
|
||||||
call: Call?,
|
|
||||||
recordExpressionType: Boolean
|
|
||||||
): SmartCastResult? {
|
|
||||||
val calleeExpression = call?.calleeExpression
|
|
||||||
val expectedTypes = if (c.languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
|
|
||||||
expectedType.expandIntersectionTypeIfNecessary()
|
|
||||||
else
|
|
||||||
listOf(expectedType)
|
|
||||||
|
|
||||||
for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings)) {
|
|
||||||
if (expectedTypes.any { ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, it) } &&
|
|
||||||
(additionalPredicate == null || additionalPredicate(possibleType))
|
|
||||||
) {
|
|
||||||
if (expression != null) {
|
|
||||||
recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType)
|
|
||||||
} else if (calleeExpression != null && dataFlowValue.isStable) {
|
|
||||||
val receiver = (dataFlowValue.identifierInfo as? IdentifierInfo.Receiver)?.value
|
|
||||||
if (receiver is ImplicitReceiver) {
|
|
||||||
val oldSmartCasts = c.trace[IMPLICIT_RECEIVER_SMARTCAST, calleeExpression]
|
|
||||||
val newSmartCasts = ImplicitSmartCasts(receiver, possibleType)
|
|
||||||
if (oldSmartCasts != null) {
|
|
||||||
val oldType = oldSmartCasts.receiverTypes[receiver]
|
|
||||||
if (oldType != null && oldType != possibleType) {
|
|
||||||
throw AssertionError(
|
|
||||||
"Rewriting key $receiver for implicit smart cast on ${calleeExpression.text}: " +
|
|
||||||
"was $oldType, now $possibleType"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.trace.record(IMPLICIT_RECEIVER_SMARTCAST, calleeExpression,
|
|
||||||
oldSmartCasts?.let { it + newSmartCasts } ?: newSmartCasts)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SmartCastResult(possibleType, dataFlowValue.isStable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c.dataFlowInfo.getCollectedNullability(dataFlowValue).canBeNull() && !expectedType.isMarkedNullable) {
|
|
||||||
// Handling cases like:
|
|
||||||
// fun bar(x: Any) {}
|
|
||||||
// fun <T : Any?> foo(x: T) {
|
|
||||||
// if (x != null) {
|
|
||||||
// bar(x) // Should be allowed with smart cast
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// It doesn't handled by lower code with getPossibleTypes because smart cast of T after `x != null` is still has same type T.
|
|
||||||
// But at the same time we're sure that `x` can't be null and just check for such cases manually
|
|
||||||
|
|
||||||
// E.g. in case x!! when x has type of T where T is type parameter with nullable upper bounds
|
|
||||||
// x!! is immanently not null (see DataFlowValueFactory.createDataFlowValue for expression)
|
|
||||||
val immanentlyNotNull = !dataFlowValue.immanentNullability.canBeNull()
|
|
||||||
val nullableExpectedType = TypeUtils.makeNullable(expectedType)
|
|
||||||
|
|
||||||
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(dataFlowValue.type, nullableExpectedType) &&
|
|
||||||
(additionalPredicate == null || additionalPredicate(dataFlowValue.type))
|
|
||||||
) {
|
|
||||||
if (!immanentlyNotNull && expression != null) {
|
|
||||||
recordCastOrError(expression, dataFlowValue.type, c.trace, dataFlowValue, call, recordExpressionType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return SmartCastResult(dataFlowValue.type, immanentlyNotNull || dataFlowValue.isStable)
|
|
||||||
}
|
|
||||||
return checkAndRecordPossibleCast(dataFlowValue, nullableExpectedType, expression, c, call, recordExpressionType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.makeNullableTypeIfSaf
|
|||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||||
@@ -69,7 +70,8 @@ class KotlinToResolvedCallTransformer(
|
|||||||
private val moduleDescriptor: ModuleDescriptor,
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
private val dataFlowValueFactory: DataFlowValueFactory,
|
private val dataFlowValueFactory: DataFlowValueFactory,
|
||||||
private val builtIns: KotlinBuiltIns,
|
private val builtIns: KotlinBuiltIns,
|
||||||
private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate
|
private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate,
|
||||||
|
private val smartCastManager: SmartCastManager
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
|
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
|
||||||
@@ -471,7 +473,8 @@ class KotlinToResolvedCallTransformer(
|
|||||||
newContext,
|
newContext,
|
||||||
completedCallAtom.atom.psiKotlinCall,
|
completedCallAtom.atom.psiKotlinCall,
|
||||||
context.dataFlowValueFactory,
|
context.dataFlowValueFactory,
|
||||||
allDiagnostics
|
allDiagnostics,
|
||||||
|
smartCastManager
|
||||||
)
|
)
|
||||||
|
|
||||||
for (diagnostic in allDiagnostics) {
|
for (diagnostic in allDiagnostics) {
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public class DataFlowAnalyzer {
|
|||||||
private final LanguageVersionSettings languageVersionSettings;
|
private final LanguageVersionSettings languageVersionSettings;
|
||||||
private final EffectSystem effectSystem;
|
private final EffectSystem effectSystem;
|
||||||
private final DataFlowValueFactory dataFlowValueFactory;
|
private final DataFlowValueFactory dataFlowValueFactory;
|
||||||
|
private final SmartCastManager smartCastManager;
|
||||||
|
|
||||||
public DataFlowAnalyzer(
|
public DataFlowAnalyzer(
|
||||||
@NotNull Iterable<AdditionalTypeChecker> additionalTypeCheckers,
|
@NotNull Iterable<AdditionalTypeChecker> additionalTypeCheckers,
|
||||||
@@ -70,7 +71,8 @@ public class DataFlowAnalyzer {
|
|||||||
@NotNull ExpressionTypingFacade facade,
|
@NotNull ExpressionTypingFacade facade,
|
||||||
@NotNull LanguageVersionSettings languageVersionSettings,
|
@NotNull LanguageVersionSettings languageVersionSettings,
|
||||||
@NotNull EffectSystem effectSystem,
|
@NotNull EffectSystem effectSystem,
|
||||||
@NotNull DataFlowValueFactory factory
|
@NotNull DataFlowValueFactory factory,
|
||||||
|
@NotNull SmartCastManager smartCastManager
|
||||||
) {
|
) {
|
||||||
this.additionalTypeCheckers = additionalTypeCheckers;
|
this.additionalTypeCheckers = additionalTypeCheckers;
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
@@ -80,6 +82,7 @@ public class DataFlowAnalyzer {
|
|||||||
this.languageVersionSettings = languageVersionSettings;
|
this.languageVersionSettings = languageVersionSettings;
|
||||||
this.effectSystem = effectSystem;
|
this.effectSystem = effectSystem;
|
||||||
this.dataFlowValueFactory = factory;
|
this.dataFlowValueFactory = factory;
|
||||||
|
this.smartCastManager = smartCastManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: use this method only for functions from 'Any'
|
// NB: use this method only for functions from 'Any'
|
||||||
@@ -349,7 +352,7 @@ public class DataFlowAnalyzer {
|
|||||||
) {
|
) {
|
||||||
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);
|
return smartCastManager.checkAndRecordPossibleCast(dataFlowValue, c.expectedType, expression, c, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordExpectedType(@NotNull BindingTrace trace, @NotNull KtExpression expression, @NotNull KotlinType expectedType) {
|
public void recordExpectedType(@NotNull BindingTrace trace, @NotNull KtExpression expression, @NotNull KotlinType expectedType) {
|
||||||
|
|||||||
@@ -133,8 +133,7 @@ sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallTyp
|
|||||||
class DOT(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.DOT>(CallType.DOT, receiver)
|
class DOT(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.DOT>(CallType.DOT, receiver)
|
||||||
class SAFE(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.SAFE>(CallType.SAFE, receiver)
|
class SAFE(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.SAFE>(CallType.SAFE, receiver)
|
||||||
class SUPER_MEMBERS(receiver: KtSuperExpression) : CallTypeAndReceiver<KtSuperExpression, CallType.SUPER_MEMBERS>(
|
class SUPER_MEMBERS(receiver: KtSuperExpression) : CallTypeAndReceiver<KtSuperExpression, CallType.SUPER_MEMBERS>(
|
||||||
CallType.SUPER_MEMBERS,
|
CallType.SUPER_MEMBERS, receiver
|
||||||
receiver
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class INFIX(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.INFIX>(CallType.INFIX, receiver)
|
class INFIX(receiver: KtExpression) : CallTypeAndReceiver<KtExpression, CallType.INFIX>(CallType.INFIX, receiver)
|
||||||
@@ -275,8 +274,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
|||||||
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
|
val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext)
|
||||||
receiverValueTypes(
|
receiverValueTypes(
|
||||||
receiverValue, lhs.dataFlowInfo, bindingContext,
|
receiverValue, lhs.dataFlowInfo, bindingContext,
|
||||||
moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
|
moduleDescriptor, stableSmartCastsOnly,
|
||||||
resolutionFacade.frontendService()
|
resolutionFacade
|
||||||
).map { ReceiverType(it, 0) }
|
).map { ReceiverType(it, 0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,8 +338,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
|||||||
|
|
||||||
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
||||||
val types = receiverValueTypes(
|
val types = receiverValueTypes(
|
||||||
receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
|
receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly,
|
||||||
resolutionFacade.frontendService()
|
resolutionFacade
|
||||||
)
|
)
|
||||||
|
|
||||||
types.mapTo(result) { type -> ReceiverType(type, receiverIndex, receiverValue.takeIf { implicit }) }
|
types.mapTo(result) { type -> ReceiverType(type, receiverIndex, receiverValue.takeIf { implicit }) }
|
||||||
@@ -362,12 +361,14 @@ private fun receiverValueTypes(
|
|||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
stableSmartCastsOnly: Boolean,
|
stableSmartCastsOnly: Boolean,
|
||||||
languageVersionSettings: LanguageVersionSettings,
|
resolutionFacade: ResolutionFacade
|
||||||
dataFlowValueFactory: DataFlowValueFactory
|
|
||||||
): List<KotlinType> {
|
): List<KotlinType> {
|
||||||
|
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
|
||||||
|
val dataFlowValueFactory = resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||||
|
val smartCastManager = resolutionFacade.frontendService<SmartCastManager>()
|
||||||
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
val dataFlowValue = dataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor)
|
||||||
return if (dataFlowValue.isStable || !stableSmartCastsOnly) { // we don't include smart cast receiver types for "unstable" receiver value to mark members grayed
|
return if (dataFlowValue.isStable || !stableSmartCastsOnly) { // we don't include smart cast receiver types for "unstable" receiver value to mark members grayed
|
||||||
SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(
|
smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
|
||||||
receiverValue,
|
receiverValue,
|
||||||
bindingContext,
|
bindingContext,
|
||||||
moduleDescriptor,
|
moduleDescriptor,
|
||||||
|
|||||||
Reference in New Issue
Block a user