1 11 package org.eclipse.jdt.internal.core.util; 12 13 import java.io.PrintWriter ; 14 import java.io.StringWriter ; 15 16 import org.eclipse.jdt.core.JavaCore; 17 import org.eclipse.jdt.core.Signature; 18 import org.eclipse.jdt.core.compiler.CharOperation; 19 import org.eclipse.jdt.core.util.*; 20 import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; 21 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; 22 23 27 public class Disassembler extends ClassFileBytesDisassembler { 28 29 private static final char[] ANY_EXCEPTION = Messages.classfileformat_anyexceptionhandler.toCharArray(); 30 private static final String VERSION_UNKNOWN = Messages.classfileformat_versionUnknown; 31 32 private boolean appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier) { 33 if ((accessFlags & modifierConstant) != 0) { 34 if (!firstModifier) { 35 buffer.append(Messages.disassembler_space); 36 } 37 if (firstModifier) { 38 firstModifier = false; 39 } 40 buffer.append(modifier); 41 } 42 return firstModifier; 43 } 44 45 private void decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits) { 46 decodeModifiers(buffer, accessFlags, false, false, checkBits); 47 } 48 49 private void decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits) { 50 if (checkBits == null) return; 51 boolean firstModifier = true; 52 for (int i = 0, max = checkBits.length; i < max; i++) { 53 switch(checkBits[i]) { 54 case IModifierConstants.ACC_PUBLIC : 55 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); break; 57 case IModifierConstants.ACC_PROTECTED : 58 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); break; 60 case IModifierConstants.ACC_PRIVATE : 61 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); break; 63 case IModifierConstants.ACC_ABSTRACT : 64 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); break; 66 case IModifierConstants.ACC_STATIC : 67 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); break; 69 case IModifierConstants.ACC_FINAL : 70 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); break; 72 case IModifierConstants.ACC_SYNCHRONIZED : 73 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); break; 75 case IModifierConstants.ACC_NATIVE : 76 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); break; 78 case IModifierConstants.ACC_STRICT : 79 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); break; 81 case IModifierConstants.ACC_TRANSIENT : 82 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); break; 84 case IModifierConstants.ACC_VOLATILE : 85 if (asBridge) { 87 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); } else { 89 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); } 91 break; 92 case IModifierConstants.ACC_ENUM : 93 firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); break; 95 } 96 } 97 if (!firstModifier) { 98 if (!printDefault) buffer.append(Messages.disassembler_space); 99 } else if (printDefault) { 100 buffer.append("default"); } 103 } 104 105 private void decodeModifiersForField(StringBuffer buffer, int accessFlags) { 106 decodeModifiers(buffer, accessFlags, new int[] { 107 IModifierConstants.ACC_PUBLIC, 108 IModifierConstants.ACC_PROTECTED, 109 IModifierConstants.ACC_PRIVATE, 110 IModifierConstants.ACC_STATIC, 111 IModifierConstants.ACC_FINAL, 112 IModifierConstants.ACC_TRANSIENT, 113 IModifierConstants.ACC_VOLATILE, 114 IModifierConstants.ACC_ENUM 115 }); 116 } 117 118 private void decodeModifiersForFieldForWorkingCopy(StringBuffer buffer, int accessFlags) { 119 decodeModifiers(buffer, accessFlags, new int[] { 120 IModifierConstants.ACC_PUBLIC, 121 IModifierConstants.ACC_PROTECTED, 122 IModifierConstants.ACC_PRIVATE, 123 IModifierConstants.ACC_STATIC, 124 IModifierConstants.ACC_FINAL, 125 IModifierConstants.ACC_TRANSIENT, 126 IModifierConstants.ACC_VOLATILE, 127 }); 128 } 129 130 private final void decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault) { 131 decodeModifiers(buffer, accessFlags, printDefault, false, new int[] { 132 IModifierConstants.ACC_PUBLIC, 133 IModifierConstants.ACC_PROTECTED, 134 IModifierConstants.ACC_PRIVATE, 135 IModifierConstants.ACC_ABSTRACT, 136 IModifierConstants.ACC_STATIC, 137 IModifierConstants.ACC_FINAL, 138 }); 139 } 140 141 private final void decodeModifiersForMethod(StringBuffer buffer, int accessFlags) { 142 decodeModifiers(buffer, accessFlags, false, true, new int[] { 143 IModifierConstants.ACC_PUBLIC, 144 IModifierConstants.ACC_PROTECTED, 145 IModifierConstants.ACC_PRIVATE, 146 IModifierConstants.ACC_ABSTRACT, 147 IModifierConstants.ACC_STATIC, 148 IModifierConstants.ACC_FINAL, 149 IModifierConstants.ACC_SYNCHRONIZED, 150 IModifierConstants.ACC_NATIVE, 151 IModifierConstants.ACC_STRICT, 152 IModifierConstants.ACC_BRIDGE, 153 }); 154 } 155 156 private final void decodeModifiersForType(StringBuffer buffer, int accessFlags) { 157 decodeModifiers(buffer, accessFlags, new int[] { 158 IModifierConstants.ACC_PUBLIC, 159 IModifierConstants.ACC_ABSTRACT, 160 IModifierConstants.ACC_FINAL, 161 }); 162 } 163 public static String escapeString(String s) { 164 StringBuffer buffer = new StringBuffer (); 165 for (int i = 0, max = s.length(); i < max; i++) { 166 char c = s.charAt(i); 167 switch(c) { 168 case '\b' : 169 buffer.append("\\b"); break; 171 case '\t' : 172 buffer.append("\\t"); break; 174 case '\n' : 175 buffer.append("\\n"); break; 177 case '\f' : 178 buffer.append("\\f"); break; 180 case '\r' : 181 buffer.append("\\r"); break; 183 case '\0' : 184 buffer.append("\\0"); break; 186 case '\1' : 187 buffer.append("\\1"); break; 189 case '\2' : 190 buffer.append("\\2"); break; 192 case '\3' : 193 buffer.append("\\3"); break; 195 case '\4' : 196 buffer.append("\\4"); break; 198 case '\5' : 199 buffer.append("\\5"); break; 201 case '\6' : 202 buffer.append("\\6"); break; 204 case '\7' : 205 buffer.append("\\7"); break; 207 default: 208 buffer.append(c); 209 } 210 } 211 return buffer.toString(); 212 } 213 214 static String decodeStringValue(char[] chars) { 215 StringBuffer buffer = new StringBuffer (); 216 for (int i = 0, max = chars.length; i < max; i++) { 217 char c = chars[i]; 218 switch(c) { 219 case '\b' : 220 buffer.append("\\b"); break; 222 case '\t' : 223 buffer.append("\\t"); break; 225 case '\n' : 226 buffer.append("\\n"); break; 228 case '\f' : 229 buffer.append("\\f"); break; 231 case '\r' : 232 buffer.append("\\r"); break; 234 case '\0' : 235 buffer.append("\\0"); break; 237 case '\1' : 238 buffer.append("\\1"); break; 240 case '\2' : 241 buffer.append("\\2"); break; 243 case '\3' : 244 buffer.append("\\3"); break; 246 case '\4' : 247 buffer.append("\\4"); break; 249 case '\5' : 250 buffer.append("\\5"); break; 252 case '\6' : 253 buffer.append("\\6"); break; 255 case '\7' : 256 buffer.append("\\7"); break; 258 default: 259 buffer.append(c); 260 } 261 } 262 return buffer.toString(); 263 } 264 265 static String decodeStringValue(String s) { 266 return decodeStringValue(s.toCharArray()); 267 } 268 269 272 public String disassemble(byte[] classFileBytes, String lineSeparator) throws ClassFormatException { 273 try { 274 return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, ClassFileBytesDisassembler.DEFAULT); 275 } catch (ArrayIndexOutOfBoundsException e) { 276 StringWriter stringWriter = new StringWriter (); 277 PrintWriter writer = new PrintWriter (stringWriter); 278 e.printStackTrace(writer); 279 writer.flush(); 280 writer.close(); 281 throw new ClassFormatException(String.valueOf(stringWriter.getBuffer())); 282 } 283 } 284 285 288 public String disassemble(byte[] classFileBytes, String lineSeparator, int mode) throws ClassFormatException { 289 try { 290 return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode); 291 } catch (ArrayIndexOutOfBoundsException e) { 292 StringWriter stringWriter = new StringWriter (); 293 PrintWriter writer = new PrintWriter (stringWriter); 294 e.printStackTrace(writer); 295 writer.flush(); 296 writer.close(); 297 throw new ClassFormatException(String.valueOf(stringWriter.getBuffer())); 298 } 299 } 300 301 private void disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber) { 302 writeNewLine(buffer, lineSeparator, tabNumber + 1); 303 final int typeIndex = annotation.getTypeIndex(); 304 final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.'); 305 buffer.append( 306 Messages.bind(Messages.disassembler_annotationentrystart, new String [] { 307 Integer.toString(typeIndex), 308 new String (Signature.toCharArray(typeName)) 309 })); 310 final IAnnotationComponent[] components = annotation.getComponents(); 311 for (int i = 0, max = components.length; i < max; i++) { 312 disassemble(components[i], buffer, lineSeparator, tabNumber + 1); 313 } 314 writeNewLine(buffer, lineSeparator, tabNumber + 1); 315 buffer.append(Messages.disassembler_annotationentryend); 316 } 317 318 private void disassemble(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber) { 319 writeNewLine(buffer, lineSeparator, tabNumber + 1); 320 buffer.append( 321 Messages.bind(Messages.disassembler_annotationcomponent, 322 new String [] { 323 Integer.toString(annotationComponent.getComponentNameIndex()), 324 new String (annotationComponent.getComponentName()) 325 })); 326 disassemble(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1); 327 } 328 329 private void disassemble(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber) { 330 switch(annotationComponentValue.getTag()) { 331 case IAnnotationComponentValue.BYTE_TAG: 332 case IAnnotationComponentValue.CHAR_TAG: 333 case IAnnotationComponentValue.DOUBLE_TAG: 334 case IAnnotationComponentValue.FLOAT_TAG: 335 case IAnnotationComponentValue.INTEGER_TAG: 336 case IAnnotationComponentValue.LONG_TAG: 337 case IAnnotationComponentValue.SHORT_TAG: 338 case IAnnotationComponentValue.BOOLEAN_TAG: 339 case IAnnotationComponentValue.STRING_TAG: 340 IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue(); 341 String value = null; 342 switch(constantPoolEntry.getKind()) { 343 case IConstantPoolConstant.CONSTANT_Long : 344 value = constantPoolEntry.getLongValue() + "L"; break; 346 case IConstantPoolConstant.CONSTANT_Float : 347 value = constantPoolEntry.getFloatValue() + "f"; break; 349 case IConstantPoolConstant.CONSTANT_Double : 350 value = Double.toString(constantPoolEntry.getDoubleValue()); 351 break; 352 case IConstantPoolConstant.CONSTANT_Integer: 353 switch(annotationComponentValue.getTag()) { 354 case IAnnotationComponentValue.CHAR_TAG : 355 value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; break; 357 case IAnnotationComponentValue.BOOLEAN_TAG : 358 value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false"; break; 360 case IAnnotationComponentValue.BYTE_TAG : 361 value = "(byte) " + constantPoolEntry.getIntegerValue(); break; 363 case IAnnotationComponentValue.SHORT_TAG : 364 value = "(short) " + constantPoolEntry.getIntegerValue(); break; 366 case IAnnotationComponentValue.INTEGER_TAG : 367 value = "(int) " + constantPoolEntry.getIntegerValue(); } 369 break; 370 case IConstantPoolConstant.CONSTANT_Utf8: 371 value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\""; } 373 buffer.append(Messages.bind(Messages.disassembler_annotationdefaultvalue, value)); 374 break; 375 case IAnnotationComponentValue.ENUM_TAG: 376 final int enumConstantTypeNameIndex = annotationComponentValue.getEnumConstantTypeNameIndex(); 377 final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.'); 378 final int enumConstantNameIndex = annotationComponentValue.getEnumConstantNameIndex(); 379 final char[] constantName = annotationComponentValue.getEnumConstantName(); 380 buffer.append(Messages.bind(Messages.disassembler_annotationenumvalue, 381 new String [] { 382 Integer.toString(enumConstantTypeNameIndex), 383 Integer.toString(enumConstantNameIndex), 384 new String (Signature.toCharArray(typeName)), 385 new String (constantName) 386 })); 387 break; 388 case IAnnotationComponentValue.CLASS_TAG: 389 final int classIndex = annotationComponentValue.getClassInfoIndex(); 390 constantPoolEntry = annotationComponentValue.getClassInfo(); 391 final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.'); 392 buffer.append(Messages.bind(Messages.disassembler_annotationclassvalue, 393 new String [] { 394 Integer.toString(classIndex), 395 new String (Signature.toCharArray(className)) 396 })); 397 break; 398 case IAnnotationComponentValue.ANNOTATION_TAG: 399 buffer.append(Messages.disassembler_annotationannotationvalue); 400 IAnnotation annotation = annotationComponentValue.getAnnotationValue(); 401 disassemble(annotation, buffer, lineSeparator, tabNumber + 1); 402 break; 403 case IAnnotationComponentValue.ARRAY_TAG: 404 buffer.append(Messages.disassembler_annotationarrayvaluestart); 405 final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues(); 406 for (int i = 0, max = annotationComponentValues.length; i < max; i++) { 407 writeNewLine(buffer, lineSeparator, tabNumber + 1); 408 disassemble(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1); 409 } 410 writeNewLine(buffer, lineSeparator, tabNumber + 1); 411 buffer.append(Messages.disassembler_annotationarrayvalueend); 412 } 413 } 414 415 private void disassemble(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 416 writeNewLine(buffer, lineSeparator, tabNumber + 1); 417 buffer.append(Messages.disassembler_annotationdefaultheader); 418 IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue(); 419 writeNewLine(buffer, lineSeparator, tabNumber + 2); 420 disassemble(componentValue, buffer, lineSeparator, tabNumber + 1); 421 } 422 423 private void disassemble(IClassFileAttribute classFileAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 424 writeNewLine(buffer, lineSeparator, tabNumber + 1); 425 buffer.append(Messages.bind(Messages.disassembler_genericattributeheader, 426 new String [] { 427 new String (classFileAttribute.getAttributeName()), 428 Long.toString(classFileAttribute.getAttributeLength()) 429 })); 430 } 431 432 private void disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 433 writeNewLine(buffer, lineSeparator, tabNumber); 434 final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute(); 435 char[] methodDescriptor = methodInfo.getDescriptor(); 436 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 437 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 438 if (runtimeInvisibleAnnotationsAttribute != null) { 440 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 441 writeNewLine(buffer, lineSeparator, tabNumber); 442 } 443 if (runtimeVisibleAnnotationsAttribute != null) { 444 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 445 writeNewLine(buffer, lineSeparator, tabNumber); 446 } 447 final int accessFlags = methodInfo.getAccessFlags(); 448 decodeModifiersForMethod(buffer, accessFlags & IModifierConstants.ACC_PRIVATE); 449 CharOperation.replace(methodDescriptor, '/', '.'); 450 final boolean isVarArgs = (accessFlags & IModifierConstants.ACC_VARARGS) != 0; 451 final char[] signature = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs); 452 int index = CharOperation.indexOf(',', signature); 453 index = CharOperation.indexOf(',', signature, index + 1); 454 buffer.append(signature, 0, CharOperation.indexOf('(', signature) + 1); 455 buffer.append(signature, index + 2, signature.length - index - 2); 456 IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute(); 457 if (exceptionAttribute != null) { 458 buffer.append(" throws "); char[][] exceptionNames = exceptionAttribute.getExceptionNames(); 460 int length = exceptionNames.length; 461 for (int i = 0; i < length; i++) { 462 if (i != 0) { 463 buffer 464 .append(Messages.disassembler_comma) 465 .append(Messages.disassembler_space); 466 } 467 char[] exceptionName = exceptionNames[i]; 468 CharOperation.replace(exceptionName, '/', '.'); 469 buffer.append(returnClassName(exceptionName, '.', mode)); 470 } 471 } 472 if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0) 473 && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) { 474 buffer.append(" {"); final char[] returnType = Signature.getReturnType(methodDescriptor); 476 if (returnType.length == 1) { 477 switch(returnType[0]) { 478 case 'V' : 479 writeNewLine(buffer, lineSeparator, tabNumber); 480 break; 481 case 'I' : 482 case 'B' : 483 case 'J' : 484 case 'D' : 485 case 'F' : 486 case 'S' : 487 case 'C' : 488 writeNewLine(buffer, lineSeparator, tabNumber + 1); 489 buffer.append("return 0;"); writeNewLine(buffer, lineSeparator, tabNumber); 491 break; 492 default : 493 writeNewLine(buffer, lineSeparator, tabNumber + 1); 495 buffer.append("return false;"); writeNewLine(buffer, lineSeparator, tabNumber); 497 } 498 } else { 499 writeNewLine(buffer, lineSeparator, tabNumber + 1); 501 buffer.append("return null;"); writeNewLine(buffer, lineSeparator, tabNumber); 503 } 504 buffer.append('}'); 505 } else { 506 buffer.append(';'); 507 } 508 } 509 510 513 private void disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 514 writeNewLine(buffer, lineSeparator, tabNumber); 515 final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute(); 516 final char[] methodDescriptor = methodInfo.getDescriptor(); 517 final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE); 518 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 519 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 520 final IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS); 521 final IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS); 522 final IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT); 523 if (checkMode(mode, SYSTEM | DETAILED)) { 524 buffer.append(Messages.bind(Messages.classfileformat_methoddescriptor, 525 new String [] { 526 Integer.toString(methodInfo.getDescriptorIndex()), 527 new String (methodDescriptor) 528 })); 529 if (methodInfo.isDeprecated()) { 530 buffer.append(Messages.disassembler_deprecated); 531 } 532 writeNewLine(buffer, lineSeparator, tabNumber); 533 if (signatureAttribute != null) { 534 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String (signatureAttribute.getSignature()))); 535 writeNewLine(buffer, lineSeparator, tabNumber); 536 } 537 if (codeAttribute != null) { 538 buffer.append(Messages.bind(Messages.classfileformat_stacksAndLocals, 539 new String [] { 540 Integer.toString(codeAttribute.getMaxStack()), 541 Integer.toString(codeAttribute.getMaxLocals()) 542 })); 543 writeNewLine(buffer, lineSeparator, tabNumber); 544 } 545 } 546 if (checkMode(mode, DETAILED)) { 547 if (runtimeInvisibleAnnotationsAttribute != null) { 549 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 550 writeNewLine(buffer, lineSeparator, tabNumber); 551 } 552 if (runtimeVisibleAnnotationsAttribute != null) { 553 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 554 writeNewLine(buffer, lineSeparator, tabNumber); 555 } 556 } 557 final int accessFlags = methodInfo.getAccessFlags(); 558 decodeModifiersForMethod(buffer, accessFlags); 559 if (methodInfo.isSynthetic() && !checkMode(mode, WORKING_COPY)) { 560 buffer.append("synthetic"); buffer.append(Messages.disassembler_space); 562 } 563 CharOperation.replace(methodDescriptor, '/', '.'); 564 final boolean isVarArgs = isVarArgs(methodInfo); 565 if (methodInfo.isConstructor()) { 566 if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) { 567 final char[] signature = signatureAttribute.getSignature(); 568 CharOperation.replace(signature, '/', '.'); 569 disassembleGenericSignature(mode, buffer, signature); 570 buffer.append(' '); 571 buffer.append(Signature.toCharArray(signature, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs)); 572 } else { 573 buffer.append(Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs)); 574 } 575 } else if (methodInfo.isClinit()) { 576 buffer.append(Messages.bind(Messages.classfileformat_clinitname)); 577 } else { 578 if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) { 579 final char[] signature = signatureAttribute.getSignature(); 580 CharOperation.replace(signature, '/', '.'); 581 disassembleGenericSignature(mode, buffer, signature); 582 buffer.append(' '); 583 buffer.append(Signature.toCharArray(signature, methodInfo.getName(), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), true, isVarArgs)); 584 } else { 585 buffer.append(Signature.toCharArray(methodDescriptor, methodInfo.getName(), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), true, isVarArgs)); 586 } 587 } 588 IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute(); 589 if (exceptionAttribute != null) { 590 buffer.append(" throws "); char[][] exceptionNames = exceptionAttribute.getExceptionNames(); 592 int length = exceptionNames.length; 593 for (int i = 0; i < length; i++) { 594 if (i != 0) { 595 buffer 596 .append(Messages.disassembler_comma) 597 .append(Messages.disassembler_space); 598 } 599 char[] exceptionName = exceptionNames[i]; 600 CharOperation.replace(exceptionName, '/', '.'); 601 buffer.append(returnClassName(exceptionName, '.', mode)); 602 } 603 } 604 if (checkMode(mode, DETAILED)) { 605 if (annotationDefaultAttribute != null) { 606 buffer.append(" default "); disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode); 608 } 609 } 610 if (checkMode(mode, WORKING_COPY)) { 611 if (annotationDefaultAttribute != null) { 613 buffer.append(" default "); disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode); 615 } 616 if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0) 617 && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) { 618 buffer.append(" {"); final char[] returnType = Signature.getReturnType(methodDescriptor); 620 if (returnType.length == 1) { 621 switch(returnType[0]) { 622 case 'V' : 623 writeNewLine(buffer, lineSeparator, tabNumber); 624 break; 625 case 'I' : 626 case 'B' : 627 case 'J' : 628 case 'D' : 629 case 'F' : 630 case 'S' : 631 case 'C' : 632 writeNewLine(buffer, lineSeparator, tabNumber + 1); 633 buffer.append("return 0;"); writeNewLine(buffer, lineSeparator, tabNumber); 635 break; 636 default : 637 writeNewLine(buffer, lineSeparator, tabNumber + 1); 639 buffer.append("return false;"); writeNewLine(buffer, lineSeparator, tabNumber); 641 } 642 } else { 643 writeNewLine(buffer, lineSeparator, tabNumber + 1); 645 buffer.append("return null;"); writeNewLine(buffer, lineSeparator, tabNumber); 647 } 648 buffer.append('}'); 649 } else { 650 buffer.append(';'); 651 } 652 } else { 653 buffer.append(Messages.disassembler_endofmethodheader); 654 } 655 656 if (checkMode(mode, SYSTEM | DETAILED)) { 657 if (codeAttribute != null) { 658 disassemble(codeAttribute, buffer, lineSeparator, tabNumber, mode); 659 } 660 } 661 if (checkMode(mode, SYSTEM)) { 662 IClassFileAttribute[] attributes = methodInfo.getAttributes(); 663 int length = attributes.length; 664 if (length != 0) { 665 for (int i = 0; i < length; i++) { 666 IClassFileAttribute attribute = attributes[i]; 667 if (attribute != codeAttribute 668 && attribute != exceptionAttribute 669 && attribute != signatureAttribute 670 && attribute != annotationDefaultAttribute 671 && attribute != runtimeInvisibleAnnotationsAttribute 672 && attribute != runtimeVisibleAnnotationsAttribute 673 && attribute != runtimeInvisibleParameterAnnotationsAttribute 674 && attribute != runtimeVisibleParameterAnnotationsAttribute 675 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) 676 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 677 disassemble(attribute, buffer, lineSeparator, tabNumber); 678 writeNewLine(buffer, lineSeparator, tabNumber); 679 } 680 } 681 } 682 if (annotationDefaultAttribute != null) { 683 disassemble((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber); 684 } 685 if (runtimeVisibleAnnotationsAttribute != null) { 686 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber); 687 } 688 if (runtimeInvisibleAnnotationsAttribute != null) { 689 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber); 690 } 691 if (runtimeVisibleParameterAnnotationsAttribute != null) { 692 disassemble((IRuntimeVisibleParameterAnnotationsAttribute) runtimeVisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber); 693 } 694 if (runtimeInvisibleParameterAnnotationsAttribute != null) { 695 disassemble((IRuntimeInvisibleParameterAnnotationsAttribute) runtimeInvisibleParameterAnnotationsAttribute, buffer, lineSeparator, tabNumber); 696 } 697 } 698 } 699 700 703 public String disassemble(IClassFileReader classFileReader, String lineSeparator) { 704 return disassemble(classFileReader, lineSeparator, ClassFileBytesDisassembler.DEFAULT); 705 } 706 707 718 public String disassemble(IClassFileReader classFileReader, String lineSeparator, int mode) { 719 if (classFileReader == null) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING; 720 char[] className = classFileReader.getClassName(); 721 if (className == null) { 722 return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING; 724 } 725 className= CharOperation.replaceOnCopy(className, '/', '.'); 726 final int classNameLength = className.length; 727 final int accessFlags = classFileReader.getAccessFlags(); 728 final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0; 729 730 StringBuffer buffer = new StringBuffer (); 731 ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute(); 732 IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE); 733 ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute; 734 if (checkMode(mode, SYSTEM | DETAILED)) { 735 int minorVersion = classFileReader.getMinorVersion(); 736 int majorVersion = classFileReader.getMajorVersion(); 737 buffer.append(Messages.disassembler_begincommentline); 738 if (sourceAttribute != null) { 739 buffer.append(Messages.disassembler_sourceattributeheader); 740 buffer.append(sourceAttribute.getSourceFileName()); 741 } 742 String versionNumber = VERSION_UNKNOWN; 743 if (minorVersion == 3 && majorVersion == 45) { 744 versionNumber = JavaCore.VERSION_1_1; 745 } else if (minorVersion == 0 && majorVersion == 46) { 746 versionNumber = JavaCore.VERSION_1_2; 747 } else if (minorVersion == 0 && majorVersion == 47) { 748 versionNumber = JavaCore.VERSION_1_3; 749 } else if (minorVersion == 0 && majorVersion == 48) { 750 versionNumber = JavaCore.VERSION_1_4; 751 } else if (minorVersion == 0 && majorVersion == 49) { 752 versionNumber = JavaCore.VERSION_1_5; 753 } else if (minorVersion == 0 && majorVersion == 50) { 754 versionNumber = JavaCore.VERSION_1_6; 755 } else if (minorVersion == 0 && majorVersion == 51) { 756 versionNumber = JavaCore.VERSION_1_7; 757 } 758 buffer.append( 759 Messages.bind(Messages.classfileformat_versiondetails, 760 new String [] { 761 versionNumber, 762 Integer.toString(majorVersion), 763 Integer.toString(minorVersion), 764 ((accessFlags & IModifierConstants.ACC_SUPER) != 0 765 ? Messages.classfileformat_superflagisset 766 : Messages.classfileformat_superflagisnotset) 767 + (isDeprecated(classFileReader) ? ", deprecated" : org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING) })); 769 writeNewLine(buffer, lineSeparator, 0); 770 if (signatureAttribute != null) { 771 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String (signatureAttribute.getSignature()))); 772 writeNewLine(buffer, lineSeparator, 0); 773 } 774 } 775 final int lastDotIndexInClassName = CharOperation.lastIndexOf('.', className); 776 777 if (checkMode(mode, WORKING_COPY) && lastDotIndexInClassName != -1) { 778 buffer.append("package "); buffer.append(className, 0, lastDotIndexInClassName); 781 buffer.append(';'); 782 writeNewLine(buffer, lineSeparator, 0); 783 } 784 785 IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute(); 786 IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 787 IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 788 789 if (checkMode(mode, DETAILED)) { 790 if (runtimeInvisibleAnnotationsAttribute != null) { 792 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode); 793 writeNewLine(buffer, lineSeparator, 0); 794 } 795 if (runtimeVisibleAnnotationsAttribute != null) { 796 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode); 797 writeNewLine(buffer, lineSeparator, 0); 798 } 799 } 800 boolean decoded = false; 801 if (isEnum && checkMode(mode, WORKING_COPY)) { 802 decodeModifiersForType(buffer, accessFlags & IModifierConstants.ACC_PUBLIC); 803 } else { 804 if (innerClassesAttribute != null) { 805 IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries(); 807 for (int i = 0, max = entries.length; i < max ; i++) { 808 IInnerClassesAttributeEntry entry = entries[i]; 809 char[] innerClassName = entry.getInnerClassName(); 810 if (innerClassName != null) { 811 if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) { 812 decodeModifiersForInnerClasses(buffer, entry.getAccessFlags(), false); 813 decoded = true; 814 } 815 } 816 } 817 } 818 if (!decoded) { 819 decodeModifiersForType(buffer, accessFlags); 820 if (isSynthetic(classFileReader)) { 821 buffer.append("synthetic"); buffer.append(Messages.disassembler_space); 823 } 824 } 825 } 826 827 final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0; 828 boolean isInterface = false; 829 if (isEnum) { 830 buffer.append("enum "); } else if (classFileReader.isClass()) { 832 buffer.append("class "); } else { 834 if (isAnnotation) { 835 buffer.append("@"); } 837 buffer.append("interface "); isInterface = true; 839 } 840 841 if (checkMode(mode, WORKING_COPY)) { 842 final int start = lastDotIndexInClassName + 1; 844 buffer.append(className, start, classNameLength - start); 845 className = CharOperation.subarray(className, start, classNameLength); 846 if (signatureAttribute != null) { 847 disassembleGenericSignature(mode, buffer, signatureAttribute.getSignature()); 848 } 849 } else { 850 buffer.append(className); 851 } 852 853 char[] superclassName = classFileReader.getSuperclassName(); 854 if (superclassName != null) { 855 CharOperation.replace(superclassName, '/', '.'); 856 if (!isJavaLangObject(superclassName) && !isEnum) { 857 buffer.append(" extends "); buffer.append(returnClassName(superclassName, '.', mode)); 859 } 860 } 861 if (!isAnnotation || !checkMode(mode, WORKING_COPY)) { 862 char[][] superclassInterfaces = classFileReader.getInterfaceNames(); 863 int length = superclassInterfaces.length; 864 if (length != 0) { 865 if (isInterface) { 866 buffer.append(" extends "); } else { 868 buffer.append(" implements "); } 870 for (int i = 0; i < length; i++) { 871 if (i != 0) { 872 buffer 873 .append(Messages.disassembler_comma) 874 .append(Messages.disassembler_space); 875 } 876 char[] superinterface = superclassInterfaces[i]; 877 CharOperation.replace(superinterface, '/', '.'); 878 buffer 879 .append(returnClassName(superinterface, '.', mode)); 880 } 881 } 882 } 883 buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration)); 884 if (checkMode(mode, SYSTEM)) { 885 disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1); 886 } 887 disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum); 888 if (checkMode(mode, SYSTEM | DETAILED)) { 889 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 890 int length = attributes.length; 891 IEnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader); 892 int remainingAttributesLength = length; 893 if (innerClassesAttribute != null) { 894 remainingAttributesLength--; 895 } 896 if (enclosingMethodAttribute != null) { 897 remainingAttributesLength--; 898 } 899 if (sourceAttribute != null) { 900 remainingAttributesLength--; 901 } 902 if (signatureAttribute != null) { 903 remainingAttributesLength--; 904 } 905 if (innerClassesAttribute != null || enclosingMethodAttribute != null || remainingAttributesLength != 0) { 906 writeNewLine(buffer, lineSeparator, 0); 907 } 908 if (innerClassesAttribute != null) { 909 disassemble(innerClassesAttribute, buffer, lineSeparator, 1); 910 } 911 if (enclosingMethodAttribute != null) { 912 disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0); 913 } 914 if (checkMode(mode, SYSTEM)) { 915 if (runtimeVisibleAnnotationsAttribute != null) { 916 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 0); 917 } 918 if (runtimeInvisibleAnnotationsAttribute != null) { 919 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 0); 920 } 921 if (length != 0) { 922 for (int i = 0; i < length; i++) { 923 IClassFileAttribute attribute = attributes[i]; 924 if (attribute != innerClassesAttribute 925 && attribute != sourceAttribute 926 && attribute != signatureAttribute 927 && attribute != enclosingMethodAttribute 928 && attribute != runtimeInvisibleAnnotationsAttribute 929 && attribute != runtimeVisibleAnnotationsAttribute 930 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) 931 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 932 disassemble(attribute, buffer, lineSeparator, 0); 933 } 934 } 935 } 936 } 937 } 938 writeNewLine(buffer, lineSeparator, 0); 939 buffer.append(Messages.disassembler_closetypedeclaration); 940 return buffer.toString(); 941 } 942 943 private void disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature) { 944 CharOperation.replace(signature, '/', '.'); 945 final char[][] typeParameters = Signature.getTypeParameters(signature); 946 final int typeParametersLength = typeParameters.length; 947 if (typeParametersLength != 0) { 948 buffer.append('<'); 949 for (int i = 0; i < typeParametersLength; i++) { 950 if (i != 0) { 951 buffer.append(Messages.disassembler_comma); 952 } 953 buffer.append(typeParameters[i], 0, CharOperation.indexOf(':', typeParameters[i])); 955 final char[][] bounds = Signature.getTypeParameterBounds(typeParameters[i]); 956 final int boundsLength = bounds.length; 957 if (boundsLength != 0) { 958 if (boundsLength == 1) { 959 final char[] bound = bounds[0]; 960 if (!isJavaLangObject(Signature.toCharArray(bound))) { 962 buffer.append(" extends "); buffer.append(returnClassName(Signature.toCharArray(bound), '.', mode)); 964 } 965 } else { 966 buffer.append(" extends "); for (int j= 0; j < boundsLength; j++) { 968 if (j != 0) { 969 buffer.append(" & "); } 971 buffer.append(returnClassName(Signature.toCharArray(bounds[j]), '.', mode)); 972 } 973 } 974 } 975 } 976 buffer.append('>'); 977 } 978 } 979 980 private boolean isJavaLangObject(final char[] className) { 981 return CharOperation.equals(TypeConstants.JAVA_LANG_OBJECT, CharOperation.splitOn('.', className)); 982 } 983 984 private boolean isVarArgs(IMethodInfo methodInfo) { 985 int accessFlags = methodInfo.getAccessFlags(); 986 if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0) return true; 987 return Util.getAttribute(methodInfo, AttributeNamesConstants.VarargsName) != null; 989 } 990 private void disassemble(ICodeAttribute codeAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 991 writeNewLine(buffer, lineSeparator, tabNumber - 1); 992 DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute, buffer, lineSeparator, tabNumber, mode); 993 try { 994 codeAttribute.traverse(visitor); 995 } catch(ClassFormatException e) { 996 dumpTab(tabNumber + 2, buffer); 997 buffer.append(Messages.classformat_classformatexception); 998 writeNewLine(buffer, lineSeparator, tabNumber + 1); 999 } 1000 final int exceptionTableLength = codeAttribute.getExceptionTableLength(); 1001 boolean isFirstAttribute = true; 1002 if (exceptionTableLength != 0) { 1003 final int tabNumberForExceptionAttribute = tabNumber + 2; 1004 isFirstAttribute = false; 1005 dumpTab(tabNumberForExceptionAttribute, buffer); 1006 final IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable(); 1007 buffer.append(Messages.disassembler_exceptiontableheader); 1008 writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1); 1009 for (int i = 0; i < exceptionTableLength; i++) { 1010 if (i != 0) { 1011 writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1); 1012 } 1013 IExceptionTableEntry exceptionTableEntry = exceptionTableEntries[i]; 1014 char[] catchType; 1015 if (exceptionTableEntry.getCatchTypeIndex() != 0) { 1016 catchType = exceptionTableEntry.getCatchType(); 1017 CharOperation.replace(catchType, '/', '.'); 1018 catchType = returnClassName(catchType, '.', mode); 1019 } else { 1020 catchType = ANY_EXCEPTION; 1021 } 1022 buffer.append(Messages.bind(Messages.classfileformat_exceptiontableentry, 1023 new String [] { 1024 Integer.toString(exceptionTableEntry.getStartPC()), 1025 Integer.toString(exceptionTableEntry.getEndPC()), 1026 Integer.toString(exceptionTableEntry.getHandlerPC()), 1027 new String (catchType) 1028 })); 1029 } 1030 } 1031 final ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute(); 1032 final int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength(); 1033 if (lineAttributeLength != 0) { 1034 int tabNumberForLineAttribute = tabNumber + 2; 1035 if (!isFirstAttribute) { 1036 writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute); 1037 } else { 1038 dumpTab(tabNumberForLineAttribute, buffer); 1039 isFirstAttribute = false; 1040 } 1041 buffer.append(Messages.disassembler_linenumberattributeheader); 1042 writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1); 1043 int[][] lineattributesEntries = lineNumberAttribute.getLineNumberTable(); 1044 for (int i = 0; i < lineAttributeLength; i++) { 1045 if (i != 0) { 1046 writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1); 1047 } 1048 buffer.append(Messages.bind(Messages.classfileformat_linenumbertableentry, 1049 new String [] { 1050 Integer.toString(lineattributesEntries[i][0]), 1051 Integer.toString(lineattributesEntries[i][1]) 1052 })); 1053 } 1054 } 1055 final ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute(); 1056 final int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength(); 1057 if (localVariableAttributeLength != 0) { 1058 int tabNumberForLocalVariableAttribute = tabNumber + 2; 1059 if (!isFirstAttribute) { 1060 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute); 1061 } else { 1062 isFirstAttribute = false; 1063 dumpTab(tabNumberForLocalVariableAttribute, buffer); 1064 } 1065 buffer.append(Messages.disassembler_localvariabletableattributeheader); 1066 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1067 ILocalVariableTableEntry[] localVariableTableEntries = localVariableAttribute.getLocalVariableTable(); 1068 for (int i = 0; i < localVariableAttributeLength; i++) { 1069 if (i != 0) { 1070 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1071 } 1072 ILocalVariableTableEntry localVariableTableEntry = localVariableTableEntries[i]; 1073 int index= localVariableTableEntry.getIndex(); 1074 int startPC = localVariableTableEntry.getStartPC(); 1075 int length = localVariableTableEntry.getLength(); 1076 final char[] typeName = Signature.toCharArray(localVariableTableEntry.getDescriptor()); 1077 CharOperation.replace(typeName, '/', '.'); 1078 buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry, 1079 new String [] { 1080 Integer.toString(startPC), 1081 Integer.toString(startPC + length), 1082 new String (localVariableTableEntry.getName()), 1083 Integer.toString(index), 1084 new String (returnClassName(typeName, '.', mode)) 1085 })); 1086 } 1087 } 1088 final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) getAttribute(IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE, codeAttribute); 1089 final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength(); 1090 if (localVariableTypeTableLength != 0) { 1091 int tabNumberForLocalVariableAttribute = tabNumber + 2; 1092 if (!isFirstAttribute) { 1093 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute); 1094 } else { 1095 isFirstAttribute = false; 1096 dumpTab(tabNumberForLocalVariableAttribute, buffer); 1097 } 1098 buffer.append(Messages.disassembler_localvariabletypetableattributeheader); 1099 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1100 ILocalVariableTypeTableEntry[] localVariableTypeTableEntries = localVariableTypeAttribute.getLocalVariableTypeTable(); 1101 for (int i = 0; i < localVariableTypeTableLength; i++) { 1102 if (i != 0) { 1103 writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1); 1104 } 1105 ILocalVariableTypeTableEntry localVariableTypeTableEntry = localVariableTypeTableEntries[i]; 1106 int index= localVariableTypeTableEntry.getIndex(); 1107 int startPC = localVariableTypeTableEntry.getStartPC(); 1108 int length = localVariableTypeTableEntry.getLength(); 1109 final char[] typeName = Signature.toCharArray(localVariableTypeTableEntry.getSignature()); 1110 CharOperation.replace(typeName, '/', '.'); 1111 buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry, 1112 new String [] { 1113 Integer.toString(startPC), 1114 Integer.toString(startPC + length), 1115 new String (localVariableTypeTableEntry.getName()), 1116 Integer.toString(index), 1117 new String (returnClassName(typeName, '.', mode)) 1118 })); 1119 } 1120 } 1121 final int length = codeAttribute.getAttributesCount(); 1122 if (length != 0) { 1123 IClassFileAttribute[] attributes = codeAttribute.getAttributes(); 1124 for (int i = 0; i < length; i++) { 1125 IClassFileAttribute attribute = attributes[i]; 1126 if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP_TABLE)) { 1127 IStackMapTableAttribute stackMapTableAttribute = (IStackMapTableAttribute) attribute; 1128 if (!isFirstAttribute) { 1129 writeNewLine(buffer, lineSeparator, tabNumber + 2); 1130 } else { 1131 isFirstAttribute = false; 1132 dumpTab(tabNumber + 1, buffer); 1133 } 1134 int numberOfEntries = stackMapTableAttribute.getNumberOfEntries(); 1135 buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader, Integer.toString(numberOfEntries))); 1136 if (numberOfEntries != 0) { 1137 disassemble(stackMapTableAttribute, buffer, lineSeparator, tabNumber, mode); 1138 } 1139 } else if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP)) { 1140 IStackMapAttribute stackMapAttribute = (IStackMapAttribute) attribute; 1141 if (!isFirstAttribute) { 1142 writeNewLine(buffer, lineSeparator, tabNumber + 2); 1143 } else { 1144 isFirstAttribute = false; 1145 dumpTab(tabNumber + 1, buffer); 1146 } 1147 int numberOfEntries = stackMapAttribute.getNumberOfEntries(); 1148 buffer.append(Messages.bind(Messages.disassembler_stackmapattributeheader, Integer.toString(numberOfEntries))); 1149 if (numberOfEntries != 0) { 1150 disassemble(stackMapAttribute, buffer, lineSeparator, tabNumber, mode); 1151 } 1152 } else if (attribute != lineNumberAttribute 1153 && attribute != localVariableAttribute 1154 && attribute != localVariableTypeAttribute) { 1155 if (!isFirstAttribute) { 1156 writeNewLine(buffer, lineSeparator, tabNumber + 2); 1157 } else { 1158 isFirstAttribute = false; 1159 dumpTab(tabNumber + 1, buffer); 1160 } 1161 buffer.append(Messages.bind(Messages.disassembler_genericattributeheader, 1162 new String [] { 1163 new String (attribute.getAttributeName()), 1164 Long.toString(attribute.getAttributeLength()) 1165 })); 1166 } 1167 } 1168 } 1169 } 1170 1171 private void disassemble(IStackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1172 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1173 int numberOfEntries = attribute.getNumberOfEntries(); 1174 final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame(); 1175 int absolutePC = -1; 1176 for (int j = 0; j < numberOfEntries; j++) { 1177 if (j > 0) { 1178 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1179 } 1180 final IStackMapFrame frame = stackMapFrames[j]; 1181 int type = frame.getFrameType(); 1183 int offsetDelta = frame.getOffsetDelta(); 1184 if (absolutePC == -1) { 1185 absolutePC = offsetDelta; 1186 } else { 1187 absolutePC += (offsetDelta + 1); 1188 } 1189 switch(type) { 1190 case 247 : buffer.append( 1192 Messages.bind( 1193 Messages.disassembler_frame_same_locals_1_stack_item_extended, 1194 Integer.toString(absolutePC), 1195 disassemble(frame.getStackItems(), mode))); 1196 break; 1197 case 248 : 1198 case 249 : 1199 case 250: 1200 buffer.append( 1202 Messages.bind( 1203 Messages.disassembler_frame_chop, 1204 Integer.toString(absolutePC), 1205 Integer.toString(251 - type))); 1206 break; 1207 case 251 : 1208 buffer.append( 1210 Messages.bind( 1211 Messages.disassembler_frame_same_frame_extended, 1212 Integer.toString(absolutePC))); 1213 break; 1214 case 252 : 1215 case 253 : 1216 case 254 : 1217 buffer.append( 1219 Messages.bind( 1220 Messages.disassembler_frame_append, 1221 Integer.toString(absolutePC), 1222 disassemble(frame.getLocals(), mode))); 1223 break; 1224 case 255 : 1225 buffer.append( 1227 Messages.bind( 1228 Messages.disassembler_frame_full_frame, 1229 new String [] { 1230 Integer.toString(absolutePC), 1231 Integer.toString(frame.getNumberOfLocals()), 1232 disassemble(frame.getLocals(), mode), 1233 Integer.toString(frame.getNumberOfStackItems()), 1234 disassemble(frame.getStackItems(), mode), 1235 dumpNewLineWithTabs(lineSeparator, tabNumber + 5) 1236 })); 1237 break; 1238 default: 1239 if (type <= 63) { 1240 offsetDelta = type; 1242 buffer.append( 1243 Messages.bind( 1244 Messages.disassembler_frame_same_frame, 1245 Integer.toString(absolutePC))); 1246 } else if (type <= 127) { 1247 offsetDelta = type - 64; 1249 buffer.append( 1250 Messages.bind( 1251 Messages.disassembler_frame_same_locals_1_stack_item, 1252 Integer.toString(absolutePC), 1253 disassemble(frame.getStackItems(), mode))); 1254 } 1255 } 1256 } 1257 } 1258 1259 private void disassemble(IStackMapAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1260 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1261 int numberOfEntries = attribute.getNumberOfEntries(); 1262 final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame(); 1263 int absolutePC = -1; 1264 for (int j = 0; j < numberOfEntries; j++) { 1265 if (j > 0) { 1266 writeNewLine(buffer, lineSeparator, tabNumber + 3); 1267 } 1268 final IStackMapFrame frame = stackMapFrames[j]; 1269 int offsetDelta = frame.getOffsetDelta(); 1271 if (absolutePC == -1) { 1272 absolutePC = offsetDelta; 1273 } else { 1274 absolutePC += (offsetDelta + 1); 1275 } 1276 buffer.append( 1278 Messages.bind( 1279 Messages.disassembler_frame_full_frame, 1280 new String [] { 1281 Integer.toString(absolutePC), 1282 Integer.toString(frame.getNumberOfLocals()), 1283 disassemble(frame.getLocals(), mode), 1284 Integer.toString(frame.getNumberOfStackItems()), 1285 disassemble(frame.getStackItems(), mode), 1286 dumpNewLineWithTabs(lineSeparator, tabNumber + 5) 1287 })); 1288 } 1289 } 1290 1291 private void disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber) { 1292 writeNewLine(buffer, lineSeparator, tabNumber); 1293 int length = constantPool.getConstantPoolCount(); 1294 buffer.append(Messages.disassembler_constantpoolheader); 1295 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1296 for (int i = 1; i < length; i++) { 1297 if (i != 1) { 1298 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1299 } 1300 IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i); 1301 switch (constantPool.getEntryKind(i)) { 1302 case IConstantPoolConstant.CONSTANT_Class : 1303 buffer.append( 1304 Messages.bind(Messages.disassembler_constantpool_class, 1305 new String [] { 1306 Integer.toString(i), 1307 Integer.toString(constantPoolEntry.getClassInfoNameIndex()), 1308 new String (constantPoolEntry.getClassInfoName())})); 1309 break; 1310 case IConstantPoolConstant.CONSTANT_Double : 1311 buffer.append( 1312 Messages.bind(Messages.disassembler_constantpool_double, 1313 new String [] { 1314 Integer.toString(i), 1315 Double.toString(constantPoolEntry.getDoubleValue())})); 1316 break; 1317 case IConstantPoolConstant.CONSTANT_Fieldref : 1318 buffer.append( 1319 Messages.bind(Messages.disassembler_constantpool_fieldref, 1320 new String [] { 1321 Integer.toString(i), 1322 Integer.toString(constantPoolEntry.getClassIndex()), 1323 Integer.toString(constantPoolEntry.getNameAndTypeIndex()), 1324 new String (constantPoolEntry.getClassName()), 1325 new String (constantPoolEntry.getFieldName()), 1326 new String (constantPoolEntry.getFieldDescriptor()) 1327 })); 1328 break; 1329 case IConstantPoolConstant.CONSTANT_Float : 1330 buffer.append( 1331 Messages.bind(Messages.disassembler_constantpool_float, 1332 new String [] { 1333 Integer.toString(i), 1334 Float.toString(constantPoolEntry.getFloatValue())})); 1335 break; 1336 case IConstantPoolConstant.CONSTANT_Integer : 1337 buffer.append( 1338 Messages.bind(Messages.disassembler_constantpool_integer, 1339 new String [] { 1340 Integer.toString(i), 1341 Integer.toString(constantPoolEntry.getIntegerValue())})); 1342 break; 1343 case IConstantPoolConstant.CONSTANT_InterfaceMethodref : 1344 buffer.append( 1345 Messages.bind(Messages.disassembler_constantpool_interfacemethodref, 1346 new String [] { 1347 Integer.toString(i), 1348 Integer.toString(constantPoolEntry.getClassIndex()), 1349 Integer.toString(constantPoolEntry.getNameAndTypeIndex()), 1350 new String (constantPoolEntry.getClassName()), 1351 new String (constantPoolEntry.getMethodName()), 1352 new String (constantPoolEntry.getMethodDescriptor())})); 1353 break; 1354 case IConstantPoolConstant.CONSTANT_Long : 1355 buffer.append( 1356 Messages.bind(Messages.disassembler_constantpool_long, 1357 new String [] { 1358 Integer.toString(i), 1359 Long.toString(constantPoolEntry.getLongValue())})); 1360 break; 1361 case IConstantPoolConstant.CONSTANT_Methodref : 1362 buffer.append( 1363 Messages.bind(Messages.disassembler_constantpool_methodref, 1364 new String [] { 1365 Integer.toString(i), 1366 Integer.toString(constantPoolEntry.getClassIndex()), 1367 Integer.toString(constantPoolEntry.getNameAndTypeIndex()), 1368 new String (constantPoolEntry.getClassName()), 1369 new String (constantPoolEntry.getMethodName()), 1370 new String (constantPoolEntry.getMethodDescriptor())})); 1371 break; 1372 case IConstantPoolConstant.CONSTANT_NameAndType : 1373 int nameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex(); 1374 int typeIndex = constantPoolEntry.getNameAndTypeInfoDescriptorIndex(); 1375 IConstantPoolEntry entry = constantPool.decodeEntry(nameIndex); 1376 char[] nameValue = entry.getUtf8Value(); 1377 entry = constantPool.decodeEntry(typeIndex); 1378 char[] typeValue = entry.getUtf8Value(); 1379 buffer.append( 1380 Messages.bind(Messages.disassembler_constantpool_name_and_type, 1381 new String [] { 1382 Integer.toString(i), 1383 Integer.toString(nameIndex), 1384 Integer.toString(typeIndex), 1385 String.valueOf(nameValue), 1386 String.valueOf(typeValue)})); 1387 break; 1388 case IConstantPoolConstant.CONSTANT_String : 1389 buffer.append( 1390 Messages.bind(Messages.disassembler_constantpool_string, 1391 new String [] { 1392 Integer.toString(i), 1393 Integer.toString(constantPoolEntry.getStringIndex()), 1394 decodeStringValue(constantPoolEntry.getStringValue())})); 1395 break; 1396 case IConstantPoolConstant.CONSTANT_Utf8 : 1397 buffer.append( 1398 Messages.bind(Messages.disassembler_constantpool_utf8, 1399 new String [] { 1400 Integer.toString(i), 1401 decodeStringValue(new String (constantPoolEntry.getUtf8Value()))})); 1402 break; 1403 } 1404 } 1405 } 1406 1407 private void disassemble(IEnclosingMethodAttribute enclosingMethodAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1408 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1409 buffer.append(Messages.disassembler_enclosingmethodheader); 1410 buffer 1411 .append(Messages.disassembler_constantpoolindex) 1412 .append(enclosingMethodAttribute.getEnclosingClassIndex()) 1413 .append(" ") .append(Messages.disassembler_constantpoolindex) 1415 .append(enclosingMethodAttribute.getMethodNameAndTypeIndex()) 1416 .append(" ") .append(enclosingMethodAttribute.getEnclosingClass()); 1418 if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) { 1419 buffer 1420 .append(".") .append(enclosingMethodAttribute.getMethodName()) 1422 .append(enclosingMethodAttribute.getMethodDescriptor()); 1423 } 1424 } 1425 1426 private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode) { 1427 writeNewLine(buffer, lineSeparator, tabNumber); 1428 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 1429 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 1430 if (runtimeInvisibleAnnotationsAttribute != null) { 1432 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 1433 writeNewLine(buffer, lineSeparator, tabNumber); 1434 } 1435 if (runtimeVisibleAnnotationsAttribute != null) { 1436 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 1437 writeNewLine(buffer, lineSeparator, tabNumber); 1438 } 1439 buffer.append(new String (fieldInfo.getName())); 1440 buffer.append('('); 1441 final int length = argumentTypes.length; 1442 if (length != 0) { 1443 for (int i = 0; i < length; i++) { 1445 if (i != 0) { 1446 buffer.append(Messages.disassembler_comma); 1447 } 1448 final char[] type = argumentTypes[i]; 1449 switch(type.length) { 1450 case 1 : 1451 switch(type[0]) { 1452 case 'B' : 1453 case 'I' : 1454 case 'J' : 1455 case 'D' : 1456 case 'F' : 1457 case 'S' : 1458 buffer.append('0'); 1459 break; 1460 case 'Z' : 1461 buffer.append("false"); break; 1463 case 'C' : 1464 buffer.append("\' \'"); break; 1466 } 1467 break; 1468 default : 1469 buffer.append("null"); } 1471 } 1472 } 1473 buffer.append(')').append(Messages.disassembler_comma); 1474 } 1475 1476 1479 private void disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1480 writeNewLine(buffer, lineSeparator, tabNumber); 1481 final char[] fieldDescriptor = fieldInfo.getDescriptor(); 1482 final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE); 1483 if (checkMode(mode, SYSTEM | DETAILED)) { 1484 buffer.append(Messages.bind(Messages.classfileformat_fieldddescriptor, 1485 new String [] { 1486 Integer.toString(fieldInfo.getDescriptorIndex()), 1487 new String (fieldDescriptor) 1488 })); 1489 if (fieldInfo.isDeprecated()) { 1490 buffer.append(Messages.disassembler_deprecated); 1491 } 1492 writeNewLine(buffer, lineSeparator, tabNumber); 1493 if (signatureAttribute != null) { 1494 buffer.append(Messages.bind(Messages.disassembler_signatureattributeheader, new String (signatureAttribute.getSignature()))); 1495 writeNewLine(buffer, lineSeparator, tabNumber); 1496 } 1497 } 1498 final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS); 1499 final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS); 1500 if (checkMode(mode, DETAILED)) { 1501 if (runtimeInvisibleAnnotationsAttribute != null) { 1503 disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 1504 writeNewLine(buffer, lineSeparator, tabNumber); 1505 } 1506 if (runtimeVisibleAnnotationsAttribute != null) { 1507 disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode); 1508 writeNewLine(buffer, lineSeparator, tabNumber); 1509 } 1510 } 1511 if (checkMode(mode, WORKING_COPY)) { 1512 decodeModifiersForFieldForWorkingCopy(buffer, fieldInfo.getAccessFlags()); 1513 if (signatureAttribute != null) { 1514 buffer.append(returnClassName(getSignatureForField(signatureAttribute.getSignature()), '.', mode)); 1515 } else { 1516 buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode)); 1517 } 1518 } else { 1519 decodeModifiersForField(buffer, fieldInfo.getAccessFlags()); 1520 if (fieldInfo.isSynthetic()) { 1521 buffer.append("synthetic"); buffer.append(Messages.disassembler_space); 1523 } 1524 buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode)); 1525 } 1526 buffer.append(' '); 1527 buffer.append(new String (fieldInfo.getName())); 1528 IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute(); 1529 if (constantValueAttribute != null) { 1530 buffer.append(Messages.disassembler_fieldhasconstant); 1531 IConstantPoolEntry constantPoolEntry = constantValueAttribute.getConstantValue(); 1532 switch(constantPoolEntry.getKind()) { 1533 case IConstantPoolConstant.CONSTANT_Long : 1534 buffer.append(constantPoolEntry.getLongValue() + "L"); break; 1536 case IConstantPoolConstant.CONSTANT_Float : 1537 buffer.append(constantPoolEntry.getFloatValue() + "f"); break; 1539 case IConstantPoolConstant.CONSTANT_Double : 1540 final double doubleValue = constantPoolEntry.getDoubleValue(); 1541 if (checkMode(mode, ClassFileBytesDisassembler.WORKING_COPY)) { 1542 if (doubleValue == Double.POSITIVE_INFINITY) { 1543 buffer.append("1.0 / 0.0"); } else if (doubleValue == Double.NEGATIVE_INFINITY) { 1545 buffer.append("-1.0 / 0.0"); } else { 1547 buffer.append(constantPoolEntry.getDoubleValue()); 1548 } 1549 } else { 1550 buffer.append(constantPoolEntry.getDoubleValue()); 1551 } 1552 break; 1553 case IConstantPoolConstant.CONSTANT_Integer: 1554 switch(fieldDescriptor[0]) { 1555 case 'C' : 1556 buffer.append("'" + (char) constantPoolEntry.getIntegerValue() + "'"); break; 1558 case 'Z' : 1559 buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false"); break; 1561 case 'B' : 1562 buffer.append(constantPoolEntry.getIntegerValue()); 1563 break; 1564 case 'S' : 1565 buffer.append(constantPoolEntry.getIntegerValue()); 1566 break; 1567 case 'I' : 1568 buffer.append(constantPoolEntry.getIntegerValue()); 1569 } 1570 break; 1571 case IConstantPoolConstant.CONSTANT_String: 1572 buffer.append("\"" + decodeStringValue(constantPoolEntry.getStringValue()) + "\"" ); } 1574 } 1575 buffer.append(Messages.disassembler_endoffieldheader); 1576 if (checkMode(mode, SYSTEM)) { 1577 IClassFileAttribute[] attributes = fieldInfo.getAttributes(); 1578 int length = attributes.length; 1579 if (length != 0) { 1580 for (int i = 0; i < length; i++) { 1581 IClassFileAttribute attribute = attributes[i]; 1582 if (attribute != constantValueAttribute 1583 && attribute != signatureAttribute 1584 && attribute != runtimeInvisibleAnnotationsAttribute 1585 && attribute != runtimeVisibleAnnotationsAttribute 1586 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.DEPRECATED) 1587 && !CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 1588 disassemble(attribute, buffer, lineSeparator, tabNumber); 1589 } 1590 } 1591 } 1592 if (runtimeVisibleAnnotationsAttribute != null) { 1593 disassemble((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber); 1594 } 1595 if (runtimeInvisibleAnnotationsAttribute != null) { 1596 disassemble((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber); 1597 } 1598 } 1599 } 1600 1601 private void disassemble(IInnerClassesAttribute innerClassesAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1602 writeNewLine(buffer, lineSeparator, tabNumber); 1603 buffer.append(Messages.disassembler_innerattributesheader); 1604 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1605 IInnerClassesAttributeEntry[] innerClassesAttributeEntries = innerClassesAttribute.getInnerClassAttributesEntries(); 1606 int length = innerClassesAttributeEntries.length; 1607 int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags; 1608 IInnerClassesAttributeEntry innerClassesAttributeEntry; 1609 for (int i = 0; i < length; i++) { 1610 if (i != 0) { 1611 buffer.append(Messages.disassembler_comma); 1612 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1613 } 1614 innerClassesAttributeEntry = innerClassesAttributeEntries[i]; 1615 innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex(); 1616 outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex(); 1617 innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex(); 1618 accessFlags = innerClassesAttributeEntry.getAccessFlags(); 1619 buffer 1620 .append(Messages.disassembler_openinnerclassentry) 1621 .append(Messages.disassembler_inner_class_info_name) 1622 .append(Messages.disassembler_constantpoolindex) 1623 .append(innerClassNameIndex); 1624 if (innerClassNameIndex != 0) { 1625 buffer 1626 .append(Messages.disassembler_space) 1627 .append(innerClassesAttributeEntry.getInnerClassName()); 1628 } 1629 buffer 1630 .append(Messages.disassembler_comma) 1631 .append(Messages.disassembler_space) 1632 .append(Messages.disassembler_outer_class_info_name) 1633 .append(Messages.disassembler_constantpoolindex) 1634 .append(outerClassNameIndex); 1635 if (outerClassNameIndex != 0) { 1636 buffer 1637 .append(Messages.disassembler_space) 1638 .append(innerClassesAttributeEntry.getOuterClassName()); 1639 } 1640 writeNewLine(buffer, lineSeparator, tabNumber); 1641 dumpTab(tabNumber, buffer); 1642 buffer.append(Messages.disassembler_space); 1643 buffer 1644 .append(Messages.disassembler_inner_name) 1645 .append(Messages.disassembler_constantpoolindex) 1646 .append(innerNameIndex); 1647 if (innerNameIndex != 0) { 1648 buffer 1649 .append(Messages.disassembler_space) 1650 .append(innerClassesAttributeEntry.getInnerName()); 1651 } 1652 buffer 1653 .append(Messages.disassembler_comma) 1654 .append(Messages.disassembler_space) 1655 .append(Messages.disassembler_inner_accessflags) 1656 .append(accessFlags) 1657 .append(Messages.disassembler_space); 1658 decodeModifiersForInnerClasses(buffer, accessFlags, true); 1659 buffer 1660 .append(Messages.disassembler_closeinnerclassentry); 1661 } 1662 } 1663 1664 private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber) { 1665 IAnnotation[] annotations = parameterAnnotation.getAnnotations(); 1666 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1667 buffer.append( 1668 Messages.bind(Messages.disassembler_parameterannotationentrystart, new String [] {Integer.toString(index), Integer.toString(annotations.length)})); 1669 for (int i = 0, max = annotations.length; i < max; i++) { 1670 disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1); 1671 } 1672 } 1673 1674 private void disassemble(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1675 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1676 buffer.append(Messages.disassembler_runtimeinvisibleannotationsattributeheader); 1677 IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations(); 1678 for (int i = 0, max = annotations.length; i < max; i++) { 1679 disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1); 1680 } 1681 } 1682 1683 private void disassemble(IRuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1684 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1685 buffer.append(Messages.disassembler_runtimeinvisibleparameterannotationsattributeheader); 1686 IParameterAnnotation[] parameterAnnotations = runtimeInvisibleParameterAnnotationsAttribute.getParameterAnnotations(); 1687 for (int i = 0, max = parameterAnnotations.length; i < max; i++) { 1688 disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1); 1689 } 1690 } 1691 1692 private void disassemble(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1693 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1694 buffer.append(Messages.disassembler_runtimevisibleannotationsattributeheader); 1695 IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations(); 1696 for (int i = 0, max = annotations.length; i < max; i++) { 1697 disassemble(annotations[i], buffer, lineSeparator, tabNumber + 1); 1698 } 1699 } 1700 1701 private void disassemble(IRuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) { 1702 writeNewLine(buffer, lineSeparator, tabNumber + 1); 1703 buffer.append(Messages.disassembler_runtimevisibleparameterannotationsattributeheader); 1704 IParameterAnnotation[] parameterAnnotations = runtimeVisibleParameterAnnotationsAttribute.getParameterAnnotations(); 1705 for (int i = 0, max = parameterAnnotations.length; i < max; i++) { 1706 disassemble(i, parameterAnnotations[i], buffer, lineSeparator, tabNumber + 1); 1707 } 1708 } 1709 1710 private String disassemble(IVerificationTypeInfo[] infos, int mode) { 1711 StringBuffer buffer = new StringBuffer (); 1712 buffer.append('{'); 1713 for (int i = 0, max = infos.length; i < max; i++) { 1714 if(i != 0) { 1715 buffer 1716 .append(Messages.disassembler_comma) 1717 .append(Messages.disassembler_space); 1718 } 1719 switch(infos[i].getTag()) { 1720 case IVerificationTypeInfo.ITEM_DOUBLE : 1721 buffer.append("double"); break; 1723 case IVerificationTypeInfo.ITEM_FLOAT : 1724 buffer.append("float"); break; 1726 case IVerificationTypeInfo.ITEM_INTEGER : 1727 buffer.append("int"); break; 1729 case IVerificationTypeInfo.ITEM_LONG : 1730 buffer.append("long"); break; 1732 case IVerificationTypeInfo.ITEM_NULL : 1733 buffer.append("null"); break; 1735 case IVerificationTypeInfo.ITEM_OBJECT : 1736 char[] classTypeName = infos[i].getClassTypeName(); 1737 CharOperation.replace(classTypeName, '/', '.'); 1738 if (classTypeName.length > 0 && classTypeName[0] == '[') { classTypeName = Signature.toCharArray(classTypeName); 1740 } 1741 buffer.append(returnClassName(classTypeName, '.', mode)); 1742 break; 1743 case IVerificationTypeInfo.ITEM_TOP : 1744 buffer.append("_"); break; 1746 case IVerificationTypeInfo.ITEM_UNINITIALIZED : 1747 buffer.append("uninitialized("); buffer.append(infos[i].getOffset()); 1749 buffer.append(')'); 1750 break; 1751 case IVerificationTypeInfo.ITEM_UNINITIALIZED_THIS : 1752 buffer.append("uninitialized_this"); } 1754 } 1755 buffer.append('}'); 1756 return String.valueOf(buffer); 1757 } 1758 1759 private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1760 final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.'); 1761 buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode)); 1762 final IAnnotationComponent[] components = annotation.getComponents(); 1763 final int length = components.length; 1764 if (length != 0) { 1765 buffer.append('('); 1766 for (int i = 0; i < length; i++) { 1767 if (i > 0) { 1768 buffer.append(','); 1769 writeNewLine(buffer, lineSeparator, tabNumber); 1770 } 1771 disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode); 1772 } 1773 buffer.append(')'); 1774 } 1775 } 1776 1777 private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1778 buffer.append(annotationComponent.getComponentName()).append('='); 1779 disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode); 1780 } 1781 1782 private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1783 switch(annotationComponentValue.getTag()) { 1784 case IAnnotationComponentValue.BYTE_TAG: 1785 case IAnnotationComponentValue.CHAR_TAG: 1786 case IAnnotationComponentValue.DOUBLE_TAG: 1787 case IAnnotationComponentValue.FLOAT_TAG: 1788 case IAnnotationComponentValue.INTEGER_TAG: 1789 case IAnnotationComponentValue.LONG_TAG: 1790 case IAnnotationComponentValue.SHORT_TAG: 1791 case IAnnotationComponentValue.BOOLEAN_TAG: 1792 case IAnnotationComponentValue.STRING_TAG: 1793 IConstantPoolEntry constantPoolEntry = annotationComponentValue.getConstantValue(); 1794 String value = null; 1795 switch(constantPoolEntry.getKind()) { 1796 case IConstantPoolConstant.CONSTANT_Long : 1797 value = constantPoolEntry.getLongValue() + "L"; break; 1799 case IConstantPoolConstant.CONSTANT_Float : 1800 value = constantPoolEntry.getFloatValue() + "f"; break; 1802 case IConstantPoolConstant.CONSTANT_Double : 1803 value = Double.toString(constantPoolEntry.getDoubleValue()); 1804 break; 1805 case IConstantPoolConstant.CONSTANT_Integer: 1806 switch(annotationComponentValue.getTag()) { 1807 case IAnnotationComponentValue.CHAR_TAG : 1808 value = "'" + (char) constantPoolEntry.getIntegerValue() + "'"; break; 1810 case IAnnotationComponentValue.BOOLEAN_TAG : 1811 value = constantPoolEntry.getIntegerValue() == 1 ? "true" : "false"; break; 1813 case IAnnotationComponentValue.BYTE_TAG : 1814 value = "(byte) " + constantPoolEntry.getIntegerValue(); break; 1816 case IAnnotationComponentValue.SHORT_TAG : 1817 value = "(short) " + constantPoolEntry.getIntegerValue(); break; 1819 case IAnnotationComponentValue.INTEGER_TAG : 1820 value = "(int) " + constantPoolEntry.getIntegerValue(); } 1822 break; 1823 case IConstantPoolConstant.CONSTANT_Utf8: 1824 value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\""; } 1826 buffer.append(value); 1827 break; 1828 case IAnnotationComponentValue.ENUM_TAG: 1829 final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.'); 1830 final char[] constantName = annotationComponentValue.getEnumConstantName(); 1831 buffer.append(Signature.toCharArray(typeName)).append('.').append(constantName); 1832 break; 1833 case IAnnotationComponentValue.CLASS_TAG: 1834 constantPoolEntry = annotationComponentValue.getClassInfo(); 1835 final char[] className = CharOperation.replaceOnCopy(constantPoolEntry.getUtf8Value(), '/', '.'); 1836 buffer.append(Signature.toCharArray(className)); 1837 break; 1838 case IAnnotationComponentValue.ANNOTATION_TAG: 1839 IAnnotation annotation = annotationComponentValue.getAnnotationValue(); 1840 disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode); 1841 break; 1842 case IAnnotationComponentValue.ARRAY_TAG: 1843 final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues(); 1844 buffer.append('{'); 1845 for (int i = 0, max = annotationComponentValues.length; i < max; i++) { 1846 if (i > 0) { 1847 buffer.append(','); 1848 } 1849 disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode); 1850 } 1851 buffer.append('}'); 1852 } 1853 } 1854 1855 private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1856 IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue(); 1857 disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode); 1858 } 1859 1860 private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1861 IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations(); 1862 for (int i = 0, max = annotations.length; i < max; i++) { 1863 disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 1864 } 1865 } 1866 1867 private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) { 1868 IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations(); 1869 for (int i = 0, max = annotations.length; i < max; i++) { 1870 disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode); 1871 } 1872 } 1873 1874 private void disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum) { 1875 IFieldInfo[] fields = classFileReader.getFieldInfos(); 1876 if (isEnum && checkMode(mode, WORKING_COPY)) { 1877 int index = 0; 1878 final int fieldsLength = fields.length; 1879 IMethodInfo[] methods = classFileReader.getMethodInfos(); 1880 char[][] constructorArguments = getConstructorArgumentsForEnum(methods); 1881 enumConstantLoop: for (; index < fieldsLength; index++) { 1882 final IFieldInfo fieldInfo = fields[index]; 1883 final int accessFlags = fieldInfo.getAccessFlags(); 1884 if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) { 1885 writeNewLine(buffer, lineSeparator, tabNumber); 1886 disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments, mode); 1887 } else { 1888 break enumConstantLoop; 1889 } 1890 } 1891 buffer.append(';'); 1892 boolean foundSyntheticField = false; 1893 fieldLoop: for (; index < fieldsLength; index++) { 1894 if (!foundSyntheticField && CharOperation.equals(TypeConstants.SYNTHETIC_ENUM_VALUES, fields[index].getName())) { 1895 foundSyntheticField = true; 1896 continue fieldLoop; 1897 } 1898 writeNewLine(buffer, lineSeparator, tabNumber); 1899 disassemble(fields[index], buffer, lineSeparator, tabNumber, mode); 1900 } 1901 methodLoop: for (int i = 0, max = methods.length; i < max; i++) { 1902 final IMethodInfo methodInfo = methods[i]; 1903 if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUES)) { 1904 final char[] descriptor = methodInfo.getDescriptor(); 1905 CharOperation.replace(descriptor, '/', '.'); 1906 if (Signature.getParameterCount(descriptor) == 0) { 1907 if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode), 1908 CharOperation.concat(new char[] {'[', 'L'}, className, new char[] {';'}))) { 1909 continue methodLoop; 1910 } 1911 } 1912 } else if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUEOF)) { 1913 final char[] descriptor = methodInfo.getDescriptor(); 1914 CharOperation.replace(descriptor, '/', '.'); 1915 final char[][] parameterTypes = Signature.getParameterTypes(descriptor); 1916 if (parameterTypes.length == 1 1917 && CharOperation.equals(parameterTypes[0], "Ljava.lang.String;".toCharArray())) { if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode), 1919 CharOperation.concat('L', className, ';'))) { 1920 continue methodLoop; 1921 } 1922 } 1923 } else if (methodInfo.isClinit() || methodInfo.isSynthetic()) { 1924 continue methodLoop; 1925 } else if (methodInfo.isConstructor()) { 1926 writeNewLine(buffer, lineSeparator, tabNumber); 1927 disassembleEnumConstructor(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode); 1928 } else { 1929 writeNewLine(buffer, lineSeparator, tabNumber); 1930 disassemble(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode); 1931 } 1932 } 1933 } else { 1934 for (int i = 0, max = fields.length; i < max; i++) { 1935 writeNewLine(buffer, lineSeparator, tabNumber); 1936 disassemble(fields[i], buffer, lineSeparator, tabNumber, mode); 1937 } 1938 IMethodInfo[] methods = classFileReader.getMethodInfos(); 1939 for (int i = 0, max = methods.length; i < max; i++) { 1940 writeNewLine(buffer, lineSeparator, tabNumber); 1941 disassemble(classFileReader, className, methods[i], buffer, lineSeparator, tabNumber, mode); 1942 } 1943 } 1944 } 1945 1946 private char[][] getConstructorArgumentsForEnum(final IMethodInfo[] methods) { 1947 loop: for (int i = 0, max = methods.length; i < max; i++) { 1948 IMethodInfo methodInfo = methods[i]; 1949 if (methodInfo.isConstructor()) { 1950 char[][] parameterTypes = Signature.getParameterTypes(methodInfo.getDescriptor()); 1951 final int length = parameterTypes.length; 1952 if (length >= 2) { 1953 return CharOperation.subarray(parameterTypes, 2, length); 1954 } 1955 } else { 1956 continue loop; 1957 } 1958 } 1959 return null; 1960 } 1961 1962 private final void dumpTab(int tabNumber, StringBuffer buffer) { 1963 for (int i = 0; i < tabNumber; i++) { 1964 buffer.append(Messages.disassembler_indentation); 1965 } 1966 } 1967 1968 private final String dumpNewLineWithTabs(String lineSeparator, int tabNumber) { 1969 StringBuffer buffer = new StringBuffer (); 1970 writeNewLine(buffer, lineSeparator, tabNumber); 1971 return String.valueOf(buffer); 1972 } 1973 1974 1977 public String getDescription() { 1978 return Messages.disassembler_description; 1979 } 1980 1981 private IEnclosingMethodAttribute getEnclosingMethodAttribute(IClassFileReader classFileReader) { 1982 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 1983 for (int i = 0, max = attributes.length; i < max; i++) { 1984 if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.ENCLOSING_METHOD)) { 1985 return (IEnclosingMethodAttribute) attributes[i]; 1986 } 1987 } 1988 return null; 1989 } 1990 private IClassFileAttribute getAttribute(final char[] attributeName, final ICodeAttribute codeAttribute) { 1991 IClassFileAttribute[] attributes = codeAttribute.getAttributes(); 1992 for (int i = 0, max = attributes.length; i < max; i++) { 1993 if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) { 1994 return attributes[i]; 1995 } 1996 } 1997 return null; 1998 } 1999 2000 private char[][] getParameterNames(char[] methodDescriptor, ICodeAttribute codeAttribute, int accessFlags) { 2001 int paramCount = Signature.getParameterCount(methodDescriptor); 2002 char[][] parameterNames = new char[paramCount][]; 2003 if (codeAttribute != null) { 2005 ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute(); 2006 if (localVariableAttribute != null) { 2007 ILocalVariableTableEntry[] entries = localVariableAttribute.getLocalVariableTable(); 2008 final int startingIndex = (accessFlags & IModifierConstants.ACC_STATIC) != 0 ? 0 : 1; 2009 for (int i = 0; i < paramCount; i++) { 2010 ILocalVariableTableEntry searchedEntry = getEntryFor(getLocalIndex(startingIndex, i, methodDescriptor), entries); 2011 if (searchedEntry != null) { 2012 parameterNames[i] = searchedEntry.getName(); 2013 } else { 2014 parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray()); 2015 } 2016 } 2017 } else { 2018 for (int i = 0; i < paramCount; i++) { 2019 parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray()); 2020 } 2021 } 2022 } else { 2023 for (int i = 0; i < paramCount; i++) { 2024 parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray()); 2025 } 2026 } 2027 return parameterNames; 2028 } 2029 2030 private int getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor) { 2031 int slot = startingSlot; 2032 final char[][] types = Signature.getParameterTypes(methodDescriptor); 2033 for (int i = 0; i < index; i++) { 2034 final char[] type = types[i]; 2035 switch(type.length) { 2036 case 1 : 2037 switch(type[0]) { 2038 case 'D' : 2039 case 'J' : 2040 slot += 2; 2041 break; 2042 default : 2043 slot++; 2044 } 2045 break; 2046 default : 2047 slot++; 2048 } 2049 } 2050 return slot; 2051 } 2052 2053 private ILocalVariableTableEntry getEntryFor(final int index, final ILocalVariableTableEntry[] entries) { 2054 for (int i = 0, max = entries.length; i < max; i++) { 2055 ILocalVariableTableEntry entry = entries[i]; 2056 if (index == entry.getIndex()) { 2057 return entry; 2058 } 2059 } 2060 return null; 2061 } 2062 2063 private char[] getSignatureForField(char[] fieldDescriptor) { 2064 char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.'); 2065 newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '%'); 2066 char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor); 2067 CharOperation.replace(fieldDescriptorSignature, '%', '$'); 2068 return fieldDescriptorSignature; 2069 } 2070 2071 private boolean isDeprecated(IClassFileReader classFileReader) { 2072 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 2073 for (int i = 0, max = attributes.length; i < max; i++) { 2074 if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.DEPRECATED)) { 2075 return true; 2076 } 2077 } 2078 return false; 2079 } 2080 2081 private boolean isSynthetic(IClassFileReader classFileReader) { 2082 int flags = classFileReader.getAccessFlags(); 2083 if ((flags & IModifierConstants.ACC_SYNTHETIC) != 0) { 2084 return true; 2085 } 2086 IClassFileAttribute[] attributes = classFileReader.getAttributes(); 2087 for (int i = 0, max = attributes.length; i < max; i++) { 2088 if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.SYNTHETIC)) { 2089 return true; 2090 } 2091 } 2092 return false; 2093 } 2094 2095 private boolean checkMode(int mode, int flag) { 2096 return (mode & flag) != 0; 2097 } 2098 2099 private boolean isCompact(int mode) { 2100 return (mode & ClassFileBytesDisassembler.COMPACT) != 0; 2101 } 2102 2103 private char[] returnClassName(char[] classInfoName, char separator, int mode) { 2104 if (classInfoName.length == 0) { 2105 return CharOperation.NO_CHAR; 2106 } else if (isCompact(mode)) { 2107 int lastIndexOfSlash = CharOperation.lastIndexOf(separator, classInfoName); 2108 if (lastIndexOfSlash != -1) { 2109 return CharOperation.subarray(classInfoName, lastIndexOfSlash + 1, classInfoName.length); 2110 } 2111 } 2112 return classInfoName; 2113 } 2114 2115 private void writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber) { 2116 buffer.append(lineSeparator); 2117 dumpTab(tabNumber, buffer); 2118 } 2119} 2120 | Popular Tags |