View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.symboltable;
5   
6   import java.util.ArrayList;
7   import java.util.LinkedHashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  /**
12   * Base class for any {@link Scope}.
13   * Provides useful default implementations.
14   */
15  public abstract class AbstractScope implements Scope {
16  
17      private Scope parent;
18      /** Stores the name declaration already sorted by class. */
19      private Map<Class<? extends NameDeclaration>, Map<NameDeclaration, List<NameOccurrence>>> nameDeclarations =
20              new LinkedHashMap<Class<? extends NameDeclaration>, Map<NameDeclaration,List<NameOccurrence>>>();
21  
22      @Override
23      public Scope getParent() {
24          return parent;
25      }
26  
27      @Override
28      public void setParent(Scope parent) {
29          this.parent = parent;
30      }
31  
32      @Override
33      public Map<NameDeclaration, List<NameOccurrence>> getDeclarations() {
34          Map<NameDeclaration, List<NameOccurrence>> result = new LinkedHashMap<NameDeclaration, List<NameOccurrence>>();
35          for (Map<NameDeclaration, List<NameOccurrence>> e : nameDeclarations.values()) {
36              result.putAll(e);
37          }
38          return result;
39      }
40  
41      @Override
42      public <T extends NameDeclaration> Map<T, List<NameOccurrence>> getDeclarations(Class<T> clazz) {
43          @SuppressWarnings("unchecked")
44          Map<T, List<NameOccurrence>> result = (Map<T, List<NameOccurrence>>)nameDeclarations.get(clazz);
45          if (result == null) {
46              result = new LinkedHashMap<T, List<NameOccurrence>>();
47          }
48          return result;
49      }
50  
51      @Override
52      public boolean contains(NameOccurrence occ) {
53          for (NameDeclaration d : getDeclarations().keySet()) {
54              if (d.getImage().equals(occ.getImage())) {
55                  return true;
56              }
57          }
58          return false;
59      }
60  
61      @Override
62      public void addDeclaration(NameDeclaration declaration) {
63          Map<NameDeclaration, List<NameOccurrence>> declarationsPerClass = nameDeclarations.get(declaration.getClass());
64          if (declarationsPerClass == null) {
65              declarationsPerClass = new LinkedHashMap<NameDeclaration, List<NameOccurrence>>();
66              nameDeclarations.put(declaration.getClass(), declarationsPerClass);
67          }
68          declarationsPerClass.put(declaration, new ArrayList<NameOccurrence>());
69      }
70  
71      @Override
72      public <T extends Scope> T getEnclosingScope(Class<T> clazz) {
73          T result = null;
74          Scope current = this;
75          while (result == null && current != null) {
76              if (clazz.isAssignableFrom(current.getClass())) {
77                  @SuppressWarnings("unchecked")
78                  T cast = (T)current;
79                  result = cast;
80              }
81              current = current.getParent();
82          }
83          return result;
84      }
85  
86      @Override
87      public NameDeclaration addNameOccurrence(NameOccurrence occurrence) {
88          NameDeclaration result = null;
89          for (Map.Entry<NameDeclaration, List<NameOccurrence>> e : getDeclarations().entrySet()) {
90              if (e.getKey().getImage().equals(occurrence.getImage())) {
91                  result = e.getKey();
92                  e.getValue().add(occurrence);
93              }
94          }
95          return result;
96      }
97  }