+ added checking for ctor args
+ refactoring towards the OO variant (regarding FlowContext)
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 6e84e31..18c076f 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
@@ -68,6 +68,7 @@
 import static org.eclipse.objectteams.internal.jdt.nullity.Constants.TypeIds;
 
 import base org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import base org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
 import base org.eclipse.jdt.internal.compiler.ast.Assignment;
 import base org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import base org.eclipse.jdt.internal.compiler.ast.EqualExpression;
@@ -136,8 +137,8 @@
 				&& (local.tagBits & TagBits.AnnotationNonNull) != 0 
 				&& nullStatus != FlowInfo.NON_NULL)
 			{
-				recordNullityMismatch(currentScope, flowContext, getExpression(), local.type, 
-						nullStatus, currentScope.environment().getNonNullAnnotationName());
+				recordNullityMismatch0(flowContext, currentScope, getExpression(), nullStatus, 
+						local.type, ConditionalFlowContext.ASSIGN_TO_NONNULL);
 				nullStatus=FlowInfo.NON_NULL;
 			}
 			return nullStatus;
@@ -157,6 +158,7 @@
 		<- before FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
 	}
 	
+	/** Abstraction over o.m(a), this(a), super(a), new C(a), t.new C(a). */
 	protected abstract class MessageSendish {
 		
 		protected abstract Expression[] getArguments();
@@ -167,48 +169,19 @@
 			MethodBinding methodBinding = getBinding();
 			Expression[] arguments = getArguments();
 			if (arguments != null && methodBinding.parameterNonNullness != null) {
-				char[][] annotationName = currentScope.environment().getNonNullAnnotationName();
 				for (int i = 0; i < arguments.length; i++) {
 					if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) { 
 						TypeBinding expectedType = methodBinding.getParameters()[i];
 						Expression argument = arguments[i];
 						int nullStatus = argument.nullStatus(flowInfo); // slight loss of precision: should also use the null info from the receiver.
 						if (nullStatus != FlowInfo.NON_NULL) // if required non-null is not provided
-							recordNullityMismatch(currentScope, flowContext, argument, expectedType, nullStatus, annotationName);
+							recordNullityMismatch0(flowContext, currentScope, argument, nullStatus, expectedType, ConditionalFlowContext.ASSIGN_TO_NONNULL);
 					}
 				}
 			}
 		}
 	}
-	
-	void recordNullityMismatch(BlockScope currentScope, FlowContext flowContext, Expression expression, TypeBinding expectedType, int nullStatus, char[][] annotationName) {
-		if (expression.localVariableBinding() != null) { // flowContext cannot yet handle non-localvar expressions (e.g., fields)
-			while (flowContext != null) {
-				// some flow contexts implement deferred checking, should we participate in that?
-				if (flowContext instanceof org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext) {
-					// cf. decision structure inside FinallyFlowContext.recordUsingNullReference(..)
-					if (nullStatus == FlowInfo.UNKNOWN ||
-							((flowContext.tagBits & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0 && nullStatus != FlowInfo.NULL)) 
-					{
-						// deferred reporting
-						recordNullReference((org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext)flowContext,
-									expression, expectedType, ConditionalFlowContext.ASSIGN_TO_NONNULL);										
-						return;
-					}
-				}
-				else if (flowContext instanceof org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext) {
-					// deferred reporting
-					recordNullReference((org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext)flowContext,
-								expression, expectedType, ConditionalFlowContext.ASSIGN_TO_NONNULL);
-					return;
-				}
-				flowContext = flowContext.parent;
-			}
-		}			
-		// other cases report immediately
-		currentScope.problemReporter().nullityMismatch(expression, expectedType, nullStatus, annotationName);
-	}
-	
+
 	/** Analyse argument expressions as part of a MessageSend, check against method parameter annotation. */
 	@Instantiation(InstantiationPolicy.ALWAYS)
 	protected class MessageSend extends MessageSendish playedBy MessageSend {
@@ -249,6 +222,7 @@
 			return FlowInfo.UNKNOWN;
 		}
 	}
+
 	protected class ExplicitConstructorCall extends MessageSendish playedBy ExplicitConstructorCall {
 
 		Expression[] getArguments() -> get Expression[] arguments;
@@ -259,6 +233,17 @@
 		<- after FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
 
 	}
+
+	protected class AllocationExpression extends MessageSendish playedBy AllocationExpression {
+
+		Expression[] getArguments() -> get Expression[] arguments;
+		MethodBinding getBinding() -> get MethodBinding binding;
+		
+		// Note: this also applies to QualifiedAllocationExpression
+		void analyseArguments(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) 
+		<- after FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
+
+	}
 	
 	@Instantiation(InstantiationPolicy.ALWAYS)
 	protected class EqualExpression playedBy EqualExpression {
@@ -1056,11 +1041,37 @@
 
 	// ---- Handling sub-classes of FlowContext that perform deferred null checking: ----
 	
-	public <B base ConditionalFlowContext> void recordNullReference(B as ConditionalFlowContext flowContext,
-							Expression expression, TypeBinding expectedType, int checkType) 
+	void recordNullityMismatch0(FlowContext flowContext, BlockScope currentScope, Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
+		// std. impl to go into class FlowContext:
+		if (expression.localVariableBinding() != null) { // flowContext cannot yet handle non-localvar expressions (e.g., fields)
+			// find the inner-most flowContext that might need deferred handling:
+			while (flowContext != null) {
+				// some flow contexts implement deferred checking, should we participate in that?
+				if (flowContext instanceof org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext) {
+					// deferred reporting?
+					if (recordNullityMismatch1((org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext)flowContext,
+								currentScope, expression, nullStatus, expectedType, ConditionalFlowContext.ASSIGN_TO_NONNULL))										
+					return;
+				}
+				else if (flowContext instanceof org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext) {
+					// deferred reporting
+					if (recordNullityMismatch1((org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext)flowContext,
+								currentScope, expression, nullStatus, expectedType, ConditionalFlowContext.ASSIGN_TO_NONNULL))
+					return;
+				}
+				flowContext = flowContext.parent;
+			}
+		}			
+		// no reason to defer, so report now:
+		char[][] annotationName = currentScope.environment().getNonNullAnnotationName();
+		currentScope.problemReporter().nullityMismatch(expression, expectedType, nullStatus, annotationName);
+		// Note: in the plain Java impl, all remaining FlowContext classes must handle ASSIGN_TO_NULL by directly calling this problemReporter method.
+	}
+	
+	<B base ConditionalFlowContext> boolean recordNullityMismatch1(B as ConditionalFlowContext flowContext,
+							BlockScope scope, Expression expression, int nullStatus, TypeBinding expectedType, int checkType) 
 	{
-		flowContext.recordExpectedType(expectedType);
-		flowContext.recordNullReference(expression.localVariableBinding(), expression, checkType);
+		return flowContext.recordNullityMismatch2(expression, nullStatus, expectedType, checkType);
 	}
 	protected abstract class ConditionalFlowContext {
 		// new constant for checkTypes:
@@ -1102,19 +1113,13 @@
 		void complainOnNullTypeError(BlockScope scope, FlowInfo callerFlowInfo) {
 			FlowInfo flowInfo = getFlowInfo(callerFlowInfo);
 			if ((getTagBits() & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0) {
+				LocalVariableBinding[] locals = getNullLocals();
 				for (int i = 0; i < getNullCount(); i++) {
 					int nullCheckType = getNullCheckTypes()[i];
 					if (nullCheckType == ASSIGN_TO_NONNULL) {
 						FlowContext parent = getParent();
-						if (parent instanceof org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext) {
-							CompilerAdaptation.this.recordNullReference((org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext)parent, 
-									getNullReferences()[i], this.expectedTypes[i], nullCheckType);
-							continue;
-						} else if (parent instanceof org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext) {
-							CompilerAdaptation.this.recordNullReference((org.eclipse.jdt.internal.compiler.flow.FinallyFlowContext)parent, 
-									getNullReferences()[i], this.expectedTypes[i], nullCheckType);
-							continue;
-						}
+						CompilerAdaptation.this.recordNullityMismatch0(parent, 
+								scope, getNullReferences()[i], flowInfo.nullStatus(locals[i]), this.expectedTypes[i], nullCheckType);
 					} else {
 						getParent().recordUsingNullReference(scope, getNullLocals()[i],
 								getNullReferences()[i],	nullCheckType, flowInfo);
@@ -1136,6 +1141,7 @@
 				}
 			}
 		}
+		protected abstract boolean recordNullityMismatch2(Expression expression, int nullStatus, TypeBinding expectedType, int checkType);
 	}
 	/** Straight-forward binding of implementation role to concrete base class. */
 	protected class FinallyFlowContext extends ConditionalFlowContext playedBy FinallyFlowContext {
@@ -1155,6 +1161,17 @@
 		void complainOnNullTypeError(BlockScope scope, FlowInfo callerFlowInfo)
 		<- after void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope)
 			with { scope <- scope, callerFlowInfo <- flowInfo }
+		
+		protected boolean recordNullityMismatch2(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
+			// cf. decision structure inside FinallyFlowContext.recordUsingNullReference(..)
+			if (nullStatus == FlowInfo.UNKNOWN ||
+					((getTagBits() & FlowContext.DEFER_NULL_DIAGNOSTIC) != 0 && nullStatus != FlowInfo.NULL)) {
+				recordExpectedType(expectedType);
+				recordNullReference(expression.localVariableBinding(), expression, checkType);
+				return true;
+			}
+			return false;
+		}
 	}
 	/** Straight-forward binding of implementation role to concrete base class. */
 	protected class LoopingFlowContext extends ConditionalFlowContext playedBy LoopingFlowContext {
@@ -1178,6 +1195,12 @@
 		
 		// here the recorded data is evaluated:
 		complainOnNullTypeError <- after complainOnDeferredNullChecks;
+
+		protected boolean recordNullityMismatch2(Expression expression, int nullStatus, TypeBinding expectedType, int checkType) {
+			recordExpectedType(expectedType);
+			recordNullReference(expression.localVariableBinding(), expression, checkType);
+			return true;
+		}
 	}
 
 	// ======================= Problem reporting ==================================