001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * 2014, 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 aspect Generics { 033 034 /** 035 * Qualified access for wildcard types. 036 * Since they have no ordinary package and type name 037 * we just return the bound access. 038 */ 039 public Access AbstractWildcardType.createQualifiedAccess() { 040 return createBoundAccess(); 041 } 042 043 eq ParClassDecl.hostType() = original(); 044 eq ParInterfaceDecl.hostType() = original(); 045 eq RawClassDecl.hostType() = original(); 046 eq RawInterfaceDecl.hostType() = original(); 047 eq ClassDeclSubstituted.hostType() = getOriginal(); 048 eq InterfaceDeclSubstituted.hostType() = getOriginal(); 049 eq GenericClassDeclSubstituted.hostType() = getOriginal(); 050 eq GenericInterfaceDeclSubstituted.hostType() = getOriginal(); 051 052 refine TypeAnalysis eq MethodAccess.type() { 053 if (getNumArg() == 0 && name().equals("getClass") && decl().hostType().isObject()) { 054 TypeDecl typeClass = lookupType("java.lang", "Class"); 055 if (typeClass instanceof GenericClassDecl) { 056 TypeDecl bound = isQualified() ? qualifier().type() : hostType(); 057 ArrayList<TypeDecl> args = new ArrayList<TypeDecl>(); 058 args.add(bound.erasure().asWildcardExtends()); 059 return ((GenericClassDecl) typeClass).lookupParTypeDecl(args); 060 } 061 } 062 // Legacy getClass access using non-generic java.lang.Class. 063 return refined(); 064 } 065 066 // Imported types are considered raw types by the name resolver 067 // here we replace them by their generic counter parts. 068 refine TypeScopePropagation eq CompilationUnit.getChild().lookupType(String name) { 069 SimpleSet result = SimpleSet.emptySet; 070 for (Iterator iter = refined(name).iterator(); iter.hasNext(); ) { 071 TypeDecl typeDecl = (TypeDecl) iter.next(); 072 if (typeDecl instanceof ParTypeDecl) { 073 result = result.add(((ParTypeDecl) typeDecl).genericDecl()); 074 } else { 075 result = result.add(typeDecl); 076 } 077 } 078 return result; 079 } 080 081 refine TypeConversion eq ClassDecl.castingConversionTo(TypeDecl type) { 082 TypeDecl S = this; 083 TypeDecl T = type; 084 if (T instanceof TypeVariable) { 085 TypeVariable t = (TypeVariable) T; 086 if (t.getNumTypeBound() == 0) { 087 return true; 088 } 089 for (int i = 0; i < t.getNumTypeBound(); i++) { 090 if (castingConversionTo(t.getTypeBound(i).type())) { 091 return true; 092 } 093 } 094 return false; 095 } 096 if (T.isClassDecl() && (S.erasure() != S || T.erasure() != T)) { 097 return S.erasure().castingConversionTo(T.erasure()); 098 } 099 return refined(type); 100 } 101 102 refine TypeConversion eq InterfaceDecl.castingConversionTo(TypeDecl type) { 103 TypeDecl S = this; 104 TypeDecl T = type; 105 if (T.isArrayDecl()) { 106 return T.instanceOf(S); 107 } else if (T.isReferenceType() && !T.isFinal()) { 108 return true; 109 } else { 110 return T.instanceOf(S); 111 } 112 } 113 114 eq TypeVariable.castingConversionTo(TypeDecl type) { 115 if (!type.isReferenceType()) { 116 return false; 117 } 118 if (getNumTypeBound() == 0) { 119 return true; 120 } 121 for (int i = 0; i < getNumTypeBound(); i++) { 122 if (getTypeBound(i).type().castingConversionTo(type)) { 123 return true; 124 } 125 } 126 return false; 127 } 128 129 refine TypeConversion eq ArrayDecl.castingConversionTo(TypeDecl type) { 130 TypeDecl S = this; 131 TypeDecl T = type; 132 if (T instanceof TypeVariable) { 133 TypeVariable t = (TypeVariable) T; 134 if (!type.isReferenceType()) { 135 return false; 136 } 137 if (t.getNumTypeBound() == 0) { 138 return true; 139 } 140 for (int i = 0; i < t.getNumTypeBound(); i++) { 141 TypeDecl bound = t.getTypeBound(i).type(); 142 if (bound.isObject() || bound == typeSerializable() || bound == typeCloneable()) { 143 return true; 144 } 145 if (bound.isTypeVariable() && castingConversionTo(bound)) { 146 return true; 147 } 148 if (bound.isArrayDecl() && castingConversionTo(bound)) { 149 return true; 150 } 151 } 152 return false; 153 } else { 154 return refined(type); 155 } 156 } 157 158 refine TypeAnalysis eq ClassAccess.type() { 159 TypeDecl decl = refined(); 160 if (decl instanceof GenericClassDecl) { 161 GenericClassDecl d = (GenericClassDecl) refined(); 162 TypeDecl type = qualifier().type(); 163 if (type.isPrimitiveType()) { 164 type = type.boxed(); 165 } 166 ArrayList<TypeDecl> list = new ArrayList<TypeDecl>(); 167 list.add(type); 168 return d.lookupParTypeDecl(list); 169 } 170 // Using non-generic java.lang.Class 171 return decl; 172 } 173 174 refine AutoBoxing eq ConditionalExpr.type() { 175 TypeDecl type = refined(); 176 TypeDecl trueType = getTrueExpr().type(); 177 TypeDecl falseType = getFalseExpr().type(); 178 179 if (type.isUnknown()) { 180 if (!trueType.isReferenceType() && !trueType.boxed().isUnknown()) { 181 trueType = trueType.boxed(); 182 } 183 if (!falseType.isReferenceType() && !falseType.boxed().isUnknown()) { 184 falseType = falseType.boxed(); 185 } 186 187 ArrayList<TypeDecl> list = new ArrayList<TypeDecl>(); 188 list.add(trueType); 189 list.add(falseType); 190 return type.lookupLUBType(list); 191 } 192 return type; 193 } 194 195 syn boolean TypeVariable.isNestedType() = false; 196 197 // Accessibility for members in generic classes. The accessibility for 198 // parameterized and raw versions of a generic class should be the same as 199 // for the generic class, in other words the erasure of the paramterized 200 // version. 201 eq ParClassDecl.topLevelType() = erasure().topLevelType(); 202 203 interface GenericTypeDecl { 204 syn boolean isGenericType(); 205 TypeDecl original(); 206 int getNumTypeParameter(); 207 TypeVariable getTypeParameter(int index); 208 List<TypeVariable> getTypeParameterList(); 209 syn lazy TypeDecl rawType(); 210 public String fullName(); 211 public String typeName(); 212 } 213 214 GenericClassDecl implements GenericTypeDecl; 215 GenericInterfaceDecl implements GenericTypeDecl; 216 217 eq GenericClassDecl.rawType() = lookupParTypeDecl(Collections.<TypeDecl>emptyList()); 218 219 eq GenericInterfaceDecl.rawType() = lookupParTypeDecl(Collections.<TypeDecl>emptyList()); 220 221 syn boolean TypeDecl.isGenericType() = false; 222 223 eq GenericTypeDecl.isGenericType() = true; 224 225 // Brute force replacesment with generic one in AST 226 // make sure that the AST has not beed traversed yet! 227 public TypeDecl TypeDecl.makeGeneric(Signatures.ClassSignature s) { 228 return this; 229 } 230 231 public TypeDecl ClassDecl.makeGeneric(Signatures.ClassSignature s) { 232 // NOTE: we are overwriting List- and Opt- children here using setSuperClassOpt 233 // and setImplementsList. This is dangerous since those children are in some 234 // cases NTAs, and we should not use set methods to try to overwrite NTA values. 235 // However, we have to do this here in order to not trigger rewrites that in 236 // turn need to access certain (inherited) lookup attributes, and we are reasonably 237 // sure that we are in fact not overwriting NTA children. We exclude EnumDecl here 238 // because its [SuperClass] and Implements* are in fact NTAs. 239 // /Jesper 2015-01-22 240 if (this instanceof EnumDecl) { 241 return this; // Enum superclass and superinterfaces are NTAs. 242 } 243 if (s.hasFormalTypeParameters()) { 244 ASTNode node = getParent(); 245 int index = node.getIndexOfChild(this); 246 node.setChild( 247 new GenericClassDecl( 248 getModifiersNoTransform(), 249 getID(), 250 s.hasSuperclassSignature() 251 ? new Opt(s.superclassSignature()) 252 : getSuperClassOptNoTransform(), 253 s.hasSuperinterfaceSignature() 254 ? s.superinterfaceSignature() 255 : getImplementsListNoTransform(), 256 getBodyDeclListNoTransform(), 257 s.typeParameters() 258 ), 259 index 260 ); 261 return (TypeDecl) node.getChildNoTransform(index); 262 } else { 263 if (s.hasSuperclassSignature()) { 264 setSuperClassOpt(new Opt(s.superclassSignature())); 265 } 266 if (s.hasSuperinterfaceSignature()) { 267 setImplementsList(s.superinterfaceSignature()); 268 } 269 return this; 270 } 271 } 272 273 public TypeDecl InterfaceDecl.makeGeneric(Signatures.ClassSignature s) { 274 if (s.hasFormalTypeParameters()) { 275 ASTNode node = getParent(); 276 int index = node.getIndexOfChild(this); 277 node.setChild( 278 new GenericInterfaceDecl( 279 getModifiersNoTransform(), 280 getID(), 281 s.hasSuperinterfaceSignature() 282 ? s.superinterfaceSignature() 283 : getSuperInterfaceListNoTransform(), 284 getBodyDeclListNoTransform(), 285 s.typeParameters() 286 ), 287 index 288 ); 289 return (TypeDecl) node.getChildNoTransform(index); 290 } else { 291 if (s.hasSuperinterfaceSignature()) { 292 setSuperInterfaceList(s.superinterfaceSignature()); 293 } 294 return this; 295 } 296 } 297 298 public TypeDecl GenericTypeDecl.makeGeneric(Signatures.ClassSignature s) { 299 return (TypeDecl) this; 300 } 301 302 interface ParTypeDecl { 303 //syn String name(); 304 int getNumArgument(); 305 Access getArgument(int index); 306 syn boolean isParameterizedType(); 307 syn boolean isRawType(); 308 public String typeName(); 309 SimpleSet localFields(String name); 310 Map<String,SimpleSet> localMethodsSignatureMap(); 311 } 312 313 ParClassDecl implements ParTypeDecl; 314 ParInterfaceDecl implements ParTypeDecl; 315 316 syn boolean TypeDecl.isParameterizedType() = false; 317 eq ParTypeDecl.isParameterizedType() = true; 318 319 syn boolean TypeDecl.isRawType() = isNestedType() && enclosingType().isRawType(); 320 eq ParClassDecl.isRawType() = isNestedType() && enclosingType().isRawType(); 321 eq ParInterfaceDecl.isRawType() = isNestedType() && enclosingType().isRawType(); 322 eq RawClassDecl.isRawType() = true; 323 eq RawInterfaceDecl.isRawType() = true; 324 } 325 326 aspect GenericsTypeAnalysis { 327 eq ParTypeAccess.unqualifiedScope() = 328 getParent() instanceof Access 329 ? ((Access) getParent()).unqualifiedScope() 330 : super.unqualifiedScope(); 331 332 eq ParTypeAccess.getTypeArgument().lookupType(String name) = unqualifiedScope().lookupType(name); 333 334 eq Program.getChild().inExtendsOrImplements() = false; 335 eq ClassDecl.getSuperClass().inExtendsOrImplements() = true; 336 eq ClassDecl.getImplements(int i).inExtendsOrImplements() = true; 337 eq InterfaceDecl.getSuperInterface().inExtendsOrImplements() = true; 338 inh boolean Expr.inExtendsOrImplements(); 339 340 eq ParTypeAccess.type() { 341 TypeDecl typeDecl = genericDecl(); 342 if (typeDecl instanceof GenericTypeDecl) { 343 // Use signature in lookup for types that are used in extends and implements clauses. 344 if (unqualifiedScope().inExtendsOrImplements()) { 345 return ((GenericTypeDecl) typeDecl).lookupParTypeDecl(this); 346 } 347 ArrayList<TypeDecl> args = new ArrayList<TypeDecl>(); 348 for (int i = 0; i < getNumTypeArgument(); i++) { 349 args.add(getTypeArgument(i).type()); 350 } 351 return ((GenericTypeDecl) typeDecl).lookupParTypeDecl(args); 352 } 353 return typeDecl; 354 } 355 356 syn TypeDecl ParTypeAccess.genericDecl() = getTypeAccess().type(); 357 358 eq ParTypeAccess.isTypeAccess() = true; 359 360 refine TypeScopePropagation eq TypeAccess.decl() { 361 TypeDecl decl = refined(); 362 if (decl instanceof GenericTypeDecl && isRaw()) { 363 return ((GenericTypeDecl) decl).lookupParTypeDecl(Collections.<TypeDecl>emptyList()); 364 } 365 return decl; 366 } 367 368 /** This method assumes that the bound type is generic. */ 369 public boolean TypeAccess.isRaw() { 370 /* 371 if (hasNextAccess()) { 372 return false; 373 } 374 */ 375 ASTNode parent = getParent(); 376 while (parent instanceof AbstractDot) { 377 parent = parent.getParent(); 378 } 379 if (parent instanceof ParTypeAccess) { 380 return false; 381 } 382 if (parent instanceof ImportDecl) { 383 return false; 384 } 385 /* 386 Access a = this; 387 while (a.isTypeAccess() && hasNextAccess()) { 388 a = a.nextAccess(); 389 } 390 if (a.isThisAccess() || a.isSuperAccess()) { 391 return false; 392 } 393 */ 394 return true; 395 } 396 397 refine TypeScopePropagation eq ThisAccess.decl() { 398 TypeDecl typeDecl = refined(); 399 if (typeDecl instanceof ParTypeDecl) { 400 typeDecl = ((ParTypeDecl) typeDecl).genericDecl(); 401 } 402 return typeDecl; 403 } 404 refine TypeScopePropagation eq SuperAccess.decl() { 405 TypeDecl typeDecl = refined(); 406 if (typeDecl instanceof ParTypeDecl) { 407 typeDecl = ((ParTypeDecl) typeDecl).genericDecl(); 408 } 409 return typeDecl; 410 } 411 412 public boolean BoundTypeAccess.isRaw() { 413 return getTypeDecl().isRawType(); 414 } 415 public boolean ParTypeAccess.isRaw() { 416 return false; 417 } 418 419 } 420 421 aspect GenericsErasure { 422 syn lazy TypeDecl TypeDecl.erasure() { 423 if (isAnonymous() || isLocalClass()) { 424 return this; 425 } 426 if (!isNestedType()) { 427 return this; 428 } 429 return extractSingleType(enclosingType().erasure().memberTypes(name())); 430 } 431 eq ParClassDecl.erasure() = genericDecl(); 432 eq ParInterfaceDecl.erasure() = genericDecl(); 433 eq TypeVariable.erasure() = getTypeBound(0).type().erasure(); // Skip last erasure? 434 eq ArrayDecl.erasure() = componentType().erasure().arrayType(); 435 } 436 437 aspect GenericsTypeCheck { 438 439 public void ArrayCreationExpr.typeCheck() { 440 super.typeCheck(); 441 442 if (!type().isReifiable()) { 443 error("can not create array with non-reifiable element type"); 444 } 445 } 446 447 refine TypeCheck 448 public void InstanceOfExpr.typeCheck() { 449 refined(); 450 if (!getTypeAccess().type().isReifiable()) { 451 error("right-hand side of instanceof expression must denote a reifiable type"); 452 } 453 } 454 455 // Different parameterizations of the same generic interface may not be implemented. 456 refine TypeHierarchyCheck public void TypeDecl.typeCheck() { 457 refined(); 458 ArrayList<InterfaceDecl> interfaceList = new ArrayList<InterfaceDecl>(); 459 interfaceList.addAll(implementedInterfaces()); 460 for (InterfaceDecl decl: interfaceList) { 461 if (decl instanceof ParInterfaceDecl) { 462 ParInterfaceDecl p = (ParInterfaceDecl) decl; 463 for (InterfaceDecl decl2: interfaceList) { 464 if (decl2 instanceof ParInterfaceDecl) { 465 ParInterfaceDecl q = (ParInterfaceDecl) decl2; 466 if (p != q && p.genericDecl() == q.genericDecl() && !p.sameArgument(q)) { 467 errorf("%s cannot be inherited with different type arguments: %s and %s", 468 p.genericDecl().name(), p.typeName(), q.typeName()); 469 } 470 } 471 } 472 } 473 } 474 475 // Check if a method has same signature as another in a supertype but does not override it. 476 Map<String,SimpleSet> map = erasedAncestorMethodsMap(); 477 for (Iterator iter1 = localMethodsIterator(); iter1.hasNext(); ) { 478 MethodDecl localMethod = (MethodDecl) iter1.next(); 479 480 String signature = localMethod.signature(); 481 482 SimpleSet set = map.get(signature); 483 if (set != null) { 484 for (Iterator i2 = set.iterator(); i2.hasNext(); ) { 485 MethodDecl decl = (MethodDecl) i2.next(); 486 if (!decl.signature().equals(signature)) { 487 localMethod.errorf("method %s in %s has the same erased signature as" 488 + " %s declared in %s but does not override it", 489 signature, typeName(), decl.signature(), decl.hostType().typeName()); 490 } 491 } 492 } 493 } 494 } 495 496 syn lazy Map<String,SimpleSet> TypeDecl.erasedAncestorMethodsMap() = 497 original().localMethodsSignatureMap(); 498 499 eq ClassDecl.erasedAncestorMethodsMap() { 500 Map<String,SimpleSet> localMap = localMethodsSignatureMap(); 501 Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(); 502 if (hasSuperclass()) { 503 for (Iterator<MethodDecl> iter = superclass().localMethodsIterator(); iter.hasNext(); ) { 504 MethodDecl m = iter.next(); 505 if (!m.isPrivate() && m.accessibleFrom(this) && m.erasedMethod() != m) { 506 // map erased signature to substituted method 507 putSimpleSetElement(map, m.erasedMethod().signature(), m); 508 } 509 } 510 mergeMap(map, superclass().erasedAncestorMethodsMap()); 511 } 512 for (Iterator<MethodDecl> iter = interfacesMethodsIterator(); iter.hasNext(); ) { 513 MethodDecl m = iter.next(); 514 if (m.accessibleFrom(this) && m.erasedMethod() != m) { 515 String erasedSignature = m.erasedMethod().signature(); 516 // map erased signature to substituted method 517 putSimpleSetElement(map, erasedSignature, m); 518 } 519 } 520 return map; 521 } 522 523 eq InterfaceDecl.erasedAncestorMethodsMap() { 524 Map<String,SimpleSet> localMap = localMethodsSignatureMap(); 525 Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(localMap); 526 for (Iterator<MethodDecl> iter = interfacesMethodsIterator(); iter.hasNext(); ) { 527 MethodDecl m = (MethodDecl) iter.next(); 528 if (m.accessibleFrom(this) && m.erasedMethod() != m) { 529 String erasedSignature = m.erasedMethod().signature(); 530 if (!localMap.containsKey(erasedSignature)) { 531 // map erased signature to substituted method 532 putSimpleSetElement(map, m.erasedMethod().signature(), m); 533 } 534 } 535 } 536 for (Iterator<MethodDecl> iter = typeObject().methodsIterator(); iter.hasNext(); ) { 537 MethodDecl m = (MethodDecl) iter.next(); 538 if (m.isPublic() && m.erasedMethod() != m) { 539 String erasedSignature = m.erasedMethod().signature(); 540 if (!localMap.containsKey(erasedSignature)) { 541 // map erased signature to substituted method 542 putSimpleSetElement(map, m.erasedMethod().signature(), m); 543 } 544 } 545 } 546 return map; 547 } 548 549 /** 550 * Merge the source map into the destination map. 551 * @param dest destination map 552 * @param src source map 553 */ 554 protected void TypeDecl.mergeMap(Map<String,SimpleSet> dest, Map<String,SimpleSet> src) { 555 for (Map.Entry<String,SimpleSet> entry: src.entrySet()) { 556 String signature = entry.getKey(); 557 for (Iterator iter = entry.getValue().iterator(); iter.hasNext(); ) { 558 putSimpleSetElement(dest, signature, (SimpleSet) iter.next()); 559 } 560 } 561 } 562 563 refine TypeHierarchyCheck 564 public void ClassDecl.typeCheck() { 565 refined(); 566 567 if (hasSuperclass()) { 568 // JLS SE7 8.4.8.4 569 // check for duplicate methods inherited from parameterized supertype 570 if (superclass().isParameterizedType()) { 571 Map<String,SimpleSet> localMap = localMethodsSignatureMap(); 572 Map<String,SimpleSet> methodMap = superclass().localMethodsSignatureMap(); 573 for (Map.Entry<String,SimpleSet> entry: methodMap.entrySet()) { 574 String signature = entry.getKey(); 575 if (!localMap.containsKey(signature)) { 576 // not locally overridden 577 SimpleSet set = entry.getValue(); 578 Iterator iter = set.iterator(); 579 iter.next(); 580 while (iter.hasNext()) { 581 MethodDecl m = (MethodDecl) iter.next(); 582 errorf("method with signature %s is multiply declared when inherited from %s", 583 signature, superclass().typeName()); 584 } 585 } 586 } 587 } 588 } 589 } 590 591 syn boolean ParTypeDecl.sameArgument(ParTypeDecl decl) { 592 if (this == decl) { 593 return true; 594 } 595 if (genericDecl() != decl.genericDecl()) { 596 return false; 597 } 598 for (int i = 0; i < getNumArgument(); i++) { 599 TypeDecl t1 = getArgument(i).type(); 600 TypeDecl t2 = decl.getArgument(i).type(); 601 if (t1 instanceof ParTypeDecl && t2 instanceof ParTypeDecl) { 602 if (!((ParTypeDecl) t1).sameArgument((ParTypeDecl) t2)) { 603 return false; 604 } 605 } else { 606 if (t1 != t2) { 607 return false; 608 } 609 } 610 } 611 return true; 612 } 613 614 syn lazy HashSet<InterfaceDecl> TypeDecl.implementedInterfaces() = new HashSet<InterfaceDecl>(); 615 616 eq ClassDecl.implementedInterfaces() { 617 HashSet set = new HashSet(); 618 if (hasSuperclass()) { 619 set.addAll(superclass().implementedInterfaces()); 620 } 621 for (Iterator<TypeDecl> iter = interfacesIterator(); iter.hasNext(); ) { 622 InterfaceDecl decl = (InterfaceDecl) iter.next(); 623 set.add(decl); 624 set.addAll(decl.implementedInterfaces()); 625 } 626 return set; 627 } 628 629 eq InterfaceDecl.implementedInterfaces() { 630 HashSet<InterfaceDecl> set= new HashSet<InterfaceDecl>(); 631 set.addAll(typeObject().implementedInterfaces()); 632 for (Iterator<TypeDecl> iter = interfacesIterator(); iter.hasNext(); ) { 633 InterfaceDecl decl = (InterfaceDecl) iter.next(); 634 set.add(decl); 635 set.addAll(decl.implementedInterfaces()); 636 } 637 return set; 638 } 639 640 public void GenericClassDecl.typeCheck() { 641 super.typeCheck(); 642 if (instanceOf(typeThrowable())) { 643 errorf("generic class %s may not directly or indirectly inherit java.lang.Throwable", 644 typeName()); 645 } 646 } 647 648 public void GenericInterfaceDecl.typeCheck() { 649 super.typeCheck(); 650 if (instanceOf(typeThrowable())) { 651 errorf("generic interface %s may not directly or indirectly inherit java.lang.Throwable", 652 typeName()); 653 } 654 } 655 656 inh TypeDecl GenericClassDecl.typeThrowable(); 657 inh TypeDecl GenericInterfaceDecl.typeThrowable(); 658 659 public void TypeAccess.typeCheck() { 660 TypeDecl type = type(); 661 if (type.isRawType() && type.isNestedType() 662 && type.enclosingType().isParameterizedType() 663 && !type.enclosingType().isRawType()) { 664 error("Can not access a member type of a paramterized type as a raw type"); 665 } 666 } 667 668 public void ParTypeAccess.typeCheck() { 669 super.typeCheck(); 670 if (!genericDecl().isUnknown()) { 671 TypeDecl type = type(); 672 if (!genericDecl().isGenericType()) { 673 errorf("%s is not a generic type but used as one in %s", 674 genericDecl().typeName(), this.prettyPrint()); 675 } else if (!type.isRawType() && type.isNestedType() && type.enclosingType().isRawType()) { 676 error("Can not access a member type of a raw type as a parameterized type"); 677 } else { 678 GenericTypeDecl decl = (GenericTypeDecl) genericDecl(); 679 GenericTypeDecl original = (GenericTypeDecl) decl.original(); 680 if (original.getNumTypeParameter() != getNumTypeArgument()) { 681 errorf("%s takes %d type parameters, not %d as used in %s", 682 decl.typeName(), original.getNumTypeParameter(), getNumTypeArgument(), 683 this.prettyPrint()); 684 } else { 685 for (int i = 0; i < getNumTypeArgument(); i++) { 686 if (!getTypeArgument(i).type().withinBounds(original.getTypeParameter(i), 687 (Parameterization) type())) { 688 errorf("type argument %s is of type %s which is not within" 689 + " the bounds of type parameter %s (%s)", 690 i, getTypeArgument(i).type().typeName(), original.getTypeParameter(i).typeName(), 691 original.getTypeParameter(i).prettyPrint()); 692 } 693 } 694 } 695 } 696 } 697 } 698 699 } 700 701 aspect GenericsNameBinding { 702 703 eq ParClassDecl.getArgument().nameType() = NameType.TYPE_NAME; 704 eq ParInterfaceDecl.getArgument().nameType() = NameType.TYPE_NAME; 705 eq ParTypeAccess.getChild().nameType() = NameType.TYPE_NAME; 706 707 //eq GenericClassDecl.getParTypeDecl().isNestedType() = isNestedType(); 708 //eq GenericClassDecl.getParTypeDecl().enclosingType() = enclosingType(); 709 eq GenericClassDecl.getTypeParameter().isNestedType() = true; 710 eq GenericClassDecl.getTypeParameter().enclosingType() = this; 711 712 //eq GenericInterfaceDecl.getParTypeDecl().isNestedType() = isNestedType(); 713 //eq GenericInterfaceDecl.getParTypeDecl().enclosingType() = enclosingType(); 714 eq GenericInterfaceDecl.getTypeParameter().isNestedType() = true; 715 eq GenericInterfaceDecl.getTypeParameter().enclosingType() = this; 716 717 public SimpleSet GenericTypeDecl.addTypeVariables(SimpleSet c, String name) { 718 GenericTypeDecl original = (GenericTypeDecl) original(); 719 for (int i = 0; i < original.getNumTypeParameter(); i++) { 720 TypeVariable p = original.getTypeParameter(i); 721 if (p.name().equals(name)) { 722 c = c.add(p); 723 } 724 } 725 return c; 726 } 727 728 eq GenericInterfaceDecl.getSuperInterface().lookupType(String name) { 729 SimpleSet c = addTypeVariables(SimpleSet.emptySet, name); 730 return !c.isEmpty() ? c : lookupType(name); 731 } 732 eq GenericClassDecl.getSuperClass().lookupType(String name) { 733 SimpleSet c = addTypeVariables(SimpleSet.emptySet, name); 734 return !c.isEmpty() ? c : lookupType(name); 735 } 736 eq GenericClassDecl.getImplements().lookupType(String name) { 737 SimpleSet c = addTypeVariables(SimpleSet.emptySet, name); 738 return !c.isEmpty() ? c : lookupType(name); 739 } 740 741 eq GenericTypeDecl.getTypeParameter().lookupType(String name) { 742 SimpleSet c = memberTypes(name); 743 c = addTypeVariables(c, name); 744 if (!c.isEmpty()) { 745 return c; 746 } 747 // 8.5.2 748 if (isClassDecl() && isStatic() && !isTopLevelType()) { 749 for (Iterator iter = lookupType(name).iterator(); iter.hasNext(); ) { 750 TypeDecl d = (TypeDecl) iter.next(); 751 if (d.isStatic() || (d.enclosingType() != null && instanceOf(d.enclosingType()))) { 752 c = c.add(d); 753 } 754 } 755 } else { 756 c = lookupType(name); 757 } 758 if (!c.isEmpty()) { 759 return c; 760 } 761 return topLevelType().lookupType(name); // Fix to search imports 762 } 763 eq GenericTypeDecl.getBodyDecl(int index).lookupType(String name) { 764 SimpleSet c = memberTypes(name); 765 if (getBodyDecl(index).visibleTypeParameters()) { 766 c = addTypeVariables(c, name); 767 } 768 if (!c.isEmpty()) { 769 return c; 770 } 771 // 8.5.2 772 if (isClassDecl() && isStatic() && !isTopLevelType()) { 773 for (Iterator iter = lookupType(name).iterator(); iter.hasNext(); ) { 774 TypeDecl d = (TypeDecl) iter.next(); 775 if (d.isStatic() || (d.enclosingType() != null && instanceOf(d.enclosingType()))) { 776 c = c.add(d); 777 } 778 } 779 } else { 780 c = lookupType(name); 781 } 782 if (!c.isEmpty()) { 783 return c; 784 } 785 return topLevelType().lookupType(name); // Fix to search imports 786 // include type parameters if not static 787 } 788 789 public void ParClassDecl.collectErrors() { 790 // Disable error check for ParClassDecl which is an instanciated GenericClassDecl 791 } 792 public void ParInterfaceDecl.collectErrors() { 793 // Disable error check for ParInterfaceDecl which is an instanciated GenericInterfaceDecl 794 } 795 796 } 797 aspect LookupParTypeDecl { 798 eq TypeVariable.fullName() { 799 if (getParent().getParent() instanceof TypeDecl) { 800 TypeDecl typeDecl = (TypeDecl) getParent().getParent(); 801 return typeDecl.fullName() + "@" + name(); 802 } 803 return super.fullName(); 804 } 805 806 syn boolean TypeDecl.sameSignature(Access a) { 807 if (a instanceof ParTypeAccess) { 808 return false; 809 } 810 if (a instanceof AbstractWildcard) { 811 return false; 812 } 813 return this == a.type(); 814 } 815 eq TypeVariable.sameSignature(Access a) = a.type() == this; 816 syn boolean ParTypeDecl.sameSignature(Access a){ 817 if (a instanceof ParTypeAccess) { 818 ParTypeAccess ta = (ParTypeAccess) a; 819 if (genericDecl() != ta.genericDecl()) { 820 return false; 821 } 822 if (getNumArgument() != ta.getNumTypeArgument()) { 823 return false; 824 } 825 for (int i = 0; i < getNumArgument(); i++) { 826 if (!getArgument(i).type().sameSignature(ta.getTypeArgument(i))) { 827 return false; 828 } 829 } 830 return true; 831 } else if (a instanceof TypeAccess && ((TypeAccess) a).isRaw()) { 832 return false; 833 } 834 return super.sameSignature(a); 835 } 836 eq RawClassDecl.sameSignature(Access a) = a instanceof TypeAccess && a.type() == this; 837 eq RawInterfaceDecl.sameSignature(Access a) = a instanceof TypeAccess && a.type() == this; 838 839 eq WildcardType.sameSignature(Access a) { 840 if (a instanceof Wildcard) { 841 return true; 842 } 843 return super.sameSignature(a); 844 } 845 eq WildcardExtendsType.sameSignature(Access a) { 846 if (a instanceof WildcardExtends) { 847 return getAccess().type().sameSignature(((WildcardExtends) a).getAccess()); 848 } 849 return super.sameSignature(a); 850 } 851 eq WildcardSuperType.sameSignature(Access a) { 852 if (a instanceof WildcardSuper) { 853 return getAccess().type().sameSignature(((WildcardSuper) a).getAccess()); 854 } 855 return super.sameSignature(a); 856 } 857 858 syn lazy boolean ParTypeDecl.sameSignature(java.util.List<TypeDecl> list) circular [true] { 859 if (getNumArgument() != list.size()) { 860 return false; 861 } 862 for (int i = 0; i < list.size(); i++) { 863 if (getArgument(i).type() != list.get(i)) { 864 return false; 865 } 866 } 867 return true; 868 } 869 870 /** Transforms the parameter and calls the lookupParTypeDecl attribute for ArrayList arguments. */ 871 syn lazy TypeDecl GenericTypeDecl.lookupParTypeDecl(ParTypeAccess p) { 872 Collection<TypeDecl> typeArguments = new ArrayList<TypeDecl>(); 873 for (int i = 0; i < p.getNumTypeArgument(); i++) { 874 typeArguments.add(p.getTypeArgument(i).type()); 875 } 876 return lookupParTypeDecl(typeArguments); 877 } 878 879 syn nta TypeDecl GenericTypeDecl.lookupParTypeDecl(Collection<TypeDecl> typeArgs); 880 881 eq GenericClassDecl.lookupParTypeDecl(Collection<TypeDecl> typeArgs) { 882 ParClassDecl typeDecl = typeArgs.size() == 0 ? new RawClassDecl() : new ParClassDecl(); 883 typeDecl.setModifiers((Modifiers) getModifiers().treeCopyNoTransform()); 884 typeDecl.setID(getID()); 885 // ES: trying to only do this for ParClassDecl and then later for RawClassDecl 886 if (!(typeDecl instanceof RawClassDecl)) { 887 typeDecl.setArgumentList(createArgumentList(typeArgs)); 888 } 889 return typeDecl; 890 } 891 892 eq GenericInterfaceDecl.lookupParTypeDecl(Collection<TypeDecl> typeArgs) { 893 ParInterfaceDecl typeDecl = typeArgs.size() == 0 894 ? new RawInterfaceDecl() 895 : new ParInterfaceDecl(); 896 typeDecl.setModifiers((Modifiers) getModifiers().treeCopyNoTransform()); 897 typeDecl.setID(getID()); 898 // ES: trying to only do this for ParInterfaceDecl and then later for RawInterfaceDecl 899 if (!(typeDecl instanceof RawInterfaceDecl)) { 900 typeDecl.setArgumentList(createArgumentList(typeArgs)); 901 } 902 return typeDecl; 903 } 904 905 // TODO(jesper): remove final 906 syn lazy final List RawClassDecl.getArgumentList() = 907 ((GenericClassDecl) genericDecl()).createArgumentList(Collections.<TypeDecl>emptyList()); 908 909 // TODO(jesper): remove final 910 syn lazy final List RawInterfaceDecl.getArgumentList() = 911 ((GenericInterfaceDecl) genericDecl()).createArgumentList(Collections.<TypeDecl>emptyList()); 912 913 public List GenericTypeDecl.createArgumentList(Collection<TypeDecl> args) { 914 GenericTypeDecl original = (GenericTypeDecl) original(); 915 List<Access> list = new List<Access>(); 916 if (args.isEmpty()) { 917 // Change: Don't add any thing to the list. 918 // Concern: The previous version seem to add the erasure of the type variable for some reason, 919 // maybe this is how the raw type is represented (?), but this doesn't really comply with the 920 // claim that raw types don't have any type variables...? 921 for (int i = 0; i < original.getNumTypeParameter(); i++) { 922 list.add(original.getTypeParameter(i).erasure().createBoundAccess()); 923 } 924 } else { 925 for (TypeDecl arg : args) { 926 list.add(arg.createBoundAccess()); 927 } 928 } 929 return list; 930 } 931 932 interface Parameterization { 933 boolean isRawType(); 934 TypeDecl substitute(TypeVariable typeVariable); 935 } 936 937 ParTypeDecl implements Parameterization; 938 939 interface MemberSubstitutor extends Parameterization { 940 TypeDecl original(); 941 void addBodyDecl(BodyDecl b); 942 TypeDecl substitute(TypeVariable typeVariable); 943 } 944 945 ParClassDecl implements MemberSubstitutor; 946 ParInterfaceDecl implements MemberSubstitutor; 947 ClassDeclSubstituted implements MemberSubstitutor; 948 InterfaceDeclSubstituted implements MemberSubstitutor; 949 GenericClassDeclSubstituted implements MemberSubstitutor; 950 GenericInterfaceDeclSubstituted implements MemberSubstitutor; 951 952 public TypeDecl TypeDecl.substitute(TypeVariable typeVariable) { 953 if (isTopLevelType()) { 954 return typeVariable; 955 } 956 return enclosingType().substitute(typeVariable); 957 } 958 959 public TypeDecl ParTypeDecl.substitute(TypeVariable typeVariable) { 960 for (int i = 0; i < numTypeParameter(); i++) { 961 if (typeParameter(i) == typeVariable) { 962 return getArgument(i).type(); 963 } 964 } 965 return super.substitute(typeVariable); 966 } 967 968 public TypeDecl ParMethodDecl.substitute(TypeVariable typeVariable) { 969 for (int i = 0; i < numTypeParameter(); i++) { 970 if (typeParameter(i) == typeVariable) { 971 return getTypeArgument(i).type(); 972 } 973 } 974 return genericMethodDecl().hostType().substitute(typeVariable); 975 } 976 977 public boolean ParConstructorDecl.isRawType() { 978 return false; 979 } 980 981 public TypeDecl ParConstructorDecl.substitute(TypeVariable typeVariable) { 982 for (int i = 0; i < numTypeParameter(); i++) { 983 if (typeParameter(i) == typeVariable) { 984 return getTypeArgument(i).type(); 985 } 986 } 987 return genericConstructorDecl().hostType().substitute(typeVariable); 988 } 989 990 public int ParTypeDecl.numTypeParameter() { 991 return ((GenericTypeDecl) original()).getNumTypeParameter(); 992 } 993 994 public TypeVariable ParTypeDecl.typeParameter(int index) { 995 return ((GenericTypeDecl) original()).getTypeParameter(index); 996 } 997 998 ParMethodDecl implements Parameterization; 999 ParConstructorDecl implements Parameterization; 1000 1001 public boolean ParMethodDecl.isRawType() { 1002 return false; 1003 } 1004 1005 public boolean RawMethodDecl.isRawType() { 1006 return true; 1007 } 1008 1009 public int ParMethodDecl.numTypeParameter() { 1010 return genericMethodDecl().original().getNumTypeParameter(); 1011 } 1012 1013 public int ParConstructorDecl.numTypeParameter() { 1014 return genericConstructorDecl().original().getNumTypeParameter(); 1015 } 1016 1017 public TypeVariable ParMethodDecl.typeParameter(int index) { 1018 return genericMethodDecl().original().getTypeParameter(index); 1019 } 1020 1021 public TypeVariable ParConstructorDecl.typeParameter(int index) { 1022 return genericConstructorDecl().original().getTypeParameter(index); 1023 } 1024 1025 public Access TypeDecl.substitute(Parameterization parTypeDecl) { 1026 if (parTypeDecl instanceof ParTypeDecl && ((ParTypeDecl) parTypeDecl).genericDecl() == this) { 1027 return ((TypeDecl) parTypeDecl).createBoundAccess(); 1028 } 1029 if (isTopLevelType()) { 1030 return createBoundAccess(); 1031 } 1032 return enclosingType().substitute(parTypeDecl).qualifiesAccess(new TypeAccess(name())); 1033 } 1034 1035 public Access ArrayDecl.substitute(Parameterization parTypeDecl) { 1036 return new ArrayTypeAccess(componentType().substitute(parTypeDecl)); 1037 } 1038 1039 public Access TypeVariable.substitute(Parameterization parTypeDecl) { 1040 if (parTypeDecl.isRawType()) { 1041 return erasure().createBoundAccess(); 1042 } 1043 return parTypeDecl.substitute(this).createBoundAccess(); 1044 } 1045 1046 public Access ParTypeDecl.substitute(Parameterization parTypeDecl) { 1047 // TODO: include nesting as well.... 1048 if (parTypeDecl.isRawType()) { 1049 return ((GenericTypeDecl) genericDecl()).rawType().createBoundAccess(); 1050 } 1051 if (!usesTypeVariable()) { 1052 return super.substitute(parTypeDecl); 1053 } 1054 List<Access> list = new List<Access>(); 1055 for (Access argument : getArgumentList()) { 1056 //System.err.println("substituting " + argument.type().typeName() + " with " + parTypeDecl); 1057 list.add(argument.type().substitute(parTypeDecl)); 1058 } 1059 return new ParTypeAccess(genericDecl().createQualifiedAccess(), list); 1060 } 1061 1062 public Access RawClassDecl.substitute(Parameterization parTypeDecl) { 1063 return createBoundAccess(); 1064 } 1065 1066 public Access RawInterfaceDecl.substitute(Parameterization parTypeDecl) { 1067 return createBoundAccess(); 1068 } 1069 1070 public Access WildcardExtendsType.substitute(Parameterization parTypeDecl) { 1071 if (!usesTypeVariable()) { 1072 return super.substitute(parTypeDecl); 1073 } 1074 return new WildcardExtends(getAccess().type().substitute(parTypeDecl)); 1075 } 1076 1077 public Access WildcardSuperType.substitute(Parameterization parTypeDecl) { 1078 if (!usesTypeVariable()) { 1079 return super.substitute(parTypeDecl); 1080 } 1081 return new WildcardSuper(getAccess().type().substitute(parTypeDecl)); 1082 } 1083 1084 public Access TypeDecl.substituteReturnType(Parameterization parTypeDecl) { 1085 return substitute(parTypeDecl); 1086 } 1087 1088 public Access ArrayDecl.substituteReturnType(Parameterization parTypeDecl) { 1089 return new ArrayTypeAccess(componentType().substituteReturnType(parTypeDecl)); 1090 } 1091 1092 inh TypeDecl TypeVariable.typeObject(); 1093 1094 syn lazy TypeDecl TypeVariable.lubType() { 1095 ArrayList<TypeDecl> list = new ArrayList<TypeDecl>(); 1096 for (int i = 0; i < getNumTypeBound(); i++) { 1097 list.add(getTypeBound(i).type()); 1098 } 1099 return lookupLUBType(list); 1100 } 1101 1102 public Access TypeVariable.substituteReturnType(Parameterization parTypeDecl) { 1103 if (parTypeDecl.isRawType()) { 1104 return erasure().createBoundAccess(); 1105 } 1106 TypeDecl typeDecl = parTypeDecl.substitute(this); 1107 if (typeDecl instanceof WildcardType) { 1108 // The bound of this type variable 1109 return createBoundAccess(); 1110 //return lubType().createBoundAccess(); 1111 //return typeObject().createBoundAccess(); 1112 } else if (typeDecl instanceof WildcardExtendsType) { 1113 if (typeDecl.instanceOf(this)) { 1114 return ((WildcardExtendsType) typeDecl).extendsType().createBoundAccess(); 1115 } else { 1116 return createBoundAccess(); 1117 } 1118 1119 // the bound of this type variable of the bound of the wild card if it is more specific 1120 //return ((WildcardExtendsType) typeDecl).extendsType().createBoundAccess(); 1121 } else if (typeDecl instanceof WildcardSuperType) { 1122 // the bound of this type variable 1123 return createBoundAccess(); 1124 //return typeObject().createBoundAccess(); 1125 } 1126 return typeDecl.createBoundAccess(); 1127 } 1128 1129 public Access RawClassDecl.substituteReturnType(Parameterization parTypeDecl) { 1130 return createBoundAccess(); 1131 } 1132 1133 public Access RawInterfaceDecl.substituteReturnType(Parameterization parTypeDecl) { 1134 return createBoundAccess(); 1135 } 1136 1137 public Access TypeDecl.substituteParameterType(Parameterization parTypeDecl) { 1138 return substitute(parTypeDecl); 1139 } 1140 1141 inh TypeDecl TypeVariable.typeNull(); 1142 public Access TypeVariable.substituteParameterType(Parameterization parTypeDecl) { 1143 if (parTypeDecl.isRawType()) { 1144 return erasure().createBoundAccess(); 1145 } 1146 TypeDecl typeDecl = parTypeDecl.substitute(this); 1147 if (typeDecl instanceof WildcardType) { 1148 return typeNull().createQualifiedAccess(); 1149 } else if (typeDecl instanceof WildcardExtendsType) { 1150 return typeNull().createQualifiedAccess(); 1151 } else if (typeDecl instanceof WildcardSuperType) { 1152 return ((WildcardSuperType) typeDecl).superType().createBoundAccess(); 1153 } 1154 return typeDecl.createBoundAccess(); 1155 } 1156 1157 public Access RawClassDecl.substituteParameterType(Parameterization parTypeDecl) { 1158 return createBoundAccess(); 1159 } 1160 1161 public Access RawInterfaceDecl.substituteParameterType(Parameterization parTypeDecl) { 1162 return createBoundAccess(); 1163 } 1164 1165 public List List.substitute(Parameterization parTypeDecl) { 1166 List list = new List(); 1167 for (int i = 0; i < getNumChild(); i++) { 1168 ASTNode node = getChild(i); 1169 if (node instanceof Access) { 1170 Access a = (Access) node; 1171 list.add(a.type().substitute(parTypeDecl)); 1172 } else if (node instanceof VariableArityParameterDeclaration) { 1173 VariableArityParameterDeclaration p = (VariableArityParameterDeclaration) node; 1174 list.add( 1175 new VariableArityParameterDeclarationSubstituted( 1176 (Modifiers) p.getModifiers().treeCopyNoTransform(), 1177 // use the type acces since VariableArity adds to the dimension 1178 p.getTypeAccess().type().substituteParameterType(parTypeDecl), 1179 p.getID(), 1180 p 1181 ) 1182 ); 1183 } else if (node instanceof ParameterDeclaration) { 1184 ParameterDeclaration p = (ParameterDeclaration) node; 1185 list.add( 1186 new ParameterDeclarationSubstituted( 1187 (Modifiers) p.getModifiers().treeCopyNoTransform(), 1188 p.type().substituteParameterType(parTypeDecl), 1189 p.getID(), 1190 p 1191 ) 1192 ); 1193 } else { 1194 throw new Error("Can only substitute lists of access nodes but node number " 1195 + i + " is of type " + node.getClass().getName()); 1196 } 1197 } 1198 return list; 1199 } 1200 1201 syn lazy Opt ParClassDecl.getSuperClassOpt() { 1202 GenericClassDecl decl = (GenericClassDecl) genericDecl(); 1203 Opt opt; 1204 //System.err.println("Begin substituting extends clause"); 1205 if (decl.hasSuperClass()) { 1206 opt = new Opt((decl.getSuperClass().type().substitute(this))); 1207 } else { 1208 opt = new Opt(); 1209 } 1210 //System.err.println("End substituting extends clause"); 1211 return opt; 1212 } 1213 1214 syn lazy List ParClassDecl.getImplementsList() { 1215 GenericClassDecl decl = (GenericClassDecl) genericDecl(); 1216 //System.err.println("Begin substituting implements list"); 1217 List list = decl.getImplementsList().substitute(this); 1218 //System.err.println("End substituting implements list"); 1219 return list; 1220 } 1221 1222 syn lazy List ParClassDecl.getBodyDeclList() = new BodyDeclList(); 1223 1224 syn lazy List ParInterfaceDecl.getSuperInterfaceList() { 1225 GenericInterfaceDecl decl = (GenericInterfaceDecl) genericDecl(); 1226 //System.err.println("Begin substituting implements list"); 1227 List list = decl.getSuperInterfaceList().substitute(this); 1228 //System.err.println("End substituting implements list"); 1229 return list; 1230 } 1231 1232 syn lazy List ParInterfaceDecl.getBodyDeclList() = new BodyDeclList(); 1233 1234 syn lazy List ClassDeclSubstituted.getBodyDeclList() = new BodyDeclList(); 1235 syn lazy List InterfaceDeclSubstituted.getBodyDeclList() = new BodyDeclList(); 1236 syn lazy List GenericClassDeclSubstituted.getBodyDeclList() = new BodyDeclList(); 1237 syn lazy List GenericInterfaceDeclSubstituted.getBodyDeclList() = new BodyDeclList(); 1238 1239 1240 syn boolean ASTNode.usesTypeVariable() { 1241 for (int i = 0; i < getNumChild(); i++) { 1242 if (getChild(i).usesTypeVariable()) { 1243 return true; 1244 } 1245 } 1246 return false; 1247 } 1248 1249 syn lazy boolean MethodDecl.usesTypeVariable() = 1250 getModifiers().usesTypeVariable() || getTypeAccess().usesTypeVariable() 1251 || getParameterList().usesTypeVariable() || getExceptionList().usesTypeVariable(); 1252 1253 syn lazy boolean FieldDeclaration.usesTypeVariable() = getTypeAccess().usesTypeVariable(); 1254 1255 eq TypeAccess.usesTypeVariable() = decl().usesTypeVariable() || super.usesTypeVariable(); 1256 1257 syn lazy boolean TypeDecl.usesTypeVariable() circular [false] = 1258 isNestedType() && enclosingType().usesTypeVariable(); 1259 1260 eq ParTypeDecl.usesTypeVariable() { 1261 if (super.usesTypeVariable()) { 1262 return true; 1263 } 1264 for (int i = 0; i < getNumArgument(); i++) 1265 if (getArgument(i).type().usesTypeVariable()) { 1266 return true; 1267 } 1268 return false; 1269 } 1270 1271 eq GenericClassDecl.usesTypeVariable() = true; 1272 eq GenericInterfaceDecl.usesTypeVariable() = true; 1273 eq TypeVariable.usesTypeVariable() = true; 1274 eq WildcardExtendsType.usesTypeVariable() = getAccess().type().usesTypeVariable(); 1275 eq WildcardSuperType.usesTypeVariable() = getAccess().type().usesTypeVariable(); 1276 eq ArrayDecl.usesTypeVariable() = elementType().usesTypeVariable(); 1277 1278 syn lazy final Map<String,SimpleSet> MemberSubstitutor.localMethodsSignatureMap() { 1279 Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(); 1280 for (Iterator<MethodDecl> iter = original().localMethodsIterator(); iter.hasNext(); ) { 1281 MethodDecl decl = iter.next(); 1282 1283 if (!decl.isStatic() && (decl.usesTypeVariable() || isRawType())) { 1284 BodyDecl copyDecl = ((BodyDeclList) getBodyDeclList()).localMethodSignatureCopy(decl, this); 1285 decl = (MethodDecl) copyDecl; 1286 } 1287 putSimpleSetElement(map, decl.signature(), decl); 1288 1289 } 1290 return map; 1291 } 1292 1293 syn nta BodyDecl BodyDeclList.localMethodSignatureCopy(MethodDecl originalMethod, 1294 MemberSubstitutor m) = originalMethod.substitutedBodyDecl(m); 1295 1296 syn lazy final SimpleSet MemberSubstitutor.localFields(String name) { 1297 SimpleSet set = SimpleSet.emptySet; 1298 for (Iterator iter = original().localFields(name).iterator(); iter.hasNext(); ) { 1299 FieldDeclaration f = (FieldDeclaration) iter.next(); 1300 1301 if (!f.isStatic() && (f.usesTypeVariable() || isRawType())) { 1302 BodyDecl fCopy = ((BodyDeclList) getBodyDeclList()).localFieldCopy(f, this); 1303 f = (FieldDeclaration) fCopy; 1304 } 1305 set = set.add(f); 1306 1307 } 1308 return set; 1309 } 1310 1311 syn nta BodyDecl BodyDeclList.localFieldCopy(FieldDeclaration originalDecl, MemberSubstitutor m) = 1312 originalDecl.substitutedBodyDecl(m); 1313 1314 // TODO-ES: Add NTA for copies like above 1315 syn lazy final SimpleSet MemberSubstitutor.localTypeDecls(String name) circular [SimpleSet.emptySet] { 1316 SimpleSet set = SimpleSet.emptySet; 1317 for (Iterator iter = original().localTypeDecls(name).iterator(); iter.hasNext(); ) { 1318 TypeDecl t = (TypeDecl) iter.next(); 1319 1320 if (t.isStatic()) { 1321 set = set.add(t); 1322 } else if (t instanceof ClassDecl) { 1323 MemberClassDecl copy = 1324 ((BodyDeclList) getBodyDeclList()).localClassDeclCopy((ClassDecl) t, this); 1325 set = set.add(copy.getClassDecl()); 1326 } else if (t instanceof InterfaceDecl) { 1327 MemberInterfaceDecl copy = 1328 ((BodyDeclList) getBodyDeclList()).localInterfaceDeclCopy((InterfaceDecl) t, this); 1329 set = set.add(copy.getInterfaceDecl()); 1330 } 1331 } 1332 return set; 1333 } 1334 1335 // ES: adding NTA to store copies in 1336 syn nta MemberClassDecl BodyDeclList.localClassDeclCopy(ClassDecl originalDecl, MemberSubstitutor m) { 1337 ClassDecl copy = originalDecl.substitutedClassDecl(m); 1338 return new MemberClassDecl(copy); 1339 } 1340 1341 syn nta MemberInterfaceDecl BodyDeclList.localInterfaceDeclCopy(InterfaceDecl originalDecl, 1342 MemberSubstitutor m) { 1343 InterfaceDecl copy = originalDecl.substitutedInterfaceDecl(m); 1344 return new MemberInterfaceDecl(copy); 1345 } 1346 1347 syn lazy Collection<ConstructorDecl> MemberSubstitutor.constructors() { 1348 Collection<ConstructorDecl> constructors = new ArrayList<ConstructorDecl>(); 1349 for (Iterator iter = original().constructors().iterator(); iter.hasNext(); ) { 1350 ConstructorDecl c = (ConstructorDecl) iter.next(); 1351 1352 ConstructorDecl b = ((BodyDeclList) getBodyDeclList()).constructorCopy(c, this); 1353 constructors.add(b); 1354 } 1355 return constructors; 1356 } 1357 1358 syn nta ConstructorDecl BodyDeclList.constructorCopy(ConstructorDecl originalDecl, 1359 MemberSubstitutor m) = originalDecl.substitutedBodyDecl(m); 1360 1361 public BodyDecl BodyDecl.substitutedBodyDecl(Parameterization parTypeDecl) { 1362 throw new Error("Operation substitutedBodyDecl not supported for " + getClass().getName()); 1363 } 1364 1365 public BodyDecl MethodDecl.substitutedBodyDecl(Parameterization parTypeDecl) { 1366 MethodDecl m = new MethodDeclSubstituted( 1367 (Modifiers) getModifiers().treeCopyNoTransform(), 1368 getTypeAccess().type().substituteReturnType(parTypeDecl), 1369 getID(), 1370 getParameterList().substitute(parTypeDecl), 1371 getExceptionList().substitute(parTypeDecl), 1372 substituteBody(parTypeDecl), 1373 this 1374 ); 1375 return m; 1376 } 1377 1378 public Opt MethodDecl.substituteBody(Parameterization parTypeDecl) { 1379 return new Opt(); 1380 } 1381 1382 syn GenericMethodDecl GenericMethodDecl.original() = original != null ? original : this; 1383 public GenericMethodDecl GenericMethodDecl.original; 1384 1385 syn GenericConstructorDecl GenericConstructorDecl.original() = original != null ? original : this; 1386 public GenericConstructorDecl GenericConstructorDecl.original; 1387 1388 public ConstructorDecl ConstructorDecl.substitutedBodyDecl(Parameterization parTypeDecl) { 1389 return new ConstructorDeclSubstituted( 1390 (Modifiers) getModifiers().treeCopyNoTransform(), 1391 getID(), 1392 getParameterList().substitute(parTypeDecl), 1393 getExceptionList().substitute(parTypeDecl), 1394 new Opt(), 1395 new Block(), 1396 this 1397 ); 1398 } 1399 1400 public BodyDecl FieldDeclaration.substitutedBodyDecl(Parameterization parTypeDecl) { 1401 return new FieldDeclarationSubstituted( 1402 (Modifiers) getModifiers().treeCopyNoTransform(), 1403 getTypeAccess().type().substituteReturnType(parTypeDecl), 1404 getID(), 1405 new Opt(), 1406 this 1407 ); 1408 } 1409 1410 syn FieldDeclaration FieldDeclaration.erasedField() = this; 1411 eq FieldDeclarationSubstituted.erasedField() = getOriginal().erasedField(); 1412 1413 syn MethodDecl MethodDecl.erasedMethod() = this; 1414 eq MethodDeclSubstituted.erasedMethod() = getOriginal().erasedMethod(); 1415 eq ParMethodDecl.erasedMethod() = genericMethodDecl().erasedMethod(); 1416 1417 syn TypeDecl TypeDecl.original() = this; 1418 eq ClassDeclSubstituted.original() = getOriginal().original(); 1419 eq InterfaceDeclSubstituted.original() = getOriginal().original(); 1420 eq GenericClassDeclSubstituted.original() = getOriginal().original(); 1421 eq GenericInterfaceDeclSubstituted.original() = getOriginal().original(); 1422 eq ParTypeDecl.original() = genericDecl().original(); 1423 1424 public ClassDecl ClassDecl.substitutedClassDecl(Parameterization parTypeDecl) { 1425 return new ClassDeclSubstituted( 1426 (Modifiers) getModifiers().treeCopyNoTransform(), 1427 getID(), 1428 hasSuperClass() ? new Opt(getSuperClass().type().substitute(parTypeDecl)) : new Opt(), 1429 getImplementsList().substitute(parTypeDecl), 1430 this 1431 ); 1432 } 1433 1434 public ClassDecl GenericClassDecl.substitutedClassDecl(Parameterization parTypeDecl) { 1435 return new GenericClassDeclSubstituted( 1436 (Modifiers) getModifiers().treeCopyNoTransform(), 1437 getID(), 1438 hasSuperClass() ? new Opt(getSuperClass().type().substitute(parTypeDecl)) : new Opt(), 1439 getImplementsList().substitute(parTypeDecl), 1440 new List(), // delegates TypeParameter lookup to original 1441 this 1442 ); 1443 } 1444 1445 public InterfaceDecl InterfaceDecl.substitutedInterfaceDecl(Parameterization parTypeDecl) { 1446 return new InterfaceDeclSubstituted( 1447 (Modifiers) getModifiers().treeCopyNoTransform(), 1448 getID(), 1449 getSuperInterfaceList().substitute(parTypeDecl), 1450 this 1451 ); 1452 } 1453 1454 public InterfaceDecl GenericInterfaceDecl.substitutedInterfaceDecl(Parameterization parTypeDecl) { 1455 return new GenericInterfaceDeclSubstituted( 1456 (Modifiers) getModifiers().treeCopyNoTransform(), 1457 getID(), 1458 getSuperInterfaceList().substitute(parTypeDecl), 1459 new List(), // delegates TypeParameter lookup to original 1460 this 1461 ); 1462 } 1463 1464 syn nta WildcardsCompilationUnit Program.wildcards() { 1465 return new WildcardsCompilationUnit( 1466 "wildcards", 1467 new List(), 1468 new List() 1469 ); 1470 } 1471 1472 syn TypeDecl WildcardExtendsType.extendsType() = getAccess().type(); 1473 syn TypeDecl WildcardSuperType.superType() = getAccess().type(); 1474 1475 eq Wildcard.type() = typeWildcard(); 1476 eq WildcardExtends.type() = lookupWildcardExtends(getAccess().type()); 1477 eq WildcardSuper.type() = lookupWildcardSuper(getAccess().type()); 1478 inh TypeDecl WildcardSuper.lookupWildcardSuper(TypeDecl typeDecl); 1479 inh TypeDecl WildcardExtends.lookupWildcardExtends(TypeDecl typeDecl); 1480 inh TypeDecl Wildcard.typeWildcard(); 1481 1482 syn nta TypeDecl WildcardsCompilationUnit.typeWildcard() = 1483 new WildcardType( 1484 new Modifiers(new List().add(new Modifier("public"))), 1485 "?", 1486 new List()); 1487 1488 inh TypeDecl TypeDecl.typeWildcard(); 1489 1490 eq Program.getChild().typeWildcard() = wildcards().typeWildcard(); 1491 1492 syn nta TypeDecl WildcardsCompilationUnit.lookupWildcardExtends(TypeDecl bound) = 1493 new WildcardExtendsType( 1494 new Modifiers(new List().add(new Modifier("public"))), 1495 "? extends " + bound.fullName(), 1496 new List(), 1497 bound.createBoundAccess()); 1498 1499 eq Program.getChild().lookupWildcardExtends(TypeDecl typeDecl) = 1500 wildcards().lookupWildcardExtends(typeDecl); 1501 1502 inh TypeDecl TypeDecl.lookupWildcardExtends(TypeDecl typeDecl); 1503 1504 syn TypeDecl TypeDecl.asWildcardExtends() = lookupWildcardExtends(this); 1505 1506 syn nta TypeDecl WildcardsCompilationUnit.lookupWildcardSuper(TypeDecl bound) = 1507 new WildcardSuperType( 1508 new Modifiers(new List().add(new Modifier("public"))), 1509 "? super " + bound.fullName(), 1510 new List(), 1511 bound.createBoundAccess()); 1512 1513 eq Program.getChild().lookupWildcardSuper(TypeDecl typeDecl) = 1514 wildcards().lookupWildcardSuper(typeDecl); 1515 1516 inh TypeDecl TypeDecl.lookupWildcardSuper(TypeDecl typeDecl); 1517 1518 syn TypeDecl TypeDecl.asWildcardSuper() = lookupWildcardSuper(this); 1519 1520 syn nta LUBType WildcardsCompilationUnit.lookupLUBType(Collection bounds) = createLUBType(bounds); 1521 1522 public static LUBType WildcardsCompilationUnit.createLUBType(Collection bounds) { 1523 List boundList = new List(); 1524 StringBuilder name = new StringBuilder(); 1525 for (Iterator iter = bounds.iterator(); iter.hasNext(); ) { 1526 TypeDecl typeDecl = (TypeDecl) iter.next(); 1527 boundList.add(typeDecl.createBoundAccess()); 1528 name.append("& " + typeDecl.typeName()); 1529 } 1530 LUBType decl = new LUBType( 1531 new Modifiers(new List().add(new Modifier("public"))), 1532 name.toString(), 1533 new List(), 1534 boundList 1535 ); 1536 return decl; 1537 } 1538 1539 inh LUBType TypeDecl.lookupLUBType(Collection bounds); 1540 1541 eq Program.getChild().lookupLUBType(Collection bounds) = wildcards().lookupLUBType(bounds); 1542 1543 syn String LUBType.typeName() { 1544 if (getNumTypeBound() == 0) { 1545 return "<NOTYPE>"; 1546 } 1547 StringBuilder sb = new StringBuilder(); 1548 sb.append(getTypeBound(0).type().typeName()); 1549 for (int i = 1; i < getNumTypeBound(); i++) { 1550 sb.append(" & " + getTypeBound(i).type().typeName()); 1551 } 1552 return sb.toString(); 1553 } 1554 1555 public HashSet LUBType.implementedInterfaces(){ 1556 HashSet ret = new HashSet(); 1557 for (int i = 0; i < getNumTypeBound(); i++) { 1558 ret.addAll(getTypeBound(i).type().implementedInterfaces()); 1559 } 1560 return ret; 1561 } 1562 1563 syn nta GLBType WildcardsCompilationUnit.lookupGLBType(ArrayList bounds) { 1564 List boundList = new List(); 1565 StringBuilder name = new StringBuilder(); 1566 for (Iterator iter = bounds.iterator(); iter.hasNext(); ) { 1567 TypeDecl typeDecl = (TypeDecl) iter.next(); 1568 boundList.add(typeDecl.createBoundAccess()); 1569 name.append("& " + typeDecl.typeName()); 1570 } 1571 GLBType decl = new GLBType( 1572 new Modifiers(new List().add(new Modifier("public"))), 1573 name.toString(), 1574 new List(), 1575 boundList 1576 ); 1577 return decl; 1578 } 1579 1580 inh GLBType TypeDecl.lookupGLBType(ArrayList bounds); 1581 1582 eq Program.getChild().lookupGLBType(ArrayList bounds) = wildcards().lookupGLBType(bounds); 1583 1584 syn String GLBType.typeName() { 1585 if (getNumTypeBound() == 0) { 1586 return "<NOTYPE>"; 1587 } 1588 StringBuilder sb = new StringBuilder(); 1589 sb.append(getTypeBound(0).type().typeName()); 1590 for (int i = 1; i < getNumTypeBound(); i++) { 1591 sb.append(" & " + getTypeBound(i).type().typeName()); 1592 } 1593 return sb.toString(); 1594 } 1595 1596 public HashSet GLBType.implementedInterfaces(){ 1597 HashSet ret = new HashSet(); 1598 for (int i = 0; i < getNumTypeBound(); i++) { 1599 ret.addAll(getTypeBound(i).type().implementedInterfaces()); 1600 } 1601 return ret; 1602 } 1603 1604 } 1605 1606 aspect NewGenerics { 1607 1608 public Access TypeVariable.createQualifiedAccess() { 1609 return createBoundAccess(); 1610 } 1611 1612 eq TypeVariable.accessibleFrom(TypeDecl type) = true; 1613 1614 eq TypeVariable.typeName() = name(); 1615 } 1616 1617 aspect SourceDeclarations { 1618 syn lazy TypeDecl TypeDecl.sourceTypeDecl() = this; 1619 eq ParTypeDecl.sourceTypeDecl() = genericDecl().original().sourceTypeDecl(); 1620 eq ClassDeclSubstituted.sourceTypeDecl() = original().sourceTypeDecl(); 1621 eq InterfaceDeclSubstituted.sourceTypeDecl() = original().sourceTypeDecl(); 1622 eq GenericClassDeclSubstituted.sourceTypeDecl() = original().sourceTypeDecl(); 1623 eq GenericInterfaceDeclSubstituted.sourceTypeDecl() = original().sourceTypeDecl(); 1624 1625 syn lazy MethodDecl MethodDecl.sourceMethodDecl() = this; 1626 eq ParMethodDecl.sourceMethodDecl() = genericMethodDecl().original().sourceMethodDecl(); 1627 eq MethodDeclSubstituted.sourceMethodDecl() = getOriginal().sourceMethodDecl(); 1628 1629 syn lazy ConstructorDecl ConstructorDecl.sourceConstructorDecl() = this; 1630 1631 eq ParConstructorDecl.sourceConstructorDecl() = 1632 genericConstructorDecl().original().sourceConstructorDecl(); 1633 1634 eq ConstructorDeclSubstituted.sourceConstructorDecl() = 1635 getOriginal().sourceConstructorDecl(); 1636 1637 syn lazy Variable Variable.sourceVariableDecl(); 1638 eq VariableDeclaration.sourceVariableDecl() = this; 1639 eq FieldDeclaration.sourceVariableDecl() = this; 1640 eq FieldDeclarationSubstituted.sourceVariableDecl() = getOriginal().sourceVariableDecl(); 1641 eq ParameterDeclaration.sourceVariableDecl() = this; 1642 eq ParameterDeclarationSubstituted.sourceVariableDecl() = getOriginal().sourceVariableDecl(); 1643 1644 }