001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     * 1. Redistributions of source code must retain the above copyright notice,
008     * this list of conditions and the following disclaimer.
009     *
010     * 2. Redistributions in binary form must reproduce the above copyright notice,
011     * this list of conditions and the following disclaimer in the documentation
012     * and/or other materials provided with the distribution.
013     *
014     * 3. Neither the name of the copyright holder nor the names of its
015     * contributors may be used to endorse or promote products derived from this
016     * software without specific prior written permission.
017     *
018     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
022     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028     * POSSIBILITY OF SUCH DAMAGE.
029     */
030    
031    aspect AnonymousClasses {
032    
033      inh TypeDecl AnonymousDecl.superType();
034      eq ClassInstanceExpr.getTypeDecl().superType() = getAccess().type();
035      eq Program.getChild().superType() = null;
036    
037      inh ConstructorDecl AnonymousDecl.constructorDecl();
038    
039      eq ClassInstanceExpr.getTypeDecl().constructorDecl() {
040        Collection<ConstructorDecl> c = getAccess().type().constructors();
041        SimpleSet maxSpecific = mostSpecificConstructor(c);
042        if (maxSpecific.size() == 1) {
043          return (ConstructorDecl) maxSpecific.iterator().next();
044        }
045        return unknownConstructor();
046      }
047    
048      eq Program.getChild().constructorDecl() = unknownConstructor();
049    
050      public int TypeDecl.anonymousIndex = 0;
051    
052      eq AnonymousDecl.isCircular() = false;
053    
054      syn lazy Opt AnonymousDecl.getSuperClassOpt() {
055        if (superType().isInterfaceDecl()) {
056          return new Opt(typeObject().createQualifiedAccess());
057        } else {
058          return new Opt(superType().createBoundAccess());
059        }
060      }
061    
062      syn lazy List AnonymousDecl.getImplementsList() {
063        if (superType().isInterfaceDecl()) {
064          return new List().add(superType().createBoundAccess());
065        } else {
066          return new List();
067        }
068      }
069    
070      public int TypeDecl.nextAnonymousIndex() {
071        if (isNestedType()) {
072          return enclosingType().nextAnonymousIndex();
073        }
074        return anonymousIndex++;
075      }
076    
077      /**
078       * Create the list of parameters for the anonymous class constructor.
079       */
080      protected List AnonymousDecl.constructorParameterList(ConstructorDecl decl) {
081        List parameterList = new List();
082        for (int i = 0; i < decl.getNumParameter(); i++) {
083          ParameterDeclaration param = decl.getParameter(i);
084          parameterList.add(
085              new ParameterDeclaration(
086                param.type().createBoundAccess(),
087                param.name()
088                )
089              );
090        }
091    
092        return parameterList;
093      }
094    
095      inh TypeDecl AnonymousDecl.typeNullPointerException();
096    
097      syn lazy Collection FieldDeclaration.exceptions() {
098        HashSet set = new HashSet();
099        if (isInstanceVariable() && hasInit()) {
100          collectExceptions(set, this);
101          for (Iterator iter = set.iterator(); iter.hasNext(); ) {
102            TypeDecl typeDecl = (TypeDecl) iter.next();
103            if (!getInit().reachedException(typeDecl)) {
104              iter.remove();
105            }
106          }
107        }
108        return set;
109      }
110    
111      syn lazy Collection InstanceInitializer.exceptions() {
112        HashSet set = new HashSet();
113        collectExceptions(set, this);
114        for (Iterator iter = set.iterator(); iter.hasNext(); ) {
115          TypeDecl typeDecl = (TypeDecl) iter.next();
116          if (!getBlock().reachedException(typeDecl)) {
117            iter.remove();
118          }
119        }
120        return set;
121      }
122    
123      protected void ASTNode.collectExceptions(Collection c, ASTNode target) {
124        for (int i = 0; i < getNumChild(); i++) {
125          getChild(i).collectExceptions(c, target);
126        }
127      }
128    
129      protected void ThrowStmt.collectExceptions(Collection c, ASTNode target) {
130        super.collectExceptions(c, target);
131        TypeDecl exceptionType = getExpr().type();
132        if (exceptionType == typeNull()) {
133          exceptionType = typeNullPointerException();
134        }
135        c.add(exceptionType);
136      }
137    
138      protected void MethodAccess.collectExceptions(Collection c, ASTNode target) {
139        super.collectExceptions(c, target);
140        for (int i = 0; i < decl().getNumException(); i++) {
141          c.add(decl().getException(i).type());
142        }
143      }
144    
145    }