1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.ASTVisitor; 15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 16 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 17 import org.eclipse.jdt.internal.compiler.impl.Constant; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 23 public abstract class Annotation extends Expression { 24 25 final static MemberValuePair[] NoValuePairs = new MemberValuePair[0]; 26 public int declarationSourceEnd; 27 public Binding recipient; 28 29 public TypeReference type; 30 33 private AnnotationBinding compilerAnnotation = null; 34 35 public static long getRetentionPolicy(char[] policyName) { 36 if (policyName == null || policyName.length == 0) 37 return 0; 38 switch(policyName[0]) { 39 case 'C' : 40 if (CharOperation.equals(policyName, TypeConstants.UPPER_CLASS)) 41 return TagBits.AnnotationClassRetention; 42 break; 43 case 'S' : 44 if (CharOperation.equals(policyName, TypeConstants.UPPER_SOURCE)) 45 return TagBits.AnnotationSourceRetention; 46 break; 47 case 'R' : 48 if (CharOperation.equals(policyName, TypeConstants.UPPER_RUNTIME)) 49 return TagBits.AnnotationRuntimeRetention; 50 break; 51 } 52 return 0; } 54 55 public static long getTargetElementType(char[] elementName) { 56 if (elementName == null || elementName.length == 0) 57 return 0; 58 switch(elementName[0]) { 59 case 'A' : 60 if (CharOperation.equals(elementName, TypeConstants.UPPER_ANNOTATION_TYPE)) 61 return TagBits.AnnotationForAnnotationType; 62 break; 63 case 'C' : 64 if (CharOperation.equals(elementName, TypeConstants.UPPER_CONSTRUCTOR)) 65 return TagBits.AnnotationForConstructor; 66 break; 67 case 'F' : 68 if (CharOperation.equals(elementName, TypeConstants.UPPER_FIELD)) 69 return TagBits.AnnotationForField; 70 break; 71 case 'L' : 72 if (CharOperation.equals(elementName, TypeConstants.UPPER_LOCAL_VARIABLE)) 73 return TagBits.AnnotationForLocalVariable; 74 break; 75 case 'M' : 76 if (CharOperation.equals(elementName, TypeConstants.UPPER_METHOD)) 77 return TagBits.AnnotationForMethod; 78 break; 79 case 'P' : 80 if (CharOperation.equals(elementName, TypeConstants.UPPER_PARAMETER)) 81 return TagBits.AnnotationForParameter; 82 else if (CharOperation.equals(elementName, TypeConstants.UPPER_PACKAGE)) 83 return TagBits.AnnotationForPackage; 84 break; 85 case 'T' : 86 if (CharOperation.equals(elementName, TypeConstants.TYPE)) 87 return TagBits.AnnotationForType; 88 break; 89 } 90 return 0; } 92 93 public ElementValuePair[] computeElementValuePairs() { 94 return Binding.NO_ELEMENT_VALUE_PAIRS; 95 } 96 97 100 private long detectStandardAnnotation(Scope scope, ReferenceBinding annotationType, MemberValuePair valueAttribute) { 101 long tagBits = 0; 102 switch (annotationType.id) { 103 case TypeIds.T_JavaLangAnnotationRetention : 105 if (valueAttribute != null) { 106 Expression expr = valueAttribute.value; 107 if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) { 108 FieldBinding field = ((Reference)expr).fieldBinding(); 109 if (field != null && field.declaringClass.id == T_JavaLangAnnotationRetentionPolicy) { 110 tagBits |= getRetentionPolicy(field.name); 111 } 112 } 113 } 114 break; 115 case TypeIds.T_JavaLangAnnotationTarget : 117 tagBits |= TagBits.AnnotationTarget; if (valueAttribute != null) { 119 Expression expr = valueAttribute.value; 120 if (expr instanceof ArrayInitializer) { 121 ArrayInitializer initializer = (ArrayInitializer) expr; 122 final Expression[] expressions = initializer.expressions; 123 if (expressions != null) { 124 for (int i = 0, length = expressions.length; i < length; i++) { 125 Expression initExpr = expressions[i]; 126 if ((initExpr.bits & Binding.VARIABLE) == Binding.FIELD) { 127 FieldBinding field = ((Reference) initExpr).fieldBinding(); 128 if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) { 129 long element = getTargetElementType(field.name); 130 if ((tagBits & element) != 0) { 131 scope.problemReporter().duplicateTargetInTargetAnnotation(annotationType, (NameReference)initExpr); 132 } else { 133 tagBits |= element; 134 } 135 } 136 } 137 } 138 } 139 } else if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) { 140 FieldBinding field = ((Reference) expr).fieldBinding(); 141 if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) { 142 tagBits |= getTargetElementType(field.name); 143 } 144 } 145 } 146 break; 147 case TypeIds.T_JavaLangDeprecated : 149 tagBits |= TagBits.AnnotationDeprecated; 150 break; 151 case TypeIds.T_JavaLangAnnotationDocumented : 152 tagBits |= TagBits.AnnotationDocumented; 153 break; 154 case TypeIds.T_JavaLangAnnotationInherited : 155 tagBits |= TagBits.AnnotationInherited; 156 break; 157 case TypeIds.T_JavaLangOverride : 158 tagBits |= TagBits.AnnotationOverride; 159 break; 160 case TypeIds.T_JavaLangSuppressWarnings : 161 tagBits |= TagBits.AnnotationSuppressWarnings; 162 break; 163 } 164 return tagBits; 165 } 166 167 public AnnotationBinding getCompilerAnnotation() { 168 return this.compilerAnnotation; 169 } 170 171 public abstract MemberValuePair[] memberValuePairs(); 172 173 public StringBuffer printExpression(int indent, StringBuffer output) { 174 output.append('@'); 175 this.type.printExpression(0, output); 176 return output; 177 } 178 179 public void recordSuppressWarnings(Scope scope, int startSuppresss, int endSuppress, boolean isSuppressingWarnings) { 180 long suppressWarningIrritants = 0; 181 MemberValuePair[] pairs = this.memberValuePairs(); 182 pairLoop: for (int i = 0, length = pairs.length; i < length; i++) { 183 MemberValuePair pair = pairs[i]; 184 if (CharOperation.equals(pair.name, TypeConstants.VALUE)) { 185 Expression value = pair.value; 186 if (value instanceof ArrayInitializer) { 187 ArrayInitializer initializer = (ArrayInitializer) value; 188 Expression[] inits = initializer.expressions; 189 if (inits != null) { 190 for (int j = 0, initsLength = inits.length; j < initsLength; j++) { 191 Constant cst = inits[j].constant; 192 if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) { 193 long irritant = CompilerOptions.warningTokenToIrritant(cst.stringValue()); 194 if (irritant != 0) { 195 suppressWarningIrritants |= irritant; 196 if (~suppressWarningIrritants == 0) break pairLoop; 197 } else { 198 scope.problemReporter().unhandledWarningToken(inits[j]); 199 } 200 } 201 } 202 } 203 } else { 204 Constant cst = value.constant; 205 if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) { 206 long irritant = CompilerOptions.warningTokenToIrritant(cst.stringValue()); 207 if (irritant != 0) { 208 suppressWarningIrritants |= irritant; 209 if (~suppressWarningIrritants == 0) break pairLoop; 210 } else { 211 scope.problemReporter().unhandledWarningToken(value); 212 } 213 } 214 } 215 break pairLoop; 216 } 217 } 218 if (isSuppressingWarnings && suppressWarningIrritants != 0) { 219 scope.referenceCompilationUnit().compilationResult.recordSuppressWarnings(suppressWarningIrritants, startSuppresss, endSuppress); 220 } 221 } 222 223 public TypeBinding resolveType(BlockScope scope) { 224 225 if (this.compilerAnnotation != null) 226 return this.resolvedType; 227 this.constant = Constant.NotAConstant; 228 229 TypeBinding typeBinding = this.type.resolveType(scope); 230 if (typeBinding == null) { 231 return null; 232 } 233 this.resolvedType = typeBinding; 234 if (!typeBinding.isAnnotationType()) { 236 scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type); 237 return null; 238 } 239 240 ReferenceBinding annotationType = (ReferenceBinding) this.resolvedType; 241 MethodBinding[] methods = annotationType.methods(); 242 MemberValuePair[] originalValuePairs = memberValuePairs(); 244 MemberValuePair valueAttribute = null; MemberValuePair[] pairs; 246 int pairsLength = originalValuePairs.length; 247 if (pairsLength > 0) { 248 System.arraycopy(originalValuePairs, 0, pairs = new MemberValuePair[pairsLength], 0, pairsLength); 249 } else { 250 pairs = originalValuePairs; 251 } 252 253 nextMember: for (int i = 0, requiredLength = methods.length; i < requiredLength; i++) { 254 MethodBinding method = methods[i]; 255 char[] selector = method.selector; 256 boolean foundValue = false; 257 nextPair: for (int j = 0; j < pairsLength; j++) { 258 MemberValuePair pair = pairs[j]; 259 if (pair == null) continue nextPair; 260 char[] name = pair.name; 261 if (CharOperation.equals(name, selector)) { 262 if (valueAttribute == null && CharOperation.equals(name, TypeConstants.VALUE)) { 263 valueAttribute = pair; 264 } 265 pair.binding = method; 266 pair.resolveTypeExpecting(scope, method.returnType); 267 pairs[j] = null; foundValue = true; 269 270 boolean foundDuplicate = false; 272 for (int k = j+1; k < pairsLength; k++) { 273 MemberValuePair otherPair = pairs[k]; 274 if (otherPair == null) continue; 275 if (CharOperation.equals(otherPair.name, selector)) { 276 foundDuplicate = true; 277 scope.problemReporter().duplicateAnnotationValue(annotationType, otherPair); 278 otherPair.binding = method; 279 otherPair.resolveTypeExpecting(scope, method.returnType); 280 pairs[k] = null; 281 } 282 } 283 if (foundDuplicate) { 284 scope.problemReporter().duplicateAnnotationValue(annotationType, pair); 285 continue nextMember; 286 } 287 } 288 } 289 if (!foundValue && (method.modifiers & ClassFileConstants.AccAnnotationDefault) == 0) { 290 scope.problemReporter().missingValueForAnnotationMember(this, selector); 291 } 292 } 293 for (int i = 0; i < pairsLength; i++) { 295 if (pairs[i] != null) { 296 scope.problemReporter().undefinedAnnotationValue(annotationType, pairs[i]); 297 pairs[i].resolveTypeExpecting(scope, null); } 299 } 300 this.compilerAnnotation = scope.environment().createAnnotation((ReferenceBinding) this.resolvedType, this.computeElementValuePairs()); 302 long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute); 304 305 scope.referenceCompilationUnit().compilationResult.recordSuppressWarnings(CompilerOptions.NonExternalizedString, this.sourceStart, this.declarationSourceEnd); 307 if (this.recipient != null) { 308 if (tagBits != 0) { 309 switch (this.recipient.kind()) { 311 case Binding.PACKAGE : 312 ((PackageBinding)this.recipient).tagBits |= tagBits; 313 break; 314 case Binding.TYPE : 315 case Binding.GENERIC_TYPE : 316 SourceTypeBinding sourceType = (SourceTypeBinding) this.recipient; 317 sourceType.tagBits |= tagBits; 318 if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { 319 TypeDeclaration typeDeclaration = sourceType.scope.referenceContext; 320 int start; 321 if (scope.referenceCompilationUnit().types[0] == typeDeclaration) { 322 start = 0; 323 } else { 324 start = typeDeclaration.declarationSourceStart; 325 } 326 recordSuppressWarnings(scope, start, typeDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); 327 } 328 break; 329 case Binding.METHOD : 330 MethodBinding sourceMethod = (MethodBinding) this.recipient; 331 sourceMethod.tagBits |= tagBits; 332 if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { 333 sourceType = (SourceTypeBinding) sourceMethod.declaringClass; 334 AbstractMethodDeclaration methodDeclaration = sourceType.scope.referenceContext.declarationOf(sourceMethod); 335 recordSuppressWarnings(scope, methodDeclaration.declarationSourceStart, methodDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); 336 } 337 break; 338 case Binding.FIELD : 339 FieldBinding sourceField = (FieldBinding) this.recipient; 340 sourceField.tagBits |= tagBits; 341 if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { 342 sourceType = (SourceTypeBinding) sourceField.declaringClass; 343 FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField); 344 recordSuppressWarnings(scope, fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); 345 } 346 break; 347 case Binding.LOCAL : 348 LocalVariableBinding variable = (LocalVariableBinding) this.recipient; 349 variable.tagBits |= tagBits; 350 if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { 351 LocalDeclaration localDeclaration = variable.declaration; 352 recordSuppressWarnings(scope, localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); 353 } 354 break; 355 } 356 } 357 checkTargetCompatibility: { 359 long metaTagBits = annotationType.getAnnotationTagBits(); if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) break checkTargetCompatibility; 362 363 switch (recipient.kind()) { 364 case Binding.PACKAGE : 365 if ((metaTagBits & TagBits.AnnotationForPackage) != 0) 366 break checkTargetCompatibility; 367 break; 368 case Binding.TYPE : 369 case Binding.GENERIC_TYPE : 370 if (((ReferenceBinding)this.recipient).isAnnotationType()) { 371 if ((metaTagBits & (TagBits.AnnotationForAnnotationType|TagBits.AnnotationForType)) != 0) 372 break checkTargetCompatibility; 373 } else if ((metaTagBits & TagBits.AnnotationForType) != 0) 374 break checkTargetCompatibility; 375 break; 376 case Binding.METHOD : 377 if (((MethodBinding)this.recipient).isConstructor()) { 378 if ((metaTagBits & TagBits.AnnotationForConstructor) != 0) 379 break checkTargetCompatibility; 380 } else if ((metaTagBits & TagBits.AnnotationForMethod) != 0) 381 break checkTargetCompatibility; 382 break; 383 case Binding.FIELD : 384 if ((metaTagBits & TagBits.AnnotationForField) != 0) 385 break checkTargetCompatibility; 386 break; 387 case Binding.LOCAL : 388 if ((((LocalVariableBinding)this.recipient).tagBits & TagBits.IsArgument) != 0) { 389 if ((metaTagBits & TagBits.AnnotationForParameter) != 0) 390 break checkTargetCompatibility; 391 } else if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0) 392 break checkTargetCompatibility; 393 break; 394 } 395 scope.problemReporter().disallowedTargetForAnnotation(this); 396 } 397 } 398 return this.resolvedType; 399 } 400 401 public abstract void traverse(ASTVisitor visitor, BlockScope scope); 402 403 } 404 | Popular Tags |