View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.symboltable;
5   
6   import static org.junit.Assert.assertEquals;
7   import static org.junit.Assert.assertFalse;
8   import static org.junit.Assert.assertTrue;
9   
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.Map;
13  
14  import net.sourceforge.pmd.PMD;
15  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
16  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
17  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
18  import net.sourceforge.pmd.lang.java.ast.DummyJavaNode;
19  import net.sourceforge.pmd.lang.java.ast.JavaNode;
20  import net.sourceforge.pmd.lang.java.symboltable.ClassNameDeclaration;
21  import net.sourceforge.pmd.lang.java.symboltable.ClassScope;
22  import net.sourceforge.pmd.lang.java.symboltable.MethodNameDeclaration;
23  import net.sourceforge.pmd.lang.java.symboltable.NameOccurrence;
24  import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
25  
26  import org.junit.Test;
27  public class ClassScopeTest extends STBBaseTst {
28  
29      @Test
30      public void testEnumsClassScope() {
31          parseCode15(ENUM_SCOPE);
32      }
33  
34      // FIXME - these will break when this goes from Anonymous$1 to Foo$1
35      @Test
36      public void testAnonymousInnerClassName() {
37          ClassScope s = new ClassScope("Foo");
38          s = new ClassScope();
39          assertEquals("Anonymous$1", s.getClassName());
40          s = new ClassScope();
41          assertEquals("Anonymous$2", s.getClassName());
42      }
43  
44      @Test
45      public void testContains() {
46          ClassScope s = new ClassScope("Foo");
47          ASTVariableDeclaratorId node = new ASTVariableDeclaratorId(1);
48          node.setImage("bar");
49          s.addDeclaration(new VariableNameDeclaration(node));
50          assertTrue(s.getVariableDeclarations().keySet().iterator().hasNext());
51      }
52  
53      @Test
54      public void testCantContainsSuperToString() {
55          ClassScope s = new ClassScope("Foo");
56          JavaNode node = new DummyJavaNode(1);
57          node.setImage("super.toString");
58          assertFalse(s.contains(new NameOccurrence(node, node.getImage())));
59      }
60  
61      @Test
62      public void testContainsStaticVariablePrefixedWithClassName() {
63          ClassScope s = new ClassScope("Foo");
64          ASTVariableDeclaratorId node = new ASTVariableDeclaratorId(1);
65          node.setImage("X");
66          s.addDeclaration(new VariableNameDeclaration(node));
67  
68          JavaNode node2 = new DummyJavaNode(2);
69          node2.setImage("Foo.X");
70          assertTrue(s.contains(new NameOccurrence(node2, node2.getImage())));
71      }
72  
73      @Test
74      public void testClassName() {
75          parseCode(CLASS_NAME);
76          ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
77          assertEquals("Foo", n.getScope().getEnclosingClassScope().getClassName());
78      }
79  
80      @Test
81      public void testMethodDeclarationRecorded() {
82          parseCode(METHOD_DECLARATIONS_RECORDED);
83          ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
84          ClassScope s = (ClassScope) n.getScope();
85          Map m = s.getMethodDeclarations();
86          assertEquals(1, m.size());
87          MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next();
88          assertEquals("bar", mnd.getImage());
89          ASTMethodDeclaration node = (ASTMethodDeclaration) mnd.getNode().jjtGetParent();
90          assertTrue(node.isPrivate());
91      }
92  
93      @Test
94      public void testTwoMethodsSameNameDiffArgs() {
95          // TODO this won't work with String and java.lang.String
96          parseCode(METHODS_WITH_DIFF_ARG);
97          ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
98          Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
99          assertEquals(2, m.size());
100         Iterator i = m.keySet().iterator();
101         MethodNameDeclaration mnd = (MethodNameDeclaration) i.next();
102         assertEquals("bar", mnd.getImage());
103         assertEquals("bar", ((MethodNameDeclaration) i.next()).getImage());
104     }
105 
106 
107     @Test
108     public final void testOneParam() throws Throwable {
109         parseCode(ONE_PARAM);
110         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
111         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
112         MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next();
113         assertEquals("(String)", mnd.getParameterDisplaySignature());
114     }
115 
116     @Test
117     public final void testTwoParams() throws Throwable {
118         parseCode(TWO_PARAMS);
119         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
120         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
121         MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next();
122         assertEquals("(String,int)", mnd.getParameterDisplaySignature());
123     }
124 
125     @Test
126     public final void testNoParams() throws Throwable {
127         parseCode(NO_PARAMS);
128         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
129         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
130         MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next();
131         assertEquals("()", mnd.getParameterDisplaySignature());
132     }
133 
134     @Test
135     public final void testOneParamVararg() throws Throwable {
136     	parseCode15(ONE_PARAM_VARARG);
137         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
138         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
139         MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next();
140         assertEquals("(String...)", mnd.getParameterDisplaySignature());
141     }
142 
143     @Test
144     public final void testTwoParamsVararg() throws Throwable {
145     	parseCode15(TWO_PARAMS_VARARG);
146         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
147         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
148         MethodNameDeclaration mnd = (MethodNameDeclaration) m.keySet().iterator().next();
149         assertEquals("(String,String...)", mnd.getParameterDisplaySignature());
150     }
151 
152 
153     @Test
154     public final void testNestedClassDeclFound() throws Throwable {
155         parseCode(NESTED_CLASS_FOUND);
156         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
157         ClassScope c = (ClassScope) n.getScope();
158         Map m = c.getClassDeclarations();
159         ClassNameDeclaration cnd = (ClassNameDeclaration) m.keySet().iterator().next();
160         assertEquals("Buz", cnd.getImage());
161     }
162 
163     @Test
164     public final void testbuz() throws Throwable {
165         parseCode(METH);
166         //SymbolTableViewer st = new SymbolTableViewer();
167         //acu.jjtAccept(st, null);
168     }
169 
170     @Test
171     public void testMethodUsageSeen() {
172         parseCode(METHOD_USAGE_SEEN);
173         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
174         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
175         Iterator i = m.entrySet().iterator();
176         MethodNameDeclaration mnd;
177         Map.Entry entry;
178         
179         do {
180             entry = (Map.Entry) i.next();
181             mnd = (MethodNameDeclaration) entry.getKey();
182         } while (!mnd.getImage().equals("bar"));
183 
184         List usages = (List) entry.getValue();
185         assertEquals(1, usages.size());
186         assertEquals("bar", ((NameOccurrence) usages.get(0)).getImage());
187     }
188 
189     @Test
190     public void testMethodUsageSeenWithThis() {
191         parseCode(METHOD_USAGE_SEEN_WITH_THIS);
192         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
193         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
194         Iterator i = m.entrySet().iterator();
195         MethodNameDeclaration mnd;
196         Map.Entry entry;
197         
198         do {
199             entry = (Map.Entry) i.next();
200             mnd = (MethodNameDeclaration) entry.getKey();
201         } while (!mnd.getImage().equals("bar"));
202 
203         List usages = (List) entry.getValue();
204         assertEquals(1, usages.size());
205         assertEquals("bar", ((NameOccurrence) usages.get(0)).getImage());
206     }
207 
208     @Test
209     public void testMethodUsageSeen2() {
210         parseCode(METHOD_USAGE_SEEN2);
211         ASTClassOrInterfaceDeclaration n = acu.findDescendantsOfType(ASTClassOrInterfaceDeclaration.class).get(0);
212         Map m = ((ClassScope) n.getScope()).getMethodDeclarations();
213         Iterator i = m.entrySet().iterator();
214         Map.Entry entry = (Map.Entry) i.next();
215         MethodNameDeclaration mnd = (MethodNameDeclaration) entry.getKey();
216         if (mnd.getNode().getBeginLine() == 2) {
217             List usages = (List) entry.getValue();
218             System.out.println(usages.size());
219             System.out.println(mnd);
220             mnd = (MethodNameDeclaration) i.next();
221         }
222     }
223 
224     /**
225      * Test case for bug report #2410201
226      */
227     @Test
228     public void testNestedClassFieldAndParameter() {
229     	parseCode(NESTED_CLASS_FIELD_AND_PARAM);
230     	ASTMethodDeclaration node = acu.getFirstDescendantOfType(ASTMethodDeclaration.class);
231     	Map<VariableNameDeclaration, List<NameOccurrence>> vd = node.getScope().getVariableDeclarations();
232     	assertEquals(1, vd.size());
233     	
234     	for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : vd.entrySet()) {
235     		assertEquals("field", entry.getKey().getImage());
236     		
237     		List<NameOccurrence> occurrences = entry.getValue();
238 			assertEquals(2, occurrences.size());
239 			NameOccurrence no1 = occurrences.get(0);
240 			assertEquals(8, no1.getLocation().getBeginLine());
241 			NameOccurrence no2 = occurrences.get(1);
242 			assertEquals(9, no2.getLocation().getBeginLine());
243     	}
244     	
245     }
246 
247     private static final String NESTED_CLASS_FIELD_AND_PARAM =
248             "public class Foo {" + PMD.EOL +
249             " class Test {" + PMD.EOL +
250             "   public String field;" + PMD.EOL +
251             "   public Test t;" + PMD.EOL +
252             " }" + PMD.EOL +
253             " public void foo(String field) {" + PMD.EOL +
254             "   Test t = new Test();" + PMD.EOL +
255             "   t.field = field;" + PMD.EOL +
256             "   t.t.field = field;" + PMD.EOL +
257             " }" + PMD.EOL +
258             "}";
259 
260     private static final String METHOD_USAGE_SEEN2 =
261             "public class Foo {" + PMD.EOL +
262             " public void baz() {" + PMD.EOL +
263             "  baz(x, y);" + PMD.EOL +
264             " }" + PMD.EOL +
265             " private void baz(int x, int y) {}" + PMD.EOL +
266             "}";
267 
268 
269     private static final String METHOD_USAGE_SEEN =
270             "public class Foo {" + PMD.EOL +
271             " private void bar() {}" + PMD.EOL +
272             " public void buz() {" + PMD.EOL +
273             "  bar();" + PMD.EOL +
274             " }" + PMD.EOL +
275             "}";
276 
277     private static final String METHOD_USAGE_SEEN_WITH_THIS =
278             "public class Foo {" + PMD.EOL +
279             " private void bar() {}" + PMD.EOL +
280             " public void buz() {" + PMD.EOL +
281             "  this.bar();" + PMD.EOL +
282             " }" + PMD.EOL +
283             "}";
284 
285 
286     private static final String METH =
287             "public class Test {" + PMD.EOL +
288             "  static { " + PMD.EOL +
289             "   int y; " + PMD.EOL +
290             "  } " + PMD.EOL +
291             "  void bar(int x) {} " + PMD.EOL +
292             "  void baz(int x) {} " + PMD.EOL +
293             "}";
294 
295     private static final String NESTED_CLASS_FOUND =
296             "public class Test {" + PMD.EOL +
297             "  private class Buz {} " + PMD.EOL +
298             "}";
299 
300     private static final String ONE_PARAM =
301             "public class Test {" + PMD.EOL +
302             "  void bar(String x) {" + PMD.EOL +
303             "  }" + PMD.EOL +
304             "}";
305 
306     private static final String TWO_PARAMS =
307             "public class Test {" + PMD.EOL +
308             "  void bar(String x, int y) {" + PMD.EOL +
309             "  }" + PMD.EOL +
310             "}";
311 
312     private static final String NO_PARAMS =
313             "public class Test {" + PMD.EOL +
314             "  void bar() {" + PMD.EOL +
315             "  }" + PMD.EOL +
316             "}";
317 
318     private static final String ONE_PARAM_VARARG =
319             "public class Test {" + PMD.EOL +
320             "  void bar(String... s) {" + PMD.EOL +
321             "  }" + PMD.EOL +
322             "}";
323 
324     private static final String TWO_PARAMS_VARARG =
325             "public class Test {" + PMD.EOL +
326             "  void bar(String s1, String... s2) {" + PMD.EOL +
327             "  }" + PMD.EOL +
328             "}";
329 
330 
331     private static final String CLASS_NAME =
332             "public class Foo {}";
333 
334     private static final String METHOD_DECLARATIONS_RECORDED =
335             "public class Foo {" + PMD.EOL +
336             " private void bar() {}" + PMD.EOL +
337             "}";
338 
339     private static final String METHODS_WITH_DIFF_ARG =
340             "public class Foo {" + PMD.EOL +
341             " private void bar(String x) {}" + PMD.EOL +
342             " private void bar() {}" + PMD.EOL +
343             "}";
344 
345     private static final String ENUM_SCOPE =
346             "public enum Foo {" + PMD.EOL +
347             " HEAP(\"foo\");" + PMD.EOL +
348             " private final String fuz;" + PMD.EOL +
349             " public String getFuz() {" + PMD.EOL +
350             "  return fuz;" + PMD.EOL +
351             " }" + PMD.EOL +
352             "}";
353 
354     public static junit.framework.Test suite() {
355         return new junit.framework.JUnit4TestAdapter(ClassScopeTest.class);
356     }
357 }