/***** BEGIN LICENSE BLOCK ***** * Version: CPL 1.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Common Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/cpl-v10.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2006 Mirko Stocker <me@misto.ch> * Copyright (C) 2007 Thomas Corbat <tcorbat@hsr.ch> * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the CPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the CPL, the GPL or the LGPL. ***** END LICENSE BLOCK *****/ package org.rubypeople.rdt.refactoring.core.inlinemethod; import org.jruby.ast.ArgumentNode; import org.jruby.ast.ArrayNode; import org.jruby.ast.AssignableNode; import org.jruby.ast.InstAsgnNode; import org.jruby.ast.LocalAsgnNode; import org.jruby.ast.LocalVarNode; import org.jruby.ast.MethodDefNode; import org.jruby.ast.MultipleAsgnNode; import org.jruby.ast.NewlineNode; import org.jruby.ast.Node; import org.jruby.ast.types.INameNode; import org.jruby.lexer.yacc.IDESourcePosition; import org.jruby.lexer.yacc.ISourcePosition; import org.rubypeople.rdt.core.formatter.ReWriteVisitor; import org.rubypeople.rdt.refactoring.core.renamelocal.LocalVariableRenamer; import org.rubypeople.rdt.refactoring.documentprovider.DocumentProvider; import org.rubypeople.rdt.refactoring.documentprovider.IDocumentProvider; import org.rubypeople.rdt.refactoring.documentprovider.StringDocumentProvider; import org.rubypeople.rdt.refactoring.nodewrapper.MethodCallNodeWrapper; import org.rubypeople.rdt.refactoring.util.FileHelper; import org.rubypeople.rdt.refactoring.util.NodeUtil; public class ParameterReplacer implements IParameterReplacer { public DocumentProvider replace(IDocumentProvider doc, MethodCallNodeWrapper call, MethodDefNode definition) { DocumentProvider strDoc = new StringDocumentProvider("part_of_" + doc.getActiveFileName(), doc.getActiveFileContent().substring(definition.getPosition().getStartOffset(), definition.getPosition().getEndOffset() + 1)); //$NON-NLS-1$ ArrayNode headList = new ArrayNode(new IDESourcePosition()); ArrayNode tailList = new ArrayNode(new IDESourcePosition()); if(definition.getArgsNode().getArgs() != null && call.getArgsNode() != null) { Object[] defnArguments = definition.getArgsNode().getArgs().childNodes().toArray(); Object[] arguments = call.getArgsNode().childNodes().toArray(); for(int i = 0; i < defnArguments.length; i++) { strDoc = processArguments(strDoc, headList, tailList, (Node) arguments[i], (ArgumentNode) defnArguments[i]); } if(definition.getArgsNode().getRestArg() >= 0) { processRestArg(definition, headList, tailList, defnArguments, arguments); } } if(definition.getArgsNode().getOptArgs() != null) { processOptArgs(definition, headList, tailList); } StringBuffer insert = new StringBuffer(); if(headList.size() > 0) { String lineDelimiter = FileHelper.getLineDelimiter(strDoc.getActiveFileContent()); createAssignments(headList, tailList, insert, lineDelimiter); } MethodDefNode newDefinition = (MethodDefNode) ((NewlineNode) strDoc.getActiveFileRootNode().getBodyNode()).getNextNode(); ISourcePosition bodyPosition = NodeUtil.subPositionUnion(newDefinition.getBodyNode()); insert.append(strDoc.getActiveFileContent().substring( bodyPosition.getStartOffset(), bodyPosition.getEndOffset() + 1).trim()); return new StringDocumentProvider("subpart_of_" + doc.getActiveFileName(), insert.toString()); //$NON-NLS-1$ } private void createAssignments(ArrayNode headList, ArrayNode tailList, StringBuffer insert, String lineDelimiter) { MultipleAsgnNode multipleAsgnNode = new MultipleAsgnNode(new IDESourcePosition(), headList, null); multipleAsgnNode.setValueNode(tailList); insert.append(ReWriteVisitor.createCodeFromNode(multipleAsgnNode, "")); //$NON-NLS-1$ insert.append(lineDelimiter); } private DocumentProvider processArguments(DocumentProvider StringDocumentProvider, ArrayNode headList, ArrayNode tailList, Node node, ArgumentNode arg) { if (node instanceof LocalVarNode || node instanceof InstAsgnNode) { StringDocumentProvider = renameVariable(StringDocumentProvider, (INameNode) node, (INameNode) arg); } else { headList.add(createAssignment(arg.getName())); tailList.add(node); } return StringDocumentProvider; } private void processOptArgs(MethodDefNode definition, ArrayNode headList, ArrayNode tailList) { for(Object obj : definition.getArgsNode().getOptArgs().childNodes()) { assert obj instanceof AssignableNode; headList.add((AssignableNode) obj); tailList.add(((AssignableNode) obj).getValueNode()); ((AssignableNode) obj).setValueNode(null); } } private void processRestArg(MethodDefNode definition, ArrayNode headList, ArrayNode tailList, Object[] defnArguments, Object[] arguments) { String restArgName = definition.getScope().getVariables()[definition.getArgsNode().getRestArg()]; ArrayNode restParams = new ArrayNode(new IDESourcePosition()); for(int i = defnArguments.length; i < arguments.length; i++) { restParams.add((Node) arguments[i]); } headList.add(createAssignment(restArgName)); tailList.add(restParams); } private LocalAsgnNode createAssignment(String name) { return new LocalAsgnNode(new IDESourcePosition(), name, -1, null); } private DocumentProvider renameVariable(DocumentProvider StringDocumentProvider, INameNode varNode, INameNode argumentNode) { return new LocalVariableRenamer(StringDocumentProvider, argumentNode.getName(), varNode.getName()).rename(); } }