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