|
Lines 12-32
Link Here
|
| 12 |
|
12 |
|
| 13 |
import org.eclipse.jdt.core.compiler.CharOperation; |
13 |
import org.eclipse.jdt.core.compiler.CharOperation; |
| 14 |
import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; |
14 |
import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; |
| 15 |
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; |
15 |
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; |
| 16 |
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; |
16 |
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; |
| 17 |
import org.eclipse.jdt.internal.compiler.lookup.TagBits; |
|
|
| 18 |
|
17 |
|
| 19 |
public class MethodInfo extends ClassFileStruct implements IBinaryMethod, AttributeNamesConstants, Comparable { |
18 |
public class MethodInfo extends ClassFileStruct implements IBinaryMethod, AttributeNamesConstants, Comparable { |
| 20 |
static private final char[][] noException = CharOperation.NO_CHAR_CHAR; |
19 |
static private final char[][] noException = CharOperation.NO_CHAR_CHAR; |
| 21 |
private int accessFlags; |
20 |
private int accessFlags; |
| 22 |
private int attributeBytes; |
21 |
private int attributeBytes; |
| 23 |
private int[] constantPoolOffsets; |
22 |
protected int[] constantPoolOffsets; |
| 24 |
private char[] descriptor; |
23 |
private char[] descriptor; |
| 25 |
private char[][] exceptionNames; |
24 |
private char[][] exceptionNames; |
| 26 |
private char[] name; |
25 |
private char[] name; |
| 27 |
private char[] signature; |
26 |
private char[] signature; |
| 28 |
private int signatureUtf8Offset; |
27 |
private int signatureUtf8Offset; |
| 29 |
private long tagBits; |
28 |
private long tagBits; |
|
|
29 |
/** method annotation as well as parameter annotations |
| 30 |
* index 0 always contains the method annotation info. |
| 31 |
* index 1 and onwards contains parameter annotation info. |
| 32 |
* If the array is of size 0, there are no annotations. |
| 33 |
* If the array is of size 1, there are only method annotations. |
| 34 |
* if the array has a size greater than 1, then there are at least |
| 35 |
* parameter annotations. |
| 36 |
*/ |
| 37 |
private AnnotationInfo[][] allAnnotations; |
| 30 |
|
38 |
|
| 31 |
/** |
39 |
/** |
| 32 |
* @param classFileBytes byte[] |
40 |
* @param classFileBytes byte[] |
|
Lines 45-51
Link Here
|
| 45 |
int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; |
53 |
int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; |
| 46 |
char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); |
54 |
char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); |
| 47 |
if (attributeName.length > 0) { |
55 |
if (attributeName.length > 0) { |
| 48 |
switch(attributeName[0]) { |
56 |
switch(attributeName[0]) { |
| 49 |
case 'S' : |
57 |
case 'S' : |
| 50 |
if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) { |
58 |
if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) { |
| 51 |
this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset; |
59 |
this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset; |
|
Lines 53-59
Link Here
|
| 53 |
break; |
61 |
break; |
| 54 |
case 'R' : |
62 |
case 'R' : |
| 55 |
if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) { |
63 |
if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) { |
| 56 |
decodeStandardAnnotations(readOffset); |
64 |
decodeMethodAnnotations(readOffset, true); |
|
|
65 |
} |
| 66 |
else if (CharOperation.equals(attributeName, RuntimeInvisibleAnnotationsName)) { |
| 67 |
decodeMethodAnnotations(readOffset, false); |
| 68 |
} |
| 69 |
else if( CharOperation.equals(attributeName, RuntimeVisibleParameterAnnotationsName)){ |
| 70 |
decodeParamAnnotations(readOffset, true); |
| 71 |
} |
| 72 |
else if( CharOperation.equals(attributeName, RuntimeInvisibleParameterAnnotationsName)){ |
| 73 |
decodeParamAnnotations(readOffset, false); |
| 57 |
} |
74 |
} |
| 58 |
} |
75 |
} |
| 59 |
} |
76 |
} |
|
Lines 71-138
Link Here
|
| 71 |
if (result != 0) return result; |
88 |
if (result != 0) return result; |
| 72 |
return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor())); |
89 |
return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor())); |
| 73 |
} |
90 |
} |
| 74 |
private int decodeAnnotation(int offset) { |
91 |
|
| 75 |
int readOffset = offset; |
92 |
/** |
| 76 |
int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset; |
93 |
* @param offset the offset is located at the beginning of the |
| 77 |
char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); |
94 |
* parameter annotation attribute. |
| 78 |
int numberOfPairs = u2At(offset + 2); |
95 |
*/ |
| 79 |
readOffset += 4; |
96 |
private void decodeParamAnnotations(int offset, boolean runtimeVisible) |
| 80 |
if (typeName.length == 22 && CharOperation.equals(typeName, ConstantPool.JAVA_LANG_DEPRECATED)) { |
97 |
{ |
| 81 |
this.tagBits |= TagBits.AnnotationDeprecated; |
98 |
// u1 num_parameters; |
| 82 |
return readOffset; |
99 |
int numberOfParameters = u1At(offset + 6); |
| 83 |
} |
100 |
if( numberOfParameters > 0 ){ |
| 84 |
for (int i = 0; i < numberOfPairs; i++) { |
101 |
// u2 attribute_name_index + u4 attribute_length + u1 num_parameters |
| 85 |
readOffset += 2; |
102 |
int readOffset = offset + 7; |
| 86 |
readOffset = decodeElementValue(readOffset); |
103 |
for( int i=0; i<numberOfParameters; i++ ){ |
|
|
104 |
int numberOfAnnotations = u2At(readOffset); |
| 105 |
readOffset += 2; |
| 106 |
if( numberOfAnnotations > 0 ){ |
| 107 |
if(this.allAnnotations == null){ |
| 108 |
this.allAnnotations = new AnnotationInfo[numberOfParameters + 1][]; |
| 109 |
for(int j=0, len = numberOfParameters + 1; j < len; j++){ |
| 110 |
this.allAnnotations[j] = null; |
| 111 |
} |
| 112 |
} |
| 113 |
else{ |
| 114 |
if( this.allAnnotations.length == 1 ){ |
| 115 |
// make room for the parameter annotations |
| 116 |
final AnnotationInfo[][] newArray = new AnnotationInfo[numberOfParameters + 1][]; |
| 117 |
newArray[0] = this.allAnnotations[0]; |
| 118 |
this.allAnnotations = newArray; |
| 119 |
for(int j=1; j <= numberOfParameters; j++){ |
| 120 |
this.allAnnotations[j] = null; |
| 121 |
} |
| 122 |
} |
| 123 |
// else |
| 124 |
// have already initialize the field to the proper size. |
| 125 |
} |
| 126 |
final AnnotationInfo[] annos = |
| 127 |
decodeAnnotations(readOffset, runtimeVisible, numberOfAnnotations); |
| 128 |
for( int aIndex = 0; aIndex < annos.length; aIndex ++ ) |
| 129 |
readOffset += annos[aIndex].getLength(); |
| 130 |
final int paramAnnoIndex = i + 1; |
| 131 |
if( this.allAnnotations[paramAnnoIndex] == null ) |
| 132 |
this.allAnnotations[paramAnnoIndex] = annos; |
| 133 |
else{ |
| 134 |
final int curlen = this.allAnnotations[paramAnnoIndex].length; |
| 135 |
final int newTotal = curlen + numberOfAnnotations; |
| 136 |
final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal]; |
| 137 |
System.arraycopy(this.allAnnotations[paramAnnoIndex], 0, newAnnos, 0, curlen); |
| 138 |
System.arraycopy(annos, 0, newAnnos, curlen, numberOfAnnotations); |
| 139 |
this.allAnnotations[paramAnnoIndex] = newAnnos; |
| 140 |
} |
| 141 |
} |
| 142 |
} |
| 87 |
} |
143 |
} |
| 88 |
return readOffset; |
|
|
| 89 |
} |
144 |
} |
| 90 |
private int decodeElementValue(int offset) { |
145 |
|
| 91 |
int readOffset = offset; |
146 |
/** |
| 92 |
int tag = u1At(readOffset); |
147 |
* @param offset begining of the 'RuntimeVisibleAnnotation' or 'RuntimeInvisibleAnnotation' |
| 93 |
readOffset++; |
148 |
* attribute. |
| 94 |
switch(tag) { |
149 |
* @param runtimeVisible <code>true</code> to indicate decoding 'RuntimeVisibleAnnotation' |
| 95 |
case 'B' : |
150 |
*/ |
| 96 |
case 'C' : |
151 |
private void decodeMethodAnnotations(int offset, boolean runtimeVisible){ |
| 97 |
case 'D' : |
152 |
int numberOfAnnotations = u2At(offset + 6); |
| 98 |
case 'F' : |
153 |
final AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations); |
| 99 |
case 'I' : |
154 |
|
| 100 |
case 'J' : |
155 |
if( numberOfAnnotations > 0 ){ |
| 101 |
case 'S' : |
156 |
if( runtimeVisible ){ |
| 102 |
case 'Z' : |
157 |
for( int i=0; i<numberOfAnnotations; i++ ){ |
| 103 |
case 's' : |
158 |
this.tagBits |= annos[i].getStandardAnnotationTagBits(); |
| 104 |
readOffset += 2; |
|
|
| 105 |
break; |
| 106 |
case 'e' : |
| 107 |
readOffset += 4; |
| 108 |
break; |
| 109 |
case 'c' : |
| 110 |
readOffset += 2; |
| 111 |
break; |
| 112 |
case '@' : |
| 113 |
readOffset += decodeAnnotation(readOffset); |
| 114 |
break; |
| 115 |
case '[' : |
| 116 |
int numberOfValues = u2At(readOffset); |
| 117 |
readOffset += 2; |
| 118 |
for (int i = 0; i < numberOfValues; i++) { |
| 119 |
readOffset = decodeElementValue(readOffset); |
| 120 |
} |
159 |
} |
| 121 |
break; |
160 |
} |
|
|
161 |
|
| 162 |
if( this.allAnnotations == null ) |
| 163 |
this.allAnnotations = new AnnotationInfo[][]{annos}; |
| 164 |
else{ |
| 165 |
int curlen = this.allAnnotations[0].length; |
| 166 |
int newTotal = curlen + numberOfAnnotations; |
| 167 |
final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal]; |
| 168 |
System.arraycopy(this.allAnnotations[0], 0, newAnnos, 0, curlen); |
| 169 |
System.arraycopy(annos, 0, newAnnos, curlen, numberOfAnnotations); |
| 170 |
this.allAnnotations[0] = newAnnos; |
| 171 |
} |
| 122 |
} |
172 |
} |
| 123 |
return readOffset; |
|
|
| 124 |
} |
173 |
} |
|
|
174 |
|
| 125 |
/** |
175 |
/** |
| 126 |
* @param offset the offset is located at the beginning of the runtime visible |
176 |
* @param offset the offset is located at the beginning of the |
| 127 |
* annotation attribute. |
177 |
* annotation attribute. |
| 128 |
*/ |
178 |
*/ |
| 129 |
private void decodeStandardAnnotations(int offset) { |
179 |
private AnnotationInfo[] decodeAnnotations(int offset, |
| 130 |
int numberOfAnnotations = u2At(offset + 6); |
180 |
boolean runtimeVisible, |
| 131 |
int readOffset = offset + 8; |
181 |
int numberOfAnnotations) { |
|
|
182 |
int readOffset = offset; |
| 183 |
AnnotationInfo[] result = null; |
| 184 |
if( numberOfAnnotations > 0 ){ |
| 185 |
result = new AnnotationInfo[numberOfAnnotations]; |
| 186 |
} |
| 187 |
|
| 132 |
for (int i = 0; i < numberOfAnnotations; i++) { |
188 |
for (int i = 0; i < numberOfAnnotations; i++) { |
| 133 |
readOffset = decodeAnnotation(readOffset); |
189 |
result[i] = new AnnotationInfo(reference, |
|
|
190 |
readOffset + structOffset, |
| 191 |
this.constantPoolOffsets, |
| 192 |
runtimeVisible, |
| 193 |
false); |
| 194 |
readOffset = result[i].getLength() + readOffset; |
| 134 |
} |
195 |
} |
|
|
196 |
return result; |
| 135 |
} |
197 |
} |
|
|
198 |
|
| 199 |
/** |
| 200 |
* @return the annotations or null if there is none. |
| 201 |
*/ |
| 202 |
public IBinaryAnnotation[] getAnnotations(){ |
| 203 |
if( this.allAnnotations == null || this.allAnnotations.length == 0 ) return null; |
| 204 |
return this.allAnnotations[0]; |
| 205 |
} |
| 206 |
|
| 207 |
public IBinaryAnnotation[] getParameterAnnotations(int index) |
| 208 |
{ |
| 209 |
if(this.allAnnotations == null || this.allAnnotations.length < 2 ) return null; |
| 210 |
return this.allAnnotations[index + 1]; |
| 211 |
} |
| 212 |
|
| 136 |
/** |
213 |
/** |
| 137 |
* @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames() |
214 |
* @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames() |
| 138 |
*/ |
215 |
*/ |
|
Lines 221-226
Link Here
|
| 221 |
getMethodDescriptor(); |
298 |
getMethodDescriptor(); |
| 222 |
getExceptionTypeNames(); |
299 |
getExceptionTypeNames(); |
| 223 |
getGenericSignature(); |
300 |
getGenericSignature(); |
|
|
301 |
if( this.allAnnotations != null ){ |
| 302 |
for( int i=0, max = this.allAnnotations.length; i<max; i++ ){ |
| 303 |
if( this.allAnnotations[i] != null ){ |
| 304 |
for( int aIndex=0, aMax = this.allAnnotations[i].length; aIndex<aMax; aIndex++ ){ |
| 305 |
final AnnotationInfo anno = this.allAnnotations[i][aIndex]; |
| 306 |
anno.initialize(); |
| 307 |
} |
| 308 |
} |
| 309 |
} |
| 310 |
} |
| 224 |
reset(); |
311 |
reset(); |
| 225 |
} |
312 |
} |
| 226 |
/** |
313 |
/** |
|
Lines 306-311
Link Here
|
| 306 |
} |
393 |
} |
| 307 |
protected void reset() { |
394 |
protected void reset() { |
| 308 |
this.constantPoolOffsets = null; |
395 |
this.constantPoolOffsets = null; |
|
|
396 |
if( this.allAnnotations != null ){ |
| 397 |
for( int i=0, max = this.allAnnotations.length; i<max; i++ ){ |
| 398 |
if( this.allAnnotations[i] != null ){ |
| 399 |
final int aMax = this.allAnnotations[i].length; |
| 400 |
for( int aIndex=0; aIndex<aMax; aIndex++ ){ |
| 401 |
final AnnotationInfo anno = this.allAnnotations[i][aIndex]; |
| 402 |
anno.reset(); |
| 403 |
} |
| 404 |
} |
| 405 |
} |
| 406 |
} |
| 309 |
super.reset(); |
407 |
super.reset(); |
| 310 |
} |
408 |
} |
| 311 |
/** |
409 |
/** |
|
Lines 316-328
Link Here
|
| 316 |
public int sizeInBytes() { |
414 |
public int sizeInBytes() { |
| 317 |
return attributeBytes; |
415 |
return attributeBytes; |
| 318 |
} |
416 |
} |
| 319 |
public String toString() { |
417 |
|
|
|
418 |
public Object getDefaultValue(){ return null; } |
| 419 |
|
| 420 |
void toString(StringBuffer buffer) |
| 421 |
{ |
| 320 |
int modifiers = getModifiers(); |
422 |
int modifiers = getModifiers(); |
| 321 |
char[] desc = getGenericSignature(); |
423 |
char[] desc = getGenericSignature(); |
| 322 |
if (desc == null) |
424 |
if (desc == null) |
| 323 |
desc = getMethodDescriptor(); |
425 |
desc = getMethodDescriptor(); |
| 324 |
StringBuffer buffer = new StringBuffer(this.getClass().getName()); |
426 |
|
| 325 |
return buffer |
427 |
buffer.append(this.getClass().getName()); |
|
|
428 |
|
| 429 |
final int totalNumAnno = this.allAnnotations == null ? 0 : this.allAnnotations.length; |
| 430 |
if(totalNumAnno > 0){ |
| 431 |
buffer.append('\n'); |
| 432 |
if(this.allAnnotations[0] != null ){ |
| 433 |
for( int i=0, len = this.allAnnotations[0].length; i<len; i++ ){ |
| 434 |
|
| 435 |
buffer.append(this.allAnnotations[0][i]); |
| 436 |
buffer.append('\n'); |
| 437 |
} |
| 438 |
} |
| 439 |
} |
| 440 |
|
| 441 |
if(totalNumAnno > 1){ |
| 442 |
buffer.append('\n'); |
| 443 |
for( int i=1; i<totalNumAnno; i++ ){ |
| 444 |
buffer.append("param" + (i-1)); //$NON-NLS-1$ |
| 445 |
buffer.append('\n'); |
| 446 |
if( this.allAnnotations[i] != null ){ |
| 447 |
for( int j=0, numParamAnno=this.allAnnotations[i].length; j<numParamAnno; j++){ |
| 448 |
buffer.append(this.allAnnotations[i][j]); |
| 449 |
buffer.append('\n'); |
| 450 |
} |
| 451 |
} |
| 452 |
} |
| 453 |
} |
| 454 |
|
| 455 |
buffer |
| 326 |
.append("{") //$NON-NLS-1$ |
456 |
.append("{") //$NON-NLS-1$ |
| 327 |
.append( |
457 |
.append( |
| 328 |
((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$ |
458 |
((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$ |
|
Lines 335-341
Link Here
|
| 335 |
+ ((modifiers & 0x0080) == 0x0080 ? "varargs " : "")) //$NON-NLS-1$ //$NON-NLS-2$ |
465 |
+ ((modifiers & 0x0080) == 0x0080 ? "varargs " : "")) //$NON-NLS-1$ //$NON-NLS-2$ |
| 336 |
.append(getSelector()) |
466 |
.append(getSelector()) |
| 337 |
.append(desc) |
467 |
.append(desc) |
| 338 |
.append("}") //$NON-NLS-1$ |
468 |
.append("}"); //$NON-NLS-1$ |
| 339 |
.toString(); |
469 |
} |
|
|
470 |
public String toString() { |
| 471 |
final StringBuffer buffer = new StringBuffer(); |
| 472 |
toString(buffer); |
| 473 |
return buffer.toString(); |
| 340 |
} |
474 |
} |
| 341 |
} |
475 |
} |