View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.plsql.symboltable;
5   
6   import java.util.HashSet;
7   import java.util.List;
8   import java.util.Set;
9   import java.util.logging.Level;
10  import java.util.logging.Logger;
11  
12  import net.sourceforge.pmd.lang.plsql.ast.ASTPrimaryExpression;
13  import net.sourceforge.pmd.lang.plsql.ast.PLSQLParserVisitorAdapter;
14  import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
15  import net.sourceforge.pmd.lang.symboltable.Scope;
16  
17  public class OccurrenceFinder extends PLSQLParserVisitorAdapter {
18      private final static Logger LOGGER = Logger.getLogger(OccurrenceFinder.class.getName()); 
19  
20      public Object visit(ASTPrimaryExpression node, Object data) {
21          NameFinder nameFinder = new NameFinder(node);
22  
23          // Maybe do some sort of State pattern thingy for when NameDeclaration
24          // is empty/not empty
25          Set<NameDeclaration> declarations = new HashSet<>();
26  
27          List<PLSQLNameOccurrence> names = nameFinder.getNames();
28          for (PLSQLNameOccurrence occ: names) {
29              Search search = new Search(occ);
30              if (declarations.isEmpty()) {
31                  // doing the first name lookup
32                  search.execute();
33                  declarations.addAll(search.getResult());
34                  if (declarations.isEmpty()) {
35                      // we can't find it, so just give up
36                      // when we decide to do full symbol resolution
37                      // force this to either find a symbol or throw a SymbolNotFoundException
38                      break;
39                  }
40              } else {
41                  Set<NameDeclaration> additionalDeclarations = new HashSet<>();
42                  for (NameDeclaration decl : declarations) {
43                      // now we've got a scope we're starting with, so work from there
44                      Scope scope = decl.getScope();
45                      if (null == scope) {
46                          if (LOGGER.isLoggable(Level.FINEST)) {
47                              LOGGER.finest("NameOccurrence has no Scope:" 
48                                            + decl.getClass().getCanonicalName() 
49                                            +"=>"+decl.getImage()
50                                          );
51                          }
52                        break;
53                      }
54                      search.execute(scope);
55                      Set<NameDeclaration> found = search.getResult();
56                      additionalDeclarations.addAll(found);
57                      if (found.isEmpty()) {
58                          // nothing found
59                          // This seems to be a lack of type resolution here.
60                          // Theoretically we have the previous declaration node and know from there the Type of
61                          // the variable. The current occurrence (occ) should then be found in the declaration of
62                          // this type. The type however may or may not be known to PMD (see aux classpath).
63      
64                          // we can't find it, so just give up
65                          // when we decide to do full symbol resolution
66                          // force this to either find a symbol or throw a SymbolNotFoundException
67                          break;
68                      }
69                  }
70                  declarations.addAll(additionalDeclarations);
71              }
72          }
73          return super.visit(node, data);
74      }
75  
76  }