aspect LockedOverriding { public void ASTNode.lockOverridingDependencies(String... names) { lockOverridingDependencies(Arrays.asList(names)); } public void ASTNode.lockOverridingDependencies(Collection names) { for(int i=0;i MethodDecl.lockedOverridingDependencies = null; public void MethodDecl.lockOverridingDependencies(Collection names) { if(names.contains(name())) lockOverriding(); super.lockOverridingDependencies(names); } public void MethodDecl.lockOverriding() { if(lockedOverridingDependencies != null) return; HashSet deps = new HashSet(); for(MethodDecl md : overriddenMethods()) deps.add(md.save()); setOverridingDependencies(deps); } public void MethodDecl.lockOverriding(Collection ovr) { HashSet deps = new HashSet(); for(MethodDecl md : ovr) deps.add(md.save()); setOverridingDependencies(deps); } refine Overriding eq MethodDecl.overriddenMethods() { if(lockedOverridingDependencies == null) { return refined(); } else { HashSet res = new HashSet(); for(SavedMethodDecl md : lockedOverridingDependencies) res.add(md.getDecl()); return res; } } refine LookupMethod eq MethodDecl.overrides(MethodDecl m) { if(lockedOverridingDependencies == null) { return refined(m); } else { return overriddenMethods().contains(m); } } private void MethodDecl.setOverridingDependencies(HashSet deps) { if(deps != null) { if(this.isStatic() && !deps.isEmpty()) throw new RefactoringException("static methods cannot override other methods"); for(SavedMethodDecl smd : deps) if(smd.isFinal() || smd.isStatic()) throw new RefactoringException("cannot override static or final method"); } this.lockedOverridingDependencies = deps; } public void MethodDecl.clearOverridingDependencies() { setOverridingDependencies(null); } public static LanguageExtension ASTNode.LOCKED_OVERRIDING = new LanguageExtension("locked overriding") { public void eliminateOn(ASTNode n) { n.unlockOverriding(); n.flushCaches(); } }; public void ASTNode.unlockOverriding() { for(int i=0;i old_overridden = overriddenMethods(); clearOverridingDependencies(); this.flushCaches(); if(!old_overridden.equals(overriddenMethods())) throw new RefactoringException("overriding has changed"); } super.unlockOverriding(); } refine PrettyPrint public void MethodDecl.toString(StringBuffer s) { if(lockedOverridingDependencies != null) s.append("@LockedOverriding\n"); refined(s); } }