001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     *                    2013, 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 ConstantPoolNames {
033    
034      /**
035       * For a top-level type the constant pool name of the type is the same as the
036       * canonical name but with dots replaced by solidus.
037       *
038       * <p>For nested types the constant pool name is based on the enclosing top-level
039       * types constant pool name followed by a dollar sign and a unique index and/or
040       * the type name.
041       *
042       * @return constant pool name of this type
043       */
044      syn lazy String TypeDecl.constantPoolName() {
045        String packageName = packageName();
046        if (!packageName.equals("")) {
047          packageName = packageName.replace('.', '/') + "/";
048        }
049        return packageName + uniqueName();
050      }
051    
052      /**
053       * Computes a unique name for this type in the enclosing package.
054       * <p>For top-level types the unique name is just the type name.  For nested
055       * types it is the enclosing types unique name followed by a dollar sign and
056       * a unique index and/or the type name.
057       *
058       * @return a name for this type that is unique in the enclosing package
059       */
060      syn lazy String TypeDecl.uniqueName() {
061        if (!isNestedType()) {
062          return getID();
063        } else {
064          String prefix = enclosingType().uniqueName();
065          if (isAnonymous()) {
066            return prefix + "$" + uniqueIndex();
067          } else if (isLocalClass()) {
068            return prefix + "$" + uniqueIndex() + getID();
069          } else {
070            return prefix + "$" + getID();
071          }
072        }
073      }
074    
075      syn lazy String ArrayDecl.constantPoolName() = typeDescriptor();
076    
077      syn lazy String TypeDecl.typeDescriptor() {
078        throw new Error("Can not compute typeDescriptor for " + getClass().getName());
079      }
080      eq     ClassDecl.typeDescriptor() = "L" + constantPoolName() + ";";
081      eq InterfaceDecl.typeDescriptor() = "L" + constantPoolName() + ";";
082      eq   BooleanType.typeDescriptor() = "Z";
083      eq      ByteType.typeDescriptor() = "B";
084      eq     ShortType.typeDescriptor() = "S";
085      eq       IntType.typeDescriptor() = "I";
086      eq      LongType.typeDescriptor() = "J";
087      eq      CharType.typeDescriptor() = "C";
088      eq     FloatType.typeDescriptor() = "F";
089      eq    DoubleType.typeDescriptor() = "D";
090      eq      VoidType.typeDescriptor() = "V";
091      eq     ArrayDecl.typeDescriptor() {
092        StringBuilder dim = new StringBuilder();
093        for (int i = 0; i < dimension(); i++) {
094          dim.append("[");
095        }
096        dim.append(elementType().typeDescriptor());
097        return dim.toString();
098      }
099      eq UnknownType.typeDescriptor() {
100        throw new Error("Trying to make a typeDescriptor() of Unknown");
101      }
102    
103      syn lazy String MethodDecl.descName() {
104        StringBuilder b = new StringBuilder();
105        b.append("(");
106        for (int i=0; i<getNumParameter(); i++) {
107          b.append(getParameter(i).type().typeDescriptor());
108        }
109        b.append(")");
110        if (type().elementType().isUnknown()) {
111          System.err.println(getTypeAccess().dumpTree());
112          throw new Error("Error generating descName for " + signature() + ", did not expect unknown return type");
113        }
114        b.append(type().typeDescriptor());
115        return b.toString();
116      }
117    
118      syn lazy String ConstructorDecl.descName() {
119        StringBuilder b = new StringBuilder();
120        b.append("(");
121        // this$0
122        if (needsEnclosing()) {
123          b.append(enclosing().typeDescriptor());
124        }
125        if (needsSuperEnclosing()) {
126          b.append(superEnclosing().typeDescriptor());
127        }
128        // args
129        for (int i=0; i<getNumParameter(); i++) {
130          b.append(getParameter(i).type().typeDescriptor());
131        }
132        b.append(")V");
133        return b.toString();
134      }
135    
136      /**
137       * Computes the path to the parent directory of the source file of this
138       * compilation unit.
139       *
140       * <p>If the parent directory of the source file could not be computed
141       * the path to the working directory is returned.
142       *
143       * @return The path to the parent directory of the source file for this
144       * compilation unit, or "." if the path could not be computed.
145       */
146      syn lazy String CompilationUnit.destinationPath() {
147        String parentPath = new File(pathName()).getParent();
148        if (parentPath == null) {
149          return ".";
150        } else {
151          return parentPath;
152        }
153      }
154    
155      /**
156       * @return The path to the classfiles that should be generated for this type.
157       */
158      syn lazy String TypeDecl.destinationPath() {
159        if (program().options().hasValueForOption("-d")) {
160          return program().options().getValueForOption("-d") + File.separator
161              + constantPoolName() + ".class";
162        } else {
163          return compilationUnit().destinationPath() + File.separator
164              + uniqueName() + ".class";
165        }
166      }
167    }