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 MethodSignature15 { 011 refine LookupMethod protected SimpleSet MethodAccess.maxSpecific(Collection candidates) { 012 SimpleSet potentiallyApplicable = potentiallyApplicable(candidates); 013 // first phase 014 SimpleSet maxSpecific = applicableBySubtyping(potentiallyApplicable); 015 // second phase 016 maxSpecific = applicableByMethodInvocationConversion(potentiallyApplicable, 017 maxSpecific); 018 // third phase 019 maxSpecific = applicableVariableArity(potentiallyApplicable, maxSpecific); 020 return maxSpecific; 021 } 022 023 protected SimpleSet MethodAccess.potentiallyApplicable(Collection candidates) { 024 SimpleSet potentiallyApplicable = SimpleSet.emptySet; 025 // select potentially applicable methods 026 for(Iterator iter = candidates.iterator(); iter.hasNext(); ) { 027 MethodDecl decl = (MethodDecl)iter.next(); 028 if(potentiallyApplicable(decl) && accessible(decl)) { 029 if(decl instanceof GenericMethodDecl) { 030 decl = ((GenericMethodDecl)decl).lookupParMethodDecl(typeArguments(decl)); 031 } 032 potentiallyApplicable = potentiallyApplicable.add(decl); 033 } 034 } 035 return potentiallyApplicable; 036 } 037 038 protected SimpleSet MethodAccess.applicableBySubtyping(SimpleSet potentiallyApplicable) { 039 SimpleSet maxSpecific = SimpleSet.emptySet; 040 for(Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) { 041 MethodDecl decl = (MethodDecl)iter.next(); 042 if(applicableBySubtyping(decl)) 043 maxSpecific = mostSpecific(maxSpecific, decl); 044 } 045 return maxSpecific; 046 } 047 048 protected SimpleSet MethodAccess.applicableByMethodInvocationConversion(SimpleSet potentiallyApplicable, SimpleSet maxSpecific) { 049 if(maxSpecific.isEmpty()) { 050 for(Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) { 051 MethodDecl decl = (MethodDecl)iter.next(); 052 if(applicableByMethodInvocationConversion(decl)) 053 maxSpecific = mostSpecific(maxSpecific, decl); 054 } 055 } 056 return maxSpecific; 057 } 058 059 protected SimpleSet MethodAccess.applicableVariableArity(SimpleSet potentiallyApplicable, SimpleSet maxSpecific) { 060 if(maxSpecific.isEmpty()) { 061 for(Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) { 062 MethodDecl decl = (MethodDecl)iter.next(); 063 if(decl.isVariableArity() && applicableVariableArity(decl)) 064 maxSpecific = mostSpecific(maxSpecific, decl); 065 } 066 } 067 return maxSpecific; 068 } 069 070 refine ConstructScope eq ClassInstanceExpr.decls() { 071 TypeDecl typeDecl = hasTypeDecl() ? getTypeDecl() : getAccess().type(); 072 return chooseConstructor(typeDecl.constructors(), getArgList()); 073 } 074 refine ConstructScope eq ConstructorAccess.decls() { 075 return chooseConstructor(lookupConstructor(), getArgList()); 076 } 077 refine ConstructScope eq SuperConstructorAccess.decls() { 078 Collection c = hasPrevExpr() && !prevExpr().isTypeAccess() ? 079 hostType().lookupSuperConstructor() : lookupSuperConstructor(); 080 return chooseConstructor(c, getArgList()); 081 } 082 083 refine AnonymousClasses eq ClassInstanceExpr.getTypeDecl().constructorDecl() { 084 Collection c = getAccess().type().constructors(); 085 SimpleSet maxSpecific = chooseConstructor(c, getArgList()); 086 if(maxSpecific.size() == 1) 087 return (ConstructorDecl)maxSpecific.iterator().next(); 088 return unknownConstructor(); 089 } 090 091 protected SimpleSet Expr.chooseConstructor(Collection constructors, List argList) { 092 SimpleSet potentiallyApplicable = SimpleSet.emptySet; 093 // select potentially applicable constructors 094 for(Iterator iter = constructors.iterator(); iter.hasNext(); ) { 095 ConstructorDecl decl = (ConstructorDecl)iter.next(); 096 if(decl.potentiallyApplicable(argList) && decl.accessibleFrom(hostType())) 097 potentiallyApplicable = potentiallyApplicable.add(decl); 098 } 099 // first phase 100 SimpleSet maxSpecific = SimpleSet.emptySet; 101 for(Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) { 102 ConstructorDecl decl = (ConstructorDecl)iter.next(); 103 if(decl.applicableBySubtyping(argList)) 104 maxSpecific = mostSpecific(maxSpecific, decl); 105 } 106 107 // second phase 108 if(maxSpecific.isEmpty()) { 109 for(Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) { 110 ConstructorDecl decl = (ConstructorDecl)iter.next(); 111 if(decl.applicableByMethodInvocationConversion(argList)) 112 maxSpecific = mostSpecific(maxSpecific, decl); 113 } 114 } 115 116 // third phase 117 if(maxSpecific.isEmpty()) { 118 for(Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) { 119 ConstructorDecl decl = (ConstructorDecl)iter.next(); 120 if(decl.isVariableArity() && decl.applicableVariableArity(argList)) 121 maxSpecific = mostSpecific(maxSpecific, decl); 122 } 123 } 124 return maxSpecific; 125 } 126 127 128 protected static SimpleSet Expr.mostSpecific(SimpleSet maxSpecific, ConstructorDecl decl) { 129 if(maxSpecific.isEmpty()) 130 maxSpecific = maxSpecific.add(decl); 131 else { 132 if(decl.moreSpecificThan((ConstructorDecl)maxSpecific.iterator().next())) 133 maxSpecific = SimpleSet.emptySet.add(decl); 134 else if(!((ConstructorDecl)maxSpecific.iterator().next()).moreSpecificThan(decl)) 135 maxSpecific = maxSpecific.add(decl); 136 } 137 return maxSpecific; 138 } 139 140 private static SimpleSet MethodAccess.mostSpecific(SimpleSet maxSpecific, MethodDecl decl) { 141 if(maxSpecific.isEmpty()) 142 maxSpecific = maxSpecific.add(decl); 143 else { 144 if(decl.moreSpecificThan((MethodDecl)maxSpecific.iterator().next())) 145 maxSpecific = SimpleSet.emptySet.add(decl); 146 else if(!((MethodDecl)maxSpecific.iterator().next()).moreSpecificThan(decl)) 147 maxSpecific = maxSpecific.add(decl); 148 } 149 return maxSpecific; 150 } 151 152 eq ParMethodDecl.moreSpecificThan(MethodDecl m) = 153 genericMethodDecl().moreSpecificThan(m instanceof ParMethodDecl ? ((ParMethodDecl)m).genericMethodDecl() : m ); 154 155 refine MethodDecl eq MethodDecl.moreSpecificThan(MethodDecl m) { 156 if(!isVariableArity() && !m.isVariableArity()) 157 return refined(m); 158 int num = Math.max(getNumParameter(), m.getNumParameter()); 159 for(int i = 0; i < num; i++) { 160 TypeDecl t1 = i < getNumParameter() - 1 ? getParameter(i).type() : getParameter(getNumParameter()-1).type().componentType(); 161 TypeDecl t2 = i < m.getNumParameter() - 1 ? m.getParameter(i).type() : m.getParameter(m.getNumParameter()-1).type().componentType(); 162 if(!t1.instanceOf(t2)) 163 return false; 164 } 165 return true; 166 } 167 168 refine ConstructorDecl eq ConstructorDecl.moreSpecificThan(ConstructorDecl m) { 169 if(!isVariableArity() && !m.isVariableArity()) 170 return refined(m); 171 int num = Math.max(getNumParameter(), m.getNumParameter()); 172 for(int i = 0; i < num; i++) { 173 TypeDecl t1 = i < getNumParameter() - 1 ? getParameter(i).type() : getParameter(getNumParameter()-1).type().componentType(); 174 TypeDecl t2 = i < m.getNumParameter() - 1 ? m.getParameter(i).type() : m.getParameter(m.getNumParameter()-1).type().componentType(); 175 if(!t1.instanceOf(t2)) 176 return false; 177 } 178 return true; 179 } 180 181 syn boolean MethodAccess.applicableBySubtyping(MethodDecl m) { 182 if(m.getNumParameter() != getNumArg()) 183 return false; 184 for(int i = 0; i < m.getNumParameter(); i++) 185 if(!getArg(i).type().instanceOf(m.getParameter(i).type())) 186 return false; 187 return true; 188 } 189 190 syn boolean ConstructorDecl.applicableBySubtyping(List argList) { 191 if(getNumParameter() != argList.getNumChild()) 192 return false; 193 for(int i = 0; i < getNumParameter(); i++) { 194 TypeDecl arg = ((Expr)argList.getChild(i)).type(); 195 if(!arg.instanceOf(getParameter(i).type())) 196 return false; 197 } 198 return true; 199 } 200 201 syn boolean MethodAccess.applicableByMethodInvocationConversion(MethodDecl m) { 202 if(m.getNumParameter() != getNumArg()) 203 return false; 204 for(int i = 0; i < m.getNumParameter(); i++) 205 if(!getArg(i).type().methodInvocationConversionTo(m.getParameter(i).type())) 206 return false; 207 return true; 208 } 209 210 syn boolean ConstructorDecl.applicableByMethodInvocationConversion(List argList) { 211 if(getNumParameter() != argList.getNumChild()) 212 return false; 213 for(int i = 0; i < getNumParameter(); i++) { 214 TypeDecl arg = ((Expr)argList.getChild(i)).type(); 215 if(!arg.methodInvocationConversionTo(getParameter(i).type())) 216 return false; 217 } 218 return true; 219 } 220 221 syn boolean MethodAccess.applicableVariableArity(MethodDecl m) { 222 for(int i = 0; i < m.getNumParameter() - 1; i++) 223 if(!getArg(i).type().methodInvocationConversionTo(m.getParameter(i).type())) 224 return false; 225 for(int i = m.getNumParameter() - 1; i < getNumArg(); i++) 226 if(!getArg(i).type().methodInvocationConversionTo(m.lastParameter().type().componentType())) 227 return false; 228 return true; 229 } 230 231 syn boolean ConstructorDecl.applicableVariableArity(List argList) { 232 for(int i = 0; i < getNumParameter() - 1; i++) { 233 TypeDecl arg = ((Expr)argList.getChild(i)).type(); 234 if(!arg.methodInvocationConversionTo(getParameter(i).type())) 235 return false; 236 } 237 for(int i = getNumParameter() - 1; i < argList.getNumChild(); i++) { 238 TypeDecl arg = ((Expr)argList.getChild(i)).type(); 239 if(!arg.methodInvocationConversionTo(lastParameter().type().componentType())) 240 return false; 241 } 242 return true; 243 } 244 245 // 15.12.2.1 246 247 /* A member method is potentially applicable to a method invocation if and only if 248 all of the following are true: 249 * The name of the member is identical to the name of the method in the method 250 invocation. 251 * The member is accessible (�6.6) to the class or interface in which the 252 method invocation appears. 253 * The arity of the member is lesser or equal to the arity of the method 254 invocation. 255 * If the member is a variable arity method with arity n, the arity of the 256 method invocation is greater or equal to n-1. 257 * If the member is a fixed arity method with arity n, the arity of the method 258 invocation is equal to n. 259 * If the method invocation includes explicit type parameters, and the member 260 is a generic method, then the number of actual type parameters is equal to 261 the number of formal type parameters.*/ 262 syn boolean MethodAccess.potentiallyApplicable(MethodDecl m) { 263 if(!m.name().equals(name())) 264 return false; 265 if(!m.accessibleFrom(hostType())) 266 return false; 267 if(m.isVariableArity() && !(arity() >= m.arity()-1)) 268 return false; 269 if(!m.isVariableArity() && !(m.arity() == arity())) 270 return false; 271 if(m instanceof GenericMethodDecl) { 272 GenericMethodDecl gm = (GenericMethodDecl)m; 273 ArrayList list = typeArguments(m); 274 if(list.size() != 0) { 275 if(gm.getNumTypeParameter() != list.size()) 276 return false; 277 for(int i = 0; i < gm.getNumTypeParameter(); i++) 278 if(!((TypeDecl)list.get(i)).subtype(gm.original().getTypeParameter(i))) 279 return false; 280 } 281 } 282 return true; 283 } 284 syn int MethodDecl.arity() = getNumParameter(); 285 syn int MethodAccess.arity() = getNumArg(); 286 287 syn lazy ArrayList MethodAccess.typeArguments(MethodDecl m) { 288 ArrayList typeArguments = new ArrayList(); 289 if(m instanceof GenericMethodDecl) { 290 GenericMethodDecl g = (GenericMethodDecl)m; 291 Collection arguments = computeConstraints(g); 292 if(arguments.isEmpty()) 293 return typeArguments; 294 int i = 0; 295 for(Iterator iter = arguments.iterator(); iter.hasNext(); i++) { 296 TypeDecl typeDecl = (TypeDecl)iter.next(); 297 if(typeDecl == null) { 298 TypeVariable v = g.original().getTypeParameter(i); 299 if(v.getNumTypeBound() == 0) 300 typeDecl = typeObject(); 301 else if(v.getNumTypeBound() == 1) 302 typeDecl = v.getTypeBound(0).type(); 303 else 304 typeDecl = v.lubType(); 305 } 306 typeArguments.add(typeDecl); 307 } 308 } 309 return typeArguments; 310 } 311 eq ParMethodAccess.typeArguments(MethodDecl m) { 312 ArrayList typeArguments = new ArrayList(); 313 for(int i = 0; i < getNumTypeArgument(); i++) 314 typeArguments.add(getTypeArgument(i).type()); 315 return typeArguments; 316 } 317 318 syn boolean ConstructorDecl.potentiallyApplicable(List argList) { 319 if(isVariableArity() && !(argList.getNumChild() >= arity()-1)) 320 return false; 321 if(!isVariableArity() && !(arity() == argList.getNumChild())) 322 return false; 323 return true; 324 } 325 syn int ConstructorDecl.arity() = getNumParameter(); 326 syn int ConstructorAccess.arity() = getNumArg(); 327 syn int ClassInstanceExpr.arity() = getNumArg(); 328 329 // 15.12.3 330 // refine old type checking to be valid when using variable arity parameters 331 refine TypeCheck public void MethodAccess.typeCheck() { 332 if(isQualified() && decl().isAbstract() && qualifier().isSuperAccess()) 333 error("may not access abstract methods in superclass"); 334 if(!decl().isVariableArity() || invokesVariableArityAsArray()) { 335 for(int i = 0; i < decl().getNumParameter(); i++) { 336 TypeDecl exprType = getArg(i).type(); 337 TypeDecl parmType = decl().getParameter(i).type(); 338 if(!exprType.methodInvocationConversionTo(parmType) && !exprType.isUnknown() && !parmType.isUnknown()) { 339 error("#The type " + exprType.typeName() + " of expr " + 340 getArg(i) + " is not compatible with the method parameter " + 341 decl().getParameter(i)); 342 } 343 } 344 } 345 } 346 347 refine MethodDecl eq MethodDecl.signature() { 348 StringBuffer s = new StringBuffer(); 349 s.append(name() + "("); 350 for(int i = 0; i < getNumParameter(); i++) { 351 if(i != 0) s.append(", "); 352 s.append(getParameter(i).type().erasure().typeName()); 353 } 354 s.append(")"); 355 return s.toString(); 356 357 } 358 359 refine MemberMethods eq ClassDecl.methodsSignatureMap() { 360 HashMap map = new HashMap(localMethodsSignatureMap()); 361 if(hasSuperclass()) { 362 for(Iterator iter = superclass().methodsIterator(); iter.hasNext(); ) { 363 MethodDecl m = (MethodDecl)iter.next(); 364 if(!m.isPrivate() && m.accessibleFrom(this) && !localMethodsSignatureMap().containsKey(m.signature())) { 365 if(!(m instanceof MethodDeclSubstituted) || !localMethodsSignatureMap().containsKey(m.sourceMethodDecl().signature())) 366 putSimpleSetElement(map, m.signature(), m); 367 } 368 } 369 } 370 for(Iterator outerIter = interfacesIterator(); outerIter.hasNext(); ) { 371 TypeDecl typeDecl = (TypeDecl)outerIter.next(); 372 for(Iterator iter = typeDecl.methodsIterator(); iter.hasNext(); ) { 373 MethodDecl m = (MethodDecl)iter.next(); 374 if(!m.isPrivate() && m.accessibleFrom(this) && !localMethodsSignatureMap().containsKey(m.signature())) { 375 if(!(m instanceof MethodDeclSubstituted) || !localMethodsSignatureMap().containsKey(m.sourceMethodDecl().signature())) { 376 if(allMethodsAbstract((SimpleSet)map.get(m.signature())) && 377 (!(m instanceof MethodDeclSubstituted) || 378 allMethodsAbstract((SimpleSet)map.get(m.sourceMethodDecl().signature())) ) 379 ) 380 putSimpleSetElement(map, m.signature(), m); 381 } 382 } 383 } 384 } 385 return map; 386 } 387 refine MemberMethods eq InterfaceDecl.methodsSignatureMap() { 388 HashMap map = new HashMap(localMethodsSignatureMap()); 389 for(Iterator outerIter = superinterfacesIterator(); outerIter.hasNext(); ) { 390 TypeDecl typeDecl = (TypeDecl)outerIter.next(); 391 for(Iterator iter = typeDecl.methodsIterator(); iter.hasNext(); ) { 392 MethodDecl m = (MethodDecl)iter.next(); 393 if(!m.isPrivate() && m.accessibleFrom(this) && !localMethodsSignatureMap().containsKey(m.signature())) 394 if(!(m instanceof MethodDeclSubstituted) || !localMethodsSignatureMap().containsKey(m.sourceMethodDecl().signature())) 395 putSimpleSetElement(map, m.signature(), m); 396 } 397 } 398 for(Iterator iter = typeObject().methodsIterator(); iter.hasNext(); ) { 399 MethodDecl m = (MethodDecl)iter.next(); 400 if(m.isPublic() && !map.containsKey(m.signature())) 401 putSimpleSetElement(map, m.signature(), m); 402 } 403 return map; 404 } 405 406 eq ParTypeDecl.unimplementedMethods() { 407 HashSet set = new HashSet(); 408 HashSet result = new HashSet(); 409 for(Iterator iter = genericDecl().unimplementedMethods().iterator(); iter.hasNext(); ) { 410 MethodDecl m = (MethodDecl)iter.next(); 411 set.add(m.sourceMethodDecl()); 412 } 413 for(Iterator iter = super.unimplementedMethods().iterator(); iter.hasNext(); ) { 414 MethodDecl m = (MethodDecl)iter.next(); 415 if(set.contains(m.sourceMethodDecl())) 416 result.add(m); 417 } 418 return result; 419 } 420 421 }