replace all inheritors with static imports

This commit is contained in:
anna
2010-06-24 17:24:39 +04:00
parent 37d6f83aef
commit 11d811d3be
6 changed files with 204 additions and 27 deletions

View File

@@ -17,25 +17,29 @@ package com.intellij.codeInspection.actions;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.actions.OptimizeImportsProcessor;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
public class ReplaceImplementsWithStaticImportAction implements IntentionAction {
public class ReplaceImplementsWithStaticImportAction extends PsiElementBaseIntentionAction {
private static final Logger LOG = Logger.getInstance("#" + ReplaceImplementsWithStaticImportAction.class.getName());
@NotNull
@@ -48,8 +52,14 @@ public class ReplaceImplementsWithStaticImportAction implements IntentionAction
return getText();
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof PsiJavaFile)) return false;
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (!(element.getContainingFile() instanceof PsiJavaFile)) return false;
if (element instanceof PsiIdentifier) {
final PsiElement parent = element.getParent();
if (parent instanceof PsiClass) {
return isEmptyClass(project, (PsiClass)parent) && DirectClassInheritorsSearch.search((PsiClass)parent).findFirst() != null;
}
}
final PsiReference psiReference = TargetElementUtilBase.findReference(editor);
if (psiReference == null) return false;
@@ -64,11 +74,13 @@ public class ReplaceImplementsWithStaticImportAction implements IntentionAction
final PsiElement target = psiReference.resolve();
if (target == null || !(target instanceof PsiClass)) return false;
PsiClass targetClass = (PsiClass)target;
return isEmptyClass(project, (PsiClass)target);
}
private static boolean isEmptyClass(Project project, PsiClass targetClass) {
if (!targetClass.isInterface()) {
return false;
}
final PsiReferenceList extendsList = targetClass.getExtendsList();
LOG.assertTrue(extendsList != null);
if (extendsList.getReferencedTypes().length > 0) {
@@ -78,7 +90,8 @@ public class ReplaceImplementsWithStaticImportAction implements IntentionAction
if (objectClass == null) return false;
methods.removeAll(Arrays.asList(objectClass.getMethods()));
if (methods.size() > 0) return false;
} else if (targetClass.getMethods().length > 0){
}
else if (targetClass.getMethods().length > 0) {
return false;
}
return targetClass.getAllFields().length > 0;
@@ -87,30 +100,127 @@ public class ReplaceImplementsWithStaticImportAction implements IntentionAction
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
if (!CodeInsightUtilBase.preparePsiElementForWrite(file)) return;
final PsiReference psiReference = file.findReferenceAt(editor.getCaretModel().getOffset());
LOG.assertTrue(psiReference != null);
final int offset = editor.getCaretModel().getOffset();
final PsiReference psiReference = file.findReferenceAt(offset);
if (psiReference != null) {
final PsiElement element = psiReference.getElement();
final PsiElement element = psiReference.getElement();
final PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
LOG.assertTrue(psiClass != null);
final PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
LOG.assertTrue(psiClass != null);
final PsiElement target = psiReference.resolve();
LOG.assertTrue(target instanceof PsiClass);
final PsiElement target = psiReference.resolve();
LOG.assertTrue(target instanceof PsiClass);
final PsiClass targetClass = (PsiClass)target;
final PsiClass targetClass = (PsiClass)target;
new WriteCommandAction(project, getText(), file) {
protected void run(Result result) throws Throwable {
for (PsiField constField : targetClass.getAllFields()) {
final PsiClass containingClass = constField.getContainingClass();
for (PsiReference ref : ReferencesSearch.search(constField, new LocalSearchScope(psiClass))) {
((PsiReferenceExpressionImpl)ref)
.bindToElementViaStaticImport(containingClass, constField.getName(), ((PsiJavaFile)file).getImportList());
}
}
element.delete();
JavaCodeStyleManager.getInstance(project).optimizeImports(file);
}
}.execute();
}
else {
final PsiElement identifier = file.findElementAt(offset);
LOG.assertTrue(identifier instanceof PsiIdentifier);
final PsiElement element = identifier.getParent();
LOG.assertTrue(element instanceof PsiClass);
final PsiClass targetClass = (PsiClass)element;
final Map<PsiFile, Map<PsiField, Set<PsiReference>>> refs = new HashMap<PsiFile, Map<PsiField, Set<PsiReference>>>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
for (PsiField field : targetClass.getAllFields()) {
final String fieldName = field.getName();
if (progressIndicator != null) {
progressIndicator.setText2(fieldName);
}
for (PsiReference reference : ReferencesSearch.search(field)) {
final PsiFile psiFile = reference.getElement().getContainingFile();
if (psiFile instanceof PsiJavaFile) {
Map<PsiField, Set<PsiReference>> references = refs.get(psiFile);
if (references == null) {
references = new HashMap<PsiField, Set<PsiReference>>();
refs.put(psiFile, references);
}
Set<PsiReference> fieldsRefs = references.get(field);
if (fieldsRefs == null) {
fieldsRefs = new HashSet<PsiReference>();
references.put(field, fieldsRefs);
}
fieldsRefs.add(reference);
}
}
}
}
}, "Find constant field usages...", true, project)) {
return;
}
for (PsiField constField : targetClass.getAllFields()) {
for (PsiReference ref : ReferencesSearch.search(constField, new LocalSearchScope(psiClass))) {
((PsiReferenceExpressionImpl)ref).bindToElementViaStaticImport(targetClass, constField.getName(), ((PsiJavaFile)file).getImportList());
final Set<PsiJavaCodeReferenceElement> refs2Unimplement = new HashSet<PsiJavaCodeReferenceElement>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
for (PsiClass psiClass : DirectClassInheritorsSearch.search(targetClass)) {
PsiFile containingFile = psiClass.getContainingFile();
if (!refs.containsKey(containingFile)) {
refs.put(containingFile, new HashMap<PsiField, Set<PsiReference>>());
}
if (collectExtendsImplements(targetClass, psiClass.getExtendsList(), refs2Unimplement)) continue;
collectExtendsImplements(targetClass, psiClass.getImplementsList(), refs2Unimplement);
}
}
}, "Find references in implement/extends lists...", true, project)) {
return;
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
for (PsiFile psiFile : refs.keySet()) {
final Map<PsiField, Set<PsiReference>> map = refs.get(psiFile);
for (PsiField psiField : map.keySet()) {
final PsiClass containingClass = psiField.getContainingClass();
final String fieldName = psiField.getName();
for (PsiReference reference : map.get(psiField)) {
((PsiReferenceExpressionImpl)reference)
.bindToElementViaStaticImport(containingClass, fieldName, ((PsiJavaFile)psiFile).getImportList());
}
}
}
for (PsiJavaCodeReferenceElement referenceElement : refs2Unimplement) {
referenceElement.delete();
}
for (PsiFile psiFile : refs.keySet()) {
JavaCodeStyleManager.getInstance(project).optimizeImports(psiFile);
}
}
});
}
}
private static boolean collectExtendsImplements(final PsiClass targetClass,
final PsiReferenceList referenceList,
final Set<PsiJavaCodeReferenceElement> refs) {
if (referenceList != null) {
for (PsiJavaCodeReferenceElement referenceElement : referenceList.getReferenceElements()) {
if (referenceElement.resolve() == targetClass) {
refs.add(referenceElement);
return true;
}
}
}
element.delete();
new OptimizeImportsProcessor(project, file).run();
return false;
}
public boolean startInWriteAction() {
return true;
return false;
}
}

View File

@@ -1,7 +1,7 @@
// "Replace Implements with Static Import" "true"
import static I.BAZZ;
import static I.FOO;
import static I1.BAZZ;
public class X {
void bar() {

View File

@@ -0,0 +1,18 @@
// "Replace Implements with Static Import" "true"
import static I1.BAZZ;
public class X implements I {
void bar() {
System.out.println(FOO);
System.out.println(BAZZ);
}
}
interface I {
String FOO = "foo";
}
interface I1 {
String BAZZ = "bazz";
}

View File

@@ -0,0 +1,19 @@
// "Replace Implements with Static Import" "true"
import static I1.BAZZ;
import static II.FOO;
public class X {
void bar() {
System.out.println(FOO);
System.out.println(BAZZ);
}
}
interface II extends I1{
String FOO = "foo";
}
interface I1 {
String BAZZ = "bazz";
}

View File

@@ -0,0 +1,15 @@
// "Replace Implements with Static Import" "true"
public class X implements I {
void bar() {
System.out.println(FOO);
System.out.println(BAZZ);
}
}
interface I extends I1{
String FOO = "foo";
}
interface I<caret>1 {
String BAZZ = "bazz";
}

View File

@@ -0,0 +1,15 @@
// "Replace Implements with Static Import" "true"
public class X implements II {
void bar() {
System.out.println(FOO);
System.out.println(BAZZ);
}
}
interface I<caret>I extends I1{
String FOO = "foo";
}
interface I1 {
String BAZZ = "bazz";
}