package org.cloudsmith.geppetto.ruby.jruby;
import java.util.LinkedList;
import org.jruby.ast.FCallNode;
import org.jruby.ast.FCallTwoArgBlockNode;
import org.jruby.ast.ModuleNode;
import org.jruby.ast.Node;
import com.google.common.collect.Iterables;
public class RubyFunctionCallFinder {
/**
* Returns the first found module with the given qualified name, or null if no such module
* was found. The qualified name should be specified in natural order
* e.g. new String[] { "Puppet", "Parser", "Functions" }.
*
* @param root
* @param qualifiedName
* @return found module or null
*/
public FCallNode findFuntion(ModuleNode root, String name) {
return new FunctionVisitor().findFunction(root, name);
}
private static class FunctionVisitor extends AbstractJRubyVisitor {
/**
* Returned when a visited node detect it is not meaningful to visit its
* children.
*/
public static final Object DO_NOT_VISIT_CHILDREN = new Object();
private ConstEvaluator constEvaluator = new ConstEvaluator();
private String name = null;
public FCallNode findFunction(Node root, String name) {
this.name = name;
return (FCallNode) findFunction(root);
}
/**
* Visits all nodes in graph, and if visitor returns non-null, the iteration stops
* and the returned non-null value is returned.
* @param root
* @return
*/
private Object findFunction(Node root) {
Object r = root.accept(this);
if(r != DO_NOT_VISIT_CHILDREN) {
if(r != null) {
return r;
}
for(Node n : root.childNodes()) {
r = findFunction(n);
if(r != null)
return r;
}
}
return null;
}
@Override
public Object visitFCallNode(FCallNode iVisited) {
if(name.equals(iVisited.getName()))
return iVisited;
return null;
}
}
}