src/share/classes/com/sun/tools/javap/ClassWriter.java

Fri, 04 Oct 2013 16:08:18 -0700

author
ksrini
date
Fri, 04 Oct 2013 16:08:18 -0700
changeset 2089
bb87db832b31
parent 1578
040f02711b73
child 2267
3b9176029091
permissions
-rw-r--r--

8003537: javap use internal class name when printing bound of type variable
Reviewed-by: jjg

jjg@46 1 /*
jjh@1478 2 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
jjg@46 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@46 4 *
jjg@46 5 * This code is free software; you can redistribute it and/or modify it
jjg@46 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
jjg@46 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@46 10 *
jjg@46 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@46 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@46 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@46 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@46 15 * accompanied this code).
jjg@46 16 *
jjg@46 17 * You should have received a copy of the GNU General Public License version
jjg@46 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@46 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@46 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
jjg@46 24 */
jjg@46 25
jjg@46 26 package com.sun.tools.javap;
jjg@46 27
jjg@88 28 import java.net.URI;
jjg@283 29 import java.text.DateFormat;
jjg@46 30 import java.util.Collection;
jjg@283 31 import java.util.Date;
jjg@46 32 import java.util.List;
jjg@46 33
jjg@46 34 import com.sun.tools.classfile.AccessFlags;
jjg@46 35 import com.sun.tools.classfile.Attribute;
jjg@46 36 import com.sun.tools.classfile.Attributes;
jjg@46 37 import com.sun.tools.classfile.ClassFile;
jjg@46 38 import com.sun.tools.classfile.Code_attribute;
jjg@46 39 import com.sun.tools.classfile.ConstantPool;
jjg@46 40 import com.sun.tools.classfile.ConstantPoolException;
jjg@87 41 import com.sun.tools.classfile.ConstantValue_attribute;
jjg@46 42 import com.sun.tools.classfile.Descriptor;
jjg@46 43 import com.sun.tools.classfile.DescriptorException;
jjg@46 44 import com.sun.tools.classfile.Exceptions_attribute;
jjg@46 45 import com.sun.tools.classfile.Field;
jjg@46 46 import com.sun.tools.classfile.Method;
jjg@46 47 import com.sun.tools.classfile.Signature;
jjg@46 48 import com.sun.tools.classfile.Signature_attribute;
jjg@46 49 import com.sun.tools.classfile.SourceFile_attribute;
jjg@46 50 import com.sun.tools.classfile.Type;
jjg@953 51 import com.sun.tools.classfile.Type.ArrayType;
jjg@953 52 import com.sun.tools.classfile.Type.ClassSigType;
jjg@953 53 import com.sun.tools.classfile.Type.ClassType;
jjg@953 54 import com.sun.tools.classfile.Type.MethodType;
jjg@953 55 import com.sun.tools.classfile.Type.SimpleType;
jjg@953 56 import com.sun.tools.classfile.Type.TypeParamType;
jjg@953 57 import com.sun.tools.classfile.Type.WildcardType;
jjg@46 58
jjg@46 59 import static com.sun.tools.classfile.AccessFlags.*;
jjg@46 60
jjg@46 61 /*
jjg@46 62 * The main javap class to write the contents of a class file as text.
jjg@46 63 *
jjg@581 64 * <p><b>This is NOT part of any supported API.
jjg@581 65 * If you write code that depends on this, you do so at your own risk.
jjg@46 66 * This code and its internal interfaces are subject to change or
jjg@46 67 * deletion without notice.</b>
jjg@46 68 */
jjg@46 69 public class ClassWriter extends BasicWriter {
jjg@46 70 static ClassWriter instance(Context context) {
jjg@46 71 ClassWriter instance = context.get(ClassWriter.class);
jjg@46 72 if (instance == null)
jjg@46 73 instance = new ClassWriter(context);
jjg@46 74 return instance;
jjg@46 75 }
jjg@46 76
jjg@46 77 protected ClassWriter(Context context) {
jjg@46 78 super(context);
jjg@46 79 context.put(ClassWriter.class, this);
jjg@46 80 options = Options.instance(context);
jjg@46 81 attrWriter = AttributeWriter.instance(context);
jjg@46 82 codeWriter = CodeWriter.instance(context);
jjg@46 83 constantWriter = ConstantWriter.instance(context);
jjg@46 84 }
jjg@46 85
jjg@88 86 void setDigest(String name, byte[] digest) {
jjg@88 87 this.digestName = name;
jjg@88 88 this.digest = digest;
jjg@88 89 }
jjg@88 90
jjg@88 91 void setFile(URI uri) {
jjg@88 92 this.uri = uri;
jjg@88 93 }
jjg@88 94
jjg@88 95 void setFileSize(int size) {
jjg@88 96 this.size = size;
jjg@88 97 }
jjg@88 98
jjg@88 99 void setLastModified(long lastModified) {
jjg@88 100 this.lastModified = lastModified;
jjg@88 101 }
jjg@88 102
jjg@300 103 protected ClassFile getClassFile() {
jjg@46 104 return classFile;
jjg@46 105 }
jjg@46 106
jjg@300 107 protected void setClassFile(ClassFile cf) {
jjg@300 108 classFile = cf;
jjg@300 109 constant_pool = classFile.constant_pool;
jjg@300 110 }
jjg@300 111
jjg@300 112 protected Method getMethod() {
jjg@46 113 return method;
jjg@46 114 }
jjg@46 115
jjg@300 116 protected void setMethod(Method m) {
jjg@300 117 method = m;
jjg@300 118 }
jjg@300 119
jjg@46 120 public void write(ClassFile cf) {
jjg@300 121 setClassFile(cf);
jjg@46 122
jjg@88 123 if ((options.sysInfo || options.verbose) && !options.compat) {
jjg@88 124 if (uri != null) {
jjg@88 125 if (uri.getScheme().equals("file"))
jjg@88 126 println("Classfile " + uri.getPath());
jjg@88 127 else
jjg@88 128 println("Classfile " + uri);
jjg@88 129 }
jjg@348 130 indent(+1);
jjg@88 131 if (lastModified != -1) {
jjg@88 132 Date lm = new Date(lastModified);
jjg@88 133 DateFormat df = DateFormat.getDateInstance();
jjg@88 134 if (size > 0) {
jjg@88 135 println("Last modified " + df.format(lm) + "; size " + size + " bytes");
jjg@88 136 } else {
jjg@88 137 println("Last modified " + df.format(lm));
jjg@88 138 }
jjg@88 139 } else if (size > 0) {
jjg@88 140 println("Size " + size + " bytes");
jjg@88 141 }
jjg@88 142 if (digestName != null && digest != null) {
jjg@88 143 StringBuilder sb = new StringBuilder();
jjg@88 144 for (byte b: digest)
jjg@88 145 sb.append(String.format("%02x", b));
jjg@88 146 println(digestName + " checksum " + sb);
jjg@88 147 }
jjg@88 148 }
jjg@88 149
jjg@46 150 Attribute sfa = cf.getAttribute(Attribute.SourceFile);
jjg@46 151 if (sfa instanceof SourceFile_attribute) {
jjg@46 152 println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
jjg@46 153 }
jjg@46 154
jjg@348 155 if ((options.sysInfo || options.verbose) && !options.compat) {
jjg@348 156 indent(-1);
jjg@348 157 }
jjg@348 158
jjg@46 159 String name = getJavaName(classFile);
jjg@46 160 AccessFlags flags = cf.access_flags;
jjg@46 161
jjg@46 162 writeModifiers(flags.getClassModifiers());
jjg@46 163
jjg@46 164 if (classFile.isClass())
jjg@46 165 print("class ");
jjg@46 166 else if (classFile.isInterface())
jjg@46 167 print("interface ");
jjg@46 168
jjg@46 169 print(name);
jjg@46 170
jjg@46 171 Signature_attribute sigAttr = getSignature(cf.attributes);
jjg@46 172 if (sigAttr == null) {
jjg@46 173 // use info from class file header
jjg@65 174 if (classFile.isClass() && classFile.super_class != 0 ) {
jjg@65 175 String sn = getJavaSuperclassName(cf);
jjg@953 176 if (!sn.equals("java.lang.Object")) {
jjg@953 177 print(" extends ");
jjg@953 178 print(sn);
jjg@953 179 }
jjg@46 180 }
jjg@46 181 for (int i = 0; i < classFile.interfaces.length; i++) {
jjg@46 182 print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
jjg@46 183 print(getJavaInterfaceName(classFile, i));
jjg@46 184 }
jjg@46 185 } else {
jjg@46 186 try {
jjg@46 187 Type t = sigAttr.getParsedSignature().getType(constant_pool);
jjg@953 188 JavaTypePrinter p = new JavaTypePrinter(classFile.isInterface());
jjg@46 189 // The signature parser cannot disambiguate between a
jjg@46 190 // FieldType and a ClassSignatureType that only contains a superclass type.
jjg@953 191 if (t instanceof Type.ClassSigType) {
jjg@953 192 print(p.print(t));
jjg@953 193 } else if (options.verbose || !t.isObject()) {
jjg@46 194 print(" extends ");
jjg@953 195 print(p.print(t));
jjg@46 196 }
jjg@46 197 } catch (ConstantPoolException e) {
jjg@46 198 print(report(e));
jjg@46 199 }
jjg@46 200 }
jjg@46 201
jjg@46 202 if (options.verbose) {
jjg@46 203 println();
jjg@348 204 indent(+1);
jjg@46 205 attrWriter.write(cf, cf.attributes, constant_pool);
jjg@348 206 println("minor version: " + cf.minor_version);
jjg@348 207 println("major version: " + cf.major_version);
jjg@46 208 if (!options.compat)
jjh@1478 209 writeList("flags: ", flags.getClassFlags(), "\n");
jjg@348 210 indent(-1);
jjg@46 211 constantWriter.writeConstantPool();
jjg@46 212 } else {
jjg@348 213 print(" ");
jjg@46 214 }
jjg@46 215
jjg@46 216 println("{");
jjg@348 217 indent(+1);
jjg@46 218 writeFields();
jjg@46 219 writeMethods();
jjg@348 220 indent(-1);
jjg@46 221 println("}");
jjg@46 222 }
jjg@953 223 // where
jjg@953 224 class JavaTypePrinter implements Type.Visitor<StringBuilder,StringBuilder> {
jjg@953 225 boolean isInterface;
jjg@953 226
jjg@953 227 JavaTypePrinter(boolean isInterface) {
jjg@953 228 this.isInterface = isInterface;
jjg@953 229 }
jjg@953 230
jjg@953 231 String print(Type t) {
jjg@953 232 return t.accept(this, new StringBuilder()).toString();
jjg@953 233 }
jjg@953 234
ksrini@2089 235 String printTypeArgs(List<? extends TypeParamType> typeParamTypes) {
ksrini@2089 236 StringBuilder builder = new StringBuilder();
ksrini@2089 237 appendIfNotEmpty(builder, "<", typeParamTypes, "> ");
ksrini@2089 238 return builder.toString();
ksrini@2089 239 }
ksrini@2089 240
jjg@953 241 public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) {
jjg@953 242 sb.append(getJavaName(type.name));
jjg@953 243 return sb;
jjg@953 244 }
jjg@953 245
jjg@953 246 public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) {
jjg@953 247 append(sb, type.elemType);
jjg@953 248 sb.append("[]");
jjg@953 249 return sb;
jjg@953 250 }
jjg@953 251
jjg@953 252 public StringBuilder visitMethodType(MethodType type, StringBuilder sb) {
jjg@953 253 appendIfNotEmpty(sb, "<", type.typeParamTypes, "> ");
jjg@953 254 append(sb, type.returnType);
jjg@953 255 append(sb, " (", type.paramTypes, ")");
jjg@953 256 appendIfNotEmpty(sb, " throws ", type.throwsTypes, "");
jjg@953 257 return sb;
jjg@953 258 }
jjg@953 259
jjg@953 260 public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) {
jjg@953 261 appendIfNotEmpty(sb, "<", type.typeParamTypes, ">");
jjg@953 262 if (isInterface) {
jjg@953 263 appendIfNotEmpty(sb, " extends ", type.superinterfaceTypes, "");
jjg@953 264 } else {
jjg@953 265 if (type.superclassType != null
jjg@953 266 && (options.verbose || !type.superclassType.isObject())) {
jjg@953 267 sb.append(" extends ");
jjg@953 268 append(sb, type.superclassType);
jjg@953 269 }
jjg@953 270 appendIfNotEmpty(sb, " implements ", type.superinterfaceTypes, "");
jjg@953 271 }
jjg@953 272 return sb;
jjg@953 273 }
jjg@953 274
jjg@953 275 public StringBuilder visitClassType(ClassType type, StringBuilder sb) {
jjg@953 276 if (type.outerType != null) {
jjg@953 277 append(sb, type.outerType);
jjg@953 278 sb.append(".");
jjg@953 279 }
jjg@953 280 sb.append(getJavaName(type.name));
jjg@953 281 appendIfNotEmpty(sb, "<", type.typeArgs, ">");
jjg@953 282 return sb;
jjg@953 283 }
jjg@953 284
jjg@953 285 public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) {
jjg@953 286 sb.append(type.name);
jjg@953 287 String sep = " extends ";
jjg@953 288 if (type.classBound != null
jjg@953 289 && (options.verbose || !type.classBound.isObject())) {
jjg@953 290 sb.append(sep);
jjg@953 291 append(sb, type.classBound);
jjg@953 292 sep = " & ";
jjg@953 293 }
jjg@953 294 if (type.interfaceBounds != null) {
jjg@953 295 for (Type bound: type.interfaceBounds) {
jjg@953 296 sb.append(sep);
jjg@953 297 append(sb, bound);
jjg@953 298 sep = " & ";
jjg@953 299 }
jjg@953 300 }
jjg@953 301 return sb;
jjg@953 302 }
jjg@953 303
jjg@953 304 public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) {
jjg@953 305 switch (type.kind) {
jjg@953 306 case UNBOUNDED:
jjg@953 307 sb.append("?");
jjg@953 308 break;
jjg@953 309 case EXTENDS:
jjg@953 310 sb.append("? extends ");
jjg@953 311 append(sb, type.boundType);
jjg@953 312 break;
jjg@953 313 case SUPER:
jjg@953 314 sb.append("? super ");
jjg@953 315 append(sb, type.boundType);
jjg@953 316 break;
jjg@953 317 default:
jjg@953 318 throw new AssertionError();
jjg@953 319 }
jjg@953 320 return sb;
jjg@953 321 }
jjg@953 322
jjg@953 323 private void append(StringBuilder sb, Type t) {
jjg@953 324 t.accept(this, sb);
jjg@953 325 }
jjg@953 326
jjg@953 327 private void append(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
jjg@953 328 sb.append(prefix);
jjg@953 329 String sep = "";
jjg@953 330 for (Type t: list) {
jjg@953 331 sb.append(sep);
jjg@953 332 append(sb, t);
jjg@953 333 sep = ", ";
jjg@953 334 }
jjg@953 335 sb.append(suffix);
jjg@953 336 }
jjg@953 337
jjg@953 338 private void appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> list, String suffix) {
jjg@953 339 if (!isEmpty(list))
jjg@953 340 append(sb, prefix, list, suffix);
jjg@953 341 }
jjg@953 342
jjg@953 343 private boolean isEmpty(List<? extends Type> list) {
jjg@953 344 return (list == null || list.isEmpty());
jjg@953 345 }
jjg@953 346 }
jjg@46 347
jjg@300 348 protected void writeFields() {
jjg@46 349 for (Field f: classFile.fields) {
jjg@46 350 writeField(f);
jjg@46 351 }
jjg@46 352 }
jjg@46 353
jjg@300 354 protected void writeField(Field f) {
jjg@46 355 if (!options.checkAccess(f.access_flags))
jjg@46 356 return;
jjg@46 357
jjg@46 358 AccessFlags flags = f.access_flags;
jjg@46 359 writeModifiers(flags.getFieldModifiers());
jjg@46 360 Signature_attribute sigAttr = getSignature(f.attributes);
jjg@46 361 if (sigAttr == null)
jjg@528 362 print(getJavaFieldType(f.descriptor));
jjg@46 363 else {
jjg@46 364 try {
jjg@46 365 Type t = sigAttr.getParsedSignature().getType(constant_pool);
jjg@528 366 print(getJavaName(t.toString()));
jjg@46 367 } catch (ConstantPoolException e) {
jjg@46 368 // report error?
jjg@46 369 // fall back on non-generic descriptor
jjg@528 370 print(getJavaFieldType(f.descriptor));
jjg@46 371 }
jjg@46 372 }
jjg@46 373 print(" ");
jjg@46 374 print(getFieldName(f));
jjg@87 375 if (options.showConstants && !options.compat) { // BUG 4111861 print static final field contents
jjg@87 376 Attribute a = f.attributes.get(Attribute.ConstantValue);
jjg@87 377 if (a instanceof ConstantValue_attribute) {
jjg@87 378 print(" = ");
jjg@87 379 ConstantValue_attribute cv = (ConstantValue_attribute) a;
jjg@87 380 print(getConstantValue(f.descriptor, cv.constantvalue_index));
jjg@87 381 }
jjg@87 382 }
jjg@46 383 print(";");
jjg@46 384 println();
jjg@46 385
jjg@348 386 indent(+1);
jjg@348 387
jjg@1578 388 if (options.showDescriptors)
jjg@1578 389 println("descriptor: " + getValue(f.descriptor));
jjg@46 390
jjg@46 391 if (options.verbose && !options.compat)
jjh@1478 392 writeList("flags: ", flags.getFieldFlags(), "\n");
jjg@46 393
jjg@46 394 if (options.showAllAttrs) {
jjg@46 395 for (Attribute attr: f.attributes)
jjg@46 396 attrWriter.write(f, attr, constant_pool);
jjg@46 397 println();
jjg@46 398 }
jjg@46 399
jjg@348 400 indent(-1);
jjg@348 401
jjg@46 402 if (options.showDisassembled || options.showLineAndLocalVariableTables)
jjg@46 403 println();
jjg@46 404 }
jjg@46 405
jjg@300 406 protected void writeMethods() {
jjg@46 407 for (Method m: classFile.methods)
jjg@46 408 writeMethod(m);
jjg@348 409 setPendingNewline(false);
jjg@46 410 }
jjg@46 411
jjg@300 412 protected void writeMethod(Method m) {
jjg@46 413 if (!options.checkAccess(m.access_flags))
jjg@46 414 return;
jjg@46 415
jjg@46 416 method = m;
jjg@46 417
jjg@46 418 AccessFlags flags = m.access_flags;
jjg@46 419
jjg@46 420 Descriptor d;
jjg@46 421 Type.MethodType methodType;
jjg@46 422 List<? extends Type> methodExceptions;
jjg@46 423
jjg@46 424 Signature_attribute sigAttr = getSignature(m.attributes);
jjg@46 425 if (sigAttr == null) {
jjg@46 426 d = m.descriptor;
jjg@46 427 methodType = null;
jjg@46 428 methodExceptions = null;
jjg@46 429 } else {
jjg@46 430 Signature methodSig = sigAttr.getParsedSignature();
jjg@46 431 d = methodSig;
jjg@46 432 try {
jjg@46 433 methodType = (Type.MethodType) methodSig.getType(constant_pool);
jjg@46 434 methodExceptions = methodType.throwsTypes;
jjg@953 435 if (methodExceptions != null && methodExceptions.isEmpty())
jjg@46 436 methodExceptions = null;
jjg@46 437 } catch (ConstantPoolException e) {
jjg@46 438 // report error?
jjg@46 439 // fall back on standard descriptor
jjg@46 440 methodType = null;
jjg@46 441 methodExceptions = null;
jjg@46 442 }
jjg@46 443 }
jjg@46 444
jjg@46 445 writeModifiers(flags.getMethodModifiers());
jjg@46 446 if (methodType != null) {
ksrini@2089 447 print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes));
jjg@46 448 }
jjg@46 449 if (getName(m).equals("<init>")) {
jjg@46 450 print(getJavaName(classFile));
jjg@528 451 print(getJavaParameterTypes(d, flags));
jjg@46 452 } else if (getName(m).equals("<clinit>")) {
jjg@46 453 print("{}");
jjg@46 454 } else {
jjg@528 455 print(getJavaReturnType(d));
jjg@46 456 print(" ");
jjg@46 457 print(getName(m));
jjg@528 458 print(getJavaParameterTypes(d, flags));
jjg@46 459 }
jjg@46 460
jjg@46 461 Attribute e_attr = m.attributes.get(Attribute.Exceptions);
jjg@46 462 if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
jjg@46 463 if (e_attr instanceof Exceptions_attribute) {
jjg@46 464 Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
jjg@46 465 print(" throws ");
jjg@46 466 if (methodExceptions != null) { // use generic list if available
jjg@46 467 writeList("", methodExceptions, "");
jjg@46 468 } else {
jjg@46 469 for (int i = 0; i < exceptions.number_of_exceptions; i++) {
jjg@46 470 if (i > 0)
jjg@46 471 print(", ");
jjg@52 472 print(getJavaException(exceptions, i));
jjg@46 473 }
jjg@46 474 }
jjg@46 475 } else {
jjg@46 476 report("Unexpected or invalid value for Exceptions attribute");
jjg@46 477 }
jjg@46 478 }
jjg@46 479
jjg@348 480 println(";");
jjg@46 481
jjg@348 482 indent(+1);
jjg@46 483
jjg@1578 484 if (options.showDescriptors) {
jjg@1578 485 println("descriptor: " + getValue(m.descriptor));
jjg@348 486 }
jjg@348 487
jjg@348 488 if (options.verbose && !options.compat) {
jjh@1478 489 writeList("flags: ", flags.getMethodFlags(), "\n");
jjg@348 490 }
jjg@46 491
jjg@46 492 Code_attribute code = null;
jjg@46 493 Attribute c_attr = m.attributes.get(Attribute.Code);
jjg@46 494 if (c_attr != null) {
jjg@46 495 if (c_attr instanceof Code_attribute)
jjg@46 496 code = (Code_attribute) c_attr;
jjg@46 497 else
jjg@46 498 report("Unexpected or invalid value for Code attribute");
jjg@46 499 }
jjg@46 500
jjg@46 501 if (options.showDisassembled && !options.showAllAttrs) {
jjg@46 502 if (code != null) {
jjg@348 503 println("Code:");
jjg@46 504 codeWriter.writeInstrs(code);
jjg@46 505 codeWriter.writeExceptionTable(code);
jjg@46 506 }
jjg@46 507 }
jjg@46 508
jjg@46 509 if (options.showLineAndLocalVariableTables) {
jjg@348 510 if (code != null) {
jjg@46 511 attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
jjg@46 512 attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
jjg@348 513 }
jjg@46 514 }
jjg@46 515
jjg@46 516 if (options.showAllAttrs) {
jjg@46 517 Attribute[] attrs = m.attributes.attrs;
jjg@46 518 for (Attribute attr: attrs)
jjg@46 519 attrWriter.write(m, attr, constant_pool);
jjg@348 520 }
jjg@46 521
jjg@348 522 indent(-1);
jjg@348 523
jjg@348 524 // set pendingNewline to write a newline before the next method (if any)
jjg@348 525 // if a separator is desired
jjg@348 526 setPendingNewline(
jjg@348 527 options.showDisassembled ||
jjg@348 528 options.showAllAttrs ||
jjg@1578 529 options.showDescriptors ||
jjg@348 530 options.showLineAndLocalVariableTables ||
jjg@348 531 options.verbose);
jjg@46 532 }
jjg@46 533
jjg@46 534 void writeModifiers(Collection<String> items) {
jjg@46 535 for (Object item: items) {
jjg@46 536 print(item);
jjg@46 537 print(" ");
jjg@46 538 }
jjg@46 539 }
jjg@46 540
jjg@46 541 void writeList(String prefix, Collection<?> items, String suffix) {
jjg@46 542 print(prefix);
jjg@46 543 String sep = "";
jjg@46 544 for (Object item: items) {
jjg@46 545 print(sep);
jjg@46 546 print(item);
jjg@46 547 sep = ", ";
jjg@46 548 }
jjg@46 549 print(suffix);
jjg@46 550 }
jjg@46 551
jjg@46 552 void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
jjg@46 553 if (items != null && items.size() > 0)
jjg@46 554 writeList(prefix, items, suffix);
jjg@46 555 }
jjg@46 556
jjg@46 557 Signature_attribute getSignature(Attributes attributes) {
jjg@46 558 if (options.compat) // javap does not recognize recent attributes
jjg@46 559 return null;
jjg@46 560 return (Signature_attribute) attributes.get(Attribute.Signature);
jjg@46 561 }
jjg@46 562
jjg@46 563 String adjustVarargs(AccessFlags flags, String params) {
jjg@46 564 if (flags.is(ACC_VARARGS) && !options.compat) {
jjg@46 565 int i = params.lastIndexOf("[]");
jjg@46 566 if (i > 0)
jjg@46 567 return params.substring(0, i) + "..." + params.substring(i+2);
jjg@46 568 }
jjg@46 569
jjg@46 570 return params;
jjg@46 571 }
jjg@46 572
jjg@46 573 String getJavaName(ClassFile cf) {
jjg@46 574 try {
jjg@46 575 return getJavaName(cf.getName());
jjg@46 576 } catch (ConstantPoolException e) {
jjg@46 577 return report(e);
jjg@46 578 }
jjg@46 579 }
jjg@46 580
jjg@46 581 String getJavaSuperclassName(ClassFile cf) {
jjg@46 582 try {
jjg@46 583 return getJavaName(cf.getSuperclassName());
jjg@46 584 } catch (ConstantPoolException e) {
jjg@46 585 return report(e);
jjg@46 586 }
jjg@46 587 }
jjg@46 588
jjg@46 589 String getJavaInterfaceName(ClassFile cf, int index) {
jjg@46 590 try {
jjg@46 591 return getJavaName(cf.getInterfaceName(index));
jjg@46 592 } catch (ConstantPoolException e) {
jjg@46 593 return report(e);
jjg@46 594 }
jjg@46 595 }
jjg@46 596
jjg@528 597 String getJavaFieldType(Descriptor d) {
jjg@46 598 try {
jjg@528 599 return getJavaName(d.getFieldType(constant_pool));
jjg@46 600 } catch (ConstantPoolException e) {
jjg@46 601 return report(e);
jjg@46 602 } catch (DescriptorException e) {
jjg@46 603 return report(e);
jjg@46 604 }
jjg@46 605 }
jjg@46 606
jjg@528 607 String getJavaReturnType(Descriptor d) {
jjg@46 608 try {
jjg@528 609 return getJavaName(d.getReturnType(constant_pool));
jjg@46 610 } catch (ConstantPoolException e) {
jjg@46 611 return report(e);
jjg@46 612 } catch (DescriptorException e) {
jjg@46 613 return report(e);
jjg@46 614 }
jjg@46 615 }
jjg@46 616
jjg@528 617 String getJavaParameterTypes(Descriptor d, AccessFlags flags) {
jjg@46 618 try {
jjg@528 619 return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool)));
jjg@46 620 } catch (ConstantPoolException e) {
jjg@46 621 return report(e);
jjg@46 622 } catch (DescriptorException e) {
jjg@46 623 return report(e);
jjg@46 624 }
jjg@46 625 }
jjg@46 626
jjg@52 627 String getJavaException(Exceptions_attribute attr, int index) {
jjg@52 628 try {
jjg@52 629 return getJavaName(attr.getException(index, constant_pool));
jjg@52 630 } catch (ConstantPoolException e) {
jjg@52 631 return report(e);
jjg@52 632 }
jjg@52 633 }
jjg@52 634
jjg@46 635 String getValue(Descriptor d) {
jjg@46 636 try {
jjg@46 637 return d.getValue(constant_pool);
jjg@46 638 } catch (ConstantPoolException e) {
jjg@46 639 return report(e);
jjg@46 640 }
jjg@46 641 }
jjg@46 642
jjg@46 643 String getFieldName(Field f) {
jjg@46 644 try {
jjg@46 645 return f.getName(constant_pool);
jjg@46 646 } catch (ConstantPoolException e) {
jjg@46 647 return report(e);
jjg@46 648 }
jjg@46 649 }
jjg@46 650
jjg@46 651 String getName(Method m) {
jjg@46 652 try {
jjg@46 653 return m.getName(constant_pool);
jjg@46 654 } catch (ConstantPoolException e) {
jjg@46 655 return report(e);
jjg@46 656 }
jjg@46 657 }
jjg@46 658
jjg@46 659 static String getJavaName(String name) {
jjg@46 660 return name.replace('/', '.');
jjg@46 661 }
jjg@46 662
jjg@46 663 String getSourceFile(SourceFile_attribute attr) {
jjg@46 664 try {
jjg@46 665 return attr.getSourceFile(constant_pool);
jjg@46 666 } catch (ConstantPoolException e) {
jjg@46 667 return report(e);
jjg@46 668 }
jjg@46 669 }
jjg@46 670
jjg@87 671 /**
jjg@87 672 * Get the value of an entry in the constant pool as a Java constant.
jjg@87 673 * Characters and booleans are represented by CONSTANT_Intgere entries.
jjg@87 674 * Character and string values are processed to escape characters outside
jjg@87 675 * the basic printable ASCII set.
jjg@87 676 * @param d the descriptor, giving the expected type of the constant
jjg@87 677 * @param index the index of the value in the constant pool
jjg@87 678 * @return a printable string containing the value of the constant.
jjg@87 679 */
jjg@87 680 String getConstantValue(Descriptor d, int index) {
jjg@87 681 try {
jjg@87 682 ConstantPool.CPInfo cpInfo = constant_pool.get(index);
jjg@87 683
jjg@87 684 switch (cpInfo.getTag()) {
jjg@87 685 case ConstantPool.CONSTANT_Integer: {
jjg@87 686 ConstantPool.CONSTANT_Integer_info info =
jjg@87 687 (ConstantPool.CONSTANT_Integer_info) cpInfo;
jjg@87 688 String t = d.getValue(constant_pool);
jjg@87 689 if (t.equals("C")) { // character
jjg@87 690 return getConstantCharValue((char) info.value);
jjg@87 691 } else if (t.equals("Z")) { // boolean
jjg@87 692 return String.valueOf(info.value == 1);
jjg@87 693 } else { // other: assume integer
jjg@87 694 return String.valueOf(info.value);
jjg@87 695 }
jjg@87 696 }
jjg@87 697
jjg@87 698 case ConstantPool.CONSTANT_String: {
jjg@87 699 ConstantPool.CONSTANT_String_info info =
jjg@87 700 (ConstantPool.CONSTANT_String_info) cpInfo;
jjg@87 701 return getConstantStringValue(info.getString());
jjg@87 702 }
jjg@87 703
jjg@87 704 default:
jjg@87 705 return constantWriter.stringValue(cpInfo);
jjg@87 706 }
jjg@87 707 } catch (ConstantPoolException e) {
jjg@87 708 return "#" + index;
jjg@87 709 }
jjg@87 710 }
jjg@87 711
jjg@87 712 private String getConstantCharValue(char c) {
jjg@87 713 StringBuilder sb = new StringBuilder();
jjg@87 714 sb.append('\'');
jjg@87 715 sb.append(esc(c, '\''));
jjg@87 716 sb.append('\'');
jjg@87 717 return sb.toString();
jjg@87 718 }
jjg@87 719
jjg@87 720 private String getConstantStringValue(String s) {
jjg@87 721 StringBuilder sb = new StringBuilder();
jjg@87 722 sb.append("\"");
jjg@87 723 for (int i = 0; i < s.length(); i++) {
jjg@87 724 sb.append(esc(s.charAt(i), '"'));
jjg@87 725 }
jjg@87 726 sb.append("\"");
jjg@87 727 return sb.toString();
jjg@87 728 }
jjg@87 729
jjg@87 730 private String esc(char c, char quote) {
jjg@87 731 if (32 <= c && c <= 126 && c != quote)
jjg@87 732 return String.valueOf(c);
jjg@87 733 else switch (c) {
jjg@87 734 case '\b': return "\\b";
jjg@87 735 case '\n': return "\\n";
jjg@87 736 case '\t': return "\\t";
jjg@87 737 case '\f': return "\\f";
jjg@87 738 case '\r': return "\\r";
jjg@87 739 case '\\': return "\\\\";
jjg@87 740 case '\'': return "\\'";
jjg@87 741 case '\"': return "\\\"";
jjg@87 742 default: return String.format("\\u%04x", (int) c);
jjg@87 743 }
jjg@87 744 }
jjg@87 745
jjg@46 746 private Options options;
jjg@46 747 private AttributeWriter attrWriter;
jjg@46 748 private CodeWriter codeWriter;
jjg@46 749 private ConstantWriter constantWriter;
jjg@46 750 private ClassFile classFile;
jjg@88 751 private URI uri;
jjg@88 752 private long lastModified;
jjg@88 753 private String digestName;
jjg@88 754 private byte[] digest;
jjg@88 755 private int size;
jjg@46 756 private ConstantPool constant_pool;
jjg@46 757 private Method method;
jjg@46 758 }

mercurial