aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax/Type.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax/Type.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Type.java54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Type.java b/src/main/java/com/google/devtools/build/lib/syntax/Type.java
index dbbfc79c42..387794b40f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Type.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Type.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.syntax;
import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -139,6 +140,31 @@ public abstract class Type<T> {
*/
public abstract void visitLabels(LabelVisitor visitor, Object value) throws InterruptedException;
+ /** Classifications of labels by their usage. */
+ public enum LabelClass {
+ /** Used for types which are not labels. */
+ NONE,
+ /** Used for types which use labels to declare a dependency. */
+ DEPENDENCY,
+ /**
+ * Used for types which use labels to reference another target but do not declare a dependency,
+ * in cases where doing so would cause a dependency cycle.
+ */
+ NONDEP_REFERENCE,
+ /** Used for types which use labels to declare an output path. */
+ OUTPUT,
+ /**
+ * Used for types which contain Fileset entries, which contain labels but do not produce
+ * normal dependencies.
+ */
+ FILESET_ENTRY
+ }
+
+ /** Returns the class of labels contained by this type, if any. */
+ public LabelClass getLabelClass() {
+ return LabelClass.NONE;
+ }
+
/**
* Implementation of concatenation for this type (e.g. "val1 + val2"). Returns null to
* indicate concatenation isn't supported.
@@ -423,6 +449,8 @@ public abstract class Type<T> {
private final Map<KeyT, ValueT> empty = ImmutableMap.of();
+ private final LabelClass labelClass;
+
@Override
public void visitLabels(LabelVisitor visitor, Object value) throws InterruptedException {
for (Entry<KeyT, ValueT> entry : cast(value).entrySet()) {
@@ -433,12 +461,24 @@ public abstract class Type<T> {
public static <KEY, VALUE> DictType<KEY, VALUE> create(
Type<KEY> keyType, Type<VALUE> valueType) {
- return new DictType<>(keyType, valueType);
+ LabelClass keyLabelClass = keyType.getLabelClass();
+ LabelClass valueLabelClass = valueType.getLabelClass();
+ Preconditions.checkArgument(
+ keyLabelClass == LabelClass.NONE
+ || valueLabelClass == LabelClass.NONE
+ || keyLabelClass == valueLabelClass,
+ "A DictType's keys and values must be the same class of label if both contain labels, "
+ + "but the key type " + keyType + " contains " + keyLabelClass + " labels, while "
+ + "the value type " + valueType + " contains " + valueLabelClass + " labels.");
+ LabelClass labelClass = (keyLabelClass != LabelClass.NONE) ? keyLabelClass : valueLabelClass;
+
+ return new DictType<>(keyType, valueType, labelClass);
}
- private DictType(Type<KeyT> keyType, Type<ValueT> valueType) {
+ private DictType(Type<KeyT> keyType, Type<ValueT> valueType, LabelClass labelClass) {
this.keyType = keyType;
this.valueType = valueType;
+ this.labelClass = labelClass;
}
public Type<KeyT> getKeyType() {
@@ -449,6 +489,11 @@ public abstract class Type<T> {
return valueType;
}
+ @Override
+ public LabelClass getLabelClass() {
+ return labelClass;
+ }
+
@SuppressWarnings("unchecked")
@Override
public Map<KeyT, ValueT> cast(Object value) {
@@ -511,6 +556,11 @@ public abstract class Type<T> {
}
@Override
+ public LabelClass getLabelClass() {
+ return elemType.getLabelClass();
+ }
+
+ @Override
public List<ElemT> getDefaultValue() {
return empty;
}