private static HashSet<PsiMethod> collectDefaultConstructorsToPropagate(PsiMethod method) {
   final HashSet<PsiMethod> methodsToPropagate = new HashSet<PsiMethod>();
   for (PsiClass inheritor : ClassInheritorsSearch.search(method.getContainingClass())) {
     methodsToPropagate.add(inheritor.getConstructors()[0]);
   }
   return methodsToPropagate;
 }
  protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    checkExistingMethods(conflicts, true);
    checkExistingMethods(conflicts, false);
    final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      final Set<PsiMethod> setters = new HashSet<PsiMethod>();
      final Set<PsiMethod> getters = new HashSet<PsiMethod>();

      for (PsiClass aClass : classes) {
        final PsiMethod getterOverrider =
            myDescriptor.isToEncapsulateGet()
                ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false)
                : null;
        if (getterOverrider != null) {
          getters.add(getterOverrider);
        }
        final PsiMethod setterOverrider =
            myDescriptor.isToEncapsulateSet()
                ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false)
                : null;
        if (setterOverrider != null) {
          setters.add(setterOverrider);
        }
      }
      if (!getters.isEmpty() || !setters.isEmpty()) {
        final PsiField field = fieldDescriptor.getField();
        for (PsiReference reference : ReferencesSearch.search(field)) {
          final PsiElement place = reference.getElement();
          if (place instanceof PsiReferenceExpression) {
            final PsiExpression qualifierExpression =
                ((PsiReferenceExpression) place).getQualifierExpression();
            final PsiClass ancestor;
            if (qualifierExpression == null) {
              ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
            } else {
              ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType());
            }

            final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression) place);
            for (PsiMethod overridden : isGetter ? getters : setters) {
              if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) {
                conflicts.putValue(
                    overridden,
                    "There is already a "
                        + RefactoringUIUtil.getDescription(overridden, true)
                        + " which would hide generated "
                        + (isGetter ? "getter" : "setter")
                        + " for "
                        + place.getText());
                break;
              }
            }
          }
        }
      }
    }
    return showConflicts(conflicts, refUsages.get());
  }
예제 #3
0
  @NotNull
  @Override
  public List<LightRef> getHierarchyRestrictedToLibraryScope(
      @NotNull LightRef baseRef,
      @NotNull PsiElement basePsi,
      @NotNull ByteArrayEnumerator names,
      @NotNull GlobalSearchScope libraryScope) {
    final PsiClass baseClass =
        ObjectUtils.notNull(
            basePsi instanceof PsiClass
                ? (PsiClass) basePsi
                : ReadAction.compute(() -> (PsiMember) basePsi).getContainingClass());

    final List<LightRef> overridden = new ArrayList<>();
    Processor<PsiClass> processor =
        c -> {
          if (c.hasModifierProperty(PsiModifier.PRIVATE)) return true;
          String qName = ReadAction.compute(() -> c.getQualifiedName());
          if (qName == null) return true;
          overridden.add(baseRef.override(id(qName, names)));
          return true;
        };

    ClassInheritorsSearch.search(
            baseClass,
            LibraryScopeCache.getInstance(baseClass.getProject()).getLibrariesOnlyScope(),
            true)
        .forEach(processor);
    return overridden;
  }
  public InheritorRenamer(PsiClass aClass, String newClassName) {
    for (final PsiClass inheritor : ClassInheritorsSearch.search(aClass).findAll()) {
      if (inheritor.getName() != null) {
        myElements.add(inheritor);
      }
    }

    suggestAllNames(aClass.getName(), newClassName);
  }
  public boolean execute(
      @NotNull final AllOverridingMethodsSearch.SearchParameters p,
      @NotNull final Processor<Pair<PsiMethod, PsiMethod>> consumer) {
    final PsiClass psiClass = p.getPsiClass();

    PsiMethod[] methodsArray = psiClass.getMethods();
    final List<PsiMethod> methods = new ArrayList<PsiMethod>(methodsArray.length);
    for (PsiMethod method : methodsArray) {
      if (PsiUtil.canBeOverriden(method)) methods.add(method);
    }

    final SearchScope scope = p.getScope();

    Processor<PsiClass> inheritorsProcessor =
        new Processor<PsiClass>() {
          public boolean process(PsiClass inheritor) {
            // could be null if not java inheritor, TODO only JavaClassInheritors are needed
            PsiSubstitutor substitutor =
                TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY);
            if (substitutor == null) return true;

            for (PsiMethod method : methods) {
              if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)
                  && !JavaPsiFacade.getInstance(inheritor.getProject())
                      .arePackagesTheSame(psiClass, inheritor)) continue;

              MethodSignature signature = method.getSignature(substitutor);
              PsiMethod inInheritor =
                  MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false);
              if (inInheritor == null || inInheritor.hasModifierProperty(PsiModifier.STATIC)) {
                if (psiClass.isInterface()
                    && !inheritor.isInterface()) { // check for sibling implementation
                  final PsiClass superClass = inheritor.getSuperClass();
                  if (superClass != null && !superClass.isInheritor(psiClass, true)) {
                    inInheritor =
                        MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived(
                            inheritor, superClass, signature, true);
                    if (inInheritor != null
                        && !inInheritor.hasModifierProperty(PsiModifier.STATIC)) {
                      if (!consumer.process(new Pair<PsiMethod, PsiMethod>(method, inInheritor)))
                        return false;
                    }
                  }
                }
                continue;
              }
              if (!consumer.process(new Pair<PsiMethod, PsiMethod>(method, inInheritor)))
                return false;
            }

            return true;
          }
        };

    return ClassInheritorsSearch.search(psiClass, scope, true).forEach(inheritorsProcessor);
  }
 private static void addInheritorUsages(
     PsiClass aClass, final GlobalSearchScope searchScope, final List<UsageInfo> usages) {
   for (PsiClass inheritor : ClassInheritorsSearch.search(aClass, searchScope, false).findAll()) {
     if (!inheritor.isInterface()) {
       usages.add(new InheritorUsageInfo(inheritor));
     } else {
       addInheritorUsages(inheritor, searchScope, usages);
     }
   }
 }
예제 #7
0
 private void doJUnit3test() throws IOException {
   myFixture.configureByFile(getFileName());
   List<String> directives =
       InTextDirectivesUtils.findListWithPrefix(
           "// CLASS: ", FileUtil.loadFile(new File(getPathToFile())));
   assertFalse("Specify CLASS directive in test file", directives.isEmpty());
   String superClassName = directives.get(0);
   PsiClass psiClass = getPsiClass(superClassName);
   checkResult(ClassInheritorsSearch.search(psiClass, getProjectScope(), false));
 }
 private static void addInheritors(
     final PsiClass aClass,
     final Processor<UsageInfo> results,
     final JavaClassFindUsagesOptions options) {
   ClassInheritorsSearch.search(aClass, options.searchScope, options.isCheckDeepInheritance)
       .forEach(
           new PsiElementProcessorAdapter<PsiClass>(
               new PsiElementProcessor<PsiClass>() {
                 @Override
                 public boolean execute(@NotNull PsiClass element) {
                   addResult(results, element, options);
                   return true;
                 }
               }));
 }
 private static void addImplementingClasses(
     PsiClass anInterface,
     final Processor<UsageInfo> results,
     final JavaClassFindUsagesOptions options) {
   ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance)
       .forEach(
           new PsiElementProcessorAdapter<PsiClass>(
               new PsiElementProcessor<PsiClass>() {
                 @Override
                 public boolean execute(@NotNull PsiClass inheritor) {
                   if (!inheritor.isInterface()) {
                     addResult(results, inheritor, options);
                   }
                   return true;
                 }
               }));
 }
  public static boolean processImplementations(
      final PsiClass psiClass, final Processor<PsiElement> processor, SearchScope scope) {
    final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces");
    if (!ClassInheritorsSearch.search(psiClass, scope, true)
        .forEach(
            new PsiElementProcessorAdapter<>(
                element -> {
                  if (!showInterfaces && element.isInterface()) {
                    return true;
                  }
                  return processor.process(element);
                }))) {
      return false;
    }

    return FunctionalExpressionSearch.search(psiClass, scope)
        .forEach((Processor<PsiFunctionalExpression>) processor::process);
  }
  private static List<LanguageDefinition> collectLanguageDefinitions(final ConvertContext context) {
    final Project project = context.getProject();
    final Collection<PsiClass> allLanguages =
        CachedValuesManager.getManager(project)
            .getCachedValue(
                project,
                () -> {
                  final PsiClass languageClass =
                      JavaPsiFacade.getInstance(project)
                          .findClass(Language.class.getName(), GlobalSearchScope.allScope(project));
                  if (languageClass == null) {
                    return Result.create(
                        Collections.emptyList(),
                        PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
                  }

                  final GlobalSearchScope projectProductionScope =
                      GlobalSearchScopesCore.projectProductionScope(project);
                  GlobalSearchScope allScope =
                      projectProductionScope.union(ProjectScope.getLibrariesScope(project));
                  final Collection<PsiClass> allInheritors =
                      ClassInheritorsSearch.search(languageClass, allScope, true).findAll();
                  return Result.create(
                      allInheritors, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
                });
    if (allLanguages.isEmpty()) {
      return Collections.emptyList();
    }

    final List<LanguageDefinition> libraryDefinitions =
        collectLibraryLanguages(context, allLanguages);

    final GlobalSearchScope projectProductionScope =
        GlobalSearchScopesCore.projectProductionScope(project);
    final Collection<PsiClass> projectLanguages =
        ContainerUtil.filter(
            allLanguages, aClass -> PsiSearchScopeUtil.isInScope(projectProductionScope, aClass));
    final List<LanguageDefinition> projectDefinitions =
        collectProjectLanguages(projectLanguages, libraryDefinitions);

    final List<LanguageDefinition> all = ContainerUtil.newArrayList(libraryDefinitions);
    all.addAll(projectDefinitions);
    return all;
  }
예제 #12
0
  @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;
  }
  private void addExprTypesByDerivedClasses(LinkedHashSet<PsiType> set, PsiExpression expr) {
    PsiType type = expr.getType();
    if (!(type instanceof PsiClassType)) return;
    PsiClass refClass = PsiUtil.resolveClassInType(type);
    if (refClass == null) return;

    PsiManager manager = PsiManager.getInstance(myProject);
    PsiElementProcessor.CollectElementsWithLimit<PsiClass> processor =
        new PsiElementProcessor.CollectElementsWithLimit<>(5);
    ClassInheritorsSearch.search(refClass).forEach(new PsiElementProcessorAdapter<>(processor));
    if (processor.isOverflow()) return;

    for (PsiClass derivedClass : processor.getCollection()) {
      if (derivedClass instanceof PsiAnonymousClass) continue;
      PsiType derivedType =
          JavaPsiFacade.getInstance(manager.getProject())
              .getElementFactory()
              .createType(derivedClass);
      set.add(derivedType);
    }
  }
  @Override
  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
    int offset = editor.getCaretModel().getOffset();
    final PsiMethod method = findMethod(file, offset);

    if (method == null || !method.isValid()) return false;
    setText(getIntentionName(method));

    if (!method.getManager().isInProject(method)) return false;

    PsiClass containingClass = method.getContainingClass();
    if (containingClass == null) return false;
    final boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
    if (isAbstract
        || !method.hasModifierProperty(PsiModifier.PRIVATE)
            && !method.hasModifierProperty(PsiModifier.STATIC)) {
      if (!isAbstract && !isOnIdentifier(file, offset)) return false;
      MyElementProcessor processor = new MyElementProcessor(method);
      if (containingClass.isEnum()) {
        for (PsiField field : containingClass.getFields()) {
          if (field instanceof PsiEnumConstant) {
            final PsiEnumConstantInitializer initializingClass =
                ((PsiEnumConstant) field).getInitializingClass();
            if (initializingClass == null) {
              processor.myHasMissingImplementations = true;
            } else {
              if (!processor.execute(initializingClass)) {
                break;
              }
            }
          }
        }
      }
      ClassInheritorsSearch.search(containingClass, false)
          .forEach(new PsiElementProcessorAdapter<PsiClass>(processor));
      return isAvailable(processor);
    }

    return false;
  }
  private void processMethodsDuplicates() {
    ProgressManager.getInstance()
        .runProcessWithProgressSynchronously(
            () ->
                ApplicationManager.getApplication()
                    .runReadAction(
                        () -> {
                          if (!myTargetSuperClass.isValid()) return;
                          final Query<PsiClass> search =
                              ClassInheritorsSearch.search(myTargetSuperClass);
                          final Set<VirtualFile> hierarchyFiles = new HashSet<>();
                          for (PsiClass aClass : search) {
                            final PsiFile containingFile = aClass.getContainingFile();
                            if (containingFile != null) {
                              final VirtualFile virtualFile = containingFile.getVirtualFile();
                              if (virtualFile != null) {
                                hierarchyFiles.add(virtualFile);
                              }
                            }
                          }
                          final Set<PsiMember> methodsToSearchDuplicates = new HashSet<>();
                          for (PsiMember psiMember : myMembersAfterMove) {
                            if (psiMember instanceof PsiMethod
                                && psiMember.isValid()
                                && ((PsiMethod) psiMember).getBody() != null) {
                              methodsToSearchDuplicates.add(psiMember);
                            }
                          }

                          MethodDuplicatesHandler.invokeOnScope(
                              myProject,
                              methodsToSearchDuplicates,
                              new AnalysisScope(myProject, hierarchyFiles),
                              true);
                        }),
            MethodDuplicatesHandler.REFACTORING_NAME,
            true,
            myProject);
  }
예제 #16
0
  @NotNull
  private Object[] getSubclassVariants(
      @NotNull PsiPackage context, @NotNull String[] extendClasses) {
    HashSet<Object> lookups = new HashSet<Object>();
    GlobalSearchScope packageScope = PackageScope.packageScope(context, true);
    GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope();
    if (scope != null) {
      packageScope = packageScope.intersectWith(scope);
    }
    final GlobalSearchScope allScope = ProjectScope.getAllScope(context.getProject());
    final boolean instantiatable =
        JavaClassReferenceProvider.INSTANTIATABLE.getBooleanValue(getOptions());
    final boolean notInterface =
        JavaClassReferenceProvider.NOT_INTERFACE.getBooleanValue(getOptions());
    final boolean notEnum = JavaClassReferenceProvider.NOT_ENUM.getBooleanValue(getOptions());
    final boolean concrete = JavaClassReferenceProvider.CONCRETE.getBooleanValue(getOptions());

    final ClassKind classKind = getClassKind();

    for (String extendClassName : extendClasses) {
      final PsiClass extendClass =
          JavaPsiFacade.getInstance(context.getProject()).findClass(extendClassName, allScope);
      if (extendClass != null) {
        // add itself
        if (packageScope.contains(extendClass.getContainingFile().getVirtualFile())) {
          if (isClassAccepted(
              extendClass, classKind, instantiatable, concrete, notInterface, notEnum)) {
            ContainerUtil.addIfNotNull(createSubclassLookupValue(context, extendClass), lookups);
          }
        }
        for (final PsiClass clazz : ClassInheritorsSearch.search(extendClass, packageScope, true)) {
          if (isClassAccepted(clazz, classKind, instantiatable, concrete, notInterface, notEnum)) {
            ContainerUtil.addIfNotNull(createSubclassLookupValue(context, clazz), lookups);
          }
        }
      }
    }
    return lookups.toArray();
  }
 @Override
 public void visitClass(@NotNull PsiClass aClass) {
   // no call to super, so that it doesn't drill down to inner classes
   if (aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
     return;
   }
   if (!UtilityClassUtil.isUtilityClass(aClass)) {
     return;
   }
   if (ignoreClassesWithOnlyMain && hasOnlyMain(aClass)) {
     return;
   }
   if (hasPrivateConstructor(aClass)) {
     return;
   }
   final SearchScope scope = GlobalSearchScope.projectScope(aClass.getProject());
   final Query<PsiClass> query = ClassInheritorsSearch.search(aClass, scope, true, true);
   final PsiClass subclass = query.findFirst();
   if (subclass != null) {
     return;
   }
   registerClassError(aClass, aClass);
 }
 private static void findSubmemberHidesFieldCollisions(
     final PsiField field, final String newName, final List<UsageInfo> result) {
   if (field.getContainingClass() == null) return;
   if (field.hasModifierProperty(PsiModifier.PRIVATE)) return;
   final PsiClass containingClass = field.getContainingClass();
   Collection<PsiClass> inheritors = ClassInheritorsSearch.search(containingClass).findAll();
   for (PsiClass inheritor : inheritors) {
     PsiField conflictingField = inheritor.findFieldByName(newName, false);
     if (conflictingField != null) {
       result.add(new SubmemberHidesMemberUsageInfo(conflictingField, field));
     } else { // local class
       final PsiMember member = PsiTreeUtil.getParentOfType(inheritor, PsiMember.class);
       if (member != null) {
         final ArrayList<PsiVariable> variables = new ArrayList<>();
         ControlFlowUtil.collectOuterLocals(variables, inheritor, inheritor, member);
         for (PsiVariable variable : variables) {
           if (newName.equals(variable.getName())) {
             result.add(new FieldHidesLocalUsageInfo(variable, field));
           }
         }
       }
     }
   }
 }
  public void testEnumWithInitializedConstants() throws Exception {
    setupLoadingFilter();
    final GlobalSearchScope moduleScope = GlobalSearchScope.moduleScope(myModule);
    PsiClass enumClass =
        myJavaFacade.findClass("enums.OurEnumWithInitializedConstants", moduleScope);
    assertNotNull(enumClass);
    assertTrue(enumClass.isEnum());
    PsiField[] fields = enumClass.getFields();
    assertEquals(3, fields.length);
    assertTrue(fields[0] instanceof PsiEnumConstant);
    assertTrue(fields[1] instanceof PsiEnumConstant);
    assertTrue(fields[2] instanceof PsiEnumConstant);
    PsiAnonymousClass initializingClass0 = ((PsiEnumConstant) fields[0]).getInitializingClass();
    PsiClass baseClass0 = initializingClass0.getBaseClassType().resolve();
    assertTrue(baseClass0 == enumClass);

    PsiAnonymousClass initializingClass1 = ((PsiEnumConstant) fields[1]).getInitializingClass();
    PsiClass baseClass1 = initializingClass1.getBaseClassType().resolve();
    assertTrue(baseClass1 == enumClass);

    PsiAnonymousClass initializingClass2 = ((PsiEnumConstant) fields[1]).getInitializingClass();
    PsiClass baseClass2 = initializingClass2.getBaseClassType().resolve();
    assertTrue(baseClass2 == enumClass);

    assertTrue(initializingClass0.isInheritor(enumClass, false));
    assertTrue(initializingClass1.isInheritor(enumClass, false));
    assertTrue(initializingClass2.isInheritor(enumClass, false));

    final PsiClass[] enumInheritors =
        ClassInheritorsSearch.search(enumClass, moduleScope, false).toArray(PsiClass.EMPTY_ARRAY);
    assertEquals(3, enumInheritors.length);
    assertTrue(Arrays.asList(enumInheritors).contains(initializingClass0));
    assertTrue(Arrays.asList(enumInheritors).contains(initializingClass1));
    assertTrue(Arrays.asList(enumInheritors).contains(initializingClass2));

    PsiMethod[] methods1 = initializingClass2.getMethods();
    assertEquals(1, methods1.length);
    assertEquals("foo", methods1[0].getName());

    final PsiClass baseInterfaceClass =
        myJavaFacade.findClass(
            "enums.OurBaseInterface", GlobalSearchScope.moduleWithLibrariesScope(myModule));
    assertNotNull(baseInterfaceClass);

    final PsiClass[] inheritors =
        ClassInheritorsSearch.search(baseInterfaceClass, moduleScope, false)
            .toArray(PsiClass.EMPTY_ARRAY);
    assertEquals(1, inheritors.length);
    assertTrue(inheritors[0] instanceof PsiAnonymousClass);

    teardownLoadingFilter();

    assertTrue(inheritors[0].getParent().getParent() instanceof PsiExpressionList);
    assertTrue(inheritors[0].getParent().getParent().getParent() == fields[2]);

    final PsiExpression[] expressions2 =
        ((PsiEnumConstant) fields[2]).getArgumentList().getExpressions();
    assertEquals(1, expressions2.length);
    assertTrue(expressions2[0] instanceof PsiNewExpression);
    final PsiAnonymousClass anonymousClass2 =
        ((PsiNewExpression) expressions2[0]).getAnonymousClass();
    assertTrue(anonymousClass2 != null);
    assertTrue(anonymousClass2.isInheritor(baseInterfaceClass, false));
  }
예제 #20
0
  public static void processSubTypes(
      PsiType psiType,
      final PsiElement context,
      boolean getRawSubtypes,
      @NotNull final PrefixMatcher matcher,
      Consumer<PsiType> consumer) {
    int arrayDim = psiType.getArrayDimensions();

    psiType = psiType.getDeepComponentType();
    if (!(psiType instanceof PsiClassType)) return;

    final Condition<String> shortNameCondition =
        new Condition<String>() {
          @Override
          public boolean value(String s) {
            return matcher.prefixMatches(s);
          }
        };

    final PsiClassType baseType = (PsiClassType) psiType;
    final PsiClassType.ClassResolveResult baseResult =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<PsiClassType.ClassResolveResult>() {
                  @Override
                  public PsiClassType.ClassResolveResult compute() {
                    return JavaCompletionUtil.originalize(baseType).resolveGenerics();
                  }
                });
    final PsiClass baseClass = baseResult.getElement();
    final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor();
    if (baseClass == null) return;

    final GlobalSearchScope scope =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<GlobalSearchScope>() {
                  @Override
                  public GlobalSearchScope compute() {
                    return context.getResolveScope();
                  }
                });

    final Processor<PsiClass> inheritorsProcessor =
        createInheritorsProcessor(
            context, baseType, arrayDim, getRawSubtypes, consumer, baseClass, baseSubstitutor);
    if (matcher.getPrefix().length() > 2) {
      AllClassesGetter.processJavaClasses(
          matcher,
          context.getProject(),
          scope,
          new Processor<PsiClass>() {
            @Override
            public boolean process(PsiClass psiClass) {
              if (psiClass.isInheritor(baseClass, true)) {
                return inheritorsProcessor.process(psiClass);
              }
              return true;
            }
          });
    } else {
      final Query<PsiClass> baseQuery =
          ClassInheritorsSearch.search(
              new ClassInheritorsSearch.SearchParameters(
                  baseClass, scope, true, false, false, shortNameCondition));
      final Query<PsiClass> query =
          new FilteredQuery<PsiClass>(
              baseQuery,
              new Condition<PsiClass>() {
                @Override
                public boolean value(final PsiClass psiClass) {
                  return !(psiClass instanceof PsiTypeParameter);
                }
              });
      query.forEach(inheritorsProcessor);
    }
  }
  private static void checkSuperclassMembers(
      PsiClass superClass,
      MemberInfoBase<? extends PsiMember>[] infos,
      MultiMap<PsiElement, String> conflictsList) {
    for (MemberInfoBase<? extends PsiMember> info : infos) {
      PsiMember member = info.getMember();
      boolean isConflict = false;
      if (member instanceof PsiField) {
        String name = member.getName();

        isConflict = superClass.findFieldByName(name, false) != null;
      } else if (member instanceof PsiMethod) {
        PsiSubstitutor superSubstitutor =
            TypeConversionUtil.getSuperClassSubstitutor(
                superClass, member.getContainingClass(), PsiSubstitutor.EMPTY);
        MethodSignature signature = ((PsiMethod) member).getSignature(superSubstitutor);
        final PsiMethod superClassMethod =
            MethodSignatureUtil.findMethodBySignature(superClass, signature, false);
        isConflict = superClassMethod != null;
      }

      if (isConflict) {
        String message =
            RefactoringBundle.message(
                "0.already.contains.a.1",
                RefactoringUIUtil.getDescription(superClass, false),
                RefactoringUIUtil.getDescription(member, false));
        message = CommonRefactoringUtil.capitalize(message);
        conflictsList.putValue(superClass, message);
      }

      if (member instanceof PsiMethod) {
        final PsiMethod method = (PsiMethod) member;
        final PsiModifierList modifierList = method.getModifierList();
        if (!modifierList.hasModifierProperty(PsiModifier.PRIVATE)) {
          for (PsiClass subClass : ClassInheritorsSearch.search(superClass)) {
            if (method.getContainingClass() != subClass) {
              MethodSignature signature =
                  ((PsiMethod) member)
                      .getSignature(
                          TypeConversionUtil.getSuperClassSubstitutor(
                              superClass, subClass, PsiSubstitutor.EMPTY));
              final PsiMethod wouldBeOverriden =
                  MethodSignatureUtil.findMethodBySignature(subClass, signature, false);
              if (wouldBeOverriden != null
                  && VisibilityUtil.compare(
                          VisibilityUtil.getVisibilityModifier(wouldBeOverriden.getModifierList()),
                          VisibilityUtil.getVisibilityModifier(modifierList))
                      > 0) {
                conflictsList.putValue(
                    wouldBeOverriden,
                    CommonRefactoringUtil.capitalize(
                        RefactoringUIUtil.getDescription(method, true)
                            + " in super class would clash with local method from "
                            + RefactoringUIUtil.getDescription(subClass, true)));
              }
            }
          }
        }
      }
    }
  }
  // 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();
  }