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 8a00c167243a..fae7d6f3c6db 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 @@ -15,17 +15,20 @@ */ package com.intellij.codeInsight.daemon.impl.analysis; +import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.JavaHightlightInfoTypes; +import com.intellij.codeInsight.daemon.impl.actions.SuppressFix; import com.intellij.codeInsight.daemon.impl.quickfix.*; import com.intellij.codeInsight.intention.EmptyIntentionAction; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.codeInspection.SuppressManager; import com.intellij.codeInspection.ex.InspectionManagerEx; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; @@ -1109,6 +1112,49 @@ public class GenericsHighlightUtil { } } + @Nullable + public static HighlightInfo checkUncheckedGenericsArrayCreation(PsiReferenceExpression referenceExpression, PsiElement resolved){ + if (isUncheckedWarning(referenceExpression, resolved, false)) { + final HighlightInfo highlightInfo = + HighlightInfo.createHighlightInfo(HighlightInfoType.WARNING, referenceExpression, "Unchecked generics array creation for varargs parameter"); + QuickFixAction.registerQuickFixAction(highlightInfo, new SuppressFix("unchecked")); + return highlightInfo; + } + return null; + } + + public static boolean isUncheckedWarning(PsiReferenceExpression expression, PsiElement resolve, boolean ignoreSuppressed) { + if (resolve instanceof PsiMethod) { + final PsiMethod psiMethod = (PsiMethod)resolve; + + final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(expression); + if (!ignoreSuppressed) { + if (SuppressManager.getInstance().isSuppressedFor(expression, "unchecked")) return false; + } + + if (psiMethod.isVarArgs()) { + if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7) || !AnnotationUtil.isAnnotated(psiMethod, "java.lang.SafeVarargs", false)) { + final int parametersCount = psiMethod.getParameterList().getParametersCount(); + final PsiParameter varargParameter = + psiMethod.getParameterList().getParameters()[parametersCount - 1]; + 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; + } + } + } + } + } + } + } + return false; + } + public static boolean isReifiableType(PsiType type) { if (type instanceof PsiArrayType) { return isReifiableType(((PsiArrayType)type).getComponentType()); 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 951de551451c..a0e24bba2741 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 @@ -836,6 +836,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved)); + if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkUncheckedGenericsArrayCreation(expression, resolved)); } @Override public void visitReferenceList(PsiReferenceList list) { diff --git a/java/java-impl/src/com/intellij/codeInspection/RedundantUncheckedSuppressWarningsInspection.java b/java/java-impl/src/com/intellij/codeInspection/RedundantUncheckedSuppressWarningsInspection.java index 8b6575560df6..11fe84b84ac5 100644 --- a/java/java-impl/src/com/intellij/codeInspection/RedundantUncheckedSuppressWarningsInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/RedundantUncheckedSuppressWarningsInspection.java @@ -107,13 +107,6 @@ public class RedundantUncheckedSuppressWarningsInspection extends BaseJavaLocalI private static void checkIfSafeToRemoveWarning(PsiElement suppressElement, PsiElement placeToCheckWarningsIn, ProblemsHolder holder) { final HashSet warningsElements = new HashSet(); collectUncheckedWarnings(placeToCheckWarningsIn, true, warningsElements); - for (Iterator iterator = warningsElements.iterator(); iterator.hasNext(); ) { - PsiReferenceExpression element = iterator.next(); - final PsiElement resolve = element.resolve(); - if (resolve instanceof PsiMethod && AnnotationUtil.isAnnotated((PsiMethod)resolve, "java.lang.SafeVarargs", false)) { - iterator.remove(); - } - } if (warningsElements.isEmpty()) { final int uncheckedIdx = suppressElement.getText().indexOf(RemoveUncheckedWarningFix.UNCHECKED); holder.registerProblem(suppressElement, @@ -127,28 +120,8 @@ public class RedundantUncheckedSuppressWarningsInspection extends BaseJavaLocalI @Override public void visitReferenceExpression(PsiReferenceExpression expression) { super.visitReferenceExpression(expression); - if (!ignoreSuppressed && SuppressManager.getInstance().isSuppressedFor(expression, RemoveUncheckedWarningFix.UNCHECKED)) return; - - final PsiElement resolve = expression.resolve(); - if (resolve instanceof PsiMethod) { - final PsiMethod psiMethod = (PsiMethod)resolve; - if (psiMethod.isVarArgs()) { - final int parametersCount = psiMethod.getParameterList().getParametersCount(); - final PsiParameter varargParameter = - psiMethod.getParameterList().getParameters()[parametersCount - 1]; - final PsiType componentType = ((PsiEllipsisType)varargParameter.getType()).getComponentType(); - if (!GenericsHighlightUtil.isReifiableType(componentType)) { - final PsiElement parent = expression.getParent(); - if (parent instanceof PsiMethodCallExpression) { - final PsiExpression[] args = ((PsiMethodCallExpression)parent).getArgumentList().getExpressions(); - if (args.length >= parametersCount) { - if (!GenericsHighlightUtil.isReifiableType(args[args.length - 1].getType())){ - warningsElements.add(expression); - } - } - } - } - } + if (GenericsHighlightUtil.isUncheckedWarning(expression, expression.resolve(), ignoreSuppressed)) { + warningsElements.add(expression); } } }); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java new file mode 100644 index 000000000000..52dcb04f60ca --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/UncheckedGenericsArrayCreation.java @@ -0,0 +1,45 @@ +import java.util.*; + +public class Test { + static List asList(T... tt) { + System.out.println(tt); + return null; + } + + @SafeVarargs + static List asListSuppressed(T... tt) { + System.out.println(tt); + return null; + } + + static List asStringList(List... tt) { + return tt[0]; + } + + static List asQList(List... tt) { + return tt[0]; + } + + static List asIntList(int... tt) { + System.out.println(tt); + return null; + } + + + public static void main(String[] args) { + asList(new ArrayList()); + + asListSuppressed(new ArrayList()); + + //noinspection unchecked + asList(new ArrayList()); + + asStringList(new ArrayList()); + + asQList(new ArrayList()); + asIntList(1); + + final ArrayList list = new ArrayList(); + asList(list); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java index 090c21cf4dcd..863890a701b6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IntersectionTypes.java @@ -112,7 +112,7 @@ class Maps { class Client { void f(Date d) { //this call should be OK - Maps.asMap(Maps.entry(fieldName(), "Test"), + Maps.asMap(Maps.entry(fieldName(), "Test"), Maps.entry(fieldName(), 1), Maps.entry(fieldName(), d)); } @@ -136,7 +136,7 @@ Boolean.class, Boolean.TYPE /*,String[].class */ /*,BigDecimal.class*/); public static final List> SIMPLE_TYPES_INFERRED = - asList(String.class, Integer.class ,Long.class, Double.class, /*Date.class,*/ + asList(String.class, Integer.class ,Long.class, Double.class, /*Date.class,*/ Boolean.class, Boolean.TYPE ,String[].class /*,BigDecimal.class*/); @@ -157,7 +157,7 @@ public class MaximalType { return null; } { - getParentOfType(M2.class, M.class); + getParentOfType(M2.class, M.class); } } class M extends MaximalType implements L{} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index 0b1625a31512..a4ab1b0aa8e6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -156,4 +156,8 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { public void testSafeVarargsApplicability() throws Exception { doTest(true, false); } + + public void testUncheckedGenericsArrayCreation() throws Exception { + doTest(true, false); + } }