1 24 25 package org.aspectj.compiler.base.ast; 26 27 import java.util.*; 28 29 import org.aspectj.compiler.base.*; 30 import org.aspectj.compiler.base.cst.*; 31 import org.aspectj.compiler.crosscuts.*; 33 import org.aspectj.compiler.base.bcg.CodeBuilder; 34 35 40 public class MethodDec extends CodeDec { 41 public MethodDec(SourceLocation source,Modifiers modifiers, TypeD resultTypeD, String id, Formals formals, 43 TypeDs _throws, BlockStmt block) 44 { 45 this(source,modifiers, resultTypeD, id, formals, _throws, blockToBody(block)); 46 } 47 public MethodDec(SourceLocation source,Modifiers modifiers, Type resultType, String id, Formals formals, 48 TypeDs _throws, BlockStmt block) 49 { 50 this(source,modifiers, resultType.makeTypeD(), id, formals, _throws, blockToBody(block)); 51 } 52 53 public ASTObject postFixAST(final ASTFixerPass fixer) { 54 if (this.isIntroduced()) this.getModifiers().setPublic(true); 55 56 if (getBytecodeTypeDec() instanceof InterfaceDec) { 57 this.getModifiers().setValue(Modifiers.ABSTRACT|Modifiers.PUBLIC); 58 this.setBody(null); 59 } 60 return this; 61 } 62 63 public ASTObject postImplementMixin(MixinImplementationPass fixer) { 65 TypeDec inTypeDec = getBytecodeTypeDec(); 66 67 if (!(inTypeDec instanceof InterfaceDec)) return this; 68 69 if (getBody() == null) return this; 70 71 if (isStatic()) { 72 ((InterfaceDec)inTypeDec).addToHelperClass(this); 73 return null; 74 } 75 76 77 this.getModifiers().setFinal(false); 78 this.getModifiers().setPublic(true); 79 80 Set topmostImplementors = 81 Type.filterTopTypes(Type.filterConcreteTypes(inTypeDec.getType().getSubTypes())); 82 83 for (Iterator i = topmostImplementors.iterator(); i.hasNext(); ) { 84 Type implType = (Type)i.next(); 85 TypeDec implDec = implType.getTypeDec(); 86 88 if (!shouldImplement(implDec.getType(), this)) continue; 90 91 MethodDec newDec = (MethodDec)fixer.copyToClass(this, implDec); 92 implDec.getBody().add( newDec ); 94 } 95 96 this.setBody(null); 97 this.getModifiers().setSynchronized(false); 98 return this; 99 } 100 101 102 boolean shouldImplement(Type onType, Dec dec) { 103 Dec existingDec = onType.findMatchingDec(dec); 104 if (existingDec != null && existingDec != dec) return false; 105 106 Dec owner = dec.owner; 107 if (owner != null) return shouldImplement(onType, owner); 108 else return true; 109 } 110 111 public void preScope(ScopeWalker walker) { 113 walker.addMethodDec(this); 114 super.preScope(walker); 115 } 116 117 public Expr getExpr() { return null; } 118 119 public String toShortString() { 120 return addIntroducedFromType( 121 modifiers.toShortString() + " " + resultTypeD.toShortString() + " " + 122 getDeclaringType().toShortString()+"." + id + 123 formals.toShortString()); 124 } 125 126 public String getKind() { return "method"; } 127 128 public SemanticObject makeCorrespondingSemanticObject() { 129 return new Method(this); 130 } 131 132 public Method getMethod() { return (Method)getCorrespondingSemanticObject(); } 133 134 MethodDec makeSuperCaller() { 135 final AST ast = getAST(); 136 137 Modifiers modifiers = ast.makeModifiers(0); 138 if (isProtected()) modifiers.setProtected(); 139 if (isPublic()) modifiers.setPublic(true); 140 141 Type resultType = getResultType(); 142 Formals formals = (Formals)getFormals().copy(); 143 CallExpr superCall = ast.makeSuperCall(getMethod(), formals.makeExprs()); 144 145 Stmt stmt; 146 if (resultType.isVoid()) { 147 stmt = ast.makeStmt(superCall); 148 } else { 149 stmt = ast.makeReturn(superCall); 150 } 151 152 MethodDec ret = ast.makeMethod(modifiers, resultType, getId(), 153 formals, ast.makeBlock(stmt)); 154 if (getThrows() != null) { 155 ret.setThrows((TypeDs)getThrows().copy()); 156 } 157 return ret; 158 } 159 160 public void checkSpec() { 161 super.checkSpec(); 162 if (getModifiers().isAbstract()) { 163 if (getModifiers().isStrict()) { 164 getModifiers().showError("illegal combination of modifiers: abstract strictfp"); 165 } else if (getModifiers().isPrivate()) { 166 if (!isIntroduced()) { 167 showError("abstract private method can never be implemented"); 168 } 169 } else if (getModifiers().isStatic()) { 170 getModifiers().showError("illegal combination of modifiers: abstract static"); 171 } 172 } 173 if (isAbstract() || getModifiers().isNative()) { 174 if (getBody() != null) { 175 showError("abstract or native methods cannot have a body"); 176 } 177 } else { 178 if (getBody() == null) { 179 showError("non-abstract/native methods must have a body"); 180 } 181 } 182 } 183 184 void showOverrideError(Type inType, MethodDec other, String message) { 185 if (getDeclaringType() != inType) { 186 inType.getTypeDec().showError("inherited method " + this.toShortString() + 187 " is incompatible with inherited method " + other.toShortString() + 188 "; " + message); 189 } else { 190 String overrideKind = "override"; 191 if (other.getDeclaringType().isInterface()) { 192 overrideKind = "implement"; 193 } 194 showError(toShortString() + " cannot " + overrideKind + " " + 195 other.toShortString() + "; " + message); 196 } 197 } 198 199 public boolean isEffectivelyAbstract(Type inType) { 200 return isAbstract() || 201 (inType.isInterface() && getDeclaringType().isObject()); 202 } 203 204 public boolean checkOverride(Type inType, Dec otherDec) { 205 MethodDec other = (MethodDec)otherDec; 206 207 211 if (getDeclaringType() != inType) { 213 if (isEffectivelyAbstract(inType)) { 214 if (!other.isEffectivelyAbstract(inType)) { 215 other.internalCheckOverride(inType, this); 216 return true; 217 } else { 218 if (getModifiers().isWeakerThan(other.getModifiers())) { 219 other.internalCheckOverride(inType, this); 220 return true; 221 } else { 222 this.internalCheckOverride(inType, other); 223 return false; 224 } 225 } 226 } else { 227 if (other.isEffectivelyAbstract(inType)) { 228 this.internalCheckOverride(inType, other); 229 return false; 230 } else if (this.overrides(other)) { 231 this.internalCheckOverride(inType, other); 232 return false; 233 } else if (other.overrides(this)) { 234 other.internalCheckOverride(inType, this); 235 return true; 236 } else { 237 showOverrideError(inType, other, "both methods are concrete"); 238 return false; 239 } 240 } 241 } else { 242 this.internalCheckOverride(inType, other); 243 return false; 244 } 245 } 246 247 private void internalCheckOverride(Type inType, MethodDec other) { 248 if (!getResultType().isEquivalent(other.getResultType())) { 249 showOverrideError(inType, other, 250 "attempting to use incompatible return type\n" + 251 "found : " + getResultType().getString() + "\n" + 252 "required: " + other.getResultType().getString()); 253 } else if (other.getModifiers().isFinal()) { 254 showOverrideError(inType, other, "overridden method is final"); 255 } else if (other.isStatic() && !this.isStatic()) { 256 showOverrideError(inType, other, "overridden method is static"); 257 } else if (this.isStatic() && !other.isStatic()) { 258 showOverrideError(inType, other, "overridden method is non-static"); 259 } else if (getModifiers().isWeakerThan(other.getModifiers())) { 260 showOverrideError(inType, other, 261 "attempting to assign weaker access privileges; was " + 262 other.getModifiers().toShortString()); 263 } else if (_throws != null) { 264 for (int i=0; i<_throws.size(); i++) { 266 if (!other.canThrow(_throws.get(i).getType())) { 267 showOverrideError(inType, other, 268 "overridden method does not throw " + 269 _throws.get(i).getType().getString()); 270 break; 271 } 272 } 273 } 274 275 return; 276 } 277 278 279 public boolean overrides(MethodDec other) { 280 for (Iterator i = getDeclaringType().getDirectSuperTypes().iterator(); i.hasNext(); ) { 281 Type type = (Type)i.next(); 282 MethodDec dec = (MethodDec)type.findMatchingDec(this); 283 if (dec == null) continue; 284 if (dec == other) return true; 285 if (dec == this) { 286 getCompiler().internalError(this, "nonsense"); 287 return false; 288 } 289 if (dec.overrides(other)) return true; 290 } 291 return false; 292 } 293 294 public Set getMatchingMethods() { 295 Set ret = new HashSet(); 296 297 for (Iterator i = getDeclaringType().getSubTypes().iterator(); i.hasNext(); ) { 298 Type type = (Type)i.next(); 299 MethodDec dec = (MethodDec)type.findMatchingDec(this); 300 if (dec != null) ret.add(dec); 301 } 302 303 return ret; 304 } 305 306 316 private Set matchingSignatureTypes = null; 317 318 public Set getMatchingSignatureTypes() { 319 if (matchingSignatureTypes == null) { 320 Set s = new HashSet(); 321 addMatchingSignatureTypes(s, getDeclaringType()); 322 } 323 return matchingSignatureTypes; 324 } 325 326 private void addMatchingSignatureTypes(Set s, Type myType) { 327 if (s.contains(myType)) { 329 if (matchingSignatureTypes != s) { 330 getCompiler().internalError(this, 331 "bad invariant in collecting matching signatures"); 332 } 333 return; 334 } 335 336 matchingSignatureTypes = s; 337 338 s.add(myType); 339 340 addMatchingSignaturesIn(s, myType.getDirectSubTypes()); 341 addMatchingSignaturesIn(s, myType.getDirectSuperTypes()); 342 } 343 344 private void addMatchingSignaturesIn(Set s, Collection types) { 345 for (Iterator i = types.iterator(); i.hasNext(); ) { 346 Type type = (Type)i.next(); 347 MethodDec dec = (MethodDec)type.findMatchingDec(this); 349 if (dec != null) { 350 dec.addMatchingSignatureTypes(s, type); 351 } 352 } 353 } 354 355 372 375 private MethodDec backdoorMethod; 376 377 public MethodDec getBackdoorMethod() { 378 if (backdoorMethod != null) return backdoorMethod; 379 380 final AST ast = getAST(); 381 String id = getBytecodeId() + "$ajc$backdoor"; 382 383 Modifiers modifiers = ast.makeModifiers(Modifiers.FINAL|Modifiers.PUBLIC); 384 if (isStatic()) modifiers.setStatic(true); 385 386 Formals formals = (Formals)getFormals().copy(); 387 Expr thisExpr; 388 if (isStatic()) thisExpr = ast.makeTypeExpr(getBytecodeTypeDec().getType()); 389 else thisExpr = ast.makeThis(getBytecodeTypeDec().getType()); 390 391 CallExpr innerCall = ast.makeCall(this, thisExpr, formals.makeExprs()); 392 Stmt stmt; 393 if (resultTypeD.getType().isEquivalent(getTypeManager().voidType)) { 394 stmt = ast.makeStmt(innerCall); 395 } else { 396 stmt = ast.makeReturn(innerCall); 397 } 398 399 MethodDec ret = ast.makeMethod(modifiers, getResultType(), id, formals, 400 ast.makeBlock(stmt)); 401 ret.getBody().setParsed(true); 402 if (getThrows() != null) { 403 ret.setThrows((TypeDs)getThrows().copy()); 404 } 405 406 getDeclaringType().getTypeDec().addToBody(ret); 407 408 backdoorMethod = ret; 409 return backdoorMethod; 410 } 411 412 413 public void unparse(CodeWriter writer) { 414 if (getBytecodeTypeDec() instanceof InterfaceDec && (isPrivate() || isFinal())) { 415 return; 416 } 417 418 writeModifiers(writer); 419 writer.write(resultTypeD); 420 writer.requiredSpace(); 421 writer.write(getBytecodeId()); 422 writer.write(formals); 423 424 writeNames(writer, "throws", getThrows()); 425 426 if (!writer.isOnlySignatures()) { 427 if (body == null) { 428 writer.closeStmt(); 429 } else { 430 writer.optionalSpace(); 431 writer.write(body); 432 } 433 writer.newLine(); 434 } 435 } 436 437 440 protected void cgCodeMember(CodeBuilder cb) { 441 cb.setMaxFrame(getFrameSize()); 442 cb.enterBlock(); 443 Formals f = getFormals(); 444 for (int i = 0, len = f.size(); i < len; i++) { 445 cb.enterVar(f.get(i)); 446 } 447 getBody().cgTop(cb); 448 cb.exitBlock(); 449 } 450 451 private String descriptor; 452 public synchronized String getDescriptor() { 453 if (descriptor == null) { 454 descriptor = "("; 455 456 for (Iterator i = getFormals().iterator(); i.hasNext(); ) { 457 FormalDec dec = (FormalDec)i.next(); 458 descriptor += dec.getType().getDescriptor(); 459 } 460 descriptor += ")"; 461 descriptor += getResultType().getDescriptor(); 462 } 463 return descriptor; 464 } 465 466 private boolean isDeltaComputed = false; 467 private int stackDelta; 468 public synchronized int getStackDelta() { 469 if (!isDeltaComputed) { 470 stackDelta = getResultType().getSlotCount(); 471 if (!isStatic()) stackDelta--; 472 for (Iterator i = getFormals().iterator(); i.hasNext(); ) { 473 FormalDec dec = (FormalDec)i.next(); 474 stackDelta -= dec.getType().getSlotCount(); 475 } 476 isDeltaComputed = true; 477 } 478 return stackDelta; 479 } 480 481 484 public void preThreading(LocalClassPass.ThreadingWalker walker) { 485 walker.pushNonConstructorEnv(); 486 } 487 488 public ASTObject postThreading(LocalClassPass.ThreadingWalker walker) { 489 walker.popEnv(); 490 return this; 491 } 492 493 protected TypeD resultTypeD; 495 public TypeD getResultTypeD() { return resultTypeD; } 496 public void setResultTypeD(TypeD _resultTypeD) { 497 if (_resultTypeD != null) _resultTypeD.setParent(this); 498 resultTypeD = _resultTypeD; 499 } 500 501 protected String id; 502 public String getId() { return id; } 503 public void setId(String _id) { id = _id; } 504 505 public MethodDec(SourceLocation location, Modifiers _modifiers, TypeD _resultTypeD, String _id, Formals _formals, TypeDs __throws, CodeBody _body) { 506 super(location, _modifiers, _formals, __throws, _body); 507 setResultTypeD(_resultTypeD); 508 setId(_id); 509 } 510 protected MethodDec(SourceLocation source) { 511 super(source); 512 } 513 514 public ASTObject copyWalk(CopyWalker walker) { 515 MethodDec ret = new MethodDec(getSourceLocation()); 516 ret.preCopy(walker, this); 517 if (modifiers != null) ret.setModifiers( (Modifiers)walker.process(modifiers) ); 518 if (resultTypeD != null) ret.setResultTypeD( (TypeD)walker.process(resultTypeD) ); 519 ret.id = id; 520 if (formals != null) ret.setFormals( (Formals)walker.process(formals) ); 521 if (_throws != null) ret.setThrows( (TypeDs)walker.process(_throws) ); 522 if (body != null) ret.setBody( (CodeBody)walker.process(body) ); 523 return ret; 524 } 525 526 public ASTObject getChildAt(int childIndex) { 527 switch(childIndex) { 528 case 0: return modifiers; 529 case 1: return resultTypeD; 530 case 2: return formals; 531 case 3: return _throws; 532 case 4: return body; 533 default: return super.getChildAt(childIndex); 534 } 535 } 536 public String getChildNameAt(int childIndex) { 537 switch(childIndex) { 538 case 0: return "modifiers"; 539 case 1: return "resultTypeD"; 540 case 2: return "formals"; 541 case 3: return "throws"; 542 case 4: return "body"; 543 default: return super.getChildNameAt(childIndex); 544 } 545 } 546 public void setChildAt(int childIndex, ASTObject child) { 547 switch(childIndex) { 548 case 0: setModifiers((Modifiers)child); return; 549 case 1: setResultTypeD((TypeD)child); return; 550 case 2: setFormals((Formals)child); return; 551 case 3: setThrows((TypeDs)child); return; 552 case 4: setBody((CodeBody)child); return; 553 default: super.setChildAt(childIndex, child); return; 554 } 555 } 556 public int getChildCount() { 557 return 5; 558 } 559 560 public String getDefaultDisplayName() { 561 return "MethodDec(id: "+id+")"; 562 } 563 564 } 566 | Popular Tags |