summaryrefslogtreecommitdiff
path: root/java/java-impl/src/com/intellij/codeInsight/daemon
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-07-08 11:26:24 -0700
committerTor Norbye <tnorbye@google.com>2013-07-08 11:26:24 -0700
commitc1ace1f7e1e49c81bb4b75377c99f07be340abfe (patch)
tree9d0db96bd3d86ddfec80e7e3554cad9dcc066553 /java/java-impl/src/com/intellij/codeInsight/daemon
parentc6218e46d5d2017e987ecdbd99b318a95c42abc0 (diff)
downloadidea-c1ace1f7e1e49c81bb4b75377c99f07be340abfe.tar.gz
Snapshot aea001abfc1b38fec3a821bcd5174cc77dc75787 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: Icdea2a2bd7ad43b4d05967b1f0479db3bda1c93c
Diffstat (limited to 'java/java-impl/src/com/intellij/codeInsight/daemon')
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java7
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java87
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java38
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java43
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java19
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java37
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java5
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java19
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java1
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java1
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java3
16 files changed, 154 insertions, 118 deletions
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java
index e79fdbe14ed9..5caad6166995 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaAwareInspectionProfileCoverter.java
@@ -20,9 +20,8 @@
*/
package com.intellij.codeInsight.daemon;
-import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.ModifiableModel;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import org.jdom.Element;
@@ -53,8 +52,8 @@ public class JavaAwareInspectionProfileCoverter extends InspectionProfileConvert
super.fillErrorLevels(profile);
//javadoc attributes
- final InspectionProfileEntry inspectionTool = profile.getInspectionTool(JavaDocLocalInspection.SHORT_NAME, null);
- JavaDocLocalInspection inspection = (JavaDocLocalInspection)((LocalInspectionToolWrapper)inspectionTool).getTool();
+ final InspectionToolWrapper toolWrapper = profile.getInspectionTool(JavaDocLocalInspection.SHORT_NAME, null);
+ JavaDocLocalInspection inspection = (JavaDocLocalInspection)toolWrapper.getTool();
inspection.myAdditionalJavadocTags = myAdditionalJavadocTags;
}
} \ No newline at end of file
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 a36521fbe936..43a7037397ff 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
@@ -139,7 +139,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
VirtualFile virtualFile = viewProvider.getVirtualFile();
myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);
- myRefCountHolder = RefCountHolder.endUsing(myFile);
+ myRefCountHolder = RefCountHolder.endUsing(myFile, progress);
if (myRefCountHolder == null || !myRefCountHolder.retrieveUnusedReferencesInfo(progress, new Runnable() {
@Override
public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java
index 0fd26857ab86..892eec196986 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RecursiveCallLineMarkerProvider.java
@@ -63,7 +63,7 @@ public class RecursiveCallLineMarkerProvider implements LineMarkerProvider {
public static boolean isRecursiveMethodCall(@NotNull PsiMethodCallExpression methodCall) {
final PsiMethod method = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class);
- if (method == null) {
+ if (method == null || !method.getName().equals(methodCall.getMethodExpression().getReferenceName())) {
return false;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
index 6fd6ba54a888..175c1332db46 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
@@ -18,7 +18,6 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.*;
@@ -34,11 +33,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.SoftReference;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
public class RefCountHolder {
@@ -55,34 +50,35 @@ public class RefCountHolder {
private volatile ProgressIndicator analyzedUnder;
private static class HolderReference extends SoftReference<RefCountHolder> {
- @SuppressWarnings("UnusedDeclaration")
- private volatile RefCountHolder myHardRef; // to prevent gc
- // number of live references to RefCountHolder. Once it reaches zero, hard ref is cleared
- // the counter is used instead of a flag because multiple passes can be running simultaneously (one actual and several canceled winding down)
- // and there is a chance they overlap the usage of RCH
- private final AtomicInteger myRefCount = new AtomicInteger();
+ // Map holding hard references to RefCountHolder for each highlighting pass (identified by its progress indicator)
+ // there can be multiple passes running simultaneously (one actual and several passes just canceled and winding down but still alive)
+ // so there is a chance they overlap the usage of RCH
+ // As soon as everybody finished using RCH, map become empty and the RefCountHolder is eligible for gc
+ private final Map<ProgressIndicator, RefCountHolder> map = new ConcurrentHashMap<ProgressIndicator, RefCountHolder>();
public HolderReference(@NotNull RefCountHolder holder) {
super(holder);
- myHardRef = holder;
}
- private void changeLivenessBy(int delta) {
- if (myRefCount.addAndGet(delta) == 0) {
- myHardRef = null;
- }
- else if (myHardRef == null) {
- myHardRef = get();
- }
+ private void acquire(@NotNull ProgressIndicator indicator) {
+ RefCountHolder holder = get();
+ assert holder != null: "no way";
+ map.put(indicator, holder);
+ holder = get();
+ assert holder != null: "can't be!";
+ }
+
+ private RefCountHolder release(@NotNull ProgressIndicator indicator) {
+ return map.remove(indicator);
}
}
private static final Key<HolderReference> REF_COUNT_HOLDER_IN_FILE_KEY = Key.create("REF_COUNT_HOLDER_IN_FILE_KEY");
- @NotNull
- private static Pair<RefCountHolder, HolderReference> getInstance(@NotNull PsiFile file, boolean create) {
+
+ private static RefCountHolder getInstance(@NotNull PsiFile file, @NotNull ProgressIndicator indicator, boolean acquire) {
HolderReference ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
RefCountHolder holder = ref == null ? null : ref.get();
- if (holder == null && create) {
+ if (holder == null && acquire) {
holder = new RefCountHolder(file);
HolderReference newRef = new HolderReference(holder);
while (true) {
@@ -99,31 +95,30 @@ public class RefCountHolder {
}
}
}
- return Pair.create(holder, ref);
+ if (ref != null) {
+ if (acquire) {
+ ref.acquire(indicator);
+ }
+ else {
+ ref.release(indicator);
+ }
+ }
+ return holder;
}
@NotNull
- public static RefCountHolder startUsing(@NotNull PsiFile file) {
- Pair<RefCountHolder, HolderReference> pair = getInstance(file, true);
- HolderReference reference = pair.second;
- reference.changeLivenessBy(1); // make sure RefCountHolder won't be gced during highlighting
- log("startUsing: " + pair.first.myState+" for "+file);
- return pair.first;
+ public static RefCountHolder startUsing(@NotNull PsiFile file, @NotNull ProgressIndicator indicator) {
+ return getInstance(file, indicator, true);
}
@Nullable("might be gced")
- public static RefCountHolder endUsing(@NotNull PsiFile file) {
- Pair<RefCountHolder, HolderReference> pair = getInstance(file, false);
- HolderReference reference = pair.second;
- reference.changeLivenessBy(-1); // no longer needed, can be cleared
- RefCountHolder holder = pair.first;
- log("endUsing: " + (holder == null ? null : holder.myState)+" for "+file);
- return holder;
+ public static RefCountHolder endUsing(@NotNull PsiFile file, @NotNull ProgressIndicator indicator) {
+ return getInstance(file, indicator, false);
}
private RefCountHolder(@NotNull PsiFile file) {
myFile = file;
- log("c: created: " + myState.get()+" for "+file);
+ log("c: created: ", myState.get(), " for ", file);
}
private void clear() {
@@ -284,10 +279,10 @@ public class RefCountHolder {
ProgressIndicator old = myState.get();
if (old != VIRGIN && old != READY) return false;
if (!myState.compareAndSet(old, indicator)) {
- log("a: failed to change " + old + "->" + indicator);
+ log("a: failed to change ", old, "->", indicator);
return false;
}
- log("a: changed " + old + "->" + indicator);
+ log("a: changed ", old, "->", indicator);
analyzedUnder = null;
boolean completed = false;
try {
@@ -308,22 +303,22 @@ public class RefCountHolder {
ProgressIndicator resultState = completed ? READY : VIRGIN;
boolean set = myState.compareAndSet(indicator, resultState);
assert set : myState.get();
- log("a: changed after analyze" + indicator + "->" + resultState);
+ log("a: changed after analyze", indicator, "->", resultState);
}
return true;
}
- private static void log(@NonNls String s) {
- //System.err.println("RFC: "+s);
+ private static void log(@NonNls Object... s) {
+ //System.err.println("RFC: "+ Arrays.asList(s));
}
public boolean retrieveUnusedReferencesInfo(@NotNull ProgressIndicator indicator, @NotNull Runnable analyze) {
ProgressIndicator old = myState.get();
if (!myState.compareAndSet(READY, indicator)) {
- log("r: failed to change " + old + "->" + indicator);
+ log("r: failed to change ", old, "->", indicator);
return false;
}
- log("r: changed " + old + "->" + indicator);
+ log("r: changed ", old, "->", indicator);
try {
if (analyzedUnder != indicator) {
return false;
@@ -333,7 +328,7 @@ public class RefCountHolder {
finally {
boolean set = myState.compareAndSet(indicator, READY);
assert set : myState.get();
- log("r: changed back " + indicator + "->" + READY);
+ log("r: changed back ", indicator, "->", READY);
}
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 1d74a2f3dcf4..48e10ee31035 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -40,6 +40,7 @@ import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -384,8 +385,10 @@ public class GenericsHighlightUtil {
}
@Nullable
- public static HighlightInfo checkElementInTypeParameterExtendsList(PsiReferenceList referenceList, JavaResolveResult resolveResult, PsiElement element) {
- PsiClass aClass = (PsiClass)referenceList.getParent();
+ public static HighlightInfo checkElementInTypeParameterExtendsList(@NotNull PsiReferenceList referenceList,
+ @NotNull PsiClass aClass,
+ @NotNull JavaResolveResult resolveResult,
+ @NotNull PsiElement element) {
final PsiJavaCodeReferenceElement[] referenceElements = referenceList.getReferenceElements();
PsiClass extendFrom = (PsiClass)resolveResult.getElement();
if (extendFrom == null) return null;
@@ -462,7 +465,7 @@ public class GenericsHighlightUtil {
return null;
}
- public static HighlightInfo checkOverrideEquivalentMethods(final PsiClass aClass) {
+ public static HighlightInfo checkOverrideEquivalentMethods(@NotNull PsiClass aClass) {
final Collection<HierarchicalMethodSignature> signaturesWithSupers = aClass.getVisibleSignatures();
PsiManager manager = aClass.getManager();
Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods =
@@ -520,10 +523,10 @@ public class GenericsHighlightUtil {
}
@Nullable
- private static HighlightInfo checkSameErasureNotSubSignatureInner(final HierarchicalMethodSignature signature,
- final PsiManager manager,
- final PsiClass aClass,
- final Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods) {
+ private static HighlightInfo checkSameErasureNotSubSignatureInner(@NotNull HierarchicalMethodSignature signature,
+ @NotNull PsiManager manager,
+ @NotNull PsiClass aClass,
+ @NotNull Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods) {
PsiMethod method = signature.getMethod();
JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
if (!facade.getResolveHelper().isAccessible(method, aClass, null)) return null;
@@ -549,10 +552,11 @@ public class GenericsHighlightUtil {
if (superSignature.isRaw() && !signature.isRaw()) {
final PsiType[] parameterTypes = signature.getParameterTypes();
- PsiType[] types = superSignature.getParameterTypes();
- for (int i = 0; i < types.length; i++) {
- if (!Comparing.equal(parameterTypes[i], TypeConversionUtil.erasure(types[i]))) {
- return getSameErasureMessage(false, method, superSignature.getMethod(), HighlightNamesUtil.getClassDeclarationTextRange(aClass));
+ PsiType[] erasedTypes = superSignature.getErasedParameterTypes();
+ for (int i = 0; i < erasedTypes.length; i++) {
+ if (!Comparing.equal(parameterTypes[i], erasedTypes[i])) {
+ return getSameErasureMessage(false, method, superSignature.getMethod(),
+ HighlightNamesUtil.getClassDeclarationTextRange(aClass));
}
}
}
@@ -601,10 +605,10 @@ public class GenericsHighlightUtil {
!(checkEqualsSuper && Arrays.equals(superSignature.getParameterTypes(), signatureToCheck.getParameterTypes())) &&
!atLeast17) {
int idx = 0;
- final PsiType[] parameterTypes = signatureToCheck.getParameterTypes();
- boolean erasure = parameterTypes.length > 0;
+ final PsiType[] erasedTypes = signatureToCheck.getErasedParameterTypes();
+ boolean erasure = erasedTypes.length > 0;
for (PsiType type : superSignature.getParameterTypes()) {
- erasure &= Comparing.equal(type, TypeConversionUtil.erasure(parameterTypes[idx]));
+ erasure &= Comparing.equal(type, erasedTypes[idx]);
idx++;
}
@@ -624,9 +628,9 @@ public class GenericsHighlightUtil {
}
}
- private static HighlightInfo getSameErasureMessage(final boolean sameClass, final PsiMethod method, final PsiMethod superMethod,
+ private static HighlightInfo getSameErasureMessage(final boolean sameClass, @NotNull PsiMethod method, @NotNull PsiMethod superMethod,
TextRange textRange) {
- @NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
+ @NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
method.hasModifierProperty(PsiModifier.STATIC) ?
"generics.methods.have.same.erasure.hide" :
"generics.methods.have.same.erasure.override";
@@ -1275,7 +1279,7 @@ public class GenericsHighlightUtil {
if (resolve instanceof PsiClass) {
final PsiClass containingClass = ((PsiClass)resolve).getContainingClass();
if (containingClass != null) {
- if (psiClass.isInheritor(containingClass, true) ||
+ if (psiClass.isInheritor(containingClass, true) ||
unqualifiedNestedClassReferenceAccessedViaContainingClassInheritance(containingClass, ((PsiClass)resolve).getExtendsList()) ||
unqualifiedNestedClassReferenceAccessedViaContainingClassInheritance(containingClass, ((PsiClass)resolve).getImplementsList())) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(((PsiClass)resolve).getName() + " is not accessible in current context").range(ref).create();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index 4f6f0996ad29..ae32b61b8e45 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
@@ -55,10 +55,7 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
+import java.util.*;
public class HighlightClassUtil {
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
@@ -94,19 +91,32 @@ public class HighlightClassUtil {
static HighlightInfo checkClassWithAbstractMethods(PsiClass aClass, PsiElement implementsFixElement, TextRange range) {
PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(aClass);
- if (abstractMethod == null || abstractMethod.getContainingClass() == null) {
+ if (abstractMethod == null) {
return null;
}
+
+ final PsiClass superClass = abstractMethod.getContainingClass();
+ if (superClass == null) {
+ return null;
+ }
+
String baseClassName = HighlightUtil.formatClass(aClass, false);
String methodName = JavaHighlightUtil.formatMethod(abstractMethod);
String message = JavaErrorMessages.message(aClass instanceof PsiEnumConstantInitializer || implementsFixElement instanceof PsiEnumConstant ? "enum.constant.should.implement.method" : "class.must.be.abstract",
baseClassName,
methodName,
- HighlightUtil.formatClass(abstractMethod.getContainingClass(), false));
+ HighlightUtil.formatClass(superClass, false));
HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create();
- if (ClassUtil.getAnyMethodToImplement(aClass) != null) {
- QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(implementsFixElement));
+ final PsiMethod anyMethodToImplement = ClassUtil.getAnyMethodToImplement(aClass);
+ if (anyMethodToImplement != null) {
+ if (!anyMethodToImplement.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) ||
+ JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, superClass)) {
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(implementsFixElement));
+ } else {
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(anyMethodToImplement, PsiModifier.PROTECTED, true, true));
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(anyMethodToImplement, PsiModifier.PUBLIC, true, true));
+ }
}
if (!(aClass instanceof PsiAnonymousClass)
&& HighlightUtil.getIncompatibleModifier(PsiModifier.ABSTRACT, aClass.getModifierList()) == null) {
@@ -985,7 +995,7 @@ public class HighlightClassUtil {
if (classReference == null) return;
final PsiClass psiClass = (PsiClass)classReference.resolve();
if (psiClass == null) return;
- final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, psiClass);
+ final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, psiClass, false);
if (chooser == null) return;
final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
@@ -999,12 +1009,17 @@ public class HighlightClassUtil {
newExpression = (PsiNewExpression)startElement.replace(newExpression);
final PsiClass psiClass = newExpression.getAnonymousClass();
if (psiClass == null) return;
- PsiClassType baseClassType = ((PsiAnonymousClass)psiClass).getBaseClassType();
- PsiClass resolve = baseClassType.resolve();
- if (resolve == null) return;
- PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(resolve, psiClass, PsiSubstitutor.EMPTY);
+ Map<PsiClass, PsiSubstitutor> subst = new HashMap<PsiClass, PsiSubstitutor>();
for (PsiMethodMember selectedElement : selectedElements) {
- selectedElement.setSubstitutor(superClassSubstitutor);
+ final PsiClass baseClass = selectedElement.getElement().getContainingClass();
+ if (baseClass != null) {
+ PsiSubstitutor substitutor = subst.get(baseClass);
+ if (substitutor == null) {
+ substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, psiClass, PsiSubstitutor.EMPTY);
+ subst.put(baseClass, substitutor);
+ }
+ selectedElement.setSubstitutor(substitutor);
+ }
}
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, psiClass, selectedElements, chooser.isCopyJavadoc(),
chooser.isInsertOverrideAnnotation());
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index 80f4b1715a1c..2d1a4db5ff7d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -35,6 +35,7 @@ import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.ui.ColorUtil;
+import com.intellij.util.containers.MostlySingularMultiMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.intellij.lang.annotations.Language;
@@ -833,18 +834,15 @@ public class HighlightMethodUtil {
}
@Nullable
- static HighlightInfo checkDuplicateMethod(PsiClass aClass, PsiMethod method) {
+ static HighlightInfo checkDuplicateMethod(PsiClass aClass,
+ @NotNull PsiMethod method,
+ @NotNull MostlySingularMultiMap<MethodSignature, PsiMethod> duplicateMethods) {
if (aClass == null || method instanceof ExternallyDefinedPsiElement) return null;
MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY);
- int methodCount = 0;
- final PsiMethod[] methodsByName = aClass.findMethodsByName(method.getName(), false);
- for (PsiMethod other : methodsByName) {
- if (other instanceof ExternallyDefinedPsiElement) continue;
- if (other == method ||
- other.isConstructor() == method.isConstructor() && other.getSignature(PsiSubstitutor.EMPTY).equals(methodSignature)) {
- methodCount++;
- if (methodCount > 1) break;
- }
+ int methodCount = 1;
+ List<PsiMethod> methods = (List<PsiMethod>)duplicateMethods.get(methodSignature);
+ if (methods.size() > 1) {
+ methodCount++;
}
if (methodCount == 1 && aClass.isEnum() &&
@@ -874,6 +872,7 @@ public class HighlightMethodUtil {
if (hasNoBody) {
if (isExtension) {
description = JavaErrorMessages.message("extension.method.should.have.a.body");
+ additionalFixes.add(new AddMethodBodyFix(method));
}
else if (isInterface && isStatic) {
description = "Static methods in interfaces should have a body";
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 94508dfe2352..e7b3d6b4bbc9 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -2516,7 +2516,7 @@ public class HighlightUtil extends HighlightUtilBase {
PsiClass aClass = (PsiClass)resolved;
if (refGrandParent instanceof PsiClass) {
if (refGrandParent instanceof PsiTypeParameter) {
- highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, resolveResult, ref);
+ highlightInfo = GenericsHighlightUtil.checkElementInTypeParameterExtendsList(referenceList, (PsiClass)refGrandParent, resolveResult, ref);
}
else {
highlightInfo = HighlightClassUtil.checkExtendsClassAndImplementsInterface(referenceList, resolveResult, ref);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index 1c0e2ecf342b..c705951fe395 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -39,11 +39,9 @@ import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTagValue;
-import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.util.*;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.containers.MostlySingularMultiMap;
import gnu.trove.THashMap;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
@@ -82,11 +80,27 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
};
+ private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>>();
public HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
myResolveHelper = resolveHelper;
}
+ @NotNull
+ private MostlySingularMultiMap<MethodSignature, PsiMethod> getDuplicateMethods(PsiClass aClass) {
+ MostlySingularMultiMap<MethodSignature, PsiMethod> signatures = myDuplicateMethods.get(aClass);
+ if (signatures == null) {
+ signatures = new MostlySingularMultiMap<MethodSignature, PsiMethod>();
+ for (PsiMethod method : aClass.getMethods()) {
+ MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
+ signatures.add(signature, method);
+ }
+
+ myDuplicateMethods.put(aClass, signatures);
+ }
+ return signatures;
+ }
+
@Override
@NotNull
public HighlightVisitorImpl clone() {
@@ -130,12 +144,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
Project project = file.getProject();
DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
- RefCountHolder refCountHolder = RefCountHolder.startUsing(file);
+ ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ if (indicator == null) throw new IllegalStateException("Must be run under progress");
+ RefCountHolder refCountHolder = RefCountHolder.startUsing(file, indicator);
myRefCountHolder = refCountHolder;
Document document = PsiDocumentManager.getInstance(project).getDocument(file);
TextRange dirtyScope = document == null ? file.getTextRange() : fileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL);
- ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
- success = indicator != null && refCountHolder.analyze(file, dirtyScope, action, indicator);
+ success = refCountHolder.analyze(file, dirtyScope, action, indicator);
}
else {
myRefCountHolder = null;
@@ -152,6 +167,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myRefCountHolder = null;
myFile = null;
myHolder = null;
+ myDuplicateMethods.clear();
}
return success;
@@ -775,7 +791,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
PsiClass aClass = method.getContainingClass();
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method));
}
@@ -932,7 +948,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkCannotPassInner(ref));
if (resolved != null && parent instanceof PsiReferenceList) {
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkElementInReferenceList(ref, (PsiReferenceList)parent, result));
+ if (!myHolder.hasErrorResults()) {
+ PsiReferenceList referenceList = (PsiReferenceList)parent;
+ myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result));
+ }
}
if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java
index 4457e5d47c40..0057749d056b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsConditionalFix.java
@@ -102,8 +102,8 @@ public class AddTypeArgumentsConditionalFix implements IntentionAction {
return true;
}
- public static void register(HighlightInfo highlightInfo, PsiExpression expression, PsiType lType) {
- if (expression instanceof PsiConditionalExpression) {
+ public static void register(HighlightInfo highlightInfo, PsiExpression expression, @NotNull PsiType lType) {
+ if (lType != PsiType.NULL && expression instanceof PsiConditionalExpression) {
final PsiExpression thenExpression = ((PsiConditionalExpression)expression).getThenExpression();
final PsiExpression elseExpression = ((PsiConditionalExpression)expression).getElseExpression();
if (thenExpression != null && elseExpression != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
index ad63c638f5d0..667143b2da35 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
@@ -134,7 +134,7 @@ public class CreateFromUsageUtils {
JVMElementFactory factory = JVMElementFactories.getFactory(aClass.getLanguage(), aClass.getProject());
- LOG.assertTrue(!aClass.isInterface(), "Interface bodies should be already set up");
+ LOG.assertTrue(!aClass.isInterface() || method.hasModifierProperty(PsiModifier.DEFAULT), "Interface bodies should be already set up");
FileType fileType = FileTypeManager.getInstance().getFileTypeByExtension(template.getExtension());
Properties properties = new Properties();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
index 24ba71dc024c..919c6b447259 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
@@ -54,8 +54,11 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix {
if (!super.isAvailableImpl(offset)) return false;
if(myReferenceExpression.isQualified()) return false;
PsiElement scope = PsiTreeUtil.getParentOfType(myReferenceExpression, PsiModifierListOwner.class);
+ if (scope instanceof PsiAnonymousClass) {
+ scope = PsiTreeUtil.getParentOfType(scope, PsiModifierListOwner.class, true);
+ }
return scope instanceof PsiMethod || scope instanceof PsiClassInitializer ||
- scope instanceof PsiLocalVariable || scope instanceof PsiAnonymousClass;
+ scope instanceof PsiLocalVariable;
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
index f9c9b7b7373c..5e632738fa5c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
@@ -28,16 +28,13 @@ import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiEnumConstant;
-import com.intellij.psi.PsiFile;
+import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiElement {
public ImplementMethodsFix(PsiElement aClass) {
@@ -75,7 +72,7 @@ public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiEle
if (editor == null || !FileModificationService.getInstance().prepareFileForWrite(myPsiElement.getContainingFile())) return;
if (myPsiElement instanceof PsiEnumConstant) {
- final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, ((PsiEnumConstant)myPsiElement).getContainingClass());
+ final MemberChooser<PsiMethodMember> chooser = chooseMethodsToImplement(editor, startElement, ((PsiEnumConstant)myPsiElement).getContainingClass(), true);
if (chooser == null) return;
final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
@@ -103,10 +100,14 @@ public class ImplementMethodsFix extends LocalQuickFixAndIntentionActionOnPsiEle
@Nullable
- protected static MemberChooser<PsiMethodMember> chooseMethodsToImplement(Editor editor, PsiElement startElement, PsiClass aClass) {
+ protected static MemberChooser<PsiMethodMember> chooseMethodsToImplement(Editor editor,
+ PsiElement startElement,
+ PsiClass aClass,
+ boolean implemented) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT);
+ final Collection<CandidateInfo> overrideImplement = OverrideImplementExploreUtil.getMapToOverrideImplement(aClass, true, implemented).values();
return OverrideImplementUtil
- .showOverrideImplementChooser(editor, startElement, true, OverrideImplementExploreUtil.getMethodsToOverrideImplement(aClass, true), Collections.<CandidateInfo>emptyList());
+ .showOverrideImplementChooser(editor, startElement, true, overrideImplement, ContainerUtil.<CandidateInfo>newArrayList());
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
index a2bebf63ac18..2e23f7ef65e4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFix.java
@@ -107,6 +107,7 @@ public class ImportClassFix extends ImportClassFixBase<PsiJavaCodeReferenceEleme
return super.getRequiredMemberName(reference);
}
+ @NotNull
@Override
protected List<PsiClass> filterByContext(@NotNull List<PsiClass> candidates, @NotNull PsiJavaCodeReferenceElement ref) {
PsiElement typeElement = ref.getParent();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
index e34ad1820c89..bfb7c45bf3c8 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
@@ -184,6 +184,7 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
return null;
}
+ @NotNull
protected List<PsiClass> filterByContext(@NotNull List<PsiClass> candidates, @NotNull T ref) {
return candidates;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
index 6ac2e5d9e37e..0d710688eec1 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
@@ -141,6 +141,7 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement {
final PsiModifierList myModifierList = (PsiModifierList)startElement;
final PsiVariable variable = myVariable == null ? null : myVariable.getElement();
if (!FileModificationService.getInstance().preparePsiElementForWrite(myModifierList)) return;
+ if (variable != null && !FileModificationService.getInstance().preparePsiElementForWrite(variable)) return;
final List<PsiModifierList> modifierLists = new ArrayList<PsiModifierList>();
final PsiFile containingFile = myModifierList.getContainingFile();
final PsiModifierList modifierList;
@@ -180,8 +181,6 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement {
}));
}
- if (!FileModificationService.getInstance().prepareFileForWrite(containingFile)) return;
-
if (!modifierLists.isEmpty()) {
if (Messages.showYesNoDialog(project,
QuickFixBundle.message("change.inheritors.visibility.warning.text"),