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 fae7d6f3c6db..efc3b9807f10 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 @@ -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; 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 a0e24bba2741..57b3c20c7d1a 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 @@ -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); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java index 52dcb04f60ca..ab08ae041339 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java @@ -42,4 +42,80 @@ public class Test { final ArrayList list = new ArrayList(); asList(list); } + + public static void join(V[] list) { + Arrays.asList(list); + } +} + +class NoWarngs { + static final SemKey FILE_DESCRIPTION_KEY = SemKey.createKey("FILE_DESCRIPTION_KEY"); + + void f() { + OCM o = + new OCM<>("", true, new Condition(){ + @Override + public boolean val(String s) { + return false; + } + }, Condition.TRUE); + System.out.println(o); + } +} + +class SemKey { + private final String myDebugName; + private final SemKey[] mySupers; + + private SemKey(String debugName, SemKey... supers) { + myDebugName = debugName; + System.out.println(myDebugName); + mySupers = supers; + System.out.println(mySupers); + } + + public static SemKey createKey(String debugName, SemKey... supers) { + return new SemKey(debugName, supers); + } + + public SemKey subKey(String debugName, SemKey... otherSupers) { + if (otherSupers.length == 0) { + return new SemKey(debugName, this); + } + return new SemKey(debugName, append(otherSupers, this)); + } + + public static T[] append(final T[] src, final T element) { + return append(src, element, (Class)src.getClass().getComponentType()); + } + + public static T[] append(T[] src, final T element, Class 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 { + boolean val(T t); + + Condition TRUE = new Condition() { + @Override + public boolean val(Object o) { + return true; + } + }; +} +class OCM { + OCM(T s, boolean b, Condition... c) { + System.out.println(s); + System.out.println(b); + System.out.println(c); + } + + OCM(T s, Condition... c) { + this(s, false, c); + } } \ No newline at end of file