unchecked warning explanation (IDEA-126457)

This commit is contained in:
Anna Kozlova
2015-03-16 13:34:32 +01:00
parent 83e429cd8f
commit 6ad1810157
4 changed files with 78 additions and 16 deletions
@@ -27,9 +27,11 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.*;
import com.intellij.xml.util.XmlUtil;
import org.intellij.lang.annotations.Pattern;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -135,7 +137,15 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
return new UncheckedWarningsVisitor(isOnTheFly, languageLevel){
@Override
protected void registerProblem(@NotNull String message, @NotNull PsiElement psiElement, @NotNull LocalQuickFix[] quickFixes) {
protected void registerProblem(@NotNull String message,
@Nullable PsiElement callExpression,
@NotNull PsiElement psiElement,
@NotNull LocalQuickFix[] quickFixes) {
final String rawExpression = isMethodCalledOnRawType(callExpression);
if (rawExpression != null) {
final String referenceName = ((PsiMethodCallExpression)callExpression).getMethodExpression().getReferenceName();
message += ". Reason: '" + rawExpression + "' has raw type, so result of " + referenceName + " is erased";
}
holder.registerProblem(psiElement, message, quickFixes);
}
};
@@ -145,6 +155,21 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
return null;
}
private static String isMethodCalledOnRawType(PsiElement expression) {
if (expression instanceof PsiMethodCallExpression) {
final PsiExpression qualifierExpression = ((PsiMethodCallExpression)expression).getMethodExpression().getQualifierExpression();
if (qualifierExpression != null) {
final PsiClass qualifierClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType());
if (qualifierClass != null) {
if (PsiUtil.isRawSubstitutor(qualifierClass, ((PsiMethodCallExpression)expression).resolveMethodGenerics().getSubstitutor())) {
return qualifierExpression.getText();
}
}
}
}
return null;
}
private abstract class UncheckedWarningsVisitor extends JavaElementVisitor {
private final boolean myOnTheFly;
@NotNull private final LanguageLevel myLanguageLevel;
@@ -156,7 +181,10 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
myGenerifyFixes = onTheFly ? createFixes() : LocalQuickFix.EMPTY_ARRAY;
}
protected abstract void registerProblem(@NotNull String message, @NotNull PsiElement psiElement, @NotNull LocalQuickFix[] quickFixes);
protected abstract void registerProblem(@NotNull String message,
PsiElement callExpression,
@NotNull PsiElement psiElement,
@NotNull LocalQuickFix[] quickFixes);
@Override
@@ -164,7 +192,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return;
final JavaResolveResult result = expression.advancedResolve(false);
if (JavaGenericsUtil.isUncheckedWarning(expression, result, myLanguageLevel)) {
registerProblem("Unchecked generics array creation for varargs parameter", expression, LocalQuickFix.EMPTY_ARRAY);
registerProblem("Unchecked generics array creation for varargs parameter", null, expression, LocalQuickFix.EMPTY_ARRAY);
}
}
@@ -174,7 +202,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
if (IGNORE_UNCHECKED_GENERICS_ARRAY_CREATION) return;
final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
if (classReference != null && JavaGenericsUtil.isUncheckedWarning(classReference, expression.resolveMethodGenerics(), myLanguageLevel)) {
registerProblem("Unchecked generics array creation for varargs parameter", classReference, LocalQuickFix.EMPTY_ARRAY);
registerProblem("Unchecked generics array creation for varargs parameter", expression, classReference, LocalQuickFix.EMPTY_ARRAY);
}
}
@@ -194,7 +222,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final String description =
JavaErrorMessages.message("generics.unchecked.cast", JavaHighlightUtil.formatType(exprType), JavaHighlightUtil
.formatType(castType));
registerProblem(description, expression, myGenerifyFixes);
registerProblem(description, operand, expression, myGenerifyFixes);
}
}
@@ -206,7 +234,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final String description = getUncheckedCallDescription(result);
if (description != null) {
final PsiElement referenceNameElement = expression.getReferenceNameElement();
registerProblem(description, referenceNameElement != null ? referenceNameElement : expression, myGenerifyFixes);
registerProblem(description, expression, referenceNameElement != null ? referenceNameElement : expression, myGenerifyFixes);
}
}
@@ -220,7 +248,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final PsiExpression element = callExpression instanceof PsiMethodCallExpression
? ((PsiMethodCallExpression)callExpression).getMethodExpression()
: callExpression;
registerProblem(description, element, myGenerifyFixes);
registerProblem(description, callExpression, element, myGenerifyFixes);
}
else {
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
@@ -238,7 +266,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final PsiType parameterType = substitutor.substitute(parameter.getType());
final PsiType expressionType = expression.getType();
if (expressionType != null) {
checkRawToGenericsAssignment(expression, parameterType, expressionType, true, myGenerifyFixes);
checkRawToGenericsAssignment(expression, expression, parameterType, expressionType, true, myGenerifyFixes);
}
}
}
@@ -254,7 +282,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
PsiExpression initializer = variable.getInitializer();
if (initializer == null || initializer instanceof PsiArrayInitializerExpression) return;
final PsiType initializerType = initializer.getType();
checkRawToGenericsAssignment(initializer, variable.getType(), initializerType, true,
checkRawToGenericsAssignment(initializer, initializer, variable.getType(), initializerType, true,
myOnTheFly ? getChangeVariableTypeFixes(variable, initializerType) : LocalQuickFix.EMPTY_ARRAY);
}
@@ -267,7 +295,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final PsiExpression iteratedValue = statement.getIteratedValue();
if (iteratedValue == null) return;
final PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
checkRawToGenericsAssignment(parameter, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType) : LocalQuickFix.EMPTY_ARRAY);
checkRawToGenericsAssignment(parameter, iteratedValue, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType) : LocalQuickFix.EMPTY_ARRAY);
}
@Override
@@ -288,7 +316,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
leftVar = (PsiVariable)element;
}
}
checkRawToGenericsAssignment(rExpr, lType, rType, true, myOnTheFly && leftVar != null ? getChangeVariableTypeFixes(leftVar, rType) : LocalQuickFix.EMPTY_ARRAY);
checkRawToGenericsAssignment(rExpr, rExpr, lType, rType, true, myOnTheFly && leftVar != null ? getChangeVariableTypeFixes(leftVar, rType) : LocalQuickFix.EMPTY_ARRAY);
}
@Override
@@ -320,14 +348,14 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
}
if (fix != null) {
registerProblem(description, expression, new LocalQuickFix[]{fix});
registerProblem(description, null, expression, new LocalQuickFix[]{fix});
}
}
}
}
private void checkRawToGenericsAssignment(@NotNull PsiElement parameter,
PsiType parameterType,
PsiExpression expression, PsiType parameterType,
PsiType itemType,
boolean checkAssignability,
@NotNull LocalQuickFix[] quickFixes) {
@@ -337,7 +365,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
String description = JavaErrorMessages.message("generics.unchecked.assignment",
JavaHighlightUtil.formatType(itemType),
JavaHighlightUtil.formatType(parameterType));
registerProblem(description, parameter, quickFixes);
registerProblem(description, expression, parameter, quickFixes);
}
}
@@ -364,7 +392,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final PsiTypeElement returnTypeElement = method.getReturnTypeElement();
LOG.assertTrue(returnTypeElement != null);
registerProblem(message, returnTypeElement, LocalQuickFix.EMPTY_ARRAY);
registerProblem(message, null, returnTypeElement, LocalQuickFix.EMPTY_ARRAY);
}
}
}
@@ -384,7 +412,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
if (returnValue != null) {
final PsiType valueType = returnValue.getType();
if (valueType != null) {
checkRawToGenericsAssignment(returnValue, returnType, valueType,
checkRawToGenericsAssignment(returnValue, returnValue, returnType, valueType,
false,
new LocalQuickFix[]{QuickFixFactory.getInstance().createMethodReturnFix(method, valueType, true)});
}
@@ -0,0 +1,29 @@
import java.util.Iterator;
import java.util.List;
class A<<warning descr="Type parameter 'T' is never used">T</warning>> {
List<String> getList() {
return null;
}
}
public class DefaultEventSource<<warning descr="Type parameter 'T' is never used">T</warning>> extends A {
public Iterator<String> getKeys(){
return null;
}
@Override
List<String> getList() {
return <warning descr="Unchecked assignment: 'java.util.List' to 'java.util.List<java.lang.String>'. Reason: 'super' has raw type, so result of getList is erased">super.getList()</warning>;
}
void f(DefaultEventSource source){
final Iterator<String> <warning descr="Variable 'keys' is never used">keys</warning> = <warning descr="Unchecked assignment: 'java.util.Iterator' to 'java.util.Iterator<java.lang.String>'. Reason: 'source' has raw type, so result of getKeys is erased">source. getKeys()</warning>;
final Iterator<String> <warning descr="Variable 'keys1' is never used">keys1</warning> = <warning descr="Unchecked cast: 'java.util.Iterator' to 'java.util.Iterator<java.lang.String>'. Reason: 'source' has raw type, so result of getKeys is erased">(Iterator<String>)source.getKeys()</warning>;
final Iterator<String> <warning descr="Variable 'keys2' is assigned but never accessed">keys2</warning>;
keys2 = <warning descr="Unchecked assignment: 'java.util.Iterator' to 'java.util.Iterator<java.lang.String>'. Reason: 'source' has raw type, so result of getKeys is erased">source.getKeys()</warning>;
for (<error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.String'">String <warning descr="Parameter 'o' is never used">o</warning> : super.getList()</error>) {}
}
}
@@ -188,4 +188,8 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testIDEA111450() { doTest(true, false); }
public void testExternalizable() { doTest(true, false); }
public void testAccessToStaticMethodsFromInterfaces() { doTest(true, false); }
public void testUncheckedExtendedWarnings() throws Exception {
doTest(true, false);
}
}
@@ -8,5 +8,6 @@ by the compiler, for example:
}
</code>
</pre>
Hint: Pass -Xlint:unchecked to javac to get more details.
</body>
</html>