blob: dd9b91a64ffa8615f242887a6383186f712864c9 [file] [log] [blame]
// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed 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 com.google.devtools.build.lib.syntax;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.Mutability.Freezable;
import com.google.devtools.build.lib.syntax.Mutability.MutabilityException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Base class for data structures that are only mutable with a proper Mutability.
*/
abstract class SkylarkMutable implements Freezable, SkylarkValue {
protected SkylarkMutable() {}
/**
* Check whether this object is mutable in the current evaluation Environment.
* @throws EvalException if the object was not mutable.
*/
protected void checkMutable(Location loc, Environment env) throws EvalException {
try {
Mutability.checkMutable(this, env);
} catch (MutabilityException ex) {
throw new EvalException(loc, ex);
}
}
@Override
public boolean isImmutable() {
return !mutability().isMutable();
}
@Override
public String toString() {
return Printer.repr(this);
}
abstract static class MutableCollection<E> extends SkylarkMutable implements Collection<E> {
protected MutableCollection() {}
/**
* The underlying contents is a (usually) mutable data structure.
* Read access is forwarded to these contents.
* This object must not be modified outside an {@link Environment}
* with a correct matching {@link Mutability},
* which should be checked beforehand using {@link #checkMutable}.
* it need not be an instance of {@link com.google.common.collect.ImmutableCollection}.
*/
protected abstract Collection<E> getContentsUnsafe();
@Override
public Iterator<E> iterator() {
return getContentsUnsafe().iterator();
};
@Override
public int size() {
return getContentsUnsafe().size();
}
@Override
public final Object[] toArray() {
return getContentsUnsafe().toArray();
}
@Override
public final <Object> Object[] toArray(Object[] other) {
return getContentsUnsafe().toArray(other);
}
@Override
public boolean isEmpty() {
return getContentsUnsafe().isEmpty();
}
@Override
public final boolean contains(@Nullable Object object) {
return getContentsUnsafe().contains(object);
}
@Override
public final boolean containsAll(Collection<?> collection) {
return getContentsUnsafe().containsAll(collection);
}
// Disable all mutation interfaces without a mutation context.
@Deprecated
@Override
public final boolean add(E element) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final boolean addAll(Collection<? extends E> collection) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final boolean remove(Object object) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final boolean removeAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final boolean retainAll(Collection<?> collection) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean equals(Object o) {
return getContentsUnsafe().equals(o);
}
@Override
public int hashCode() {
return getContentsUnsafe().hashCode();
}
}
abstract static class MutableMap<K, V> extends SkylarkMutable implements Map<K, V> {
MutableMap() {}
/**
* The underlying contents is a (usually) mutable data structure.
* Read access is forwarded to these contents.
* This object must not be modified outside an {@link Environment}
* with a correct matching {@link Mutability},
* which should be checked beforehand using {@link #checkMutable}.
*/
protected abstract Map<K, V> getContentsUnsafe();
// A SkylarkDict forwards all read-only access to the contents.
@Override
public final V get(Object key) {
return getContentsUnsafe().get(key);
}
@Override
public boolean containsKey(Object key) {
return getContentsUnsafe().containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return getContentsUnsafe().containsValue(value);
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
return getContentsUnsafe().entrySet();
}
@Override
public Set<K> keySet() {
return getContentsUnsafe().keySet();
}
@Override
public Collection<V> values() {
return getContentsUnsafe().values();
}
@Override
public int size() {
return getContentsUnsafe().size();
}
@Override
public boolean isEmpty() {
return getContentsUnsafe().isEmpty();
}
// Disable all mutation interfaces without a mutation context.
@Deprecated
@Override
public final V put(K key, V value) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final void putAll(Map<? extends K, ? extends V> map) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final V remove(Object key) {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public final void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean equals(Object o) {
return getContentsUnsafe().equals(o);
}
@Override
public int hashCode() {
return getContentsUnsafe().hashCode();
}
}
}