Variance (@NotNull PsiMethod method, @NotNull PsiTypeParameter typeParameter) { PsiTypeParameterListOwner owner = typeParameter.getOwner(); PsiClass methodClass = method.getContainingClass(); if (methodClass == null || !(owner instanceof PsiClass)) return Variance.INVARIANT; PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(methodClass, (PsiClass)owner, PsiSubstitutor.EMPTY); if (superClassSubstitutor == null) return Variance.INVARIANT; Variance r = Variance.NOVARIANT; for (PsiParameter parameter : method.getParameterList().getParameters()) { PsiType type = parameter.getType(); if (typeResolvesTo(type, typeParameter, superClassSubstitutor)) { r = Variance.CONTRAVARIANT; } else if (containsDeepIn(type, typeParameter, superClassSubstitutor, false)) { return Variance.INVARIANT; } } PsiType returnType = method.getReturnType(); if (returnType != null && !TypeConversionUtil.isPrimitiveAndNotNullOrWrapper(returnType)) { if (typeResolvesTo(returnType, typeParameter, superClassSubstitutor)) { r = r.combine(Variance.COVARIANT); } else if (isComposeMethod(method, returnType, typeParameter, superClassSubstitutor)) { // ignore } else if (containsDeepIn(returnType, typeParameter, superClassSubstitutor, false)) { r = Variance.INVARIANT; } } return r; }