public static MultiMap<PsiElement, String> checkConflicts(
     final MemberInfoBase<? extends PsiMember>[] infos,
     @NotNull final PsiClass subclass,
     @Nullable PsiClass superClass,
     @NotNull final PsiPackage targetPackage,
     @NotNull PsiDirectory targetDirectory,
     final InterfaceContainmentVerifier interfaceContainmentVerifier,
     boolean movedMembers2Super) {
   final Set<PsiMember> movedMembers = new HashSet<PsiMember>();
   final Set<PsiMethod> abstractMethods = new HashSet<PsiMethod>();
   final boolean isInterfaceTarget;
   final PsiElement targetRepresentativeElement;
   if (superClass != null) {
     isInterfaceTarget = superClass.isInterface();
     targetRepresentativeElement = superClass;
   } else {
     isInterfaceTarget = false;
     targetRepresentativeElement = targetDirectory;
   }
   for (MemberInfoBase<? extends PsiMember> info : infos) {
     PsiMember member = info.getMember();
     if (member instanceof PsiMethod) {
       if (!info.isToAbstract() && !isInterfaceTarget) {
         movedMembers.add(member);
       } else {
         abstractMethods.add((PsiMethod) member);
       }
     } else {
       movedMembers.add(member);
     }
   }
   final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
   final Set<PsiMethod> abstrMethods = new HashSet<PsiMethod>(abstractMethods);
   if (superClass != null) {
     for (PsiMethod method : subclass.getMethods()) {
       if (!movedMembers.contains(method) && !method.hasModifierProperty(PsiModifier.PRIVATE)) {
         if (method.findSuperMethods(superClass).length > 0) {
           abstrMethods.add(method);
         }
       }
     }
   }
   RefactoringConflictsUtil.analyzeAccessibilityConflicts(
       movedMembers,
       superClass,
       conflicts,
       VisibilityUtil.ESCALATE_VISIBILITY,
       targetRepresentativeElement,
       abstrMethods);
   if (superClass != null) {
     if (movedMembers2Super) {
       checkSuperclassMembers(superClass, infos, conflicts);
       if (isInterfaceTarget) {
         checkInterfaceTarget(infos, conflicts);
       }
     } else {
       final String qualifiedName = superClass.getQualifiedName();
       assert qualifiedName != null;
       if (superClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
         if (!Comparing.strEqual(
             StringUtil.getPackageName(qualifiedName), targetPackage.getQualifiedName())) {
           conflicts.putValue(
               superClass,
               RefactoringUIUtil.getDescription(superClass, true)
                   + " won't be accessible from "
                   + RefactoringUIUtil.getDescription(targetPackage, true));
         }
       }
     }
   }
   // check if moved methods use other members in the classes between Subclass and Superclass
   List<PsiElement> checkModuleConflictsList = new ArrayList<PsiElement>();
   for (PsiMember member : movedMembers) {
     if (member instanceof PsiMethod
         || member instanceof PsiClass && !(member instanceof PsiCompiledElement)) {
       ClassMemberReferencesVisitor visitor =
           movedMembers2Super
               ? new ConflictingUsagesOfSubClassMembers(
                   member,
                   movedMembers,
                   abstractMethods,
                   subclass,
                   superClass,
                   superClass != null ? null : targetPackage,
                   conflicts,
                   interfaceContainmentVerifier)
               : new ConflictingUsagesOfSuperClassMembers(
                   member, subclass, targetPackage, movedMembers, conflicts);
       member.accept(visitor);
     }
     ContainerUtil.addIfNotNull(checkModuleConflictsList, member);
   }
   for (final PsiMethod method : abstractMethods) {
     ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getParameterList());
     ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getReturnTypeElement());
     ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getTypeParameterList());
   }
   RefactoringConflictsUtil.analyzeModuleConflicts(
       subclass.getProject(),
       checkModuleConflictsList,
       new UsageInfo[0],
       targetRepresentativeElement,
       conflicts);
   final String fqName = subclass.getQualifiedName();
   final String packageName;
   if (fqName != null) {
     packageName = StringUtil.getPackageName(fqName);
   } else {
     final PsiFile psiFile = PsiTreeUtil.getParentOfType(subclass, PsiFile.class);
     if (psiFile instanceof PsiClassOwner) {
       packageName = ((PsiClassOwner) psiFile).getPackageName();
     } else {
       packageName = null;
     }
   }
   final boolean toDifferentPackage =
       !Comparing.strEqual(targetPackage.getQualifiedName(), packageName);
   for (final PsiMethod abstractMethod : abstractMethods) {
     abstractMethod.accept(
         new ClassMemberReferencesVisitor(subclass) {
           @Override
           protected void visitClassMemberReferenceElement(
               PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) {
             if (classMember != null && willBeMoved(classMember, movedMembers)) {
               boolean isAccessible = false;
               if (classMember.hasModifierProperty(PsiModifier.PRIVATE)) {
                 isAccessible = true;
               } else if (classMember.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)
                   && toDifferentPackage) {
                 isAccessible = true;
               }
               if (isAccessible) {
                 String message =
                     RefactoringUIUtil.getDescription(abstractMethod, false)
                         + " uses "
                         + RefactoringUIUtil.getDescription(classMember, true)
                         + " which won't be accessible from the subclass.";
                 message = CommonRefactoringUtil.capitalize(message);
                 conflicts.putValue(classMember, message);
               }
             }
           }
         });
     if (abstractMethod.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) {
       if (!isInterfaceTarget) {
         String message =
             "Can't make "
                 + RefactoringUIUtil.getDescription(abstractMethod, false)
                 + " abstract as it won't be accessible from the subclass.";
         message = CommonRefactoringUtil.capitalize(message);
         conflicts.putValue(abstractMethod, message);
       }
     }
   }
   return conflicts;
 }
예제 #2
0
  public void checkTargetClassConflicts(
      final PsiClass targetClass, final boolean checkStatic, final PsiElement context) {
    if (targetClass != null) {
      for (final PsiMember movedMember : myMovedMembers) {
        checkMemberPlacementInTargetClassConflict(targetClass, movedMember);
        movedMember.accept(
            new JavaRecursiveElementWalkingVisitor() {
              @Override
              public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                super.visitMethodCallExpression(expression);
                if (expression.getMethodExpression().getQualifierExpression()
                    instanceof PsiSuperExpression) {
                  final PsiMethod resolvedMethod = expression.resolveMethod();
                  if (resolvedMethod != null) {
                    final PsiClass resolvedClass = resolvedMethod.getContainingClass();
                    if (resolvedClass != null) {
                      if (myClass.isInheritor(resolvedClass, true)) {
                        final PsiMethod methodBySignature =
                            myClass.findMethodBySignature(resolvedMethod, false);
                        if (methodBySignature != null
                            && !myMovedMembers.contains(methodBySignature)) {
                          myConflicts.putValue(
                              expression, "Super method call will resolve to another method");
                        }
                      }
                    }
                  }
                }
              }
            });
      }
    }
    Members:
    for (PsiMember member : myMovedMembers) {
      for (PsiReference ref : ReferencesSearch.search(member, member.getResolveScope(), false)) {
        final PsiElement element = ref.getElement();
        if (element instanceof PsiReferenceExpression) {
          final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) element;
          final PsiExpression qualifier = referenceExpression.getQualifierExpression();
          if (qualifier != null) {
            final PsiType qualifierType = qualifier.getType();
            PsiClass aClass = null;
            if (qualifierType instanceof PsiClassType) {
              aClass = ((PsiClassType) qualifierType).resolve();
            } else {
              if (!checkStatic) continue;
              if (qualifier instanceof PsiReferenceExpression) {
                final PsiElement resolved = ((PsiReferenceExpression) qualifier).resolve();
                if (resolved instanceof PsiClass) {
                  aClass = (PsiClass) resolved;
                }
              }
            }

            if (!InheritanceUtil.isInheritorOrSelf(aClass, targetClass, true)) {
              myConflicts.putValue(
                  referenceExpression,
                  RefactoringBundle.message(
                      "pushed.members.will.not.be.visible.from.certain.call.sites"));
              break Members;
            }
          }
        }
      }
    }
    // RefactoringConflictsUtil.analyzeAccessibilityConflicts(myMovedMembers, targetClass,
    // myConflicts, null, context, myAbstractMembers);

  }