@NotNull public static Map<PsiMethod, SiblingInfo> getSiblingInheritanceInfos( @NotNull final Collection<PsiMethod> methods) { MultiMap<PsiClass, PsiMethod> byClass = MultiMap.create(); for (PsiMethod method : methods) { PsiClass containingClass = method.getContainingClass(); if (canHaveSiblingSuper(method, containingClass)) { byClass.putValue(containingClass, method); } } Map<PsiMethod, SiblingInfo> result = new HashMap<>(); for (PsiClass psiClass : byClass.keySet()) { SiblingInheritorSearcher searcher = new SiblingInheritorSearcher(byClass.get(psiClass), psiClass); ClassInheritorsSearch.search(psiClass, psiClass.getUseScope(), true, true, false) .forEach(searcher); result.putAll(searcher.getResult()); } return result; }
@NotNull public static SearchScope getClassUseScope(@NotNull PsiClass aClass) { if (aClass instanceof PsiAnonymousClass) { return new LocalSearchScope(aClass); } final GlobalSearchScope maximalUseScope = ResolveScopeManager.getElementUseScope(aClass); PsiFile file = aClass.getContainingFile(); if (PsiImplUtil.isInServerPage(file)) return maximalUseScope; final PsiClass containingClass = aClass.getContainingClass(); if (aClass.hasModifierProperty(PsiModifier.PUBLIC) || aClass.hasModifierProperty(PsiModifier.PROTECTED)) { return containingClass == null ? maximalUseScope : containingClass.getUseScope(); } else if (aClass.hasModifierProperty(PsiModifier.PRIVATE) || aClass instanceof PsiTypeParameter) { PsiClass topClass = PsiUtil.getTopLevelClass(aClass); return new LocalSearchScope(topClass == null ? aClass.getContainingFile() : topClass); } else { PsiPackage aPackage = null; if (file instanceof PsiJavaFile) { aPackage = JavaPsiFacade.getInstance(aClass.getProject()) .findPackage(((PsiJavaFile) file).getPackageName()); } if (aPackage == null) { PsiDirectory dir = file.getContainingDirectory(); if (dir != null) { aPackage = JavaDirectoryService.getInstance().getPackage(dir); } } if (aPackage != null) { SearchScope scope = PackageScope.packageScope(aPackage, false); scope = scope.intersectWith(maximalUseScope); return scope; } return new LocalSearchScope(file); } }
private void processMemberType( final PsiElement element, final TypeParameterSearcher parameterSearcher, final PsiClass psiClass, final PsiSubstitutor substitutor, final Map<PsiElement, Pair<PsiReference[], PsiType>> roots) { final PsiType elementType = TypeMigrationLabeler.getElementType(element); if (elementType != null && elementType.accept(parameterSearcher).booleanValue()) { final PsiType memberType = substitutor.substitute(elementType); prepareMethodsChangeSignature(psiClass, element, memberType); final List<PsiReference> refs = TypeMigrationLabeler.filterReferences( psiClass, ReferencesSearch.search(element, psiClass.getUseScope())); roots.put( element, Pair.create( myLabeler.markRootUsages( element, memberType, refs.toArray(new PsiReference[refs.size()])), memberType)); } }
// returns super method, sub class public static Pair<PsiMethod, PsiClass> getSiblingInheritedViaSubClass( @NotNull final PsiMethod method, @NotNull Map<PsiClass, PsiClass> subClassCache) { if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null; if (method.hasModifierProperty(PsiModifier.STATIC)) return null; final PsiClass containingClass = method.getContainingClass(); boolean hasSubClass = containingClass != null && !containingClass.isInterface() && subClassCache.get(containingClass) != null; if (!hasSubClass) { return null; } final Collection<PsiAnchor> checkedInterfaces = new THashSet<PsiAnchor>(); final Ref<Pair<PsiMethod, PsiClass>> result = Ref.create(); ClassInheritorsSearch.search(containingClass, containingClass.getUseScope(), true, true, false) .forEach( new Processor<PsiClass>() { @Override public boolean process(PsiClass inheritor) { for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) { PsiClassType.ClassResolveResult resolved = interfaceType.resolveGenerics(); PsiClass anInterface = resolved.getElement(); if (anInterface == null || !checkedInterfaces.add(PsiAnchor.create(anInterface))) continue; for (PsiMethod superMethod : anInterface.findMethodsByName(method.getName(), true)) { PsiClass superInterface = superMethod.getContainingClass(); if (superInterface == null) { continue; } if (containingClass.isInheritor(superInterface, true)) { // if containingClass implements the superInterface then it's not a sibling // inheritance but a pretty boring the usual one continue; } // calculate substitutor of containingClass --> inheritor PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor( containingClass, inheritor, PsiSubstitutor.EMPTY); // calculate substitutor of inheritor --> superInterface substitutor = TypeConversionUtil.getSuperClassSubstitutor( superInterface, inheritor, substitutor); final MethodSignature superSignature = superMethod.getSignature(substitutor); final MethodSignature derivedSignature = method.getSignature(PsiSubstitutor.EMPTY); boolean isOverridden = MethodSignatureUtil.isSubsignature(superSignature, derivedSignature); if (!isOverridden) { continue; } result.set(Pair.create(superMethod, inheritor)); return false; } } return true; } }); return result.get(); }