unify diagnostics for different nodes, using the same "type mismatch" messages throughout

revert to previous strategy to call  bindArguments from resolveTypesFor:
+ now that annotations are no longer inherited, defaults must be applied first
  and we must have annotations of super methods evaluated from defaults 
  before doing the inheritance check.
+ include fillInDefaultNullness in bindArguments
+ also force-trigger type.getAnnotationTagBits() before bindArguments
  because only then we know if the type has a default annotation

Synthetic Annotations also need declarationSourceEnd (otherwise ASTConverter fails)

Started to update the quickfixes to the current implementation (Work in progress)
+ after unifying IProblems we will have to do more analysis on the AST
  to find out what correction to apply

Reorganized tests (extract better suitable runTestXYZ methods)
and update expected compiler messages
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java
index c5083a6..230aa89 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java
@@ -120,8 +120,8 @@
 				&& (local.tagBits & TagBits.AnnotationNonNull) != 0 
 				&& nullStatus != FlowInfo.NON_NULL)
 			{
-				currentScope.problemReporter().possiblyNullToNonNullLocal(local.name, getExpression(), nullStatus,
-						currentScope.environment().getNonNullAnnotationName());
+				currentScope.problemReporter().nullityMismatch(getExpression(), local.type,
+						nullStatus, currentScope.environment().getNonNullAnnotationName());
 				nullStatus=FlowInfo.NON_NULL;
 			}
 			return nullStatus;
@@ -174,7 +174,7 @@
 						if (methodBinding.parameterNonNullness[i].booleanValue()) // if @NonNull is required
 						{
 							char[][] annotationName = currentScope.environment().getNonNullAnnotationName();
-							currentScope.problemReporter().possiblyNullToNonNullParameter(arguments[i], nullStatus, annotationName[annotationName.length-1]);
+							currentScope.problemReporter().nullityMismatch(arguments[i], methodBinding.getParameters()[i], nullStatus, annotationName);
 						}
 					}
 				}
@@ -257,15 +257,16 @@
 				if (nullStatus != FlowInfo.NON_NULL) {
 					// if we can't prove non-null check against declared null-ness of the enclosing method:
 					long tagBits;
+					org.eclipse.jdt.internal.compiler.lookup.MethodBinding methodBinding;
 					try {
-						tagBits = currentScope.methodScope().referenceMethod().binding.tagBits;
+						methodBinding = currentScope.methodScope().referenceMethod().binding;
+						tagBits = methodBinding.tagBits;
 					} catch (NullPointerException npe) {
 						return;
 					}
 					if ((tagBits & TagBits.AnnotationNonNull) != 0) {
 						char[][] annotationName = currentScope.environment().getNonNullAnnotationName();
-						currentScope.problemReporter().possiblyNullFromNonNullMethod(this, nullStatus, 
-								annotationName[annotationName.length-1]);
+						currentScope.problemReporter().nullityMismatch(expression, methodBinding.returnType, nullStatus, annotationName);
 					}
 				}
 			}
@@ -311,20 +312,32 @@
 		Annotation[] getAnnotations()			-> get Annotation[] annotations;
 		void setAnnotations(Annotation[] annot)	-> set Annotation[] annotations;
 		MethodBinding getBinding() 				-> get MethodBinding binding;
-		void bindArguments()       				-> void bindArguments();
+		void doBindArguments()       			-> void bindArguments();
 		
 		
-		void resolveArgumentNullAnnotations() <- replace void bindArguments();
-
+		void guardedBindArguments() 			<- replace void bindArguments()
+//			base when (!isExecutingCallin())
+		;
 		@SuppressWarnings("basecall")
-		callin void resolveArgumentNullAnnotations() {
+		callin void guardedBindArguments() {
+			// See also comments #45, #49 and #75 in bug 186342
 			MethodBinding binding = getBinding();
 			if (binding != null) {
 				if ((binding.getTagBits() & TagBits.HasBoundArguments) != 0) // avoid double execution
 					return;
 				binding.addTagBit(TagBits.HasBoundArguments);
 			}
-			base.resolveArgumentNullAnnotations();
+			base.guardedBindArguments();
+		}
+		
+		public void bindArguments() {
+			MethodBinding binding = getBinding();
+			if (binding == null)
+				return;
+			if ((binding.getTagBits() & TagBits.HasBoundArguments) == 0) { // avoid double execution
+				doBindArguments();
+				binding.addTagBit(TagBits.HasBoundArguments);
+			}
 			Argument[] arguments = this.getArguments();
 			if (arguments != null && binding != null) {
 				for (int i = 0, length = arguments.length; i < length; i++) {
@@ -337,6 +350,11 @@
 					}
 				}
 			}
+			TypeBinding annotationBinding = findDefaultNullness(binding.getDeclaringSourceType(), getScope().environment());
+			if (annotationBinding != null) {
+				long defaultNullness = Constants.getNullnessTagbit(annotationBinding);
+				binding.fillInDefaultNullness(defaultNullness, annotationBinding);
+			}
 		}
 
 		/** Feed null status from parameter annotation into the analysis of the method's body. */
@@ -379,11 +397,12 @@
 		}
 
 		Annotation[] addAnnotation(ASTNode location, Annotation[] annotations, ReferenceBinding annotationBinding) {
-			int sourceStart = location.sourceStart();
-			long pos = ((long)sourceStart<<32) + location.sourceEnd();
+			int sourceStart = location.sourceStart;
+			long pos = ((long)sourceStart<<32) + location.sourceEnd;
 			long[] poss = new long[annotationBinding.compoundName.length];
 			Arrays.fill(poss, pos);
 			MarkerAnnotation annotation = new MarkerAnnotation(new QualifiedTypeReference(annotationBinding.compoundName, poss), sourceStart);
+			annotation.declarationSourceEnd = location.sourceEnd;
 			annotation.resolvedType = annotationBinding;
 			if (annotations == null) {
 				annotations = new Annotation[] {annotation};
@@ -403,6 +422,8 @@
 		public Boolean[] parameterNonNullness;  // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
 
 		ReferenceBinding getDeclaringClass() 	-> get ReferenceBinding declaringClass;
+		SourceTypeBinding getDeclaringSourceType()	-> get ReferenceBinding declaringClass
+			with { result 						<- (SourceTypeBinding)declaringClass }
 		TypeBinding[] getParameters() 			-> get TypeBinding[] parameters;
 		long getTagBits() 					 	-> get long tagBits;
 		public void addTagBit(long bit) 	 	-> set long tagBits 
@@ -455,10 +476,6 @@
 		<- after
 		void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods);
 
-		void bindMethodArguments() <- after void computeMethods();
-
-		void fillInDefaultNullness() <- before void checkMethods();
-		
 		void checkNullContractInheritance(MethodBinding currentMethod, MethodBinding[] methods, int length) {
 			// TODO: change traversal: process all methods at once!
 			for (int i = length; --i >= 0;)
@@ -470,16 +487,7 @@
 			long inheritedBits = inheritedMethod.getTagBits();
 			long currentBits = currentMethod.getTagBits();
 			LookupEnvironment environment = this.getEnvironment();
-			
-			if ((inheritedBits & TagBits.HasBoundArguments) == 0) {
-				ReferenceBinding supertype = inheritedMethod.getDeclaringClass();
-				if (!((ReferenceBinding) supertype.erasure()).isBinaryBinding()) {
-					AbstractMethodDeclaration sourceMethod = inheritedMethod.sourceMethod();
-					if (sourceMethod != null)
-						sourceMethod.bindArguments();
-				}
-			}
-			
+
 			// return type:
 			if ((inheritedBits & TagBits.AnnotationNonNull) != 0) {
 				long currentNullBits = currentBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable);
@@ -532,69 +540,43 @@
 				}
 			}
 		}
-
-		void bindMethodArguments() {
-			// binding the arguments is required for null contract checking, which needs argument annotations
-			AbstractMethodDeclaration[] methodDeclarations = getMethodDeclarations();
-			if (methodDeclarations != null)
-				for (AbstractMethodDeclaration methodDecl : methodDeclarations)
-					methodDecl.bindArguments();
+	}
+	TypeBinding findDefaultNullness(SourceTypeBinding type, LookupEnvironment environment) {
+		// find the applicable default inside->out:
+		
+		// type
+		SourceTypeBinding currentType = type;
+		TypeBinding annotationBinding = null;
+		while (currentType != null) {
+			annotationBinding = currentType.nullnessDefaultAnnotation;
+			if (annotationBinding != null)
+				return annotationBinding;
+			currentType = currentType.enclosingType();
 		}
 		
-		/** 
-		 * fill in missing annotations from a default setting from an enclosing scope.
-		 */
-		void fillInDefaultNullness() {
-			TypeBinding annotationBinding = findDefaultNullness();
-			// apply this default to all methods:
-			if (annotationBinding != null) {
-				long defaultNullness = Constants.getNullnessTagbit(annotationBinding);
-				MethodBinding[] methodBindings = getMethodBindings();
-				if (methodBindings != null) {
-					for (MethodBinding methodBinding : methodBindings)
-						methodBinding.fillInDefaultNullness(defaultNullness, annotationBinding);
-				}
-			}
-		}
-	
-		TypeBinding findDefaultNullness() {
-			// find the applicable default inside->out:
-
-			// type
-			SourceTypeBinding type = getType();
-			SourceTypeBinding currentType = type;
-			TypeBinding annotationBinding = null;
-			while (currentType != null) {
-				annotationBinding = currentType.nullnessDefaultAnnotation;
-				if (annotationBinding != null)
-					return annotationBinding;
-				currentType = currentType.enclosingType();
-			}
-			
-			// package
-			annotationBinding = type.getPackage().nullnessDefaultAnnotation;
+		// package
+		annotationBinding = type.getPackage().nullnessDefaultAnnotation;
+		if (annotationBinding != null)
+			return annotationBinding;
+		
+		// global
+		long defaultNullness = environment.getGlobalOptions().defaultNonNullness;
+		if (defaultNullness != 0) {
+			annotationBinding = environment.getNullAnnotationBinding(defaultNullness);
 			if (annotationBinding != null)
 				return annotationBinding;
 			
-			// global
-			long defaultNullness = getEnvironment().getGlobalOptions().defaultNonNullness;
-			if (defaultNullness != 0) {
-				annotationBinding = getEnvironment().getNullAnnotationBinding(defaultNullness);
-				if (annotationBinding != null)
-					return annotationBinding;
-				
-				// on this branch default was not defined using an annotation, thus annotation type can still be missing
-				if (defaultNullness == TagBits.AnnotationNonNull)
-					type.problemReporter().missingNullAnnotationType(getEnvironment().getNonNullAnnotationName());
-				else if (defaultNullness == TagBits.AnnotationNullable)
-					type.problemReporter().missingNullAnnotationType(getEnvironment().getNullableAnnotationName());
-				else
-					type.problemReporter().abortDueToInternalError("Illegal default nullness value: "+defaultNullness); //$NON-NLS-1$
-				// reset default to avoid duplicate errors:
-				getEnvironment().getGlobalOptions().defaultNonNullness = 0;
-			}
-			return null;
+			// on this branch default was not defined using an annotation, thus annotation type can still be missing
+			if (defaultNullness == TagBits.AnnotationNonNull)
+				type.problemReporter().missingNullAnnotationType(environment.getNonNullAnnotationName());
+			else if (defaultNullness == TagBits.AnnotationNullable)
+				type.problemReporter().missingNullAnnotationType(environment.getNullableAnnotationName());
+			else
+				type.problemReporter().abortDueToInternalError("Illegal default nullness value: "+defaultNullness); //$NON-NLS-1$
+			// reset default to avoid duplicate errors:
+			environment.getGlobalOptions().defaultNonNullness = 0;
 		}
+		return null;
 	}
 
 	@SuppressWarnings("bindingconventions")
@@ -614,6 +596,8 @@
 		SourceTypeBinding enclosingType() 	-> ReferenceBinding enclosingType()
 					with { result 			<- (SourceTypeBinding)result }
 		
+		void computeAnnotations()			-> long getAnnotationTagBits();
+		
 		protected TypeBinding nullnessDefaultAnnotation;
 
 		/** initialize a normal type */
@@ -623,6 +607,15 @@
 		evaluateNullAnnotations 			<- after initializeDeprecatedAnnotationTagBits
 			base when (CharOperation.equals(base.sourceName, TypeConstants.PACKAGE_INFO_NAME));
 
+		private void callBindArguments(MethodBinding method) {
+			if (method.getParameters() != Binding.NO_PARAMETERS) {
+				computeAnnotations();
+				AbstractMethodDeclaration methodDecl = method.sourceMethod();
+				methodDecl.bindArguments();
+			}			
+		}
+		void callBindArguments(MethodBinding method) <- after MethodBinding resolveTypesFor(MethodBinding method);
+		
 		@SuppressWarnings("inferredcallout")
 		void evaluateNullAnnotations() {
 			// transfer nullness info from tagBits to this.nullnessDefaultAnnotation 
@@ -921,20 +914,14 @@
 
 		private static int getIrritant(int problemID) {
 			switch(problemID) {
-				case IProblem.DefiniteNullFromNonNullMethod:
-				case IProblem.DefiniteNullToNonNullLocal:
-				case IProblem.DefiniteNullToNonNullParameter:
+				case IProblem.RequiredNonNullButProvidedNull:
 				case IProblem.IllegalReturnNullityRedefinition:
 				case IProblem.IllegalRedefinitionToNonNullParameter:
 				case IProblem.IllegalDefinitionToNonNullParameter:
 					return CompilerOptions.NullContractViolation;
-				case IProblem.PotentialNullFromNonNullMethod:
-				case IProblem.PotentialNullToNonNullLocal:
-				case IProblem.PotentialNullToNonNullParameter:
+				case IProblem.RequiredNonNullButProvidedPotentialNull:
 					return CompilerOptions.PotentialNullContractViolation;
-				case IProblem.NonNullLocalInsufficientInfo:
-				case IProblem.NonNullParameterInsufficientInfo:
-				case IProblem.NonNullReturnInsufficientInfo:
+				case IProblem.RequiredNonNullButProvidedUnknown:
 					return CompilerOptions.NullContractInsufficientInfo;
 				case IProblem.PotentialNullMessageSendReference:
 					return org.eclipse.jdt.internal.compiler.impl.CompilerOptions.PotentialNullReference;
@@ -944,51 +931,27 @@
 			return 0;
 		}
 	
-		public void possiblyNullFromNonNullMethod(ReturnStatement returnStatement, int nullStatus, char[] annotationName) {
-			int problemId = IProblem.NonNullReturnInsufficientInfo;
+		public void nullityMismatch(Expression expression, TypeBinding requiredType, int nullStatus, char[][] annotationName) {
+			int problemId = IProblem.RequiredNonNullButProvidedUnknown;
 			if ((nullStatus & FlowInfo.NULL) != 0)
-				problemId = IProblem.DefiniteNullFromNonNullMethod;
+				problemId = IProblem.RequiredNonNullButProvidedNull;
 			if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
-				problemId = IProblem.PotentialNullFromNonNullMethod;
-			String[] arguments = new String[] { String.valueOf(annotationName) };
-			this.handle(
-				problemId,
-				arguments,
-				arguments,
-				returnStatement.getSourceStart(),
-				returnStatement.getSourceEnd());
-		}
-		public void possiblyNullToNonNullLocal(char[] variableName, org.eclipse.jdt.internal.compiler.ast.Expression expression, int nullStatus, char[][] annotationName) {
-			int problemId = IProblem.NonNullLocalInsufficientInfo;
-			if ((nullStatus & FlowInfo.NULL) != 0)
-				problemId = IProblem.DefiniteNullToNonNullLocal;
-			else if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
-				problemId = IProblem.PotentialNullToNonNullLocal;
-			String[] arguments = new String[] {
-					String.valueOf(variableName),
-					String.valueOf(annotationName[annotationName.length-1]) 
+				problemId = IProblem.RequiredNonNullButProvidedPotentialNull;
+			String[] arguments = new String[] { 
+					String.valueOf(CharOperation.concatWith(annotationName, '.')),
+					String.valueOf(requiredType.readableName())
+			};
+			String[] argumentsShort = new String[] { 
+					String.valueOf(annotationName[annotationName.length-1]),
+					String.valueOf(requiredType.shortReadableName())
 			};
 			this.handle(
 				problemId,
 				arguments,
-				arguments,
+				argumentsShort,
 				expression.sourceStart,
 				expression.sourceEnd);
 		}
-		public void possiblyNullToNonNullParameter(org.eclipse.jdt.internal.compiler.ast.Expression argument, int nullStatus, char[] annotationName) {
-			int problemId = IProblem.NonNullParameterInsufficientInfo;
-			if ((nullStatus & FlowInfo.NULL) != 0)
-				problemId = IProblem.DefiniteNullToNonNullParameter;
-			else if ((nullStatus & FlowInfo.POTENTIALLY_NULL) != 0)
-				problemId = IProblem.PotentialNullToNonNullParameter;
-			String[] arguments = new String[] { String.valueOf(annotationName) };
-			this.handle(
-				problemId,
-				arguments,
-				arguments,
-				argument.sourceStart,
-				argument.sourceEnd);
-		}
 		public void illegalRedefinitionToNonNullParameter(Argument argument, ReferenceBinding declaringClass, char[][] inheritedAnnotationName) {
 			int sourceStart = argument.type.sourceStart;
 			if (argument.annotations != null) {
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/Constants.java b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/Constants.java
index 4e290f1..fa01ced 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/Constants.java
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/Constants.java
@@ -13,6 +13,7 @@
 import static org.eclipse.jdt.core.compiler.IProblem.ImportRelated;
 import static org.eclipse.jdt.core.compiler.IProblem.Internal;
 import static org.eclipse.jdt.core.compiler.IProblem.MethodRelated;
+import static org.eclipse.jdt.core.compiler.IProblem.TypeRelated;
 
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -41,37 +42,25 @@
 	/** Additional constants for {@link org.eclipse.jdt.core.compiler.IProblem}. */
 	public static interface IProblem {
 		/** @since 3.7 */
-		int DefiniteNullFromNonNullMethod = MethodRelated + 910;
+		int RequiredNonNullButProvidedNull = TypeRelated + 910;
 		/** @since 3.7 */
-		int PotentialNullFromNonNullMethod = MethodRelated + 911;
+		int RequiredNonNullButProvidedPotentialNull = TypeRelated + 911;
 		/** @since 3.7 */
-		int NonNullReturnInsufficientInfo = MethodRelated + 912;
+		int RequiredNonNullButProvidedUnknown = TypeRelated + 912;
 		/** @since 3.7 */
-		int DefiniteNullToNonNullParameter = MethodRelated + 913;
+		int MissingNullAnnotationType = ImportRelated + 913;
 		/** @since 3.7 */
-		int PotentialNullToNonNullParameter = MethodRelated + 914;
+		int IllegalReturnNullityRedefinition = MethodRelated + 914;
 		/** @since 3.7 */
-		int NonNullParameterInsufficientInfo = MethodRelated + 915;
+		int IllegalRedefinitionToNonNullParameter = MethodRelated + 915;
 		/** @since 3.7 */
-		int DefiniteNullToNonNullLocal = Internal + 916;
+		int IllegalDefinitionToNonNullParameter = MethodRelated + 916;
 		/** @since 3.7 */
-		int PotentialNullToNonNullLocal = Internal + 917;
+		int ParameterLackingNonNullAnnotation = MethodRelated + 917;
 		/** @since 3.7 */
-		int NonNullLocalInsufficientInfo = Internal + 918;
+		int PotentialNullMessageSendReference = Internal + 918;
 		/** @since 3.7 */
-		int MissingNullAnnotationType = ImportRelated + 919;
-		/** @since 3.7 */
-		int IllegalReturnNullityRedefinition = MethodRelated + 920;
-		/** @since 3.7 */
-		int IllegalRedefinitionToNonNullParameter = MethodRelated + 921;
-		/** @since 3.7 */
-		int IllegalDefinitionToNonNullParameter = MethodRelated + 922;
-		/** @since 3.7 */
-		int ParameterLackingNonNullAnnotation = 923;
-		/** @since 3.7 */
-		int PotentialNullMessageSendReference = Internal + 924;
-		/** @since 3.7 */
-		int RedundantNullCheckOnNonNullMessageSend = 925;
+		int RedundantNullCheckOnNonNullMessageSend = Internal + 919;
 	}
 	
 	/** Translate from a nullness annotation to the corresponding tag bit or 0L. */
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/problem_messages.properties b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/problem_messages.properties
index 4c5d473..83d86e2 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/problem_messages.properties
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/problem_messages.properties
@@ -11,19 +11,13 @@
 
 ### addition for /org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
 ### NULL ANNOTATIONS
-910 = Type mismatch: returning null from a method declared as @{0}
-911 = Type mismatch: return value can be null but method is declared as @{0}
-912 = Potential type mismatch: insufficient nullness information regarding return value while the method is declared as @{0}
-913 = Type mismatch: passing null to a parameter declared as @{0}
-914 = Type mismatch: potentially passing null to a parameter declared as @{0}
-915 = Potential type mismatch: insufficient nullness information regarding a value that is passed to a parameter declared as @{0}
-916 = Type mismatch: assigning null to local variable {0}, which is declared as @{1}
-917 = Type mismatch: potentially assigning null to local variable {0}, which is declared as @{1}
-918 = Potential type mismatch: insufficient nullness information regarding a value that is assigned to local variable {0}, which is declared as @{1}
-919 = Buildpath problem: the type {0} which is configured as a null annotation type cannot be resolved
-920 = The return type is incompatible with the @{1} return from {0}
-921 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2}
-922 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter
-923 = Missing null annotation: inherited method from {1} declares this parameter as @{2}
-924 = Potential null pointer access: The method {0} may return null
-925 = Redundant null check: The method {0} cannot return null
+910 = Type mismatch: required '@{0} {1}' but the provided value is null
+911 = Type mismatch: required '@{0} {1}' but the provided value can be null
+912 = Potential type mismatch: required '@{0} {1}' but nullness of the provided value is unknown
+913 = Buildpath problem: the type {0} which is configured as a null annotation type cannot be resolved
+914 = The return type is incompatible with the @{1} return from {0}
+915 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2}
+916 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter
+917 = Missing null annotation: inherited method from {1} declares this parameter as @{2}
+918 = Potential null pointer access: The method {0} may return null
+919 = Redundant null check: The method {0} cannot return null
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.java b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.java
index 2214cdf..8a1e38a 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.java
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.java
@@ -21,7 +21,7 @@
 	
 	public static String QuickFixes_add_annotation_change_name;
 	
-	public static String QuickFixes_declare_method_parameter_nullable;
+	public static String QuickFixes_declare_method_parameter_nullness;
 
 	public static String QuickFixes_declare_method_return_nullable;
 
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.properties b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.properties
index f3c575a..cc36be8 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.properties
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/FixMessages.properties
@@ -1,7 +1,7 @@
 NullAnnotationsCleanUp_add_nullable_annotation=Add missing @Nullable annotation
 NullAnnotationsCleanUp_add_nonnull_annotation=Add missing @NonNull annotation
 QuickFixes_add_annotation_change_name=Add Annotations
-QuickFixes_declare_method_parameter_nullable=Declare method parameter as @{0}
+QuickFixes_declare_method_parameter_nullness=Declare method parameter as @{0}
 QuickFixes_declare_method_return_nullable=Declare method return as @{0}
 QuickFixes_declare_overridden_parameter_as_nonnull=Adjust overridden method from {1}, mark parameter as @{0}
 QuickFixes_declare_overridden_return_as_nullable=Adjust overridden method from {1}, mark as returning @{0}
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/NullAnnotationsCleanUp.java b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/NullAnnotationsCleanUp.java
index f71e1d4..d20aaa4 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/NullAnnotationsCleanUp.java
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/NullAnnotationsCleanUp.java
@@ -70,12 +70,16 @@
 	protected ICleanUpFix createFix(CompilationUnit compilationUnit, IProblemLocation[] problems) throws CoreException {
 		if (compilationUnit == null)
 			return null;
+		IProblemLocation[] locations = null;
 		ArrayList<IProblemLocation> filteredLocations = new ArrayList<IProblemLocation>();
-		for (int i = 0; i < problems.length; i++) {
-			if (problems[i].getProblemId() == this.handledProblemID)
-				filteredLocations.add(problems[i]);
+		if (problems != null) {
+			for (int i = 0; i < problems.length; i++) {
+				if (problems[i].getProblemId() == this.handledProblemID)
+					filteredLocations.add(problems[i]);
+			}
+			locations = filteredLocations.toArray(new IProblemLocation[filteredLocations.size()]);
 		}
-		return this.master.createCleanUp(compilationUnit, filteredLocations.toArray(new IProblemLocation[filteredLocations.size()]), this.handledProblemID);
+		return this.master.createCleanUp(compilationUnit, locations, this.handledProblemID);
 	}
 
 	private Map getRequiredOptions() {
@@ -92,15 +96,16 @@
 	public String[] getStepDescriptions() {
 		List result= new ArrayList();
 		switch (this.handledProblemID) {
-		case DefiniteNullToNonNullParameter:
 		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
 		case IProblem.RedundantNullCheckOnNonNullLocalVariable:
-		case DefiniteNullFromNonNullMethod:
-		case PotentialNullFromNonNullMethod:
+		case RequiredNonNullButProvidedNull:
+		case RequiredNonNullButProvidedPotentialNull:
+		case RequiredNonNullButProvidedUnknown:
 			result.add(FixMessages.NullAnnotationsCleanUp_add_nullable_annotation);
 			break;
 		case IllegalDefinitionToNonNullParameter:
 		case IllegalRedefinitionToNonNullParameter:
+		case ParameterLackingNonNullAnnotation:
 			result.add(FixMessages.NullAnnotationsCleanUp_add_nonnull_annotation);
 			break;	
 		}
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/QuickFixes.java b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/QuickFixes.java
index 8035891..08a4324 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/QuickFixes.java
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/QuickFixes.java
@@ -10,13 +10,13 @@
  *******************************************************************************/
 package org.eclipse.objectteams.internal.jdt.nullity.quickfix;
 
-import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.DefiniteNullFromNonNullMethod;
-import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.DefiniteNullToNonNullParameter;
+import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.RequiredNonNullButProvidedNull;
+import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.RequiredNonNullButProvidedPotentialNull;
+import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.RequiredNonNullButProvidedUnknown;
 import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.IllegalDefinitionToNonNullParameter;
 import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.IllegalRedefinitionToNonNullParameter;
 import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.IllegalReturnNullityRedefinition;
-import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.PotentialNullFromNonNullMethod;
-import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.PotentialNullToNonNullParameter;
+import static org.eclipse.objectteams.internal.jdt.nullity.Constants.IProblem.ParameterLackingNonNullAnnotation;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -68,11 +68,13 @@
 
 	public boolean hasCorrections(ICompilationUnit cu, int problemId) {
 		switch (problemId) {
-		case DefiniteNullFromNonNullMethod:
-		case PotentialNullFromNonNullMethod:
-		case DefiniteNullToNonNullParameter:
-		case PotentialNullToNonNullParameter:
+		case RequiredNonNullButProvidedNull:
+		case RequiredNonNullButProvidedPotentialNull:
+		case RequiredNonNullButProvidedUnknown:
 		case IllegalReturnNullityRedefinition:
+		case IllegalRedefinitionToNonNullParameter:
+		case IllegalDefinitionToNonNullParameter:
+		case ParameterLackingNonNullAnnotation:
 		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
 		case IProblem.RedundantNullCheckOnNonNullLocalVariable:
 				return true;
@@ -106,19 +108,23 @@
 		if (id == 0) { // no proposals for none-problem locations
 			return;
 		}
+		CompilationUnit astRoot= context.getASTRoot();
+		ASTNode selectedNode= problem.getCoveringNode(astRoot);
+
 		switch (id) {
-		case DefiniteNullFromNonNullMethod:
-		case PotentialNullFromNonNullMethod:
-		case DefiniteNullToNonNullParameter:
-		case PotentialNullToNonNullParameter:
 		case IllegalReturnNullityRedefinition:
 		case IllegalDefinitionToNonNullParameter:
 		case IllegalRedefinitionToNonNullParameter:
+		case ParameterLackingNonNullAnnotation:
 			addNullAnnotationInSignatureProposal(context, problem, proposals);
 			break;
+		case RequiredNonNullButProvidedNull:
+		case RequiredNonNullButProvidedPotentialNull:
+		case RequiredNonNullButProvidedUnknown:
 		case IProblem.NonNullLocalVariableComparisonYieldsFalse:
 		case IProblem.RedundantNullCheckOnNonNullLocalVariable:
-			if (isComplainingAboutArgument(context, problem))
+			if (isComplainingAboutArgument(selectedNode)
+				|| isComplainingAboutReturn(selectedNode))
 				addNullAnnotationInSignatureProposal(context, problem, proposals);
 			break;
 		}
@@ -163,11 +169,7 @@
 		}		
 	}
 	
-	boolean isComplainingAboutArgument(IInvocationContext context, IProblemLocation problem) {
-
-		CompilationUnit astRoot= context.getASTRoot();
-		ASTNode selectedNode= problem.getCoveringNode(astRoot);
-
+	boolean isComplainingAboutArgument(ASTNode selectedNode) {
 		if (!(selectedNode instanceof SimpleName)) {
 			return false;
 		}
@@ -177,6 +179,10 @@
 			return true;
 		return false;
 	}
+	
+	boolean isComplainingAboutReturn(ASTNode selectedNode) {
+		return selectedNode.getParent().getNodeType() == ASTNode.RETURN_STATEMENT;
+	}
 
 	MyCURewriteOperationsFix createNullAnnotationInSignatureFix(CompilationUnit compilationUnit, IProblemLocation problem)
 	{
@@ -188,6 +194,7 @@
 		switch (problem.getProblemId()) {
 		case IllegalDefinitionToNonNullParameter:
 		case IllegalRedefinitionToNonNullParameter:
+		case ParameterLackingNonNullAnnotation:
 			annotationToAdd = nonNullAnnotationName;
 			annotationToRemove = nullableAnnotationName;
 			break;
@@ -247,8 +254,10 @@
 			switch (problem.getProblemId()) {
 			case IllegalDefinitionToNonNullParameter:
 			case IllegalRedefinitionToNonNullParameter:
+			case ParameterLackingNonNullAnnotation:
 				annotationToAdd = nonNullAnnotationName;
 				annotationToRemove = nullableAnnotationName;
+				// all others propose to add @Nullable
 			}
 			// when performing multiple changes we can only modify the one CU that the CleanUp infrastructure provides to the operation.
 			CompilationUnitRewriteOperation fix = RewriteOperations.createAddAnnotationOperation(
@@ -259,8 +268,7 @@
 	}
 	
 	public static boolean isMissingNullAnnotationProblem(int id) {
-		return id == DefiniteNullFromNonNullMethod || id == PotentialNullFromNonNullMethod 
-				|| id == DefiniteNullToNonNullParameter || id == PotentialNullToNonNullParameter
+		return id == RequiredNonNullButProvidedNull || id == RequiredNonNullButProvidedPotentialNull 
 				|| id == IllegalReturnNullityRedefinition
 				|| mayIndicateParameterNullcheck(id);
 	}
diff --git a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/RewriteOperations.java b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/RewriteOperations.java
index 4dd2d3d..ede2791 100644
--- a/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/RewriteOperations.java
+++ b/contrib/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/quickfix/RewriteOperations.java
@@ -33,6 +33,7 @@
 import org.eclipse.jdt.core.dom.MethodInvocation;
 import org.eclipse.jdt.core.dom.SimpleName;
 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclaration;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
@@ -217,11 +218,9 @@
 			return null;
 				
 		switch (problem.getProblemId()) {
-		case DefiniteNullToNonNullParameter:
-		case PotentialNullToNonNullParameter:
-		case IllegalReturnNullityRedefinition:
+//		case IllegalReturnNullityRedefinition:
 		case IllegalDefinitionToNonNullParameter:
-		case IllegalRedefinitionToNonNullParameter:
+//		case IllegalRedefinitionToNonNullParameter:
 			// these affect another method
 			break;
 		default:
@@ -256,7 +255,7 @@
 			ASTNode methodDecl = compilationUnit.findDeclaringNode(methodBinding.getKey());
 			if (methodDecl == null)
 				return null;
-			message = Messages.format(FixMessages.QuickFixes_declare_method_parameter_nullable, annotationNameLabel);
+			message = Messages.format(FixMessages.QuickFixes_declare_method_parameter_nullness, annotationNameLabel);
 			result = new ParameterAnnotationRewriteOperation(compilationUnit,
 														     (MethodDeclaration) methodDecl,
 														     annotationToAdd,
@@ -271,20 +270,21 @@
 			MethodDeclaration declaration= (MethodDeclaration) declaringNode;
 			
 			switch (problem.getProblemId()) {
+				case ParameterLackingNonNullAnnotation:
 				case IProblem.NonNullLocalVariableComparisonYieldsFalse:
 				case IProblem.RedundantNullCheckOnNonNullLocalVariable:
 					// statements suggest changing parameters:
-					if (selectedNode.getNodeType() == ASTNode.SIMPLE_NAME && declaration.getNodeType() == ASTNode.METHOD_DECLARATION) {
-						IBinding binding = ((SimpleName)selectedNode).resolveBinding();
-						if (binding.getKind() == IBinding.VARIABLE && ((IVariableBinding)binding).isParameter()) {
-							message = Messages.format(FixMessages.QuickFixes_declare_method_parameter_nullable, annotationNameLabel);
+					if (declaration.getNodeType() == ASTNode.METHOD_DECLARATION) {
+						String paramName = findAffectedParameterName(selectedNode);
+						if (paramName != null) {
+							message = Messages.format(FixMessages.QuickFixes_declare_method_parameter_nullness, annotationNameLabel);
 							result = new ParameterAnnotationRewriteOperation(compilationUnit,
-																							   declaration,
-																							   annotationToAdd,
-																							   annotationToRemove,
-																							   ((SimpleName) selectedNode).getIdentifier(),
-																							   allowRemove,
-																							   message);
+																		   declaration,
+																		   annotationToAdd,
+																		   annotationToRemove,
+																		   paramName,
+																		   allowRemove,
+																		   message);
 						}
 					}
 					break;
@@ -293,12 +293,13 @@
 					result = createChangeOverriddenParameterOperation(compilationUnit, cu, declaration, selectedNode, allowRemove,
 																	  annotationToAdd, annotationToRemove, annotationNameLabel);
 					break;
-				case IllegalReturnNullityRedefinition:
-					result = createChangeOverriddenReturnOperation(compilationUnit, cu, declaration, allowRemove,
-																   annotationToAdd, annotationToRemove, annotationNameLabel);
-					break;
-				case DefiniteNullFromNonNullMethod:
-				case PotentialNullFromNonNullMethod:
+// TODO: how do we know which method to change (this or super)?
+//				case IllegalReturnNullityRedefinition:
+//					result = createChangeOverriddenReturnOperation(compilationUnit, cu, declaration, allowRemove,
+//																   annotationToAdd, annotationToRemove, annotationNameLabel);
+//					break;
+				case RequiredNonNullButProvidedNull:
+				case RequiredNonNullButProvidedPotentialNull:
 					message = Messages.format(FixMessages.QuickFixes_declare_method_return_nullable, annotationNameLabel);
 					result = new ReturnAnnotationRewriteOperation(compilationUnit,
 																				    declaration,
@@ -348,15 +349,28 @@
 									annotationNameLabel,
 									BasicElementLabels.getJavaElementName(overridden.getDeclaringClass().getName())
 								  });
+		String paramName = findAffectedParameterName(selectedNode);
 		result = new ParameterAnnotationRewriteOperation(compilationUnit,
 													     declaration,
 													     annotationToAdd,
 													     annotationToRemove,
-													     ((SimpleName) selectedNode).getIdentifier(),
+													     paramName,
 													     allowRemove,
 													     message);
 		return result;
 	}
+	
+	static String findAffectedParameterName(ASTNode selectedNode) {
+		VariableDeclaration argDecl = (VariableDeclaration) ASTNodes.getParent(selectedNode, VariableDeclaration.class);
+		if (argDecl != null)
+			return argDecl.getName().getIdentifier();
+		if (selectedNode.getNodeType() == ASTNode.SIMPLE_NAME) {
+			IBinding binding = ((SimpleName)selectedNode).resolveBinding();
+			if (binding.getKind() == IBinding.VARIABLE && ((IVariableBinding)binding).isParameter())
+				return ((SimpleName)selectedNode).getIdentifier();
+		}
+		return null;
+	}
 
 	static SignatureAnnotationRewriteOperation createChangeOverriddenReturnOperation(CompilationUnit compilationUnit,
 																					 ICompilationUnit cu,