VarianceCandidate (@NotNull PsiTypeElement innerTypeElement) { PsiType type = innerTypeElement.getType(); if (type instanceof PsiWildcardType || type instanceof PsiCapturedWildcardType) return null; if (!(innerTypeElement.getParent() instanceof PsiReferenceParameterList referenceParameterList)) return null; if (!(referenceParameterList.getParent() instanceof PsiJavaCodeReferenceElement refElement)) return null; if (!referenceParameterList.equals(refElement.getParameterList())) return null; if (!(refElement.advancedResolve(false).getElement() instanceof PsiClass resolved)) return null; int index = ArrayUtil.indexOf(referenceParameterList.getTypeParameterElements(), innerTypeElement); if (!(refElement.getParent() instanceof PsiTypeElement typeElement)) return null; if (!(typeElement.getParent() instanceof PsiParameter parameter)) return null; if (!(parameter.getDeclarationScope() instanceof PsiMethod method)) return null; PsiTypeParameter[] typeParameters = resolved.getTypeParameters(); if (typeParameters.length <= index) return null; PsiTypeParameter typeParameter = typeParameters[index]; PsiParameterList parameterList = method.getParameterList(); int parameterIndex = parameterList.getParameterIndex(parameter); if (parameterIndex == -1) return null; if (!(parameter.getType() instanceof PsiClassReferenceType classReferenceType)) return null; PsiParameter[] methodParameters = parameterList.getParameters(); VarianceCandidate candidate = new VarianceCandidate(parameter, classReferenceType, method, parameterIndex, typeParameter, type, index); // check that if there is a super method, then it's parameterized similarly. // otherwise, it would make no sense to wildcardize "new Function<List<T>, T>(){ T apply(List<T> param) {...} }" // Oh, and make sure super methods are all modifiable, or it wouldn't make sense to report them if (!SuperMethodsSearch.search(method, null, true, true).forEach((MethodSignatureBackedByPsiMethod superMethod)-> { ProgressManager.checkCanceled(); if (superMethod.getMethod() instanceof PsiCompiledElement) return false; // check not substituted super parameters PsiParameter[] superMethodParameters = superMethod.getMethod().getParameterList().getParameters(); if (superMethodParameters.length != methodParameters.length) return false; PsiType superParameterType = superMethodParameters[parameterIndex].getType(); if (!(superParameterType instanceof PsiClassType classType)) return false; PsiType[] superTypeParameters = classType.getParameters(); candidate.superMethods.add(superMethod.getMethod()); return superTypeParameters.length == typeParameters.length; })) return null; return candidate; }