Refactoring: extract method to detect redundant is out

This commit is contained in:
Mikhail Zarechenskiy
2017-05-10 15:06:52 +03:00
parent cd24adac32
commit b323d2b24a
2 changed files with 30 additions and 10 deletions
@@ -350,6 +350,15 @@ public class DataFlowAnalyzer {
@NotNull ResolutionContext c @NotNull ResolutionContext c
) { ) {
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c); DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c);
return getAllPossibleTypes(type, c, dataFlowValue);
}
@NotNull
public static Collection<KotlinType> getAllPossibleTypes(
@NotNull KotlinType type,
@NotNull ResolutionContext c,
@NotNull DataFlowValue dataFlowValue
) {
Collection<KotlinType> possibleTypes = Sets.newHashSet(type); Collection<KotlinType> possibleTypes = Sets.newHashSet(type);
possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue)); possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue));
return possibleTypes; return possibleTypes;
@@ -436,21 +436,15 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
if (targetDescriptor != null && DescriptorUtils.isEnumEntry(targetDescriptor)) { if (targetDescriptor != null && DescriptorUtils.isEnumEntry(targetDescriptor)) {
context.trace.report(IS_ENUM_ENTRY.on(typeReferenceAfterIs)) context.trace.report(IS_ENUM_ENTRY.on(typeReferenceAfterIs))
} }
val subjectTypeHasError = subjectType.containsError() if (!subjectType.containsError() && !TypeUtils.isNullableType(subjectType) && targetType.isMarkedNullable) {
if (!subjectTypeHasError && !TypeUtils.isNullableType(subjectType) && targetType.isMarkedNullable) {
val element = typeReferenceAfterIs.typeElement val element = typeReferenceAfterIs.typeElement
assert(element is KtNullableType) { "element must be instance of " + KtNullableType::class.java.name } assert(element is KtNullableType) { "element must be instance of " + KtNullableType::class.java.name }
context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(element as KtNullableType)) context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(element as KtNullableType))
} }
checkTypeCompatibility(context, targetType, subjectType, typeReferenceAfterIs) checkTypeCompatibility(context, targetType, subjectType, typeReferenceAfterIs)
if (!subjectTypeHasError && !targetType.containsError()) {
val possibleTypes = hashSetOf(subjectType) detectRedundantIs(context, subjectType, targetType, isCheck, negated, subjectDataFlowValue)
possibleTypes.addAll(context.dataFlowInfo.getStableTypes(subjectDataFlowValue))
val intersection = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, possibleTypes.map { it.upperIfFlexible() })
if (intersection?.isSubtypeOf(targetType) ?: false) {
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
}
}
if (CastDiagnosticsUtil.isCastErased(subjectType, targetType, KotlinTypeChecker.DEFAULT)) { if (CastDiagnosticsUtil.isCastErased(subjectType, targetType, KotlinTypeChecker.DEFAULT)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, targetType)) context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, targetType))
} }
@@ -459,6 +453,23 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
} }
} }
private fun detectRedundantIs(
context: ExpressionTypingContext,
subjectType: KotlinType,
targetType: KotlinType,
isCheck: KtElement,
negated: Boolean,
subjectDataFlowValue: DataFlowValue
) {
if (subjectType.containsError() || targetType.containsError()) return
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue)
val intersection = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, possibleTypes.map { it.upperIfFlexible() })
if (intersection?.isSubtypeOf(targetType) ?: false) {
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
}
}
private fun noChange(context: ExpressionTypingContext) = ConditionalDataFlowInfo(context.dataFlowInfo) private fun noChange(context: ExpressionTypingContext) = ConditionalDataFlowInfo(context.dataFlowInfo)
/* /*