Index: compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java,v
retrieving revision 1.62
diff -u -r1.62 LocalDeclaration.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 28 Oct 2006 04:11:27 -0000 1.62
+++ compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 28 Jul 2007 11:21:59 -0000
@@ -62,6 +62,8 @@
default:
flowInfo.markAsDefinitelyUnknown(this.binding);
}
+ if (isNonNullAnnotated(currentScope, binding.getAnnotations()) && nullStatus != FlowInfo.NON_NULL)
+ binding.declaringScope.problemReporter().localCannotBeAssignedWithPotentiallyNull(binding, initialization);
// no need to inform enclosing try block since its locals won't get
// known by the finally block
}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java,v
retrieving revision 1.69
diff -u -r1.69 EqualExpression.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java 19 Jul 2007 14:04:59 -0000 1.69
+++ compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java 28 Jul 2007 11:21:58 -0000
@@ -28,10 +28,33 @@
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, right.nullStatus(flowInfo), this.left);
}
+ // TODO: if allowed, simpler check would be for left and right nullStatus equality (for != UNKNOW)
+ Expression tmp = left;
+ while (tmp instanceof CastExpression)
+ tmp = ((CastExpression)tmp).expression;
+ if (tmp instanceof MessageSend) {
+ MessageSend ms = (MessageSend)tmp;
+ int rightNullStatus = right.nullStatus(flowInfo);
+ if ((rightNullStatus == FlowInfo.NULL
+ || rightNullStatus == FlowInfo.NON_NULL)
+ && isNonNullAnnotated(scope, ms.binding.getAnnotations()))
+ scope.problemReporter().cannotReturnPotentiallyNullExpression(left);
+ }
local = this.right.localVariableBinding();
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, left.nullStatus(flowInfo), this.right);
}
+ tmp = right;
+ while (tmp instanceof CastExpression)
+ tmp = ((CastExpression)tmp).expression;
+ if (tmp instanceof MessageSend) {
+ MessageSend ms = (MessageSend)tmp;
+ int rightNullStatus = left.nullStatus(flowInfo);
+ if ((rightNullStatus == FlowInfo.NULL
+ || rightNullStatus == FlowInfo.NON_NULL)
+ && isNonNullAnnotated(scope, ms.binding.getAnnotations()))
+ scope.problemReporter().cannotReturnPotentiallyNullExpression(right);
+ }
}
private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
switch (nullStatus) {
Index: compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java,v
retrieving revision 1.84
diff -u -r1.84 ASTNode.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 22 Jun 2007 15:50:14 -0000 1.84
+++ compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 28 Jul 2007 11:21:56 -0000
@@ -15,7 +15,9 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
public abstract class ASTNode implements TypeConstants, TypeIds {
@@ -711,6 +713,30 @@
}
}
+/**
+ * Return true
if ab
contains
+ * a non-null annotation.
+ */
+public static boolean isNonNullAnnotated(Scope currentScope, AnnotationBinding[] ab) {
+ if (ab == null || ab.length == 0)
+ return false;
+ if (currentScope.compilerOptions().getSeverity(CompilerOptions.NullReference) != ProblemSeverities.Ignore) {
+ // TODO: use lazy creation
+ char[][] annotations = CharOperation.splitOn(';', currentScope.compilerOptions().nonNullAnnotations.toCharArray());
+ for (int i = 0; i < ab.length; i++) {
+ if (ab[i] != null) {
+ for (int j = 0; j < annotations.length; j++) {
+ char[] annotation = ab[i].getAnnotationType().readableName();
+ if (CharOperation.compareTo(annotation, annotations[j]) == 0) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
public int sourceStart() {
return this.sourceStart;
}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java,v
retrieving revision 1.122
diff -u -r1.122 MessageSend.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 26 Apr 2007 21:03:26 -0000 1.122
+++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 28 Jul 2007 11:22:00 -0000
@@ -55,6 +55,8 @@
public TypeReference[] typeArguments;
public TypeBinding[] genericTypeArguments;
+ private boolean isReturnValueNonNull = false;
+
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
boolean nonStatic = !this.binding.isStatic();
@@ -67,6 +69,11 @@
int length = this.arguments.length;
for (int i = 0; i < length; i++) {
flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+
+ if (arguments[i].nullStatus(flowInfo) != FlowInfo.NON_NULL
+ && isNonNullAnnotated(currentScope, binding.getParameterAnnotations(i))) {
+ currentScope.problemReporter().cannotPassPotentiallyNullExpressionAsArgument(binding, arguments[i]);
+ }
}
}
ReferenceBinding[] thrownExceptions;
@@ -254,6 +261,8 @@
}
}
public int nullStatus(FlowInfo flowInfo) {
+ if (isReturnValueNonNull)
+ return FlowInfo.NON_NULL;
return FlowInfo.UNKNOWN;
}
@@ -513,6 +522,10 @@
}
}
}
+
+ if (isNonNullAnnotated(scope, binding.getAnnotations()))
+ isReturnValueNonNull = true;
+
return this.resolvedType;
}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java,v
retrieving revision 1.61
diff -u -r1.61 MethodDeclaration.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java 17 Jul 2007 15:48:43 -0000 1.61
+++ compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java 28 Jul 2007 11:22:01 -0000
@@ -20,6 +20,8 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -67,6 +69,37 @@
if (binding.isAbstract() || binding.isNative())
return;
+ boolean[] argumentIsNonNull = null;
+ if (arguments != null)
+ argumentIsNonNull = new boolean[arguments.length];
+
+ ReferenceBinding declaringClassRef = binding.declaringClass;
+
+ if ((returnType.bits & TagBits.IsBaseType) == 0) {
+
+ ReferenceBinding type = isOverriddenMethodNonNullAnnotated(declaringClassRef, -1, classScope);
+ if (type != null && !isNonNullAnnotated(classScope, binding.getAnnotations()))
+ classScope.problemReporter().nonNullAnnotationIsMissingForOverridingMethod(type, binding, this);
+ }
+
+ if (arguments != null) {
+ for (int i = 0; i < arguments.length; i++) {
+ ReferenceBinding type = isOverriddenMethodNonNullAnnotated(declaringClassRef, i, classScope);
+ boolean argIsNonNull = isNonNullAnnotated(classScope, binding.getParameterAnnotations(i));
+ if (type != null && !argIsNonNull)
+ classScope.problemReporter().nonNullAnnotationIsMissingForArgumentInOverridingMethod(type, binding, arguments[i]);
+
+ argumentIsNonNull[i] = type != null || argIsNonNull;
+ }
+ }
+
+ if (argumentIsNonNull != null) {
+ for (int i = 0; i < argumentIsNonNull.length; i++) {
+ if (!argumentIsNonNull[i] && isNonNullAnnotated(classScope, binding.getParameterAnnotations(i)))
+ argumentIsNonNull[i] = true;
+ }
+ }
+
ExceptionHandlingFlowContext methodContext =
new ExceptionHandlingFlowContext(
initializationContext,
@@ -79,6 +112,8 @@
if (this.arguments != null) {
for (int i = 0, count = this.arguments.length; i < count; i++) {
flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
+ if (argumentIsNonNull[i])
+ flowInfo.markAsDefinitelyNonNull(this.arguments[i].binding);
}
}
// propagate to statements
@@ -111,6 +146,77 @@
}
}
+
+ /**
+ * Check all the overridden methods (super classes and interfaces)
+ * searching for NonNull annotation. Return the first type which
+ * contains an annotated overridden method.
+ *
+ * @param declaringClassRef the base type
+ * @param argument if positive, search annotations on parameters, else
+ * search on method
+ * @param classScope
+ * @return the type containing the overridden and annotated method
+ * or null
+ */
+ public ReferenceBinding isOverriddenMethodNonNullAnnotated(ReferenceBinding declaringClassRef, int argument, ClassScope classScope) {
+ if (declaringClassRef == null)
+ return null;
+
+ if (binding.isPrivate() || binding.isConstructor())
+ return null;
+
+ ReferenceBinding superClassRef = declaringClassRef.superclass();
+ if (superClassRef != null) {
+ MethodBinding mb = superClassRef.getExactMethod(selector, binding.parameters, classScope.compilationUnitScope());
+
+ if (mb != null) {
+ boolean nonNullAnnotated;
+ if (argument < 0)
+ nonNullAnnotated = isNonNullAnnotated(classScope, mb.getAnnotations());
+ else
+ nonNullAnnotated = isNonNullAnnotated(classScope, mb.getParameterAnnotations(argument));
+
+ // if an annotation is found, returns
+ if (nonNullAnnotated)
+ return superClassRef;
+ } else {
+ ReferenceBinding type = isOverriddenMethodNonNullAnnotated(superClassRef, argument, classScope);
+ if (type != null)
+ return type;
+ }
+ }
+
+ // if an overridden method have been found, but it was not annotated
+ // the check continues through the interfaces
+
+ ReferenceBinding[] superInterfacesRef = declaringClassRef.superInterfaces();
+ if (superInterfacesRef != null) {
+ for (int i = 0; i < superInterfacesRef.length; i++) {
+ if (superInterfacesRef[i] != null) {
+ MethodBinding mb = superInterfacesRef[i].getExactMethod(selector, binding.parameters, classScope.compilationUnitScope());
+
+ if (mb != null) {
+ boolean nonNullAnnotated;
+ if (argument < 0)
+ nonNullAnnotated = isNonNullAnnotated(classScope, mb.getAnnotations());
+ else
+ nonNullAnnotated = isNonNullAnnotated(classScope, mb.getParameterAnnotations(argument));
+
+ if (nonNullAnnotated)
+ return superInterfacesRef[i];
+ } else {
+ ReferenceBinding type = isOverriddenMethodNonNullAnnotated(superInterfacesRef[i], argument, classScope);
+ if (type != null)
+ return type;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
public boolean isMethod() {
return true;
Index: compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java,v
retrieving revision 1.59
diff -u -r1.59 ReturnStatement.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java 19 Jul 2007 14:05:58 -0000 1.59
+++ compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java 28 Jul 2007 11:22:02 -0000
@@ -37,6 +37,14 @@
if (this.expression != null) {
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
+
+ AbstractMethodDeclaration methodDecl = currentScope.methodScope().referenceMethod();
+ MethodBinding methodBinding = methodDecl.binding;
+
+ if ((methodBinding.returnType.tagBits & TagBits.IsBaseType) == 0
+ && expression.nullStatus(flowInfo) != FlowInfo.NON_NULL
+ && isNonNullAnnotated(currentScope, methodBinding.getAnnotations()))
+ currentScope.problemReporter().cannotReturnPotentiallyNullExpression(expression);
}
this.initStateIndex =
currentScope.methodScope().recordInitializationStates(flowInfo);
Index: compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java,v
retrieving revision 1.78
diff -u -r1.78 Assignment.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 6 Mar 2007 02:38:48 -0000 1.78
+++ compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java 28 Jul 2007 11:21:56 -0000
@@ -22,7 +22,8 @@
public Expression lhs;
public Expression expression;
-
+ private boolean isNonNull;
+
public Assignment(Expression lhs, Expression expression, int sourceEnd) {
//lhs is always a reference by construction ,
//but is build as an expression ==> the checkcast cannot fail
@@ -31,8 +32,10 @@
this.expression = expression;
this.sourceStart = lhs.sourceStart;
this.sourceEnd = sourceEnd;
+ this.isNonNull = false;
}
+
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
// record setting a variable: various scenarii are possible, setting an array reference,
// a field reference, a blank final field reference, a field of an enclosing instance or
@@ -44,6 +47,8 @@
flowContext.recordUsingNullReference(currentScope, local, this.lhs,
FlowContext.CAN_ONLY_NULL | FlowContext.IN_ASSIGNMENT, flowInfo);
}
+ if (isNonNull && nullStatus != FlowInfo.NON_NULL)
+ local.declaringScope.problemReporter().localCannotBeAssignedWithPotentiallyNull(local, expression);
}
flowInfo = ((Reference) lhs)
.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
@@ -57,7 +62,10 @@
flowInfo.markAsDefinitelyNonNull(local);
break;
default:
- flowInfo.markAsDefinitelyUnknown(local);
+ if (isNonNull)
+ flowInfo.markAsDefinitelyNonNull(local);
+ else
+ flowInfo.markAsDefinitelyUnknown(local);
}
if (flowContext.initsOnFinally != null) {
switch(nullStatus) {
@@ -68,7 +76,10 @@
flowContext.initsOnFinally.markAsDefinitelyNonNull(local);
break;
default:
- flowContext.initsOnFinally.markAsDefinitelyUnknown(local);
+ if (isNonNull)
+ flowContext.initsOnFinally.markAsDefinitelyNonNull(local);
+ else
+ flowContext.initsOnFinally.markAsDefinitelyUnknown(local);
}
}
}
@@ -146,6 +157,8 @@
}
public int nullStatus(FlowInfo flowInfo) {
+ if (isNonNull)
+ return FlowInfo.NON_NULL;
return this.expression.nullStatus(flowInfo);
}
@@ -192,6 +205,13 @@
scope.problemReporter().assignmentHasNoEffect(this, left.shortReadableName());
}
+ // check for NonNull annotation
+ LocalVariableBinding local = this.lhs.localVariableBinding();
+ if (local != null && local.kind() == Binding.LOCAL
+ && (local.type.tagBits & TagBits.IsBaseType) == 0) {
+ isNonNull = isNonNullAnnotated(scope, local.getAnnotations());
+ }
+
// Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
// may require to widen the rhs expression at runtime
if (lhsType != rhsType) // must call before computeConversion() and typeMismatchError()
Index: compiler/org/eclipse/jdt/core/compiler/IProblem.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java,v
retrieving revision 1.190
diff -u -r1.190 IProblem.java
--- compiler/org/eclipse/jdt/core/compiler/IProblem.java 11 Jul 2007 13:47:21 -0000 1.190
+++ compiler/org/eclipse/jdt/core/compiler/IProblem.java 28 Jul 2007 11:21:54 -0000
@@ -1275,4 +1275,11 @@
// associated with it
/** @since 3.2 */
int ExternalProblemFixable = 901;
+
+ int LocalCannotBeAssignedPotentiallyNull = Internal + 903;
+ int CannotPassPotentiallyNullExpressionAsArgument = Internal + 904;
+ int CannotReturnPotentiallyNullExpression = Internal + 905;
+ int NonNullAnnotationIsMissingForOverridingMethod = Internal + 906;
+ int NonNullAnnotationIsMissingForArgumentInOverridingMethod = Internal + 907;
+
}
Index: compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties,v
retrieving revision 1.221
diff -u -r1.221 messages.properties
--- compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 11 Jul 2007 13:40:49 -0000 1.221
+++ compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties 28 Jul 2007 11:22:25 -0000
@@ -587,3 +587,10 @@
857 = Incorrect number of type arguments for generic constructor <{3}>{0}({1}) of type {2}; it cannot be parameterized with arguments <{4}>
858 = The parameterized constructor <{3}>{0}({1}) of type {2} is not applicable for the arguments ({4})
859 = The constructor {0}({1}) of raw type {2} is no longer generic; it cannot be parameterized with arguments <{3}>
+
+### @NonNull annotation
+903 = Cannot assign null or potentially null expression to {0} because of @NonNull annotation
+904 = Cannot pass null or potentially null expression as argument for method {0} because of @NonNull annotation
+905 = Cannot return null or potentially null expression because of @NonNull annotation
+906 = Method {1} isn't NonNull annotated while overridden method in {0} is
+907 = Argument {2} in method {1} isn't NonNull annotated while overridden method in type {0} is
Index: compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java,v
retrieving revision 1.351
diff -u -r1.351 ProblemReporter.java
--- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 19 Jul 2007 14:07:25 -0000 1.351
+++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 28 Jul 2007 11:22:23 -0000
@@ -293,6 +293,13 @@
case IProblem.OverridingMethodWithoutSuperInvocation:
return CompilerOptions.OverridingMethodWithoutSuperInvocation;
+
+ case IProblem.LocalCannotBeAssignedPotentiallyNull:
+ case IProblem.CannotReturnPotentiallyNullExpression:
+ case IProblem.CannotPassPotentiallyNullExpressionAsArgument:
+ case IProblem.NonNullAnnotationIsMissingForOverridingMethod:
+ case IProblem.NonNullAnnotationIsMissingForArgumentInOverridingMethod:
+ return CompilerOptions.NullReference;
}
return 0;
}
@@ -4460,6 +4467,66 @@
nodeSourceStart(local, location),
nodeSourceEnd(local, location));
}
+public void localCannotBeAssignedWithPotentiallyNull(LocalVariableBinding local, ASTNode location) {
+ int severity = computeSeverity(IProblem.LocalCannotBeAssignedPotentiallyNull);
+ if (severity == ProblemSeverities.Ignore) return;
+ String[] arguments = new String[] { new String(local.name) };
+ this.handle(
+ IProblem.LocalCannotBeAssignedPotentiallyNull,
+ arguments,
+ arguments,
+ severity,
+ nodeSourceStart(local, location),
+ nodeSourceEnd(local, location));
+}
+public void cannotReturnPotentiallyNullExpression(ASTNode location) {
+ int severity = computeSeverity(IProblem.CannotReturnPotentiallyNullExpression);
+ if (severity == ProblemSeverities.Ignore) return;
+ String[] arguments = new String[] { };
+ this.handle(
+ IProblem.CannotReturnPotentiallyNullExpression,
+ arguments,
+ arguments,
+ severity,
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void nonNullAnnotationIsMissingForOverridingMethod(ReferenceBinding type, MethodBinding method, ASTNode location) {
+ int severity = computeSeverity(IProblem.NonNullAnnotationIsMissingForOverridingMethod);
+ if (severity == ProblemSeverities.Ignore) return;
+ String[] arguments = new String[] { new String(type.readableName()), new String(method.readableName()) };
+ this.handle(
+ IProblem.NonNullAnnotationIsMissingForOverridingMethod,
+ arguments,
+ arguments,
+ severity,
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void nonNullAnnotationIsMissingForArgumentInOverridingMethod(ReferenceBinding type, MethodBinding method, Argument arg) {
+ int severity = computeSeverity(IProblem.NonNullAnnotationIsMissingForArgumentInOverridingMethod);
+ if (severity == ProblemSeverities.Ignore) return;
+ String[] arguments = new String[] { new String(type.readableName()), new String(method.readableName()), new String(arg.name) };
+ this.handle(
+ IProblem.NonNullAnnotationIsMissingForArgumentInOverridingMethod,
+ arguments,
+ arguments,
+ severity,
+ arg.sourceStart,
+ arg.sourceEnd);
+}
+public void cannotPassPotentiallyNullExpressionAsArgument(MethodBinding method, ASTNode location) {
+ int severity = computeSeverity(IProblem.CannotPassPotentiallyNullExpressionAsArgument);
+ if (severity == ProblemSeverities.Ignore) return;
+ String[] arguments = new String[] { new String(method.readableName()) };
+ this.handle(
+ IProblem.CannotPassPotentiallyNullExpressionAsArgument,
+ arguments,
+ arguments,
+ severity,
+ nodeSourceStart(method, location),
+ nodeSourceEnd(method, location));
+}
public void localVariableNullComparedToNonNull(LocalVariableBinding local, ASTNode location) {
int severity = computeSeverity(IProblem.NullLocalVariableComparisonYieldsFalse);
if (severity == ProblemSeverities.Ignore) return;
Index: compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java,v
retrieving revision 1.184
diff -u -r1.184 CompilerOptions.java
--- compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 7 May 2007 17:01:22 -0000 1.184
+++ compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 28 Jul 2007 11:22:07 -0000
@@ -113,6 +113,7 @@
public static final String OPTION_ReportOverridingMethodWithoutSuperInvocation = "org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation"; //$NON-NLS-1$
public static final String OPTION_GenerateClassFiles = "org.eclipse.jdt.core.compiler.generateClassFiles"; //$NON-NLS-1$
public static final String OPTION_Process_Annotations = "org.eclipse.jdt.core.compiler.processAnnotations"; //$NON-NLS-1$
+ public static final String OPTION_NonNullAnnotations = "org.eclipse.jdt.core.compiler.nonNullAnnotations"; //$NON-NLS-1$
// Backward compatibility
public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$
@@ -199,7 +200,7 @@
public static final long OverridingMethodWithoutSuperInvocation = ASTNode.Bit50L;
public static final long PotentialNullReference = ASTNode.Bit51L;
public static final long RedundantNullCheck = ASTNode.Bit52L;
-
+
// Map: String optionKey --> Long irritant>
private static Map OptionToIrritants;
@@ -320,6 +321,9 @@
// Enable annotation processing by default only in batch mode
public boolean processAnnotations = false;
+ // annotations list for null checks (separator is ';')
+ public String nonNullAnnotations = "org.NonNull;edu.umd.cs.findbugs.annotations.NonNull"; //$NON-NLS-1$
+
/**
* Initializing the compiler options with defaults
*/
@@ -434,6 +438,7 @@
optionsMap.put(OPTION_ReportOverridingMethodWithoutSuperInvocation, getSeverityString(OverridingMethodWithoutSuperInvocation));
optionsMap.put(OPTION_GenerateClassFiles, this.generateClassFiles ? ENABLED : DISABLED);
optionsMap.put(OPTION_Process_Annotations, this.processAnnotations ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_NonNullAnnotations, this.nonNullAnnotations);
return optionsMap;
}
@@ -926,6 +931,9 @@
this.storeAnnotations = false;
}
}
+ if ((optionValue = optionsMap.get(OPTION_NonNullAnnotations)) != null) {
+ this.nonNullAnnotations = (String)optionValue;
+ }
}
public String toString() {
@@ -1010,6 +1018,7 @@
buf.append("\n\t- parameter assignment: ").append(getSeverityString(ParameterAssignment)); //$NON-NLS-1$
buf.append("\n\t- generate class files: ").append(this.generateClassFiles ? ENABLED : DISABLED); //$NON-NLS-1$
buf.append("\n\t- process annotations: ").append(this.processAnnotations ? ENABLED : DISABLED); //$NON-NLS-1$
+ buf.append("\n\t- non null annotations list (';'): ").append(this.nonNullAnnotations); //$NON-NLS-1$
return buf.toString();
}