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