package org.rubypeople.rdt.internal.ti;
import java.util.Iterator;
import org.jruby.ast.ArgsNode;
import org.jruby.ast.ArgumentNode;
import org.jruby.ast.ArrayNode;
import org.jruby.ast.CallNode;
import org.jruby.ast.ClassNode;
import org.jruby.ast.Colon2Node;
import org.jruby.ast.FCallNode;
import org.jruby.ast.ListNode;
import org.jruby.ast.MethodDefNode;
import org.jruby.ast.ModuleNode;
import org.jruby.ast.Node;
import org.jruby.ast.VCallNode;
import org.jruby.ast.types.INameNode;
public class TypeInferenceHelper {
//Singleton pattern
private TypeInferenceHelper() {}
private static TypeInferenceHelper staticInstance = new TypeInferenceHelper();
public static TypeInferenceHelper Instance() {
return staticInstance;
}
/**
* Extracts the name of a variable from a VarNode
* @param node LocalVarNode, InstVarNode, or GlobalVarNode referring to a variable.
* @return Name of the variable.
*/
public String getVarName(Node node)
{
if(node instanceof INameNode) {
return ((INameNode) node).getName();
}
return null;
}
public int getArgIndex(ListNode listNode, String argName)
{
int argNumber = 0;
for ( Iterator iter = listNode.childNodes().iterator(); iter.hasNext();) {
if (((ArgumentNode)iter.next()).getName().equals(argName)) { return argNumber; }
argNumber++;
}
return -1;
}
public String getTypeNodeName( Node node ) {
if ( node instanceof ClassNode ) { return ((Colon2Node)((ClassNode)node).getCPath()).getName(); }
if ( node instanceof ModuleNode ) { return ((Colon2Node)((ModuleNode)node).getCPath()).getName(); }
return null;
}
public String getMethodDefinitionNodeName(Node methodNode) {
if ( methodNode instanceof MethodDefNode ) return ((MethodDefNode)methodNode).getName();
return null;
}
public boolean isArgumentInMethod( String varName, Node enclosingScopeNode ) {
ListNode listNode = getArgsListNode( enclosingScopeNode );
// If the args node cannot be located, varName is probably not an arg ;)
if ( listNode == null ) {
return false;
}
// See if the method contains the variable by name
return ( getArgIndex( listNode, varName ) >= 0 );
}
public ListNode getArgsListNode( Node node ) {
if ( node instanceof MethodDefNode ) { return (((MethodDefNode)node).getArgsNode() ).getArgs(); }
if ( node instanceof CallNode ) { return ((ArgsNode)( ((CallNode)node).getArgsNode() )).getArgs(); }
//TODO: Is ArrayNode the proper cast?
if ( node instanceof FCallNode ) { return (ArrayNode)( ((FCallNode)node).getArgsNode() ); }
// VCallNode is a node w/o args
return null;
}
public String getCallNodeMethodName( Node node ) {
if ( node instanceof CallNode ) { return ((CallNode)node).getName(); }
if ( node instanceof FCallNode ) { return ((FCallNode)node).getName(); }
if ( node instanceof VCallNode ) { return ((VCallNode)node).getName(); }
return null;
}
public Node findNthArgExprInSendExpr( int n, Node sendExprNode ) {
ListNode listNode = getArgsListNode( sendExprNode );
if ( listNode == null ) {
return null;
}
return listNode.get(n);
}
}