View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.symboltable;
5   
6   import java.util.List;
7   
8   import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
9   import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
10  import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
11  import net.sourceforge.pmd.lang.symboltable.Scope;
12  
13  public class OccurrenceFinder extends JavaParserVisitorAdapter {
14  
15      public Object visit(ASTPrimaryExpression node, Object data) {
16          NameFinder nameFinder = new NameFinder(node);
17  
18          // Maybe do some sort of State pattern thingy for when NameDeclaration
19          // is null/not null?
20          NameDeclaration decl = null;
21  
22          List<JavaNameOccurrence> names = nameFinder.getNames();
23          for (JavaNameOccurrence occ : names) {
24              Search search = new Search(occ);
25              if (decl == null) {
26                  // doing the first name lookup
27                  search.execute();
28                  decl = search.getResult();
29                  if (decl == null) {
30                      // we can't find it, so just give up
31                      // when we decide to do full symbol resolution
32                      // force this to either find a symbol or throw a
33                      // SymbolNotFoundException
34                      break;
35                  }
36              } else {
37                  // now we've got a scope we're starting with, so work from there
38                  Scope startingScope = decl.getScope();
39                  // in case the previous found declaration is a class reference
40                  // for a class inside the same source file
41                  // we need to search this class
42                  // e.g. the list of name occurrence could come from
43                  // outerClassRef.member. See also bug #1302
44                  if (decl instanceof VariableNameDeclaration) {
45                      String typeImage = ((VariableNameDeclaration) decl).getTypeImage();
46                      ClassNameDeclaration clazzDeclaration = startingScope.getEnclosingScope(SourceFileScope.class)
47                              .findClassNameDeclaration(typeImage);
48                      if (clazzDeclaration != null) {
49                          startingScope = clazzDeclaration.getScope();
50                      }
51                  }
52                  search.execute(startingScope);
53                  decl = search.getResult();
54  
55                  if (decl == null) {
56                      // nothing found
57                      // This seems to be a lack of type resolution here.
58                      // Theoretically we have the previous declaration node and
59                      // know from there the Type of
60                      // the variable. The current occurrence (occ) should then be
61                      // found in the declaration of
62                      // this type. The type however may or may not be known to
63                      // PMD (see aux classpath).
64  
65                      // we can't find it, so just give up
66                      // when we decide to do full symbol resolution
67                      // force this to either find a symbol or throw a
68                      // SymbolNotFoundException
69                      break;
70                  }
71              }
72          }
73          return super.visit(node, data);
74      }
75  
76  }