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 GenericTypeVariables { 032 033 // The bounds of a type variable should be resolved to type names 034 eq TypeVariable.getTypeBound().nameType() = NameType.TYPE_NAME; 035 036 rewrite TypeVariable { 037 when (getNumTypeBound() == 0) 038 to TypeVariable { 039 addTypeBound( 040 new TypeAccess( 041 "java.lang", 042 "Object" 043 ) 044 ); 045 return this; 046 } 047 } 048 049 public void TypeVariable.nameCheck() { 050 if (extractSingleType(lookupType(name())) != this) { 051 errorf("*** Semantic Error: type variable %s is multiply declared", name()); 052 } 053 } 054 055 syn TypeDecl TypeVariable.lowerBound() = getTypeBound(0).type(); 056 057 } 058 059 aspect GenericTypeVariablesMembers { 060 eq TypeVariable.memberMethods(String name) { 061 Collection list = new HashSet(); 062 for (int i = 0; i < getNumTypeBound(); i++) { 063 for (Iterator iter = getTypeBound(i).type().memberMethods(name).iterator(); iter.hasNext(); ) { 064 MethodDecl decl = (MethodDecl) iter.next(); 065 list.add(decl); 066 } 067 } 068 return list; 069 } 070 071 eq TypeVariable.memberFields(String name) { 072 SimpleSet set = SimpleSet.emptySet; 073 for (int i = 0; i < getNumTypeBound(); i++) { 074 for (Iterator iter = getTypeBound(i).type().memberFields(name).iterator(); iter.hasNext(); ) { 075 FieldDeclaration decl = (FieldDeclaration) iter.next(); 076 set = set.add(decl); 077 } 078 } 079 return set; 080 } 081 082 } 083 084 aspect GenricTypeVariablesTypeAnalysis { 085 086 public void TypeVariable.typeCheck() { 087 if (!getTypeBound(0).type().isTypeVariable() && !getTypeBound(0).type().isClassDecl() 088 && !getTypeBound(0).type().isInterfaceDecl()) { 089 errorf("the first type bound must be either a type variable," 090 + " or a class or interface type which %s is not", 091 getTypeBound(0).type().fullName()); 092 } 093 for (int i = 1; i < getNumTypeBound(); i++) { 094 if (!getTypeBound(i).type().isInterfaceDecl()) { 095 errorf("type bound %s must be an interface type which %s is not", 096 i, getTypeBound(i).type().fullName()); 097 } 098 } 099 HashSet typeSet = new HashSet(); 100 for (int i = 0; i < getNumTypeBound(); i++) { 101 TypeDecl type = getTypeBound(i).type(); 102 TypeDecl erasure = type.erasure(); 103 if (typeSet.contains(erasure)) { 104 if (type != erasure) { 105 errorf("the erasure %s of typebound %s is multiply declared in %s", 106 erasure.fullName(), getTypeBound(i).prettyPrint(), this); 107 } else { 108 errorf("%s is multiply declared", type.fullName()); 109 } 110 } 111 typeSet.add(erasure); 112 } 113 114 for (int i = 0; i < getNumTypeBound(); i++) { 115 TypeDecl type = getTypeBound(i).type(); 116 for (Iterator iter = type.methodsIterator(); iter.hasNext(); ) { 117 MethodDecl m = (MethodDecl) iter.next(); 118 for (int j = i+1; j < getNumTypeBound(); j++) { 119 TypeDecl destType = getTypeBound(j).type(); 120 for (Iterator destIter = destType.memberMethods(m.name()).iterator(); destIter.hasNext(); ) { 121 MethodDecl n = (MethodDecl) destIter.next(); 122 if (m.sameSignature(n) && m.type() != n.type()) { 123 errorf("the two bounds, %s and %s, in type variable %s have" 124 + " a method %s with conflicting return types %s and %s", 125 type.name(), destType.name(), name(), m.signature(), 126 m.type().name(), n.type().name()); 127 } 128 } 129 } 130 } 131 } 132 133 134 } 135 136 137 }