diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 07afec137ebe..72fe6ba7109c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -489,42 +489,22 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { @Nullable private HighlightInfo processMethod(final PsiMethod method, ProgressIndicator progress) { - if (myRefCountHolder.isReferenced(method)) return null; boolean isPrivate = method.hasModifierProperty(PsiModifier.PRIVATE); PsiClass containingClass = method.getContainingClass(); - HighlightInfoType highlightInfoType = HighlightInfoType.UNUSED_SYMBOL; - HighlightDisplayKey highlightDisplayKey = myUnusedSymbolKey; - - if (HighlightMethodUtil.isSerializationRelatedMethod(method, containingClass)) return null; + if (isMethodReferenced(method, progress, isPrivate, containingClass)) return null; + HighlightInfoType highlightInfoType; + HighlightDisplayKey highlightDisplayKey; + String key; if (isPrivate) { - if (isIntentionalPrivateConstructor(method, containingClass)) { - return null; - } - if (isImplicitUsage(method, progress)) { - return null; - } + highlightInfoType = HighlightInfoType.UNUSED_SYMBOL; + highlightDisplayKey = myUnusedSymbolKey; + key = method.isConstructor() ? "private.constructor.is.not.used" : "private.method.is.not.used"; } else { - //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too - if (containingClass != null && method.isConstructor() - && containingClass.getConstructors().length == 1 - && isClassUnused(containingClass, progress) == USED) { - return null; - } - if (isImplicitUsage(method, progress)) return null; - - if (method.findSuperMethods().length != 0) { - return null; - } - if (!weAreSureThereAreNoUsages(method, progress)) { - return null; - } highlightInfoType = myDeadCodeInfoType; highlightDisplayKey = myDeadCodeKey; + key = method.isConstructor() ? "constructor.is.not.used" : "method.is.not.used"; } - String key = isPrivate - ? method.isConstructor() ? "private.constructor.is.not.used" : "private.method.is.not.used" - : method.isConstructor() ? "constructor.is.not.used" : "method.is.not.used"; String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY); String message = JavaErrorMessages.message(key, symbolName); PsiIdentifier identifier = method.getNameIdentifier(); @@ -537,13 +517,44 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { return true; } }); - if (method.getReturnType() != null || (containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName()))) { + if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) { //ignore methods with deleted return types as they are always marked as unused without any reason ChangeSignatureGestureDetector.getInstance(myProject).dismissForElement(method); } return highlightInfo; } + private boolean isMethodReferenced(PsiMethod method, ProgressIndicator progress, boolean aPrivate, PsiClass containingClass) { + if (myRefCountHolder.isReferenced(method)) return true; + + if (HighlightMethodUtil.isSerializationRelatedMethod(method, containingClass)) return true; + if (aPrivate) { + if (isIntentionalPrivateConstructor(method, containingClass)) { + return true; + } + if (isImplicitUsage(method, progress)) { + return true; + } + } + else { + //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too + if (containingClass != null && method.isConstructor() + && containingClass.getConstructors().length == 1 + && isClassUnused(containingClass, progress) == USED) { + return true; + } + if (isImplicitUsage(method, progress)) return true; + + if (method.findSuperMethods().length != 0) { + return true; + } + if (!weAreSureThereAreNoUsages(method, progress)) { + return true; + } + } + return false; + } + private boolean weAreSureThereAreNoUsages(PsiMember member, ProgressIndicator progress) { if (myInLibrary) return false; if (!myDeadCodeEnabled) return false; @@ -565,7 +576,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) { if (member instanceof PsiEnumConstant) { - return checkEnumValuesUsages(member, progress); + return !isEnumValuesMethodUsed(member, progress); } if (!canBeReferencedViaWeirdNames(member)) return true; } @@ -589,20 +600,18 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { boolean used = findUsagesManager.isUsed(member, findUsagesOptions); if (!used && member instanceof PsiEnumConstant) { - return checkEnumValuesUsages(member, progress); + return !isEnumValuesMethodUsed(member, progress); } return !used; } - private boolean checkEnumValuesUsages(PsiMember member, ProgressIndicator progress) { + private boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress) { final PsiClassImpl containingClass = (PsiClassImpl)member.getContainingClass(); - if (containingClass != null) { - final PsiMethod valuesMethod = containingClass.getValuesMethod(); - if (valuesMethod != null && weAreSureThereAreNoUsages(valuesMethod, progress)) { - return true; - } - } - return false; + if (containingClass == null) return true; + final PsiMethod valuesMethod = containingClass.getValuesMethod(); + if (valuesMethod == null) return true; + boolean isPrivate = valuesMethod.hasModifierProperty(PsiModifier.PRIVATE); + return isMethodReferenced(valuesMethod, progress, isPrivate, containingClass); } private static boolean canBeReferencedViaWeirdNames(PsiMember member) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java index 8e997d680670..142976847925 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java @@ -41,7 +41,7 @@ public class LightMethod extends LightElement implements PsiMethod { private final PsiMethod myMethod; private final PsiClass myContainingClass; - public LightMethod(PsiManager manager, PsiMethod method, PsiClass containingClass) { + public LightMethod(@NotNull PsiManager manager, @NotNull PsiMethod method, @NotNull PsiClass containingClass) { super(manager, JavaLanguage.INSTANCE); myMethod = method; myContainingClass = containingClass; @@ -214,6 +214,11 @@ public class LightMethod extends LightElement implements PsiMethod { return myContainingClass; } + @Override + public PsiFile getContainingFile() { + return myContainingClass.getContainingFile(); + } + public String toString() { return "PsiMethod:" + getName(); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index f226b867ff89..f5bcc1302cce 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -46,6 +46,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; import com.intellij.util.concurrency.JBReentrantReadWriteLock; import com.intellij.util.concurrency.LockFactory; import gnu.trove.THashMap; @@ -384,51 +385,48 @@ public class RefManagerImpl extends RefManager { @Nullable public RefElement getReference(final PsiElement elem, final boolean ignoreScope) { - if (elem != null && (elem instanceof PsiDirectory || belongsToScope(elem, ignoreScope))) { - if (!elem.isValid()) return null; - - RefElement ref = getFromRefTable(elem); - if (ref == null) { - if (!isValidPointForReference()) { - //LOG.assertTrue(true, "References may become invalid after process is finished"); - return null; - } - - final RefElementImpl refElement = ApplicationManager.getApplication().runReadAction(new Computable() { - @Nullable - public RefElementImpl compute() { - final RefManagerExtension extension = getExtension(elem.getLanguage()); - if (extension != null) { - final RefElement refElement = extension.createRefElement(elem); - if (refElement != null) return (RefElementImpl)refElement; - } - if (elem instanceof PsiFile) { - return new RefFileImpl((PsiFile)elem, RefManagerImpl.this); - } - else if (elem instanceof PsiDirectory) { - return new RefDirectoryImpl((PsiDirectory)elem, RefManagerImpl.this); - } - else { - return null; - } - } - }); - if (refElement == null) return null; - - putToRefTable(elem, refElement); - - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - refElement.initialize(); - } - }); - - return refElement; - } - return ref; + if (elem == null || !elem.isValid() || + elem instanceof LightElement || !(elem instanceof PsiDirectory) && !belongsToScope(elem, ignoreScope)) { + return null; } - return null; + RefElement ref = getFromRefTable(elem); + if (ref != null) return ref; + if (!isValidPointForReference()) { + //LOG.assertTrue(true, "References may become invalid after process is finished"); + return null; + } + + final RefElementImpl refElement = ApplicationManager.getApplication().runReadAction(new Computable() { + @Nullable + public RefElementImpl compute() { + final RefManagerExtension extension = getExtension(elem.getLanguage()); + if (extension != null) { + final RefElement refElement = extension.createRefElement(elem); + if (refElement != null) return (RefElementImpl)refElement; + } + if (elem instanceof PsiFile) { + return new RefFileImpl((PsiFile)elem, RefManagerImpl.this); + } + else if (elem instanceof PsiDirectory) { + return new RefDirectoryImpl((PsiDirectory)elem, RefManagerImpl.this); + } + else { + return null; + } + } + }); + if (refElement == null) return null; + + putToRefTable(elem, refElement); + + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + refElement.initialize(); + } + }); + + return refElement; } private RefManagerExtension getExtension(final Language language) { diff --git a/platform/lang-impl/src/com/intellij/psi/search/ProjectScopeBuilderImpl.java b/platform/lang-impl/src/com/intellij/psi/search/ProjectScopeBuilderImpl.java index 5369e9b9444c..9099f33fafa2 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/ProjectScopeBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/search/ProjectScopeBuilderImpl.java @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; * @author yole */ public class ProjectScopeBuilderImpl extends ProjectScopeBuilder { - private Project myProject; + protected final Project myProject; public ProjectScopeBuilderImpl(Project project) { myProject = project;