void (PsiElement targetElement, PushDownData<MemberInfo, PsiMember> pushDownData) { final PsiElementFactory factory = JavaPsiFacade.getElementFactory(pushDownData.getSourceClass().getProject()); final PsiClass targetClass = targetElement instanceof PsiClass ? (PsiClass)targetElement : null; if (targetClass == null) { return; } final PsiClass sourceClass = (PsiClass)pushDownData.getSourceClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(sourceClass, targetClass, PsiSubstitutor.EMPTY); for (MemberInfo memberInfo : pushDownData.getMembersToMove()) { PsiMember member = memberInfo.getMember(); final List<PsiReference> refsToRebind = new ArrayList<>(); final PsiModifierList list = member.getModifierList(); LOG.assertTrue(list != null); if (list.hasModifierProperty(PsiModifier.STATIC) && !PsiUtil.isLocalOrAnonymousClass(targetClass)) { for (final PsiReference reference : ReferencesSearch.search(member)) { final PsiElement element = reference.getElement(); if (element instanceof PsiReferenceExpression) { final PsiExpression qualifierExpression = ((PsiReferenceExpression)element).getQualifierExpression(); if (qualifierExpression == null) { continue; } if (qualifierExpression instanceof PsiReferenceExpression) { PsiElement resolve = ((PsiReferenceExpression)qualifierExpression).resolve(); if (!(resolve instanceof PsiClass) || resolve != sourceClass) { continue; } if (pushDownData.preserveExternalLinks() && !PsiTreeUtil.isAncestor(targetElement, element, false)) { continue; } PsiClass inheritor = InheritanceUtil.findEnclosingInstanceInScope(sourceClass, element, Conditions.alwaysTrue(), false); if (inheritor != null && inheritor != targetClass) { //usages in other targets should be updated on corresponding turns continue; } } } refsToRebind.add(reference); } } if (member instanceof PsiField) { ((PsiField)member).normalizeDeclaration(); } member = (PsiMember)member.copy(); RefactoringUtil.renameConflictingTypeParameters(member, targetClass); RefactoringUtil.replaceMovedMemberTypeParameters(member, PsiUtil.typeParametersIterable(sourceClass), substitutor, factory); PsiMember newMember = null; if (member instanceof PsiField) { if (sourceClass.isInterface() && !targetClass.isInterface()) { PsiUtil.setModifierProperty(member, PsiModifier.PUBLIC, true); PsiUtil.setModifierProperty(member, PsiModifier.STATIC, true); PsiUtil.setModifierProperty(member, PsiModifier.FINAL, true); } newMember = (PsiMember)targetClass.add(member); } else if (member instanceof PsiMethod method) { PsiMethod methodBySignature = MethodSignatureUtil.findMethodBySuperSignature(targetClass, method.getSignature(substitutor), false); boolean pushMethodToClass = methodBySignature == null; if (pushMethodToClass) { if (Arrays.stream(targetClass.findMethodsBySignature(method, true)) .map(m -> m.getContainingClass()) .filter(Objects::nonNull).anyMatch(aClass -> aClass.isInheritor(sourceClass, true))) { continue; } newMember = (PsiMethod)targetClass.add(method); final PsiMethod oldMethod = (PsiMethod)memberInfo.getMember(); if (sourceClass.isInterface() && !targetClass.isInterface()) { PsiUtil.setModifierProperty(newMember, PsiModifier.PUBLIC, true); if (oldMethod.hasModifierProperty(PsiModifier.ABSTRACT)) { if (oldMethod.getBody() == null) { RefactoringUtil.makeMethodAbstract(targetClass, (PsiMethod)newMember); } } else { PsiUtil.setModifierProperty(newMember, PsiModifier.DEFAULT, false); } } if (memberInfo.isToAbstract()) { if (newMember.hasModifierProperty(PsiModifier.PRIVATE)) { PsiUtil.setModifierProperty(newMember, PsiModifier.PROTECTED, true); } pushDownData.getCommentPolicy().processNewJavaDoc(((PsiMethod)newMember).getDocComment()); OverrideImplementUtil.annotateOnOverrideImplement((PsiMethod)newMember, targetClass, (PsiMethod)memberInfo.getMember()); } } else { //abstract method: remove @Override if (!memberInfo.isToAbstract()) { final PsiAnnotation annotation = AnnotationUtil.findAnnotation(methodBySignature, "java.lang.Override"); if (annotation != null && !leaveOverrideAnnotation(sourceClass, substitutor, method)) { annotation.delete(); } PsiParameter[] sourceParameters = method.getParameterList().getParameters(); PsiParameter[] targetParameters = methodBySignature.getParameterList().getParameters(); for (int i = 0; i < sourceParameters.length; i++) { GenerateMembersUtil.copyAnnotations(sourceParameters[i], targetParameters[i]); } GenerateMembersUtil.copyAnnotations(method, methodBySignature); } final PsiDocComment oldDocComment = method.getDocComment(); if (oldDocComment != null) { final PsiDocComment docComment = methodBySignature.getDocComment(); final int policy = pushDownData.getCommentPolicy().getJavaDocPolicy(); if (policy == DocCommentPolicy.COPY || policy == DocCommentPolicy.MOVE) { if (docComment != null) { docComment.replace(oldDocComment); } else { methodBySignature.getParent().addBefore(oldDocComment, methodBySignature); } } } inlineSuperCall(memberInfo, methodBySignature); } } else if (member instanceof PsiClass) { if (sourceClass.isInterface() && !targetClass.isInterface()) { PsiUtil.setModifierProperty(member, PsiModifier.PUBLIC, true); } if (Boolean.FALSE.equals(memberInfo.getOverrides())) { final PsiClass psiClass = (PsiClass)memberInfo.getMember(); PsiClassType classType = null; if (!targetClass.isInheritor(psiClass, false)) { final PsiClassType[] types = memberInfo.getSourceReferenceList().getReferencedTypes(); for (PsiClassType type : types) { if (type.resolve() == psiClass) { classType = (PsiClassType)substitutor.substitute(type); } } PsiJavaCodeReferenceElement classRef = classType != null ? factory.createReferenceElementByType(classType) : factory.createClassReferenceElement(psiClass); PsiReferenceList extendsImplementsList = psiClass.isInterface() && !targetClass.isInterface() ? targetClass.getImplementsList() : targetClass.getExtendsList(); if (extendsImplementsList != null) { extendsImplementsList.add(classRef); } } } else { newMember = (PsiMember)targetClass.add(member); } } else if (member instanceof PsiClassInitializer) { newMember = (PsiMember)targetClass.add(member); } if (newMember != null) { decodeRefs(sourceClass, newMember, targetClass); //rebind imports first refsToRebind.sort(Comparator.comparing(PsiReference::getElement, PsiUtil.BY_POSITION)); for (PsiReference psiReference : refsToRebind) { JavaCodeStyleManager.getInstance(sourceClass.getProject()).shortenClassReferences(psiReference.bindToElement(newMember)); } final JavaRefactoringListenerManager listenerManager = JavaRefactoringListenerManager.getInstance(newMember.getProject()); ((JavaRefactoringListenerManagerImpl)listenerManager).fireMemberMoved(sourceClass, newMember); } } }