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