private NecessaryAccessorsVisitor checkNecessaryGettersSetters4SourceClass() {
    final NecessaryAccessorsVisitor visitor =
        new NecessaryAccessorsVisitor() {
          @Override
          protected boolean hasGetterOrSetter(PsiMethod[] getters) {
            for (PsiMethod getter : getters) {
              if (!isInMovedElement(getter)) return true;
            }
            return false;
          }

          @Override
          protected boolean isProhibitedReference(PsiField field) {
            if (fields.contains(field)) {
              return false;
            }
            if (innerClasses.contains(field.getContainingClass())) {
              return false;
            }
            return true;
          }
        };
    for (PsiField field : fields) {
      field.accept(visitor);
    }
    for (PsiMethod method : methods) {
      method.accept(visitor);
    }
    for (PsiClass innerClass : innerClasses) {
      innerClass.accept(visitor);
    }
    return visitor;
  }
 private static boolean isSuperMethod(PsiMethod method, PsiMethod movedMethod) {
   final PsiMethod[] superMethods = movedMethod.findSuperMethods();
   for (PsiMethod testMethod : superMethods) {
     if (testMethod.equals(method)) {
       return true;
     }
   }
   return false;
 }
 public ExtractClassProcessor(
     PsiClass sourceClass,
     List<PsiField> fields,
     List<PsiMethod> methods,
     List<PsiClass> classes,
     String packageName,
     MoveDestination moveDestination,
     String newClassName,
     String newVisibility,
     boolean generateAccessors,
     List<MemberInfo> enumConstants) {
   super(sourceClass.getProject());
   this.sourceClass = sourceClass;
   this.newPackageName = packageName;
   myMoveDestination = moveDestination;
   myNewVisibility = newVisibility;
   myGenerateAccessors = generateAccessors;
   this.enumConstants = new ArrayList<PsiField>();
   for (MemberInfo constant : enumConstants) {
     if (constant.isChecked()) {
       this.enumConstants.add((PsiField) constant.getMember());
     }
   }
   this.fields = new ArrayList<PsiField>(fields);
   this.methods = new ArrayList<PsiMethod>(methods);
   this.innerClasses = new ArrayList<PsiClass>(classes);
   this.newClassName = newClassName;
   delegateFieldName = calculateDelegateFieldName();
   requiresBackpointer =
       new BackpointerUsageVisitor(fields, innerClasses, methods, sourceClass)
           .backpointerRequired();
   if (requiresBackpointer) {
     ContainerUtil.addAll(typeParams, sourceClass.getTypeParameters());
   } else {
     final Set<PsiTypeParameter> typeParamSet = new HashSet<PsiTypeParameter>();
     final TypeParametersVisitor visitor = new TypeParametersVisitor(typeParamSet);
     for (PsiField field : fields) {
       field.accept(visitor);
     }
     for (PsiMethod method : methods) {
       method.accept(visitor);
       // do not include method's type parameters in class signature
       typeParamSet.removeAll(Arrays.asList(method.getTypeParameters()));
     }
     typeParams.addAll(typeParamSet);
   }
   myClass =
       new WriteCommandAction<PsiClass>(myProject, getCommandName()) {
         @Override
         protected void run(@NotNull Result<PsiClass> result) throws Throwable {
           result.setResult(buildClass());
         }
       }.execute().getResultObject();
   myExtractEnumProcessor = new ExtractEnumProcessor(myProject, this.enumConstants, myClass);
 }
 private void calculateInitializersConflicts(MultiMap<PsiElement, String> conflicts) {
   final PsiClassInitializer[] initializers = sourceClass.getInitializers();
   for (PsiClassInitializer initializer : initializers) {
     if (initializerDependsOnMoved(initializer)) {
       conflicts.putValue(initializer, "Class initializer requires moved members");
     }
   }
   for (PsiMethod constructor : sourceClass.getConstructors()) {
     if (initializerDependsOnMoved(constructor.getBody())) {
       conflicts.putValue(constructor, "Constructor requires moved members");
     }
   }
 }
  private void findUsagesForStaticMethod(PsiMethod method, List<FixableUsageInfo> usages) {
    final PsiManager psiManager = method.getManager();
    final Project project = psiManager.getProject();
    final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
    final Iterable<PsiReference> calls = ReferencesSearch.search(method, scope);
    final String fullyQualifiedName = getQualifiedName();
    for (PsiReference reference : calls) {
      final PsiElement referenceElement = reference.getElement();

      final PsiElement parent = referenceElement.getParent();
      if (parent instanceof PsiMethodCallExpression) {
        final PsiMethodCallExpression call = (PsiMethodCallExpression) parent;
        if (!isInMovedElement(call)) {
          usages.add(new RetargetStaticMethodCall(call, fullyQualifiedName));
        }
      } else if (parent instanceof PsiImportStaticStatement) {
        final PsiJavaCodeReferenceElement importReference =
            ((PsiImportStaticStatement) parent).getImportReference();
        if (importReference != null) {
          final PsiElement qualifier = importReference.getQualifier();
          if (qualifier instanceof PsiJavaCodeReferenceElement) {
            usages.add(
                new ReplaceClassReference(
                    (PsiJavaCodeReferenceElement) qualifier, fullyQualifiedName));
          }
        }
      }
    }
    usages.add(new RemoveMethod(method));
  }
  private void findUsagesForMethod(PsiMethod method, List<FixableUsageInfo> usages) {
    final PsiManager psiManager = method.getManager();
    final Project project = psiManager.getProject();
    final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
    final Iterable<PsiReference> calls = ReferencesSearch.search(method, scope);
    for (PsiReference reference : calls) {
      final PsiElement referenceElement = reference.getElement();
      final PsiElement parent = referenceElement.getParent();
      if (parent instanceof PsiMethodCallExpression) {
        final PsiMethodCallExpression call = (PsiMethodCallExpression) parent;
        if (isInMovedElement(call)) {
          continue;
        }
        final PsiReferenceExpression methodExpression = call.getMethodExpression();
        final PsiExpression qualifier = methodExpression.getQualifierExpression();
        if (qualifier == null || qualifier instanceof PsiThisExpression) {
          usages.add(new ReplaceThisCallWithDelegateCall(call, delegateFieldName));
        }
        delegationRequired = true;
      }
    }

    if (!delegationRequired && MethodInheritanceUtils.hasSiblingMethods(method)) {
      delegationRequired = true;
    }

    if (delegationRequired) {
      usages.add(new MakeMethodDelegate(method, delegateFieldName));
    } else {
      usages.add(new RemoveMethod(method));
    }
  }
 private static boolean usesDefaultClone(PsiClass aClass) {
   final Project project = aClass.getProject();
   final PsiManager manager = aClass.getManager();
   final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
   final PsiClass cloneable =
       JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Cloneable", scope);
   if (!InheritanceUtil.isInheritorOrSelf(aClass, cloneable, true)) {
     return false;
   }
   final PsiMethod[] methods = aClass.findMethodsByName("clone", false);
   for (PsiMethod method : methods) {
     final PsiParameterList parameterList = method.getParameterList();
     final PsiParameter[] parameters = parameterList.getParameters();
     if (parameters.length == 0) {
       return false;
     }
   }
   return true;
 }
 public void findUsages(@NotNull List<FixableUsageInfo> usages) {
   for (PsiField field : fields) {
     findUsagesForField(field, usages);
     usages.add(new RemoveField(field));
   }
   usages.addAll(
       myExtractEnumProcessor.findEnumConstantUsages(new ArrayList<FixableUsageInfo>(usages)));
   for (PsiClass innerClass : innerClasses) {
     findUsagesForInnerClass(innerClass, usages);
     usages.add(new RemoveInnerClass(innerClass));
   }
   for (PsiMethod method : methods) {
     if (method.hasModifierProperty(PsiModifier.STATIC)) {
       findUsagesForStaticMethod(method, usages);
     } else {
       findUsagesForMethod(method, usages);
     }
   }
 }
 private static boolean usesDefaultSerialization(PsiClass aClass) {
   final Project project = aClass.getProject();
   final PsiManager manager = aClass.getManager();
   final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
   final PsiClass serializable =
       JavaPsiFacade.getInstance(manager.getProject()).findClass("java.io.Serializable", scope);
   if (!InheritanceUtil.isInheritorOrSelf(aClass, serializable, true)) {
     return false;
   }
   final PsiMethod[] methods = aClass.findMethodsByName("writeObject", false);
   for (PsiMethod method : methods) {
     final PsiParameterList parameterList = method.getParameterList();
     final PsiParameter[] parameters = parameterList.getParameters();
     if (parameters.length == 1) {
       final PsiType type = parameters[0].getType();
       final String text = type.getCanonicalText();
       if ("java.io.DataOutputStream".equals(text)) {
         return false;
       }
     }
   }
   return true;
 }
  private void findUsagesForField(PsiField field, List<FixableUsageInfo> usages) {
    final PsiManager psiManager = field.getManager();
    final Project project = psiManager.getProject();
    final GlobalSearchScope scope = GlobalSearchScope.allScope(project);

    final String qualifiedName = getQualifiedName();
    @NonNls String getter = null;
    if (myGenerateAccessors) {
      getter = GenerateMembersUtil.suggestGetterName(field);
    } else {
      final PsiMethod fieldGetter =
          PropertyUtil.findPropertyGetter(sourceClass, field.getName(), false, false);
      if (fieldGetter != null && isInMovedElement(fieldGetter)) {
        getter = fieldGetter.getName();
      }
    }

    @NonNls String setter = null;
    if (myGenerateAccessors) {
      setter = GenerateMembersUtil.suggestSetterName(field);
    } else {
      final PsiMethod fieldSetter =
          PropertyUtil.findPropertySetter(sourceClass, field.getName(), false, false);
      if (fieldSetter != null && isInMovedElement(fieldSetter)) {
        setter = fieldSetter.getName();
      }
    }
    final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);

    for (PsiReference reference : ReferencesSearch.search(field, scope)) {
      final PsiElement element = reference.getElement();
      if (isInMovedElement(element)) {
        continue;
      }

      if (element instanceof PsiReferenceExpression) {
        final PsiReferenceExpression exp = (PsiReferenceExpression) element;
        if (RefactoringUtil.isPlusPlusOrMinusMinus(exp.getParent())) {
          usages.add(
              isStatic
                  ? new ReplaceStaticVariableIncrementDecrement(exp, qualifiedName)
                  : new ReplaceInstanceVariableIncrementDecrement(
                      exp, delegateFieldName, setter, getter, field.getName()));
        } else if (RefactoringUtil.isAssignmentLHS(exp)) {
          usages.add(
              isStatic
                  ? new ReplaceStaticVariableAssignment(exp, qualifiedName)
                  : new ReplaceInstanceVariableAssignment(
                      PsiTreeUtil.getParentOfType(exp, PsiAssignmentExpression.class),
                      delegateFieldName,
                      setter,
                      getter,
                      field.getName()));

        } else {
          usages.add(
              isStatic
                  ? new ReplaceStaticVariableAccess(
                      exp, qualifiedName, enumConstants.contains(field))
                  : new ReplaceInstanceVariableAccess(
                      exp, delegateFieldName, getter, field.getName()));
        }

        if (!isStatic) {
          delegationRequired = true;
        }
      } else if (element instanceof PsiDocTagValue) {
        usages.add(new BindJavadocReference(element, qualifiedName, field.getName()));
      }
    }
  }