diff --git a/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql b/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql index 726c2453f65..e3ac1384243 100644 --- a/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql +++ b/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql @@ -60,13 +60,43 @@ private predicate candidateMethod(RefType t, Method m, string name, int numParam not whitelist(name) } -pragma[inline] -private predicate potentiallyConfusingTypes(Type a, Type b) { - exists(RefType commonSubtype | hasSubtypeOrInstantiation*(a, commonSubtype) | - hasSubtypeOrInstantiation*(b, commonSubtype) +predicate paramTypePair(Type t1, Type t2) { + exists(Method n, Method m, int i | + overloadedMethodsMostSpecific(n, m) and + t1 = n.getParameterType(i) and + t2 = m.getParameterType(i) ) +} + +// handle simple cases separately +predicate potentiallyConfusingTypesSimple(Type t1, Type t2) { + paramTypePair(t1, t2) and + ( + t1 = t2 + or + t1 instanceof TypeObject and t2 instanceof RefType + or + t2 instanceof TypeObject and t1 instanceof RefType + or + confusingPrimitiveBoxedTypes(t1, t2) + ) +} + +// check erased types first +predicate potentiallyConfusingTypesRefTypes(RefType t1, RefType t2) { + paramTypePair(t1, t2) and + not potentiallyConfusingTypesSimple(t1, t2) and + haveIntersection(t1, t2) +} + +// then check hasSubtypeOrInstantiation +predicate potentiallyConfusingTypes(Type t1, Type t2) { + potentiallyConfusingTypesSimple(t1, t2) or - confusingPrimitiveBoxedTypes(a, b) + potentiallyConfusingTypesRefTypes(t1, t2) and + exists(RefType commonSubtype | hasSubtypeOrInstantiation*(t1, commonSubtype) | + hasSubtypeOrInstantiation*(t2, commonSubtype) + ) } private predicate hasSubtypeOrInstantiation(RefType t, RefType sub) {