예제 #1
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;
  }
  @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();
  }