unchecked generics array creation: in new expressions; detect generic signature in anonymous class creation

This commit is contained in:
anna
2011-02-17 09:48:43 +01:00
parent cee90781bd
commit ab784c95c2
3 changed files with 115 additions and 11 deletions
@@ -1113,7 +1113,7 @@ public class GenericsHighlightUtil {
}
@Nullable
public static HighlightInfo checkUncheckedGenericsArrayCreation(PsiReferenceExpression referenceExpression, PsiElement resolved){
public static HighlightInfo checkUncheckedGenericsArrayCreation(PsiJavaCodeReferenceElement referenceExpression, PsiElement resolved){
if (isUncheckedWarning(referenceExpression, resolved, false)) {
final HighlightInfo highlightInfo =
HighlightInfo.createHighlightInfo(HighlightInfoType.WARNING, referenceExpression, "Unchecked generics array creation for varargs parameter");
@@ -1123,7 +1123,7 @@ public class GenericsHighlightUtil {
return null;
}
public static boolean isUncheckedWarning(PsiReferenceExpression expression, PsiElement resolve, boolean ignoreSuppressed) {
public static boolean isUncheckedWarning(PsiJavaCodeReferenceElement expression, PsiElement resolve, boolean ignoreSuppressed) {
if (resolve instanceof PsiMethod) {
final PsiMethod psiMethod = (PsiMethod)resolve;
@@ -1140,12 +1140,31 @@ public class GenericsHighlightUtil {
final PsiType componentType = ((PsiEllipsisType)varargParameter.getType()).getComponentType();
if (!isReifiableType(componentType)) {
final PsiElement parent = expression.getParent();
if (parent instanceof PsiMethodCallExpression) {
final PsiExpression[] args = ((PsiMethodCallExpression)parent).getArgumentList().getExpressions();
for (int i = parametersCount - 1; i < args.length; i++) {
if (!isReifiableType(args[i].getType())){
return true;
if (parent instanceof PsiCall) {
final PsiExpressionList argumentList = ((PsiCall)parent).getArgumentList();
if (argumentList != null) {
final PsiExpression[] args = argumentList.getExpressions();
if (args.length == parametersCount) {
final PsiExpression lastArg = args[args.length - 1];
if (lastArg instanceof PsiReferenceExpression) {
final PsiElement lastArgsResolve = ((PsiReferenceExpression)lastArg).resolve();
if (lastArgsResolve instanceof PsiParameter) {
if (((PsiParameter)lastArgsResolve).getType() instanceof PsiArrayType) {
return false;
}
}
} else if (lastArg instanceof PsiMethodCallExpression) {
if (lastArg.getType() instanceof PsiArrayType) {
return false;
}
}
}
for (int i = parametersCount - 1; i < args.length; i++) {
if (!isReifiableType(args[i].getType())){
return true;
}
}
return args.length < parametersCount;
}
}
}
@@ -1169,14 +1188,22 @@ public class GenericsHighlightUtil {
}
if (type instanceof PsiClassType) {
final PsiClassType classType = (PsiClassType)type;
final PsiClassType classType = (PsiClassType)PsiUtil.convertAnonymousToBaseType(type);
if (classType.isRaw()) {
return true;
}
if (!classType.hasParameters()) {
return true;
PsiType[] parameters = classType.getParameters();
for (PsiType parameter : parameters) {
if (parameter instanceof PsiWildcardType && ((PsiWildcardType)parameter).getBound() == null) {
return true;
}
}
return !classType.hasNonTrivialParameters();
final PsiClass resolved = ((PsiClassType)PsiUtil.convertAnonymousToBaseType(classType)).resolve();
if (resolved instanceof PsiTypeParameter) {
return false;
}
return parameters.length == 0;
}
return false;
@@ -686,6 +686,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkUncheckedGenericsArrayCreation(expression.getClassOrAnonymousClassReference(), expression.resolveConstructor()));
if (!myHolder.hasErrorResults()) registerConstructorCall(expression);
if (!myHolder.hasErrorResults()) visitExpression(expression);
@@ -42,4 +42,80 @@ public class Test {
final ArrayList<String> list = new ArrayList<String>();
<warning descr="Unchecked generics array creation for varargs parameter">asList</warning>(list);
}
public static <V> void join(V[] list) {
Arrays.asList(list);
}
}
class NoWarngs {
static final SemKey<String> FILE_DESCRIPTION_KEY = <warning descr="Unchecked generics array creation for varargs parameter">SemKey.createKey</warning>("FILE_DESCRIPTION_KEY");
void f() {
OCM<String> o =
new <warning descr="Unchecked generics array creation for varargs parameter">OCM<></warning>("", true, new Condition<String>(){
@Override
public boolean val(String s) {
return false;
}
}, Condition.TRUE);
System.out.println(o);
}
}
class SemKey<T extends String> {
private final String myDebugName;
private final SemKey<? super T>[] mySupers;
private SemKey(String debugName, SemKey<? super T>... supers) {
myDebugName = debugName;
System.out.println(myDebugName);
mySupers = supers;
System.out.println(mySupers);
}
public static <T extends String> SemKey<T> createKey(String debugName, SemKey<? super T>... supers) {
return new SemKey<T>(debugName, supers);
}
public <K extends T> SemKey<K> subKey(String debugName, SemKey<? super T>... otherSupers) {
if (otherSupers.length == 0) {
return new <warning descr="Unchecked generics array creation for varargs parameter">SemKey<K></warning>(debugName, this);
}
return new SemKey<K>(debugName, append(otherSupers, this));
}
public static <T> T[] append(final T[] src, final T element) {
return append(src, element, (Class<T>)src.getClass().getComponentType());
}
public static <T> T[] append(T[] src, final T element, Class<T> componentType) {
int length = src.length;
T[] result = (T[])java.lang.reflect.Array.newInstance(componentType, length + 1);
System.arraycopy(src, 0, result, 0, length);
result[length] = element;
return result;
}
}
interface Condition<T> {
boolean val(T t);
Condition TRUE = new Condition() {
@Override
public boolean val(Object o) {
return true;
}
};
}
class OCM<T> {
OCM(T s, boolean b, Condition<T>... c) {
System.out.println(s);
System.out.println(b);
System.out.println(c);
}
OCM(T s, Condition<T>... c) {
this(s, false, c);
}
}