IDEA-66936 move classes with static and aliased imports

This commit is contained in:
Maxim Medvedev
2011-03-31 16:01:44 +04:00
parent 658b5eee39
commit 11b37cbb63
20 changed files with 127 additions and 22 deletions
@@ -18,10 +18,13 @@ package com.intellij.refactoring.move.moveClassesOrPackages;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDirectory;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author Maxim.Medvedev
*/
@@ -43,5 +46,7 @@ public interface MoveClassHandler {
* @param clazz psiClass
* @return null, if this instance of FileNameForPsiProvider cannot provide name for clazz
*/
String getName(PsiClass clazz);
String getName(PsiClass clazz);
void preprocessUsages(Collection<UsageInfo> results);
}
@@ -61,17 +61,21 @@ public class MoveClassesOrPackagesUtil {
for (PsiReference reference : ReferencesSearch.search(element, projectScope, false)) {
TextRange range = reference.getRangeInElement();
if (foundReferences.contains(reference)) continue;
results.add(
new MoveRenameUsageInfo(reference.getElement(), reference, range.getStartOffset(), range.getEndOffset(),
element, false));
results.add(new MoveRenameUsageInfo(reference.getElement(), reference, range.getStartOffset(), range.getEndOffset(), element, false));
foundReferences.add(reference);
}
findNonCodeUsages(searchInStringsAndComments, searchInNonJavaFiles, element, newQName, results);
preprocessUsages(results);
return results.toArray(new UsageInfo[results.size()]);
}
private static void preprocessUsages(ArrayList<UsageInfo> results) {
for (MoveClassHandler handler : MoveClassHandler.EP_NAME.getExtensions()) {
handler.preprocessUsages(results);
}
}
private static String getQualfiedName(final PsiElement element) {
final String oldQName;
if (element instanceof PsiClass) {
@@ -21,9 +21,11 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -134,4 +136,8 @@ public class MoveJavaClassHandler implements MoveClassHandler {
if (!(file instanceof PsiJavaFile)) return null;
return ((PsiJavaFile)file).getClasses().length > 1 ? clazz.getName() + "." + StdFileTypes.JAVA.getDefaultExtension() : file.getName();
}
@Override
public void preprocessUsages(Collection<UsageInfo> results) {
}
}
@@ -36,7 +36,14 @@ public class GroovyChangeContextUtil {
private static final Key<PsiMember> REF_TO_MEMBER = Key.create("REF_TO_MEMBER");
private static final Key<Object> KEY_ENCODED = Key.create("KEY_ENCODED");
private GroovyChangeContextUtil() {
}
public static void encodeContextInfo(PsiElement element) {
encodeContextInfo(element, element);
}
public static void encodeContextInfo(PsiElement element, PsiElement scope) {
if (!(element instanceof GroovyPsiElement)) return;
if (element instanceof GrThisReferenceExpression) {
GrThisReferenceExpression thisExpr = (GrThisReferenceExpression)element;
@@ -49,14 +56,15 @@ public class GroovyChangeContextUtil {
final GrExpression qualifier = refExpr.getQualifierExpression();
if (qualifier == null) {
PsiElement refElement = refExpr.resolve();
if (refElement instanceof GrAccessorMethod) refElement = ((GrAccessorMethod)refElement).getProperty();
if (refElement instanceof PsiClass) {
refExpr.putCopyableUserData(REF_TO_CLASS, (PsiClass)refElement);
element.putCopyableUserData(KEY_ENCODED, KEY_ENCODED);
}
else if (refElement instanceof PsiMember) {
refExpr.putCopyableUserData(REF_TO_MEMBER, (PsiMember)refElement);
element.putCopyableUserData(KEY_ENCODED, KEY_ENCODED);
element.putCopyableUserData(KEY_ENCODED, KEY_ENCODED);
if (refElement != null && !PsiTreeUtil.isContextAncestor(scope, refElement, false)) {
if (refElement instanceof GrAccessorMethod) refElement = ((GrAccessorMethod)refElement).getProperty();
if (refElement instanceof PsiClass) {
refExpr.putCopyableUserData(REF_TO_CLASS, (PsiClass)refElement);
}
else if (refElement instanceof PsiMember) {
refExpr.putCopyableUserData(REF_TO_MEMBER, (PsiMember)refElement);
}
}
}
}
@@ -65,15 +73,15 @@ public class GroovyChangeContextUtil {
final PsiReference ref = element.getReference();
if (ref != null) {
final PsiElement resolvedElement = ref.resolve();
if (resolvedElement instanceof PsiClass) {
element.putCopyableUserData(KEY_ENCODED, KEY_ENCODED);
if (resolvedElement instanceof PsiClass && !PsiTreeUtil.isContextAncestor(scope, resolvedElement, false)) {
element.putCopyableUserData(REF_TO_CLASS, (PsiClass)resolvedElement);
element.putCopyableUserData(KEY_ENCODED, KEY_ENCODED);
}
}
}
for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
encodeContextInfo(child);
encodeContextInfo(child, scope);
}
}
@@ -116,7 +124,7 @@ public class GroovyChangeContextUtil {
else if (thisAccessExpr instanceof GrReferenceExpression) {
final PsiElement qualifier = refExpr.getQualifier();
if (!(qualifier instanceof GrReferenceExpression)) {
refExpr.setQualifier((GrReferenceExpression)thisAccessExpr);
refExpr.setQualifier(thisAccessExpr);
return;
}
}
@@ -23,6 +23,7 @@ import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,9 +34,8 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocCommentOwner;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.impl.GrDocCommentUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.*;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
@@ -45,6 +45,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.refactoring.GroovyChangeContextUtil;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Maxim.Medvedev
@@ -198,6 +199,28 @@ public class MoveGroovyClassHandler implements MoveClassHandler {
return ((GroovyFile)file).getClasses().length > 1 ? clazz.getName() + "." + GroovyFileType.DEFAULT_EXTENSION : file.getName();
}
@Override
public void preprocessUsages(Collection<UsageInfo> results) {
//remove all alias-imported usages from collection
for (Iterator<UsageInfo> iterator = results.iterator(); iterator.hasNext(); ) {
UsageInfo info = iterator.next();
final PsiReference ref = info.getReference();
if (ref==null) continue;
final PsiElement element = ref.getElement();
if (!(element instanceof GrReferenceElement)) continue;
final GroovyResolveResult resolveResult = ((GrReferenceElement)element).advancedResolve();
final GroovyPsiElement context = resolveResult.getCurrentFileResolveContext();
if (!(context instanceof GrImportStatement)) continue;
final String importedName = ((GrImportStatement)context).getImportedName();
if (importedName == null) continue;
iterator.remove();
}
}
@Override
public void prepareMove(@NotNull PsiClass aClass) {
if (aClass.getContainingFile() instanceof GroovyFileBase) {
@@ -220,8 +243,9 @@ public class MoveGroovyClassHandler implements MoveClassHandler {
final Collection<PsiReference> all = ReferencesSearch.search(oldClass, new LocalSearchScope(newClass.getContainingFile())).findAll();
for (PsiReference reference : all) {
final PsiElement element = reference.getElement();
if (element.getParent() instanceof GrImportStatement) {
element.getParent().delete();
final PsiElement parent = element.getParent();
if (parent instanceof GrImportStatement && !((GrImportStatement)parent).isStatic()) {
parent.delete();
}
reference.bindToElement(newClass);
}
@@ -126,6 +126,14 @@ public class GroovyMoveClassTest extends LightCodeInsightFixtureTestCase {
doTest("twoClasses", new String[] {"p1.C1", "p1.C2"}, "p2");
}
public void testStaticImport() {
doTest("staticImport", new String[] {"p1.C1"}, "p2");
}
public void testAliasImported() {
doTest("aliasImported", new String[]{"p1.C1"}, "p2");
}
private void performAction(String[] classNames, String newPackageName) {
final PsiClass[] classes = new PsiClass[classNames.length];
for (int i = 0; i < classes.length; i++) {
@@ -0,0 +1,5 @@
package p1
import p2.C1 as Alias
print new Alias()
@@ -0,0 +1,12 @@
package p2
import static p2.C1.E.e
class C1 {
def foo() {
print e
}
static enum E {
e
}
}
@@ -0,0 +1,4 @@
package p1
class C1 {
}
@@ -0,0 +1,5 @@
package p1
import p1.C1 as Alias
print new Alias()
@@ -0,0 +1,12 @@
package p2
import static p2.C1.E.e
class C1 {
def foo() {
print e
}
static enum E {
e
}
}
@@ -0,0 +1,12 @@
package p1
import static p1.C1.E.e
class C1 {
def foo() {
print e
}
static enum E {
e
}
}