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:
Max Medvedev
2013-10-24 15:39:40 +04:00
parent 0553c874da
commit 91e3c30f86
24 changed files with 841 additions and 576 deletions
@@ -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
@@ -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;
}
@@ -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
);
@@ -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);
}
};
@@ -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,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.
@@ -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;
}
}
+2
View File
@@ -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">
@@ -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
@@ -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;
}
@@ -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);
}
@@ -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;
}
@@ -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);
}
}
@@ -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
+6
View File
@@ -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>