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 AnonymousClasses {
011    
012      //eq ParameterDeclaration.getTypeAccess().hostType() = hostType().isAnonymous() ? ((ClassDecl)hostType()).superclass() : hostType();
013    
014      inh TypeDecl AnonymousDecl.superType();
015      eq ClassInstanceExpr.getTypeDecl().superType() = getAccess().type();
016      eq Program.getChild().superType() = null;
017    
018      inh ConstructorDecl AnonymousDecl.constructorDecl();
019      eq ClassInstanceExpr.getTypeDecl().constructorDecl() {
020        Collection c = getAccess().type().constructors();
021        SimpleSet maxSpecific = mostSpecificConstructor(c);
022        if(maxSpecific.size() == 1)
023          return (ConstructorDecl)maxSpecific.iterator().next();
024        return unknownConstructor();
025      }
026      eq Program.getChild().constructorDecl() = null;
027    
028      public int TypeDecl.anonymousIndex = 0;
029    
030      eq AnonymousDecl.isCircular() = false;
031    
032      syn lazy Opt AnonymousDecl.getSuperClassAccessOpt() {
033        if(superType().isInterfaceDecl())
034          return new Opt(typeObject().createQualifiedAccess());
035        else
036          return new Opt(superType().createBoundAccess());
037      }
038      syn lazy List AnonymousDecl.getImplementsList() {
039        if(superType().isInterfaceDecl())
040          return new List().add(superType().createBoundAccess());
041        else
042          return new List();
043      }
044    
045      public int TypeDecl.nextAnonymousIndex() {
046        if(isNestedType())
047          return enclosingType().nextAnonymousIndex();
048        return anonymousIndex++;
049      }
050    
051      /**
052       * Create the list of parameters for the anonymous class constructor.
053       */
054      protected List AnonymousDecl.constructorParameterList(ConstructorDecl decl) {
055        List parameterList = new List();
056        for(int i = 0; i < decl.getNumParameter(); i++) {
057          ParameterDeclaration param = decl.getParameter(i);
058          parameterList.add(
059              new ParameterDeclaration(
060                param.type().createBoundAccess(),
061                param.name()
062                )
063              );
064        }
065    
066        return parameterList;
067      }
068    
069      rewrite AnonymousDecl {
070        when(noConstructor())
071        to AnonymousDecl {
072          setModifiers(new Modifiers(new List().add(new Modifier("final"))));
073    
074          ConstructorDecl decl = constructorDecl();
075          Modifiers modifiers = (Modifiers)decl.getModifiers().fullCopy();
076          String anonName = "Anonymous" + nextAnonymousIndex();
077    
078          ConstructorDecl constructor = new ConstructorDecl(modifiers, anonName,
079              constructorParameterList(decl), new List(), new Opt(), new Block());
080          constructor.setDefaultConstructor();
081          addBodyDecl(constructor);
082    
083          setID(anonName);
084    
085          List argList = new List();
086          for(int i = 0; i < constructor.getNumParameter(); i++) {
087            argList.add(new VarAccess(constructor.getParameter(i).name()));
088          }
089    
090          constructor.setConstructorInvocation(
091            new ExprStmt(
092              new SuperConstructorAccess("super", argList)
093            )
094          );
095    
096          HashSet set = new HashSet();
097          for(int i = 0; i < getNumBodyDecl(); i++) {
098            if(getBodyDecl(i) instanceof InstanceInitializer) {
099              InstanceInitializer init = (InstanceInitializer)getBodyDecl(i);
100              set.addAll(init.exceptions());
101            }
102            else if(getBodyDecl(i) instanceof FieldDeclaration) {
103              FieldDeclaration f = (FieldDeclaration)getBodyDecl(i);
104              if(f.isInstanceVariable()) {
105                set.addAll(f.exceptions());
106              }
107            }
108          }
109          List exceptionList = new List();
110          for(Iterator iter = set.iterator(); iter.hasNext(); ) {
111            TypeDecl exceptionType = (TypeDecl)iter.next();
112            if(exceptionType.isNull())
113              exceptionType = typeNullPointerException();
114            exceptionList.add(exceptionType.createQualifiedAccess());
115          }
116          constructor.setExceptionList(exceptionList);
117          return this;
118          /*
119          setModifiers(new Modifiers(new List().add(new Modifier("final"))));
120          
121          ConstructorDecl constructor = new ConstructorDecl();
122          addBodyDecl(constructor);
123    
124          constructor.setModifiers((Modifiers)constructorDecl().getModifiers().fullCopy());
125          String name = "Anonymous" + nextAnonymousIndex();
126          setID(name);
127          constructor.setID(name);
128    
129          List parameterList = new List();
130          for(int i = 0; i < constructorDecl().getNumParameter(); i++) {
131            parameterList.add(
132              new ParameterDeclaration(
133                constructorDecl().getParameter(i).type().createBoundAccess(),
134                constructorDecl().getParameter(i).name()
135              )
136            );
137          }
138          constructor.setParameterList(parameterList);
139          
140          List argList = new List();
141          for(int i = 0; i < constructor.getNumParameter(); i++)
142            argList.add(new VarAccess(constructor.getParameter(i).name()));
143          constructor.setConstructorInvocation(
144            new ExprStmt(
145              new SuperConstructorAccess("super", argList)
146            )
147          );
148          constructor.setBlock(new Block());
149    
150          HashSet set = new HashSet();
151          for(int i = 0; i < getNumBodyDecl(); i++) {
152            if(getBodyDecl(i) instanceof InstanceInitializer) {
153              InstanceInitializer init = (InstanceInitializer)getBodyDecl(i);
154              set.addAll(init.exceptions());
155            }
156            else if(getBodyDecl(i) instanceof FieldDeclaration) {
157              FieldDeclaration f = (FieldDeclaration)getBodyDecl(i);
158              if(f.isInstanceVariable()) {
159                set.addAll(f.exceptions());
160              }
161            }
162          }
163          List exceptionList = new List();
164          for(Iterator iter = set.iterator(); iter.hasNext(); ) {
165            TypeDecl exceptionType = (TypeDecl)iter.next();
166            if(exceptionType.isNull())
167              exceptionType = typeNullPointerException();
168            exceptionList.add(exceptionType.createQualifiedAccess());
169          }
170          constructor.setExceptionList(exceptionList);
171          return this;
172          */
173        }
174      }
175      inh TypeDecl AnonymousDecl.typeNullPointerException();
176    
177    
178      syn lazy Collection FieldDeclaration.exceptions() {
179        HashSet set = new HashSet();
180        if(isInstanceVariable() && hasInit()) {
181          collectExceptions(set, this);
182          for(Iterator iter = set.iterator(); iter.hasNext(); ) {
183            TypeDecl typeDecl = (TypeDecl)iter.next();
184            if(!getInit().reachedException(typeDecl))
185              iter.remove();
186          }
187        }
188        return set;
189      }
190    
191      syn lazy Collection InstanceInitializer.exceptions() {
192        HashSet set = new HashSet();
193        collectExceptions(set, this);
194        for(Iterator iter = set.iterator(); iter.hasNext(); ) {
195          TypeDecl typeDecl = (TypeDecl)iter.next();
196          if(!getBlock().reachedException(typeDecl))
197            iter.remove();
198        }
199        return set;
200      }
201    
202      protected void ASTNode.collectExceptions(Collection c, ASTNode target) {
203        for(int i = 0; i < getNumChild(); i++)
204          getChild(i).collectExceptions(c, target);
205      }
206    
207      protected void ThrowStmt.collectExceptions(Collection c, ASTNode target) {
208        super.collectExceptions(c, target);
209        TypeDecl exceptionType = getExpr().type();
210        if(exceptionType == typeNull())
211          exceptionType = typeNullPointerException();
212        c.add(exceptionType);
213      }
214    
215      protected void MethodAccess.collectExceptions(Collection c, ASTNode target) {
216        super.collectExceptions(c, target);
217        for(int i = 0; i < decl().getNumException(); i++)
218          c.add(decl().getException(i).type());
219      }
220    
221    }