IDEA-96860 Improper error reporting with type parameter

This commit is contained in:
Max Medvedev
2012-12-12 13:12:57 +04:00
parent 36de07318c
commit 6cec6a9078
5 changed files with 47 additions and 18 deletions
@@ -338,4 +338,5 @@ java.style.for.each.statement.requires.a.type.declaration=Java-style for-each st
enums.may.not.have.extends.clause=Enums may not have 'extends' clause
super.cannot.be.used.in.static.context='super' cannot be used in static context
qualified.0.is.allowed.only.in.nested.or.inner.classes=Qualified {0} is allowed only in nested/inner classes
groovy.file.0=Groovy file ''{0}''
groovy.file.0=Groovy file ''{0}''
type.argument.list.is.not.allowed.here=Type argument list is not allowed here
@@ -149,19 +149,16 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
@Override
public void visitTypeArgumentList(GrTypeArgumentList typeArgumentList) {
PsiElement parent = typeArgumentList.getParent();
final PsiElement resolved;
if (parent instanceof GrReferenceElement) {
resolved = ((GrReferenceElement)parent).resolve();
}
else {
resolved = null;
}
if (!(parent instanceof GrReferenceElement)) return;
final GroovyResolveResult resolveResult = ((GrReferenceElement)parent).advancedResolve();
final PsiElement resolved = resolveResult.getElement();
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
if (resolved == null) return;
if (!(resolved instanceof PsiTypeParameterListOwner)) {
//myHolder.createErrorAnnotation(typeArgumentList, GroovyBundle.message("type.argument.list.is.no.a"))
//todo correct error description
myHolder.createWarningAnnotation(typeArgumentList, GroovyBundle.message("type.argument.list.is.not.allowed.here"));
return;
}
@@ -173,8 +170,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
final GrTypeElement[] arguments = typeArgumentList.getTypeArgumentElements();
if (arguments.length != parameters.length) {
myHolder.createErrorAnnotation(typeArgumentList,
GroovyBundle.message("wrong.number.of.type.arguments", arguments.length, parameters.length));
myHolder.createWarningAnnotation(typeArgumentList,
GroovyBundle.message("wrong.number.of.type.arguments", arguments.length, parameters.length));
return;
}
@@ -183,8 +180,9 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
final PsiClassType[] superTypes = parameter.getExtendsListTypes();
final PsiType argType = arguments[i].getType();
for (PsiClassType superType : superTypes) {
if (!superType.isAssignableFrom(argType)) {
myHolder.createErrorAnnotation(arguments[i], GroovyBundle
final PsiType substitutedSuper = substitutor.substitute(superType);
if (substitutedSuper != null && !substitutedSuper.isAssignableFrom(argType)) {
myHolder.createWarningAnnotation(arguments[i], GroovyBundle
.message("type.argument.0.is.not.in.its.bound.should.extend.1", argType.getCanonicalText(), superType.getCanonicalText()));
break;
}
@@ -75,6 +75,17 @@ package java.math;
public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
''')
}
protected void addHashSet() {
myFixture.addClass('''\
package java.util;
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{}
''')
}
@@ -408,9 +408,9 @@ private def handleImplicitBind(arg) {
public void testIncorrectTypeArguments() {
myFixture.configureByText('_.groovy', '''\
class C <T extends String> {}
C<<error descr="Type parameter 'java.lang.Double' is not in its bound; should extend 'java.lang.String'">Double</error>> c
C<<warning descr="Type parameter 'java.lang.Double' is not in its bound; should extend 'java.lang.String'">Double</warning>> c
C<String> c2
C<error descr="Wrong number of type arguments: 2; required: 1"><String, Double></error> c3
C<warning descr="Wrong number of type arguments: 2; required: 1"><String, Double></warning> c3
''')
myFixture.testHighlighting(true, false, true)
}
@@ -953,6 +953,25 @@ print new Foo()
<error descr="Ambiguous code block">{
String toString() {'abc'}
}</error>
''')
}
void testGenerics() {
addHashSet()
testHighlighting('''
class NodeInfo{}
interface NodeEvent<T> {}
interface TrackerEventsListener<N extends NodeInfo, E extends NodeEvent<N>> {
void onEvents(Collection<E> events)
}
class AgentInfo extends NodeInfo {}
print new HashSet<TrackerEventsListener<AgentInfo, NodeEvent<AgentInfo>>>() //correct
print new HashSet<TrackerEventsListener<AgentInfo, <warning descr="Type parameter 'NodeEvent<java.lang.Object>' is not in its bound; should extend 'NodeEvent<N>'">NodeEvent<Object></warning>>>() //incorrect
''')
}
}
@@ -28,10 +28,10 @@ class TroubleCase {
}
public interface Foo<FFIC> {}
public class Bar implements Cloneable, Zoo<Goo, Doo, <error descr="Type parameter 'Coo' is not in its bound; should extend 'Hoo<AR>'">Coo</error>, <error descr="Type parameter 'Woo' is not in its bound; should extend 'Hoo<FR>'">Woo</error>> {}
public class Bar implements Cloneable, Zoo<Goo, Doo, Coo, Woo> {}
public interface Zoo<AR, FR, AM extends Hoo<AR>, FM extends Hoo<FR>> {}
public interface Hoo<R> {}
public class Baz implements Cloneable, Zoo<String,String,<error descr="Type parameter 'Too' is not in its bound; should extend 'Hoo<AR>'">Too</error>,<error descr="Type parameter 'Yoo' is not in its bound; should extend 'Hoo<FR>'">Yoo</error>> {}
public class Baz implements Cloneable, Zoo<String,String,Too,Yoo> {}
public class Goo {}
public class Too implements Hoo<String> {}
public class Coo implements Serializable, Cloneable, Hoo<Goo> {}