blob: 077c7f1ea544101e780f8fe05e35a9ba8e8a68f7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.codehaus.groovy.ast;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Represents a variable scope. This is primarily used to determine variable sharing
* across method and closure boundaries.
*
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
* @author Jochen Theodorou
*/
public class VariableScope {
private Map<String, Variable> declaredVariables = Collections.emptyMap();
private Map<String, Variable> referencedLocalVariables = Collections.emptyMap();
private Map<String, Variable> referencedClassVariables = Collections.emptyMap();
private boolean inStaticContext = false;
private boolean resolvesDynamic = false;
// Non-null iff this scope corresponds to a class, as opposed to a method, "if" statement,
// block statement, etc.
private ClassNode clazzScope;
private VariableScope parent;
public VariableScope() {
}
public VariableScope(VariableScope parent) {
this.parent = parent;
}
public Variable getDeclaredVariable(String name) {
return declaredVariables.get(name);
}
public boolean isReferencedLocalVariable(String name) {
return referencedLocalVariables.containsKey(name);
}
public boolean isReferencedClassVariable(String name) {
return referencedClassVariables.containsKey(name);
}
public VariableScope getParent() {
return parent;
}
public boolean isInStaticContext() {
return inStaticContext;
}
public void setInStaticContext(boolean inStaticContext) {
this.inStaticContext = inStaticContext;
}
public void setClassScope(ClassNode node) {
this.clazzScope = node;
}
/**
* Non-null iff this scope corresponds to a class; as opposed to a method, "if" statement,
* block statement, etc.
*/
public ClassNode getClassScope(){
return clazzScope;
}
/**
* Returns true iff this scope corresponds to a class; as opposed to a method, "if" statement,
* block statement, etc.
*/
public boolean isClassScope(){
return clazzScope!=null;
}
public boolean isRoot() {
return parent==null;
}
public VariableScope copy() {
VariableScope copy = new VariableScope();
copy.clazzScope = clazzScope;
if (!declaredVariables.isEmpty()) {
copy.declaredVariables = new HashMap<String, Variable>();
copy.declaredVariables.putAll(declaredVariables);
}
copy.inStaticContext = inStaticContext;
copy.parent = parent;
if (!referencedClassVariables.isEmpty()) {
copy.referencedClassVariables = new HashMap<String, Variable>();
copy.referencedClassVariables.putAll(referencedClassVariables);
}
if (!referencedLocalVariables.isEmpty()) {
copy.referencedLocalVariables = new HashMap<String, Variable>();
copy.referencedLocalVariables.putAll(referencedLocalVariables);
}
copy.resolvesDynamic = resolvesDynamic;
return copy;
}
public void putDeclaredVariable(Variable var) {
if (declaredVariables == Collections.EMPTY_MAP)
declaredVariables = new HashMap<String, Variable>();
declaredVariables.put(var.getName(), var);
}
public Iterator<Variable> getReferencedLocalVariablesIterator() {
return referencedLocalVariables.values().iterator();
}
public int getReferencedLocalVariablesCount() {
return referencedLocalVariables.size();
}
public Variable getReferencedLocalVariable(String name) {
return referencedLocalVariables.get(name);
}
public void putReferencedLocalVariable(Variable var) {
if (referencedLocalVariables == Collections.EMPTY_MAP)
referencedLocalVariables = new HashMap<String, Variable>();
referencedLocalVariables.put(var.getName(), var);
}
public void putReferencedClassVariable(Variable var) {
if (referencedClassVariables == Collections.EMPTY_MAP)
referencedClassVariables = new HashMap<String, Variable>();
referencedClassVariables.put(var.getName(), var);
}
public Variable getReferencedClassVariable(String name) {
return referencedClassVariables.get(name);
}
public Object removeReferencedClassVariable(String name) {
if (referencedClassVariables == Collections.EMPTY_MAP)
return null;
else
return referencedClassVariables.remove(name);
}
/**
* Gets a map containing the class variables referenced
* by this scope. This not can not be modified.
* @return a map containing the class variable references
*/
public Map<String, Variable> getReferencedClassVariables() {
if (referencedClassVariables == Collections.EMPTY_MAP) {
return referencedClassVariables;
} else {
return Collections.unmodifiableMap(referencedClassVariables);
}
}
/**
* Gets an iterator for the referenced class variables. The
* remove operation is not supported.
* @return an iterator for the referenced class variables
*/
public Iterator<Variable> getReferencedClassVariablesIterator() {
return getReferencedClassVariables().values().iterator();
}
/**
* Gets a map containing the variables declared in this scope.
* This map cannot be modified.
* @return a map containing the declared variable references
*/
public Map<String, Variable> getDeclaredVariables() {
if (declaredVariables == Collections.EMPTY_MAP) {
return declaredVariables;
} else {
return Collections.unmodifiableMap(declaredVariables);
}
}
/**
* Gets an iterator for the declared class variables. The remove
* operation is not supported.
* @return an iterator for the declared variables
*/
public Iterator<Variable> getDeclaredVariablesIterator() {
return getDeclaredVariables().values().iterator();
}
}