1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package test.net.sourceforge.pmd.testframework;
5   
6   import net.sourceforge.pmd.TargetJDKVersion;
7   import net.sourceforge.pmd.ast.ASTCompilationUnit;
8   import net.sourceforge.pmd.ast.JavaParser;
9   import net.sourceforge.pmd.ast.JavaParserVisitor;
10  import net.sourceforge.pmd.dfa.DataFlowFacade;
11  import net.sourceforge.pmd.symboltable.SymbolFacade;
12  
13  import java.io.StringReader;
14  import java.lang.reflect.InvocationHandler;
15  import java.lang.reflect.Method;
16  import java.lang.reflect.Proxy;
17  import java.util.ArrayList;
18  import java.util.Collection;
19  import java.util.HashSet;
20  import java.util.List;
21  import java.util.Set;
22  
23  public abstract class ParserTst {
24  
25      private class Collector<E> implements InvocationHandler {
26          private Class<E> clazz = null;
27          private Collection<E> collection;
28  
29          public Collector(Class<E> clazz) {
30              this(clazz, new HashSet<E>());
31          }
32  
33          public Collector(Class<E> clazz, Collection<E> coll) {
34              this.clazz = clazz;
35              this.collection = coll;
36          }
37  
38          public Collection<E> getCollection() {
39              return collection;
40          }
41  
42          public Object invoke(Object proxy, Method method, Object params[]) throws Throwable {
43              if (method.getName().equals("visit")) {
44                  if (clazz.isInstance(params[0])) {
45                      collection.add((E) params[0]);
46                  }
47              }
48  
49              Method childrenAccept = params[0].getClass().getMethod("childrenAccept", new Class[]{JavaParserVisitor.class, Object.class});
50              childrenAccept.invoke(params[0], new Object[]{proxy, null});
51              return null;
52          }
53      }
54  
55      public <E> Set<E> getNodes(Class<E> clazz, String javaCode) throws Throwable {
56          return getNodes(TargetJDKVersion.DEFAULT_JDK_VERSION, clazz, javaCode);
57      }
58  
59      public <E> Set<E> getNodes(TargetJDKVersion jdk, Class<E> clazz, String javaCode) throws Throwable {
60          Collector<E> coll = new Collector<E>(clazz);
61          JavaParser parser = jdk.createParser(new StringReader(javaCode));
62          ASTCompilationUnit cu = parser.CompilationUnit();
63          JavaParserVisitor jpv = (JavaParserVisitor) Proxy.newProxyInstance(JavaParserVisitor.class.getClassLoader(), new Class[]{JavaParserVisitor.class}, coll);
64          jpv.visit(cu, null);
65          return (Set<E>) coll.getCollection();
66      }
67  
68      public <E> List<E> getOrderedNodes(Class<E> clazz, String javaCode) throws Throwable {
69          Collector<E> coll = new Collector<E>(clazz, new ArrayList<E>());
70          JavaParser parser = TargetJDKVersion.DEFAULT_JDK_VERSION.createParser(new StringReader(javaCode));
71          ASTCompilationUnit cu = parser.CompilationUnit();
72          JavaParserVisitor jpv = (JavaParserVisitor) Proxy.newProxyInstance(JavaParserVisitor.class.getClassLoader(), new Class[]{JavaParserVisitor.class}, coll);
73          jpv.visit(cu, null);
74          SymbolFacade sf = new SymbolFacade();
75          sf.initializeWith(cu);
76          DataFlowFacade dff = new DataFlowFacade();
77          dff.initializeWith(cu);
78          return (List<E>) coll.getCollection();
79      }
80  
81      public ASTCompilationUnit buildDFA(String javaCode) throws Throwable {
82          JavaParser parser = TargetJDKVersion.DEFAULT_JDK_VERSION.createParser(new StringReader(javaCode));
83          ASTCompilationUnit cu = parser.CompilationUnit();
84          JavaParserVisitor jpv = (JavaParserVisitor) Proxy.newProxyInstance(JavaParserVisitor.class.getClassLoader(), new Class[]{JavaParserVisitor.class}, new Collector<ASTCompilationUnit>(ASTCompilationUnit.class));
85          jpv.visit(cu, null);
86          new SymbolFacade().initializeWith(cu);
87          new DataFlowFacade().initializeWith(cu);
88          return cu;
89      }
90  }