001    /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com>
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     *     * Redistributions of source code must retain the above copyright notice,
008     *       this list of conditions and the following disclaimer.
009     *     * Redistributions in binary form must reproduce the above copyright
010     *       notice, this list of conditions and the following disclaimer in the
011     *       documentation and/or other materials provided with the distribution.
012     *     * Neither the name of the Lund University nor the names of its
013     *       contributors may be used to endorse or promote products derived from
014     *       this software without specific prior written permission.
015     *
016     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
026     * POSSIBILITY OF SUCH DAMAGE.
027     */
028    aspect Transformations {
029      public void LambdaExpr.transformation() {
030        toClass().transformation();
031      }
032    
033      public void ExprMethodReference.transformation() {
034        toClass().transformation();
035      }
036    
037      public void TypeMethodReference.transformation() {
038        toClass().transformation();
039      }
040    
041      public void ConstructorReference.transformation() {
042        toClass().transformation();
043      }
044    
045      // TEMPORARY REFINE TO PREVENT SUPERACCESSORS FROM BEING CREATED WHEN INTERFACE IS THE QUALIFIER
046      refine VariableArityParametersCodegen
047      public void MethodAccess.transformation() {
048        if (decl().isVariableArity() && !invokesVariableArityAsArray()) {
049          // arguments to normal parameters
050          List list = new List();
051          for (int i = 0; i < decl().getNumParameter() - 1; i++)
052            list.add(getArg(i).treeCopyNoTransform());
053          // arguments to variable arity parameters
054          List last = new List();
055          for (int i = decl().getNumParameter() - 1; i < getNumArg(); i++)
056            last.add(getArg(i).treeCopyNoTransform());
057          // build an array holding arguments
058          Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess();
059          for (int i = 0; i < decl().lastParameter().type().dimension(); i++)
060            typeAccess = new ArrayTypeAccess(typeAccess);
061          list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last))));
062          // replace argument list with augemented argument list
063          setArgList(list);
064        }
065        MethodDecl m = decl();
066    
067    
068        /*if (!isQualified() && !m.isStatic()) {
069          TypeDecl typeDecl = hostType();
070          while (typeDecl != null && !typeDecl.hasMethod(name())) {
071            typeDecl = typeDecl.enclosingType();
072          }
073          ASTNode result = this.replaceWith(typeDecl.createQualifiedAccess().qualifiesAccess(new ThisAccess("this")).qualifiesAccess(new MethodAccess(name(), getArgList())));
074          result.transformation();
075          return;
076        }*/
077    
078        if (requiresAccessor()) {
079          /* Access to private methods in enclosing types:
080          The original MethodAccess is replaced with an access to an accessor method
081          built by createAccessor(). This method is built lazily and differs from
082          normal MethodDeclarations in the following ways:
083          1) The method in the class file should always be static and the signature
084             is thus changed to include a possible this reference as the first argument.
085          2) The method is always invoked using INVOKESTATIC
086          3) The flags must indicate that the method is static and package private
087          */
088          super.transformation();
089          this.replaceWith(decl().createAccessor(methodQualifierType()).createBoundAccess(getArgList()));
090          return;
091        } else if (!m.isStatic() && isQualified()
092            && prevExpr().isSuperAccess()
093            && !hostType().instanceOf(prevExpr().type())
094            && !prevExpr().type().isInterfaceDecl()) {
095          decl().createSuperAccessor(superAccessorTarget());
096        }
097        super.transformation();
098      }
099    }