aspect LockedConstructor { private boolean ConstructorDecl.locked = false; private void ConstructorDecl.setLocked(boolean value) { locked = value; } public ASTNode ConstructorDecl.lockNames(Collection endangered) { if(!locked && endangered.contains(name())) setLocked(true); return super.lockNames(endangered); } public void ConstructorDecl.eliminateLockedNames() { unlock(); super.eliminateLockedNames(); } public ConstructorDecl ConstructorDecl.unlock() { if(locked) { if(fromSource()) setID(hostType().name()); else throw new RefactoringException("cannot adjust constructor in bytecode"); } setLocked(false); return this; } public boolean ConstructorDecl.isLocked() { return locked; } // locked constructor accesses and class instance expressions are analogous to locked method accesses private ConstructorDecl ConstructorAccess.targetConstructor = null; private ConstructorDecl ClassInstanceExpr.targetConstructor = null; private void ConstructorAccess.setTarget(ConstructorDecl targetConstructor) { this.targetConstructor = targetConstructor; } private void ClassInstanceExpr.setTarget(ConstructorDecl targetConstructor) { this.targetConstructor = targetConstructor; } refine LookupConstructor eq ConstructorAccess.decl() = targetConstructor == null ? refined() : targetConstructor; refine LookupConstructor eq ClassInstanceExpr.decl() = targetConstructor == null ? refined() : targetConstructor; refine TypeAnalysis eq ClassInstanceExpr.type() = targetConstructor == null ? refined() : targetConstructor.hostType(); refine PrettyPrint public void ConstructorAccess.toString(StringBuffer s) { if(targetConstructor == null) { refined(s); } else { s.append("[["); refined(s); s.append("]]"); } } refine PrettyPrint public void ClassInstanceExpr.toString(StringBuffer s) { if(targetConstructor == null) { refined(s); } else { s.append("[["); refined(s); s.append("]]"); } } public void ConstructorAccess.lockConstructorCalls(Collection endangered) { if(endangered.contains(decl().hostType())) lock(); super.lockConstructorCalls(endangered); } public void ClassInstanceExpr.lockConstructorCalls(Collection endangered) { if(endangered.contains(decl().hostType())) lock(); super.lockConstructorCalls(endangered); } public ConstructorAccess ConstructorAccess.lock() { if(targetConstructor == null) lock(decl()); return this; } public ClassInstanceExpr ClassInstanceExpr.lock() { if(targetConstructor == null) lock(decl()); return this; } public ConstructorAccess ConstructorAccess.lock(ConstructorDecl ctor) { assert ctor != null && ctor != unknownConstructor(); setTarget(ctor); return this; } public ClassInstanceExpr ClassInstanceExpr.lock(ConstructorDecl ctor) { assert ctor != null && ctor != unknownConstructor(); setTarget(ctor); return this; } public boolean ConstructorAccess.isLocked() { return targetConstructor != null; } public boolean ClassInstanceExpr.isLocked() { return targetConstructor != null; } public void ConstructorAccess.eliminateLockedNames() { if(targetConstructor != null) unlock(); super.eliminateLockedNames(); } public ConstructorAccess ConstructorAccess.unlock() { ConstructorDecl targetConstructor = this.targetConstructor.refresh(); setTarget(null); flushCache(); if(!decl().equals(targetConstructor)) { if(!fromSource()) throw new RefactoringException("cannot adjust constructor access in library code"); setArgList(MethodAccessInfo.insertCasts(targetConstructor, getArgList())); flushCache(); if(!decl().equals(targetConstructor.refresh())) throw new RefactoringException("cannot disambiguate constructor access"); } return this; } public void ClassInstanceExpr.eliminateLockedNames() { if(targetConstructor != null) unlock(); super.eliminateLockedNames(); } public ClassInstanceExpr ClassInstanceExpr.unlock() { ConstructorDecl targetConstructor = this.targetConstructor.refresh(); setTarget(null); if(fromSource() && getAccess().type() != targetConstructor.hostType()) setAccess(targetConstructor.hostType().createLockedAccess()); flushCache(); if(!decl().equals(targetConstructor)) { if(!fromSource()) throw new RefactoringException("cannot adjust constructor access in library code"); setArgList(MethodAccessInfo.insertCasts(targetConstructor, getArgList())); flushCache(); if(!decl().equals(targetConstructor)) throw new RefactoringException("cannot disambiguate constructor access"); } return this; } }