diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java index 82fe110fa752..ee80c762befc 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java @@ -2,14 +2,15 @@ package com.intellij.refactoring.move.moveMembers; import com.intellij.codeInsight.ChangeContextUtil; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.PsiUtilBase; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilBase; import com.intellij.refactoring.util.EnumConstantsUtil; -import com.intellij.refactoring.util.RefactoringUtil; -import com.intellij.util.VisibilityUtil; import com.intellij.refactoring.util.RefactoringHierarchyUtil; +import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -85,16 +86,14 @@ public class MoveJavaMemberHandler implements MoveMemberHandler { return false; } - public PsiMember doMove(MoveMembersOptions options, PsiMember member, ArrayList otherUsages) { + public PsiMember doMove(MoveMembersOptions options, PsiMember member, PsiElement anchor, PsiClass targetClass) { if (member instanceof PsiVariable) { ((PsiVariable)member).normalizeDeclaration(); } - PsiClass targetClass = JavaPsiFacade.getInstance(member.getManager().getProject()) - .findClass(options.getTargetClassName(), GlobalSearchScope.projectScope(member.getProject())); + ChangeContextUtil.encodeContextInfo(member, true); if (targetClass == null) return null; - PsiElement anchor = getAnchor(member, targetClass); final PsiMember memberCopy; if (options.makeEnumConstant() && @@ -132,9 +131,9 @@ public class MoveJavaMemberHandler implements MoveMemberHandler { } @Nullable - private static PsiElement getAnchor(final PsiMember member, final PsiClass targetClass) { + public PsiElement getAnchor(final PsiMember member, final PsiClass targetClass) { if (member instanceof PsiField && member.hasModifierProperty(PsiModifier.STATIC)) { - final List referencedFields = new ArrayList(); + final List afterFields = new ArrayList(); final PsiExpression psiExpression = ((PsiField)member).getInitializer(); if (psiExpression != null) { psiExpression.accept(new JavaRecursiveElementWalkingVisitor() { @@ -144,20 +143,35 @@ public class MoveJavaMemberHandler implements MoveMemberHandler { final PsiElement psiElement = expression.resolve(); if (psiElement instanceof PsiField) { final PsiField psiField = (PsiField)psiElement; - if (psiField.getContainingClass() == targetClass && !referencedFields.contains(psiField)) { - referencedFields.add(psiField); + if (psiField.getContainingClass() == targetClass && !afterFields.contains(psiField)) { + afterFields.add(psiField); } } } }); } - if (!referencedFields.isEmpty()) { - Collections.sort(referencedFields, new Comparator() { - public int compare(final PsiField o1, final PsiField o2) { - return -PsiUtilBase.compareElementsByPosition(o1, o2); - } - }); - return referencedFields.get(0); + + final Comparator fieldComparator = new Comparator() { + public int compare(final PsiField o1, final PsiField o2) { + return -PsiUtilBase.compareElementsByPosition(o1, o2); + } + }; + + if (!afterFields.isEmpty()) { + Collections.sort(afterFields, fieldComparator); + return afterFields.get(0); + } + + final List beforeFields = new ArrayList(); + for (PsiReference psiReference : ReferencesSearch.search(member, new LocalSearchScope(targetClass))) { + final PsiField fieldWithReference = PsiTreeUtil.getParentOfType(psiReference.getElement(), PsiField.class); + if (fieldWithReference != null && !afterFields.contains(fieldWithReference)) { + beforeFields.add(fieldWithReference); + } + } + Collections.sort(beforeFields, fieldComparator); + if (!beforeFields.isEmpty()) { + return beforeFields.get(0).getPrevSibling(); } } return null; diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java index 7ce4522f9623..7043a0ae444f 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMemberHandler.java @@ -1,13 +1,14 @@ package com.intellij.refactoring.move.moveMembers; import com.intellij.lang.LanguageExtension; -import com.intellij.psi.*; - -import java.util.ArrayList; -import java.util.Set; - +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiReference; import org.jetbrains.annotations.Nullable; +import java.util.Set; + /** * @author Maxim.Medvedev */ @@ -21,7 +22,10 @@ public interface MoveMemberHandler { boolean changeExternalUsage(MoveMembersOptions options, MoveMembersProcessor.MoveMembersUsageInfo usage); - PsiMember doMove(MoveMembersOptions options, PsiMember member, ArrayList otherUsages); + PsiMember doMove(MoveMembersOptions options, PsiMember member, PsiElement anchor, PsiClass targetClass); void decodeContextInfo(PsiElement scope); + + @Nullable + PsiElement getAnchor(PsiMember member, PsiClass targetClass); } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java index 2e576d54500b..5e024479332b 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java @@ -139,7 +139,13 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { try { // correct references to moved members from the outside LanguageExtension extension=new LanguageExtension("com.intellij.refactoring.moveMemberHandler"); - + PsiClass targetClass = JavaPsiFacade.getInstance(myProject) + .findClass(myOptions.getTargetClassName(), GlobalSearchScope.projectScope(myProject)); + if (targetClass == null) return; + final Map anchors = new HashMap(); + for (PsiMember member : myMembersToMove) { + anchors.put(member, extension.forLanguage(member.getLanguage()).getAnchor(member, targetClass)); + } ArrayList otherUsages = new ArrayList(); for (UsageInfo usageInfo : usages) { MoveMembersUsageInfo usage = (MoveMembersUsageInfo)usageInfo; @@ -166,7 +172,7 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { } final RefactoringElementListener elementListener = getTransaction().getElementListener(member); final MoveMemberHandler handler = extension.forLanguage(member.getLanguage()); - PsiMember newMember=handler.doMove(myOptions, member, otherUsages); + PsiMember newMember=handler.doMove(myOptions, member, anchors.get(member), targetClass); elementListener.elementMoved(newMember); fixVisibility(newMember, usages); diff --git a/refactoring/tests/com/intellij/refactoring/MoveMembersTest.java b/refactoring/tests/com/intellij/refactoring/MoveMembersTest.java index f108268ddff8..8d06d4a6ce05 100644 --- a/refactoring/tests/com/intellij/refactoring/MoveMembersTest.java +++ b/refactoring/tests/com/intellij/refactoring/MoveMembersTest.java @@ -74,6 +74,10 @@ public class MoveMembersTest extends MultiFileTestCase { doTest("B", "A", 0); } + public void testDependantFields() throws Exception { + doTest("B", "A", 0); + } + protected String getTestRoot() { return "/refactoring/moveMembers/"; } diff --git a/testData/refactoring/moveMembers/dependantFields/after/A.java b/testData/refactoring/moveMembers/dependantFields/after/A.java new file mode 100644 index 000000000000..6213d1201db8 --- /dev/null +++ b/testData/refactoring/moveMembers/dependantFields/after/A.java @@ -0,0 +1,6 @@ +public class A { + void foo(){} + + public static final String ONE = ""; + public static final String TWO = ONE + ""; +} \ No newline at end of file diff --git a/testData/refactoring/moveMembers/dependantFields/after/B.java b/testData/refactoring/moveMembers/dependantFields/after/B.java new file mode 100644 index 000000000000..ebbe4dc08cb2 --- /dev/null +++ b/testData/refactoring/moveMembers/dependantFields/after/B.java @@ -0,0 +1,2 @@ +public class B { +} \ No newline at end of file diff --git a/testData/refactoring/moveMembers/dependantFields/before/A.java b/testData/refactoring/moveMembers/dependantFields/before/A.java new file mode 100644 index 000000000000..617cbfc95478 --- /dev/null +++ b/testData/refactoring/moveMembers/dependantFields/before/A.java @@ -0,0 +1,4 @@ +public class A { + void foo(){} + public static final String TWO = B.ONE + ""; +} \ No newline at end of file diff --git a/testData/refactoring/moveMembers/dependantFields/before/B.java b/testData/refactoring/moveMembers/dependantFields/before/B.java new file mode 100644 index 000000000000..acf3478236a6 --- /dev/null +++ b/testData/refactoring/moveMembers/dependantFields/before/B.java @@ -0,0 +1,3 @@ +public class B { + public static final String ONE = ""; +} \ No newline at end of file