aspect AddParameter { public void MethodDecl.addParameter(ParameterDeclaration pd, int idx, Literal value, boolean createDelegate) { if(idx < 0 || idx > getNumParameter()) throw new RefactoringException("invalid index for new parameter"); programRoot().lockMethodNames(name()); programRoot().lockOverridingDependencies(name()); Collection relatives = relatives(); for(MethodDecl md : relatives()) { if(!md.parameterDeclaration(pd.name()).isEmpty()) throw new RefactoringException("parameter of same name exists"); if(idx == md.getNumParameter() && md.isVariableArity()) throw new RefactoringException("cannot insert parameter after vararg"); if(idx != md.getNumParameter() && pd.isVariableArity()) throw new RefactoringException("cannot insert vararg parameter anywhere except in last position"); // TODO: use locked copy Collection uses = md.uses(); if(createDelegate) { MethodDecl delegate = (MethodDecl)md.fullCopyAndDetach(); if(!md.hostType().isInterfaceDecl()) { delegate.getModifiers().removeModifiers("abstract", "native"); List args = new List(); for(ParameterDeclaration mdpd : md.getParameters()) args.add(new VarAccess(mdpd.name())); args.insertChild((Expr)value.fullCopyAndDetach(), idx); delegate.setBlock(new Block(new List().add(new ReturnStmt(md.createLockedAccess(args))))); } md.hostType().getBodyDeclList().insertChild(delegate, md.getChildIndex()); } ParameterDeclaration pd_copy = (ParameterDeclaration) pd.fullCopyAndDetach(); md.getParameterList().insertChild(pd_copy, idx); for(MethodAccess ma : uses) { if(relatives.contains(ma.hostBodyDecl())) { ma.getArgList().insertChild(new VarAccess(pd.name()), idx); } else { Expr arg = (Expr)value.fullCopyAndDetach(); ma.getArgList().insertChild(arg, idx); if(!arg.type().methodInvocationConversionTo(pd_copy.type())) throw new RefactoringException("Default value does not have right type."); } } } } public void MethodDecl.doAddParameter(ParameterDeclaration pd, int idx, Literal value, boolean createDelegate) { addParameter(pd, idx, value, createDelegate); programRoot().eliminate(RETURN_VOID, LOCKED_NAMES, LOCKED_OVERRIDING); } }