/***** 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 Lukas Felber <lfelber@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; import java.util.ArrayList; import java.util.Collection; import java.util.Locale; import org.jruby.ast.ArgsCatNode; import org.jruby.ast.ArgsNode; import org.jruby.ast.ArgumentNode; import org.jruby.ast.ArrayNode; import org.jruby.ast.BlockArgNode; import org.jruby.ast.BlockNode; import org.jruby.ast.CallNode; import org.jruby.ast.ClassNode; import org.jruby.ast.ClassVarAsgnNode; import org.jruby.ast.ClassVarNode; import org.jruby.ast.Colon2ImplicitNode; import org.jruby.ast.Colon3Node; import org.jruby.ast.CommentNode; import org.jruby.ast.ConstDeclNode; import org.jruby.ast.ConstNode; import org.jruby.ast.DVarNode; import org.jruby.ast.DefnNode; import org.jruby.ast.DefsNode; import org.jruby.ast.FCallNode; import org.jruby.ast.FCallOneArgNode; import org.jruby.ast.InstAsgnNode; import org.jruby.ast.InstVarNode; import org.jruby.ast.ListNode; import org.jruby.ast.LocalAsgnNode; import org.jruby.ast.LocalVarNode; import org.jruby.ast.MultipleAsgnNode; import org.jruby.ast.NewlineNode; import org.jruby.ast.Node; import org.jruby.ast.RestArgNode; import org.jruby.ast.SelfNode; import org.jruby.ast.SuperNode; import org.jruby.ast.SymbolNode; import org.jruby.ast.VCallNode; import org.jruby.ast.ZSuperNode; import org.jruby.lexer.yacc.IDESourcePosition; import org.jruby.lexer.yacc.ISourcePosition; import org.jruby.parser.LocalStaticScope; import org.jruby.parser.StaticScope; import org.rubypeople.rdt.refactoring.nodewrapper.ArgsNodeWrapper; import org.rubypeople.rdt.refactoring.nodewrapper.AttrAccessorNodeWrapper; import org.rubypeople.rdt.refactoring.nodewrapper.VisibilityNodeWrapper; import org.rubypeople.rdt.refactoring.util.Constants; public class NodeFactory { public static final Node NULL_POSITION_NODE = new NewlineNode(new IDESourcePosition(), null); public static FCallNode createSimpleAccessorNode(String definitionName, String attrName) { ArrayNode argsNode = new ArrayNode(new IDESourcePosition()); argsNode.add(new SymbolNode(new IDESourcePosition(), attrName)); return new FCallOneArgNode(new IDESourcePosition(), definitionName, argsNode); } public static DefsNode createStaticMethodNode(String methodName, Collection<String> args, StaticScope scopeNode, Node body) { return createStaticMethodNode( "self", methodName, createArgsNode(args.toArray(new String[args.size()])), scopeNode == null ? new LocalStaticScope(null) : scopeNode, body); //$NON-NLS-1$ } public static DefnNode createMethodNode(String methodName, String[] args, Node scopeContentNode) { ArgsNode argsNode = createArgsNode(args); return createMethodNode(methodName, argsNode, scopeContentNode); } public static DefnNode createMethodNode(String methodName, ArgsNode argsNode, Node body) { ArgumentNode methodNameNode = new ArgumentNode(new IDESourcePosition(), methodName); return new DefnNode(new IDESourcePosition(), methodNameNode, argsNode, new LocalStaticScope(null), body != null ? new NewlineNode(body.getPosition(), body) : null); } public static DefnNode createMethodNodeWithoutNewline(String methodName, ArgsNode argsNode, Node body) { ArgumentNode methodNameNode = new ArgumentNode(new IDESourcePosition(), methodName); return new DefnNode(new IDESourcePosition(), methodNameNode, argsNode, new LocalStaticScope(null), body); } public static DefsNode createStaticMethodNode(String className, String methodName, ArgsNodeWrapper argsNode, StaticScope scopeNode) { return createStaticMethodNode(className, methodName, argsNode.getWrappedNode(), scopeNode, null); } public static DefsNode createStaticMethodNode(String className, String methodName, ArgsNode argsNode, StaticScope scopeNode, Node body) { return new DefsNode(new IDESourcePosition(), createConstNode(className), createArgumentNode(methodName), argsNode, scopeNode, body); } public static ArgsNode createArgsNode(String... args) { return createArgsNode(args, null, -1, null, null); } public static ArgsNode createArgsNode(Collection<String> args) { return createArgsNode(args.toArray(new String[args.size()])); } public static ArgsNode createArgsNode(String[] args, ListNode optArgs, int restArgs, RestArgNode restArgNode, BlockArgNode blockArg) { ListNode argumentsList = null; if (args.length > 0) { argumentsList = new ListNode(new IDESourcePosition()); for (String arg : args) argumentsList.add(new ArgumentNode(new IDESourcePosition(), arg)); } ArgsNode argsNode = new ArgsNode(new IDESourcePosition(), argumentsList, optArgs, restArgNode, null, blockArg); return argsNode; } public static DefnNode createConstructor(BlockNode content) { return createMethodNode(Constants.CONSTRUCTOR_NAME, new String[] {}, content); } public static DefnNode createDefaultConstructor() { return createConstructor(new BlockNode(new IDESourcePosition())); } public static InstAsgnNode createInstAsgnNode(String name, Node valueNode) { return new InstAsgnNode(new IDESourcePosition(), name, valueNode); } public static InstVarNode createInstVarNode(String name) { return new InstVarNode(new IDESourcePosition(), name); } public static Node createSuperNode(Collection<String> args) { if (args.isEmpty()) { return new ZSuperNode(new IDESourcePosition()); } ArrayNode argsNode = createArrayNodeWithLocalVarNodes(args); return new SuperNode(new IDESourcePosition(), argsNode); } private static ArrayNode createArrayNodeWithLocalVarNodes(Collection<String> args) { ArrayNode arrayNode = new ArrayNode(new IDESourcePosition()); for (String name : args) { arrayNode.add(new LocalVarNode(new IDESourcePosition(), 0, name)); } return arrayNode; } public static BlockNode createBlockNode() { return new BlockNode(new IDESourcePosition()); } public static BlockNode createBlockNode(Node... content) { BlockNode blockNode = new BlockNode(new IDESourcePosition()); for (Node node : content) { blockNode.add(node); } return blockNode; } public static BlockNode createBlockNode(boolean needsNewLineAtEndOfBlock, Node... contentNodes) { return createBlockNode(true, needsNewLineAtEndOfBlock, contentNodes); } public static BlockNode createBlockNode(boolean leadingNewLine, boolean subsequentNewline, Node... contentNodes) { return createBlockNode(leadingNewLine, subsequentNewline, false, contentNodes); } public static BlockNode createBlockNode(boolean leadingNewLine, boolean subsequentNewline, boolean newLineBetweenNodes, Node... contentNodes) { BlockNode blockNode = createBlockNode(); if (leadingNewLine) { blockNode.add(NodeFactory.createNewLineNode(null)); } for (Node aktContentNode : contentNodes) { if (newLineBetweenNodes) { blockNode.add(createNewLineNode(aktContentNode)); } else { blockNode.add(aktContentNode); } } if (subsequentNewline) { blockNode.add(NodeFactory.createNewLineNode(null)); } return blockNode; } public static NewlineNode createNewLineNode(Node nextNode) { return new NewlineNode(new IDESourcePosition(), nextNode); } public static ListNode createListNode(Collection<? extends Node> nodes) { ListNode listNode = new ListNode(new IDESourcePosition()); for (Node aktNode : nodes) { listNode.add(aktNode); } return listNode; } public static ListNode createListNode() { return new ListNode(new IDESourcePosition()); } public static ClassNode createClassNode(String className, Node bodyNode) { Colon2ImplicitNode classNameNode = new Colon2ImplicitNode(new IDESourcePosition(), className); return new ClassNode(new IDESourcePosition(), classNameNode, new LocalStaticScope(null), bodyNode, null); } public static Node createCommentNode(String commentValue) { return new CommentNode(new IDESourcePosition(), commentValue); } public static ClassVarNode createClassVarNode(String name) { return new ClassVarNode(new IDESourcePosition(), name); } public static ClassVarAsgnNode createClassVarAsgnNode(String name, Node valueNode) { return new ClassVarAsgnNode(new IDESourcePosition(), name, valueNode); } public static Node createMethodCallNode(String name, Collection<? extends Node> arguments) { if (arguments == null || arguments.isEmpty()) { return createVCallNode(name); } return createFCallNode(name, arguments); } public static Node createMethodCallNode(String name, Node argsNode) { if (argsNode == null) { return createVCallNode(name); } return createFCallNode(name, argsNode); } public static FCallNode createFCallNode(String name, Collection<? extends Node> arguments) { return new FCallNode(new IDESourcePosition(), name, createArrayNode(arguments)); } public static FCallNode createFCallNode(String name, Node argumentNode) { return new FCallNode(new IDESourcePosition(), name, argumentNode); } public static ArrayNode createArrayNode(Collection<? extends Node> nodes) { ArrayNode arrNode = new ArrayNode(new IDESourcePosition()); for (Node aktNode : nodes) { arrNode.add(aktNode); } return arrNode; } public static Node createVCallNode(String name) { return new VCallNode(new IDESourcePosition(), name); } public static LocalAsgnNode createLocalAsgnNode(String name, int id, Node valueNode) { return new LocalAsgnNode(new IDESourcePosition(), name, id, valueNode); } public static MultipleAsgnNode createMultipleAsgnNode(Collection<? extends Node> headNodes, Node valueNode) { ListNode listNode = createListNode(headNodes); MultipleAsgnNode multipleAsgnNode = new MultipleAsgnNode(new IDESourcePosition(), listNode, null); multipleAsgnNode.setValueNode(valueNode); return multipleAsgnNode; } public static SymbolNode createSymboleNode(String symbolName) { return new SymbolNode(new IDESourcePosition(), symbolName); } public static DVarNode createDVarNode(String name) { return new DVarNode(new IDESourcePosition(), 0, name); } public static ISourcePosition unionPositions(ISourcePosition first, ISourcePosition second) { String fileName = first.getFile(); int startOffset = first.getStartOffset(); int endOffset = first.getEndOffset(); int startLine = first.getStartLine(); int endLine = first.getEndLine(); if (startOffset > second.getStartOffset()) { startOffset = second.getStartOffset(); startLine = second.getStartLine(); } if (endOffset < second.getEndOffset()) { endOffset = second.getEndOffset(); endLine = second.getEndLine(); } return new IDESourcePosition(fileName, startLine, endLine, startOffset, endOffset); } public static BlockNode createGetterSetter(String attrName, boolean isWriterMethod, VisibilityNodeWrapper.METHOD_VISIBILITY visibility) { return createGetterSetter(attrName, isWriterMethod, visibility, new ArrayList<CommentNode>()); } public static BlockNode createGetterSetter(String attrName, boolean isWriterMethod, VisibilityNodeWrapper.METHOD_VISIBILITY visibility, Collection<CommentNode> comments) { String methodName = attrName + ((isWriterMethod) ? "=" : ""); //$NON-NLS-1$ //$NON-NLS-2$ String[] args = (isWriterMethod) ? new String[] { attrName } : new String[] {}; DefnNode methodNode = createGetterSetterNode(isWriterMethod, methodName, attrName, args); methodNode.addComments(comments); BlockNode block = createBlockNode(); block.add(createNewLineNode(methodNode)); if (!visibility.equals(VisibilityNodeWrapper.METHOD_VISIBILITY.NONE)) block.add(createVisibilityNode(visibility, methodName)); return block; } public static Node createVisibilityNode(VisibilityNodeWrapper.METHOD_VISIBILITY visibility, String... methodNames) { Collection<Node> arguments = new ArrayList<Node>(); for (String methodName : methodNames) { SymbolNode symbolNode = NodeFactory.createSymboleNode(methodName); arguments.add(symbolNode); } FCallNode fCallNode = NodeFactory.createFCallNode(visibility.name().toLowerCase(Locale.ENGLISH), arguments); return NodeFactory.createNewLineNode(fCallNode); } private static DefnNode createGetterSetterNode(boolean isWriterMethod, String methodName, String attrName, String[] args) { Node bodyContent; if (isWriterMethod) bodyContent = NodeFactory.createInstAsgnNode('@' + attrName, NodeFactory.createLocalVarNode(attrName)); else bodyContent = NodeFactory.createInstVarNode('@' + attrName); DefnNode methodNode = NodeFactory.createMethodNode(methodName, args, bodyContent); return methodNode; } public static CallNode createCallNode(Node receiverNode, String name, Node argsNode) { return new CallNode(new IDESourcePosition(), receiverNode, name, argsNode, null); } public static ArgumentNode createArgumentNode(String name) { return new ArgumentNode(new IDESourcePosition(), name); } public static FCallNode createAccessorNode(AttrAccessorNodeWrapper accessor) { ArrayNode argsNode = new ArrayNode(new IDESourcePosition()); argsNode.add(new SymbolNode(new IDESourcePosition(), accessor.getAttrName())); return new FCallOneArgNode(new IDESourcePosition(), accessor.getAccessorTypeName(), argsNode); } public static ConstNode createConstNode(String name) { return new ConstNode(new IDESourcePosition(), name); } public static ArgsCatNode createArgsCatNode(Node firstNode, Node secondNode) { return new ArgsCatNode(new IDESourcePosition(), firstNode, secondNode); } public static SelfNode createSelfNode() { return new SelfNode(new IDESourcePosition()); } public static ArrayNode createArrayNode() { return new ArrayNode(new IDESourcePosition()); } public static Node createLocalVarNode(String argName) { return new LocalVarNode(new IDESourcePosition(), 0, argName); } public static Node createConstDeclNode(String name, Node valueNode) { return new ConstDeclNode(new IDESourcePosition(), name, null, valueNode); } }