aspect CloseOverVariables { // closing a local class over local variables and type variables public void LocalClassDeclStmt.closeOverLocalVariables() { Map fmap = new HashMap(); for(VarAccess va : localVarAccesses()) getClassDecl().closeOver(va, fmap); } public void ClassDecl.closeOver(VarAccess va, Map fmap) { // only need to close over local variables declared in the enclosing body declaration; // variables further out or further in will still be visible to the new member class ASTNode decl = (ASTNode)va.decl(); if(decl.isDescendantTo(this) || !decl.isDescendantTo(enclosingBodyDecl())) return; FieldDeclaration fd = fmap.get(va.decl()); if(fd == null) { fd = new FreshField(new Modifiers("private", "final"), va.type().createLockedAccess(), va.name(), new Opt()); addBodyDecl(fd); fmap.put((LocalDeclaration)va.decl(), fd); for(ConstructorDecl cd : (Collection)constructors()) { ParameterDeclaration pd = new FreshParameter(va.type().createLockedAccess(), va.name()); cd.insertParameter(pd, 0); ConstructorAccess cacc = cd.getConstructorAccess(); if(cacc instanceof SuperConstructorAccess) { cd.getBlock().insertStmt(0, AssignExpr.asStmt(fd.createLockedAccess(), pd.createLockedAccess())); } else { cacc.insertArg(pd.createLockedAccess(), 0); } } for(Access acc : instantiations()) { if(acc instanceof SuperConstructorAccess) { ((SuperConstructorAccess)acc).insertArg(va.decl().createLockedAccess(), 0); } else if(acc instanceof ClassInstanceExpr) { ((ClassInstanceExpr)acc).insertArg(va.decl().createLockedAccess(), 0); } } } va.lock(fd); } public ClassDecl LocalClassDeclStmt.closeOverTypeVariables() { Map tvmap = new HashMap(); ArrayList tvs = new ArrayList(); ClassDecl cd = getClassDecl(); Collection cd_uses = cd.uses(); for(TypeAccess ta : typeVarAccesses()) { TypeVariable tv = (TypeVariable)ta.decl(); if(tv.owner() == enclosingBodyDecl()) { TypeVariable tv2 = tvmap.get(tv); if(tv2 == null) { if(!cd.isGenericType()) setClassDecl(cd = new GenericClassDecl(cd.getModifiers(), cd.getID(), cd.getSuperClassAccessOpt(), cd.getImplementsList(), cd.getBodyDeclList(), new List())); GenericClassDecl gcd = (GenericClassDecl)cd; gcd.addTypeParameter(tv2 = (TypeVariable)tv.fullCopyAndDetach()); tvmap.put(tv, tv2); tvs.add(tv); } ta.lock(tv2); } } if(tvs.size() > 0) { for(Access tacc : cd_uses) { if(tacc instanceof ParTypeAccess) { ParTypeAccess ptacc = (ParTypeAccess)tacc; for(TypeVariable tv : tvs) ptacc.addTypeArgument(tv.createLockedAccess()); } else { List parms = new List(); for(TypeVariable tv : tvs) parms.add(tv.createLockedAccess()); int idx = tacc.getChildIndex(); ASTNode parent = tacc.getParent(); parent.setChild(new ParTypeAccess(tacc, parms), idx); } } enclosingBodyDecl().flushCaches(); } return cd; } }