- implement general preference org.eclipse.jdt.core.compiler.annotation.nulldefault
  - apply its value in fillInNullNessDefault()
- temporary tweak: don't complain against tightening contract inherited 
  from binary type (disabled)
- fix issue with compile order where bindArguments of super type 
  was not done before verifyMethods
TODO: check if transitive inheritance of annotations and defaults play well together
 regarding compile order.
diff --git a/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java b/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java
index d5f5bc9..8bd42dc 100644
--- a/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java
+++ b/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/CompilerAdaptation.java
@@ -177,7 +177,8 @@
 		int getSourceStart() 		-> get int sourceStart;
 		int getSourceEnd() 			-> get int sourceEnd;
 		
-		void analyseNull(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) <- after FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
+		void analyseNull(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) 
+		<- after FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
 
 		void analyseNull(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 			Expression expression = getExpression();
@@ -226,6 +227,7 @@
 	
 	protected class AbstractMethodDeclaration playedBy AbstractMethodDeclaration {
 
+		BlockScope getScope()      -> get MethodScope scope;
 		Argument[] getArguments()  -> get Argument[] arguments;
 		MethodBinding getBinding() -> get MethodBinding binding;
 		void bindArguments()       -> void bindArguments();
@@ -262,15 +264,18 @@
 			with { info <- info }
 
 		private void analyseArgumentNullity(FlowInfo info) {
+			MethodBinding binding = getBinding();
 			Argument[] arguments = this.getArguments();
-			if (arguments != null) {
+			if (arguments != null && binding.parameterNonNullness != null) {
 				for (int i = 0, count = arguments.length; i < count; i++) {
 					// leverage null-info from parameter annotations:
-					long argumentTagBits = arguments[i].binding.tagBits;
-					if ((argumentTagBits & TagBits.AnnotationNullable) != 0)
-						info.markPotentiallyNullBit(arguments[i].binding);
-					else if ((argumentTagBits & TagBits.AnnotationNonNull) != 0)
-						info.markAsDefinitelyNonNull(arguments[i].binding);
+					Boolean nonNullNess = binding.parameterNonNullness[i];
+					if (nonNullNess != null) {
+						if (nonNullNess)
+							info.markAsDefinitelyNonNull(arguments[i].binding);
+						else
+							info.markPotentiallyNullBit(arguments[i].binding);
+					}
 				}
 			}
 		}
@@ -291,6 +296,19 @@
 		boolean isStatic() 						-> boolean isStatic();
 		boolean isValidBinding() 				-> boolean isValidBinding();
 		AbstractMethodDeclaration sourceMethod()-> AbstractMethodDeclaration sourceMethod();
+
+		/** After method verifier has finished, fill in missing nullness values from the default. */
+		protected void fillInDefaultNullness(long defaultNullness) {
+			if (this.parameterNonNullness == null)
+				this.parameterNonNullness = new Boolean[getParameters().length];
+			Boolean value = Boolean.valueOf(defaultNullness == TagBits.AnnotationNonNull);
+			for (int i = 0; i < this.parameterNonNullness.length; i++) {
+				if (this.parameterNonNullness[i] == null)
+					this.parameterNonNullness[i] = value;
+			}
+			if ((getTagBits() & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
+				addTagBit(defaultNullness);
+		}
 	}
 
 	/** Transfer inherited null contracts and check compatibility. */
@@ -302,6 +320,8 @@
 				with  {  result 			<- type.scope.problemReporter() }
 		AbstractMethodDeclaration[] getMethodDeclarations() -> get SourceTypeBinding type
 				with { 	result 				<- type.scope.referenceContext.methods }
+		MethodBinding[] getMethodBindings() -> get SourceTypeBinding type
+				with { 	result 				<- type.methods() }
 
 		
 		void checkNullContractInheritance(MethodBinding currentMethod, MethodBinding[] methods, int length)
@@ -310,7 +330,7 @@
 
 		void bindMethodArguments() <- after void computeMethods();
 
-		
+		void fillInDefaultNullNess() <- after void checkMethods();
 		
 		void checkNullContractInheritance(MethodBinding currentMethod, MethodBinding[] methods, int length) {
 			for (int i = length; --i >= 0;)
@@ -323,6 +343,15 @@
 			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) {
 				if ((currentBits & TagBits.AnnotationNullable) != 0) {
@@ -367,6 +396,8 @@
 					}
 				}
 			} else if (currentMethod.parameterNonNullness != null) {
+  // Temporary tweak:
+//			  if (!((ReferenceBinding) inheritedMethod.getDeclaringClass().erasure()).isBinaryBinding()) // WORKAROUND WHILE PLAYING WITH DEFAULTS
 				// super method has no annotations but current has
 				for (int i = 0; i < currentMethod.parameterNonNullness.length; i++) {
 					if (currentMethod.parameterNonNullness[i] == Boolean.TRUE) { // tightening from unconstrained to @NonNull
@@ -386,6 +417,17 @@
 				for (AbstractMethodDeclaration methodDecl : methodDeclarations)
 					methodDecl.bindArguments();
 		}
+		
+		void fillInDefaultNullNess() {
+			long defaultNullNess = getEnvironment().getGlobalOptions().defaultNonNullness;
+			if (defaultNullNess != 0) {
+				MethodBinding[] methodBindings = getMethodBindings();
+				if (methodBindings != null) {
+					for (MethodBinding methodBinding : methodBindings)
+						methodBinding.fillInDefaultNullness(defaultNullNess);
+				}
+			}
+		}
 	}
 
 	/** Retrieve null annotations from binary methods. */
@@ -789,10 +831,6 @@
 	@SuppressWarnings("rawtypes")
 	protected class CompilerOptions implements org.eclipse.objectteams.internal.jdt.nullity.NullCompilerOptions playedBy CompilerOptions 
 	{
-		// copies from orig:
-		public static final String ENABLED = "enabled"; //$NON-NLS-1$
-		public static final String DISABLED = "disabled"; //$NON-NLS-1$
-
 
 		@SuppressWarnings("decapsulation")
 		void updateSeverity(int irritant, Object severityString) 	-> void updateSeverity(int irritant, Object severityString);
@@ -806,6 +844,8 @@
 		/** Should null annotation types be emulated by synthetic bindings? */
 		public boolean emulateNullAnnotationTypes;
 		
+		public long defaultNonNullness; // 0 or TagBits#AnnotationNullable or TagBits#AnnotationNonNull
+
 		String optionKeyFromIrritant(int irritant) <- replace String optionKeyFromIrritant(int irritant);
 		@SuppressWarnings("basecall")
 		static callin String optionKeyFromIrritant(int irritant) {
@@ -848,6 +888,12 @@
 				optionsMap.put(OPTION_NonNullAnnotationName, String.valueOf(compoundName));
 			}
 			optionsMap.put(OPTION_EmulateNullAnnotationTypes, this.emulateNullAnnotationTypes ? ENABLED : DISABLED);
+			if (this.defaultNonNullness == TagBits.AnnotationNullable)
+				optionsMap.put(OPTION_NullnessDefault, NULLABLE);
+			else if (this.defaultNonNullness == TagBits.AnnotationNonNull)
+				optionsMap.put(OPTION_NullnessDefault, NONNULL);
+			else
+				optionsMap.remove(OPTION_NullnessDefault);
 		}
 		void set(Map optionsMap) <- before void set(Map optionsMap);
 		private void set(Map optionsMap) {
@@ -865,14 +911,28 @@
 				if (ENABLED.equals(optionValue)) {
 					this.emulateNullAnnotationTypes = true;
 					// ensure that we actually have annotation names to emulate:
-					if (this.nullableAnnotationName == null)
-						this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME;
-					if (this.nonNullAnnotationName == null)
-						this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
+					ensureNullAnnotationNames();
 				} else if (DISABLED.equals(optionValue)) {
 					this.emulateNullAnnotationTypes = false;
 				}
 			}
+			if ((optionValue = optionsMap.get(OPTION_NullnessDefault)) != null) {
+				if (NULLABLE.equals(optionValue)) {
+					defaultNonNullness = TagBits.AnnotationNullable;
+					ensureNullAnnotationNames();
+				} else if (NONNULL.equals(optionValue)) {
+					defaultNonNullness = TagBits.AnnotationNonNull;
+					ensureNullAnnotationNames();
+				} else {
+					defaultNonNullness = 0;
+				}
+			}
+		}
+		private void ensureNullAnnotationNames() {
+			if (this.nullableAnnotationName == null)
+				this.nullableAnnotationName = DEFAULT_NULLABLE_ANNOTATION_NAME;
+			if (this.nonNullAnnotationName == null)
+				this.nonNullAnnotationName = DEFAULT_NONNULL_ANNOTATION_NAME;
 		}
 	}
 	protected class JavaModelManager playedBy JavaModelManager {
@@ -896,6 +956,7 @@
 			optionNames.add(NullCompilerOptions.OPTION_ReportNullContractInsufficientInfo);
 			optionNames.add(NullCompilerOptions.OPTION_ReportNullContractViolation);
 			optionNames.add(NullCompilerOptions.OPTION_ReportPotentialNullContractViolation);
+			optionNames.add(NullCompilerOptions.OPTION_NullnessDefault);
 		}
 	}
 }
diff --git a/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/NullCompilerOptions.java b/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/NullCompilerOptions.java
index 48e56e3..b18f290 100644
--- a/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/NullCompilerOptions.java
+++ b/plugins/org.eclipse.objectteams.jdt.nullity/src/org/eclipse/objectteams/internal/jdt/nullity/NullCompilerOptions.java
@@ -17,6 +17,15 @@
 /** Additional constants for {@link CompilerOptions}. */
 @SuppressWarnings("restriction")
 public interface NullCompilerOptions {
+	// copies from orig:
+	public static final String ENABLED = "enabled"; //$NON-NLS-1$
+	public static final String DISABLED = "disabled"; //$NON-NLS-1$
+
+
+	// new:
+	public static final String NONNULL = "nonnull"; //$NON-NLS-1$
+	public static final String NULLABLE = "nullable"; //$NON-NLS-1$
+
 	public static final String OPTION_ReportNullContractViolation = "org.eclipse.jdt.core.compiler.problem.nullContractViolation";  //$NON-NLS-1$
 	public static final String OPTION_ReportPotentialNullContractViolation = "org.eclipse.jdt.core.compiler.problem.potentialNullContractViolation";  //$NON-NLS-1$
 	public static final String OPTION_ReportNullContractInsufficientInfo = "org.eclipse.jdt.core.compiler.problem.nullContractInsufficientInfo";  //$NON-NLS-1$
@@ -25,6 +34,9 @@
 	public static final String OPTION_NonNullAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnull"; //$NON-NLS-1$
 	public static final String OPTION_EmulateNullAnnotationTypes = "org.eclipse.jdt.core.compiler.annotation.emulate"; //$NON-NLS-1$
 	
+	public static final String OPTION_NullnessDefault = "org.eclipse.jdt.core.compiler.annotation.nulldefault";  //$NON-NLS-1$
+	
+
 	public static final int NullContractViolation = IrritantSet.GROUP2 | ASTNode.Bit7;
 	public static final int PotentialNullContractViolation = IrritantSet.GROUP2 | ASTNode.Bit8;
 	public static final int NullContractInsufficientInfo = IrritantSet.GROUP2 | ASTNode.Bit9;