ensure method signature is highlighted when changes are made inside method body but the actual highlighting is performed on class level (IDEA-141532; IDEA-158137)

This commit is contained in:
Anna.Kozlova
2016-07-13 11:43:16 +02:00
parent 8e7077bb5b
commit f27c5080f6
3 changed files with 29 additions and 3 deletions
@@ -48,6 +48,7 @@ import com.intellij.psi.util.*;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.MostlySingularMultiMap;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -88,6 +89,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
};
private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<>();
private final Set<PsiClass> myOverrideEquivalentMethodsVisitedClasses = new THashSet<>();
private LanguageLevel myLanguageLevel;
private JavaSdkVersion myJavaSdkVersion;
@@ -194,6 +196,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myFile = null;
myHolder = null;
myDuplicateMethods.clear();
myOverrideEquivalentMethodsVisitedClasses.clear();
}
return success;
@@ -896,6 +899,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method,myFile));
if (!myHolder.hasErrorResults() && aClass != null &&
myOverrideEquivalentMethodsVisitedClasses.add(aClass)) {
myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
}
}
else if (parent instanceof PsiClass) {
PsiClass aClass = (PsiClass)parent;
@@ -909,7 +916,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper));
}
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass, myFile, myLanguageLevel));
if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
if (!myHolder.hasErrorResults() && myOverrideEquivalentMethodsVisitedClasses.add(aClass)) {
myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
}
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass));
}
catch (IndexNotReadyException ignored) {
@@ -1067,7 +1076,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference()) &&
myOverrideEquivalentMethodsVisitedClasses.add((PsiClass)parent)) {
PsiClass aClass = (PsiClass)parent;
myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
}
@@ -8,6 +8,6 @@ interface A
<error descr="Class 'B' must either be declared abstract or implement abstract method 'foo(S)' in 'A'">class B implements A</error>
{
public void foo(Collection<?> x) { }
<error descr="'foo(Collection<?>)' in 'B' clashes with 'foo(S)' in 'A'; both methods have same erasure, yet neither overrides the other">public void foo(Collection<?> x)</error> { }
public <S extends List<?> & Collection<?>> void foo(S x) { }
}
@@ -846,6 +846,22 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
assertEmpty(highlightErrors());
}
public void testOverrideMethodsHighlightingPersistWhenTypeInsideMethodBody() throws Throwable {
configureByText(JavaFileType.INSTANCE, "package x; \n" +
"class ClassA {\n" +
" static <T> void sayHello(Class<? extends T> msg) {}\n" +
"}\n" +
"class ClassB extends ClassA {\n" +
" static <T extends String> void sayHello(Class<? extends T> msg) {<caret>\n" +
" }\n" +
"}\n");
assertSize(1, highlightErrors());
type("//my comment inside method body, so class modifier won't be visited");
assertSize(1, highlightErrors());
}
public void testLineMarkersClearWhenTypingAtTheEndOfPsiComment() throws Throwable {
configureByText(JavaFileType.INSTANCE, "class S {\n//ddd<caret>\n}");
StringBuffer log = new StringBuffer();