Refactory: phphelp plugin.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / AnnotationBinding.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.lookup;
12
13 import net.sourceforge.phpdt.internal.compiler.ast.Annotation;
14
15 /**
16  * Represents JSR 175 Annotation instances in the type-system.
17  */ 
18 public class AnnotationBinding {
19         // do not access directly - use getters instead (UnresolvedAnnotationBinding
20         // resolves types for type and pair contents just in time)
21         ReferenceBinding type;
22         ElementValuePair[] pairs;
23
24 /**
25  * Add the standard annotations encoded in the tag bits to the recorded annotations.
26  * 
27  * @param recordedAnnotations existing annotations already created
28  * @param annotationTagBits
29  * @param env
30  * @return the combined list of annotations
31  */
32 public static AnnotationBinding[] addStandardAnnotations(AnnotationBinding[] recordedAnnotations, long annotationTagBits, LookupEnvironment env) {
33         // NOTE: expect annotations to be requested just once so there is no need to store the standard annotations
34         // and all of the standard annotations created by this method are fully resolved since the sender is expected to use them immediately
35         int count = 0;
36         if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0)
37                 count++;
38         if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0)
39                 count++;
40         if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0)
41                 count++;
42         if ((annotationTagBits & TagBits.AnnotationDocumented) != 0)
43                 count++;
44         if ((annotationTagBits & TagBits.AnnotationInherited) != 0)
45                 count++;
46         if ((annotationTagBits & TagBits.AnnotationOverride) != 0)
47                 count++;
48         if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0)
49                 count++;
50         if (count == 0)
51                 return recordedAnnotations;
52
53         int index = recordedAnnotations.length;
54         AnnotationBinding[] result = new AnnotationBinding[index + count];
55         System.arraycopy(recordedAnnotations, 0, result, 0, index);
56         if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0)
57                 result[index++] = buildTargetAnnotation(annotationTagBits, env);
58         if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0)
59                 result[index++] = buildRetentionAnnotation(annotationTagBits, env);
60         if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0)
61                 result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_DEPRECATED, env);
62         if ((annotationTagBits & TagBits.AnnotationDocumented) != 0)
63                 result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED, env);
64         if ((annotationTagBits & TagBits.AnnotationInherited) != 0)
65                 result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_INHERITED, env);
66         if ((annotationTagBits & TagBits.AnnotationOverride) != 0)
67                 result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, env);
68         if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0)
69                 result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, env);
70         return result;
71 }
72
73 private static AnnotationBinding buildMarkerAnnotation(char[][] compoundName, LookupEnvironment env) {
74         ReferenceBinding type = env.getResolvedType(compoundName, null);
75         return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS);
76 }
77
78 private static AnnotationBinding buildRetentionAnnotation(long bits, LookupEnvironment env) {
79         ReferenceBinding retentionPolicy = 
80                 env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY, 
81                         null);
82         Object value = null;
83         if ((bits & TagBits.AnnotationRuntimeRetention) != 0)
84                 value = retentionPolicy.getField(TypeConstants.UPPER_RUNTIME, true);
85         else if ((bits & TagBits.AnnotationClassRetention) != 0)
86                 value = retentionPolicy.getField(TypeConstants.UPPER_CLASS, true);
87         else if ((bits & TagBits.AnnotationSourceRetention) != 0)
88                 value = retentionPolicy.getField(TypeConstants.UPPER_SOURCE, true);
89         return env.createAnnotation(
90                 env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTION, null),
91                 new ElementValuePair[] { 
92                         new ElementValuePair(TypeConstants.VALUE, value, null)
93                 });
94 }
95
96 private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironment env) {
97         ReferenceBinding target = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_TARGET, null);
98         if ((bits & TagBits.AnnotationTarget) != 0)
99                 return new AnnotationBinding(target, Binding.NO_ELEMENT_VALUE_PAIRS);
100
101         int arraysize = 0;
102         if ((bits & TagBits.AnnotationForAnnotationType) != 0)
103                 arraysize++;
104         if ((bits & TagBits.AnnotationForConstructor) != 0)
105                 arraysize++;
106         if ((bits & TagBits.AnnotationForField) != 0)
107                 arraysize++;
108         if ((bits & TagBits.AnnotationForLocalVariable) != 0)
109                 arraysize++;
110         if ((bits & TagBits.AnnotationForMethod) != 0)
111                 arraysize++;
112         if ((bits & TagBits.AnnotationForPackage) != 0)
113                 arraysize++;
114         if ((bits & TagBits.AnnotationForParameter) != 0)
115                 arraysize++;
116         if ((bits & TagBits.AnnotationForType) != 0)
117                 arraysize++;
118         Object[] value = new Object[arraysize];
119         if (arraysize > 0) {
120                 ReferenceBinding elementType = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, null);
121                 int index = 0;
122                 if ((bits & TagBits.AnnotationForAnnotationType) != 0)
123                         value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true);
124                 if ((bits & TagBits.AnnotationForConstructor) != 0)
125                         value[index++] = elementType.getField(TypeConstants.UPPER_CONSTRUCTOR, true);
126                 if ((bits & TagBits.AnnotationForField) != 0)
127                         value[index++] = elementType.getField(TypeConstants.UPPER_FIELD, true);
128                 if ((bits & TagBits.AnnotationForLocalVariable) != 0)
129                         value[index++] = elementType.getField(TypeConstants.UPPER_LOCAL_VARIABLE, true);
130                 if ((bits & TagBits.AnnotationForMethod) != 0)
131                         value[index++] = elementType.getField(TypeConstants.UPPER_METHOD, true);
132                 if ((bits & TagBits.AnnotationForPackage) != 0)
133                         value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true);
134                 if ((bits & TagBits.AnnotationForParameter) != 0)
135                         value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true);
136                 if ((bits & TagBits.AnnotationForType) != 0)
137                         value[index++] = elementType.getField(TypeConstants.TYPE, true);
138         }
139         return env.createAnnotation(
140                         target,
141                         new ElementValuePair[] {
142                                 new ElementValuePair(TypeConstants.VALUE, value, null)
143                         });
144 }
145
146 AnnotationBinding(ReferenceBinding type, ElementValuePair[] pairs) {
147         this.type = type;
148         this.pairs = pairs;
149 }
150
151 AnnotationBinding(Annotation astAnnotation) {
152         this((ReferenceBinding) astAnnotation.resolvedType, astAnnotation.computeElementValuePairs());
153 }
154
155 /*
156  * Computes a key that uniquely identifies this binding, using the given recipient's unique key.
157  * recipientKey @ typeKey
158  * @MyAnnot void bar() --> Lp/X;.bar()V@Lp/MyAnnot;
159  */
160 public char[] computeUniqueKey(char[] recipientKey) {
161         char[] typeKey = this.type.computeUniqueKey(false);
162         int recipientKeyLength = recipientKey.length;
163         char[] uniqueKey = new char[recipientKeyLength+1+typeKey.length];
164         System.arraycopy(recipientKey, 0, uniqueKey, 0, recipientKeyLength);
165         uniqueKey[recipientKeyLength] = '@';
166         System.arraycopy(typeKey, 0, uniqueKey, recipientKeyLength+1, typeKey.length);
167         return uniqueKey;
168 }
169
170 public ReferenceBinding getAnnotationType() {
171         return this.type;
172 }
173
174 public ElementValuePair[] getElementValuePairs() {
175         return this.pairs;
176 }
177
178 public static void setMethodBindings(ReferenceBinding type, ElementValuePair[] pairs) {
179         // set the method bindings of each element value pair
180         for (int i = pairs.length; --i >= 0;) {
181                 ElementValuePair pair = pairs[i];
182                 MethodBinding[] methods = type.getMethods(pair.getName());
183                 // there should be exactly one since the type is an annotation type.
184                 if (methods != null && methods.length == 1)
185                         pair.setMethodBinding(methods[0]);
186         }
187 }
188
189 public String toString() {
190         StringBuffer buffer = new StringBuffer(5);
191         buffer.append('@').append(this.type.sourceName);
192         if (this.pairs != null && this.pairs.length > 0) {
193                 buffer.append("{ "); //$NON-NLS-1$
194                 for (int i = 0, max = this.pairs.length; i < max; i++) {
195                         if (i > 0) buffer.append(", "); //$NON-NLS-1$
196                         buffer.append(this.pairs[i]);
197                 }
198                 buffer.append('}');
199         }
200         return buffer.toString();
201 }
202 }