View | Details | Raw Unified | Return to bug 146556 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (-2 / +6 lines)
Lines 27-33 Link Here
27
	public final static int Bit2 = 0x2; 						// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
27
	public final static int Bit2 = 0x2; 						// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
28
	public final static int Bit3 = 0x4; 						// return type (operator) | name reference kind (name ref) | implicit this (this ref)
28
	public final static int Bit3 = 0x4; 						// return type (operator) | name reference kind (name ref) | implicit this (this ref)
29
	public final static int Bit4 = 0x8; 						// return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
29
	public final static int Bit4 = 0x8; 						// return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
30
	public final static int Bit5 = 0x10; 						// value for return (expression) | has all method bodies (unit) | supertype ref (type ref)
30
	public final static int Bit5 = 0x10; 						// value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)
31
	public final static int Bit6 = 0x20; 						// depth (name ref, msg) | ignore need cast check (cast expression)
31
	public final static int Bit6 = 0x20; 						// depth (name ref, msg) | ignore need cast check (cast expression)
32
	public final static int Bit7 = 0x40; 						// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement)
32
	public final static int Bit7 = 0x40; 						// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement)
33
	public final static int Bit8 = 0x80; 						// depth (name ref, msg) | operator (operator) | unsafe cast (cast expression)
33
	public final static int Bit8 = 0x80; 						// depth (name ref, msg) | operator (operator) | unsafe cast (cast expression)
Lines 36-42 Link Here
36
	public final static int Bit11 = 0x400; 					// depth (name ref, msg) | operator (operator) | is member type (type decl)
36
	public final static int Bit11 = 0x400; 					// depth (name ref, msg) | operator (operator) | is member type (type decl)
37
	public final static int Bit12 = 0x800; 					// depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
37
	public final static int Bit12 = 0x800; 					// depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
38
	public final static int Bit13 = 0x1000; 				// depth (name ref, msg) | is secondary type (type decl)
38
	public final static int Bit13 = 0x1000; 				// depth (name ref, msg) | is secondary type (type decl)
39
	public final static int Bit14 = 0x2000; 				// strictly assigned (reference lhs)
39
	public final static int Bit14 = 0x2000; 				// strictly assigned (reference lhs) | discard enclosing instance (explicit constr call)
40
	public final static int Bit15 = 0x4000; 				// is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement)
40
	public final static int Bit15 = 0x4000; 				// is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement)
41
	public final static int Bit16 = 0x8000; 				// in javadoc comment (name ref, type ref, msg)
41
	public final static int Bit16 = 0x8000; 				// in javadoc comment (name ref, type ref, msg)
42
	public final static int Bit17 = 0x10000; 				// compound assigned (reference lhs)
42
	public final static int Bit17 = 0x10000; 				// compound assigned (reference lhs)
Lines 141-146 Link Here
141
141
142
	// for type, method and field declarations
142
	// for type, method and field declarations
143
	public static final int HasLocalType = Bit2; // cannot conflict with AddAssertionMASK
143
	public static final int HasLocalType = Bit2; // cannot conflict with AddAssertionMASK
144
	public static final int HasBeenResolved = Bit5; // field decl only (to handle forward references)
144
145
145
	// for expression
146
	// for expression
146
	public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29
147
	public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29
Lines 151-156 Link Here
151
	public static final int IsStrictlyAssigned = Bit14; // set only for true assignments, as opposed to compound ones
152
	public static final int IsStrictlyAssigned = Bit14; // set only for true assignments, as opposed to compound ones
152
	public static final int IsCompoundAssigned = Bit17; // set only for compound assignments, as opposed to other ones
153
	public static final int IsCompoundAssigned = Bit17; // set only for compound assignments, as opposed to other ones
153
154
155
	// for explicit constructor call
156
	public static final int DiscardEnclosingInstance = Bit14; // used for codegen
157
	
154
	// for empty statement
158
	// for empty statement
155
	public static final int IsUsefulEmptyStatement = Bit1;
159
	public static final int IsUsefulEmptyStatement = Bit1;
156
160
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java (-237 / +223 lines)
Lines 20-26 Link Here
20
public class FieldDeclaration extends AbstractVariableDeclaration {
20
public class FieldDeclaration extends AbstractVariableDeclaration {
21
	
21
	
22
	public FieldBinding binding;
22
	public FieldBinding binding;
23
	boolean hasBeenResolved = false; // TODO (philippe) should use a tagBit instead
24
	public Javadoc javadoc;
23
	public Javadoc javadoc;
25
24
26
	//allows to retrieve both the "type" part of the declaration (part1)
25
	//allows to retrieve both the "type" part of the declaration (part1)
Lines 34-303 Link Here
34
	public int endPart1Position;
33
	public int endPart1Position;
35
	public int endPart2Position;
34
	public int endPart2Position;
36
35
37
	public FieldDeclaration() {
36
public FieldDeclaration() {
38
		// for subtypes or conversion
37
	// for subtypes or conversion
39
	}
38
}
40
39
41
	public FieldDeclaration(
40
public FieldDeclaration(	char[] name, int sourceStart, int sourceEnd) {
42
		char[] name,
41
	this.name = name;
43
		int sourceStart,
42
	//due to some declaration like 
44
		int sourceEnd) {
43
	// int x, y = 3, z , x ;
45
44
	//the sourceStart and the sourceEnd is ONLY on  the name
46
		this.name = name;
45
	this.sourceStart = sourceStart;
47
46
	this.sourceEnd = sourceEnd;
48
		//due to some declaration like 
47
}
49
		// int x, y = 3, z , x ;
50
		//the sourceStart and the sourceEnd is ONLY on  the name
51
		this.sourceStart = sourceStart;
52
		this.sourceEnd = sourceEnd;
53
	}
54
48
55
	public FlowInfo analyseCode(
49
public FlowInfo analyseCode(MethodScope initializationScope, FlowContext flowContext, FlowInfo flowInfo) {
56
		MethodScope initializationScope,
50
	if (this.binding != null && !this.binding.isUsed()) {
57
		FlowContext flowContext,
51
		if (this.binding.isPrivate() || (this.binding.declaringClass != null && this.binding.declaringClass.isLocalType())) {
58
		FlowInfo flowInfo) {
52
			if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
59
53
				initializationScope.problemReporter().unusedPrivateField(this);
60
		if (this.binding != null && !this.binding.isUsed()) {
61
			if (this.binding.isPrivate() || (this.binding.declaringClass != null && this.binding.declaringClass.isLocalType())) {
62
				if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
63
					initializationScope.problemReporter().unusedPrivateField(this);
64
				}
65
			}
54
			}
66
		}
55
		}
67
		// cannot define static non-constant field inside nested class
68
		if (this.binding != null
69
				&& this.binding.isValidBinding()
70
				&& this.binding.isStatic()
71
				&& this.binding.constant() == Constant.NotAConstant
72
				&& this.binding.declaringClass.isNestedType()
73
				&& !this.binding.declaringClass.isStatic()) {
74
			initializationScope.problemReporter().unexpectedStaticModifierForField(
75
				(SourceTypeBinding) this.binding.declaringClass,
76
				this);
77
		}
78
79
		if (this.initialization != null) {
80
			flowInfo =
81
				this.initialization
82
					.analyseCode(initializationScope, flowContext, flowInfo)
83
					.unconditionalInits();
84
			flowInfo.markAsDefinitelyAssigned(this.binding);
85
		}
86
		return flowInfo;
87
	}
56
	}
88
57
	// cannot define static non-constant field inside nested class
89
	/**
58
	if (this.binding != null
90
	 * Code generation for a field declaration:
59
			&& this.binding.isValidBinding()
91
	 *	   standard assignment to a field 
60
			&& this.binding.isStatic()
92
	 *
61
			&& this.binding.constant() == Constant.NotAConstant
93
	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
62
			&& this.binding.declaringClass.isNestedType()
94
	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
63
			&& !this.binding.declaringClass.isStatic()) {
95
	 */
64
		initializationScope.problemReporter().unexpectedStaticModifierForField(
96
	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
65
			(SourceTypeBinding) this.binding.declaringClass,
97
66
			this);
98
		if ((this.bits & IsReachable) == 0) {
99
			return;
100
		}
101
		// do not generate initialization code if final and static (constant is then
102
		// recorded inside the field itself).
103
		int pc = codeStream.position;
104
		boolean isStatic;
105
		if (this.initialization != null
106
			&& !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) {
107
			// non-static field, need receiver
108
			if (!isStatic)
109
				codeStream.aload_0();
110
			// generate initialization value
111
			this.initialization.generateCode(currentScope, codeStream, true);
112
			// store into field
113
			if (isStatic) {
114
				codeStream.putstatic(this.binding);
115
			} else {
116
				codeStream.putfield(this.binding);
117
			}
118
		}
119
		codeStream.recordPositionsFrom(pc, this.sourceStart);
120
	}
67
	}
121
68
122
	/**
69
	if (this.initialization != null) {
123
	 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
70
		flowInfo =
124
	 */
71
			this.initialization
125
	public int getKind() {
72
				.analyseCode(initializationScope, flowContext, flowInfo)
126
		return this.type == null ? ENUM_CONSTANT : FIELD;
73
				.unconditionalInits();
74
		flowInfo.markAsDefinitelyAssigned(this.binding);
127
	}
75
	}
128
	
76
	return flowInfo;
129
	public boolean isStatic() {
77
}
130
78
131
		if (this.binding != null)
79
/**
132
			return this.binding.isStatic();
80
 * Code generation for a field declaration:
133
		return (this.modifiers & ClassFileConstants.AccStatic) != 0;
81
 *	   standard assignment to a field 
82
 *
83
 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
84
 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
85
 */
86
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
87
	if ((this.bits & IsReachable) == 0) {
88
		return;
134
	}
89
	}
135
90
	// do not generate initialization code if final and static (constant is then
136
	public StringBuffer printStatement(int indent, StringBuffer output) {
91
	// recorded inside the field itself).
137
		if (this.javadoc != null) {
92
	int pc = codeStream.position;
138
			this.javadoc.print(indent, output);
93
	boolean isStatic;
94
	if (this.initialization != null
95
		&& !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) {
96
		// non-static field, need receiver
97
		if (!isStatic)
98
			codeStream.aload_0();
99
		// generate initialization value
100
		this.initialization.generateCode(currentScope, codeStream, true);
101
		// store into field
102
		if (isStatic) {
103
			codeStream.putstatic(this.binding);
104
		} else {
105
			codeStream.putfield(this.binding);
139
		}
106
		}
140
		return super.printStatement(indent, output);
141
	}
107
	}
108
	codeStream.recordPositionsFrom(pc, this.sourceStart);
109
}
142
110
143
	public void resolve(MethodScope initializationScope) {
111
/**
112
 * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
113
 */
114
public int getKind() {
115
	return this.type == null ? ENUM_CONSTANT : FIELD;
116
}
144
117
145
		// the two <constant = Constant.NotAConstant> could be regrouped into
118
public boolean isStatic() {
146
		// a single line but it is clearer to have two lines while the reason of their
119
	if (this.binding != null)
147
		// existence is not at all the same. See comment for the second one.
120
		return this.binding.isStatic();
121
	return (this.modifiers & ClassFileConstants.AccStatic) != 0;
122
}
148
123
149
		//--------------------------------------------------------
124
public StringBuffer printStatement(int indent, StringBuffer output) {
150
		if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
125
	if (this.javadoc != null) {
126
		this.javadoc.print(indent, output);
127
	}
128
	return super.printStatement(indent, output);
129
}
151
130
152
			this.hasBeenResolved = true;
131
public void resolve(MethodScope initializationScope) {
132
	// the two <constant = Constant.NotAConstant> could be regrouped into
133
	// a single line but it is clearer to have two lines while the reason of their
134
	// existence is not at all the same. See comment for the second one.
135
136
	//--------------------------------------------------------
137
	if ((this.bits & ASTNode.HasBeenResolved) != 0) return;
138
	if (this.binding == null || !this.binding.isValidBinding()) return;
139
	
140
	this.bits |= ASTNode.HasBeenResolved;
153
141
154
			// check if field is hiding some variable - issue is that field binding already got inserted in scope
142
	// check if field is hiding some variable - issue is that field binding already got inserted in scope
155
			// thus must lookup separately in super type and outer context
143
	// thus must lookup separately in super type and outer context
156
			ClassScope classScope = initializationScope.enclosingClassScope();
144
	ClassScope classScope = initializationScope.enclosingClassScope();
157
			
145
	
158
			if (classScope != null) {
146
	if (classScope != null) {
159
				checkHiding: {
147
		checkHiding: {
160
					SourceTypeBinding declaringType = classScope.enclosingSourceType();
148
			SourceTypeBinding declaringType = classScope.enclosingSourceType();
161
					checkHidingSuperField: {
149
			checkHidingSuperField: {
162
						if (declaringType.superclass == null) break checkHidingSuperField;
150
				if (declaringType.superclass == null) break checkHidingSuperField;
163
						Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this,  false /*do not resolve hidden field*/);
151
				Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this,  false /*do not resolve hidden field*/);
164
						if (existingVariable == null) break checkHidingSuperField; // keep checking outer scenario
152
				if (existingVariable == null) break checkHidingSuperField; // keep checking outer scenario
165
						if (!existingVariable.isValidBinding())  break checkHidingSuperField; // keep checking outer scenario
153
				if (!existingVariable.isValidBinding())  break checkHidingSuperField; // keep checking outer scenario
166
						if (existingVariable instanceof FieldBinding) {
154
				if (existingVariable instanceof FieldBinding) {
167
							FieldBinding existingField = (FieldBinding) existingVariable;
155
					FieldBinding existingField = (FieldBinding) existingVariable;
168
							if (existingField.original() == this.binding) break checkHidingSuperField; // keep checking outer scenario
156
					if (existingField.original() == this.binding) break checkHidingSuperField; // keep checking outer scenario
169
						}
170
						// collision with supertype field
171
						initializationScope.problemReporter().fieldHiding(this, existingVariable);
172
						break checkHiding; // already found a matching field
173
					}					
174
					// only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
175
					// from outer scope. Subsequent static contexts are detected for free.
176
					Scope outerScope = classScope.parent;
177
					if (outerScope.kind == Scope.COMPILATION_UNIT_SCOPE) break checkHiding;
178
					Binding existingVariable = outerScope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
179
					if (existingVariable == null) break checkHiding;
180
					if (!existingVariable.isValidBinding()) break checkHiding;
181
					if (existingVariable == this.binding) break checkHiding;
182
					if (existingVariable instanceof FieldBinding) {
183
						FieldBinding existingField = (FieldBinding) existingVariable;
184
						if (existingField.original() == this.binding) break checkHiding;
185
						if (!existingField.isStatic() && declaringType.isStatic()) break checkHiding;
186
					}
187
					// collision with outer field or local variable
188
					initializationScope.problemReporter().fieldHiding(this, existingVariable);
189
				}
157
				}
158
				// collision with supertype field
159
				initializationScope.problemReporter().fieldHiding(this, existingVariable);
160
				break checkHiding; // already found a matching field
161
			}					
162
			// only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
163
			// from outer scope. Subsequent static contexts are detected for free.
164
			Scope outerScope = classScope.parent;
165
			if (outerScope.kind == Scope.COMPILATION_UNIT_SCOPE) break checkHiding;
166
			Binding existingVariable = outerScope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
167
			if (existingVariable == null) break checkHiding;
168
			if (!existingVariable.isValidBinding()) break checkHiding;
169
			if (existingVariable == this.binding) break checkHiding;
170
			if (existingVariable instanceof FieldBinding) {
171
				FieldBinding existingField = (FieldBinding) existingVariable;
172
				if (existingField.original() == this.binding) break checkHiding;
173
				if (!existingField.isStatic() && declaringType.isStatic()) break checkHiding;
190
			}
174
			}
175
			// collision with outer field or local variable
176
			initializationScope.problemReporter().fieldHiding(this, existingVariable);
177
		}
178
	}
179
	
180
	if (this.type != null ) { // enum constants have no declared type
181
		this.type.resolvedType = this.binding.type; // update binding for type reference
182
	}
183
184
	FieldBinding previousField = initializationScope.initializedField;
185
	int previousFieldID = initializationScope.lastVisibleFieldID;
186
	try {
187
		initializationScope.initializedField = this.binding;
188
		initializationScope.lastVisibleFieldID = this.binding.id;
189
190
		resolveAnnotations(initializationScope, this.annotations, this.binding);
191
		// check @Deprecated annotation presence
192
		if ((this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
193
				&& (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
194
				&& initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
195
			initializationScope.problemReporter().missingDeprecatedAnnotationForField(this);
196
		}						
197
		// the resolution of the initialization hasn't been done
198
		if (this.initialization == null) {
199
			this.binding.setConstant(Constant.NotAConstant);
200
		} else {
201
			// break dead-lock cycles by forcing constant to NotAConstant
202
			this.binding.setConstant(Constant.NotAConstant);
191
			
203
			
192
			if (this.type != null ) { // enum constants have no declared type
204
			TypeBinding fieldType = this.binding.type;
193
				this.type.resolvedType = this.binding.type; // update binding for type reference
205
			TypeBinding initializationType;
194
			}
206
			this.initialization.setExpectedType(fieldType); // needed in case of generic method invocation
207
			if (this.initialization instanceof ArrayInitializer) {
208
209
				if ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) {
210
					((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
211
					this.initialization.computeConversion(initializationScope, fieldType, initializationType);
212
				}
213
			} else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
195
214
196
			FieldBinding previousField = initializationScope.initializedField;
215
				if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
197
			int previousFieldID = initializationScope.lastVisibleFieldID;
216
					initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType);
198
			try {
217
				if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType)
199
				initializationScope.initializedField = this.binding;
218
						|| (fieldType.isBaseType() && BaseTypeBinding.isWidening(fieldType.id, initializationType.id))
200
				initializationScope.lastVisibleFieldID = this.binding.id;
219
						|| initializationType.isCompatibleWith(fieldType)) {
201
220
					this.initialization.computeConversion(initializationScope, fieldType, initializationType);
202
				resolveAnnotations(initializationScope, this.annotations, this.binding);
221
					if (initializationType.needsUncheckedConversion(fieldType)) {
203
				// check @Deprecated annotation presence
222
						    initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType);
204
				if ((this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
205
						&& (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
206
						&& initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
207
					initializationScope.problemReporter().missingDeprecatedAnnotationForField(this);
208
				}						
209
				// the resolution of the initialization hasn't been done
210
				if (this.initialization == null) {
211
					this.binding.setConstant(Constant.NotAConstant);
212
				} else {
213
					// break dead-lock cycles by forcing constant to NotAConstant
214
					this.binding.setConstant(Constant.NotAConstant);
215
					
216
					TypeBinding fieldType = this.binding.type;
217
					TypeBinding initializationType;
218
					this.initialization.setExpectedType(fieldType); // needed in case of generic method invocation
219
					if (this.initialization instanceof ArrayInitializer) {
220
221
						if ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) {
222
							((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
223
							this.initialization.computeConversion(initializationScope, fieldType, initializationType);
224
						}
225
					} else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
226
227
						if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
228
							initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType);
229
						if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType)
230
								|| (fieldType.isBaseType() && BaseTypeBinding.isWidening(fieldType.id, initializationType.id))
231
								|| initializationType.isCompatibleWith(fieldType)) {
232
							this.initialization.computeConversion(initializationScope, fieldType, initializationType);
233
							if (initializationType.needsUncheckedConversion(fieldType)) {
234
								    initializationScope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, fieldType);
235
							}
236
							if (this.initialization instanceof CastExpression 
237
									&& (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
238
								CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization);
239
							}								
240
						} else if (initializationScope.isBoxingCompatibleWith(initializationType, fieldType) 
241
											|| (initializationType.isBaseType()  // narrowing then boxing ?
242
													&& initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
243
													&& !fieldType.isBaseType()
244
													&& initialization.isConstantValueOfTypeAssignableToType(initializationType, initializationScope.environment().computeBoxingType(fieldType)))) {
245
							this.initialization.computeConversion(initializationScope, fieldType, initializationType);
246
							if (this.initialization instanceof CastExpression 
247
									&& (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
248
								CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization);
249
							}							
250
						} else {
251
							initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this);
252
						}
253
						if (this.binding.isFinal()){ // cast from constant actual type to variable type
254
							this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID()));
255
						}
256
					} else {
257
						this.binding.setConstant(Constant.NotAConstant);
258
					}
223
					}
259
					// check for assignment with no effect
224
					if (this.initialization instanceof CastExpression 
260
					if (this.binding == Assignment.getDirectBinding(this.initialization)) {
225
							&& (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
261
						initializationScope.problemReporter().assignmentHasNoEffect(this, this.name);
226
						CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization);
262
					}					
227
					}								
228
				} else if (initializationScope.isBoxingCompatibleWith(initializationType, fieldType) 
229
									|| (initializationType.isBaseType()  // narrowing then boxing ?
230
											&& initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
231
											&& !fieldType.isBaseType()
232
											&& initialization.isConstantValueOfTypeAssignableToType(initializationType, initializationScope.environment().computeBoxingType(fieldType)))) {
233
					this.initialization.computeConversion(initializationScope, fieldType, initializationType);
234
					if (this.initialization instanceof CastExpression 
235
							&& (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
236
						CastExpression.checkNeedForAssignedCast(initializationScope, fieldType, (CastExpression) this.initialization);
237
					}							
238
				} else {
239
					initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this);
263
				}
240
				}
264
				// Resolve Javadoc comment if one is present
241
				if (this.binding.isFinal()){ // cast from constant actual type to variable type
265
				if (this.javadoc != null) {
242
					this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID()));
266
					/*
267
					if (classScope != null) {
268
						this.javadoc.resolve(classScope);
269
					}
270
					*/
271
					this.javadoc.resolve(initializationScope);
272
				} else if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
273
					initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
274
				}
243
				}
275
			} finally {
244
			} else {
276
				initializationScope.initializedField = previousField;
245
				this.binding.setConstant(Constant.NotAConstant);
277
				initializationScope.lastVisibleFieldID = previousFieldID;
278
				if (this.binding.constant() == null)
279
					this.binding.setConstant(Constant.NotAConstant);
280
			}
246
			}
247
			// check for assignment with no effect
248
			if (this.binding == Assignment.getDirectBinding(this.initialization)) {
249
				initializationScope.problemReporter().assignmentHasNoEffect(this, this.name);
250
			}					
281
		}
251
		}
252
		// Resolve Javadoc comment if one is present
253
		if (this.javadoc != null) {
254
			/*
255
			if (classScope != null) {
256
				this.javadoc.resolve(classScope);
257
			}
258
			*/
259
			this.javadoc.resolve(initializationScope);
260
		} else if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
261
			initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
262
		}
263
	} finally {
264
		initializationScope.initializedField = previousField;
265
		initializationScope.lastVisibleFieldID = previousFieldID;
266
		if (this.binding.constant() == null)
267
			this.binding.setConstant(Constant.NotAConstant);
282
	}
268
	}
269
}
283
270
284
	public void traverse(ASTVisitor visitor, MethodScope scope) {
271
public void traverse(ASTVisitor visitor, MethodScope scope) {
285
272
	if (visitor.visit(this, scope)) {
286
		if (visitor.visit(this, scope)) {
273
		if (this.javadoc != null) {
287
			if (this.javadoc != null) {
274
			this.javadoc.traverse(visitor, scope);
288
				this.javadoc.traverse(visitor, scope);
289
			}
290
			if (this.annotations != null) {
291
				int annotationsLength = this.annotations.length;
292
				for (int i = 0; i < annotationsLength; i++)
293
					this.annotations[i].traverse(visitor, scope);
294
			}
295
			if (this.type != null) {
296
				this.type.traverse(visitor, scope);
297
			}
298
			if (this.initialization != null)
299
				this.initialization.traverse(visitor, scope);
300
		}
275
		}
301
		visitor.endVisit(this, scope);
276
		if (this.annotations != null) {
277
			int annotationsLength = this.annotations.length;
278
			for (int i = 0; i < annotationsLength; i++)
279
				this.annotations[i].traverse(visitor, scope);
280
		}
281
		if (this.type != null) {
282
			this.type.traverse(visitor, scope);
283
		}
284
		if (this.initialization != null)
285
			this.initialization.traverse(visitor, scope);
302
	}
286
	}
287
	visitor.endVisit(this, scope);
288
}
303
}
289
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java (-3 / +3 lines)
Lines 32-38 Link Here
32
	public final static int This = 3;
32
	public final static int This = 3;
33
33
34
	public VariableBinding[][] implicitArguments;
34
	public VariableBinding[][] implicitArguments;
35
	boolean discardEnclosingInstance;
35
//	boolean discardEnclosingInstance;
36
	
36
	
37
	// TODO Remove once DOMParser is activated
37
	// TODO Remove once DOMParser is activated
38
	public int typeArgumentsSourceStart;
38
	public int typeArgumentsSourceStart;
Lines 117-123 Link Here
117
				codeStream.generateSyntheticEnclosingInstanceValues(
117
				codeStream.generateSyntheticEnclosingInstanceValues(
118
					currentScope,
118
					currentScope,
119
					targetType,
119
					targetType,
120
					discardEnclosingInstance ? null : qualification,
120
					(this.bits & ASTNode.DiscardEnclosingInstance) != 0 ? null : qualification,
121
					this);
121
					this);
122
			}
122
			}
123
			// generate arguments
123
			// generate arguments
Lines 296-302 Link Here
296
					scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
296
					scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
297
						qualification,
297
						qualification,
298
						receiverType);
298
						receiverType);
299
					discardEnclosingInstance = true;
299
					this.bits |= ASTNode.DiscardEnclosingInstance;
300
				} else {
300
				} else {
301
					TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
301
					TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
302
					qualification.computeConversion(scope, qTb, qTb);
302
					qualification.computeConversion(scope, qTb, qTb);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java (-115 / +115 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-148 Link Here
11
package org.eclipse.jdt.internal.compiler.ast;
11
package org.eclipse.jdt.internal.compiler.ast;
12
12
13
import org.eclipse.jdt.internal.compiler.ASTVisitor;
13
import org.eclipse.jdt.internal.compiler.ASTVisitor;
14
import org.eclipse.jdt.internal.compiler.impl.*;
15
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
14
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16
import org.eclipse.jdt.internal.compiler.codegen.*;
15
import org.eclipse.jdt.internal.compiler.codegen.CaseLabel;
17
import org.eclipse.jdt.internal.compiler.flow.*;
16
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.lookup.*;
17
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
18
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
19
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.impl.IntConstant;
21
import org.eclipse.jdt.internal.compiler.lookup.Binding;
22
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
23
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
19
26
20
public class CaseStatement extends Statement {
27
public class CaseStatement extends Statement {
21
	
28
	
22
	public Expression constantExpression;
29
	public Expression constantExpression;
23
	public CaseLabel targetLabel;
30
	public CaseLabel targetLabel;
24
	public boolean isEnumConstant;
25
	
31
	
26
	public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
32
public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
27
		this.constantExpression = constantExpression;
33
	this.constantExpression = constantExpression;
28
		this.sourceEnd = sourceEnd;
34
	this.sourceEnd = sourceEnd;
29
		this.sourceStart = sourceStart;
35
	this.sourceStart = sourceStart;
30
	}
36
}
31
37
32
	public FlowInfo analyseCode(
38
public FlowInfo analyseCode(
33
		BlockScope currentScope,
39
	BlockScope currentScope,
34
		FlowContext flowContext,
40
	FlowContext flowContext,
35
		FlowInfo flowInfo) {
41
	FlowInfo flowInfo) {
36
42
37
		if (constantExpression != null) {
43
	if (this.constantExpression != null) {
38
			if (!this.isEnumConstant && constantExpression.constant == Constant.NotAConstant) {
44
		if (this.constantExpression.constant == Constant.NotAConstant 
39
				currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
45
				&& !this.constantExpression.resolvedType.isEnum()) {
40
			}
46
			currentScope.problemReporter().caseExpressionMustBeConstant(this.constantExpression);
41
			this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
42
		}
47
		}
43
		return flowInfo;
48
		this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
44
	}
49
	}
50
	return flowInfo;
51
}
45
52
46
	public StringBuffer printStatement(int tab, StringBuffer output) {
53
public StringBuffer printStatement(int tab, StringBuffer output) {
47
54
	printIndent(tab, output);
48
		printIndent(tab, output);
55
	if (this.constantExpression == null) {
49
		if (constantExpression == null) {
56
		output.append("default : "); //$NON-NLS-1$
50
			output.append("default : "); //$NON-NLS-1$
57
	} else {
51
		} else {
58
		output.append("case "); //$NON-NLS-1$
52
			output.append("case "); //$NON-NLS-1$
59
		this.constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
53
			constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
54
		}
55
		return output.append(';');
56
	}
60
	}
57
	
61
	return output.append(';');
58
	/**
62
}
59
	 * Case code generation
60
	 *
61
	 */
62
	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
63
63
64
		if ((bits & IsReachable) == 0) {
64
/**
65
			return;
65
 * Case code generation
66
		}
66
 *
67
		int pc = codeStream.position;
67
 */
68
		targetLabel.place();
68
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
69
		codeStream.recordPositionsFrom(pc, this.sourceStart);
69
	if ((this.bits & ASTNode.IsReachable) == 0) {
70
	}
70
		return;
71
71
	}
72
	/**
72
	int pc = codeStream.position;
73
	 * No-op : should use resolveCase(...) instead.
73
	this.targetLabel.place();
74
	 */
74
	codeStream.recordPositionsFrom(pc, this.sourceStart);
75
	public void resolve(BlockScope scope) {
75
}
76
		// no-op : should use resolveCase(...) instead.
76
77
	}
77
/**
78
78
 * No-op : should use resolveCase(...) instead.
79
	/**
79
 */
80
	 * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
80
public void resolve(BlockScope scope) {
81
	 * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolveCase(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.ast.SwitchStatement)
81
	// no-op : should use resolveCase(...) instead.
82
	 */
82
}
83
	public Constant resolveCase(BlockScope scope, TypeBinding switchExpressionType, SwitchStatement switchStatement) {
83
84
		// switchExpressionType maybe null in error case
84
/**
85
	    scope.enclosingCase = this; // record entering in a switch case block
85
 * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
86
	    
86
 * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolveCase(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.ast.SwitchStatement)
87
		if (constantExpression == null) {
87
 */
88
			// remember the default case into the associated switch statement
88
public Constant resolveCase(BlockScope scope, TypeBinding switchExpressionType, SwitchStatement switchStatement) {
89
			if (switchStatement.defaultCase != null)
89
	// switchExpressionType maybe null in error case
90
				scope.problemReporter().duplicateDefaultCase(this);
90
    scope.enclosingCase = this; // record entering in a switch case block
91
	
91
    
92
			// on error the last default will be the selected one ...	
92
	if (this.constantExpression == null) {
93
			switchStatement.defaultCase = this;
93
		// remember the default case into the associated switch statement
94
			return Constant.NotAConstant;
94
		if (switchStatement.defaultCase != null)
95
		}
95
			scope.problemReporter().duplicateDefaultCase(this);
96
		// add into the collection of cases of the associated switch statement
96
97
		switchStatement.cases[switchStatement.caseCount++] = this;
97
		// on error the last default will be the selected one ...	
98
		// tag constant name with enum type for privileged access to its members
98
		switchStatement.defaultCase = this;
99
		if (switchExpressionType != null && switchExpressionType.isEnum() && (constantExpression instanceof SingleNameReference)) {
99
		return Constant.NotAConstant;
100
			((SingleNameReference) constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
100
	}
101
		}
101
	// add into the collection of cases of the associated switch statement
102
		TypeBinding caseType = constantExpression.resolveType(scope);
102
	switchStatement.cases[switchStatement.caseCount++] = this;
103
		if (caseType == null || switchExpressionType == null) return Constant.NotAConstant;
103
	// tag constant name with enum type for privileged access to its members
104
		if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
104
	if (switchExpressionType != null && switchExpressionType.isEnum() && (this.constantExpression instanceof SingleNameReference)) {
105
				|| caseType.isCompatibleWith(switchExpressionType)) {
105
		((SingleNameReference) this.constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
106
			if (caseType.isEnum()) {
106
	}
107
				this.isEnumConstant = true;
107
	TypeBinding caseType = this.constantExpression.resolveType(scope);
108
				if (((this.constantExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) {
108
	if (caseType == null || switchExpressionType == null) return Constant.NotAConstant;
109
					scope.problemReporter().enumConstantsCannotBeSurroundedByParenthesis(this.constantExpression);
109
	if (this.constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
110
				}
110
			|| caseType.isCompatibleWith(switchExpressionType)) {
111
		if (caseType.isEnum()) {
112
			if (((this.constantExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) {
113
				scope.problemReporter().enumConstantsCannotBeSurroundedByParenthesis(this.constantExpression);
114
			}
111
115
112
				if (constantExpression instanceof NameReference
116
			if (this.constantExpression instanceof NameReference
113
						&& (constantExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
117
					&& (this.constantExpression.bits & ASTNode.RestrictiveFlagMASK) == Binding.FIELD) {
114
					NameReference reference = (NameReference) constantExpression;
118
				NameReference reference = (NameReference) this.constantExpression;
115
					FieldBinding field = reference.fieldBinding();
119
				FieldBinding field = reference.fieldBinding();
116
					if ((field.modifiers & ClassFileConstants.AccEnum) == 0) {
120
				if ((field.modifiers & ClassFileConstants.AccEnum) == 0) {
117
						 scope.problemReporter().enumSwitchCannotTargetField(reference, field);
121
					 scope.problemReporter().enumSwitchCannotTargetField(reference, field);
118
					} else 	if (reference instanceof QualifiedNameReference) {
122
				} else 	if (reference instanceof QualifiedNameReference) {
119
						 scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel(reference, field);
123
					 scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel(reference, field);
120
					}
121
					return IntConstant.fromValue(field.original().id + 1); // (ordinal value + 1) zero should not be returned see bug 141810
122
				}
124
				}
123
			} else {
125
				return IntConstant.fromValue(field.original().id + 1); // (ordinal value + 1) zero should not be returned see bug 141810
124
				return constantExpression.constant;
125
			}
126
			}
126
		} else if (scope.isBoxingCompatibleWith(caseType, switchExpressionType)
127
		} else {
127
						|| (caseType.isBaseType()  // narrowing then boxing ?
128
			return this.constantExpression.constant;
128
								&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
129
								&& !switchExpressionType.isBaseType()
130
								&& constantExpression.isConstantValueOfTypeAssignableToType(caseType, scope.environment().computeBoxingType(switchExpressionType)))) {
131
			// constantExpression.computeConversion(scope, caseType, switchExpressionType); - do not report boxing/unboxing conversion
132
			return constantExpression.constant;
133
		}
129
		}
134
		scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
130
	} else if (scope.isBoxingCompatibleWith(caseType, switchExpressionType)
135
		return Constant.NotAConstant;
131
					|| (caseType.isBaseType()  // narrowing then boxing ?
132
							&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
133
							&& !switchExpressionType.isBaseType()
134
							&& this.constantExpression.isConstantValueOfTypeAssignableToType(caseType, scope.environment().computeBoxingType(switchExpressionType)))) {
135
		// constantExpression.computeConversion(scope, caseType, switchExpressionType); - do not report boxing/unboxing conversion
136
		return this.constantExpression.constant;
136
	}
137
	}
138
	scope.problemReporter().typeMismatchError(caseType, switchExpressionType, this.constantExpression);
139
	return Constant.NotAConstant;
140
}
137
141
138
142
public void traverse(ASTVisitor visitor, 	BlockScope blockScope) {
139
	public void traverse(
143
	if (visitor.visit(this, blockScope)) {
140
		ASTVisitor visitor,
144
		if (this.constantExpression != null) this.constantExpression.traverse(visitor, blockScope);
141
		BlockScope blockScope) {
142
143
		if (visitor.visit(this, blockScope)) {
144
			if (constantExpression != null) constantExpression.traverse(visitor, blockScope);
145
		}
146
		visitor.endVisit(this, blockScope);
147
	}
145
	}
146
	visitor.endVisit(this, blockScope);
147
}
148
}
148
}
(-)codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java (-1 / +3 lines)
Lines 2282-2288 Link Here
2282
			char[][] alreadyUsedConstants = new char[switchStatement.caseCount][];
2282
			char[][] alreadyUsedConstants = new char[switchStatement.caseCount][];
2283
			int alreadyUsedConstantCount = 0;
2283
			int alreadyUsedConstantCount = 0;
2284
			for (int i = 0; i < switchStatement.caseCount; i++) {
2284
			for (int i = 0; i < switchStatement.caseCount; i++) {
2285
				if(cases[i].isEnumConstant && cases[i].constantExpression instanceof SingleNameReference) {
2285
				Expression caseExpression = cases[i].constantExpression;
2286
				if((caseExpression instanceof SingleNameReference)
2287
						&& (caseExpression.resolvedType != null && caseExpression.resolvedType.isEnum())) {
2286
					alreadyUsedConstants[alreadyUsedConstantCount++] = ((SingleNameReference)cases[i].constantExpression).token;
2288
					alreadyUsedConstants[alreadyUsedConstantCount++] = ((SingleNameReference)cases[i].constantExpression).token;
2287
				}
2289
				}
2288
			}
2290
			}

Return to bug 146556