001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 aspect GenericMethods { 011 public void ParMethodAccess.typeCheck() { 012 super.typeCheck(); 013 if(!decl().hostType().isUnknown()) { 014 if(!(decl() instanceof ParMethodDecl)) 015 error("can not have type parameters on a non generic method"); 016 else { 017 ParMethodDecl m = (ParMethodDecl)decl(); 018 if(!(m instanceof RawMethodDecl) && m.numTypeParameter() != getNumTypeArgument()) 019 error("generic method " + m.signature() + " requires " + m.numTypeParameter() + " type arguments"); 020 else { 021 } 022 } 023 } 024 } 025 026 027 // ES: removing this, it has been replaced with a paramaterized syn nta attribute 028 //syn lazy final List GenericMethodDecl.getParMethodDeclList() = new List(); 029 // 030 // ES: removing this, it appears not to be used. Maybe needed earlier due to some interface (?) 031 //syn lazy final List GenericConstructorDecl.getParConstructorDeclList() = new List(); 032 // 033 034 syn lazy final MethodDecl GenericMethodDecl.rawMethodDecl() = lookupParMethodDecl(new ArrayList()); 035 //syn lazy final ParConstructorDecl GenericConstructorDecl.rawConstructorDecl() = lookupParConstructorDecl(new ArrayList()); 036 037 /* ES: replacing this with 038 syn lazy GenericMethodDecl ParMethodDecl.genericMethodDecl() { 039 if(getParent() != null && getParent().getParent() instanceof GenericMethodDecl) 040 return (GenericMethodDecl)getParent().getParent(); 041 return null; 042 } 043 with: 044 */ 045 syn lazy GenericMethodDecl ParMethodDecl.genericMethodDecl() { 046 return getGenericMethodDecl(); 047 } 048 049 syn lazy GenericConstructorDecl ParConstructorDecl.genericConstructorDecl() { 050 if(getParent() != null && getParent().getParent() instanceof GenericConstructorDecl) 051 return (GenericConstructorDecl)getParent().getParent(); 052 return null; 053 } 054 055 /* ES: replacing this: 056 syn lazy MethodDecl GenericMethodDecl.lookupParMethodDecl(java.util.List typeArguments) { 057 l: for(int i = 0; i < getNumParMethodDecl(); i++) { 058 ParMethodDecl decl = getParMethodDecl(i); 059 if(decl instanceof RawMethodDecl) { 060 if(typeArguments.isEmpty()) 061 return decl; 062 } 063 else if(decl.getNumTypeArgument() == typeArguments.size()) { 064 for(int j = 0; j < decl.getNumTypeArgument(); j++) 065 if(decl.getTypeArgument(j).type() != typeArguments.get(j)) 066 continue l; 067 return decl; 068 } 069 } 070 return newParMethodDecl(typeArguments); 071 } 072 with: 073 */ 074 syn nta MethodDecl GenericMethodDecl.lookupParMethodDecl(java.util.List typeArguments) { 075 return newParMethodDecl(typeArguments); 076 } 077 078 079 /* ES: replacing this: 080 public ParMethodDecl GenericMethodDecl.newParMethodDecl(java.util.List typeArguments) { 081 ParMethodDecl methodDecl = typeArguments.isEmpty() ? new RawMethodDecl() : new ParMethodDecl(); 082 addParMethodDecl(methodDecl); 083 List list = new List(); 084 if(typeArguments.isEmpty()) { 085 GenericMethodDecl original = original(); 086 for(int i = 0; i < original.getNumTypeParameter(); i++) 087 list.add(original.getTypeParameter(i).erasure().createBoundAccess()); 088 } 089 else { 090 for(Iterator iter = typeArguments.iterator(); iter.hasNext(); ) 091 list.add(((TypeDecl)iter.next()).createBoundAccess()); 092 } 093 methodDecl.setTypeArgumentList(list); 094 methodDecl.setModifiers((Modifiers)getModifiers().fullCopy()); 095 methodDecl.setTypeAccess(getTypeAccess().type().substituteReturnType(methodDecl)); 096 methodDecl.setID(getID()); 097 methodDecl.setParameterList(getParameterList().substitute(methodDecl)); 098 methodDecl.setExceptionList(getExceptionList().substitute(methodDecl)); 099 return getParMethodDecl(getNumParMethodDecl()-1); 100 } 101 with: 102 */ 103 public ParMethodDecl GenericMethodDecl.newParMethodDecl(java.util.List typeArguments) { 104 ParMethodDecl methodDecl = typeArguments.isEmpty() ? new RawMethodDecl() : new ParMethodDecl(); 105 // adding a link to GenericMethodDecl to be used during substitution 106 // instead of the not yet existing parent link 107 methodDecl.setGenericMethodDecl(this); 108 List list = new List(); 109 if(typeArguments.isEmpty()) { 110 GenericMethodDecl original = original(); 111 for(int i = 0; i < original.getNumTypeParameter(); i++) 112 list.add(original.getTypeParameter(i).erasure().createBoundAccess()); 113 } 114 else { 115 for(Iterator iter = typeArguments.iterator(); iter.hasNext(); ) 116 list.add(((TypeDecl)iter.next()).createBoundAccess()); 117 } 118 methodDecl.setTypeArgumentList(list); 119 methodDecl.setModifiers((Modifiers)getModifiers().fullCopy()); 120 methodDecl.setTypeAccess(getTypeAccess().type().substituteReturnType(methodDecl)); 121 methodDecl.setID(getID()); 122 methodDecl.setParameterList(getParameterList().substitute(methodDecl)); 123 methodDecl.setExceptionList(getExceptionList().substitute(methodDecl)); 124 return methodDecl; 125 } 126 127 128 } 129 130 aspect TypeCheck { 131 // Disable error checking in instantiated generic methods 132 public void ParMethodDecl.collectErrors() { 133 } 134 // Allow covariant return types 135 refine TypeHierarchyCheck eq MethodDecl.mayOverrideReturn(MethodDecl m) { 136 return type().instanceOf(m.type()); 137 } 138 } 139 140 aspect GenericMethodsNameAnalysis { 141 142 eq ParMethodAccess.getTypeArgument().nameType() = NameType.TYPE_NAME; 143 eq ParMethodAccess.getTypeArgument().lookupType(String name) = unqualifiedScope().lookupType(name); 144 eq GenericMethodDecl.getTypeParameter().nameType() = NameType.TYPE_NAME; 145 146 inh SimpleSet GenericMethodDecl.lookupType(String name); 147 syn SimpleSet GenericMethodDecl.localLookupType(String name) { 148 for(int i = 0; i < getNumTypeParameter(); i++) { 149 if(original().getTypeParameter(i).name().equals(name)) 150 return SimpleSet.emptySet.add(original().getTypeParameter(i)); 151 } 152 return SimpleSet.emptySet; 153 } 154 eq GenericMethodDecl.getChild().lookupType(String name) = localLookupType(name).isEmpty() ? lookupType(name) : localLookupType(name); 155 156 eq ParConstructorAccess.getTypeArgument().nameType() = NameType.TYPE_NAME; 157 eq ParConstructorAccess.getTypeArgument().lookupType(String name) = unqualifiedScope().lookupType(name); 158 eq ParSuperConstructorAccess.getTypeArgument().nameType() = NameType.TYPE_NAME; 159 eq ParSuperConstructorAccess.getTypeArgument().lookupType(String name) = unqualifiedScope().lookupType(name); 160 eq GenericConstructorDecl.getTypeParameter().nameType() = NameType.TYPE_NAME; 161 162 inh SimpleSet GenericConstructorDecl.lookupType(String name); 163 syn SimpleSet GenericConstructorDecl.localLookupType(String name) { 164 for(int i = 0; i < getNumTypeParameter(); i++) { 165 if(original().getTypeParameter(i).name().equals(name)) 166 return SimpleSet.emptySet.add(original().getTypeParameter(i)); 167 } 168 return SimpleSet.emptySet; 169 } 170 eq GenericConstructorDecl.getChild().lookupType(String name) = localLookupType(name).isEmpty() ? lookupType(name) : localLookupType(name); 171 172 eq ParClassInstanceExpr.getTypeArgument().nameType() = NameType.TYPE_NAME; 173 eq ParClassInstanceExpr.getTypeArgument().lookupType(String name) = unqualifiedScope().lookupType(name); 174 175 } 176 177 aspect GenericMethodsPrettyPrint { 178 179 public void ParMethodAccess.toString(StringBuffer s) { 180 s.append("<"); 181 for(int i = 0; i < getNumTypeArgument(); i++) { 182 if(i != 0) s.append(", "); 183 getTypeArgument(i).toString(s); 184 } 185 s.append(">"); 186 super.toString(s); 187 } 188 public void ParConstructorAccess.toString(StringBuffer s) { 189 s.append("<"); 190 for(int i = 0; i < getNumTypeArgument(); i++) { 191 if(i != 0) s.append(", "); 192 getTypeArgument(i).toString(s); 193 } 194 s.append(">"); 195 super.toString(s); 196 } 197 public void ParSuperConstructorAccess.toString(StringBuffer s) { 198 s.append("<"); 199 for(int i = 0; i < getNumTypeArgument(); i++) { 200 if(i != 0) s.append(", "); 201 getTypeArgument(i).toString(s); 202 } 203 s.append(">"); 204 super.toString(s); 205 } 206 public void ParClassInstanceExpr.toString(StringBuffer s) { 207 s.append("<"); 208 for(int i = 0; i < getNumTypeArgument(); i++) { 209 if(i != 0) s.append(", "); 210 getTypeArgument(i).toString(s); 211 } 212 s.append(">"); 213 super.toString(s); 214 } 215 216 private void GenericMethodDecl.ppTypeParameters(StringBuffer s) { 217 s.append(" <"); 218 for(int i = 0; i < getNumTypeParameter(); i++) { 219 if(i != 0) s.append(", "); 220 original().getTypeParameter(i).toString(s); 221 } 222 s.append("> "); 223 } 224 225 public void GenericMethodDecl.toString(StringBuffer s) { 226 s.append(indent()); 227 getModifiers().toString(s); 228 229 ppTypeParameters(s); 230 231 getTypeAccess().toString(s); 232 s.append(" " + getID()); 233 s.append("("); 234 if(getNumParameter() > 0) { 235 getParameter(0).toString(s); 236 for(int i = 1; i < getNumParameter(); i++) { 237 s.append(", "); 238 getParameter(i).toString(s); 239 } 240 } 241 s.append(")"); 242 if(getNumException() > 0) { 243 s.append(" throws "); 244 getException(0).toString(s); 245 for(int i = 1; i < getNumException(); i++) { 246 s.append(", "); 247 getException(i).toString(s); 248 } 249 } 250 if(hasBlock()) { 251 s.append(" "); 252 getBlock().toString(s); 253 } 254 else { 255 s.append(";\n"); 256 } 257 } 258 public void GenericConstructorDecl.toString(StringBuffer s) { 259 s.append(indent()); 260 getModifiers().toString(s); 261 262 s.append(" <"); 263 for(int i = 0; i < getNumTypeParameter(); i++) { 264 if(i != 0) s.append(", "); 265 original().getTypeParameter(i).toString(s); 266 } 267 s.append("> "); 268 269 s.append(getID() + "("); 270 if(getNumParameter() > 0) { 271 getParameter(0).toString(s); 272 for(int i = 1; i < getNumParameter(); i++) { 273 s.append(", "); 274 getParameter(i).toString(s); 275 } 276 } 277 s.append(")"); 278 if(getNumException() > 0) { 279 s.append(" throws "); 280 getException(0).toString(s); 281 for(int i = 1; i < getNumException(); i++) { 282 s.append(", "); 283 getException(i).toString(s); 284 } 285 } 286 287 s.append(" {"); 288 if(hasConstructorInvocation()) { 289 s.append(indent()); 290 getConstructorInvocation().toString(s); 291 } 292 for(int i = 0; i < getBlock().getNumStmt(); i++) { 293 s.append(indent()); 294 getBlock().getStmt(i).toString(s); 295 } 296 s.append(indent()); 297 s.append("}"); 298 } 299 300 }