aspect ConstructorExt { syn lazy ConstructorAccess ConstructorDecl.getConstructorAccess() = (ConstructorAccess)((ExprStmt)getConstructorInvocation()).getExpr(); syn boolean ConstructorDecl.isChained() = getConstructorAccess() != null && !(getConstructorAccess() instanceof SuperConstructorAccess); // fill in some missing methods syn ConstructorDecl GenericConstructorDecl.rawConstructor() = lookupParConstructorDecl(new ArrayList()); syn lazy ConstructorDecl GenericConstructorDecl.lookupParConstructorDecl(ArrayList list) { for(int i = 0; i < getNumTypeParameter(); i++) { ParConstructorDecl decl = (ParConstructorDecl)((ParTypeDecl)getTypeParameter(i)); if(decl.isRawConstructor() ? list.isEmpty() : (!list.isEmpty() && decl.sameSignature(list))) return decl; } throw new Error("not implemented yet"); } syn lazy boolean ParConstructorDecl.sameSignature(ArrayList list) circular [true] { if(getNumTypeArgument() != list.size()) return false; for(int i = 0; i < list.size(); i++) if(getTypeArgument(i).type() != list.get(i)) return false; return true; } syn boolean ConstructorDecl.isRawConstructor() = false; eq RawConstructorDecl.isRawConstructor() = true; inh ConstructorDecl TypeDecl.unknownConstructor(); syn lazy ConstructorDecl TypeDecl.constructorSignature(ArrayList parmTypes, boolean isVariableArity) { outer: for(ConstructorDecl ctor : (Collection)constructors()) { if(ctor.isVariableArity() != isVariableArity || ctor.getNumParameter() != parmTypes.size()) continue; for(int i=0;i ConstructorDecl.usesOfAllCopies() { Collection res = new HashSet(uses()); for(ConstructorDecl cd : substitutedCopies()) res.addAll(cd.uses()); return res; } public Collection GenericConstructorDecl.usesOfAllCopies() { Collection res = super.usesOfAllCopies(); res.addAll(parUses()); return res; } public Collection ConstructorDecl.substitutedCopies() { Collection res = new LinkedList(); if(!hostType().isGenericType()) return res; GenericTypeDecl host = (GenericTypeDecl)hostType(); for(int i=0;i GenericConstructorDecl.parUses() [new HashSet()] with add root Program; ClassInstanceExpr contributes this when decl() instanceof ParConstructorDecl to GenericConstructorDecl.parUses() for ((ParConstructorDecl)decl()).sourceConstructorDecl(); ConstructorAccess contributes this when decl() instanceof ParConstructorDecl to GenericConstructorDecl.parUses() for ((ParConstructorDecl)decl()).sourceConstructorDecl(); // create a static factory method that calls the constructor public MethodDecl ConstructorDecl.createFactoryMethod() { if(hostType().isEnumDecl()) throw new RefactoringException("cannot introduce factory method for enum constructor"); String name = "create" + hostType().name(); List parms = new List(); List args = new List(); for(ParameterDeclaration pd : getParameters()) { parms.add((ParameterDeclaration)pd.lockedCopy()); args.add(new VarAccess(pd.name())); } List exns = new List(); for(Access acc : getExceptions()) exns.add(acc.type().createLockedAccess()); Block body = new Block(new List().add(new ReturnStmt(new ClassInstanceExpr(hostType().createLockedAccess(), args)))); MethodDecl factoryMethod = new MethodDecl(new Modifiers("public", "static"), hostType().createLockedAccess(), name, parms, exns, new Opt(body)); hostType().insertUnusedMethod(factoryMethod, 0); factoryMethod = factoryMethod.closeOverTypeVariables(factoryMethod); return factoryMethod; } public MethodDecl ConstructorDeclSubstituted.createFactoryMethod() { return sourceConstructorDecl().createFactoryMethod(); } public MethodDecl ParConstructorDecl.createFactoryMethod() { return sourceConstructorDecl().createFactoryMethod(); } }