001 /* Copyright 2000, 2001, Compaq Computer Corporation */ 002 003 package javafe.tc; 004 005 import java.util.Hashtable; 006 007 import javafe.ast.*; 008 import javafe.util.*; 009 010 /** 011 * 012 */ 013 014 public class TypeSig extends Type 015 { 016 /*************************************************** 017 * * 018 * Basic TypeSig instance variables: * 019 * * 020 **************************************************/ 021 022 /** 023 * The name of the package we belong to. Always non-null. 024 */ 025 //@ invariant \nonnullelements(packageName); 026 public /*public readonly non_null */ String[] packageName; 027 028 /** 029 * Our enclosing type or null iff we are a package-member type. 030 */ 031 public /*public readonly*/ TypeSig enclosingType; 032 033 /** 034 * Our simple name or null if we are an anonymous type. 035 */ 036 public /*public readonly*/ String simpleName; 037 038 /** 039 * Are we a direct member of a package or a type? <p> 040 * 041 * (Otherwise, we are a block-level type or an anonymous type.) <p> 042 */ 043 public /*public readonly*/ boolean member; 044 045 046 /** 047 * Our enclosing Env; may be null for member types because of 048 * laziness. Use TypeSig.getEnclosingEnv() to obtain an always 049 * non-null version of this. 050 */ 051 protected /*subclass-only*/ Env enclosingEnv; 052 053 /** 054 * Our TypeDecl; may be null only for package-member type 055 * because of laziness. Use getTypeDecl() to obtain an always 056 * non-null version of this. <p> 057 * 058 * This variable should be set only using setDecl. <p> 059 */ 060 //@ invariant state>=PARSED ==> myTypeDecl != null; 061 //@ invariant state<PARSED ==> myTypeDecl==null; 062 /*@spec_public*/ protected TypeDecl myTypeDecl; 063 064 /** 065 * The CompilationUnit we belong to; null iff myTypeDecl is null 066 * because of laziness. Use getCompilationUnit() to obtain an 067 * always non-null version of this. 068 */ 069 //@ invariant (myTypeDecl==null) == (CU==null); 070 protected CompilationUnit CU; 071 072 073 074 /* 075 * Enforce the various invariants about what kind of type we represent 076 * and the nullness of our basic instance variables. 077 * 078 * 079 * You can tell what kind of type we are as follows: 080 * 081 * package-member type if enclosingType==null 082 * type-member type if enclosingType != null && member 083 * block level type if simpleName != null && !member 084 * anonymous type if simpleName==null 085 */ 086 //@ invariant (enclosingType==null) ==> member; // package-member 087 //@ invariant (simpleName==null) ==> !member; // anonymous 088 //@ invariant !member ==> enclosingEnv != null; 089 //@ invariant (enclosingType != null) ==> myTypeDecl != null; 090 091 092 /*************************************************** 093 * * 094 * Associating TypeSigs and TypeDecls: * 095 * * 096 **************************************************/ 097 098 /** 099 * Decorates <code>TypeDecl</code> nodes to point to 100 * <code>TypeSig</code> objects. 101 */ 102 //@ invariant sigDecoration.decorationType == \type(TypeSig); 103 public static final ASTDecoration sigDecoration 104 = new ASTDecoration("sigDecoration"); 105 106 107 /** 108 * The myTypeDecl field maps TypeSigs to TypeDecls. The 109 * getSig(TypeDecl) function provides the reverse mapping. <p> 110 * 111 * Precondition: d has already been associated with a TypeSig. <p> 112 */ 113 //@ ensures \result != null; 114 public static TypeSig getSig(/*@ non_null @*/ TypeDecl d) { 115 TypeSig r = (TypeSig)sigDecoration.get(d); 116 if (r == null) Assert.notNull(r, //@ nowarn Pre; 117 "getSig called on a TypeDecl (" + d.id + ") not associated with a TypeSig"); 118 return r; 119 } 120 121 122 /** 123 * Protected routine used to associate a TypeSig with a TypeDecl. <p> 124 * 125 * It automatically creates TypeSigs for any (indirect) members 126 * of decl and associates them properly. <p> 127 * 128 * CU must be the CompilationUnit that decl belongs to.<p> 129 */ 130 //@ ensures this.myTypeDecl != null; 131 protected void setDecl(/*@ non_null @*/ TypeDecl decl, 132 /*@ non_null @*/ CompilationUnit CU) { 133 this.myTypeDecl = decl; 134 this.CU = CU; 135 state = PARSED; 136 sigDecoration.set(decl, this); 137 138 // Create TypeSigs for any TypeDecl members of us: 139 for (int i = 0; i < decl.elems.size(); i++) { 140 TypeDeclElem member = decl.elems.elementAt(i); 141 if (!(member instanceof TypeDecl)) 142 continue; 143 144 TypeDecl subDecl = (TypeDecl)member; 145 TypeSig subSig = Types.makeTypeSig( 146 packageName, subDecl.id.toString(), 147 this, subDecl, CU); 148 // (The TypeSig constructor will call subSig.setDecl(subDecl, CU)) 149 } 150 } 151 152 /*************************************************** 153 * * 154 * Creation: * 155 * * 156 **************************************************/ 157 158 /** 159 * Create a TypeSig that represents a non-member type. <p> 160 * 161 * We represent a block-level type if simpleName is non-null, 162 * and an anonymous type otherwise. <p> 163 */ 164 //@ requires !(enclosingEnv instanceof EnvForCU); 165 protected TypeSig(String simpleName, 166 /*@ non_null @*/ Env enclosingEnv, 167 /*@ non_null @*/ TypeDecl decl) { 168 super(); //@ nowarn Pre; // can't do set before super() 169 170 member = false; 171 172 this.simpleName = simpleName; 173 this.enclosingEnv = enclosingEnv; 174 175 this.enclosingType = enclosingEnv.getEnclosingClass(); 176 //@ assume this.enclosingType != this; 177 Assert.notNull(this.enclosingType); 178 179 // We inherit our packageName and CompilationUnit from our 180 // enclosing type: 181 this.packageName = this.enclosingType.packageName; 182 this.CU = this.enclosingType.getCompilationUnit(); 183 184 setDecl(decl, this.CU); //@ nowarn Invariant; // helper function 185 } 186 187 188 /** 189 * Create a TypeSig that represents a member type. <p> 190 * 191 * This constructor is designed to be private to TypeSig; 192 * It is protected to support the Types inst pattern, but 193 * clients should use 194 * OutsideEnv.lookup[Deffered] and getSig to get TypeSig's 195 * representing member types. <p> 196 * 197 * We represent a package-member type if enclosingType is 198 * non-null, and a type-member type otherwise. <p> 199 * 200 * Note: packageName should never be modified by the caller after 201 * this call.<p> 202 * 203 * CU must be the CompilationUnit that decl belongs to.<p> 204 */ 205 //@ requires \nonnullelements(packageName); 206 //@ requires (enclosingType != null) ==> (decl != null); 207 //@ requires (decl==null) == (CU==null); 208 protected TypeSig(/*@non_null*/ String[] packageName, 209 /*@ non_null @*/ String simpleName, 210 TypeSig enclosingType, 211 TypeDecl decl, CompilationUnit CU) { 212 super(); //@ nowarn Pre; // can't do set before super 213 214 member = true; 215 216 this.packageName = packageName; 217 this.simpleName = simpleName; 218 this.enclosingType = enclosingType; 219 220 this.enclosingEnv = null; // be lazy... 221 if (decl != null) 222 setDecl(decl, CU); //@ nowarn Invariant; // helper function 223 } 224 225 226 /** 227 * Create a TypeSig that represents an internal-use-only 228 * package-member type. Such types do not have external names 229 * and should be avoided if at all possible since they are 230 * kludges. <p> 231 * 232 * This constructor should only be used by 233 * PrepTypeDeclaration.getRootInterface().<p> 234 * 235 * Note: packageName should never be modified by the caller after 236 * this call.<p> 237 * 238 * CU must be the CompilationUnit that decl belongs to.<p> 239 */ 240 //@ requires \nonnullelements(packageName); 241 protected TypeSig(/*@non_null*/ String[] packageName, 242 /*@ non_null @*/ String simpleName, 243 /*@ non_null @*/ TypeDecl decl, 244 /*@ non_null @*/ CompilationUnit CU) { 245 this(packageName, simpleName, null, decl, CU); 246 } 247 248 249 250 // //@ requires \nonnullelements(packageName); 251 // //@ requires (enclosingType != null) ==> (decl != null); 252 // //@ requires (decl==null) == (CU==null); 253 // //@ ensures \result != null; 254 // UNUSED 255 // private static TypeSig make(String[] packageName, 256 // /*@ non_null @*/ String simpleName, 257 // TypeSig enclosingType, 258 // TypeDecl decl, 259 // CompilationUnit CU) { 260 // TypeSig t = Types.makeTypeSig(packageName, 261 // simpleName, 262 // enclosingType, 263 // decl, 264 // CU); 265 // return t; 266 // } 267 268 /*************************************************** 269 * * 270 * Interning by External Name for package-members: * 271 * * 272 **************************************************/ 273 274 /* 275 * We maintain a mapping from fully-qualified names to 276 * package-member types so that OutsideEnv never creates 2 277 * TypeSigs with the same external name. 278 * 279 * This map is complete in the sense that all created 280 * package-member types are in its range. 281 * 282 * These functions are intended for use *only* by OutsideEnv! 283 */ 284 285 286 /** 287 * The map from fully-qualified external names of package-member 288 * types to the TypeSigs representing them. <p> 289 * 290 * Invariant: map's range includes all existing package-member 291 * TypeSigs; map sends getKey(P,T) to the unique package-member 292 * TypeSig with external name P.T.<p> 293 * 294 * The domain type of map is String and its range type is (non-null) 295 * TypeSigs.<p> 296 */ 297 // Old specs from original full JML spec files. Must be 298 // rewritten for current java.util.Hashtable specs. 299 //- invariant map.keyType == \type(String); 300 //- invariant map.elementType == \type(TypeSig); 301 //@ spec_public 302 private static final Hashtable map = new Hashtable(101); 303 304 public static final void clear() { 305 map.clear(); 306 } 307 308 /** 309 * Compute the key for map for fully-qualified type P.T. 310 */ 311 //@ requires \nonnullelements(P); 312 //@ ensures \result != null; 313 private static String getKey(/*@non_null*/ String[] P, /*@ non_null @*/ String T) { 314 String key = ""; 315 316 for (int i=0; i<P.length; i++) 317 key += "."+P[i]; 318 key += "."+T; 319 320 return key; 321 } 322 323 324 /** 325 * If a TypeSig representing the package-member type named P.T 326 * has been created, return it; otherwise, return null. <p> 327 * 328 * This function should only be called by OutsideEnv. <p> 329 */ 330 //@ requires \nonnullelements(P); 331 static public TypeSig lookup(/*@non_null*/ String[] P, /*@ non_null @*/ String T) { 332 return (TypeSig)map.get(getKey(P,T)); 333 } 334 335 // FIXME - the type lookup ends up parsing a qualified name into 336 // pieces and then reassembling them through getKey into a 337 // qualified name. This could be improved by providing a 338 // direct lookup from a fully qualified name 339 340 /** 341 * If a TypeSig representing the package-member type named P.T 342 * has been created, return it; otherwise, create such a TypeSig 343 * then return it. <p> 344 * 345 * This function should only be called by OutsideEnv. <p> 346 */ 347 //@ requires \nonnullelements(P); 348 //@ ensures \result != null; 349 static /*package*/ TypeSig get(/*@non_null*/ String[] P, /*@ non_null @*/ String T) { 350 String key = getKey(P,T); 351 TypeSig result = (TypeSig)map.get(key); 352 if (result != null) 353 return result; 354 355 result = Types.makeTypeSig(P, T, (TypeSig)null, (TypeDecl)null, 356 (CompilationUnit)null); 357 map.put(key, result); 358 return result; 359 } 360 361 /*************************************************** 362 * * 363 * Lazy loading of TypeDecls: * 364 * * 365 **************************************************/ 366 367 /** 368 * Get the non-null TypeDecl we are associated with. <p> 369 * 370 * (Under the covers, for package-member types, this method may 371 * cause <code>OutsideEnv</code> to parse the 372 * <code>TypeDecl</code> in question, but this should be 373 * transparent to most clients.) <p> 374 */ 375 //@ ensures \result != null; 376 //@ ensures state>=PARSED; 377 public TypeDecl getTypeDecl() { 378 if (myTypeDecl==null) 379 preload(); 380 381 return myTypeDecl; 382 } 383 384 /** 385 * Get the non-null CompilationUnit we are associated with. <p> 386 * 387 * (Under the covers, for package-member types, this method may 388 * cause <code>OutsideEnv</code> to parse the type in question, 389 * but this should be transparent to most clients.) <p> 390 */ 391 //@ ensures \result != null; 392 public CompilationUnit getCompilationUnit() { 393 if (myTypeDecl==null) 394 preload(); 395 396 return CU; 397 } 398 399 400 /** 401 * Ensure that we have loaded our TypeDecl, invoking OutsideEnv 402 * if needed to load a TypeDecl into us via load below. We abort 403 * via an assertion failure if OutsideEnv fails to load us. 404 */ 405 //@ ensures myTypeDecl != null; 406 private void preload() { 407 if (myTypeDecl != null) 408 return; 409 410 /* 411 * This call should always call our load method (below) with a 412 * TypeDecl. 413 */ 414 OutsideEnv.load(this); 415 Assert.notNull(myTypeDecl); 416 } 417 418 419 /* 420 * The below functions are provided for use by OutsideEnv in 421 * loading us. 422 */ 423 424 425 /** 426 * Is our TypeDecl already loaded? 427 */ 428 //@ ensures !member ==> \result; 429 //@ ensures \result == (myTypeDecl != null); 430 public boolean isPreloaded() { 431 return myTypeDecl != null; 432 } 433 434 435 /** 436 * Load the non-null TypeDecl decl as our TypeDecl. 437 * This method is used by OutsideEnv to install a TypeDecl in us once 438 * it has been loaded.<p> 439 * 440 * If we have already been loaded with a different TypeDecl, then 441 * an appropriate fatal error results. <p> 442 * 443 * Note: This method should *only* be called by OutsideEnv.load.<p> 444 * 445 * CU must be the CompilationUnit that decl belongs to.<p> 446 */ 447 //@ ensures myTypeDecl != null; 448 /*package*/ void load(/*@ non_null @*/ TypeDecl decl, 449 /*@ non_null @*/ CompilationUnit CU) { 450 // If no (potential) duplication, just install decl and return: 451 if (myTypeDecl==null) { 452 setDecl(decl, CU); 453 return; 454 } 455 456 if (myTypeDecl==decl && this.CU==CU) 457 return; 458 459 ErrorSet.fatal(decl.loc, "type " + this.getExternalName() 460 + " already defined at " 461 + Location.toString(myTypeDecl.loc)); 462 } 463 464 /*************************************************** 465 * * 466 * Name accessor functions: * 467 * * 468 **************************************************/ 469 470 /** 471 * Return our package name as a human-readable string 472 * suitable for display. If we are in the unnamed package, 473 * the constant THE_UNNAMED_PACKAGE is returned. 474 */ 475 //@ ensures \result != null; 476 public String getPackageName() { 477 if (packageName.length == 0) 478 return THE_UNNAMED_PACKAGE; 479 480 StringBuffer P = new StringBuffer(5*packageName.length); 481 for (int i = 0; i < packageName.length; i++) { 482 if (i != 0) 483 P.append('.'); 484 P.append(packageName[i]); 485 } 486 487 return P.toString(); 488 } 489 490 public final static String THE_UNNAMED_PACKAGE = "<the unnamed package>"; 491 492 493 /** 494 * Return our exact type name, omitting the package name, as a 495 * human-readable string suitable for display. 496 */ 497 //@ ensures \result != null; 498 public String getTypeName() { 499 if (enclosingType==null) { 500 // package-member type: 501 return simpleName; 502 } 503 504 String parent = enclosingType.getTypeName(); 505 if (member) 506 return parent+"$"+simpleName; 507 if (simpleName != null) 508 return parent+"$" 509 +Location.toLineNumber(getTypeDecl().getStartLoc())+"$" 510 +simpleName; 511 else 512 return parent+"$" 513 +Location.toLineNumber(getTypeDecl().getStartLoc())+"$" 514 +"<anonymous>"; 515 } 516 517 518 /** 519 * Return our exact fully-qualified external name as a 520 * human-readable string suitable for display. The package name is 521 * omitted if it is the unnamed package. 522 */ 523 //@ ensures \result != null; 524 public String getExternalName() { 525 String P = getPackageName(); 526 if (P==THE_UNNAMED_PACKAGE) 527 return getTypeName(); 528 else 529 return P+"."+getTypeName(); 530 } 531 532 533 /** 534 * Returns a String that represents the value of this Object. 535 */ 536 public String toString() { 537 return getExternalName(); 538 } 539 540 /*************************************************** 541 * * 542 * ASTNode functions: * 543 * * 544 **************************************************/ 545 546 public int childCount() { 547 return 0; 548 } 549 550 public Object childAt(int i) { 551 throw new IndexOutOfBoundsException(); 552 } //@ nowarn Exception; 553 554 public int getTag() { 555 return TagConstants.TYPESIG; 556 } 557 558 public void accept(Visitor v) { 559 // v does not have a special visitor method for TypeSig 560 // so just use the one for Type 561 v.visitType( this ); 562 } 563 564 565 public Object accept(VisitorArgResult v, Object o) { 566 return v.visitType( this,o ); 567 } 568 569 /* 570 // We don't promise any meaningful locations... 571 //@ invariant !syntax; 572 { 573 // Deal with can't handle non-injective fields & invariants problem: 574 //@ assume (\forall MethodDecl m; m.returnType != this); 575 //@ assume (\forall GenericVarDecl g; g.type != this); 576 //@ set syntax = false; 577 } 578 */ 579 580 public int getStartLoc() { 581 return getTypeDecl().getStartLoc(); 582 } 583 584 public int getEndLoc() { 585 return getTypeDecl().getEndLoc(); 586 } 587 588 /*************************************************** 589 * * 590 * Looking up type members: * 591 * * 592 **************************************************/ 593 594 /** 595 * Do we have a type member named id (including inherited type 596 * members)? <p> 597 * 598 * If we have exactly one such type member, then return it. If 599 * we have no such type member, return null. If we have more 600 * than one such type member, then if loc != Location.NULL then a 601 * fatal error is reported at that location via ErrorSet else one 602 * of the relevant type members is returned.<p> 603 * 604 * If caller is null, this routine does not check that the 605 * resulting type (if any) is accessible. If caller is not 606 * null, then the resulting type is checked to be accessible 607 * from the caller. <p> 608 */ 609 public TypeSig lookupType(TypeSig caller, 610 /*@ non_null @*/ Identifier id, int loc) { 611 // Look locally first: 612 TypeSig result = lookupLocalType(caller,id); 613 if (result != null) 614 return result; 615 616 /* 617 * Then try our superclass (if any): 618 */ 619 resolveSupertypeLinks(); 620 TypeSig s = superClass(); 621 if (s != null) { 622 result = s.lookupType(caller,id,loc); 623 } 624 625 /* 626 * and our superinterfaces, checking for duplicates: 627 */ 628 TypeDecl decl = getTypeDecl(); 629 for (int i=0; i<decl.superInterfaces.size(); i++ ) { 630 TypeName superInterfaceName = decl.superInterfaces.elementAt(i); 631 TypeSig newResult = getSig(superInterfaceName).lookupType(caller,id, loc); 632 if (newResult==null) 633 continue; 634 635 if (result==null || result==newResult) 636 result = newResult; 637 else { 638 if (loc != Location.NULL) 639 ErrorSet.fatal(loc, "Reference to type member `" 640 + id.toString() 641 + "' of type " + toString() 642 + " is ambiguous; it may refer to type " 643 + result.toString() 644 + " or to type " 645 + newResult.toString() 646 + "."); 647 else 648 return result; 649 } 650 } 651 652 return result; 653 } 654 655 656 /** 657 * Do we have a type member named id (*not* including inherited 658 * type members)? If so, return it; otherwise, return null. <p> 659 * 660 * If caller is null, then this routine does not check that the 661 * resulting type (if any) is actually accessable. If caller is 662 * non_null, then the resulting type is checked that it is 663 * accessible from the caller.<p> 664 */ 665 666 public TypeSig lookupLocalType(TypeSig caller, Identifier id) { 667 TypeDeclElemVec elems = getTypeDecl().elems; 668 for (int i=0; i<elems.size(); i++) { 669 TypeDeclElem e = elems.elementAt(i); 670 if (e instanceof TypeDecl && ((TypeDecl)e).id==id) { 671 TypeDecl td = (TypeDecl)e; 672 TypeSig t = getSig(td); 673 if (caller == null) return t; 674 TypeSig c = caller; 675 do { 676 if (TypeCheck.inst.canAccess(c, this, td.modifiers, 677 td.pmodifiers) ) { 678 return t; 679 } 680 c = c.enclosingType; 681 } while (c != null); 682 } 683 } 684 return null; 685 } 686 687 /*************************************************** 688 * * 689 * Environments: * 690 * * 691 **************************************************/ 692 693 /** 694 * Return our enclosing environment. 695 */ 696 //@ ensures \result != null; 697 public Env getEnclosingEnv() { 698 if (enclosingEnv != null) 699 return enclosingEnv; 700 701 if (enclosingType==null) 702 enclosingEnv = new EnvForCU(getCompilationUnit()); 703 else 704 enclosingEnv = enclosingType.getEnv(isStatic()); 705 706 return enclosingEnv; 707 } 708 709 710 /** 711 * Return an environment for use in checking code inside us. <p> 712 * 713 * Our instance members are considered accessible iff 714 * staticContext is false. 715 */ 716 //@ ensures \result != null; 717 public EnvForTypeSig getEnv(boolean staticContext) { 718 return new EnvForTypeSig(getEnclosingEnv(), this, staticContext); 719 } 720 721 /*************************************************** 722 * * 723 * Misc: * 724 * * 725 **************************************************/ 726 727 /** 728 * Are we (possibly implicitly) static? <p> 729 * 730 * This differs from using Modifiers.isStatic because it does not 731 * rely on Prep'ing having added the static modifier where 732 * implicit so we can be used by Prep itself. 733 */ 734 public boolean isStatic() { 735 if (Modifiers.isStatic(getTypeDecl().modifiers)) 736 return true; 737 738 // interfaces are implicitly static: 739 if (getTypeDecl() instanceof InterfaceDecl) 740 return true; 741 742 // interface members are implicitly static: 743 if (enclosingType != null && 744 enclosingType.getTypeDecl() instanceof InterfaceDecl) 745 return true; 746 747 return false; 748 } 749 750 751 /** 752 * Are we a top-level type? <p> 753 * 754 * True iff either we are a package-level type or a static member 755 * of a top-level type. <p> 756 * 757 * Note: This may be called during any state; it may bump 758 * TypeSigs to the Parsed state. <p> 759 */ 760 //@ ensures enclosingType==null ==> \result; 761 public boolean isTopLevelType() { 762 if (enclosingType==null) 763 return true; 764 765 if (!isStatic()) 766 return false; 767 768 return enclosingType.isTopLevelType(); 769 } 770 771 //************************************************************ 772 //************************************************************ 773 //************************************************************ 774 //************************************************************ 775 //************************************************************ 776 777 /*************************************************** 778 * * 779 * TypeSig states and transition functions: * 780 * * 781 **************************************************/ 782 783 /* 784 * The states that a TypeSig can be in. The variable state (below) 785 * holds our current state, which must be one of the following 786 * values: 787 */ 788 public final static int CREATED = 1; 789 public final static int PARSED = 2; 790 public final static int RESOLVINGLINKS = 3; // used by SLResolution 791 public final static int LINKSRESOLVED = 4; 792 public final static int PREPPED = 5; 793 public final static int CHECKED = 6; 794 795 /** 796 * The current state of <code>this</code>. Must be one of 797 * <code>CREATED</code>, <code>PARSED</code>, 798 * <code>LINKSRESOLVED</code>, <code>PREPPED</code>, or 799 * <code>CHECKED</code>. In most circumstances, this field 800 * should not be written to; rather, methods of 801 * <code>TypeSig</code> should be called to effect changes to it. 802 * This field must never be decreased after creation time. 803 */ 804 public int state = CREATED; 805 806 807 /* 808 * Note: The transition to PARSED from CREATED is performed 809 * automatically by setDecl. 810 */ 811 812 /** 813 * Transition <code>this</code> to the supertype links resolved 814 * state. <p> 815 * 816 * See the TypeSig type comments for details of what this involves.<p> 817 * 818 * A fatal error may be reported if we cannot resolve a supertype 819 * name, or detect a cycle in the type hierarchy.<p> 820 */ 821 //@ modifies state; 822 //@ ensures state>=TypeSig.LINKSRESOLVED; 823 public void resolveSupertypeLinks() { 824 if (state<LINKSRESOLVED) 825 SLResolution.transition(this); 826 } 827 828 /** 829 * Transition <code>this</code> to the "prepped" state. <p> 830 * 831 * A prepped declaration has all of the <code>TypeName</code> 832 * nodes defining the types of its members resolved. For a field 833 * declaration, this means resolving the <code>type</code> field; 834 * For a routine declaration, this means resolving 835 * <code>TypeName</code>s that occur in the <code>args</code>, 836 * <code>raises</code>, and <code>returnType</code> fields.<p> 837 * 838 * See the TypeSig type comments for more details of what this 839 * involves.<p> 840 */ 841 //@ modifies state; 842 //@ ensures state >= PREPPED; 843 public void prep() { 844 if (state >= TypeSig.PREPPED) 845 return; 846 847 if (Info.on) Info.out("[prepping-slinks " + this + "]"); 848 resolveSupertypeLinks(); 849 if (Info.on) Info.out("[prepping " + this + "]"); 850 PrepTypeDeclaration.inst.prepTypeSignature(this); 851 if (Info.on) Info.out("[prepping-complete " + this + "]"); 852 853 state = TypeSig.PREPPED; 854 } 855 856 /** 857 * Transition <code>this</code> to the "checked" state. <p> 858 * 859 * See the TypeSig type comments for details of what this involves.<p> 860 * 861 * A fatal error may be reported if we cannot resolve a supertype 862 * name, or detect a cycle in the type hierarchy.<p> 863 */ 864 //@ modifies state; 865 //@ ensures state >= CHECKED; 866 public void typecheck() { 867 if (this.state >= TypeSig.CHECKED) 868 return; 869 if (this.state < TypeSig.PREPPED) 870 prep(); 871 872 typecheckSuperTypes(); 873 long start = 0; 874 if (Info.on) start = javafe.Tool.currentTime(); 875 if (Info.on) Info.out("[typechecking " + this + "]"); 876 TypeCheck.inst.makeFlowInsensitiveChecks().checkTypeDeclaration(this); 877 if (Info.on) Info.out("[typechecking-end " + this + " " + javafe.Tool.timeUsed(start) + "]"); 878 // @review kiniry 31 Aug - Why is this commented out? 879 // FlowSensitiveChecks.checkTypeDeclaration(this); 880 this.state = TypeSig.CHECKED; 881 } 882 883 /** 884 * Typecheck the superclass of the current classtype being typecheck and 885 * typecheck all interfaces that the current classtype implements. 886 */ 887 public void typecheckSuperTypes() { 888 TypeSig t = superClass(); 889 // If we are typechecking an inner class whose parent is the enclosing 890 // environment, then do not try to typecheck the parent as that is what we 891 // are doing at this moment! 892 if ((t != null) && getEnclosingEnv().getEnclosingClass() != enclosingType) 893 t.typecheck(); 894 TypeDecl decl = getTypeDecl(); 895 for (int i=0; i<decl.superInterfaces.size(); i++ ) { 896 TypeName superInterfaceName = decl.superInterfaces.elementAt(i); 897 TypeSig ts = getSig(superInterfaceName); 898 ts.typecheck(); 899 } 900 } 901 902 /*************************************************** 903 * * 904 * Looking up fields, methods, and constructors: * 905 * * 906 **************************************************/ 907 908 //// Fields and methods associated with preparation of a TypeSig 909 910 /** After preparation, this field contains all field members of 911 the <code>TypeDecl</code> associated with <code>this</code>, 912 including inherited ones. */ 913 914 // "invariant" fields.<each element>.hasParent 915 //@ invariant state>=PREPPED ==> fields != null; 916 //@ spec_public 917 protected FieldDeclVec fields; 918 919 // Note: 'fields' contains all visible fields 920 // 'hiddenfields' contains all the others (e.g. hidden or not accessible) 921 //@ invariant state>=PREPPED ==> hiddenfields != null; 922 protected FieldDeclVec hiddenfields; 923 924 /** After preparation, this field contains all method members of 925 the <code>TypeDecl</code> associated with <code>this</code>, 926 including inherited ones. */ 927 928 // "invariant" methods.<each element>.hasParent 929 //@ invariant state>=PREPPED ==> methods != null; 930 //@ spec_public 931 protected MethodDeclVec methods; 932 933 /** Returns all fields of the type declaration associated with 934 <code>this</code>, including inherited ones. (If 935 <code>this</code> has not been prepped yet, this method will prep 936 it (possibly triggering parsing and/or processing of other 937 types).) If allFields is true, then all declared fields, including 938 hidden and inaccessible fields, are returned; if allFields is false, 939 then only visible fields are returned. */ 940 941 // "ensures" <result elements>.hasParent 942 //@ ensures \result != null; 943 public FieldDeclVec getFields(boolean allFields) { 944 prep(); 945 Assert.notNull( fields ); 946 if (!allFields) return fields; 947 FieldDeclVec v = fields.copy(); 948 v.append(hiddenfields); 949 return v; 950 } 951 952 public FieldDeclVec getFieldsRaw() { return fields; } 953 954 public FieldDeclVec getHiddenFields() { return hiddenfields; } 955 956 /** Similar to <code>getFields</code>, except for methods. */ 957 958 // "ensures" <result elements>.hasParent 959 //@ ensures \result != null; 960 public MethodDeclVec getMethods() { 961 prep(); 962 Assert.notNull( methods ); 963 return methods; 964 } 965 966 967 /** TBW */ 968 969 //@ requires \nonnullelements(args) && caller != null; 970 //@ ensures \result != null; 971 public ConstructorDecl lookupConstructor(Type[] args, TypeSig caller) 972 throws LookupException 973 { 974 prep(); 975 976 // Holds the most specific, applicable, accessible constructor found so far 977 ConstructorDecl mostSpecific = null; 978 boolean somethingFound = false; 979 TypeDecl decl = getTypeDecl(); 980 981 search: 982 for(int i = 0; i < decl.elems.size(); i++) { 983 TypeDeclElem elem = decl.elems.elementAt(i); 984 if (elem instanceof ConstructorDecl) { 985 ConstructorDecl md = (ConstructorDecl)elem; 986 if (md.args.size() == args.length 987 && TypeCheck.inst.canAccess(caller, this, md.modifiers, 988 md.pmodifiers) ) { 989 // accessible, same name and number of args 990 991 somethingFound = true; 992 for(int j = 0; j < args.length; j++) 993 if (! Types.isInvocationConvertable(args[j], 994 md.args.elementAt(j).type)) 995 continue search; 996 // accessible and applicable 997 998 if (mostSpecific == null || 999 Types.routineMoreSpecific(md, mostSpecific)) 1000 mostSpecific = md; 1001 else if (! Types.routineMoreSpecific(mostSpecific, md)) 1002 throw new LookupException( LookupException.AMBIGUOUS ); 1003 } 1004 } 1005 } 1006 1007 if (mostSpecific != null) 1008 return mostSpecific; 1009 else if (somethingFound) 1010 throw new LookupException( LookupException.BADTYPECOMBO ); 1011 else 1012 throw new LookupException( LookupException.NOTFOUND ); 1013 } 1014 1015 /** TBW */ 1016 1017 //@ ensures \result != null; 1018 //@ ensures \result.id == id; 1019 public FieldDecl lookupField(Identifier id, /*@ non_null */ TypeSig caller) 1020 throws LookupException 1021 { 1022 FieldDeclVec fields = getFields(false); 1023 FieldDecl r = null; 1024 for(int i=0; i<fields.size(); i++ ) { 1025 FieldDecl fd = fields.elementAt(i); 1026 if (fd.id == id) 1027 if (r == null) r = fd; 1028 else throw new LookupException( LookupException.AMBIGUOUS ); 1029 } 1030 1031 if (r == null) 1032 throw new LookupException( LookupException.NOTFOUND ); 1033 else if (! TypeCheck.inst.canAccess(caller, this, r.modifiers, 1034 r.pmodifiers)) 1035 throw new LookupException( LookupException.NOTACCESSIBLE ); 1036 else return r; 1037 } 1038 1039 1040 /** TBW */ 1041 1042 public boolean hasField(Identifier id) { 1043 FieldDeclVec fields = getFields(false); 1044 for(int i=0; i<fields.size(); i++) 1045 if (fields.elementAt(i).id == id) return true; 1046 return false; 1047 } 1048 1049 public MethodDecl hasMethod(Identifier id, Type[] args) { 1050 try { 1051 return lookupMethod(id,args,this); 1052 } catch (LookupException e) { 1053 return null; 1054 } 1055 } 1056 1057 /** TBW */ 1058 1059 //@ requires \nonnullelements(args) && caller != null; 1060 //@ ensures \result != null; 1061 //@ ensures \result.id == id; 1062 public MethodDecl lookupMethod(Identifier id, Type[] args, TypeSig caller) 1063 throws LookupException 1064 { 1065 MethodDeclVec methods = getMethods(); 1066 1067 // Holds the most specific, applicable, accessible method found so far 1068 MethodDecl mostSpecific = null; 1069 boolean somethingFound = false; 1070 1071 search: 1072 for(int i = 0; i < methods.size(); i++) { 1073 MethodDecl md = methods.elementAt(i); 1074 if (md.id == id 1075 && md.args.size() == args.length 1076 && TypeCheck.inst.canAccess(caller, this, md.modifiers, 1077 md.pmodifiers)) { 1078 // accessible, same name and number of args 1079 1080 somethingFound = true; 1081 for(int j=0; j<args.length; j++) { 1082 // FIXME - the argument (particularly the second) might be just a 1083 // Typename - ought to resolve it once and for all, instead of doing so 1084 // each time the following method is called. 1085 if(! Types.isInvocationConvertable(args[j], 1086 md.args.elementAt(j).type)) { 1087 continue search; 1088 } 1089 } 1090 // accessible and applicable 1091 1092 if (mostSpecific == null 1093 || Types.routineMoreSpecific(md, mostSpecific)) 1094 mostSpecific = md; 1095 else if (! Types.routineMoreSpecific(mostSpecific, md)) 1096 throw new LookupException( LookupException.AMBIGUOUS ); 1097 } 1098 } 1099 1100 if (mostSpecific != null) 1101 return mostSpecific; 1102 else if (somethingFound) 1103 throw new LookupException( LookupException.BADTYPECOMBO ); 1104 else 1105 throw new LookupException( LookupException.NOTFOUND ); 1106 } 1107 1108 //************************************************************ 1109 //************************************************************ 1110 //************************************************************ 1111 //************************************************************ 1112 //************************************************************ 1113 1114 /** 1115 1116 A <code>TypeSig</code> is a proxy and adaptor for <a 1117 href="javafe.ast.TypeDecl.html"><code>TypeDecl</code></a>.<p> 1118 1119 They are proxies because, during name resolution, <a 1120 href="javafe.ast.TypeName.html"><code>TypeName</code></a> objects are 1121 resolved to point to <code>TypeSig</code> objects rather than directly 1122 to <code>TypeDecl</code> objects. This gives us the flexibility of 1123 deferring parsing of a type declaration until we know we need detailed 1124 information about it.<p> 1125 1126 They are adaptors because they provide extra functionality not provided 1127 by <code>TypeDecl</code> objects. In particular, they provide lookup 1128 methods that allow clients to find particular members of a type 1129 declaration (including inherited members), and resolve methods that 1130 perform name resolution inside the implementation of a type 1131 declaration.<p> 1132 1133 <i>What about the fact that we are a subtype of <code>Type</code>?</i> 1134 1135 1136 <h3> Interning </h3> 1137 1138 <code>TypeSig</code> objects are meant to be "interned"; that is, for 1139 each <i>canonical</i> <code>TypeDecl</code>, we want there to be exactly 1140 one associated <code>TypeSig</code> object. The first 1141 <code>TypeDecl</code> loaded by the system for a given typename is 1142 considered to be the canonical <code>TypeDecl</code> for that typename; 1143 all other <code>TypeDecl</code>s for that typename are considered 1144 non-canonical.<p> 1145 1146 To achieve this interning, clients of the <code>javafe.tc</code> package 1147 should not directly create <code>TypeSig</code> objects; rather, they 1148 should rely on <code>javafe.tc</code> to create <code>TypeSig</code> 1149 objects for them. Similarly, clients of the <code>javafe.tc</code> 1150 package should rely on <code>javafe.tc</code> to do the parsing 1151 necessary to create instances of <code>TypeDecl</code>. Not only will 1152 the <code>javafe.tc</code> package intern <code>TypeSig</code> objects, 1153 it will also ensure that, for <code>TypeSig s</code> and <code>TypeDecl 1154 d,</code><ul> 1155 1156 <li> <code>s.getTypeDecl()</code> is always a canonical <code>TypeDecl</code> 1157 1158 <li> <code>s.getTypeDecl().sig == s</code> 1159 1160 <li> if <code>d</code> is canonical then <code>d.sig.getTypeDecl()==d</code> 1161 1162 <li> if <code>d</code> is not canonical then <code>d.sig</code> is the 1163 <code>TypeSig</code> associated with <code>d</code>'s typename.</ul> 1164 1165 <i>What is the interface for clients within the <code>javafe.tc</code> 1166 package?</i><p> 1167 1168 1169 1170 <h3> Staging the processing of type declarations </h3><p> 1171 1172 Resolving the names in a type declaration and checking its static 1173 semantics usually involves looking at other declarations to which it 1174 refers. Finding, reading, and processing referred-to types makes 1175 resolution and checking fairly complicated. As a result, we have 1176 decomposed it into smaller steps. Type declarations move through a 1177 number of states as the resolution and checking process proceeds. In 1178 addition to making the overall processing of type declarations 1179 conceptually more manageable, this decomposition has two other 1180 benefits:<ul> 1181 1182 1183 <li> <i>Handling cycles</i>. As mentioned above, processing one type may 1184 involve processing types to which it refers. However, two types may 1185 refer to each other, making it impossible to process any one of them 1186 "first." Decomposing the processing into stages helps us handle such 1187 cycles. 1188 1189 <li> <i>Improving performance</i>. Processing one type declaration does 1190 not require fully processing the declarations to which it refers. How 1191 much processing is required of a referred-to type depends on the manner 1192 in which it is referred (e.g., the superclass of a class requires more 1193 processing than a type referred to by another type referred to by the 1194 class). Decomposing processing into stages allows us to be lazy in 1195 processing referred-to types; that is, it allows us to process them only 1196 to the extent that is necessary and no further.</ul> 1197 1198 1199 The rest of this section details the states through which a 1200 <code>TypeSig</code> object moves during its lifetime. Most clients of 1201 the <code>javafe.tc</code> package do not need to know about these 1202 details. However, clients interested in extending the processing done 1203 by the <code>javafe.tc</code> package may need to add other states as 1204 well. Also, this documentation gives an overview of the 1205 <code>javafe.tc</code> package for those interested in understanding its 1206 implementation.<p> 1207 1208 <code>TypeSig</code>s start in the <i><code>TypeSig</code> created</i> 1209 state then move sequentially through the following four states: 1210 <i>parsed</i>, <i>supertype links resolved</i>, <i>prepped</i>, and 1211 <i>checked</i>. Each following state represents additional processing 1212 completed on top of the processing required for the previous state. A 1213 description of these states in reverse order follows. Included are the 1214 properties that hold in each state; these properties are "additive": 1215 properties of states later in the list are also properties of states 1216 earlier in the list.<ul> 1217 1218 <li> <i>Checked.</i> Type declarations in this state have been fully 1219 disambiguated, resolved and checked (see <a 1220 href="javafe.tc.TypeCheck.html"> <code>TypeCheck</code> </a> for the 1221 definitions of disambiguation, resolution, and checking). 1222 Transitioning to this state can trigger parsing and/or preparation of 1223 types referenced (<i>where?</i>) either explicitly or implicitly. 1224 Implicitly referenced types are types used but not explicitly 1225 mentioned in a <code>TypeName</code> node (<i>huh?</i>); for example, 1226 the type of the result of <code>foo</code> in the expression 1227 "<code>bar(x.foo())</code>" is implicitly referenced by this 1228 expression.<p> 1229 1230 1231 <li> <i>Prepped.</i> When checking a type declaration, we need to look 1232 up members of other type declarations it uses. Before looking up 1233 members of these referred-to declarations, it is useful to do some work 1234 on them first, such as building internal tables. <code>TypeSig</code>s 1235 in the prepped state have had such work done on their declarations, 1236 preparing them for having their members queried. As a convenience, the 1237 methods of <code>TypeSig</code> that lookup the members of a type 1238 declaration, such as <A href="#lookupField(javafe.ast.Identifier, 1239 javafe.tc.TypeSig)"> <code>lookupField</code></A> and <A 1240 href="#lookupMethod(javafe.ast.Identifier, javafe.ast.Type[], 1241 javafe.tc.TypeSig)"> <code>lookupMethod</code></a>, automatically 1242 transition the declaration (<i><code>TypeSig</code></i>?) to the prepped 1243 state if it isn't there already.<p> 1244 1245 When preparing the declaration associated with a <code>TypeSig</code>, 1246 it is also useful to report certain errors in it, such as two fields 1247 with the same name. This way, when checking a class, the user will also 1248 see a report of errors in the interfaces (but not the implementations) 1249 of the classes used by the class being checked.<p> 1250 1251 The prepped state is <i>supertype transitive</i>: a state <i>X</i> is 1252 supertype transitive if a <code>TypeSig</code> can only be in state 1253 <i>X</i> if all its supertypes are at least in state <i>X</i>. Note 1254 that there is no requirement that <i>X</i>'s type members be in any 1255 particular state.<p> 1256 1257 1258 <li> <i>Supertype links resolved.</i> When preparing or checking a type 1259 declaration, we may need to ask if one type referred to by the 1260 declaration is a supertype of another. To perform this query, we need 1261 to resolve supertype links. After parsing, the supertypes of a type 1262 declaration are represented as <code>TypeName</code>s, which are 1263 symbolic references. Resolution of a <code>TypeName</code> object 1264 involves pointing its <code>sig</code> field to the <code>TypeSig</code> 1265 object for the type declaration to which the <code>TypeName</code> 1266 symbolically refers. Resolving the supertype links of type declarations 1267 separately from preparing them allows us to perform supertype checks 1268 during the preparation process.<p> 1269 1270 As a convenience, the <code>isSubtypeOf</code> method of 1271 <code>TypeSig</code>, which performs the supertype test, automatically 1272 resolves supertype links if they have not been resolved already.<p> 1273 1274 Like the prepped state, the "supertype links resolved" state is 1275 supertype transitive.<p> 1276 1277 1278 <li> <i>Parsed</i>. Although many <code>TypeSig</code>s come into 1279 existence when their type declarations are parsed, some of them can be 1280 created earlier. Thus, we can distinguish <code>TypeSig</code>s that 1281 have been parsed from those that have not. However, it is difficult for 1282 a client outside <code>javafe.tc</code> to know whether or not a 1283 <code>TypeSig</code> has been parsed. This is because, if a client 1284 calls <a href="#getTypeDecl()"> <code>getTypeDecl</code></a> on a 1285 <code>TypeSig</code> that has not been parsed, it will be parsed 1286 automatically.<p> 1287 1288 1289 <li> <i><code>TypeSig</code> created</i>. This is the initial state 1290 of <code>TypeSig</code> objects that come into existence before their 1291 corresponding declarations have been parsed. Again, it is it is 1292 difficult for a client outside <code>javafe.tc</code> to to distinguish 1293 between this state and the parsed state.</ul> 1294 1295 1296 1297 1298 <h3> More internal details </h3> 1299 1300 <p> This section contains a few more details about the implementation 1301 for those who wish to understand it. 1302 1303 <p> Inside the <code>javafe.tc</code> package, creation of 1304 <code>TypeSig</code> and <code>TypeDecl</code> objects is managed by 1305 the <a href="javafe.tc.OutsideEnv.html"> <code>OutsideEnv</code> 1306 </a> class. Methods of this class take the fully-qualified name of 1307 an "package-member type" -- that is, a type declaration not nested 1308 inside another declaration -- and return the <code>TypeSig</code> 1309 instance associated with the type declaration denoted by that name. 1310 <code>OutsideEnv</code> also coordinates the parsing of type 1311 declarations, ensuring that only one <code>TypeDecl</code> is 1312 created for a type declaration, and ensuring that 1313 <code>TypeSig</code> objects point to the appropriate 1314 <code>TypeDecl</code> objects. 1315 1316 <p> The <code>OutsideEnv</code> uses direct instances of 1317 <code>TypeSig</CODE> for nested types only. It uses a special subclass 1318 of <code>TypeSig</code>, <code>TopTypeSig</code>, for externally 1319 nameable types (what the Java spec calls "top-level types"). This 1320 subclass has fields giving the types external name. A further subclass 1321 of <code>TopTypeSig</code>, <code>OutsideTypeSig</code>, handles outside 1322 types. Alone among <code>TypeSigs</code>, <code>OutsideTypeSig</code>s 1323 have the the ability to load their <code>TypeDecl</code> objects lazily. 1324 All other <code>TypeSig</code> classes must have their 1325 <code>TypeDecl</code> provided at creation time. However, this is an 1326 implementation issue only: clients outside of <code>javafe.tc</code> 1327 should not assume the existence of these subclasses. 1328 1329 <p> Transitioning a <code>TypeSig</code> from one state to another may 1330 require parsing and processing of other types such as supertypes or the 1331 types found in method signatures. For example, checking that the 1332 <code>throws</code> clause of a method override is legal may involve 1333 checking a subtype relationship, which requires that types involved be 1334 supertype-link resolved. We call transitions that arise in the process 1335 of another transitions "secondary transitions." The code that 1336 implements transitions does not have to explicitly invoke secondary 1337 transitions; rather, they are performed by calling methods like 1338 <code>lookupField</code> or <code>isSubtypeOf</code>, whose 1339 implementations <em>do</em> invoke transitions if they are needed. For 1340 example, the method that implements the preparation transition does not 1341 directly call the method that implements supertype link resolution, but 1342 it <em>does</code> call <code>isSubtypeOf</code>, which in turn does 1343 directly call the supertype link resolution method. Thus, secondary 1344 transitions are largely transparent to the code implementing each 1345 transition, with one exception. The code implementing the transition to 1346 one state can<em>not</em> invoke methods that automatically transition 1347 types to a higher state. For example, the code implementing supertype 1348 link resolution cannot call <code>lookupField</code>. This discipline 1349 helps us avoid looping. 1350 1351 1352 @see OutsideEnv 1353 @see TypeCheck 1354 @see TypeDecl 1355 @see TypeName 1356 1357 */ 1358 1359 /** 1360 * Gets the TypeSig recorded by <code>setSig</code>, or null. 1361 */ 1362 public static TypeSig getRawSig(/*@ non_null @*/ TypeName n) { 1363 TypeSig r = (TypeSig)sigDecoration.get(n); 1364 return r; 1365 } 1366 1367 /** 1368 * Gets the TypeSig recorded by <code>setSig</code>. 1369 * 1370 * Precondition: n has been resolved. 1371 */ 1372 //@ ensures \result != null; 1373 public static TypeSig getSig(/*@ non_null @*/ TypeName n) { 1374 TypeSig r = (TypeSig)sigDecoration.get(n); 1375 if (r==null) { 1376 ErrorSet.error(n.getStartLoc(), 1377 "Internal error: getSig called on a TypeName (" 1378 + n + ") that has not been resolved!"); 1379 System.out.flush(); 1380 Assert.precondition( //@ nowarn Pre; // punt on catching this 1381 "See previous error message"); 1382 } 1383 1384 return r; 1385 } 1386 1387 public static void setSig(/*@ non_null @*/ TypeName n, 1388 /*@ non_null @*/ TypeSig sig) { 1389 sigDecoration.set(n, sig); 1390 } 1391 1392 public final boolean isSubtypeOf(TypeSig s2) { 1393 if (state < TypeSig.LINKSRESOLVED) 1394 resolveSupertypeLinks(); 1395 1396 TypeSig jlo = Types.javaLangObject(); 1397 1398 if (this == s2 || s2 == jlo) 1399 return true; 1400 if (this == jlo) 1401 return false; 1402 1403 TypeDecl d = getTypeDecl(); 1404 if (d.getTag() == TagConstants.CLASSDECL && 1405 ((ClassDecl)d).superClass != null) { 1406 TypeSig s1 = getSig(((ClassDecl)d).superClass); 1407 if (s1 == s2) 1408 return true; 1409 if (s1.isSubtypeOf(s2)) 1410 return true; 1411 } 1412 1413 for(int i = 0; i < d.superInterfaces.size(); i++) { 1414 TypeSig s1 = getSig(d.superInterfaces.elementAt(i)); 1415 if (s1 == s2) 1416 return true; 1417 if (s1.isSubtypeOf(s2)) 1418 return true; 1419 } 1420 1421 return false; 1422 } 1423 1424 //// Helper functions 1425 1426 //@ requires s != null; 1427 public final boolean inSamePackageAs(TypeSig s) { 1428 String[] p1 = this.packageName; 1429 String[] p2 = s.packageName; 1430 if (p1.length != p2.length) return false; 1431 for(int i = 0; i < p1.length; i++) 1432 if (! p1[i].equals(p2[i])) return false; 1433 return true; 1434 } 1435 1436 /** Check invariants of a TypeSig, raising an exception if 1437 they don't hold. */ 1438 1439 public void check() { 1440 Assert.notFalse(state != RESOLVINGLINKS); //@ nowarn Pre; 1441 1442 if (state >= CREATED) { 1443 if (state == CREATED) 1444 Assert.notFalse(myTypeDecl == null); 1445 } 1446 1447 if (state >= PARSED) { 1448 Assert.notNull(myTypeDecl); 1449 Assert.notFalse(this == getSig(myTypeDecl)); //@ nowarn Pre; 1450 } 1451 } 1452 1453 /** Check invariants of a TypeSig, raising an exception if 1454 they don't hold. */ 1455 1456 public void deepCheck() { 1457 Info.out("[checking deep invariants on " + this + "]"); 1458 check(); 1459 if (state >= PARSED) { 1460 myTypeDecl.check(); 1461 CheckInvariants.checkTypeDeclOfSig(this); 1462 } 1463 } 1464 1465 private TypeSig superClass = null; 1466 1467 // Probably should use this only after super types have been resolved. 1468 public TypeSig superClass() { 1469 if (superClass != null) return superClass; 1470 TypeDecl decl = getTypeDecl(); 1471 if (decl instanceof ClassDecl) { 1472 TypeName n = ((ClassDecl)decl).superClass; 1473 if (n != null) { 1474 superClass = getSig(n); 1475 } 1476 } 1477 return superClass; 1478 } 1479 1480 /* This class returns a Collection containing all of the super interfaces 1481 of the receiver TypeSig. No interface is repeated. 1482 */ 1483 public java.util.Collection superInterfaces() { 1484 TypeSig t = this; 1485 java.util.ArrayList result = new java.util.ArrayList(); 1486 int j = 0; 1487 while (true) { 1488 TypeNameVec tv = t.getTypeDecl().superInterfaces; 1489 for (int i = 0; i<tv.size(); ++i) { 1490 TypeName tt = tv.elementAt(i); 1491 TypeSig tts = getSig(tt); 1492 if (!result.contains(tts)) result.add(tts); 1493 } 1494 if (j >= result.size()) break; 1495 t = (TypeSig)result.get(j++); 1496 } 1497 return result; 1498 } 1499 1500 } // end of class TypeSig 1501 1502 /* 1503 * Local Variables: 1504 * Mode: Java 1505 * fill-column: 85 1506 * End: 1507 */