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