// Copyright 2014 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.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import com.google.devtools.build.lib.util.LoggingUtil;
import com.google.devtools.build.lib.util.StringCanonicalizer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
import javax.annotation.Nullable;
/**
*
Root of Type symbol hierarchy for values in the build language.
*
*
Type symbols are primarily used for their convert method,
* which is a kind of cast operator enabling conversion from untyped (Object)
* references to values in the build language, to typed references.
*
*
For example, this code type-converts a value x returned by
* the evaluator, to a list of strings:
*
*
* Object x = expr.eval(env);
* List<String> s = Type.STRING_LIST.convert(x);
*
*/
public abstract class Type {
protected Type() {}
/**
* Converts untyped Object x resulting from the evaluation of an expression in the build language,
* into a typed object of type T.
*
*
x must be *directly* convertible to this type. This therefore disqualifies "selector
* expressions" of the form "{ config1: 'value1_of_orig_type', config2: 'value2_of_orig_type; }"
* (which support configurable attributes). To handle those expressions, see
* {@link com.google.devtools.build.lib.packages.BuildType#selectableConvert}.
*
* @param x the build-interpreter value to convert.
* @param what a string description of what x is for; should be included in
* any exception thrown. Grammatically, must describe a syntactic
* construct, e.g. "attribute 'srcs' of rule foo".
* @param context the label of the current BUILD rule; must be non-null if resolution of
* package-relative label strings is required
* @throws ConversionException if there was a problem performing the type conversion
*/
public abstract T convert(Object x, String what, @Nullable Object context)
throws ConversionException;
// TODO(bazel-team): Check external calls (e.g. in PackageFactory), verify they always want
// this over selectableConvert.
/**
* Equivalent to {@link #convert(Object, String, Object)} where the label is {@code null}.
* Useful for converting values to types that do not involve the type {@code LABEL}
* and hence do not require the label of the current package.
*/
public final T convert(Object x, String what) throws ConversionException {
return convert(x, what, null);
}
/**
* Like {@link #convert(Object, String, Object)}, but converts skylark {@code None}
* to given {@code defaultValue}.
*/
@Nullable public final T convertOptional(Object x,
String what, @Nullable Object context, T defaultValue)
throws ConversionException {
if (EvalUtils.isNullOrNone(x)) {
return defaultValue;
}
return convert(x, what, context);
}
/**
* Like {@link #convert(Object, String, Object)}, but converts skylark {@code None}
* to java {@code null}.
*/
@Nullable public final T convertOptional(Object x, String what, @Nullable Object context)
throws ConversionException {
return convertOptional(x, what, context, null);
}
/**
* Like {@link #convert(Object, String)}, but converts skylark {@code NONE} to java {@code null}.
*/
@Nullable public final T convertOptional(Object x, String what) throws ConversionException {
return convertOptional(x, what, null);
}
public abstract T cast(Object value);
@Override
public abstract String toString();
/**
* Returns the default value for this type; may return null iff no default is defined for this
* type.
*/
public abstract T getDefaultValue();
/**
* Flatten the an instance of the type if the type is a composite one.
*
*
This is used to support reliable label visitation in
* {@link com.google.devtools.build.lib.packages.AbstractAttributeMapper#visitLabels}. To preserve
* that reliability, every type should faithfully define its own instance of this method. In other
* words, be careful about defining default instances in base types that get auto-inherited by
* their children. Keep all definitions as explicit as possible.
*/
public abstract Collection extends Object> flatten(Object value);
/**
* {@link #flatten} return value for types that don't contain labels.
*/
protected static final Collection