mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-114289 Groovy: Pull Members Up: 'implements library interface' clause is not suggested it 'Members to be pulled up' list
This commit is contained in:
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,7 @@ import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.refactoring.extractInterface.ExtractInterfaceHandler;
|
||||
import com.intellij.refactoring.extractSuperclass.ExtractSuperclassHandler;
|
||||
import com.intellij.refactoring.memberPullUp.JavaPullUpHandler;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -127,7 +127,7 @@ public class PullAsAbstractUpFix extends LocalQuickFixAndIntentionActionOnPsiEle
|
||||
final MemberInfo memberInfo = new MemberInfo(method);
|
||||
memberInfo.setChecked(true);
|
||||
memberInfo.setToAbstract(true);
|
||||
new PullUpHelper(containingClass, baseClass, new MemberInfo[]{memberInfo}, new DocCommentPolicy(DocCommentPolicy.ASIS)).run();
|
||||
new PullUpProcessor(containingClass, baseClass, new MemberInfo[]{memberInfo}, new DocCommentPolicy(DocCommentPolicy.ASIS)).run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,7 @@ import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.extractSuperclass.ExtractSuperClassUtil;
|
||||
import com.intellij.refactoring.lang.ElementsHandler;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
@@ -144,7 +144,7 @@ public class ExtractInterfaceHandler implements RefactoringActionHandler, Elemen
|
||||
final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList();
|
||||
assert referenceList != null;
|
||||
referenceList.add(ref);
|
||||
PullUpHelper pullUpHelper = new PullUpHelper(aClass, anInterface, selectedMembers, javaDocPolicy);
|
||||
PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, anInterface, selectedMembers, javaDocPolicy);
|
||||
pullUpHelper.moveMembersToBase();
|
||||
return anInterface;
|
||||
}
|
||||
|
||||
+11
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,8 +27,11 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.ui.ConflictsDialog;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
@@ -39,7 +42,10 @@ import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
@@ -76,7 +82,7 @@ public class ExtractSuperClassUtil {
|
||||
PsiJavaCodeReferenceElement ref = createExtendingReference(superclass, subclass, selectedMemberInfos);
|
||||
subclass.getExtendsList().add(ref);
|
||||
|
||||
PullUpHelper pullUpHelper = new PullUpHelper(subclass, superclass, selectedMemberInfos,
|
||||
PullUpProcessor pullUpHelper = new PullUpProcessor(subclass, superclass, selectedMemberInfos,
|
||||
javaDocPolicy
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoChange;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoModel;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.ui.MemberSelectionPanel;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.InterfaceContainmentVerifier;
|
||||
@@ -39,7 +39,7 @@ import java.util.List;
|
||||
class ExtractSuperclassDialog extends JavaExtractSuperBaseDialog {
|
||||
private final InterfaceContainmentVerifier myContainmentVerifier = new InterfaceContainmentVerifier() {
|
||||
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
|
||||
return PullUpHelper.checkedInterfacesContain(myMemberInfos, psiMethod);
|
||||
return PullUpProcessor.checkedInterfacesContain(myMemberInfos, psiMethod);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+137
-269
@@ -13,222 +13,123 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: dsl
|
||||
* Date: 14.06.2002
|
||||
* Time: 22:35:19
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.ChangeContextUtil;
|
||||
import com.intellij.codeInsight.PsiEquivalenceUtil;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.lang.findUsages.DescriptiveNameUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoBase;
|
||||
import com.intellij.refactoring.listeners.JavaRefactoringListenerManager;
|
||||
import com.intellij.refactoring.listeners.impl.JavaRefactoringListenerManagerImpl;
|
||||
import com.intellij.refactoring.util.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.RefactoringChangeUtil;
|
||||
import com.intellij.refactoring.util.RefactoringHierarchyUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.classMembers.ClassMemberReferencesVisitor;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.refactoring.util.duplicates.MethodDuplicatesHandler;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.memberPullUp.PullUpHelper");
|
||||
/**
|
||||
* Created by Max Medvedev on 10/3/13
|
||||
*/
|
||||
public class JavaPullUpHelper implements PullUpHelper<MemberInfo> {
|
||||
private static final Logger LOG = Logger.getInstance(JavaPullUpHelper.class);
|
||||
|
||||
private static final Key<Boolean> PRESERVE_QUALIFIER = Key.create("PRESERVE_QUALIFIER");
|
||||
|
||||
|
||||
private final PsiClass mySourceClass;
|
||||
private final PsiClass myTargetSuperClass;
|
||||
private final boolean myIsTargetInterface;
|
||||
private final MemberInfo[] myMembersToMove;
|
||||
private final DocCommentPolicy myJavaDocPolicy;
|
||||
private Set<PsiMember> myMembersAfterMove = null;
|
||||
private final PsiManager myManager;
|
||||
private Set<PsiMember> myMembersToMove;
|
||||
private Project myProject;
|
||||
|
||||
public PullUpHelper(PsiClass sourceClass, PsiClass targetSuperClass, MemberInfo[] membersToMove, DocCommentPolicy javaDocPolicy) {
|
||||
super(sourceClass.getProject());
|
||||
mySourceClass = sourceClass;
|
||||
myTargetSuperClass = targetSuperClass;
|
||||
myMembersToMove = membersToMove;
|
||||
myJavaDocPolicy = javaDocPolicy;
|
||||
myIsTargetInterface = targetSuperClass.isInterface();
|
||||
myManager = mySourceClass.getManager();
|
||||
private final QualifiedThisSuperAdjuster myThisSuperAdjuster;
|
||||
private final ExplicitSuperDeleter myExplicitSuperDeleter;
|
||||
|
||||
public JavaPullUpHelper(PullUpData data) {
|
||||
myProject = data.getProject();
|
||||
myMembersToMove = data.getMembersToMove();
|
||||
myMembersAfterMove = data.getMovedMembers();
|
||||
myTargetSuperClass = data.getTargetClass();
|
||||
mySourceClass = data.getSourceClass();
|
||||
myJavaDocPolicy = data.getDocCommentPolicy();
|
||||
myIsTargetInterface = myTargetSuperClass.isInterface();
|
||||
|
||||
myThisSuperAdjuster = new QualifiedThisSuperAdjuster();
|
||||
myExplicitSuperDeleter = new ExplicitSuperDeleter();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
|
||||
return new PullUpUsageViewDescriptor();
|
||||
@Override
|
||||
public void encodeContextInfo(MemberInfo info) {
|
||||
ChangeContextUtil.encodeContextInfo(info.getMember(), true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected UsageInfo[] findUsages() {
|
||||
final List<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
for (MemberInfo memberInfo : myMembersToMove) {
|
||||
final PsiMember member = memberInfo.getMember();
|
||||
if (member.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
for (PsiReference reference : ReferencesSearch.search(member)) {
|
||||
result.add(new UsageInfo(reference));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void move(MemberInfo info, PsiSubstitutor substitutor) {
|
||||
if (info.getMember() instanceof PsiMethod) {
|
||||
doMoveMethod(substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiField) {
|
||||
doMoveField(substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiClass) {
|
||||
doMoveClass(substitutor, info);
|
||||
}
|
||||
return result.isEmpty() ? UsageInfo.EMPTY_ARRAY : result.toArray(new UsageInfo[result.size()]);
|
||||
}
|
||||
|
||||
protected void performRefactoring(UsageInfo[] usages) {
|
||||
moveMembersToBase();
|
||||
moveFieldInitializations();
|
||||
for (UsageInfo usage : usages) {
|
||||
PsiElement element = usage.getElement();
|
||||
if (element instanceof PsiReferenceExpression) {
|
||||
PsiExpression qualifierExpression = ((PsiReferenceExpression)element).getQualifierExpression();
|
||||
if (qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() == mySourceClass) {
|
||||
((PsiReferenceExpression)qualifierExpression).bindToElement(myTargetSuperClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void postProcessMember(PsiMember member) {
|
||||
member.accept(myExplicitSuperDeleter);
|
||||
member.accept(myThisSuperAdjuster);
|
||||
|
||||
ChangeContextUtil.decodeContextInfo(member, null, null);
|
||||
|
||||
member.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void run() {
|
||||
processMethodsDuplicates();
|
||||
}
|
||||
}, ModalityState.NON_MODAL, myProject.getDisposed());
|
||||
}
|
||||
|
||||
private void processMethodsDuplicates() {
|
||||
if (!myTargetSuperClass.isValid()) return;
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Query<PsiClass> search = ClassInheritorsSearch.search(myTargetSuperClass);
|
||||
final Set<VirtualFile> hierarchyFiles = new HashSet<VirtualFile>();
|
||||
for (PsiClass aClass : search) {
|
||||
final PsiFile containingFile = aClass.getContainingFile();
|
||||
if (containingFile != null) {
|
||||
final VirtualFile virtualFile = containingFile.getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
hierarchyFiles.add(virtualFile);
|
||||
}
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
final PsiExpression qualifierExpression = expression.getQualifierExpression();
|
||||
if (qualifierExpression != null) {
|
||||
final Boolean preserveQualifier = qualifierExpression.getCopyableUserData(PRESERVE_QUALIFIER);
|
||||
if (preserveQualifier != null && !preserveQualifier) {
|
||||
qualifierExpression.delete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
final Set<PsiMember> methodsToSearchDuplicates = new HashSet<PsiMember>();
|
||||
for (PsiMember psiMember : myMembersAfterMove) {
|
||||
if (psiMember instanceof PsiMethod && ((PsiMethod)psiMember).getBody() != null) {
|
||||
methodsToSearchDuplicates.add(psiMember);
|
||||
}
|
||||
}
|
||||
|
||||
MethodDuplicatesHandler.invokeOnScope(myProject, methodsToSearchDuplicates, new AnalysisScope(myProject, hierarchyFiles), true);
|
||||
super.visitReferenceExpression(expression);
|
||||
}
|
||||
}, MethodDuplicatesHandler.REFACTORING_NAME, true, myProject);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle.message("pullUp.command", DescriptiveNameUtil.getDescriptiveName(mySourceClass));
|
||||
}
|
||||
|
||||
public void moveMembersToBase() throws IncorrectOperationException {
|
||||
final Set<PsiMember> movedMembers = ContainerUtil.newHashSet();
|
||||
myMembersAfterMove = ContainerUtil.newHashSet();
|
||||
|
||||
// build aux sets
|
||||
for (MemberInfo info : myMembersToMove) {
|
||||
movedMembers.add(info.getMember());
|
||||
}
|
||||
|
||||
// correct private member visibility
|
||||
for (MemberInfo info : myMembersToMove) {
|
||||
if (info.getMember() instanceof PsiClass && info.getOverrides() != null) continue;
|
||||
setCorrectVisibility(movedMembers, info);
|
||||
ChangeContextUtil.encodeContextInfo(info.getMember(), true);
|
||||
}
|
||||
|
||||
final PsiSubstitutor substitutor = upDownSuperClassSubstitutor();
|
||||
|
||||
// do actual move
|
||||
for (MemberInfo info : myMembersToMove) {
|
||||
if (info.getMember() instanceof PsiMethod) {
|
||||
doMoveMethod(movedMembers, substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiField) {
|
||||
doMoveField(movedMembers, substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiClass) {
|
||||
doMoveClass(movedMembers, substitutor, info);
|
||||
}
|
||||
}
|
||||
|
||||
ExplicitSuperDeleter explicitSuperDeleter = new ExplicitSuperDeleter();
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
member.accept(explicitSuperDeleter);
|
||||
}
|
||||
explicitSuperDeleter.fixSupers();
|
||||
|
||||
final QualifiedThisSuperAdjuster qualifiedThisSuperAdjuster = new QualifiedThisSuperAdjuster();
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
member.accept(qualifiedThisSuperAdjuster);
|
||||
}
|
||||
|
||||
ChangeContextUtil.decodeContextInfo(myTargetSuperClass, null, null);
|
||||
|
||||
for (final PsiMember movedMember : myMembersAfterMove) {
|
||||
movedMember.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
final PsiExpression qualifierExpression = expression.getQualifierExpression();
|
||||
if (qualifierExpression != null) {
|
||||
final Boolean preserveQualifier = qualifierExpression.getCopyableUserData(PRESERVE_QUALIFIER);
|
||||
if (preserveQualifier != null && !preserveQualifier) {
|
||||
qualifierExpression.delete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.visitReferenceExpression(expression);
|
||||
}
|
||||
});
|
||||
final JavaRefactoringListenerManager listenerManager = JavaRefactoringListenerManager.getInstance(movedMember.getProject());
|
||||
((JavaRefactoringListenerManagerImpl)listenerManager).fireMemberMoved(mySourceClass, movedMember);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCorrectVisibility(final Set<PsiMember> movedMembers, MemberInfo info) {
|
||||
@Override
|
||||
public void setCorrectVisibility(MemberInfo info) {
|
||||
PsiModifierListOwner modifierListOwner = info.getMember();
|
||||
if (myIsTargetInterface) {
|
||||
PsiUtil.setModifierProperty(modifierListOwner, PsiModifier.PUBLIC, true);
|
||||
}
|
||||
else if (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (info.isToAbstract() || willBeUsedInSubclass(modifierListOwner, movedMembers, myTargetSuperClass, mySourceClass)) {
|
||||
if (info.isToAbstract() || willBeUsedInSubclass(modifierListOwner, myTargetSuperClass, mySourceClass)) {
|
||||
PsiUtil.setModifierProperty(modifierListOwner, PsiModifier.PROTECTED, true);
|
||||
}
|
||||
if (modifierListOwner instanceof PsiClass) {
|
||||
@@ -251,7 +152,7 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
|
||||
private void check(PsiMember member) {
|
||||
if (member.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (willBeUsedInSubclass(member, movedMembers, myTargetSuperClass, mySourceClass)) {
|
||||
if (willBeUsedInSubclass(member, myTargetSuperClass, mySourceClass)) {
|
||||
PsiUtil.setModifierProperty(member, PsiModifier.PROTECTED, true);
|
||||
}
|
||||
}
|
||||
@@ -261,7 +162,7 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
private void doMoveClass(Set<PsiMember> movedMembers, PsiSubstitutor substitutor, MemberInfo info) {
|
||||
private void doMoveClass(PsiSubstitutor substitutor, MemberInfo info) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
PsiClass aClass = (PsiClass)info.getMember();
|
||||
if (Boolean.FALSE.equals(info.getOverrides())) {
|
||||
@@ -273,35 +174,35 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
if (ref != null && !myTargetSuperClass.isInheritor(aClass, false)) {
|
||||
RefactoringUtil.replaceMovedMemberTypeParameters(ref, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
final PsiReferenceList referenceList =
|
||||
myTargetSuperClass.isInterface() ? myTargetSuperClass.getExtendsList() : myTargetSuperClass.getImplementsList();
|
||||
myIsTargetInterface ? myTargetSuperClass.getExtendsList() : myTargetSuperClass.getImplementsList();
|
||||
assert referenceList != null;
|
||||
referenceList.add(ref);
|
||||
}
|
||||
}
|
||||
else {
|
||||
RefactoringUtil.replaceMovedMemberTypeParameters(aClass, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
fixReferencesToStatic(aClass, movedMembers);
|
||||
final PsiMember movedElement = (PsiMember)myTargetSuperClass.add(aClass);
|
||||
fixReferencesToStatic(aClass);
|
||||
final PsiMember movedElement = (PsiMember)myTargetSuperClass.add(convertClassToLanguage(aClass, myTargetSuperClass.getLanguage()));
|
||||
myMembersAfterMove.add(movedElement);
|
||||
aClass.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void doMoveField(Set<PsiMember> movedMembers, PsiSubstitutor substitutor, MemberInfo info) {
|
||||
private void doMoveField(PsiSubstitutor substitutor, MemberInfo info) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
PsiField field = (PsiField)info.getMember();
|
||||
field.normalizeDeclaration();
|
||||
RefactoringUtil.replaceMovedMemberTypeParameters(field, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
fixReferencesToStatic(field, movedMembers);
|
||||
fixReferencesToStatic(field);
|
||||
if (myIsTargetInterface) {
|
||||
PsiUtil.setModifierProperty(field, PsiModifier.PUBLIC, true);
|
||||
}
|
||||
final PsiMember movedElement = (PsiMember)myTargetSuperClass.add(field);
|
||||
final PsiMember movedElement = (PsiMember)myTargetSuperClass.add(convertFieldToLanguage(field, myTargetSuperClass.getLanguage()));
|
||||
myMembersAfterMove.add(movedElement);
|
||||
field.delete();
|
||||
}
|
||||
|
||||
private void doMoveMethod(Set<PsiMember> movedMembers, PsiSubstitutor substitutor, MemberInfo info) {
|
||||
private void doMoveMethod(PsiSubstitutor substitutor, MemberInfo info) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
PsiMethod method = (PsiMethod)info.getMember();
|
||||
PsiMethod sibling = method;
|
||||
@@ -340,11 +241,11 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
final PsiMember movedElement = anchor != null ? (PsiMember)myTargetSuperClass.addBefore(methodCopy, anchor) : (PsiMember)myTargetSuperClass.add(methodCopy);
|
||||
CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(method.getProject());
|
||||
if (styleSettings.INSERT_OVERRIDE_ANNOTATION) {
|
||||
if (PsiUtil.isLanguageLevel5OrHigher(mySourceClass) && !myTargetSuperClass.isInterface() || PsiUtil.isLanguageLevel6OrHigher(mySourceClass)) {
|
||||
if (PsiUtil.isLanguageLevel5OrHigher(mySourceClass) && !myIsTargetInterface || PsiUtil.isLanguageLevel6OrHigher(mySourceClass)) {
|
||||
new AddAnnotationFix(Override.class.getName(), method).invoke(method.getProject(), null, mySourceClass.getContainingFile());
|
||||
}
|
||||
}
|
||||
if (!PsiUtil.isLanguageLevel6OrHigher(mySourceClass) && myTargetSuperClass.isInterface()) {
|
||||
if (!PsiUtil.isLanguageLevel6OrHigher(mySourceClass) && myIsTargetInterface) {
|
||||
if (isOriginalMethodAbstract) {
|
||||
for (PsiMethod oMethod : OverridingMethodsSearch.search(method)) {
|
||||
deleteOverrideAnnotationIfFound(oMethod);
|
||||
@@ -362,35 +263,45 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
PsiUtil.setModifierProperty(myTargetSuperClass, PsiModifier.ABSTRACT, true);
|
||||
}
|
||||
RefactoringUtil.replaceMovedMemberTypeParameters(methodCopy, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
fixReferencesToStatic(methodCopy, movedMembers);
|
||||
fixReferencesToStatic(methodCopy);
|
||||
|
||||
Language language = myTargetSuperClass.getLanguage();
|
||||
final PsiMethod superClassMethod = myTargetSuperClass.findMethodBySignature(methodCopy, false);
|
||||
if (superClassMethod != null && superClassMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
superClassMethod.replace(methodCopy);
|
||||
superClassMethod.replace(convertMethodToLanguage(methodCopy, language));
|
||||
}
|
||||
else {
|
||||
final PsiMember movedElement =
|
||||
anchor != null ? (PsiMember)myTargetSuperClass.addBefore(methodCopy, anchor) : (PsiMember)myTargetSuperClass.add(methodCopy);
|
||||
anchor != null ? (PsiMember)myTargetSuperClass.addBefore(convertMethodToLanguage(methodCopy,
|
||||
language), anchor) : (PsiMember)myTargetSuperClass.add(
|
||||
convertMethodToLanguage(
|
||||
methodCopy, language));
|
||||
myMembersAfterMove.add(movedElement);
|
||||
}
|
||||
method.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private PsiSubstitutor upDownSuperClassSubstitutor() {
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(mySourceClass)) {
|
||||
substitutor = substitutor.put(parameter, null);
|
||||
private static PsiMethod convertMethodToLanguage(PsiMethod method, Language language) {
|
||||
if (method.getLanguage().equals(language)) {
|
||||
return method;
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap =
|
||||
TypeConversionUtil.getSuperClassSubstitutor(myTargetSuperClass, mySourceClass, PsiSubstitutor.EMPTY).getSubstitutionMap();
|
||||
for (PsiTypeParameter parameter : substitutionMap.keySet()) {
|
||||
final PsiType type = substitutionMap.get(parameter);
|
||||
final PsiClass resolvedClass = PsiUtil.resolveClassInType(type);
|
||||
if (resolvedClass instanceof PsiTypeParameter) {
|
||||
substitutor = substitutor.put((PsiTypeParameter)resolvedClass, JavaPsiFacade.getElementFactory(myProject).createType(parameter));
|
||||
}
|
||||
return JVMElementFactories.getFactory(language, method.getProject()).createMethodFromText(method.getText(), null);
|
||||
}
|
||||
|
||||
private static PsiField convertFieldToLanguage(PsiField field, Language language) {
|
||||
if (field.getLanguage().equals(language)) {
|
||||
return field;
|
||||
}
|
||||
return substitutor;
|
||||
return JVMElementFactories.getFactory(language, field.getProject()).createField(field.getName(), field.getType());
|
||||
}
|
||||
|
||||
private static PsiClass convertClassToLanguage(PsiClass clazz, Language language) {
|
||||
//if (clazz.getLanguage().equals(language)) {
|
||||
// return clazz;
|
||||
//}
|
||||
//PsiClass newClass = JVMElementFactories.getFactory(language, clazz.getProject()).createClass(clazz.getName());
|
||||
return clazz;
|
||||
}
|
||||
|
||||
private static void deleteOverrideAnnotationIfFound(PsiMethod oMethod) {
|
||||
@@ -400,17 +311,8 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
public void moveFieldInitializations() throws IncorrectOperationException {
|
||||
LOG.assertTrue(myMembersAfterMove != null);
|
||||
|
||||
final LinkedHashSet<PsiField> movedFields = new LinkedHashSet<PsiField>();
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
if (member instanceof PsiField) {
|
||||
movedFields.add((PsiField)member);
|
||||
}
|
||||
}
|
||||
|
||||
if (movedFields.isEmpty()) return;
|
||||
@Override
|
||||
public void moveFieldInitializations(LinkedHashSet<PsiField> movedFields) {
|
||||
PsiMethod[] constructors = myTargetSuperClass.getConstructors();
|
||||
|
||||
if (constructors.length == 0) {
|
||||
@@ -424,6 +326,16 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUsage(PsiElement element) {
|
||||
if (element instanceof PsiReferenceExpression) {
|
||||
PsiExpression qualifierExpression = ((PsiReferenceExpression)element).getQualifierExpression();
|
||||
if (qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() == mySourceClass) {
|
||||
((PsiReferenceExpression)qualifierExpression).bindToElement(myTargetSuperClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Initializer {
|
||||
public final PsiStatement initializer;
|
||||
public final Set<PsiField> movedFieldsUsed;
|
||||
@@ -486,7 +398,7 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(myProject);
|
||||
|
||||
if (constructor == null) {
|
||||
constructor = (PsiMethod) myTargetSuperClass.add(factory.createConstructor());
|
||||
@@ -522,8 +434,8 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
|
||||
PsiStatement assignmentStatement = (PsiStatement)constructor.getBody().add(initializer.initializer);
|
||||
|
||||
ChangeContextUtil.decodeContextInfo(assignmentStatement,
|
||||
myTargetSuperClass, RefactoringChangeUtil.createThisExpression(myManager, null));
|
||||
PsiManager manager = PsiManager.getInstance(myProject);
|
||||
ChangeContextUtil.decodeContextInfo(assignmentStatement, myTargetSuperClass, RefactoringChangeUtil.createThisExpression(manager, null));
|
||||
for (PsiElement psiElement : initializer.statementsToRemove) {
|
||||
psiElement.delete();
|
||||
}
|
||||
@@ -768,8 +680,8 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
return constructorsToSubConstructors;
|
||||
}
|
||||
|
||||
private void fixReferencesToStatic(PsiElement classMember, Set<PsiMember> movedMembers) throws IncorrectOperationException {
|
||||
final StaticReferencesCollector collector = new StaticReferencesCollector(movedMembers);
|
||||
private void fixReferencesToStatic(PsiElement classMember) throws IncorrectOperationException {
|
||||
final StaticReferencesCollector collector = new StaticReferencesCollector();
|
||||
classMember.accept(collector);
|
||||
ArrayList<PsiJavaCodeReferenceElement> refs = collector.getReferences();
|
||||
ArrayList<PsiElement> members = collector.getReferees();
|
||||
@@ -799,11 +711,9 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
private ArrayList<PsiJavaCodeReferenceElement> myReferences;
|
||||
private ArrayList<PsiElement> myReferees;
|
||||
private ArrayList<PsiClass> myRefereeClasses;
|
||||
private final Set<PsiMember> myMovedMembers;
|
||||
|
||||
private StaticReferencesCollector(Set<PsiMember> movedMembers) {
|
||||
private StaticReferencesCollector() {
|
||||
super(mySourceClass);
|
||||
myMovedMembers = movedMembers;
|
||||
myReferees = new ArrayList<PsiElement>();
|
||||
myRefereeClasses = new ArrayList<PsiClass>();
|
||||
myReferences = new ArrayList<PsiJavaCodeReferenceElement>();
|
||||
@@ -823,13 +733,13 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
|
||||
protected void visitClassMemberReferenceElement(PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) {
|
||||
if (classMember.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
if (!myMovedMembers.contains(classMember) &&
|
||||
if (!myMembersToMove.contains(classMember) &&
|
||||
RefactoringHierarchyUtil.isMemberBetween(myTargetSuperClass, mySourceClass, classMember)) {
|
||||
myReferences.add(classMemberReference);
|
||||
myReferees.add(classMember);
|
||||
myRefereeClasses.add(classMember.getContainingClass());
|
||||
}
|
||||
else if (myMovedMembers.contains(classMember) || myMembersAfterMove.contains(classMember)) {
|
||||
else if (myMembersToMove.contains(classMember) || myMembersAfterMove.contains(classMember)) {
|
||||
myReferences.add(classMemberReference);
|
||||
myReferees.add(classMember);
|
||||
myRefereeClasses.add(myTargetSuperClass);
|
||||
@@ -857,7 +767,7 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
final PsiJavaCodeReferenceElement qualifier = expression.getQualifier();
|
||||
if (qualifier != null && qualifier.isReferenceTo(mySourceClass)) {
|
||||
try {
|
||||
expression.replace(JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory().createExpressionFromText(myTargetSuperClass.getName() + ".this", null));
|
||||
expression.replace(JavaPsiFacade.getElementFactory(myProject).createExpressionFromText(myTargetSuperClass.getName() + ".this", null));
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
@@ -867,23 +777,25 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
}
|
||||
|
||||
private class ExplicitSuperDeleter extends JavaRecursiveElementWalkingVisitor {
|
||||
private final ArrayList<PsiExpression> mySupersToDelete = new ArrayList<PsiExpression>();
|
||||
private final ArrayList<PsiSuperExpression> mySupersToChangeToThis = new ArrayList<PsiSuperExpression>();
|
||||
private final PsiExpression myThisExpression = JavaPsiFacade.getElementFactory(myProject).createExpressionFromText("this", null);
|
||||
|
||||
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
if(expression.getQualifierExpression() instanceof PsiSuperExpression) {
|
||||
PsiElement resolved = expression.resolve();
|
||||
if (resolved == null || resolved instanceof PsiMethod && shouldFixSuper((PsiMethod) resolved)) {
|
||||
mySupersToDelete.add(expression.getQualifierExpression());
|
||||
expression.getQualifierExpression().delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visitSuperExpression(PsiSuperExpression expression) {
|
||||
mySupersToChangeToThis.add(expression);
|
||||
@Override
|
||||
public void visitSuperExpression(PsiSuperExpression expression) {
|
||||
expression.replace(myThisExpression);
|
||||
}
|
||||
|
||||
@Override public void visitClass(PsiClass aClass) {
|
||||
@Override
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@@ -904,59 +816,15 @@ public class PullUpHelper extends BaseRefactoringProcessor{
|
||||
final PsiMethod methodFromSuper = myTargetSuperClass.findMethodBySignature(method, false);
|
||||
return methodFromSuper == null;
|
||||
}
|
||||
|
||||
public void fixSupers() throws IncorrectOperationException {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
|
||||
PsiThisExpression thisExpression = (PsiThisExpression) factory.createExpressionFromText("this", null);
|
||||
for (PsiExpression psiExpression : mySupersToDelete) {
|
||||
psiExpression.delete();
|
||||
}
|
||||
|
||||
for (PsiSuperExpression psiSuperExpression : mySupersToChangeToThis) {
|
||||
psiSuperExpression.replace(thisExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean willBeUsedInSubclass(PsiElement member, Set<PsiMember> movedMembers, PsiClass superclass, PsiClass subclass) {
|
||||
private boolean willBeUsedInSubclass(PsiElement member, PsiClass superclass, PsiClass subclass) {
|
||||
for (PsiReference ref : ReferencesSearch.search(member, new LocalSearchScope(subclass), false)) {
|
||||
PsiElement element = ref.getElement();
|
||||
if (!RefactoringHierarchyUtil.willBeInTargetClass(element, movedMembers, superclass, false)) {
|
||||
if (!RefactoringHierarchyUtil.willBeInTargetClass(element, myMembersToMove, superclass, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean checkedInterfacesContain(Collection<? extends MemberInfoBase<? extends PsiMember>> memberInfos, PsiMethod psiMethod) {
|
||||
for (MemberInfoBase<? extends PsiMember> memberInfo : memberInfos) {
|
||||
if (memberInfo.isChecked() &&
|
||||
memberInfo.getMember() instanceof PsiClass &&
|
||||
Boolean.FALSE.equals(memberInfo.getOverrides())) {
|
||||
if (((PsiClass)memberInfo.getMember()).findMethodBySignature(psiMethod, true) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class PullUpUsageViewDescriptor implements UsageViewDescriptor {
|
||||
public String getProcessedElementsHeader() {
|
||||
return "Pull up members from";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getElements() {
|
||||
return new PsiElement[]{mySourceClass};
|
||||
}
|
||||
|
||||
public String getCodeReferencesText(int usagesCount, int filesCount) {
|
||||
return "Class to pull up members to \"" + RefactoringUIUtil.getDescription(myTargetSuperClass, true) + "\"";
|
||||
}
|
||||
|
||||
public String getCommentReferencesText(int usagesCount, int filesCount) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/4/13
|
||||
*/
|
||||
public class JavaPullUpHelperFactory implements PullUpHelperFactory {
|
||||
@Override
|
||||
public PullUpHelper createPullUpHelper(PullUpData data) {
|
||||
return new JavaPullUpHelper(data);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public class PullUpDialog extends PullUpDialogBase<MemberInfoStorage, MemberInfo
|
||||
|
||||
private final InterfaceContainmentVerifier myInterfaceContainmentVerifier = new InterfaceContainmentVerifier() {
|
||||
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
|
||||
return PullUpHelper.checkedInterfacesContain(myMemberInfos, psiMethod);
|
||||
return PullUpProcessor.checkedInterfacesContain(myMemberInfos, psiMethod);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,7 +139,7 @@ public class PullUpDialog extends PullUpDialogBase<MemberInfoStorage, MemberInfo
|
||||
}
|
||||
|
||||
List<MemberInfo> infos = getSelectedMemberInfos();
|
||||
invokeRefactoring(new PullUpHelper(myClass, superClass, infos.toArray(new MemberInfo[infos.size()]),
|
||||
invokeRefactoring(new PullUpProcessor(myClass, superClass, infos.toArray(new MemberInfo[infos.size()]),
|
||||
new DocCommentPolicy(getJavaDocPolicy())));
|
||||
close(OK_EXIT_CODE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: dsl
|
||||
* Date: 14.06.2002
|
||||
* Time: 22:35:19
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.findUsages.DescriptiveNameUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoBase;
|
||||
import com.intellij.refactoring.listeners.JavaRefactoringListenerManager;
|
||||
import com.intellij.refactoring.listeners.impl.JavaRefactoringListenerManagerImpl;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.refactoring.util.duplicates.MethodDuplicatesHandler;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpData {
|
||||
private static final Logger LOG = Logger.getInstance(PullUpProcessor.class);
|
||||
|
||||
private final PsiClass mySourceClass;
|
||||
private final PsiClass myTargetSuperClass;
|
||||
private final MemberInfo[] myMembersToMove;
|
||||
private final DocCommentPolicy myJavaDocPolicy;
|
||||
private Set<PsiMember> myMembersAfterMove = null;
|
||||
private Set<PsiMember> myMovedMembers = null;
|
||||
private Map<Language, PullUpHelper<MemberInfo>> myProcessors = ContainerUtil.newHashMap();
|
||||
|
||||
public PullUpProcessor(PsiClass sourceClass, PsiClass targetSuperClass, MemberInfo[] membersToMove, DocCommentPolicy javaDocPolicy) {
|
||||
super(sourceClass.getProject());
|
||||
mySourceClass = sourceClass;
|
||||
myTargetSuperClass = targetSuperClass;
|
||||
myMembersToMove = membersToMove;
|
||||
myJavaDocPolicy = javaDocPolicy;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
|
||||
return new PullUpUsageViewDescriptor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected UsageInfo[] findUsages() {
|
||||
final List<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
for (MemberInfo memberInfo : myMembersToMove) {
|
||||
final PsiMember member = memberInfo.getMember();
|
||||
if (member.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
for (PsiReference reference : ReferencesSearch.search(member)) {
|
||||
result.add(new UsageInfo(reference));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.isEmpty() ? UsageInfo.EMPTY_ARRAY : result.toArray(new UsageInfo[result.size()]);
|
||||
}
|
||||
|
||||
protected void performRefactoring(UsageInfo[] usages) {
|
||||
moveMembersToBase();
|
||||
moveFieldInitializations();
|
||||
for (UsageInfo usage : usages) {
|
||||
PsiElement element = usage.getElement();
|
||||
if (element == null) continue;
|
||||
|
||||
PullUpHelper<MemberInfo> processor = getProcessor(element);
|
||||
processor.updateUsage(element);
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processMethodsDuplicates();
|
||||
}
|
||||
}, ModalityState.NON_MODAL, myProject.getDisposed());
|
||||
}
|
||||
|
||||
private void processMethodsDuplicates() {
|
||||
if (!myTargetSuperClass.isValid()) return;
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Query<PsiClass> search = ClassInheritorsSearch.search(myTargetSuperClass);
|
||||
final Set<VirtualFile> hierarchyFiles = new HashSet<VirtualFile>();
|
||||
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<PsiMember>();
|
||||
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);
|
||||
}
|
||||
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle.message("pullUp.command", DescriptiveNameUtil.getDescriptiveName(mySourceClass));
|
||||
}
|
||||
|
||||
public void moveMembersToBase() throws IncorrectOperationException {
|
||||
myMovedMembers = ContainerUtil.newHashSet();
|
||||
myMembersAfterMove = ContainerUtil.newHashSet();
|
||||
|
||||
// build aux sets
|
||||
for (MemberInfo info : myMembersToMove) {
|
||||
myMovedMembers.add(info.getMember());
|
||||
}
|
||||
|
||||
final PsiSubstitutor substitutor = upDownSuperClassSubstitutor();
|
||||
|
||||
for (MemberInfo info : myMembersToMove) {
|
||||
PullUpHelper<MemberInfo> processor = getProcessor(info);
|
||||
|
||||
if (!(info.getMember() instanceof PsiClass) || info.getOverrides() == null) {
|
||||
processor.setCorrectVisibility(info);
|
||||
processor.encodeContextInfo(info);
|
||||
}
|
||||
|
||||
processor.move(info, substitutor);
|
||||
}
|
||||
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
getProcessor(member).postProcessMember(member);
|
||||
|
||||
final JavaRefactoringListenerManager listenerManager = JavaRefactoringListenerManager.getInstance(myProject);
|
||||
((JavaRefactoringListenerManagerImpl)listenerManager).fireMemberMoved(mySourceClass, member);
|
||||
}
|
||||
}
|
||||
|
||||
private PullUpHelper<MemberInfo> getProcessor(@NotNull PsiElement element) {
|
||||
Language language = element.getLanguage();
|
||||
return getProcessor(language);
|
||||
}
|
||||
|
||||
private PullUpHelper<MemberInfo> getProcessor(Language language) {
|
||||
PullUpHelper<MemberInfo> helper = myProcessors.get(language);
|
||||
if (helper == null) {
|
||||
helper = PullUpHelper.INSTANCE.forLanguage(language).createPullUpHelper(this);
|
||||
myProcessors.put(language, helper);
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
private PullUpHelper<MemberInfo> getProcessor(@NotNull MemberInfo info) {
|
||||
PsiReferenceList refList = info.getSourceReferenceList();
|
||||
if (refList != null) {
|
||||
return getProcessor(refList.getLanguage());
|
||||
}
|
||||
return getProcessor(info.getMember());
|
||||
}
|
||||
|
||||
private PsiSubstitutor upDownSuperClassSubstitutor() {
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(mySourceClass)) {
|
||||
substitutor = substitutor.put(parameter, null);
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap =
|
||||
TypeConversionUtil.getSuperClassSubstitutor(myTargetSuperClass, mySourceClass, PsiSubstitutor.EMPTY).getSubstitutionMap();
|
||||
for (PsiTypeParameter parameter : substitutionMap.keySet()) {
|
||||
final PsiType type = substitutionMap.get(parameter);
|
||||
final PsiClass resolvedClass = PsiUtil.resolveClassInType(type);
|
||||
if (resolvedClass instanceof PsiTypeParameter) {
|
||||
substitutor = substitutor.put((PsiTypeParameter)resolvedClass, JavaPsiFacade.getElementFactory(myProject).createType(parameter));
|
||||
}
|
||||
}
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
public void moveFieldInitializations() throws IncorrectOperationException {
|
||||
LOG.assertTrue(myMembersAfterMove != null);
|
||||
|
||||
final LinkedHashSet<PsiField> movedFields = new LinkedHashSet<PsiField>();
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
if (member instanceof PsiField) {
|
||||
movedFields.add((PsiField)member);
|
||||
}
|
||||
}
|
||||
|
||||
if (movedFields.isEmpty()) return;
|
||||
|
||||
getProcessor(myTargetSuperClass).moveFieldInitializations(movedFields);
|
||||
}
|
||||
|
||||
public static boolean checkedInterfacesContain(Collection<? extends MemberInfoBase<? extends PsiMember>> memberInfos, PsiMethod psiMethod) {
|
||||
for (MemberInfoBase<? extends PsiMember> memberInfo : memberInfos) {
|
||||
if (memberInfo.isChecked() &&
|
||||
memberInfo.getMember() instanceof PsiClass &&
|
||||
Boolean.FALSE.equals(memberInfo.getOverrides())) {
|
||||
if (((PsiClass)memberInfo.getMember()).findMethodBySignature(psiMethod, true) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getSourceClass() {
|
||||
return mySourceClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getTargetClass() {
|
||||
return myTargetSuperClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocCommentPolicy getDocCommentPolicy() {
|
||||
return myJavaDocPolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PsiMember> getMembersToMove() {
|
||||
return myMovedMembers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PsiMember> getMovedMembers() {
|
||||
return myMembersAfterMove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
private class PullUpUsageViewDescriptor implements UsageViewDescriptor {
|
||||
public String getProcessedElementsHeader() {
|
||||
return "Pull up members from";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getElements() {
|
||||
return new PsiElement[]{mySourceClass};
|
||||
}
|
||||
|
||||
public String getCodeReferencesText(int usagesCount, int filesCount) {
|
||||
return "Class to pull up members to \"" + RefactoringUIUtil.getDescription(myTargetSuperClass, true) + "\"";
|
||||
}
|
||||
|
||||
public String getCommentReferencesText(int usagesCount, int filesCount) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.refactoring.extractSuperclass.ExtractSuperClassProcessor;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpConflictsUtil;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.InterfaceContainmentVerifier;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
@@ -183,7 +183,7 @@ public class ExtractSuperClassTest extends RefactoringTestCase {
|
||||
PullUpConflictsUtil.checkConflicts(members, psiClass, superClass, targetPackage, targetDirectory, new InterfaceContainmentVerifier() {
|
||||
@Override
|
||||
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
|
||||
return PullUpHelper.checkedInterfacesContain(Arrays.asList(members), psiMethod);
|
||||
return PullUpProcessor.checkedInterfacesContain(Arrays.asList(members), psiMethod);
|
||||
}
|
||||
}, false);
|
||||
if (conflicts != null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpConflictsUtil;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.InterfaceContainmentVerifier;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
@@ -70,11 +70,11 @@ public class PullUpMultifileTest extends MultiFileTestCase {
|
||||
PullUpConflictsUtil.checkConflicts(membersToMove, srcClass, targetClass, targetPackage, targetDirectory, new InterfaceContainmentVerifier() {
|
||||
@Override
|
||||
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
|
||||
return PullUpHelper.checkedInterfacesContain(Arrays.asList(membersToMove), psiMethod);
|
||||
return PullUpProcessor.checkedInterfacesContain(Arrays.asList(membersToMove), psiMethod);
|
||||
}
|
||||
}));
|
||||
|
||||
new PullUpHelper(srcClass, targetClass, membersToMove, new DocCommentPolicy(DocCommentPolicy.ASIS)).run();
|
||||
new PullUpProcessor(srcClass, targetClass, membersToMove, new DocCommentPolicy(DocCommentPolicy.ASIS)).run();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.listeners.JavaRefactoringListenerManager;
|
||||
import com.intellij.refactoring.listeners.MoveMemberListener;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
@@ -176,7 +176,7 @@ public class PullUpTest extends LightRefactoringTestCase {
|
||||
}
|
||||
};
|
||||
JavaRefactoringListenerManager.getInstance(getProject()).addMoveMembersListener(listener);
|
||||
final PullUpHelper helper = new PullUpHelper(sourceClass, targetClass, infos, new DocCommentPolicy(DocCommentPolicy.ASIS));
|
||||
final PullUpProcessor helper = new PullUpProcessor(sourceClass, targetClass, infos, new DocCommentPolicy(DocCommentPolicy.ASIS));
|
||||
helper.run();
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
JavaRefactoringListenerManager.getInstance(getProject()).removeMoveMembersListener(listener);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/3/13
|
||||
*/
|
||||
public interface PullUpData {
|
||||
PsiClass getSourceClass();
|
||||
|
||||
PsiClass getTargetClass();
|
||||
|
||||
DocCommentPolicy getDocCommentPolicy();
|
||||
|
||||
Set<PsiMember> getMembersToMove();
|
||||
|
||||
Set<PsiMember> getMovedMembers();
|
||||
|
||||
Project getProject();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoBase;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/4/13
|
||||
*/
|
||||
public interface PullUpHelper<T extends MemberInfoBase<? extends PsiMember>> {
|
||||
LanguageExtension<PullUpHelperFactory> INSTANCE = new LanguageExtension<PullUpHelperFactory>("com.intellij.refactoring.pullUpHelperFactory");
|
||||
|
||||
void encodeContextInfo(T info);
|
||||
|
||||
void move(T info, PsiSubstitutor substitutor);
|
||||
|
||||
void postProcessMember(PsiMember member);
|
||||
|
||||
void setCorrectVisibility(T info);
|
||||
|
||||
void moveFieldInitializations(LinkedHashSet<PsiField> movedFields);
|
||||
|
||||
void updateUsage(PsiElement element);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/4/13
|
||||
*/
|
||||
public interface PullUpHelperFactory {
|
||||
PullUpHelper createPullUpHelper(PullUpData data);
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,7 +41,7 @@ public class MemberDependenciesStorage<T extends NavigatablePsiElement, C extend
|
||||
protected Set<T> getMemberDependencies(T member) {
|
||||
Set<T> result = myDependencyGraph.get(member);
|
||||
if (result == null) {
|
||||
DependentMembersCollectorBase<T, C> collector = getCollector();
|
||||
DependentMembersCollectorBase<T, C> collector = getCollector(member);
|
||||
if (collector != null) {
|
||||
collector.collect(member);
|
||||
result = collector.getCollection();
|
||||
@@ -51,8 +51,8 @@ public class MemberDependenciesStorage<T extends NavigatablePsiElement, C extend
|
||||
return result;
|
||||
}
|
||||
|
||||
private DependentMembersCollectorBase<T, C> getCollector() {
|
||||
final ClassMembersRefactoringSupport factory = LanguageDependentMembersRefactoringSupport.INSTANCE.forLanguage(myClass.getLanguage());
|
||||
private DependentMembersCollectorBase<T, C> getCollector(T member) {
|
||||
final ClassMembersRefactoringSupport factory = LanguageDependentMembersRefactoringSupport.INSTANCE.forLanguage(member.getLanguage());
|
||||
return factory != null ? factory.createDependentMembersCollector(myClass, mySuperClass) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,6 +1445,8 @@
|
||||
<codeInsight.unresolvedReferenceQuickFixProvider implementation="org.jetbrains.plugins.groovy.jarFinder.GroovyFindJarQuickFixProvider"/>
|
||||
<lang.refactoringSupport.classMembersRefactoringSupport language="Groovy"
|
||||
implementationClass="org.jetbrains.plugins.groovy.refactoring.classMembers.GroovyClassMembersRefactoringSupport"/>
|
||||
<refactoring.pullUpHelperFactory language="Groovy"
|
||||
implementationClass="org.jetbrains.plugins.groovy.refactoring.memberPullUp.GrPullUpHelperFactory"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.debugger">
|
||||
|
||||
+2
-2
@@ -25,6 +25,7 @@ import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
|
||||
import com.intellij.refactoring.memberPullUp.JavaPullUpHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
@@ -41,7 +42,6 @@ import org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrIntroduceCo
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldHandler;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterHandler;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GrIntroduceVariableHandler;
|
||||
import org.jetbrains.plugins.groovy.refactoring.memberPullUp.GrPullUpHandler;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -134,7 +134,7 @@ public class GroovyRefactoringSupportProvider extends RefactoringSupportProvider
|
||||
@Nullable
|
||||
@Override
|
||||
public RefactoringActionHandler getPullUpHandler() {
|
||||
return new GrPullUpHandler();
|
||||
return new JavaPullUpHandler();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.extractInterface.ExtractClassUtil;
|
||||
import com.intellij.refactoring.extractSuperclass.ExtractSuperClassUtil;
|
||||
import com.intellij.refactoring.lang.ElementsHandler;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
@@ -140,7 +140,7 @@ public class GrExtractInterfaceHandler implements RefactoringActionHandler, Elem
|
||||
final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList();
|
||||
assert referenceList != null;
|
||||
referenceList.add(ref);
|
||||
PullUpHelper pullUpHelper = new PullUpHelper(aClass, anInterface, selectedMembers, javaDocPolicy);
|
||||
PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, anInterface, selectedMembers, javaDocPolicy);
|
||||
pullUpHelper.moveMembersToBase();
|
||||
return anInterface;
|
||||
}
|
||||
|
||||
+4
-5
@@ -29,11 +29,10 @@ import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoModel;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpDialogBase;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
|
||||
import com.intellij.refactoring.ui.AbstractMemberSelectionTable;
|
||||
import com.intellij.refactoring.ui.ClassCellRenderer;
|
||||
import com.intellij.refactoring.ui.DocCommentPanel;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.RefactoringHierarchyUtil;
|
||||
import com.intellij.refactoring.util.classMembers.InterfaceContainmentVerifier;
|
||||
import com.intellij.refactoring.util.classMembers.UsesAndInterfacesDependencyMemberInfoModel;
|
||||
@@ -58,7 +57,7 @@ class GrPullUpDialog extends PullUpDialogBase<GrMemberInfoStorage, GrMemberInfo,
|
||||
|
||||
private final InterfaceContainmentVerifier myInterfaceContainmentVerifier = new InterfaceContainmentVerifier() {
|
||||
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
|
||||
return PullUpHelper.checkedInterfacesContain(myMemberInfos, psiMethod);
|
||||
return PullUpProcessor.checkedInterfacesContain(myMemberInfos, psiMethod);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,8 +142,8 @@ class GrPullUpDialog extends PullUpDialogBase<GrMemberInfoStorage, GrMemberInfo,
|
||||
}
|
||||
|
||||
List<GrMemberInfo> infos = getSelectedMemberInfos();
|
||||
GrPullUpHelper processor = new GrPullUpHelper(myClass, superClass, infos.toArray(new GrMemberInfo[infos.size()]), new DocCommentPolicy(getJavaDocPolicy()));
|
||||
invokeRefactoring(processor);
|
||||
//GrPullUpProcessor processor = new GrPullUpProcessor(myClass, superClass, infos.toArray(new GrMemberInfo[infos.size()]), new DocCommentPolicy(getJavaDocPolicy()));
|
||||
//invokeRefactoring(processor);
|
||||
close(OK_EXIT_CODE);
|
||||
}
|
||||
|
||||
|
||||
+188
-260
@@ -17,8 +17,9 @@ package org.jetbrains.plugins.groovy.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.lang.findUsages.DescriptiveNameUtil;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
@@ -30,19 +31,13 @@ import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.listeners.JavaRefactoringListenerManager;
|
||||
import com.intellij.refactoring.listeners.impl.JavaRefactoringListenerManagerImpl;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpData;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.util.DocCommentPolicy;
|
||||
import com.intellij.refactoring.util.RefactoringHierarchyUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocCommentOwner;
|
||||
@@ -64,215 +59,106 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyChangeContextUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.classMembers.GrClassMemberReferenceVisitor;
|
||||
import org.jetbrains.plugins.groovy.refactoring.classMembers.GrMemberInfo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
* Created by Max Medvedev on 10/4/13
|
||||
*/
|
||||
public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
public class GrPullUpHelper implements PullUpHelper<MemberInfo> {
|
||||
private static final Logger LOG = Logger.getInstance(GrPullUpHelper.class);
|
||||
|
||||
private static final Key<Boolean> SUPER_REF = Key.create("SUPER_REF");
|
||||
private static final Key<Boolean> THIS_REF = Key.create("THIS_REF");
|
||||
private static final Key<Boolean> PRESERVE_QUALIFIER = Key.create("PRESERVE_QUALIFIER");
|
||||
|
||||
private PsiClass mySourceClass;
|
||||
private GrTypeDefinition myTargetSuperClass;
|
||||
private GrMemberInfo[] myMembersToMove;
|
||||
private final PsiClass myTargetSuperClass;
|
||||
private final Set<PsiMember> myMembersToMove;
|
||||
private final PsiClass mySourceClass;
|
||||
private Project myProject;
|
||||
private DocCommentPolicy myDocCommentPolicy;
|
||||
private Set<PsiMember> myMembersAfterMove;
|
||||
|
||||
final ExplicitSuperDeleter myExplicitSuperDeleter;
|
||||
final QualifiedThisSuperAdjuster myThisSuperAdjuster;
|
||||
private QualifiedThisSuperSearcher myQualifiedSearcher;
|
||||
|
||||
public GrPullUpHelper(PsiClass aClass, PsiClass superClass, GrMemberInfo[] infos, DocCommentPolicy policy) {
|
||||
super(aClass.getProject());
|
||||
public GrPullUpHelper(PullUpData data) {
|
||||
myTargetSuperClass = data.getTargetClass();
|
||||
myMembersToMove = data.getMembersToMove();
|
||||
mySourceClass = data.getSourceClass();
|
||||
myProject = data.getProject();
|
||||
myDocCommentPolicy = data.getDocCommentPolicy();
|
||||
myMembersAfterMove = data.getMovedMembers();
|
||||
myExplicitSuperDeleter = new ExplicitSuperDeleter();
|
||||
myThisSuperAdjuster = new QualifiedThisSuperAdjuster();
|
||||
|
||||
mySourceClass = aClass;
|
||||
myTargetSuperClass = (GrTypeDefinition)superClass;
|
||||
myMembersToMove = infos;
|
||||
myDocCommentPolicy = policy;
|
||||
myQualifiedSearcher = new QualifiedThisSuperSearcher();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
|
||||
return new UsageViewDescriptor() {
|
||||
public String getProcessedElementsHeader() {
|
||||
return "Pull up members from";
|
||||
}
|
||||
public void encodeContextInfo(MemberInfo info) {
|
||||
GroovyChangeContextUtil.encodeContextInfo(info.getMember());
|
||||
|
||||
@NotNull
|
||||
public PsiElement[] getElements() {
|
||||
return new PsiClass[]{mySourceClass};
|
||||
}
|
||||
|
||||
public String getCodeReferencesText(int usagesCount, int filesCount) {
|
||||
return "Class to pull up members to \"" + RefactoringUIUtil.getDescription(myTargetSuperClass, true) + "\"";
|
||||
}
|
||||
|
||||
public String getCommentReferencesText(int usagesCount, int filesCount) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
((GroovyPsiElement)info.getMember()).accept(myQualifiedSearcher);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageInfo[] findUsages() {
|
||||
final List<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
for (GrMemberInfo info : myMembersToMove) {
|
||||
final PsiMember member = info.getMember();
|
||||
if (member.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
for (PsiReference reference : ReferencesSearch.search(member)) {
|
||||
result.add(new UsageInfo(reference));
|
||||
}
|
||||
}
|
||||
public void move(MemberInfo info, PsiSubstitutor substitutor) {
|
||||
if (info.getMember() instanceof PsiMethod) {
|
||||
doMoveMethod(substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiField) {
|
||||
doMoveField(substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiClass) {
|
||||
doMoveClass(substitutor, info);
|
||||
}
|
||||
|
||||
return DefaultGroovyMethods.asType(result, UsageInfo[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(UsageInfo[] usages) {
|
||||
moveMembersToBase();
|
||||
//moveFieldInitializations(); todo
|
||||
for (UsageInfo usage : usages) {
|
||||
PsiElement element = usage.getElement();
|
||||
if (element instanceof GrReferenceExpression) {
|
||||
GrExpression qualifier = ((GrReferenceExpression)element).getQualifier();
|
||||
if (qualifier instanceof GrReferenceExpression && ((GrReferenceExpression)qualifier).resolve().equals(mySourceClass)) {
|
||||
((GrReferenceExpression)qualifier).bindToElement(myTargetSuperClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void postProcessMember(PsiMember member) {
|
||||
((GrMember)member).accept(myExplicitSuperDeleter);
|
||||
((GrMember)member).accept(myThisSuperAdjuster);
|
||||
|
||||
/*
|
||||
todo
|
||||
ApplicationManager.application.invokeLater(new Runnable() {
|
||||
GroovyChangeContextUtil.decodeContextInfo(member, null, null);
|
||||
|
||||
((GroovyPsiElement)member).accept(new GroovyRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void run() {
|
||||
processMethodsDuplicates();
|
||||
public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
|
||||
if (processRef(referenceExpression)) return;
|
||||
super.visitReferenceExpression(referenceExpression);
|
||||
}
|
||||
}, ModalityState.NON_MODAL, myProject.getDisposed());*/
|
||||
|
||||
@Override
|
||||
public void visitCodeReferenceElement(GrCodeReferenceElement refElement) {
|
||||
if (processRef(refElement)) return;
|
||||
super.visitCodeReferenceElement(refElement);
|
||||
}
|
||||
|
||||
private boolean processRef(@NotNull GrReferenceElement<? extends GroovyPsiElement> refElement) {
|
||||
final PsiElement qualifier = refElement.getQualifier();
|
||||
if (qualifier != null) {
|
||||
final Boolean preserveQualifier = qualifier.getCopyableUserData(PRESERVE_QUALIFIER);
|
||||
if (preserveQualifier != null && !preserveQualifier) {
|
||||
refElement.setQualifier(null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle.message("pullUp.command", DescriptiveNameUtil.getDescriptiveName(mySourceClass));
|
||||
}
|
||||
|
||||
public void moveMembersToBase() throws IncorrectOperationException {
|
||||
final HashSet<PsiMember> movedMembers = ContainerUtil.newHashSet();
|
||||
myMembersAfterMove = ContainerUtil.newHashSet();
|
||||
|
||||
// build aux sets
|
||||
for (GrMemberInfo info : myMembersToMove) {
|
||||
movedMembers.add(info.getMember());
|
||||
}
|
||||
|
||||
|
||||
// correct private member visibility
|
||||
for (GrMemberInfo info : myMembersToMove) {
|
||||
if (info.getMember() instanceof PsiClass && info.getOverrides() != null) continue;
|
||||
setCorrectVisibility(movedMembers, info);
|
||||
GroovyChangeContextUtil.encodeContextInfo(info.getMember());
|
||||
info.getMember().accept(new QualifiedThisSuperSearcher());
|
||||
fixReferencesToStatic(info.getMember(), movedMembers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
final PsiSubstitutor substitutor = upDownSuperClassSubstitutor();
|
||||
|
||||
// do actual move
|
||||
for (GrMemberInfo info : myMembersToMove) {
|
||||
if (info.getMember() instanceof PsiMethod) {
|
||||
doMoveMethod(substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof GrField) {
|
||||
doMoveField(substitutor, info);
|
||||
}
|
||||
else if (info.getMember() instanceof PsiClass) {
|
||||
doMoveClass(substitutor, info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ExplicitSuperDeleter explicitSuperDeleter = new ExplicitSuperDeleter();
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
((GrMember)member).accept(explicitSuperDeleter);
|
||||
}
|
||||
explicitSuperDeleter.fixSupers();
|
||||
|
||||
final QualifiedThisSuperAdjuster qualifiedThisSuperAdjuster = new QualifiedThisSuperAdjuster();
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
((GrMember)member).accept(qualifiedThisSuperAdjuster);
|
||||
}
|
||||
|
||||
for (PsiMember member : myMembersAfterMove) {
|
||||
GroovyChangeContextUtil.decodeContextInfo(member, null, null);
|
||||
}
|
||||
|
||||
|
||||
final JavaRefactoringListenerManagerImpl listenerManager = (JavaRefactoringListenerManagerImpl)JavaRefactoringListenerManager.getInstance(myProject);
|
||||
for (final PsiMember movedMember : myMembersAfterMove) {
|
||||
((GroovyPsiElement)movedMember).accept(new GroovyRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
|
||||
if (processRef(referenceExpression)) return;
|
||||
super.visitReferenceExpression(referenceExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCodeReferenceElement(GrCodeReferenceElement refElement) {
|
||||
if (processRef(refElement)) return;
|
||||
super.visitCodeReferenceElement(refElement);
|
||||
}
|
||||
|
||||
private boolean processRef(@NotNull GrReferenceElement<? extends GroovyPsiElement> refElement) {
|
||||
final PsiElement qualifier = refElement.getQualifier();
|
||||
if (qualifier != null) {
|
||||
final Boolean preserveQualifier = qualifier.getCopyableUserData(PRESERVE_QUALIFIER);
|
||||
if (preserveQualifier != null && !preserveQualifier) {
|
||||
refElement.setQualifier(null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
listenerManager.fireMemberMoved(mySourceClass, movedMember);
|
||||
}
|
||||
}
|
||||
|
||||
private PsiSubstitutor upDownSuperClassSubstitutor() {
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(mySourceClass)) {
|
||||
substitutor = substitutor.put(parameter, null);
|
||||
}
|
||||
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap =
|
||||
TypeConversionUtil.getSuperClassSubstitutor(myTargetSuperClass, mySourceClass, PsiSubstitutor.EMPTY).getSubstitutionMap();
|
||||
for (PsiTypeParameter parameter : substitutionMap.keySet()) {
|
||||
final PsiType type = substitutionMap.get(parameter);
|
||||
final PsiClass resolvedClass = PsiUtil.resolveClassInType(type);
|
||||
if (resolvedClass instanceof PsiTypeParameter) {
|
||||
substitutor = substitutor.put((PsiTypeParameter)resolvedClass, JavaPsiFacade.getElementFactory(myProject).createType(parameter));
|
||||
}
|
||||
}
|
||||
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
public void setCorrectVisibility(final HashSet<PsiMember> movedMembers, GrMemberInfo info) {
|
||||
public void setCorrectVisibility(MemberInfo info) {
|
||||
PsiModifierListOwner modifierListOwner = info.getMember();
|
||||
if (myTargetSuperClass.isInterface()) {
|
||||
PsiUtil.setModifierProperty(modifierListOwner, PsiModifier.PUBLIC, true);
|
||||
}
|
||||
else if (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (info.isToAbstract() || willBeUsedInSubclass(modifierListOwner, movedMembers, myTargetSuperClass, mySourceClass)) {
|
||||
if (info.isToAbstract() || willBeUsedInSubclass(modifierListOwner, myMembersToMove, myTargetSuperClass, mySourceClass)) {
|
||||
PsiUtil.setModifierProperty(modifierListOwner, PsiModifier.PROTECTED, true);
|
||||
}
|
||||
|
||||
@@ -296,7 +182,7 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
|
||||
private void check(PsiMember member) {
|
||||
if (member.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (willBeUsedInSubclass(member, movedMembers, myTargetSuperClass, mySourceClass)) {
|
||||
if (willBeUsedInSubclass(member, myMembersToMove, myTargetSuperClass, mySourceClass)) {
|
||||
PsiUtil.setModifierProperty(member, PsiModifier.PROTECTED, true);
|
||||
}
|
||||
}
|
||||
@@ -304,6 +190,22 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveFieldInitializations(LinkedHashSet<PsiField> movedFields) {
|
||||
//todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUsage(PsiElement element) {
|
||||
if (element instanceof GrReferenceExpression) {
|
||||
GrExpression qualifierExpression = ((GrReferenceExpression)element).getQualifierExpression();
|
||||
if (qualifierExpression instanceof GrReferenceExpression && ((GrReferenceExpression)qualifierExpression).resolve() == mySourceClass) {
|
||||
((GrReferenceExpression)qualifierExpression).bindToElement(myTargetSuperClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean willBeUsedInSubclass(PsiElement member, Set<PsiMember> movedMembers, PsiClass superclass, PsiClass subclass) {
|
||||
@@ -317,7 +219,7 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void doMoveMethod(PsiSubstitutor substitutor, GrMemberInfo info) {
|
||||
private void doMoveMethod(PsiSubstitutor substitutor, MemberInfo info) {
|
||||
GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
GrMethod method = (GrMethod)info.getMember();
|
||||
PsiMethod sibling = method;
|
||||
@@ -376,20 +278,25 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
PsiUtil.setModifierProperty(myTargetSuperClass, PsiModifier.ABSTRACT, true);
|
||||
}
|
||||
|
||||
//fixReferencesToStatic(methodCopy, movedMembers);
|
||||
fixReferencesToStatic(methodCopy);
|
||||
replaceMovedMemberTypeParameters(methodCopy, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
final PsiMethod superClassMethod = myTargetSuperClass.findMethodBySignature(methodCopy, false);
|
||||
final GrMethod movedElement;
|
||||
|
||||
Language language = myTargetSuperClass.getLanguage();
|
||||
final PsiMethod movedElement;
|
||||
if (superClassMethod != null && superClassMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
movedElement = (GrMethod)superClassMethod.replace(methodCopy);
|
||||
movedElement = (PsiMethod)superClassMethod.replace(convertMethodToLanguage(methodCopy, language));
|
||||
}
|
||||
else {
|
||||
movedElement =
|
||||
anchor != null ? (GrMethod)myTargetSuperClass.addBefore(methodCopy, anchor) : (GrMethod)myTargetSuperClass.add(methodCopy);
|
||||
movedElement = anchor != null
|
||||
? (PsiMethod)myTargetSuperClass.addBefore(convertMethodToLanguage(methodCopy, language), anchor)
|
||||
: (PsiMethod)myTargetSuperClass.add(convertMethodToLanguage(methodCopy, language));
|
||||
myMembersAfterMove.add(movedElement);
|
||||
}
|
||||
|
||||
GrDocCommentUtil.setDocComment(movedElement, method.getDocComment());
|
||||
if (movedElement instanceof GrMethod) {
|
||||
GrDocCommentUtil.setDocComment((GrDocCommentOwner)movedElement, method.getDocComment());
|
||||
}
|
||||
|
||||
deleteMemberWithDocComment(method);
|
||||
}
|
||||
@@ -447,8 +354,8 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void fixReferencesToStatic(GroovyPsiElement classMember, Set<PsiMember> movedMembers) throws IncorrectOperationException {
|
||||
final StaticReferencesCollector collector = new StaticReferencesCollector(movedMembers);
|
||||
private void fixReferencesToStatic(GroovyPsiElement classMember) throws IncorrectOperationException {
|
||||
final StaticReferencesCollector collector = new StaticReferencesCollector(myMembersToMove);
|
||||
classMember.accept(collector);
|
||||
ArrayList<GrReferenceElement> refs = collector.getReferences();
|
||||
ArrayList<PsiElement> members = collector.getReferees();
|
||||
@@ -515,20 +422,18 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
}
|
||||
|
||||
private class ExplicitSuperDeleter extends GroovyRecursiveElementVisitor {
|
||||
private final ArrayList<GrExpression> mySupersToDelete = ContainerUtil.newArrayList();
|
||||
private final ArrayList<GrReferenceExpression> mySupersToChangeToThis = ContainerUtil.newArrayList();
|
||||
private final GrExpression myThisExpression = GroovyPsiElementFactory.getInstance(myProject).createExpressionFromText("this", null);
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(GrReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if(org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isSuperReference(expression.getQualifierExpression())) {
|
||||
PsiElement resolved = expression.resolve();
|
||||
if (resolved == null || resolved instanceof PsiMethod && shouldFixSuper((PsiMethod) resolved)) {
|
||||
mySupersToDelete.add(expression.getQualifierExpression());
|
||||
expression.setQualifier(null);
|
||||
}
|
||||
}
|
||||
else if (org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isSuperReference(expression)) {
|
||||
mySupersToChangeToThis.add(expression);
|
||||
expression.replaceWithExpression(myThisExpression, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,20 +459,6 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
final PsiMethod methodFromSuper = myTargetSuperClass.findMethodBySignature(method, false);
|
||||
return methodFromSuper == null;
|
||||
}
|
||||
|
||||
public void fixSupers() throws IncorrectOperationException {
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
GrReferenceExpression thisExpression = (GrReferenceExpression) factory.createExpressionFromText("this", null);
|
||||
for (GrExpression expression : mySupersToDelete) {
|
||||
if (expression.getParent() instanceof GrReferenceExpression) {
|
||||
((GrReferenceExpression)expression.getParent()).setQualifier(null);
|
||||
}
|
||||
}
|
||||
|
||||
for (GrReferenceExpression superExpression : mySupersToChangeToThis) {
|
||||
superExpression.replace(thisExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class QualifiedThisSuperAdjuster extends GroovyRecursiveElementVisitor {
|
||||
@@ -604,70 +495,102 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void doMoveField(PsiSubstitutor substitutor, GrMemberInfo info) {
|
||||
private void doMoveField(PsiSubstitutor substitutor, MemberInfo info) {
|
||||
GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
GrField field = (GrField)info.getMember();
|
||||
field.normalizeDeclaration();
|
||||
replaceMovedMemberTypeParameters(field, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
//fixReferencesToStatic(field, movedMembers);
|
||||
fixReferencesToStatic(field);
|
||||
if (myTargetSuperClass.isInterface()) {
|
||||
PsiUtil.setModifierProperty(field, PsiModifier.PUBLIC, true);
|
||||
}
|
||||
final PsiMember movedElement = (PsiMember)myTargetSuperClass.add(field);
|
||||
final PsiMember movedElement = (PsiMember)myTargetSuperClass.add(convertFieldToLanguage(field, myTargetSuperClass.getLanguage()));
|
||||
myMembersAfterMove.add(movedElement);
|
||||
deleteMemberWithDocComment(field);
|
||||
}
|
||||
|
||||
private void doMoveClass(PsiSubstitutor substitutor, GrMemberInfo info) {
|
||||
GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
GrTypeDefinition aClass = (GrTypeDefinition)info.getMember();
|
||||
private void doMoveClass(PsiSubstitutor substitutor, MemberInfo info) {
|
||||
if (Boolean.FALSE.equals(info.getOverrides())) {
|
||||
final GrReferenceList sourceReferenceList = info.getSourceReferenceList();
|
||||
LOG.assertTrue(sourceReferenceList != null);
|
||||
GrCodeReferenceElement ref = mySourceClass.equals(sourceReferenceList.getParent()) ?
|
||||
removeFromReferenceList(sourceReferenceList, aClass) :
|
||||
findReferenceToClass(sourceReferenceList, aClass);
|
||||
if (ref != null && !myTargetSuperClass.isInheritor(aClass, false)) {
|
||||
replaceMovedMemberTypeParameters(ref, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
GrReferenceList referenceList;
|
||||
if (myTargetSuperClass.isInterface()) {
|
||||
referenceList = myTargetSuperClass.getExtendsClause();
|
||||
if (referenceList == null) {
|
||||
GrExtendsClause newClause = GroovyPsiElementFactory.getInstance(myProject).createExtendsClause();
|
||||
PsiElement anchor = myTargetSuperClass.getTypeParameterList() != null ? myTargetSuperClass.getTypeParameterList():
|
||||
myTargetSuperClass.getNameIdentifierGroovy();
|
||||
referenceList = (GrReferenceList)myTargetSuperClass.addAfter(newClause, anchor);
|
||||
addSpacesAround(referenceList);
|
||||
}
|
||||
}
|
||||
else {
|
||||
referenceList = myTargetSuperClass.getImplementsClause();
|
||||
|
||||
if (referenceList == null) {
|
||||
GrImplementsClause newClause = GroovyPsiElementFactory.getInstance(myProject).createImplementsClause();
|
||||
PsiElement anchor = myTargetSuperClass.getExtendsClause() != null ? myTargetSuperClass.getExtendsClause() :
|
||||
myTargetSuperClass.getTypeParameterList() != null ? myTargetSuperClass.getTypeParameterList() :
|
||||
myTargetSuperClass.getNameIdentifierGroovy();
|
||||
referenceList = (GrReferenceList)myTargetSuperClass.addAfter(newClause, anchor);
|
||||
addSpacesAround(referenceList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assert referenceList != null;
|
||||
referenceList.add(ref);
|
||||
PsiClass aClass = (PsiClass)info.getMember();
|
||||
if (myTargetSuperClass instanceof GrTypeDefinition) {
|
||||
addClassToSupers(info, aClass, substitutor, (GrTypeDefinition)myTargetSuperClass);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
GrTypeDefinition aClass = (GrTypeDefinition)info.getMember();
|
||||
GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
replaceMovedMemberTypeParameters(aClass, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
//fixReferencesToStatic(aClass, movedMembers);
|
||||
PsiMember movedElement = (PsiMember)myTargetSuperClass.addAfter(aClass, null);
|
||||
//movedElement = (PsiMember)CodeStyleManager.getInstance(myProject).reformat(movedElement);
|
||||
fixReferencesToStatic(aClass);
|
||||
PsiMember movedElement = (PsiMember)myTargetSuperClass.addAfter(convertClassToLanguage(aClass, myTargetSuperClass.getLanguage()), null);
|
||||
myMembersAfterMove.add(movedElement);
|
||||
deleteMemberWithDocComment(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiMethod convertMethodToLanguage(PsiMethod method, Language language) {
|
||||
if (method.getLanguage().equals(language)) {
|
||||
return method;
|
||||
}
|
||||
return JVMElementFactories.getFactory(language, method.getProject()).createMethodFromText(method.getText(), null);
|
||||
}
|
||||
|
||||
private static PsiField convertFieldToLanguage(PsiField field, Language language) {
|
||||
if (field.getLanguage().equals(language)) {
|
||||
return field;
|
||||
}
|
||||
return JVMElementFactories.getFactory(language, field.getProject()).createField(field.getName(), field.getType());
|
||||
}
|
||||
|
||||
private static PsiClass convertClassToLanguage(PsiClass clazz, Language language) {
|
||||
//if (clazz.getLanguage().equals(language)) {
|
||||
// return clazz;
|
||||
//}
|
||||
//PsiClass newClass = JVMElementFactories.getFactory(language, clazz.getProject()).createClass(clazz.getName());
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
private void addClassToSupers(MemberInfo info, PsiClass aClass, PsiSubstitutor substitutor, GrTypeDefinition targetSuperClass) {
|
||||
final PsiReferenceList sourceReferenceList = info.getSourceReferenceList();
|
||||
LOG.assertTrue(sourceReferenceList != null);
|
||||
PsiQualifiedReferenceElement ref = mySourceClass.equals(sourceReferenceList.getParent()) ?
|
||||
removeFromReferenceList(sourceReferenceList, aClass) :
|
||||
findReferenceToClass(sourceReferenceList, aClass);
|
||||
if (ref != null && !targetSuperClass.isInheritor(aClass, false)) {
|
||||
GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
|
||||
replaceMovedMemberTypeParameters(ref, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
|
||||
GrReferenceList referenceList;
|
||||
if (targetSuperClass.isInterface()) {
|
||||
referenceList = targetSuperClass.getExtendsClause();
|
||||
if (referenceList == null) {
|
||||
GrExtendsClause newClause = GroovyPsiElementFactory.getInstance(myProject).createExtendsClause();
|
||||
PsiElement anchor = targetSuperClass.getTypeParameterList() != null ? targetSuperClass.getTypeParameterList():
|
||||
targetSuperClass.getNameIdentifierGroovy();
|
||||
referenceList = (GrReferenceList)targetSuperClass.addAfter(newClause, anchor);
|
||||
addSpacesAround(referenceList);
|
||||
}
|
||||
}
|
||||
else {
|
||||
referenceList = targetSuperClass.getImplementsClause();
|
||||
|
||||
if (referenceList == null) {
|
||||
GrImplementsClause newClause = GroovyPsiElementFactory.getInstance(myProject).createImplementsClause();
|
||||
PsiElement anchor = targetSuperClass.getExtendsClause() != null ? targetSuperClass.getExtendsClause() :
|
||||
targetSuperClass.getTypeParameterList() != null ? targetSuperClass.getTypeParameterList() :
|
||||
targetSuperClass.getNameIdentifierGroovy();
|
||||
referenceList = (GrReferenceList)targetSuperClass.addAfter(newClause, anchor);
|
||||
addSpacesAround(referenceList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assert referenceList != null;
|
||||
referenceList.add(ref);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSpacesAround(@NotNull GrReferenceList list) {
|
||||
PsiElement prev = list.getPrevSibling();
|
||||
if (!PsiImplUtil.isWhiteSpace(prev)) {
|
||||
@@ -680,13 +603,16 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
public static GrCodeReferenceElement findReferenceToClass(GrReferenceList refList, PsiClass aClass) {
|
||||
GrCodeReferenceElement[] refs = refList.getReferenceElementsGroovy();
|
||||
for (GrCodeReferenceElement ref : refs) {
|
||||
public static PsiQualifiedReferenceElement findReferenceToClass(PsiReferenceList refList, PsiClass aClass) {
|
||||
PsiQualifiedReferenceElement[] refs = refList instanceof GrReferenceList ? ((GrReferenceList)refList).getReferenceElementsGroovy()
|
||||
: refList.getReferenceElements();
|
||||
|
||||
for (PsiQualifiedReferenceElement ref : refs) {
|
||||
if (ref.isReferenceTo(aClass)) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -696,11 +622,13 @@ public class GrPullUpHelper extends BaseRefactoringProcessor {
|
||||
*
|
||||
* @return if removed - a reference to the class or null if there were no references to this class in the reference list
|
||||
*/
|
||||
public static GrCodeReferenceElement removeFromReferenceList(GrReferenceList refList, PsiClass aClass) throws IncorrectOperationException {
|
||||
GrCodeReferenceElement[] refs = refList.getReferenceElementsGroovy();
|
||||
for (GrCodeReferenceElement ref : refs) {
|
||||
public static PsiQualifiedReferenceElement removeFromReferenceList(PsiReferenceList refList, PsiClass aClass) throws IncorrectOperationException {
|
||||
List<? extends PsiQualifiedReferenceElement> refs = Arrays.asList(
|
||||
refList instanceof GrReferenceList ? ((GrReferenceList)refList).getReferenceElementsGroovy() : refList.getReferenceElements());
|
||||
|
||||
for (PsiQualifiedReferenceElement ref : refs) {
|
||||
if (ref.isReferenceTo(aClass)) {
|
||||
GrCodeReferenceElement refCopy = (GrCodeReferenceElement)ref.copy();
|
||||
PsiQualifiedReferenceElement refCopy = (PsiQualifiedReferenceElement)ref.copy();
|
||||
ref.delete();
|
||||
return refCopy;
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.refactoring.memberPullUp.PullUpData;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelper;
|
||||
import com.intellij.refactoring.memberPullUp.PullUpHelperFactory;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/4/13
|
||||
*/
|
||||
public class GrPullUpHelperFactory implements PullUpHelperFactory{
|
||||
@Override
|
||||
public PullUpHelper createPullUpHelper(PullUpData data) {
|
||||
return new GrPullUpHelper(data);
|
||||
}
|
||||
}
|
||||
+10
-9
@@ -19,14 +19,15 @@ import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.refactoring.listeners.JavaRefactoringListenerManager
|
||||
import com.intellij.refactoring.listeners.MoveMemberListener
|
||||
import com.intellij.refactoring.memberPullUp.PullUpProcessor
|
||||
import com.intellij.refactoring.util.DocCommentPolicy
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import junit.framework.Assert
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember
|
||||
import org.jetbrains.plugins.groovy.refactoring.classMembers.GrMemberInfo
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
/**
|
||||
* Created by Max Medvedev on 8/17/13
|
||||
@@ -46,9 +47,9 @@ class GrPullUpTest extends LightGroovyTestCase {
|
||||
}
|
||||
|
||||
public void testQualifiedReference() { // IDEADEV-25008
|
||||
doTest(new MemberDescriptor("x", PsiField),
|
||||
new MemberDescriptor("getX", PsiMethod),
|
||||
new MemberDescriptor("setX", PsiMethod));
|
||||
doTest(new MemberDescriptor("getX", PsiMethod),
|
||||
new MemberDescriptor("setX", PsiMethod),
|
||||
new MemberDescriptor("x", PsiField));
|
||||
}
|
||||
|
||||
public void testPullUpInheritedStaticClasses() {
|
||||
@@ -179,7 +180,7 @@ class GrPullUpTest extends LightGroovyTestCase {
|
||||
assertTrue(interfaces[0].isWritable());
|
||||
targetClass = interfaces[0];
|
||||
}
|
||||
GrMemberInfo[] infos = findMembers(sourceClass, membersToFind);
|
||||
MemberInfo[] infos = findMembers(sourceClass, membersToFind);
|
||||
|
||||
final int[] countMoved = [0];
|
||||
final MoveMemberListener listener = new MoveMemberListener() {
|
||||
@@ -190,7 +191,7 @@ class GrPullUpTest extends LightGroovyTestCase {
|
||||
}
|
||||
};
|
||||
JavaRefactoringListenerManager.getInstance(getProject()).addMoveMembersListener(listener);
|
||||
final GrPullUpHelper helper = new GrPullUpHelper(sourceClass, targetClass, infos, new DocCommentPolicy(DocCommentPolicy.ASIS));
|
||||
final PullUpProcessor helper = new PullUpProcessor(sourceClass, targetClass, infos, new DocCommentPolicy(DocCommentPolicy.ASIS));
|
||||
helper.run();
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
JavaRefactoringListenerManager.getInstance(getProject()).removeMoveMembersListener(listener);
|
||||
@@ -217,8 +218,8 @@ class GrPullUpTest extends LightGroovyTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public static GrMemberInfo[] findMembers(final PsiClass sourceClass, final MemberDescriptor... membersToFind) {
|
||||
GrMemberInfo[] infos = new GrMemberInfo[membersToFind.length]
|
||||
public static MemberInfo[] findMembers(final PsiClass sourceClass, final MemberDescriptor... membersToFind) {
|
||||
MemberInfo[] infos = new MemberInfo[membersToFind.length]
|
||||
for (int i = 0; i < membersToFind.length; i++) {
|
||||
final Class<? extends PsiMember> clazz = membersToFind[i].myClass
|
||||
final String name = membersToFind[i].myName
|
||||
@@ -251,7 +252,7 @@ class GrPullUpTest extends LightGroovyTestCase {
|
||||
|
||||
assertNotNull(member)
|
||||
assertInstanceOf(member, GrMember)
|
||||
infos[i] = new GrMemberInfo(member as GrMember, overrides, refList)
|
||||
infos[i] = new MemberInfo(member as GrMember, overrides, refList)
|
||||
infos[i].setToAbstract(membersToFind[i].myAbstract)
|
||||
}
|
||||
return infos
|
||||
|
||||
@@ -169,6 +169,10 @@
|
||||
<with attribute="implementationClass" implements="com.intellij.refactoring.introduceParameter.ExpressionConverter"/>
|
||||
</extensionPoint>
|
||||
|
||||
<extensionPoint name="refactoring.pullUpHelperFactory" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.intellij.refactoring.memberPullUp.PullUpHelperFactory"/>
|
||||
</extensionPoint>
|
||||
|
||||
<!--<extensionPoint name="expectedTypesProvider" interface="com.intellij.codeInsight.ExpectedTypesProviderExtension"/>-->
|
||||
|
||||
<extensionPoint name="java.elementFinder" area="IDEA_PROJECT" interface="com.intellij.psi.PsiElementFinder"/>
|
||||
@@ -1473,6 +1477,8 @@
|
||||
<codeInsight.unresolvedReferenceQuickFixProvider implementation="com.intellij.jarFinder.FindJarQuickFixProvider"/>
|
||||
|
||||
<xdebugger.breakpointType implementation="org.jetbrains.java.debugger.breakpoints.JavaBreakpointType"/>
|
||||
|
||||
<refactoring.pullUpHelperFactory language="JAVA" implementationClass="com.intellij.refactoring.memberPullUp.JavaPullUpHelperFactory"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
|
||||
Reference in New Issue
Block a user