/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.symboltable; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * Base class for any {@link Scope}. Provides useful default implementations. */ public abstract class AbstractScope implements Scope { private Scope parent; /** Stores the name declaration already sorted by class. */ private Map<Class<? extends NameDeclaration>, Map<NameDeclaration, List<NameOccurrence>>> nameDeclarations = new LinkedHashMap<>(); @Override public Scope getParent() { return parent; } @Override public void setParent(Scope parent) { this.parent = parent; } @Override public Map<NameDeclaration, List<NameOccurrence>> getDeclarations() { Map<NameDeclaration, List<NameOccurrence>> result = new LinkedHashMap<>(); for (Map<NameDeclaration, List<NameOccurrence>> e : nameDeclarations.values()) { result.putAll(e); } return result; } @Override public <T extends NameDeclaration> Map<T, List<NameOccurrence>> getDeclarations(Class<T> clazz) { @SuppressWarnings("unchecked") Map<T, List<NameOccurrence>> result = (Map<T, List<NameOccurrence>>) nameDeclarations.get(clazz); if (result == null) { result = Collections.emptyMap(); } return result; } @Override public boolean contains(NameOccurrence occ) { for (NameDeclaration d : getDeclarations().keySet()) { if (d.getImage().equals(occ.getImage())) { return true; } } return false; } @Override public void addDeclaration(NameDeclaration declaration) { Map<NameDeclaration, List<NameOccurrence>> declarationsPerClass = nameDeclarations.get(declaration.getClass()); if (declarationsPerClass == null) { declarationsPerClass = new LinkedHashMap<>(); nameDeclarations.put(declaration.getClass(), declarationsPerClass); } declarationsPerClass.put(declaration, new ArrayList<NameOccurrence>()); } @SuppressWarnings("unchecked") @Override public <T extends Scope> T getEnclosingScope(Class<T> clazz) { Scope current = this; while (current != null) { if (clazz.isAssignableFrom(current.getClass())) { return (T) current; } current = current.getParent(); } return null; } @Override public Set<NameDeclaration> addNameOccurrence(NameOccurrence occurrence) { Set<NameDeclaration> result = new HashSet<>(); for (Map.Entry<NameDeclaration, List<NameOccurrence>> e : getDeclarations().entrySet()) { if (e.getKey().getImage().equals(occurrence.getImage())) { result.add(e.getKey()); e.getValue().add(occurrence); } } return result; } }