/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ruby.core.ast;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jrubyparser.StaticScope;
import org.jrubyparser.ast.ArgsNode;
import org.jrubyparser.ast.ArgumentNode;
import org.jrubyparser.ast.CallNode;
import org.jrubyparser.ast.ClassNode;
import org.jrubyparser.ast.Colon2Node;
import org.jrubyparser.ast.ConstNode;
import org.jrubyparser.ast.DAsgnNode;
import org.jrubyparser.ast.DStrNode;
import org.jrubyparser.ast.FCallNode;
import org.jrubyparser.ast.FalseNode;
import org.jrubyparser.ast.FixnumNode;
import org.jrubyparser.ast.HashNode;
import org.jrubyparser.ast.IArgumentNode;
import org.jrubyparser.ast.INameNode;
import org.jrubyparser.ast.IterNode;
import org.jrubyparser.ast.ListNode;
import org.jrubyparser.ast.LiteralNode;
import org.jrubyparser.ast.LocalAsgnNode;
import org.jrubyparser.ast.ModuleNode;
import org.jrubyparser.ast.MultipleAsgnNode;
import org.jrubyparser.ast.NilNode;
import org.jrubyparser.ast.Node;
import org.jrubyparser.ast.SelfNode;
import org.jrubyparser.ast.StrNode;
import org.jrubyparser.ast.SymbolNode;
import org.jrubyparser.ast.TrueNode;
import org.jrubyparser.ast.ZArrayNode;
import com.aptana.core.util.ArrayUtil;
import com.aptana.core.util.StringUtil;
public class ASTUtils
{
private static final String EMPTY_STRING = StringUtil.EMPTY;
private static final String NAMESPACE_DELIMETER = "::"; //$NON-NLS-1$
public static String[] getArgs(ArgsNode argsNode, StaticScope scope)
{
if (argsNode == null)
{
return ArrayUtil.NO_STRINGS;
}
List<String> arguments = getArguments(argsNode.getPre());
if (argsNode.getOptionalCount() > 0)
{
arguments.addAll(getArguments(argsNode.getOptional()));
}
if (argsNode.getRest() != null)
{
arguments.add("*" + argsNode.getRest().getName()); //$NON-NLS-1$
}
if (argsNode.getBlock() != null)
{
arguments.add("&" + scope.getVariables()[argsNode.getBlock().getCount()]); //$NON-NLS-1$
}
return arguments.toArray(new String[arguments.size()]);
}
public static List<String> getArguments(ListNode argList)
{
if (argList == null)
{
return new ArrayList<String>();
}
List<String> arguments = new ArrayList<String>();
List<Node> childNodes = argList.childNodes();
for (Node node : childNodes)
{
if (node instanceof ArgumentNode)
{
arguments.add(((ArgumentNode) node).getName());
}
else if (node instanceof LocalAsgnNode)
{
LocalAsgnNode local = (LocalAsgnNode) node;
arguments.add(MessageFormat.format("{0} = {1}", local.getName(), getStringRepresentation(local //$NON-NLS-1$
.getValueNode())));
}
}
return arguments;
}
public static List<String> getArgumentsFromFunctionCall(IArgumentNode iVisited)
{
List<String> arguments = new ArrayList<String>();
List<Node> nodes = getArgumentNodesFromFunctionCall(iVisited);
for (Node node : nodes)
{
if (node instanceof DAsgnNode)
{
arguments.add(((DAsgnNode) node).getName());
}
else
{
arguments.add(getStringRepresentation(node));
}
}
return arguments;
}
public static List<Node> getArgumentNodesFromFunctionCall(IArgumentNode iVisited)
{
List<Node> arguments = new ArrayList<Node>();
Node argsNode = iVisited.getArgsNode();
Iterator<Node> iter = null;
if (argsNode != null)
{
iter = argsNode.childNodes().iterator();
}
else
{
// block?
Node iterNode = null;
if (iVisited instanceof FCallNode)
{
iterNode = ((FCallNode) iVisited).getIterNode();
}
else if (iVisited instanceof CallNode)
{
iterNode = ((CallNode) iVisited).getIterNode();
}
if (iterNode == null)
{
return arguments;
}
if (iterNode instanceof IterNode)
{
// yup, it has a block
IterNode yeah = (IterNode) iterNode;
Node varNode = yeah.getVarNode();
if (varNode instanceof DAsgnNode)
{
// single variable in the block
arguments.add(varNode);
}
else if (varNode instanceof MultipleAsgnNode)
{
// multiple variables in the block
MultipleAsgnNode multi = (MultipleAsgnNode) varNode;
ListNode list = multi.getHeadNode();
if (list != null)
{
iter = list.childNodes().iterator();
}
else
{
Node multiArgsNode = multi.getArgsNode();
if (multiArgsNode instanceof DAsgnNode)
{
arguments.add(multiArgsNode);
}
}
}
}
}
if (iter == null)
{
return arguments;
}
while (iter.hasNext())
{
arguments.add(iter.next());
}
return arguments;
}
public static String getFullyQualifiedName(Node node)
{
if (node == null)
{
return EMPTY_STRING;
}
if (node instanceof ConstNode)
{
return ((ConstNode) node).getName();
}
if (node instanceof Colon2Node)
{
Colon2Node colonNode = (Colon2Node) node;
String prefix = getFullyQualifiedName(colonNode.getLeftNode());
if (prefix.length() > 0)
{
prefix = prefix + NAMESPACE_DELIMETER;
}
return prefix + colonNode.getName();
}
return getName(node);
}
public static String getFullyQualifiedName(Colon2Node node)
{
StringBuilder name = new StringBuilder();
Node left = node.getLeftNode();
if (left instanceof Colon2Node)
{
name.append(getFullyQualifiedName((Colon2Node) left));
}
else if (left instanceof ConstNode)
{
name.append(((ConstNode) left).getName());
}
name.append(NAMESPACE_DELIMETER).append(node.getName());
return name.toString();
}
public static String getName(Node node)
{
if (node == null)
{
return EMPTY_STRING;
}
if (node instanceof ClassNode)
{
return getName(((ClassNode) node).getCPath());
}
if (node instanceof ModuleNode)
{
return getName(((ModuleNode) node).getCPath());
}
if (node instanceof INameNode)
{
return ((INameNode) node).getName();
}
if (node instanceof LiteralNode)
{
return ((LiteralNode) node).getName();
}
// tries reflection
try
{
Method getNameMethod = node.getClass().getMethod("getName", new Class[] {}); //$NON-NLS-1$
Object name = getNameMethod.invoke(node, ArrayUtil.NO_OBJECTS);
return (String) name;
}
catch (Exception e)
{
return EMPTY_STRING;
}
}
public static String getStringRepresentation(Node node)
{
if (node == null)
{
return StringUtil.EMPTY;
}
if (node instanceof HashNode)
{
return "{}"; //$NON-NLS-1$
}
if (node instanceof SelfNode)
{
return "self"; //$NON-NLS-1$
}
if (node instanceof NilNode)
{
return "nil"; //$NON-NLS-1$
}
if (node instanceof TrueNode)
{
return "true"; //$NON-NLS-1$
}
if (node instanceof FalseNode)
{
return "false"; //$NON-NLS-1$
}
if (node instanceof SymbolNode)
{
return ':' + ((SymbolNode) node).getName();
}
if (node instanceof INameNode)
{
return ((INameNode) node).getName();
}
if (node instanceof ZArrayNode)
{
return "[]"; //$NON-NLS-1$
}
if (node instanceof FixnumNode)
{
return String.valueOf(((FixnumNode) node).getValue());
}
if (node instanceof StrNode)
{
return '"' + ((StrNode) node).getValue() + '"';
}
if (node instanceof DStrNode)
{
List<Node> children = node.childNodes();
StringBuilder text = new StringBuilder();
text.append('"');
for (Node child : children)
{
text.append(getStringRepresentation(child));
}
text.append('"');
return text.toString();
}
return node.toString();
}
}