KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > MemberValuePair


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.Constant;
15 import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
16 import org.eclipse.jdt.internal.compiler.lookup.Binding;
17 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18 import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
19 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
20 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
21 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
22
23 /**
24  * MemberValuePair node
25  */

26 public class MemberValuePair extends ASTNode {
27     
28     public char[] name;
29     public Expression value;
30     public MethodBinding binding;
31     /**
32      * The representation of this pair in the type system.
33      */

34     public ElementValuePair compilerElementPair = null;
35     
36     public MemberValuePair(char[] token, int sourceStart, int sourceEnd, Expression value) {
37         this.name = token;
38         this.sourceStart = sourceStart;
39         this.sourceEnd = sourceEnd;
40         this.value = value;
41         if (value instanceof ArrayInitializer) {
42             value.bits |= IsAnnotationDefaultValue;
43         }
44     }
45     
46     /* (non-Javadoc)
47      * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
48      */

49     public StringBuffer JavaDoc print(int indent, StringBuffer JavaDoc output) {
50         output
51             .append(name)
52             .append(" = "); //$NON-NLS-1$
53
value.print(0, output);
54         return output;
55     }
56     
57     public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) {
58         
59         if (this.value == null) {
60             this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
61             return;
62         }
63         if (requiredType == null) {
64             // fault tolerance: keep resolving
65
if (this.value instanceof ArrayInitializer) {
66                 this.value.resolveTypeExpecting(scope, null);
67             } else {
68                 this.value.resolveType(scope);
69             }
70             this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
71             return;
72         }
73
74         this.value.setExpectedType(requiredType); // needed in case of generic method invocation
75
TypeBinding valueType;
76         if (this.value instanceof ArrayInitializer) {
77             ArrayInitializer initializer = (ArrayInitializer) this.value;
78             valueType = initializer.resolveTypeExpecting(scope, this.binding.returnType);
79         } else if (this.value instanceof ArrayAllocationExpression) {
80             scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value);
81             this.value.resolveType(scope);
82             valueType = null; // no need to pursue
83
} else {
84             valueType = this.value.resolveType(scope);
85         }
86         this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
87         if (valueType == null)
88             return;
89
90         TypeBinding leafType = requiredType.leafComponentType();
91         if (!((this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType)
92                 || (requiredType.isBaseType() && BaseTypeBinding.isWidening(requiredType.id, valueType.id)))
93                 || valueType.isCompatibleWith(requiredType))) {
94
95             if (!(requiredType.isArrayType()
96                     && requiredType.dimensions() == 1
97                     && (this.value.isConstantValueOfTypeAssignableToType(valueType, leafType)
98                             || (leafType.isBaseType() && BaseTypeBinding.isWidening(leafType.id, valueType.id)))
99                             || valueType.isCompatibleWith(leafType))) {
100                 
101                 if (leafType.isAnnotationType() && !valueType.isAnnotationType()) {
102                     scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);
103                 } else {
104                     scope.problemReporter().typeMismatchError(valueType, requiredType, this.value);
105                 }
106                 return; // may allow to proceed to find more errors at once
107
}
108         } else {
109             scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType());
110             this.value.computeConversion(scope, requiredType, valueType);
111         }
112         
113         // annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
114
checkAnnotationMethodType: {
115             switch (leafType.erasure().id) {
116                 case T_byte :
117                 case T_short :
118                 case T_char :
119                 case T_int :
120                 case T_long :
121                 case T_float :
122                 case T_double :
123                 case T_boolean :
124                 case T_JavaLangString :
125                     if (this.value instanceof ArrayInitializer) {
126                         ArrayInitializer initializer = (ArrayInitializer) this.value;
127                         final Expression[] expressions = initializer.expressions;
128                         if (expressions != null) {
129                             for (int i =0, max = expressions.length; i < max; i++) {
130                                 Expression expression = expressions[i];
131                                 if (expression.resolvedType == null) continue; // fault-tolerance
132
if (expression.constant == Constant.NotAConstant) {
133                                     scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, expressions[i], false);
134                                 }
135                             }
136                         }
137                     } else if (this.value.constant == Constant.NotAConstant) {
138                         if (valueType.isArrayType()) {
139                             scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value);
140                         } else {
141                             scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, false);
142                         }
143                     }
144                     break checkAnnotationMethodType;
145                 case T_JavaLangClass :
146                     if (this.value instanceof ArrayInitializer) {
147                         ArrayInitializer initializer = (ArrayInitializer) this.value;
148                         final Expression[] expressions = initializer.expressions;
149                         if (expressions != null) {
150                             for (int i =0, max = expressions.length; i < max; i++) {
151                                 Expression currentExpression = expressions[i];
152                                 if (!(currentExpression instanceof ClassLiteralAccess)) {
153                                     scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, currentExpression);
154                                 }
155                             }
156                         }
157                     } else if (!(this.value instanceof ClassLiteralAccess)) {
158                         scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, this.value);
159                     }
160                     break checkAnnotationMethodType;
161             }
162             if (leafType.isEnum()) {
163                 if (this.value instanceof NullLiteral) {
164                     scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true);
165                 } else if (this.value instanceof ArrayInitializer) {
166                     ArrayInitializer initializer = (ArrayInitializer) this.value;
167                     final Expression[] expressions = initializer.expressions;
168                     if (expressions != null) {
169                         for (int i =0, max = expressions.length; i < max; i++) {
170                             Expression currentExpression = expressions[i];
171                             if (currentExpression instanceof NullLiteral) {
172                                 scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, currentExpression, true);
173                             } else if (currentExpression instanceof NameReference) {
174                                 NameReference nameReference = (NameReference) currentExpression;
175                                 final Binding nameReferenceBinding = nameReference.binding;
176                                 if (nameReferenceBinding.kind() == Binding.FIELD) {
177                                     FieldBinding fieldBinding = (FieldBinding) nameReferenceBinding;
178                                     if (!fieldBinding.declaringClass.isEnum()) {
179                                         scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, currentExpression, true);
180                                     }
181                                 }
182                             }
183                         }
184                     }
185                 } else if (this.value instanceof NameReference) {
186                     NameReference nameReference = (NameReference) this.value;
187                     final Binding nameReferenceBinding = nameReference.binding;
188                     if (nameReferenceBinding.kind() == Binding.FIELD) {
189                         FieldBinding fieldBinding = (FieldBinding) nameReferenceBinding;
190                         if (!fieldBinding.declaringClass.isEnum()) {
191                             if (!fieldBinding.type.isArrayType()) {
192                                 scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true);
193                             } else {
194                                 scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value);
195                             }
196                         }
197                     }
198                 }
199                 break checkAnnotationMethodType;
200             }
201             if (leafType.isAnnotationType()) {
202                 if (!valueType.leafComponentType().isAnnotationType()) { // check annotation type and also reject null literal
203
scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);
204                 } else if (this.value instanceof ArrayInitializer) {
205                     ArrayInitializer initializer = (ArrayInitializer) this.value;
206                     final Expression[] expressions = initializer.expressions;
207                     if (expressions != null) {
208                         for (int i =0, max = expressions.length; i < max; i++) {
209                             Expression currentExpression = expressions[i];
210                             if (currentExpression instanceof NullLiteral || !(currentExpression instanceof Annotation)) {
211                                 scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, currentExpression, leafType);
212                             }
213                         }
214                     }
215                 } else if (!(this.value instanceof Annotation)) {
216                     scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);
217                 }
218                 break checkAnnotationMethodType;
219             }
220         }
221     }
222     
223     public void traverse(ASTVisitor visitor, BlockScope scope) {
224         if (visitor.visit(this, scope)) {
225             if (this.value != null) {
226                 this.value.traverse(visitor, scope);
227             }
228         }
229         visitor.endVisit(this, scope);
230     }
231 }
232
Popular Tags