001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * 2014-2015, Jesper Öqvist <jesper.oqvist@cs.lth.se> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions are met: 007 * 008 * 1. Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * 2. Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * 3. Neither the name of the copyright holder nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 023 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 024 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 025 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 026 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 027 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 029 * POSSIBILITY OF SUCH DAMAGE. 030 */ 031 032 import java.util.*; 033 import java.util.zip.*; 034 import java.io.*; 035 036 aspect SpecialClasses { 037 syn lazy TypeDecl Program.typeObject() = lookupType("java.lang", "Object"); 038 syn lazy TypeDecl Program.typeCloneable() = lookupType("java.lang", "Cloneable"); 039 syn lazy TypeDecl Program.typeSerializable() = lookupType("java.io", "Serializable"); 040 041 eq Program.getChild().typeObject() = typeObject(); 042 eq Program.getChild().typeCloneable() = typeCloneable(); 043 eq Program.getChild().typeSerializable() = typeSerializable(); 044 045 syn lazy TypeDecl Program.typeBoolean() = getPrimitiveCompilationUnit().typeBoolean(); 046 syn lazy TypeDecl Program.typeByte() = getPrimitiveCompilationUnit().typeByte(); 047 syn lazy TypeDecl Program.typeShort() = getPrimitiveCompilationUnit().typeShort(); 048 syn lazy TypeDecl Program.typeChar() = getPrimitiveCompilationUnit().typeChar(); 049 syn lazy TypeDecl Program.typeInt() = getPrimitiveCompilationUnit().typeInt(); 050 syn lazy TypeDecl Program.typeLong() = getPrimitiveCompilationUnit().typeLong(); 051 syn lazy TypeDecl Program.typeFloat() = getPrimitiveCompilationUnit().typeFloat(); 052 syn lazy TypeDecl Program.typeDouble() = getPrimitiveCompilationUnit().typeDouble(); 053 syn lazy TypeDecl Program.typeString() = lookupType("java.lang", "String"); 054 055 eq Program.getChild().typeBoolean() = typeBoolean(); 056 eq Program.getChild().typeByte() = typeByte(); 057 eq Program.getChild().typeShort() = typeShort(); 058 eq Program.getChild().typeChar() = typeChar(); 059 eq Program.getChild().typeInt() = typeInt(); 060 eq Program.getChild().typeLong() = typeLong(); 061 eq Program.getChild().typeFloat() = typeFloat(); 062 eq Program.getChild().typeDouble() = typeDouble(); 063 eq Program.getChild().typeString() = typeString(); 064 065 syn lazy TypeDecl Program.typeVoid() = getPrimitiveCompilationUnit().typeVoid(); 066 eq Program.getChild().typeVoid() = typeVoid(); 067 068 syn lazy TypeDecl Program.typeNull() = getPrimitiveCompilationUnit().typeNull(); 069 eq Program.getChild().typeNull() = typeNull(); 070 071 syn lazy TypeDecl Program.unknownType() = getPrimitiveCompilationUnit().unknownType(); 072 eq Program.getChild().unknownType() = unknownType(); 073 074 inh TypeDecl Expr.typeBoolean(); 075 inh TypeDecl Expr.typeByte(); 076 inh TypeDecl Expr.typeShort(); 077 inh TypeDecl Expr.typeChar(); 078 inh TypeDecl Expr.typeInt(); 079 inh TypeDecl Expr.typeLong(); 080 inh TypeDecl Expr.typeFloat(); 081 inh TypeDecl Expr.typeDouble(); 082 inh TypeDecl Expr.typeString(); 083 inh TypeDecl Expr.typeVoid(); 084 inh TypeDecl Expr.typeNull(); 085 086 inh lazy TypeDecl SwitchStmt.typeInt(); 087 inh TypeDecl TypeDecl.typeInt(); 088 inh lazy TypeDecl SwitchStmt.typeLong(); 089 090 inh lazy TypeDecl TypeDecl.typeObject(); 091 092 inh lazy TypeDecl ThrowStmt.typeThrowable(); 093 inh lazy TypeDecl CatchClause.typeThrowable(); 094 095 inh lazy TypeDecl ThrowStmt.typeNull(); 096 097 inh TypeDecl Expr.unknownType(); 098 099 } 100 101 aspect LookupFullyQualifiedTypes { 102 syn lazy boolean Program.hasPackage(String packageName) = 103 isPackage(packageName); 104 105 /** 106 * The scope of a declaration of an observable top level package is all 107 * observable compilation units 108 */ 109 eq Program.getChild().hasPackage(String packageName) = hasPackage(packageName); 110 eq AbstractDot.getRight().hasPackage(String packageName) = 111 getLeft().hasQualifiedPackage(packageName); 112 syn boolean Expr.hasQualifiedPackage(String packageName) = false; 113 eq PackageAccess.hasQualifiedPackage(String packageName) = 114 hasPackage(packageName() + "." + packageName); 115 inh boolean Expr.hasPackage(String packageName); 116 eq MethodAccess.getArg().hasPackage(String packageName) = 117 unqualifiedScope().hasPackage(packageName); 118 eq ConstructorAccess.getArg().hasPackage(String packageName) = 119 unqualifiedScope().hasPackage(packageName); 120 eq SuperConstructorAccess.getArg().hasPackage(String packageName) = 121 unqualifiedScope().hasPackage(packageName); 122 eq ArrayAccess.getExpr().hasPackage(String packageName) = 123 unqualifiedScope().hasPackage(packageName); 124 eq ArrayTypeWithSizeAccess.getExpr().hasPackage(String packageName) = 125 unqualifiedScope().hasPackage(packageName); 126 eq ClassInstanceExpr.getArg().hasPackage(String packageName) = 127 unqualifiedScope().hasPackage(packageName); 128 129 inh TypeDecl Expr.lookupType(String packageName, String typeName); 130 inh TypeDecl Stmt.lookupType(String packageName, String typeName); 131 inh TypeDecl BodyDecl.lookupType(String packageName, String typeName); 132 inh TypeDecl TypeDecl.lookupType(String packageName, String typeName); 133 inh TypeDecl CompilationUnit.lookupType(String packageName, String typeName); 134 135 public int Program.classFileReadTime; 136 137 /** 138 * Defers the lookup to the synthesized attribute. 139 */ 140 eq Program.getChild().lookupType(String packageName, String typeName) = 141 lookupType(packageName, typeName); 142 143 /** 144 * Checks from-source compilation units for the given type. 145 * If no matching compilation unit is found the library compliation units 146 * will be searched. 147 */ 148 syn lazy TypeDecl Program.lookupType(String packageName, String typeName) { 149 // Look for a matching source type. 150 TypeDecl sourceType = lookupSourceType(packageName, typeName); 151 if (!sourceType.isUnknown()) { 152 return sourceType; 153 } 154 155 // Look for a matching library type. 156 return lookupLibraryType(packageName, typeName); 157 } 158 159 /** 160 * Extra cache for source type lookups. This cache is important in order to 161 * make all source types shadow library types with matching names, even when 162 * the source type lives in a compilation unit with a different simple name. 163 */ 164 private final Map<String, TypeDecl> Program.sourceTypeMap = new HashMap<String, TypeDecl>(); 165 private boolean Program.sourceTypeMapInitialized = false; 166 167 /** 168 * Lookup a type among source classes. 169 * <p> 170 * Invoking this method may cause more than just the specified type to be loaded, for 171 * example if there exists other types in the same source file, the additional 172 * types are also loaded and cached for the next lookup. 173 * <p> 174 * This method is not an attribute due to the necessary side-effects caused 175 * by loading and caching of extra types. 176 */ 177 protected TypeDecl Program.lookupSourceType(String packageName, String typeName) { 178 String fullName = packageName.equals("") ? typeName : packageName + "." + typeName; 179 180 if (!sourceTypeMapInitialized) { 181 initializeSourceTypeMap(); 182 sourceTypeMapInitialized = true; 183 } 184 185 if (sourceTypeMap.containsKey(fullName)) { 186 return sourceTypeMap.get(fullName); 187 } else { 188 sourceTypeMap.put(fullName, unknownType()); 189 } 190 191 // Look for a matching library type. 192 return unknownType(); 193 } 194 195 /** 196 * Initialize source types in the source type map. This puts all the types provided by 197 * Program.addSourceFile() in a map for lookup by Program.lookupSourceType. 198 */ 199 private void Program.initializeSourceTypeMap() { 200 // Initialize source type map with the compilation units supplied by Program.addSourceFile. 201 for (int i = 0; i < getNumCompilationUnit(); i++) { 202 CompilationUnit unit = getCompilationUnit(i); 203 for (int j = 0; j < unit.getNumTypeDecl(); j++) { 204 TypeDecl type = unit.getTypeDecl(j); 205 sourceTypeMap.put(type.fullName(), type); 206 } 207 } 208 } 209 210 /** 211 * Extra cache for library type lookups. This cache does not have a big 212 * effect on performance due to the caching of the parameterized 213 * lookupLibraryType attribute. The cache is needed to be able to track library types 214 * that are declared in compilation units with a different simple name than the type itself. 215 */ 216 private final Map<String, TypeDecl> Program.libraryTypeMap = new HashMap<String, TypeDecl>(); 217 private boolean Program.libraryTypeMapInitialized = false; 218 219 /** 220 * Lookup a type among library classes. The lookup includes Jar and source files. 221 * <p> 222 * Invoking this method may cause more than just the specified type to be loaded, for 223 * example if there exists other types in the same source file, the additional 224 * types are also loaded and cached for the next lookup. 225 * <p> 226 * This method is not an attribute due to the necessary side-effects caused 227 * by loading and caching of extra types. 228 */ 229 protected TypeDecl Program.lookupLibraryType(String packageName, String typeName) { 230 String fullName = packageName.equals("") ? typeName : packageName + "." + typeName; 231 232 if (!libraryTypeMapInitialized) { 233 initializeLibraryTypeMap(); 234 libraryTypeMapInitialized = true; 235 } 236 237 if (libraryTypeMap.containsKey(fullName)) { 238 return libraryTypeMap.get(fullName); 239 } 240 241 // Lookup the type in the library class path. 242 CompilationUnit libraryUnit = getLibCompilationUnit(fullName); 243 244 // Add all types from the compilation unit in the library type map so that we can find them on 245 // the next type lookup. If we don't do this lookup might incorrectly miss a type that is not 246 // declared in a Java source file with a matching name. 247 for (int j = 0; j < libraryUnit.getNumTypeDecl(); j++) { 248 TypeDecl type = libraryUnit.getTypeDecl(j); 249 if (!libraryTypeMap.containsKey(type.fullName())) { 250 libraryTypeMap.put(type.fullName(), type); 251 } 252 } 253 254 if (libraryTypeMap.containsKey(fullName)) { 255 return libraryTypeMap.get(fullName); 256 } else { 257 libraryTypeMap.put(fullName, unknownType()); 258 return unknownType(); 259 } 260 } 261 262 /** Initialize primitive types in the library type map. */ 263 private void Program.initializeLibraryTypeMap() { 264 PrimitiveCompilationUnit unit = getPrimitiveCompilationUnit(); 265 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".boolean", unit.typeBoolean()); 266 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".byte", unit.typeByte()); 267 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".short", unit.typeShort()); 268 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".char", unit.typeChar()); 269 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".int", unit.typeInt()); 270 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".long", unit.typeLong()); 271 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".float", unit.typeFloat()); 272 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".double", unit.typeDouble()); 273 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".null", unit.typeNull()); 274 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".void", unit.typeVoid()); 275 libraryTypeMap.put(PRIMITIVE_PACKAGE_NAME + ".Unknown", unit.unknownType()); 276 } 277 278 /** 279 * This attribute is used to cache library compilation units, by storing the compilation units in 280 * a parameterized NTA. 281 */ 282 syn nta CompilationUnit Program.getLibCompilationUnit(String typeName) = 283 getCompilationUnit(typeName); 284 285 syn nta CompilationUnit Program.emptyCompilationUnit() = new CompilationUnit(); 286 } 287 288 aspect TypeScopePropagation { 289 inh TypeDecl Access.unknownType(); 290 291 syn lazy SimpleSet TypeAccess.decls() = 292 packageName().equals("") 293 ? lookupType(name()) 294 : lookupType(packageName(), name()).asSet(); 295 296 /** 297 * @return a set containing this type, unless this is the unknown type in 298 * which case an empty set is returned 299 */ 300 syn SimpleSet TypeDecl.asSet() = this; 301 eq UnknownType.asSet() = SimpleSet.emptySet; 302 303 syn lazy SimpleSet PrimitiveTypeAccess.decls() = lookupType(PRIMITIVE_PACKAGE_NAME, name()); 304 syn lazy String PrimitiveTypeAccess.getPackage() = PRIMITIVE_PACKAGE_NAME; 305 syn lazy String PrimitiveTypeAccess.getID() = getName(); 306 307 syn lazy TypeDecl TypeAccess.decl() { 308 SimpleSet decls = decls(); 309 if (decls.size() == 1) { 310 return (TypeDecl) decls.iterator().next(); 311 } 312 return unknownType(); 313 } 314 315 syn lazy TypeDecl ArrayTypeAccess.decl() = getAccess().type().arrayType(); 316 317 syn SimpleSet ThisAccess.decls() = SimpleSet.emptySet; 318 syn SimpleSet SuperAccess.decls() = SimpleSet.emptySet; 319 320 /** 321 * @return the type which this access references 322 */ 323 syn lazy TypeDecl ThisAccess.decl() = isQualified() ? qualifier().type() : hostType(); 324 325 /** 326 * @return the type whose supertype this super access references 327 */ 328 syn lazy TypeDecl SuperAccess.decl() = isQualified() ? qualifier().type() : hostType(); 329 330 eq MethodAccess.getArg().lookupType(String name) = unqualifiedScope().lookupType(name); 331 eq ConstructorAccess.getArg().lookupType(String name) = unqualifiedScope().lookupType(name); 332 eq ArrayAccess.getExpr().lookupType(String name) = unqualifiedScope().lookupType(name); 333 eq ArrayTypeWithSizeAccess.getExpr().lookupType(String name) = unqualifiedScope().lookupType(name); 334 eq ClassInstanceExpr.getArg().lookupType(String name) = unqualifiedScope().lookupType(name); 335 336 inh lazy SimpleSet CompilationUnit.lookupType(String name); 337 inh lazy SimpleSet TypeDecl.lookupType(String name); 338 inh SimpleSet BodyDecl.lookupType(String name); 339 inh SimpleSet Stmt.lookupType(String name); 340 inh lazy SimpleSet Block.lookupType(String name); 341 inh SimpleSet Expr.lookupType(String name); 342 343 eq Program.getChild().lookupType(String name) = SimpleSet.emptySet; 344 345 // The scope of a type import declaration is all the class and interface type declarations in 346 // the compilation unit in which the import declaration appears. 347 eq CompilationUnit.getChild().lookupType(String name) { 348 // Locally declared types in the compilation unit. 349 SimpleSet set = localLookupType(name); 350 if (!set.isEmpty()) { 351 return set; 352 } 353 354 // Imported types. 355 set = importedTypes(name); 356 if (!set.isEmpty()) { 357 return set; 358 } 359 360 // Types in the same package. 361 TypeDecl result = lookupType(packageName(), name); 362 if (result.accessibleFromPackage(packageName())) { 363 return result; 364 } 365 366 // Types imported on demand. 367 set = importedTypesOnDemand(name); 368 if (!set.isEmpty()) { 369 return set; 370 } 371 372 // Include primitive types. 373 result = lookupType(PRIMITIVE_PACKAGE_NAME, name); 374 if (!result.isUnknown()) { 375 return result; 376 } 377 378 // 7.5.5 Automatic Imports 379 result = lookupType("java.lang", name); 380 if (result.accessibleFromPackage(packageName())) { 381 return result; 382 } 383 return lookupType(name); 384 } 385 386 /** Searches for a type with the given simple name in this compilation unit. */ 387 syn SimpleSet CompilationUnit.localLookupType(String name) { 388 for (int i = 0; i < getNumTypeDecl(); i++) { 389 if (getTypeDecl(i).name().equals(name)) { 390 return SimpleSet.emptySet.add(getTypeDecl(i)); 391 } 392 } 393 return SimpleSet.emptySet; 394 } 395 396 syn SimpleSet CompilationUnit.importedTypes(String name) { 397 SimpleSet set = SimpleSet.emptySet; 398 for (int i = 0; i < getNumImportDecl(); i++) { 399 if (!getImportDecl(i).isOnDemand()) { 400 for (Iterator iter = getImportDecl(i).importedTypes(name).iterator(); iter.hasNext(); ) { 401 set = set.add(iter.next()); 402 } 403 } 404 } 405 return set; 406 } 407 408 syn SimpleSet CompilationUnit.importedTypesOnDemand(String name) { 409 SimpleSet set = SimpleSet.emptySet; 410 for (int i = 0; i < getNumImportDecl(); i++) { 411 if (getImportDecl(i).isOnDemand()) { 412 for (Iterator iter = getImportDecl(i).importedTypes(name).iterator(); iter.hasNext(); ) { 413 set = set.add(iter.next()); 414 } 415 } 416 } 417 return set; 418 } 419 420 syn lazy SimpleSet ImportDecl.importedTypes(String name) = SimpleSet.emptySet; 421 422 eq SingleTypeImportDecl.importedTypes(String name) { 423 SimpleSet set = SimpleSet.emptySet; 424 TypeDecl type = getAccess().type(); 425 if (type.name().equals(name)) { 426 set = set.add(type); 427 } 428 return set; 429 } 430 431 /** 432 * For a single-import declaration this will return a SimpleSet 433 * containing the TypeDecl for the imported type. For dynamic 434 * import declarations this returns the empty set. 435 * @return TypeDecl of imported type wrapped in SimpleSet 436 */ 437 syn lazy SimpleSet ImportDecl.importedTypes() = SimpleSet.emptySet; 438 439 eq SingleTypeImportDecl.importedTypes() = SimpleSet.emptySet.add(getAccess().type()); 440 441 eq TypeImportOnDemandDecl.importedTypes(String name) { 442 SimpleSet set = SimpleSet.emptySet; 443 if (getAccess() instanceof PackageAccess) { 444 String packageName = ((PackageAccess) getAccess()).getPackage(); 445 TypeDecl typeDecl = lookupType(packageName, name); 446 if (typeDecl.accessibleFromPackage(packageName()) && 447 typeDecl.typeName().equals(packageName + "." + name)) { 448 // Canonical names match. 449 set = set.add(typeDecl); 450 } 451 } else { 452 for (Iterator iter = getAccess().type().memberTypes(name).iterator(); iter.hasNext(); ) { 453 TypeDecl decl = (TypeDecl) iter.next(); 454 if (decl.accessibleFromPackage(packageName()) && 455 decl.typeName().equals(getAccess().typeName() + "." + name)) { 456 // Canonical names match. 457 set = set.add(decl); 458 } 459 } 460 } 461 return set; 462 } 463 inh TypeDecl TypeImportOnDemandDecl.lookupType(String packageName, String typeName); 464 inh String ImportDecl.packageName(); 465 466 syn boolean ImportDecl.isOnDemand() = false; 467 eq TypeImportOnDemandDecl.isOnDemand() = true; 468 469 // Imports are not themselves affected by imports. 470 eq CompilationUnit.getImportDecl().lookupType(String name) = lookupType(name); 471 472 eq TypeDecl.getBodyDecl(int index).lookupType(String name) = localLookupType(name); 473 474 eq ClassDecl.getImplicitConstructor().lookupType(String name) = localLookupType(name); 475 476 syn SimpleSet TypeDecl.localLookupType(String name) { 477 SimpleSet c = memberTypes(name); 478 if (!c.isEmpty()) { 479 return c; 480 } 481 if (name().equals(name)) { 482 return SimpleSet.emptySet.add(this); 483 } 484 485 c = lookupType(name); 486 // 8.5.2 487 if (isClassDecl() && isStatic() && !isTopLevelType()) { 488 SimpleSet newSet = SimpleSet.emptySet; 489 for (Iterator iter = c.iterator(); iter.hasNext(); ) { 490 TypeDecl d = (TypeDecl) iter.next(); 491 //if (d.isStatic() || d.isTopLevelType() || this.instanceOf(d.enclosingType())) { 492 newSet = newSet.add(d); 493 //} 494 } 495 c = newSet; 496 } 497 return c; 498 } 499 500 eq Block.getStmt(int index).lookupType(String name) { 501 SimpleSet c = SimpleSet.emptySet; 502 for (int i = index; i >= 0 && !(getStmt(i) instanceof Case); i--) { 503 if (getStmt(i) instanceof LocalClassDeclStmt) { 504 TypeDecl t = ((LocalClassDeclStmt) getStmt(i)).getClassDecl(); 505 if (t.name().equals(name)) { 506 c = c.add(t); 507 } 508 } 509 } 510 if (!c.isEmpty()) { 511 return c; 512 } 513 return lookupType(name); 514 } 515 516 eq ClassInstanceExpr.getAccess().lookupType(String name) { 517 SimpleSet c = lookupType(name); 518 if (c.size() == 1) { 519 if (isQualified()) { 520 c = keepInnerClasses(c); 521 } 522 } 523 return c; 524 } 525 526 eq ClassInstanceExpr.getTypeDecl().lookupType(String name) { 527 SimpleSet c = localLookupType(name); 528 if (!c.isEmpty()) { 529 return c; 530 } 531 c = lookupType(name); 532 if (!c.isEmpty()) { 533 return c; 534 } 535 return unqualifiedScope().lookupType(name); 536 } 537 538 public SimpleSet ClassInstanceExpr.keepInnerClasses(SimpleSet c) { 539 SimpleSet newSet = SimpleSet.emptySet; 540 for (Iterator iter = c.iterator(); iter.hasNext(); ) { 541 TypeDecl t = (TypeDecl) iter.next(); 542 if (t.isInnerType() && t.isClassDecl()) { 543 newSet = newSet.add(c); 544 } 545 } 546 return newSet; 547 } 548 549 eq ParseName.qualifiedLookupType(String name) = SimpleSet.emptySet; 550 551 eq AbstractDot.getRight().lookupType(String name) = getLeft().qualifiedLookupType(name); 552 553 syn SimpleSet Expr.qualifiedLookupType(String name) = 554 keepAccessibleTypes(type().memberTypes(name)); 555 556 eq ClassInstanceExpr.qualifiedLookupType(String name) { 557 SimpleSet c = keepAccessibleTypes(type().memberTypes(name)); 558 if (!c.isEmpty()) { 559 return c; 560 } 561 if (type().name().equals(name)) { 562 return SimpleSet.emptySet.add(type()); 563 } 564 return SimpleSet.emptySet; 565 } 566 567 eq PackageAccess.qualifiedLookupType(String name) { 568 SimpleSet c = SimpleSet.emptySet; 569 TypeDecl typeDecl = lookupType(packageName(), name); 570 if (!typeDecl.isUnknown()) { 571 if (hostType() != null && typeDecl.accessibleFrom(hostType())) { 572 c = c.add(typeDecl); 573 } else if (hostType() == null && typeDecl.accessibleFromPackage(hostPackage())) { 574 c = c.add(typeDecl); 575 } 576 } 577 return c; 578 } 579 580 public SimpleSet Expr.keepAccessibleTypes(SimpleSet oldSet) { 581 SimpleSet newSet = SimpleSet.emptySet; 582 TypeDecl hostType = hostType(); 583 for (Iterator iter = oldSet.iterator(); iter.hasNext(); ) { 584 TypeDecl t = (TypeDecl) iter.next(); 585 if ((hostType != null && t.accessibleFrom(hostType)) 586 || (hostType == null && t.accessibleFromPackage(hostPackage()))) { 587 newSet = newSet.add(t); 588 } 589 } 590 return newSet; 591 } 592 593 syn lazy SimpleSet ClassInstanceExpr.localLookupType(String name) = 594 hasTypeDecl() && getTypeDecl().name().equals(name) 595 ? SimpleSet.emptySet.add(getTypeDecl()) 596 : SimpleSet.emptySet; 597 598 syn boolean TypeDecl.hasType(String name) = !memberTypes(name).isEmpty(); 599 syn boolean BodyDecl.declaresType(String name) = false; 600 eq MemberTypeDecl.declaresType(String name) = typeDecl().name().equals(name); 601 syn TypeDecl BodyDecl.type(String name) = null; 602 eq MemberTypeDecl.type(String name) = declaresType(name) ? typeDecl() : null; 603 604 syn TypeDecl MemberTypeDecl.typeDecl(); 605 eq MemberClassDecl.typeDecl() = getClassDecl(); 606 eq MemberInterfaceDecl.typeDecl() = getInterfaceDecl(); 607 608 609 syn lazy SimpleSet TypeDecl.localTypeDecls(String name) { 610 SimpleSet set = SimpleSet.emptySet; 611 for (int i = 0; i < getNumBodyDecl(); i++) { 612 if (getBodyDecl(i).declaresType(name)) { 613 set = set.add(getBodyDecl(i).type(name)); 614 } 615 } 616 return set; 617 } 618 619 syn lazy SimpleSet TypeDecl.memberTypes(String name) = SimpleSet.emptySet; 620 621 eq UnknownType.memberTypes(String name) = SimpleSet.emptySet; 622 623 eq ClassDecl.memberTypes(String name) { 624 SimpleSet set = localTypeDecls(name); 625 if (!set.isEmpty()) { 626 return set; 627 } 628 for (Iterator<TypeDecl> outerIter = interfacesIterator(); outerIter.hasNext(); ) { 629 TypeDecl type = outerIter.next(); 630 for (Iterator iter = type.memberTypes(name).iterator(); iter.hasNext(); ) { 631 TypeDecl decl = (TypeDecl) iter.next(); 632 if (!decl.isPrivate() && decl.accessibleFrom(this)) { 633 set = set.add(decl); 634 } 635 } 636 } 637 if (hasSuperclass()) { 638 for (Iterator iter = superclass().memberTypes(name).iterator(); iter.hasNext(); ) { 639 TypeDecl decl = (TypeDecl) iter.next(); 640 if (!decl.isPrivate() && decl.accessibleFrom(this)) { 641 set = set.add(decl); 642 } 643 } 644 } 645 return set; 646 } 647 648 eq InterfaceDecl.memberTypes(String name) { 649 SimpleSet set = localTypeDecls(name); 650 if (!set.isEmpty()) { 651 return set; 652 } 653 for (Iterator<TypeDecl> outerIter = interfacesIterator(); outerIter.hasNext(); ) { 654 TypeDecl typeDecl = outerIter.next(); 655 for (Iterator iter = typeDecl.memberTypes(name).iterator(); iter.hasNext(); ) { 656 TypeDecl decl = (TypeDecl) iter.next(); 657 if (!decl.isPrivate()) { 658 set = set.add(decl); 659 } 660 } 661 } 662 return set; 663 } 664 }