1 /* 2 * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.tools.java; 27 28 import sun.tools.tree.Node; 29 import sun.tools.tree.Vset; 30 import sun.tools.tree.Expression; 31 import sun.tools.tree.Statement; 32 import sun.tools.tree.Context; 33 import sun.tools.asm.Assembler; 34 import java.io.PrintStream; 35 import java.util.Vector; 36 import java.util.Map; 37 import java.util.HashMap; 38 39 /** 40 * This class defines a member of a Java class: 41 * a variable, a method, or an inner class. 42 * 43 * WARNING: The contents of this source file are not part of any 44 * supported API. Code that depends on them does so at its own risk: 45 * they are subject to change or removal without notice. 46 */ 47 public 48 class MemberDefinition implements Constants { 49 protected long where; 50 protected int modifiers; 51 protected Type type; 52 protected String documentation; 53 protected IdentifierToken expIds[]; 54 protected ClassDeclaration exp[]; 55 protected Node value; 56 protected ClassDefinition clazz; 57 protected Identifier name; 58 protected ClassDefinition innerClass; 59 protected MemberDefinition nextMember; 60 protected MemberDefinition nextMatch; 61 protected MemberDefinition accessPeer; 62 protected boolean superAccessMethod; 63 64 /** 65 * Constructor 66 */ 67 public MemberDefinition(long where, ClassDefinition clazz, int modifiers, 68 Type type, Identifier name, 69 IdentifierToken expIds[], Node value) { 70 if (expIds == null) { 71 expIds = new IdentifierToken[0]; 72 } 73 this.where = where; 74 this.clazz = clazz; 75 this.modifiers = modifiers; 76 this.type = type; 77 this.name = name; 78 this.expIds = expIds; 79 this.value = value; 80 } 81 82 /** 83 * Constructor for an inner class. 84 * Inner classes are represented as fields right along with 85 * variables and methods for simplicity of data structure, 86 * and to reflect properly the textual declaration order. 87 * <p> 88 * This constructor calls the generic constructor for this 89 * class, extracting all necessary values from the innerClass. 90 */ 91 public MemberDefinition(ClassDefinition innerClass) { 92 this(innerClass.getWhere(), 93 innerClass.getOuterClass(), 94 innerClass.getModifiers(), 95 innerClass.getType(), 96 innerClass.getName().getFlatName().getName(), 97 null, null); 98 this.innerClass = innerClass; 99 } 100 101 /** 102 * A cache of previously created proxy members. Used to ensure 103 * uniqueness of proxy objects. See the makeProxyMember method 104 * defined below. 105 */ 106 static private Map proxyCache; 107 108 /** 109 * Create a member which is externally the same as `field' but 110 * is defined in class `classDef'. This is used by code 111 * in sun.tools.tree.(MethodExpression,FieldExpression) as 112 * part of the fix for bug 4135692. 113 * 114 * Proxy members should not be added, ala addMember(), to classes. 115 * They are merely "stand-ins" to produce modified MethodRef 116 * constant pool entries during code generation. 117 * 118 * We keep a cache of previously created proxy members not to 119 * save time or space, but to ensure uniqueness of the proxy 120 * member for any (field,classDef) pair. If these are not made 121 * unique then we can end up generating duplicate MethodRef 122 * constant pool entries during code generation. 123 */ 124 public static MemberDefinition makeProxyMember(MemberDefinition field, 125 ClassDefinition classDef, 126 Environment env) { 127 128 if (proxyCache == null) { 129 proxyCache = new HashMap(); 130 } 131 132 String key = field.toString() + "@" + classDef.toString(); 133 // System.out.println("Key is : " + key); 134 MemberDefinition proxy = (MemberDefinition)proxyCache.get(key); 135 136 if (proxy != null) 137 return proxy; 138 139 proxy = new MemberDefinition(field.getWhere(), classDef, 140 field.getModifiers(), field.getType(), 141 field.getName(), field.getExceptionIds(), 142 null); 143 proxy.exp = field.getExceptions(env); 144 proxyCache.put(key, proxy); 145 146 return proxy; 147 } 148 149 /** 150 * Get the position in the input 151 */ 152 public final long getWhere() { 153 return where; 154 } 155 156 /** 157 * Get the class declaration 158 */ 159 public final ClassDeclaration getClassDeclaration() { 160 return clazz.getClassDeclaration(); 161 } 162 163 /** 164 * A stub. Subclasses can do more checking. 165 */ 166 public void resolveTypeStructure(Environment env) { 167 } 168 169 /** 170 * Get the class declaration in which the field is actually defined 171 */ 172 public ClassDeclaration getDefiningClassDeclaration() { 173 return getClassDeclaration(); 174 } 175 176 /** 177 * Get the class definition 178 */ 179 public final ClassDefinition getClassDefinition() { 180 return clazz; 181 } 182 183 /** 184 * Get the field's top-level enclosing class 185 */ 186 public final ClassDefinition getTopClass() { 187 return clazz.getTopClass(); 188 } 189 190 /** 191 * Get the field's modifiers 192 */ 193 public final int getModifiers() { 194 return modifiers; 195 } 196 public final void subModifiers(int mod) { 197 modifiers &= ~mod; 198 } 199 public final void addModifiers(int mod) { 200 modifiers |= mod; 201 } 202 203 /** 204 * Get the field's type 205 */ 206 public final Type getType() { 207 return type; 208 } 209 210 /** 211 * Get the field's name 212 */ 213 public final Identifier getName() { 214 return name; 215 } 216 217 /** 218 * Get arguments (a vector of LocalMember) 219 */ 220 public Vector getArguments() { 221 return isMethod() ? new Vector() : null; 222 } 223 224 /** 225 * Get the exceptions that are thrown by this method. 226 */ 227 public ClassDeclaration[] getExceptions(Environment env) { 228 if (expIds != null && exp == null) { 229 if (expIds.length == 0) 230 exp = new ClassDeclaration[0]; 231 else 232 // we should have translated this already! 233 throw new CompilerError("getExceptions "+this); 234 } 235 return exp; 236 } 237 238 public final IdentifierToken[] getExceptionIds() { 239 return expIds; 240 } 241 242 /** 243 * Get an inner class. 244 */ 245 public ClassDefinition getInnerClass() { 246 return innerClass; 247 } 248 249 /** 250 * Is this a synthetic field which holds a copy of, 251 * or reference to, a local variable or enclosing instance? 252 */ 253 public boolean isUplevelValue() { 254 if (!isSynthetic() || !isVariable() || isStatic()) { 255 return false; 256 } 257 String name = this.name.toString(); 258 return name.startsWith(prefixVal) 259 || name.startsWith(prefixLoc) 260 || name.startsWith(prefixThis); 261 } 262 263 public boolean isAccessMethod() { 264 // This no longer works, because access methods 265 // for constructors do not use the standard naming 266 // scheme. 267 // return isSynthetic() && isMethod() 268 // && name.toString().startsWith(prefixAccess); 269 // Assume that a method is an access method if it has 270 // an access peer. NOTE: An access method will not be 271 // recognized as such until 'setAccessMethodTarget' has 272 // been called on it. 273 return isSynthetic() && isMethod() && (accessPeer != null); 274 } 275 276 /** 277 * Is this a synthetic method which provides access to a 278 * visible private member? 279 */ 280 public MemberDefinition getAccessMethodTarget() { 281 if (isAccessMethod()) { 282 for (MemberDefinition f = accessPeer; f != null; f = f.accessPeer) { 283 // perhaps skip over another access for the same field 284 if (!f.isAccessMethod()) { 285 return f; 286 } 287 } 288 } 289 return null; 290 } 291 292 293 public void setAccessMethodTarget(MemberDefinition target) { 294 if (getAccessMethodTarget() != target) { 295 /*-------------------* 296 if (!isAccessMethod() || accessPeer != null || 297 target.accessPeer != null) { 298 throw new CompilerError("accessPeer"); 299 } 300 *-------------------*/ 301 if (accessPeer != null || target.accessPeer != null) { 302 throw new CompilerError("accessPeer"); 303 } 304 accessPeer = target; 305 } 306 } 307 308 /** 309 * If this method is a getter for a private field, return the setter. 310 */ 311 public MemberDefinition getAccessUpdateMember() { 312 if (isAccessMethod()) { 313 for (MemberDefinition f = accessPeer; f != null; f = f.accessPeer) { 314 if (f.isAccessMethod()) { 315 return f; 316 } 317 } 318 } 319 return null; 320 } 321 322 public void setAccessUpdateMember(MemberDefinition updater) { 323 if (getAccessUpdateMember() != updater) { 324 if (!isAccessMethod() || 325 updater.getAccessMethodTarget() != getAccessMethodTarget()) { 326 throw new CompilerError("accessPeer"); 327 } 328 updater.accessPeer = accessPeer; 329 accessPeer = updater; 330 } 331 } 332 333 /** 334 * Is this an access method for a field selection or method call 335 * of the form '...super.foo' or '...super.foo()'? 336 */ 337 public final boolean isSuperAccessMethod() { 338 return superAccessMethod; 339 } 340 341 /** 342 * Mark this member as an access method for a field selection 343 * or method call via the 'super' keyword. 344 */ 345 public final void setIsSuperAccessMethod(boolean b) { 346 superAccessMethod = b; 347 } 348 349 /** 350 * Tell if this is a final variable without an initializer. 351 * Such variables are subject to definite single assignment. 352 */ 353 public final boolean isBlankFinal() { 354 return isFinal() && !isSynthetic() && getValue() == null; 355 } 356 357 public boolean isNeverNull() { 358 if (isUplevelValue()) { 359 // loc$x and this$C are never null 360 return !name.toString().startsWith(prefixVal); 361 } 362 return false; 363 } 364 365 /** 366 * Get the field's final value (may return null) 367 */ 368 public Node getValue(Environment env) throws ClassNotFound { 369 return value; 370 } 371 public final Node getValue() { 372 return value; 373 } 374 public final void setValue(Node value) { 375 this.value = value; 376 } 377 public Object getInitialValue() { 378 return null; 379 } 380 381 /** 382 * Get the next field or the next match 383 */ 384 public final MemberDefinition getNextMember() { 385 return nextMember; 386 } 387 public final MemberDefinition getNextMatch() { 388 return nextMatch; 389 } 390 391 /** 392 * Get the field's documentation 393 */ 394 public String getDocumentation() { 395 return documentation; 396 } 397 398 /** 399 * Request a check of the field definition. 400 */ 401 public void check(Environment env) throws ClassNotFound { 402 } 403 404 /** 405 * Really check the field definition. 406 */ 407 public Vset check(Environment env, Context ctx, Vset vset) throws ClassNotFound { 408 return vset; 409 } 410 411 /** 412 * Generate code 413 */ 414 public void code(Environment env, Assembler asm) throws ClassNotFound { 415 throw new CompilerError("code"); 416 } 417 public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound { 418 throw new CompilerError("codeInit"); 419 } 420 421 /** 422 * Tells whether to report a deprecation error for this field. 423 */ 424 public boolean reportDeprecated(Environment env) { 425 return (isDeprecated() || clazz.reportDeprecated(env)); 426 } 427 428 /** 429 * Check if a field can reach another field (only considers 430 * forward references, not the access modifiers). 431 */ 432 public final boolean canReach(Environment env, MemberDefinition f) { 433 if (f.isLocal() || !f.isVariable() || !(isVariable() || isInitializer())) 434 return true; 435 if ((getClassDeclaration().equals(f.getClassDeclaration())) && 436 (isStatic() == f.isStatic())) { 437 // They are located in the same class, and are either both 438 // static or both non-static. Check the initialization order. 439 while (((f = f.getNextMember()) != null) && (f != this)); 440 return f != null; 441 } 442 return true; 443 } 444 445 //----------------------------------------------------------------- 446 // The code in this section is intended to test certain kinds of 447 // compatibility between methods. There are two kinds of compatibility 448 // that the compiler may need to test. The first is whether one 449 // method can legally override another. The second is whether two 450 // method definitions can legally coexist. We use the word `meet' 451 // to mean the intersection of two legally coexisting methods. 452 // For more information on these kinds of compatibility, see the 453 // comments/code for checkOverride() and checkMeet() below. 454 455 /** 456 * Constants used by getAccessLevel() to represent the access 457 * modifiers as numbers. 458 */ 459 static final int PUBLIC_ACCESS = 1; 460 static final int PROTECTED_ACCESS = 2; 461 static final int PACKAGE_ACCESS = 3; 462 static final int PRIVATE_ACCESS = 4; 463 464 /** 465 * Return the access modifier of this member as a number. The idea 466 * is that this number may be used to check properties like "the 467 * access modifier of x is more restrictive than the access 468 * modifier of y" with a simple inequality test: 469 * "x.getAccessLevel() > y.getAccessLevel. 470 * 471 * This is an internal utility method. 472 */ 473 private int getAccessLevel() { 474 // Could just compute this once instead of recomputing. 475 // Check to see if this is worth it. 476 if (isPublic()) { 477 return PUBLIC_ACCESS; 478 } else if (isProtected()) { 479 return PROTECTED_ACCESS; 480 } else if (isPackagePrivate()) { 481 return PACKAGE_ACCESS; 482 } else if (isPrivate()) { 483 return PRIVATE_ACCESS; 484 } else { 485 throw new CompilerError("getAccessLevel()"); 486 } 487 } 488 489 /** 490 * Munge our error message to report whether the override conflict 491 * came from an inherited method or a declared method. 492 */ 493 private void reportError(Environment env, String errorString, 494 ClassDeclaration clazz, 495 MemberDefinition method) { 496 497 if (clazz == null) { 498 // For example: 499 // "Instance method BLAH inherited from CLASSBLAH1 cannot be 500 // overridden by the static method declared in CLASSBLAH2." 501 env.error(getWhere(), errorString, 502 this, getClassDeclaration(), 503 method.getClassDeclaration()); 504 } else { 505 // For example: 506 // "In CLASSBLAH1, instance method BLAH inherited from CLASSBLAH2 507 // cannot be overridden by the static method inherited from 508 // CLASSBLAH3." 509 env.error(clazz.getClassDefinition().getWhere(), 510 //"inherit." + errorString, 511 errorString, 512 //clazz, 513 this, getClassDeclaration(), 514 method.getClassDeclaration()); 515 } 516 } 517 518 /** 519 * Convenience method to see if two methods return the same type 520 */ 521 public boolean sameReturnType(MemberDefinition method) { 522 // Make sure both are methods. 523 if (!isMethod() || !method.isMethod()) { 524 throw new CompilerError("sameReturnType: not method"); 525 } 526 527 Type myReturnType = getType().getReturnType(); 528 Type yourReturnType = method.getType().getReturnType(); 529 530 return (myReturnType == yourReturnType); 531 } 532 533 /** 534 * Check to see if `this' can override/hide `method'. Caller is 535 * responsible for verifying that `method' has the same signature 536 * as `this'. Caller is also responsible for verifying that 537 * `method' is visible to the class where this override is occurring. 538 * This method is called for the case when class B extends A and both 539 * A and B define some method. 540 * <pre> 541 * A - void foo() throws e1 542 * | 543 * | 544 * B - void foo() throws e2 545 * </pre> 546 */ 547 public boolean checkOverride(Environment env, MemberDefinition method) { 548 return checkOverride(env, method, null); 549 } 550 551 /** 552 * Checks whether `this' can override `method'. It `clazz' is 553 * null, it reports the errors in the class where `this' is 554 * declared. If `clazz' is not null, it reports the error in `clazz'. 555 */ 556 private boolean checkOverride(Environment env, 557 MemberDefinition method, 558 ClassDeclaration clazz) { 559 // This section of code is largely based on section 8.4.6.3 560 // of the JLS. 561 562 boolean success = true; 563 564 // Sanity 565 if (!isMethod()) { 566 throw new CompilerError("checkOverride(), expected method"); 567 } 568 569 // Suppress checks for synthetic methods, as the compiler presumably 570 // knows what it is doing, e.g., access methods. 571 if (isSynthetic()) { 572 // Sanity check: We generally do not intend for one synthetic 573 // method to override another, though hiding of static members 574 // is expected. This check may need to be changed if new uses 575 // of synthetic methods are devised. 576 // 577 // Query: this code was copied from elsewhere. What 578 // exactly is the role of the !isStatic() in the test? 579 if (method.isFinal() || 580 (!method.isConstructor() && 581 !method.isStatic() && !isStatic())) { 582 //////////////////////////////////////////////////////////// 583 // NMG 2003-01-28 removed the following test because it is 584 // invalidated by bridge methods inserted by the "generic" 585 // (1.5) Java compiler. In 1.5, this code is used, 586 // indirectly, by rmic 587 //////////////////////////////////////////////////////////// 588 // throw new CompilerError("checkOverride() synthetic"); 589 //////////////////////////////////////////////////////////// 590 } 591 592 // We trust the compiler. (Ha!) We're done checking. 593 return true; 594 } 595 596 // Our caller should have verified that the method had the 597 // same signature. 598 if (getName() != method.getName() || 599 !getType().equalArguments(method.getType())) { 600 601 throw new CompilerError("checkOverride(), signature mismatch"); 602 } 603 604 // It is forbidden to `override' a static method with an instance 605 // method. 606 if (method.isStatic() && !isStatic()) { 607 reportError(env, "override.static.with.instance", clazz, method); 608 success = false; 609 } 610 611 // It is forbidden to `hide' an instance method with a static 612 // method. 613 if (!method.isStatic() && isStatic()) { 614 reportError(env, "hide.instance.with.static", clazz, method); 615 success = false; 616 } 617 618 // We cannot override a final method. 619 if (method.isFinal()) { 620 reportError(env, "override.final.method", clazz, method); 621 success = false; 622 } 623 624 // Give a warning when we override a deprecated method with 625 // a non-deprecated one. 626 // 627 // We bend over backwards to suppress this warning if 628 // the `method' has not been already compiled or 629 // `this' has been already compiled. 630 if (method.reportDeprecated(env) && !isDeprecated() 631 && this instanceof sun.tools.javac.SourceMember) { 632 reportError(env, "warn.override.is.deprecated", 633 clazz, method); 634 } 635 636 // Visibility may not be more restrictive 637 if (getAccessLevel() > method.getAccessLevel()) { 638 reportError(env, "override.more.restrictive", clazz, method); 639 success = false; 640 } 641 642 // Return type equality 643 if (!sameReturnType(method)) { 644 //////////////////////////////////////////////////////////// 645 // PCJ 2003-07-30 removed the following error because it is 646 // invalidated by the covariant return type feature of the 647 // 1.5 compiler. The resulting check is now much looser 648 // than the actual 1.5 language spec, but that should be OK 649 // because this code is only still used by rmic. See 4892308. 650 //////////////////////////////////////////////////////////// 651 // reportError(env, "override.different.return", clazz, method); 652 // success = false; 653 //////////////////////////////////////////////////////////// 654 } 655 656 // Exception agreeement 657 if (!exceptionsFit(env, method)) { 658 reportError(env, "override.incompatible.exceptions", 659 clazz, method); 660 success = false; 661 } 662 663 return success; 664 } 665 666 /** 667 * Check to see if two method definitions are compatible, that is 668 * do they have a `meet'. The meet of two methods is essentially 669 * and `intersection' of 670 * two methods. This method is called when some class C inherits 671 * declarations for some method foo from two parents (superclass, 672 * interfaces) but it does not, itself, have a declaration of foo. 673 * Caller is responsible for making sure that both methods are 674 * indeed visible in clazz. 675 * <pre> 676 * A - void foo() throws e1 677 * \ 678 * \ B void foo() throws e2 679 * \ / 680 * \ / 681 * C 682 * </pre> 683 */ 684 public boolean checkMeet(Environment env, 685 MemberDefinition method, 686 ClassDeclaration clazz) { 687 // This section of code is largely based on Section 8.4.6 688 // and 9.4.1 of the JLS. 689 690 // Sanity 691 if (!isMethod()) { 692 throw new CompilerError("checkMeet(), expected method"); 693 } 694 695 // Check for both non-abstract. 696 if (!isAbstract() && !method.isAbstract()) { 697 throw new CompilerError("checkMeet(), no abstract method"); 698 } 699 700 // If either method is non-abstract, then we need to check that 701 // the abstract method can be properly overridden. We call 702 // the checkOverride method to check this and generate any errors. 703 // This test must follow the previous test. 704 else if (!isAbstract()) { 705 return checkOverride(env, method, clazz); 706 } else if (!method.isAbstract()) { 707 return method.checkOverride(env, this, clazz); 708 } 709 710 // Both methods are abstract. 711 712 // Our caller should have verified that the method has the 713 // same signature. 714 if (getName() != method.getName() || 715 !getType().equalArguments(method.getType())) { 716 717 throw new CompilerError("checkMeet(), signature mismatch"); 718 } 719 720 // Check for return type equality 721 if (!sameReturnType(method)) { 722 // More args? 723 env.error(clazz.getClassDefinition().getWhere(), 724 "meet.different.return", 725 this, this.getClassDeclaration(), 726 method.getClassDeclaration()); 727 return false; 728 } 729 730 // We don't have to check visibility -- there always 731 // potentially exists a meet. Similarly with exceptions. 732 733 // There does exist a meet. 734 return true; 735 } 736 737 /** 738 * This method is meant to be used to determine if one of two inherited 739 * methods could override the other. Unlike checkOverride(), failure 740 * is not an error. This method is only meant to be called after 741 * checkMeet() has succeeded on the two methods. 742 * 743 * If you call couldOverride() without doing a checkMeet() first, then 744 * you are on your own. 745 */ 746 public boolean couldOverride(Environment env, 747 MemberDefinition method) { 748 749 // Sanity 750 if (!isMethod()) { 751 throw new CompilerError("coulcOverride(), expected method"); 752 } 753 754 // couldOverride() is only called with `this' and `method' both 755 // being inherited methods. Neither of them is defined in the 756 // class which we are currently working on. Even though an 757 // abstract method defined *in* a class can override a non-abstract 758 // method defined in a superclass, an abstract method inherited 759 // from an interface *never* can override a non-abstract method. 760 // This comment may sound odd, but that's the way inheritance is. 761 // The following check makes sure we aren't trying to override 762 // an inherited non-abstract definition with an abstract definition 763 // from an interface. 764 if (!method.isAbstract()) { 765 return false; 766 } 767 768 // Visibility should be less restrictive 769 if (getAccessLevel() > method.getAccessLevel()) { 770 return false; 771 } 772 773 // Exceptions 774 if (!exceptionsFit(env, method)) { 775 return false; 776 } 777 778 // Potentially some deprecation warnings could be given here 779 // when we merge two abstract methods, one of which is deprecated. 780 // This is not currently reported. 781 782 return true; 783 } 784 785 /** 786 * Check to see if the exceptions of `this' fit within the 787 * exceptions of `method'. 788 */ 789 private boolean exceptionsFit(Environment env, 790 MemberDefinition method) { 791 ClassDeclaration e1[] = getExceptions(env); // my exceptions 792 ClassDeclaration e2[] = method.getExceptions(env); // parent's 793 794 // This code is taken nearly verbatim from the old implementation 795 // of checkOverride() in SourceClass. 796 outer: 797 for (int i = 0 ; i < e1.length ; i++) { 798 try { 799 ClassDefinition c1 = e1[i].getClassDefinition(env); 800 for (int j = 0 ; j < e2.length ; j++) { 801 if (c1.subClassOf(env, e2[j])) { 802 continue outer; 803 } 804 } 805 if (c1.subClassOf(env, 806 env.getClassDeclaration(idJavaLangError))) 807 continue outer; 808 if (c1.subClassOf(env, 809 env.getClassDeclaration(idJavaLangRuntimeException))) 810 continue outer; 811 812 // the throws was neither something declared by a parent, 813 // nor one of the ignorables. 814 return false; 815 816 } catch (ClassNotFound ee) { 817 // We were unable to find one of the exceptions. 818 env.error(getWhere(), "class.not.found", 819 ee.name, method.getClassDeclaration()); 820 } 821 } 822 823 // All of the exceptions `fit'. 824 return true; 825 } 826 827 //----------------------------------------------------------------- 828 829 /** 830 * Checks 831 */ 832 public final boolean isPublic() { 833 return (modifiers & M_PUBLIC) != 0; 834 } 835 public final boolean isPrivate() { 836 return (modifiers & M_PRIVATE) != 0; 837 } 838 public final boolean isProtected() { 839 return (modifiers & M_PROTECTED) != 0; 840 } 841 public final boolean isPackagePrivate() { 842 return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0; 843 } 844 public final boolean isFinal() { 845 return (modifiers & M_FINAL) != 0; 846 } 847 public final boolean isStatic() { 848 return (modifiers & M_STATIC) != 0; 849 } 850 public final boolean isSynchronized() { 851 return (modifiers & M_SYNCHRONIZED) != 0; 852 } 853 public final boolean isAbstract() { 854 return (modifiers & M_ABSTRACT) != 0; 855 } 856 public final boolean isNative() { 857 return (modifiers & M_NATIVE) != 0; 858 } 859 public final boolean isVolatile() { 860 return (modifiers & M_VOLATILE) != 0; 861 } 862 public final boolean isTransient() { 863 return (modifiers & M_TRANSIENT) != 0; 864 } 865 public final boolean isMethod() { 866 return type.isType(TC_METHOD); 867 } 868 public final boolean isVariable() { 869 return !type.isType(TC_METHOD) && innerClass == null; 870 } 871 public final boolean isSynthetic() { 872 return (modifiers & M_SYNTHETIC) != 0; 873 } 874 public final boolean isDeprecated() { 875 return (modifiers & M_DEPRECATED) != 0; 876 } 877 public final boolean isStrict() { 878 return (modifiers & M_STRICTFP) != 0; 879 } 880 public final boolean isInnerClass() { 881 return innerClass != null; 882 } 883 public final boolean isInitializer() { 884 return getName().equals(idClassInit); 885 } 886 public final boolean isConstructor() { 887 return getName().equals(idInit); 888 } 889 public boolean isLocal() { 890 return false; 891 } 892 public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound { 893 return (isStatic() || isPrivate() || isFinal() || isConstructor() || fromFinal) && 894 !(isSynchronized() || isNative()); 895 } 896 897 /** 898 * Check if constant: Will it inline away to a constant? 899 */ 900 public boolean isConstant() { 901 if (isFinal() && isVariable() && value != null) { 902 try { 903 // If an infinite regress requeries this name, 904 // deny that it is a constant. 905 modifiers &= ~M_FINAL; 906 return ((Expression)value).isConstant(); 907 } finally { 908 modifiers |= M_FINAL; 909 } 910 } 911 return false; 912 } 913 914 /** 915 * toString 916 */ 917 public String toString() { 918 Identifier name = getClassDefinition().getName(); 919 if (isInitializer()) { 920 return isStatic() ? "static {}" : "instance {}"; 921 } else if (isConstructor()) { 922 StringBuffer buf = new StringBuffer(); 923 buf.append(name); 924 buf.append('('); 925 Type argTypes[] = getType().getArgumentTypes(); 926 for (int i = 0 ; i < argTypes.length ; i++) { 927 if (i > 0) { 928 buf.append(','); 929 } 930 buf.append(argTypes[i].toString()); 931 } 932 buf.append(')'); 933 return buf.toString(); 934 } else if (isInnerClass()) { 935 return getInnerClass().toString(); 936 } 937 return type.typeString(getName().toString()); 938 } 939 940 /** 941 * Print for debugging 942 */ 943 public void print(PrintStream out) { 944 if (isPublic()) { 945 out.print("public "); 946 } 947 if (isPrivate()) { 948 out.print("private "); 949 } 950 if (isProtected()) { 951 out.print("protected "); 952 } 953 if (isFinal()) { 954 out.print("final "); 955 } 956 if (isStatic()) { 957 out.print("static "); 958 } 959 if (isSynchronized()) { 960 out.print("synchronized "); 961 } 962 if (isAbstract()) { 963 out.print("abstract "); 964 } 965 if (isNative()) { 966 out.print("native "); 967 } 968 if (isVolatile()) { 969 out.print("volatile "); 970 } 971 if (isTransient()) { 972 out.print("transient "); 973 } 974 out.println(toString() + ";"); 975 } 976 977 public void cleanup(Environment env) { 978 documentation = null; 979 if (isMethod() && value != null) { 980 int cost = 0; 981 if (isPrivate() || isInitializer()) { 982 value = Statement.empty; 983 } else if ((cost = 984 ((Statement)value) 985 .costInline(Statement.MAXINLINECOST, null, null)) 986 >= Statement.MAXINLINECOST) { 987 // will never be inlined 988 value = Statement.empty; 989 } else { 990 try { 991 if (!isInlineable(null, true)) { 992 value = Statement.empty; 993 } 994 } 995 catch (ClassNotFound ee) { } 996 } 997 if (value != Statement.empty && env.dump()) { 998 env.output("[after cleanup of " + getName() + ", " + 999 cost + " expression cost units remain]"); 1000 } 1001 } else if (isVariable()) { 1002 if (isPrivate() || !isFinal() || type.isType(TC_ARRAY)) { 1003 value = null; 1004 } 1005 } 1006 } 1007 }