/* * The Rename Method refactoring */ aspect RenameMethod { // rename a method and all its relatives public void MethodDecl.rename(String new_name) { if(name().equals(new_name)) return; if(!isValidName(new_name)) throw new RefactoringException("not a valid name: "+new_name); programRoot().lockMethodNames(name(), new_name); programRoot().lockOverridingDependencies(name(), new_name); for(MethodDecl md : relatives()) { md.checkRenamingPreconds(new_name); md.setID(new_name); } programRoot().eliminate(LOCKED_NAMES, LOCKED_OVERRIDING); } private void MethodDecl.checkRenamingPreconds(String new_name) { if(!fromSource() || isNative()) throw new RefactoringException("cannot rename binary/native method"); String sig = signature(); int idx = sig.indexOf('('); String new_sig = new_name + sig.substring(idx); if(!hostType().canIntroduceMethod(this, new_sig)) throw new RefactoringException("cannot introduce new method"); } public boolean TypeDecl.canIntroduceMethod(MethodDecl md) { return canIntroduceMethod(md, md.signature()); } public boolean TypeDecl.canIntroduceMethod(MethodDecl md, String sig) { if(md.isStatic() && isInnerClass()) return false; // make sure there isn't already a different method with the same signature in this type /* Note: To make it easier to compute attributes on md, we allow md to already be in * this type. But then we cannot use localMethodsSignature directly to determine * whether there is another method of the same signature, as it returns at most one * result. So we temporarily remove md from this (if it is indeed a child), flush * the local methods signature map, query for local methods of this signature, * put md back in again (if it was in before), and flush again. * Ugly, I know. */ int idx = getBodyDeclList().getIndexOfChild(md); if(idx != -1) { getBodyDeclList().removeChild(idx); localMethodsSignatureMap_computed = false; } boolean found = !localMethodsSignature(sig).isEmpty(); if(idx != -1) { getBodyDeclList().insertChild(md, idx); localMethodsSignatureMap_computed = false; } if(found) return false; // if there are any like-named methods in superclasses, we must be able to override or hide them // compare TypeDecl.typeCheck() for(Iterator i = ancestorMethods(sig).iterator();i.hasNext();) { MethodDecl md2 = (MethodDecl)i.next(); if(!md.canOverrideOrHide(md2)) return false; } for(MethodDecl md2 : descendantMethods(sig)) if(!md2.canOverrideOrHide(md)) return false; return true; } }