Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java')
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java188
1 files changed, 177 insertions, 11 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 5765e0bcf..9afa1200f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -22,6 +22,10 @@
* bug 374605 - Unreasonable warning for enum-based switch statements
* bug 388281 - [compiler][null] inheritance of null annotations as an option
* bug 376053 - [compiler][resource] Strange potential resource leak problems
+ * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
+ * bug 393719 - [compiler] inconsistent warnings on iteration variables
+ * bug 331649 - [compiler][null] consider null annotations for fields
+ * bug 382789 - [compiler][null] warn when syntactically-nonnull expression is compared against null
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.problem;
@@ -50,6 +54,7 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
@@ -81,6 +86,7 @@ import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
@@ -318,6 +324,7 @@ public static int getIrritant(int problemID) {
case IProblem.UnsafeRawConstructorInvocation:
case IProblem.UnsafeRawMethodInvocation:
case IProblem.UnsafeTypeConversion:
+ case IProblem.UnsafeElementTypeConversion:
case IProblem.UnsafeRawFieldAssignment:
case IProblem.UnsafeGenericCast:
case IProblem.UnsafeReturnTypeOverride:
@@ -356,6 +363,7 @@ public static int getIrritant(int problemID) {
return CompilerOptions.VarargsArgumentNeedCast;
case IProblem.NullLocalVariableReference:
+ case IProblem.NullableFieldReference:
return CompilerOptions.NullReference;
case IProblem.PotentialNullLocalVariableReference:
@@ -368,9 +376,14 @@ public static int getIrritant(int problemID) {
case IProblem.NonNullLocalVariableComparisonYieldsFalse:
case IProblem.NullLocalVariableComparisonYieldsFalse:
case IProblem.NullLocalVariableInstanceofYieldsFalse:
+ case IProblem.RedundantNullCheckOnNonNullExpression:
+ case IProblem.NonNullExpressionComparisonYieldsFalse:
case IProblem.RedundantNullCheckOnNonNullMessageSend:
case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable:
case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse:
+ case IProblem.NonNullMessageSendComparisonYieldsFalse:
+ case IProblem.RedundantNullCheckOnNonNullSpecdField:
+ case IProblem.NonNullSpecdFieldComparisonYieldsFalse:
return CompilerOptions.RedundantNullCheck;
case IProblem.RequiredNonNullButProvidedNull:
@@ -378,13 +391,17 @@ public static int getIrritant(int problemID) {
case IProblem.IllegalReturnNullityRedefinition:
case IProblem.IllegalRedefinitionToNonNullParameter:
case IProblem.IllegalDefinitionToNonNullParameter:
- case IProblem.ParameterLackingNonNullAnnotation:
case IProblem.ParameterLackingNullableAnnotation:
case IProblem.CannotImplementIncompatibleNullness:
+ case IProblem.UninitializedNonNullField:
+ case IProblem.UninitializedNonNullFieldHintMissingDefault:
case IProblem.ConflictingNullAnnotations:
case IProblem.ConflictingInheritedNullAnnotations:
return CompilerOptions.NullSpecViolation;
+ case IProblem.ParameterLackingNonNullAnnotation:
+ return CompilerOptions.NonnullParameterAnnotationDropped;
+
case IProblem.RequiredNonNullButProvidedPotentialNull:
return CompilerOptions.NullAnnotationInferenceConflict;
case IProblem.RequiredNonNullButProvidedUnknown:
@@ -787,6 +804,7 @@ public static int getProblemCategory(int severity, int problemID) {
case CompilerOptions.NullAnnotationInferenceConflict :
case CompilerOptions.NullUncheckedConversion :
case CompilerOptions.MissingNonNullByDefaultAnnotation:
+ case CompilerOptions.NonnullParameterAnnotationDropped:
return CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM;
case CompilerOptions.RedundantNullAnnotation :
return CategorizedProblem.CAT_UNNECESSARY_CODE;
@@ -5744,6 +5762,92 @@ public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNo
nodeSourceEnd(local, location));
}
+/**
+ * @param expr expression being compared for null or nonnull
+ * @param checkForNull true if checking for null, false if checking for nonnull
+ */
+public boolean expressionNonNullComparison(Expression expr, boolean checkForNull) {
+ int problemId = 0;
+ Binding binding = null;
+ String[] arguments = null;
+ int start = 0, end = 0;
+
+ Expression location = expr;
+ // unwrap uninteresting nodes:
+ while (true) {
+ if (expr instanceof Assignment)
+ return false; // don't report against the assignment, but the variable
+ else if (expr instanceof CastExpression)
+ expr = ((CastExpression) expr).expression;
+ else
+ break;
+ }
+ // check all those kinds of expressions that can possible answer NON_NULL from nullStatus():
+ if (expr instanceof MessageSend) {
+ problemId = checkForNull
+ ? IProblem.NonNullMessageSendComparisonYieldsFalse
+ : IProblem.RedundantNullCheckOnNonNullMessageSend;
+ MethodBinding method = ((MessageSend)expr).binding;
+ binding = method;
+ arguments = new String[] { new String(method.shortReadableName()) };
+ start = location.sourceStart;
+ end = location.sourceEnd;
+ } else if (expr instanceof Reference && !(expr instanceof ThisReference) && !(expr instanceof ArrayReference)) {
+ FieldBinding field = ((Reference)expr).lastFieldBinding();
+ if (field == null) {
+ return false;
+ }
+ if (field.isNonNull()) {
+ problemId = checkForNull
+ ? IProblem.NonNullSpecdFieldComparisonYieldsFalse
+ : IProblem.RedundantNullCheckOnNonNullSpecdField;
+ char[][] nonNullName = this.options.nonNullAnnotationName;
+ arguments = new String[] { new String(field.name),
+ new String(nonNullName[nonNullName.length-1]) };
+ }
+ binding = field;
+ start = nodeSourceStart(binding, location);
+ end = nodeSourceEnd(binding, location);
+ } else if (expr instanceof AllocationExpression
+ || expr instanceof ArrayAllocationExpression
+ || expr instanceof ArrayInitializer
+ || expr instanceof ClassLiteralAccess
+ || expr instanceof ThisReference) {
+ // fall through to bottom
+ } else if (expr instanceof Literal
+ || expr instanceof ConditionalExpression) {
+ if (expr instanceof NullLiteral) {
+ needImplementation(location); // reported as nonnull??
+ return false;
+ }
+ if (expr.resolvedType != null && expr.resolvedType.isBaseType()) {
+ // false alarm, auto(un)boxing is involved
+ return false;
+ }
+ // fall through to bottom
+ } else if (expr instanceof BinaryExpression) {
+ if ((expr.bits & ASTNode.ReturnTypeIDMASK) != TypeIds.T_JavaLangString) {
+ // false alarm, primitive types involved, must be auto(un)boxing?
+ return false;
+ }
+ // fall through to bottom
+ } else {
+ needImplementation(expr); // want to see if we get here
+ return false;
+ }
+ if (problemId == 0) {
+ // standard case, fill in details now
+ problemId = checkForNull
+ ? IProblem.NonNullExpressionComparisonYieldsFalse
+ : IProblem.RedundantNullCheckOnNonNullExpression;
+ start = location.sourceStart;
+ end = location.sourceEnd;
+ arguments = NoArgument;
+ }
+ this.handle(problemId, arguments, arguments, start, end);
+ return true;
+}
+
public void localVariableNullInstanceof(LocalVariableBinding local, ASTNode location) {
int severity = computeSeverity(IProblem.NullLocalVariableInstanceofYieldsFalse);
if (severity == ProblemSeverities.Ignore) return;
@@ -5799,6 +5903,18 @@ public void localVariablePotentialNullReference(LocalVariableBinding local, ASTN
nodeSourceEnd(local, location));
}
+public void nullableFieldDereference(VariableBinding variable, long position) {
+ String[] arguments = new String[] {new String(variable.name)};
+ char[][] nullableName = this.options.nullableAnnotationName;
+ arguments = new String[] {new String(variable.name), new String(nullableName[nullableName.length-1])};
+ this.handle(
+ IProblem.NullableFieldReference,
+ arguments,
+ arguments,
+ (int)(position >>> 32),
+ (int)(position));
+}
+
public void localVariableRedundantCheckOnNonNull(LocalVariableBinding local, ASTNode location) {
int severity = computeSeverity(IProblem.RedundantNullCheckOnNonNullLocalVariable);
if (severity == ProblemSeverities.Ignore) return;
@@ -7947,6 +8063,19 @@ public void uninitializedBlankFinalField(FieldBinding field, ASTNode location) {
nodeSourceStart(field, location),
nodeSourceEnd(field, location));
}
+public void uninitializedNonNullField(FieldBinding field, ASTNode location) {
+ char[][] nonNullAnnotationName = this.options.nonNullAnnotationName;
+ String[] arguments = new String[] {
+ new String(nonNullAnnotationName[nonNullAnnotationName.length-1]),
+ new String(field.readableName())
+ };
+ this.handle(
+ methodHasMissingSwitchDefault() ? IProblem.UninitializedNonNullFieldHintMissingDefault : IProblem.UninitializedNonNullField,
+ arguments,
+ arguments,
+ nodeSourceStart(field, location),
+ nodeSourceEnd(field, location));
+}
public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location) {
binding.tagBits |= TagBits.NotInitialized;
String[] arguments = new String[] {new String(binding.readableName())};
@@ -8334,6 +8463,21 @@ public void unsafeTypeConversion(Expression expression, TypeBinding expressionTy
expression.sourceStart,
expression.sourceEnd);
}
+public void unsafeElementTypeConversion(Expression expression, TypeBinding expressionType, TypeBinding expectedType) {
+ if (this.options.sourceLevel < ClassFileConstants.JDK1_5) return; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=305259
+ int severity = computeSeverity(IProblem.UnsafeElementTypeConversion);
+ if (severity == ProblemSeverities.Ignore) return;
+ if (!this.options.reportUnavoidableGenericTypeProblems && expression.forcedToBeRaw(this.referenceContext)) {
+ return;
+ }
+ this.handle(
+ IProblem.UnsafeElementTypeConversion,
+ new String[] { new String(expressionType.readableName()), new String(expectedType.readableName()), new String(expectedType.erasure().readableName()) },
+ new String[] { new String(expressionType.shortReadableName()), new String(expectedType.shortReadableName()), new String(expectedType.erasure().shortReadableName()) },
+ severity,
+ expression.sourceStart,
+ expression.sourceEnd);
+}
public void unusedArgument(LocalDeclaration localDecl) {
int severity = computeSeverity(IProblem.ArgumentIsNeverUsed);
if (severity == ProblemSeverities.Ignore) return;
@@ -8970,14 +9114,13 @@ public void nullityMismatch(Expression expression, TypeBinding providedType, Typ
return;
}
if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0) {
- if (expression instanceof SingleNameReference) {
- SingleNameReference snr = (SingleNameReference) expression;
- if (snr.binding instanceof LocalVariableBinding) {
- if (((LocalVariableBinding)snr.binding).isNullable()) {
- nullityMismatchSpecdNullable(expression, requiredType, annotationName);
- return;
- }
- }
+ VariableBinding var = expression.localVariableBinding();
+ if (var == null && expression instanceof Reference) {
+ var = ((Reference)expression).lastFieldBinding();
+ }
+ if (var != null && var.isNullable()) {
+ nullityMismatchSpecdNullable(expression, requiredType, annotationName);
+ return;
}
nullityMismatchPotentiallyNull(expression, requiredType, annotationName);
return;
@@ -12666,14 +12809,30 @@ public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBi
argument.type.sourceEnd);
}
}
-public void parameterLackingNullAnnotation(Argument argument, ReferenceBinding declaringClass, boolean needNonNull, char[][] inheritedAnnotationName) {
+public void parameterLackingNullableAnnotation(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
this.handle(
- needNonNull ? IProblem.ParameterLackingNonNullAnnotation : IProblem.ParameterLackingNullableAnnotation,
+ IProblem.ParameterLackingNullableAnnotation,
new String[] { new String(argument.name), new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
argument.type.sourceStart,
argument.type.sourceEnd);
}
+public void parameterLackingNonnullAnnotation(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
+ int sourceStart = 0, sourceEnd = 0;
+ if (argument != null) {
+ sourceStart = argument.type.sourceStart;
+ sourceEnd = argument.type.sourceEnd;
+ } else if (this.referenceContext instanceof TypeDeclaration) {
+ sourceStart = ((TypeDeclaration) this.referenceContext).sourceStart;
+ sourceEnd = ((TypeDeclaration) this.referenceContext).sourceEnd;
+ }
+ this.handle(
+ IProblem.ParameterLackingNonNullAnnotation,
+ new String[] { new String(declaringClass.readableName()), CharOperation.toString(inheritedAnnotationName)},
+ new String[] { new String(declaringClass.shortReadableName()), new String(inheritedAnnotationName[inheritedAnnotationName.length-1])},
+ sourceStart,
+ sourceEnd);
+}
public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl, MethodBinding inheritedMethod, char[][] nonNullAnnotationName) {
MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl;
StringBuffer methodSignature = new StringBuffer();
@@ -12758,6 +12917,13 @@ public void nullAnnotationIsRedundant(AbstractMethodDeclaration sourceMethod, in
this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
}
+public void nullAnnotationIsRedundant(FieldDeclaration sourceField) {
+ Annotation annotation = findAnnotation(sourceField.annotations, TypeIds.T_ConfiguredAnnotationNonNull);
+ int sourceStart = annotation != null ? annotation.sourceStart : sourceField.type.sourceStart;
+ int sourceEnd = sourceField.type.sourceEnd;
+ this.handle(IProblem.RedundantNullAnnotation, ProblemHandler.NoArgument, ProblemHandler.NoArgument, sourceStart, sourceEnd);
+}
+
public void nullDefaultAnnotationIsRedundant(ASTNode location, Annotation[] annotations, Binding outer) {
Annotation annotation = findAnnotation(annotations, TypeIds.T_ConfiguredAnnotationNonNullByDefault);
int start = annotation != null ? annotation.sourceStart : location.sourceStart;

Back to the top