001    /* Copyright (c) 2011-2015, Jesper Öqvist <jesper.oqvist@cs.lth.se>
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 ReifiableTypes {
032      /**
033       * A type is reifiable if it either refers to a non-parameterized type,
034       * is a raw type, is a parameterized type with only unbound wildcard
035       * parameters or is an array type with a reifiable type parameter.
036       *
037       * @see "JLS SE7 &sect;4.7"
038       */
039      syn boolean TypeDecl.isReifiable() = true;
040    
041      /**
042       * We only check for wildcards in type parameter list when checking
043       * reifiability. A wildcard type in general is not reifiable.
044       */
045      eq AbstractWildcardType.isReifiable() = false;
046    
047      /**
048       * A type variable is never reifiable.
049       * @return false
050       */
051      eq TypeVariable.isReifiable() = false;
052    
053      /**
054       * A class is reifiable if its enclosing type is reifiable.
055       */
056      eq ClassDecl.isReifiable() = !isInnerClass() || enclosingType().isReifiable();
057    
058      eq GenericClassDecl.isReifiable() = false;
059    
060      /**
061       * A parameterized type is reifiable only if it's
062       * type parameters are all unbound wildcard types.
063       */
064      eq ParClassDecl.isReifiable() {
065        if (original().isInnerClass() && !original().enclosingType().isReifiable()) {
066          return false;
067        }
068        for (Access argument: getArgumentList()) {
069          if (!argument.isWildcard()) {
070            return false;
071          }
072        }
073        return true;
074      }
075    
076      eq RawClassDecl.isReifiable() = true;
077    
078      eq GenericInterfaceDecl.isReifiable() = false;
079    
080      /**
081       * A parameterized type is reifiable only if it's
082       * type parameters are all unbound wildcard types.
083       */
084      eq ParInterfaceDecl.isReifiable() {
085        for (Access argument: getArgumentList()) {
086          if (!argument.isWildcard()) {
087            return false;
088          }
089        }
090        return true;
091      }
092    
093      eq RawInterfaceDecl.isReifiable() = true;
094    
095      /**
096       * An array type is reifiable only if the elements of the
097       * array are reifiable.
098       */
099      eq ArrayDecl.isReifiable() = componentType().isReifiable();
100    
101      /**
102       * WARNING: this attribute is not the same as TypeDecl.isWildcard,
103       * which returns true for any wildcard type (even bounded wildcard types).
104       * @return {@code true} if this is an unbounded wildcard access
105       */
106      syn boolean Access.isWildcard() = false;
107      eq Wildcard.isWildcard() = true;
108      eq BoundTypeAccess.isWildcard() = getTypeDecl() instanceof WildcardType;
109    }
110