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    }