highlighting for incompatible return types in type parameter inheritors (IDEA-57274)

This commit is contained in:
anna
2013-10-10 20:34:36 +02:00
parent e03245e5c4
commit 993fb34281
4 changed files with 34 additions and 15 deletions
@@ -456,6 +456,10 @@ public class GenericsHighlightUtil {
for (HierarchicalMethodSignature signature : signaturesWithSupers) {
HighlightInfo info = checkSameErasureNotSubSignatureInner(signature, manager, aClass, sameErasureMethods);
if (info != null) return info;
if (aClass instanceof PsiTypeParameter) {
info = HighlightMethodUtil.checkMethodIncompatibleReturnType(signature, signature.getSuperSignatures(), true, HighlightNamesUtil.getClassDeclarationTextRange(aClass));
if (info != null) return info;
}
}
final PsiIdentifier classIdentifier = aClass.getNameIdentifier();
@@ -121,8 +121,15 @@ public class HighlightMethodUtil {
static HighlightInfo checkMethodIncompatibleReturnType(MethodSignatureBackedByPsiMethod methodSignature,
List<HierarchicalMethodSignature> superMethodSignatures,
boolean includeRealPositionInfo) {
List<HierarchicalMethodSignature> superMethodSignatures,
boolean includeRealPositionInfo) {
return checkMethodIncompatibleReturnType(methodSignature, superMethodSignatures, includeRealPositionInfo, null);
}
static HighlightInfo checkMethodIncompatibleReturnType(MethodSignatureBackedByPsiMethod methodSignature,
List<HierarchicalMethodSignature> superMethodSignatures,
boolean includeRealPositionInfo,
TextRange textRange) {
PsiMethod method = methodSignature.getMethod();
PsiType returnType = methodSignature.getSubstitutor().substitute(method.getReturnType());
PsiClass aClass = method.getContainingClass();
@@ -136,7 +143,9 @@ public class HighlightMethodUtil {
PsiClass superClass = superMethod.getContainingClass();
if (superClass == null) continue;
HighlightInfo highlightInfo = checkSuperMethodSignature(superMethod, superMethodSignature, superReturnType, method, methodSignature,
returnType, includeRealPositionInfo, JavaErrorMessages.message("incompatible.return.type"), method);
returnType, JavaErrorMessages.message("incompatible.return.type"),
textRange != null ? textRange
: includeRealPositionInfo ? method.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE);
if (highlightInfo != null) return highlightInfo;
}
@@ -149,9 +158,7 @@ public class HighlightMethodUtil {
PsiMethod method,
MethodSignatureBackedByPsiMethod methodSignature,
PsiType returnType,
boolean includeRealPositionInfo,
String detailMessage,
PsiMethod methodToHighlight) {
String detailMessage, final TextRange range) {
if (superReturnType == null) return null;
if ("clone".equals(method.getName())) {
final PsiClass containingClass = method.getContainingClass();
@@ -181,19 +188,17 @@ public class HighlightMethodUtil {
}
}
return createIncompatibleReturnTypeMessage(methodToHighlight, method, superMethod, includeRealPositionInfo,
substitutedSuperReturnType, returnType, detailMessage);
return createIncompatibleReturnTypeMessage(method, superMethod,
substitutedSuperReturnType, returnType, detailMessage,
range);
}
private static HighlightInfo createIncompatibleReturnTypeMessage(PsiMethod methodToHighlight,
PsiMethod method,
private static HighlightInfo createIncompatibleReturnTypeMessage(PsiMethod method,
@NotNull PsiMethod superMethod,
boolean includeRealPositionInfo,
PsiType substitutedSuperReturnType,
@NotNull PsiType returnType,
String detailMessage) {
String detailMessage, final TextRange textRange) {
String description = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage);
TextRange textRange = includeRealPositionInfo ? methodToHighlight.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE;
HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create();
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createMethodReturnFix(method, substitutedSuperReturnType, false));
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createSuperMethodReturnFix(superMethod, returnType));
@@ -1101,8 +1106,9 @@ public class HighlightMethodUtil {
}
}
}
return createIncompatibleReturnTypeMessage(currentMethod, currentMethod, otherSuperMethod, false, otherSuperReturnType,
currentType, JavaErrorMessages.message("unrelated.overriding.methods.return.types"));
return createIncompatibleReturnTypeMessage(currentMethod, otherSuperMethod, otherSuperReturnType,
currentType, JavaErrorMessages.message("unrelated.overriding.methods.return.types"),
false ? currentMethod.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE);
}
return null;
}
@@ -0,0 +1,8 @@
interface I{
void foo();
}
abstract class A {
abstract int foo();
abstract <<error descr="'foo()' in 'A' clashes with 'foo()' in 'I'; attempting to use incompatible return type"></error><error descr="'foo()' in 'A' clashes with 'foo()' in 'I'; attempting to use incompatible return type"></error>T extends A & I> void bar(T x);
}
@@ -318,6 +318,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA113225() throws Exception { doTest5(false); }
public void testIDEA67518() throws Exception { doTest5(false); }
public void testIDEA57252() throws Exception { doTest5(false); }
public void testIDEA57274() throws Exception { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testJavaUtilCollections_NoVerify() throws Exception {
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));