/**
* 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;
}
}