	public Change createChange(IProgressMonitor pm) throws CoreException {
		if (fMethodName == null)
			return null;
		pm.beginTask("", 2); 
		try {
			ChangeRecorder cr = new ChangeRecorder(fRoot);
			Node[] nodes = fAnalyzer.getSelectedNodes();
			boolean isExpr = fAnalyzer.isExpressionSelected();
			Map<String,String> renamings = new HashMap<String,String>();
			for (ParameterInfo parameter : fParameterInfos)
				if (parameter.isRenamed())
					renamings.put(parameter.getOldName(),parameter.getNewName());
			for (Node node : nodes) {
				List<Identifier> oldNames = VariableLookup.findReferences(node, renamings.keySet());
				for (Identifier ref : oldNames) {
					ref.setName(renamings.get(ref.getName()));
				}
			}			
			CallExpression invocation= DomFactory.eINSTANCE.createCallExpression();
			{
				VariableReference ref = DomFactory.eINSTANCE.createVariableReference();
				Identifier id = DomFactory.eINSTANCE.createIdentifier();
				id.setName(fMethodName);
				ref.setVariable(id);
				invocation.setApplicant(ref);
			}
			for (ParameterInfo parameter : fParameterInfos) {
				Identifier name = DomFactory.eINSTANCE.createIdentifier();
				name.setName(parameter.getOldName());
				VariableReference local = DomFactory.eINSTANCE.createVariableReference();
				local.setVariable(name);
				invocation.getArguments().add(local);
			}
			if (isExpr) {
				EReference ref = nodes[0].eContainmentFeature();
				if (ref.isMany()) {
					EList<Expression> exprList = (EList<Expression>)nodes[0].eContainer().eGet(ref);
					exprList.set(exprList.lastIndexOf(nodes[0]), (Expression)invocation);
				} else {
					nodes[0].eContainer().eSet(ref, invocation);
				}
			} else {
				Node call;
				int returnKind= fAnalyzer.getReturnKind();
				switch (returnKind) {
				case ExtractMethodAnalyzer.ACCESS_TO_LOCAL:
					VariableBinding binding= fAnalyzer.getReturnLocal();
					if (binding != null) {
						call = createDeclaration(binding, invocation);
					} else {
						BinaryExpression assignment= DomFactory.eINSTANCE.createBinaryExpression();
						assignment.setOperation(BinaryOperator.ASSIGN);
						VariableReference retVar = DomFactory.eINSTANCE.createVariableReference();
						Identifier id = DomFactory.eINSTANCE.createIdentifier();
						id.setName(fAnalyzer.getReturnValue().getName());
						retVar.setVariable(id);
						assignment.setLeft(retVar);
						assignment.setRight(invocation);
						call = assignment;
					}
					break;
				case ExtractMethodAnalyzer.RETURN_STATEMENT_VALUE:
					ReturnStatement rs=DomFactory.eINSTANCE.createReturnStatement();
					rs.setExpression(invocation);
					call = rs;
					break;
				default:
					call = invocation;
				}
				if (call instanceof Expression) {
					ExpressionStatement stmt = DomFactory.eINSTANCE.createExpressionStatement();
					stmt.setExpression((Expression)call);
					call = stmt;
				}
				List<Statement> callNodes= new ArrayList<Statement>(2);
				callNodes.add((Statement)call);
				if (returnKind == ExtractMethodAnalyzer.RETURN_STATEMENT_VOID && !fAnalyzer.isLastStatementSelected()) {
					callNodes.add(DomFactory.eINSTANCE.createReturnStatement());
				}
				for (VariableBinding local : fAnalyzer.getCallerLocals())
					callNodes.add(createDeclaration(local, null));
				EReference ref = nodes[0].eContainmentFeature();
				if (ref.isMany()) {
					EList<Statement> list = (EList<Statement>)nodes[0].eContainer().eGet(ref);
					int index = list.lastIndexOf(nodes[0]);
					for(int i=nodes.length-1;i>=0;i--)
						list.remove(index+i);
					list.addAll(index, callNodes);
				} else if (callNodes.size() == 1) {
					nodes[0].eContainer().eSet(ref, callNodes.get(0));
				} else {
					BlockStatement block = DomFactory.eINSTANCE.createBlockStatement();
					block.getStatements().addAll(callNodes);
					nodes[0].eContainer().eSet(ref, block);
				}				
			}
			FunctionExpression mm = createNewMethodDeclaration();
			List<Statement> statements = mm.getBody().getStatements();
			VariableBinding[] methodLocals= fAnalyzer.getMethodLocals();
			for (int i= 0; i < methodLocals.length; i++) {
				if (methodLocals[i] != null)
					statements.add(createDeclaration(methodLocals[i],null));
			}
			if (isExpr) {
				ReturnStatement rs = DomFactory.eINSTANCE.createReturnStatement();
				rs.setExpression((Expression)nodes[0]);
				statements.add(rs);
			} else {
				for(Node node : nodes) 
					statements.add((Statement)node);
				VariableBinding returnValue= fAnalyzer.getReturnValue();
				if (returnValue != null) {
					ReturnStatement rs = DomFactory.eINSTANCE.createReturnStatement();
					VariableReference ret = DomFactory.eINSTANCE.createVariableReference();
					Identifier rid = DomFactory.eINSTANCE.createIdentifier();
					String name = returnValue.getName();
					if (renamings.containsKey(name))
						name = renamings.get(name);
					rid.setName(name);
					ret.setVariable(rid);
					rs.setExpression(ret);
					statements.add(rs);
				}
			}
			ExpressionStatement stmt = DomFactory.eINSTANCE.createExpressionStatement();
			stmt.setExpression(mm);
			Node enclosing = fDestination;
			EReference ref = enclosing.eContainmentFeature();
			assert ref.isMany();
			EList<Statement> list = (EList<Statement>)enclosing.eContainer().eGet(ref);
			list.add(list.lastIndexOf(enclosing),stmt);
			ChangeDescription cd = cr.endRecording();
			RewriteAnalyzer ra = new RewriteAnalyzer(cd, fSource);
			SourceModuleChange result= new SourceModuleChange(RefactoringCoreMessages.ExtractMethodRefactoring_change_name, fCUnit);
			ra.rewrite(fRoot);
			result.setSaveMode(TextFileChange.KEEP_SAVE_STATE);
			result.setDescriptor(new RefactoringChangeDescriptor(getRefactoringDescriptor()));
			result.setEdit(ra.getEdit());
			cd.apply();
			return result;
		} finally {
			pm.done();
		}
	}

	public Change createChange(IProgressMonitor pm) throws CoreException {
		if (fMethodName == null)
			return null;
		pm.beginTask("", 2); 
		try {
			ChangeRecorder cr = new ChangeRecorder(fRoot);
			Node[] nodes = fAnalyzer.getSelectedNodes();
			boolean isExpr = fAnalyzer.isExpressionSelected();
			Map<String,String> renamings = new HashMap<String,String>();
			for (ParameterInfo parameter : fParameterInfos)
				if (parameter.isRenamed())
					renamings.put(parameter.getOldName(),parameter.getNewName());
			for (Node node : nodes) {
				List<Identifier> oldNames = VariableLookup.findReferences(node, renamings.keySet());
				for (Identifier ref : oldNames) {
					ref.setName(renamings.get(ref.getName()));
				}
			}			
			CallExpression invocation= DomFactory.eINSTANCE.createCallExpression();
			{
				VariableReference ref = DomFactory.eINSTANCE.createVariableReference();
				Identifier id = DomFactory.eINSTANCE.createIdentifier();
				id.setName(fMethodName);
				ref.setVariable(id);
				invocation.setApplicant(ref);
			}
			for (ParameterInfo parameter : fParameterInfos) {
				Identifier name = DomFactory.eINSTANCE.createIdentifier();
				name.setName(parameter.getOldName());
				VariableReference local = DomFactory.eINSTANCE.createVariableReference();
				local.setVariable(name);
				invocation.getArguments().add(local);
			}
			if (isExpr) {
				EReference ref = nodes[0].eContainmentFeature();
				if (ref.isMany()) {
					EList<Expression> exprList = (EList<Expression>)nodes[0].eContainer().eGet(ref);
					exprList.set(exprList.lastIndexOf(nodes[0]), (Expression)invocation);
				} else {
					nodes[0].eContainer().eSet(ref, invocation);
				}
			} else {
				Node call;
				int returnKind= fAnalyzer.getReturnKind();
				switch (returnKind) {
				case ExtractMethodAnalyzer.ACCESS_TO_LOCAL:
					VariableBinding binding= fAnalyzer.getReturnLocal();
					if (binding != null) {
						call = createDeclaration(binding, invocation);
					} else {
						BinaryExpression assignment= DomFactory.eINSTANCE.createBinaryExpression();
						assignment.setOperation(BinaryOperator.ASSIGN);
						VariableReference retVar = DomFactory.eINSTANCE.createVariableReference();
						Identifier id = DomFactory.eINSTANCE.createIdentifier();
						id.setName(fAnalyzer.getReturnValue().getName());
						retVar.setVariable(id);
						assignment.setLeft(retVar);
						assignment.setRight(invocation);
						call = assignment;
					}
					break;
				case ExtractMethodAnalyzer.RETURN_STATEMENT_VALUE:
					ReturnStatement rs=DomFactory.eINSTANCE.createReturnStatement();
					rs.setExpression(invocation);
					call = rs;
					break;
				default:
					call = invocation;
				}
				if (call instanceof Expression) {
					ExpressionStatement stmt = DomFactory.eINSTANCE.createExpressionStatement();
					stmt.setExpression((Expression)call);
					call = stmt;
				}
				List<Statement> callNodes= new ArrayList<Statement>(2);
				callNodes.add((Statement)call);
				if (returnKind == ExtractMethodAnalyzer.RETURN_STATEMENT_VOID && !fAnalyzer.isLastStatementSelected()) {
					callNodes.add(DomFactory.eINSTANCE.createReturnStatement());
				}
				for (VariableBinding local : fAnalyzer.getCallerLocals())
					callNodes.add(createDeclaration(local, null));
				EReference ref = nodes[0].eContainmentFeature();
				if (ref.isMany()) {
					EList<Statement> list = (EList<Statement>)nodes[0].eContainer().eGet(ref);
					int index = list.lastIndexOf(nodes[0]);
					for(int i=nodes.length-1;i>=0;i--)
						list.remove(index+i);
					list.addAll(index, callNodes);
				} else if (callNodes.size() == 1) {
					nodes[0].eContainer().eSet(ref, callNodes.get(0));
				} else {
					BlockStatement block = DomFactory.eINSTANCE.createBlockStatement();
					block.getStatements().addAll(callNodes);
					nodes[0].eContainer().eSet(ref, block);
				}				
			}
			FunctionExpression mm = createNewMethodDeclaration();
			List<Statement> statements = mm.getBody().getStatements();
			VariableBinding[] methodLocals= fAnalyzer.getMethodLocals();
			for (int i= 0; i < methodLocals.length; i++) {
				if (methodLocals[i] != null)
					statements.add(createDeclaration(methodLocals[i],null));
			}
			if (isExpr) {
				ReturnStatement rs = DomFactory.eINSTANCE.createReturnStatement();
				rs.setExpression((Expression)nodes[0]);
				statements.add(rs);
			} else {
				for(Node node : nodes) 
					statements.add((Statement)node);
				VariableBinding returnValue= fAnalyzer.getReturnValue();
				if (returnValue != null) {
					ReturnStatement rs = DomFactory.eINSTANCE.createReturnStatement();
					VariableReference ret = DomFactory.eINSTANCE.createVariableReference();
					Identifier rid = DomFactory.eINSTANCE.createIdentifier();
					String name = returnValue.getName();
					if (renamings.containsKey(name))
						name = renamings.get(name);
					rid.setName(name);
					ret.setVariable(rid);
					rs.setExpression(ret);
					statements.add(rs);
				}
			}
			ExpressionStatement stmt = DomFactory.eINSTANCE.createExpressionStatement();
			stmt.setExpression(mm);
			Node enclosing = fDestination;
			EReference ref = enclosing.eContainmentFeature();
			assert ref.isMany();
			EList<Statement> list = (EList<Statement>)enclosing.eContainer().eGet(ref);
			list.add(list.lastIndexOf(enclosing)+1,stmt);
			ChangeDescription cd = cr.endRecording();
			RewriteAnalyzer ra = new RewriteAnalyzer(cd, fSource);
			SourceModuleChange result= new SourceModuleChange(RefactoringCoreMessages.ExtractMethodRefactoring_change_name, fCUnit);
			ra.rewrite(fRoot);
			result.setSaveMode(TextFileChange.KEEP_SAVE_STATE);
			result.setDescriptor(new RefactoringChangeDescriptor(getRefactoringDescriptor()));
			result.setEdit(ra.getEdit());
			cd.apply();
			return result;
		} finally {
			pm.done();
		}
	}
