Blob Blame History Raw
### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.core
Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java,v
retrieving revision 1.57
diff -u -r1.57 FlowContext.java
--- compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java	2 Apr 2007 11:05:51 -0000	1.57
+++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java	29 Jan 2009 17:06:52 -0000
@@ -18,6 +18,7 @@
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -44,6 +45,25 @@
 		
 boolean deferNullDiagnostic, preemptNullDiagnostic;
 
+public static final int 
+  CAN_ONLY_NULL_NON_NULL = 0x0000, 
+  	// check against null and non null, with definite values -- comparisons
+  CAN_ONLY_NULL = 0x0001,
+  	// check against null, with definite values -- comparisons
+  CAN_ONLY_NON_NULL = 0x0002,
+	// check against non null, with definite values -- comparisons
+  MAY_NULL = 0x0003,
+	// check against null, with potential values -- NPE guard
+  CHECK_MASK = 0x00FF,
+  IN_COMPARISON_NULL = 0x0100,
+  IN_COMPARISON_NON_NULL = 0x0200,
+    // check happened in a comparison
+  IN_ASSIGNMENT = 0x0300,
+    // check happened in an assignment
+  IN_INSTANCEOF = 0x0400,
+    // check happened in an instanceof expression
+  CONTEXT_MASK = ~CHECK_MASK;
+
 public FlowContext(FlowContext parent, ASTNode associatedNode) {
 	this.parent = parent;
 	this.associatedNode = associatedNode;
@@ -287,6 +307,28 @@
 	return null;
 }
 
+public FlowInfo getInitsForFinalBlankInitializationCheck(TypeBinding declaringType, FlowInfo flowInfo) {
+	FlowContext current = this;
+	FlowInfo inits = flowInfo;
+	do {
+		if (current instanceof InitializationFlowContext) {
+			InitializationFlowContext initializationContext = (InitializationFlowContext) current;
+			if (((TypeDeclaration)initializationContext.associatedNode).binding == declaringType) {
+				return inits;
+			}
+			inits = initializationContext.initsBeforeContext;
+			current = initializationContext.initializationParent;
+		} else if (current instanceof ExceptionHandlingFlowContext) {
+			ExceptionHandlingFlowContext exceptionContext = (ExceptionHandlingFlowContext) current;
+			current = exceptionContext.initializationParent == null ? exceptionContext.parent : exceptionContext.initializationParent;
+		} else {
+			current = current.parent;
+		}
+	} while (current != null);
+	// not found
+	return null;
+}
+
 /*
  * lookup through break labels
  */
@@ -468,25 +510,6 @@
 	}
 }
 
-public static final int 
-  CAN_ONLY_NULL_NON_NULL = 0x0000, 
-  	// check against null and non null, with definite values -- comparisons
-  CAN_ONLY_NULL = 0x0001,
-  	// check against null, with definite values -- comparisons
-  CAN_ONLY_NON_NULL = 0x0002,
-	// check against non null, with definite values -- comparisons
-  MAY_NULL = 0x0003,
-	// check against null, with potential values -- NPE guard
-  CHECK_MASK = 0x00FF,
-  IN_COMPARISON_NULL = 0x0100,
-  IN_COMPARISON_NON_NULL = 0x0200,
-    // check happened in a comparison
-  IN_ASSIGNMENT = 0x0300,
-    // check happened in an assignment
-  IN_INSTANCEOF = 0x0400,
-    // check happened in an instanceof expression
-  CONTEXT_MASK = ~CHECK_MASK;
-
 /**
  * Record a null reference for use by deferred checks. Only looping or 
  * finally contexts really record that information. The context may
Index: compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java,v
retrieving revision 1.16
diff -u -r1.16 InitializationFlowContext.java
--- compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java	28 Mar 2006 20:32:37 -0000	1.16
+++ compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java	29 Jan 2009 17:06:52 -0000
@@ -26,17 +26,17 @@
 	public TypeBinding[] thrownExceptions = new TypeBinding[5];
 	public ASTNode[] exceptionThrowers = new ASTNode[5];
 	public FlowInfo[] exceptionThrowerFlowInfos = new FlowInfo[5];
+	public FlowInfo	initsBeforeContext;
 	
-	public InitializationFlowContext(
-		FlowContext parent,
-		ASTNode associatedNode,
-		BlockScope scope) {
+	public InitializationFlowContext(FlowContext parent, ASTNode associatedNode, FlowInfo initsBeforeContext, FlowContext initializationParent, BlockScope scope) {
 		super(
 			parent,
 			associatedNode,
 			Binding.NO_EXCEPTIONS, // no exception allowed by default
+			initializationParent,
 			scope, 
 			FlowInfo.DEAD_END);
+		this.initsBeforeContext = initsBeforeContext;
 	}
 
 	public void checkInitializerExceptions(
Index: compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java,v
retrieving revision 1.42
diff -u -r1.42 ExceptionHandlingFlowContext.java
--- compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java	5 Mar 2008 07:57:20 -0000	1.42
+++ compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java	29 Jan 2009 17:06:52 -0000
@@ -41,7 +41,8 @@
 	boolean isMethodContext;
 
 	public UnconditionalFlowInfo initsOnReturn;
-
+	public FlowContext initializationParent; // special parent relationship only for initialization purpose
+	
 	// for dealing with anonymous constructor thrown exceptions
 	public ArrayList extendedExceptions;
 	
@@ -49,6 +50,7 @@
 		FlowContext parent,
 		ASTNode associatedNode,
 		ReferenceBinding[] handledExceptions,
+		FlowContext initializationParent,
 		BlockScope scope,
 		UnconditionalFlowInfo flowInfo) {
 
@@ -79,6 +81,7 @@
 		System.arraycopy(this.isReached, 0, this.isNeeded, 0, cacheSize);
 	}
 	this.initsOnReturn = FlowInfo.DEAD_END;	
+	this.	initializationParent = initializationParent;	
 }
 
 public void complainIfUnusedExceptionHandlers(AbstractMethodDeclaration method) {
Index: compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java,v
retrieving revision 1.148
diff -u -r1.148 TypeDeclaration.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java	27 May 2008 22:21:13 -0000	1.148
+++ compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java	29 Jan 2009 17:06:52 -0000
@@ -594,8 +594,8 @@
 			this.scope.problemReporter().unusedPrivateType(this);
 		}
 	}
-	InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, this.initializerScope);
-	InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, this.staticInitializerScope);
+	InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, flowInfo, flowContext, this.initializerScope);
+	InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, flowInfo, flowContext, this.staticInitializerScope);
 	FlowInfo nonStaticFieldInfo = flowInfo.unconditionalFieldLessCopy();
 	FlowInfo staticFieldInfo = flowInfo.unconditionalFieldLessCopy();
 	if (this.fields != null) {
@@ -610,11 +610,7 @@
 				} else {*/
 				staticInitializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
 				/*}*/
-				staticFieldInfo =
-					field.analyseCode(
-						this.staticInitializerScope,
-						staticInitializerContext,
-						staticFieldInfo);
+				staticFieldInfo = field.analyseCode(this.staticInitializerScope, staticInitializerContext, staticFieldInfo);
 				// in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
 				// branch, since the previous initializer already got the blame.
 				if (staticFieldInfo == FlowInfo.DEAD_END) {
@@ -630,8 +626,7 @@
 				} else {*/
 					initializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
 				/*}*/
-				nonStaticFieldInfo =
-					field.analyseCode(this.initializerScope, initializerContext, nonStaticFieldInfo);
+				nonStaticFieldInfo = field.analyseCode(this.initializerScope, initializerContext, nonStaticFieldInfo);
 				// in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
 				// branch, since the previous initializer already got the blame.
 				if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
Index: compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java,v
retrieving revision 1.51.2.1
diff -u -r1.51.2.1 Clinit.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java	1 Jul 2008 11:24:16 -0000	1.51.2.1
+++ compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java	29 Jan 2009 17:06:49 -0000
@@ -53,6 +53,7 @@
 					staticInitializerFlowContext.parent,
 					this,
 					Binding.NO_EXCEPTIONS,
+					staticInitializerFlowContext,
 					scope,
 					FlowInfo.DEAD_END);
 
Index: compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java,v
retrieving revision 1.108
diff -u -r1.108 TryStatement.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java	31 Aug 2007 19:41:31 -0000	1.108
+++ compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java	29 Jan 2009 17:06:51 -0000
@@ -87,6 +87,7 @@
 				flowContext,
 				this,
 				this.caughtExceptionTypes,
+				null,
 				this.scope,
 				flowInfo.unconditionalInits());
 		handlingContext.initsOnFinally =
@@ -198,6 +199,7 @@
 				insideSubContext,
 				this,
 				this.caughtExceptionTypes,
+				null,
 				this.scope,
 				flowInfo.unconditionalInits());
 		handlingContext.initsOnFinally =
Index: compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java,v
retrieving revision 1.92.2.2
diff -u -r1.92.2.2 ConstructorDeclaration.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java	8 Jul 2008 13:22:06 -0000	1.92.2.2
+++ compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java	29 Jan 2009 17:06:50 -0000
@@ -77,6 +77,7 @@
 				initializerFlowContext.parent,
 				this,
 				this.binding.thrownExceptions,
+				initializerFlowContext,
 				this.scope,
 				FlowInfo.DEAD_END);
 		initializerFlowContext.checkInitializerExceptions(
Index: compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java,v
retrieving revision 1.103.2.3
diff -u -r1.103.2.3 SingleNameReference.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java	27 Nov 2008 10:13:10 -0000	1.103.2.3
+++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java	29 Jan 2009 17:06:51 -0000
@@ -62,7 +62,8 @@
 				FieldBinding fieldBinding;
 				if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() 
 						&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
-					if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+					FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
+					if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
 						currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
 					}
 				}
@@ -148,7 +149,8 @@
 			// check if reading a final blank field
 			FieldBinding fieldBinding = (FieldBinding) this.binding;
 			if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
-				if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+				FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
+				if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
 					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
 				}
 			}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java,v
retrieving revision 1.116.2.2
diff -u -r1.116.2.2 FieldReference.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java	2 Oct 2008 15:29:33 -0000	1.116.2.2
+++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java	29 Jan 2009 17:06:50 -0000
@@ -57,15 +57,17 @@
 
 }
 
-public FlowInfo analyseAssignment(BlockScope currentScope, 	FlowContext flowContext, 	FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
+public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
 	// compound assignment extra work
 	if (isCompound) { // check the variable part is initialized if blank final
 		if (this.binding.isBlankFinal()
 			&& this.receiver.isThis()
-			&& currentScope.needBlankFinalFieldInitializationCheck(this.binding)
-			&& (!flowInfo.isDefinitelyAssigned(this.binding))) {
-			currentScope.problemReporter().uninitializedBlankFinalField(this.binding, this);
-			// we could improve error msg here telling "cannot use compound assignment on final blank field"
+			&& currentScope.needBlankFinalFieldInitializationCheck(this.binding)) {
+			FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(this.binding.declaringClass.original(), flowInfo);
+			if (!fieldInits.isDefinitelyAssigned(this.binding)) {
+				currentScope.problemReporter().uninitializedBlankFinalField(this.binding, this);
+				// we could improve error msg here telling "cannot use compound assignment on final blank field"
+			}
 		}
 		manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
 	}
Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java,v
retrieving revision 1.125.2.3
diff -u -r1.125.2.3 QualifiedNameReference.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java	27 Nov 2008 10:13:10 -0000	1.125.2.3
+++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java	29 Jan 2009 17:06:50 -0000
@@ -74,10 +74,9 @@
 			if (lastFieldBinding.isBlankFinal()
 				    && this.otherBindings != null // the last field binding is only assigned
 	 				&& currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)) {
-				if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) {
-					currentScope.problemReporter().uninitializedBlankFinalField(
-						lastFieldBinding,
-						this);
+				FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(lastFieldBinding.declaringClass.original(), flowInfo);
+				if (!fieldInits.isDefinitelyAssigned(lastFieldBinding)) {
+					currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
 				}
 			}
 			break;
@@ -122,9 +121,11 @@
 	if (isCompound) {
 		if (otherBindingsCount == 0
 				&& lastFieldBinding.isBlankFinal()
-				&& currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)
-				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
-			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
+				&& currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)) {
+			FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(lastFieldBinding.declaringClass.original(), flowInfo);
+			if (!fieldInits.isDefinitelyAssigned(lastFieldBinding)) {
+				currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
+			}
 		}
 		TypeBinding lastReceiverType;
 		switch (otherBindingsCount) {
@@ -212,9 +213,11 @@
 				FieldBinding fieldBinding = (FieldBinding) this.binding;
 				// check if reading a final blank field
 				if (fieldBinding.isBlankFinal()
-						&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)
-						&& !flowInfo.isDefinitelyAssigned(fieldBinding)) {
-					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+						&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
+					FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
+					if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
+						currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+					}
 				}
 			}
 			break;
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.65
diff -u -r1.65 MethodDeclaration.java
--- compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java	27 May 2008 22:21:13 -0000	1.65
+++ compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java	29 Jan 2009 17:06:50 -0000
@@ -72,6 +72,7 @@
 					initializationContext,
 					this,
 					this.binding.thrownExceptions,
+					null,
 					this.scope,
 					FlowInfo.DEAD_END);
 
Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java,v
retrieving revision 1.52
diff -u -r1.52 CodeSnippetSingleNameReference.java
--- eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java	27 May 2008 22:27:12 -0000	1.52
+++ eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java	29 Jan 2009 17:06:52 -0000
@@ -45,7 +45,8 @@
 			FieldBinding fieldBinding;
 			if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() 
 					&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
-				if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+				FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
+				if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
 					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
 				}
 			}