package dk.brics.jsrefactoring; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import dk.brics.jsparser.analysis.DepthFirstAdapter; import dk.brics.jsparser.node.Node; /** * Utility class for finding all nodes of a given type; caches results for improved performance. * * @author max.schaefer@comlab.ox.ac.uk * */ @SuppressWarnings({ "unchecked", "rawtypes" }) public class NodeFinder { private List<InputFile> allFiles; private Map<Class, Set<Node>> cache = new LinkedHashMap<Class, Set<Node>>(); public NodeFinder(Master master, Class... types) { this.allFiles = master.getAllInputFiles(); findNodes(types); } private void findNodes(final Class... types) { for(Class type : types) if(!cache.containsKey(type)) cache.put(type, new LinkedHashSet<Node>()); for (InputFile file : allFiles) { file.getAst().apply(new DepthFirstAdapter() { @Override public void defaultIn(Node node) { for(Class type : types) { if(type.isInstance(node)) { cache.get(type).add(node); } } } }); } } /** * <p> * Returns every AST node of the given type (or a subtype thereof), * including the AST of harness files. Use {@link Master#isNativeCode(Node)} * to determine if an AST node is from a harness file. * </p> * @param <T> the type of node to get * @param type class or interface object for the type to get * @return a newly created set */ public <T> Set<T> getAllNodesOfType(Class<T> type) { if(!cache.containsKey(type)) findNodes(type); return (Set<T>)Collections.unmodifiableSet(cache.get(type)); } }