1 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 26 public class MemberValuePair extends ASTNode { 27 28 public char[] name; 29 public Expression value; 30 public MethodBinding binding; 31 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 49 public StringBuffer print(int indent, StringBuffer output) { 50 output 51 .append(name) 52 .append(" = "); 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 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); 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; } 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; } 108 } else { 109 scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType()); 110 this.value.computeConversion(scope, requiredType, valueType); 111 } 112 113 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; 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()) { 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 |