aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google
diff options
context:
space:
mode:
authorGravatar Miguel Alcon Pinto <malcon@google.com>2015-10-08 18:15:44 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2015-10-09 14:40:07 +0000
commitab0b0c50dca4f0251b4513159f14ff67ebc71f5d (patch)
tree3883a4c64371aa12c2f580ce802e734bf6992f5c /src/main/java/com/google
parent006c72520bf756d34016e44d593da4cffba2491e (diff)
Add the ability to filter out attributes when doing queries.
-- MOS_MIGRATED_REVID=104979750
Diffstat (limited to 'src/main/java/com/google')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java99
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/ProtoOutputFormatter.java14
2 files changed, 100 insertions, 13 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java b/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java
index 18da84aafd..6881c8712a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java
@@ -15,6 +15,8 @@ package com.google.devtools.build.lib.packages;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@@ -23,6 +25,9 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
@@ -55,6 +60,8 @@ import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.Nullable;
+
/**
* Functionality to deserialize loaded packages.
*/
@@ -72,8 +79,37 @@ public class PackageDeserializer {
/** Returns a {@link RuleClass} object for the serialized rule. */
RuleClass getRuleClass(Build.Rule rulePb, Location ruleLocation);
+
+ /** Description of what rule attributes of each rule should be deserialized. */
+ AttributesToDeserialize attributesToDeserialize();
+ }
+
+ /**
+ * A class that defines what attributes to keep after deserialization. Note that all attributes of
+ * type label are kept in order to navigate between dependencies.
+ *
+ * <p>If {@code addSyntheticAttributeHash} is {@code true}, a synthetic attribute is added to each
+ * Rule that contains a stable hash of the entire serialized rule for the sake of permitting
+ * equality comparisons that respect the attributes that were dropped according to {@code
+ * attributesToKeep}.
+ */
+ public static class AttributesToDeserialize {
+
+ private final boolean addSyntheticAttributeHash;
+ private final Predicate<String> shouldKeepAttributeWithName;
+
+ public AttributesToDeserialize(boolean addSyntheticAttributeHash,
+ Predicate<String> shouldKeepAttributeWithName) {
+ this.addSyntheticAttributeHash = addSyntheticAttributeHash;
+ this.shouldKeepAttributeWithName = shouldKeepAttributeWithName;
+ }
+
+ public boolean includeAttribute(String attr) { return shouldKeepAttributeWithName.apply(attr); }
}
+ public static final AttributesToDeserialize DESERIALIZE_ALL_ATTRS =
+ new AttributesToDeserialize(false, Predicates.<String>alwaysTrue());
+
// Workaround for Java serialization making it tough to pass in a deserialization environment
// manually.
// volatile is needed to ensure that the objects are published safely.
@@ -101,7 +137,7 @@ public class PackageDeserializer {
private static class DeserializationContext {
private final Package.Builder packageBuilder;
- public DeserializationContext(Package.Builder packageBuilder) {
+ private DeserializationContext(Package.Builder packageBuilder) {
this.packageBuilder = packageBuilder;
}
}
@@ -124,11 +160,12 @@ public class PackageDeserializer {
Type<?> expectedType, Build.Attribute attrPb) throws PackageDeserializationException {
Object value = deserializeAttributeValue(expectedType, attrPb);
return new ParsedAttributeValue(
- attrPb.hasExplicitlySpecified() && attrPb.getExplicitlySpecified(), value,
- EmptyLocation.INSTANCE);
+ attrPb.hasExplicitlySpecified() && attrPb.getExplicitlySpecified(), value
+ );
}
- private void deserializeInputFile(DeserializationContext context, Build.SourceFile sourceFile)
+ private static void deserializeInputFile(DeserializationContext context,
+ Build.SourceFile sourceFile)
throws PackageDeserializationException {
InputFile inputFile;
try {
@@ -145,7 +182,7 @@ public class PackageDeserializer {
}
}
- private void deserializePackageGroup(DeserializationContext context,
+ private static void deserializePackageGroup(DeserializationContext context,
Build.PackageGroup packageGroupPb) throws PackageDeserializationException {
List<String> specifications = new ArrayList<>();
for (String containedPackage : packageGroupPb.getContainedPackageList()) {
@@ -169,22 +206,45 @@ public class PackageDeserializer {
Location ruleLocation = EmptyLocation.INSTANCE;
RuleClass ruleClass = packageDeserializationEnvironment.getRuleClass(rulePb, ruleLocation);
Map<String, ParsedAttributeValue> attributeValues = new HashMap<>();
+ AttributesToDeserialize attrToDeserialize =
+ packageDeserializationEnvironment.attributesToDeserialize();
+
+ Hasher hasher = Hashing.md5().newHasher();
for (Build.Attribute attrPb : rulePb.getAttributeList()) {
Type<?> type = ruleClass.getAttributeByName(attrPb.getName()).getType();
attributeValues.put(attrPb.getName(), deserializeAttribute(type, attrPb));
+ if (attrToDeserialize.addSyntheticAttributeHash) {
+ // TODO(bazel-team): This might give false positives because of explicit vs implicit.
+ hasher.putBytes(attrPb.toByteArray());
+ }
}
+ AttributeContainerWithoutLocation attributeContainer =
+ new AttributeContainerWithoutLocation(ruleClass, hasher.hash());
Label ruleLabel = deserializeLabel(rulePb.getName());
try {
Rule rule = createRuleWithParsedAttributeValues(ruleClass,
ruleLabel, context.packageBuilder, ruleLocation, attributeValues,
- NullEventHandler.INSTANCE, new AttributeContainerWithoutLocation(ruleClass));
+ NullEventHandler.INSTANCE, attributeContainer);
context.packageBuilder.addRule(rule);
+ // Remove the attribute after it is added to package in order to pass the validations
+ // and be able to compute all the outputs.
+ if (attrToDeserialize != DESERIALIZE_ALL_ATTRS) {
+ for (String attrName : attributeValues.keySet()) {
+ Attribute attribute = ruleClass.getAttributeByName(attrName);
+ if (!(attrToDeserialize.shouldKeepAttributeWithName.apply(attrName)
+ || BuildType.isLabelType(attribute.getType()))) {
+ attributeContainer.clearIfNotLabel(attrName);
+ }
+ }
+ }
+
Preconditions.checkState(!rule.containsErrors());
} catch (NameConflictException | LabelSyntaxException e) {
throw new PackageDeserializationException(e);
}
+
}
/** "Empty" location implementation, all methods should return non-null, but empty, values. */
@@ -622,10 +682,19 @@ public class PackageDeserializer {
}
}
- private static class AttributeContainerWithoutLocation extends AttributeContainer {
+ /**
+ * An special {@code AttributeContainer} implementation that does not keep
+ * the location and can contain a hashcode of the target attributes.
+ */
+ public static class AttributeContainerWithoutLocation extends AttributeContainer {
- private AttributeContainerWithoutLocation(RuleClass ruleClass) {
+ @Nullable
+ private final HashCode syntheticAttrHash;
+
+ private AttributeContainerWithoutLocation(RuleClass ruleClass,
+ @Nullable HashCode syntheticAttrHash) {
super(ruleClass, null);
+ this.syntheticAttrHash = syntheticAttrHash;
}
@Override
@@ -642,6 +711,16 @@ public class PackageDeserializer {
void setAttributeLocation(Attribute attribute, Location location) {
throw new UnsupportedOperationException("Setting location not supported");
}
+
+
+ @Nullable
+ public HashCode getSyntheticAttrHash() {
+ return syntheticAttrHash;
+ }
+
+ private void clearIfNotLabel(String attr) {
+ setAttributeValueByName(attr, null);
+ }
}
/**
@@ -687,12 +766,10 @@ public class PackageDeserializer {
private static class ParsedAttributeValue {
private final boolean explicitlySpecified;
private final Object value;
- private final Location location;
- private ParsedAttributeValue(boolean explicitlySpecified, Object value, Location location) {
+ private ParsedAttributeValue(boolean explicitlySpecified, Object value) {
this.explicitlySpecified = explicitlySpecified;
this.value = value;
- this.location = location;
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/ProtoOutputFormatter.java b/src/main/java/com/google/devtools/build/lib/query2/output/ProtoOutputFormatter.java
index d290352496..66348b3be3 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/output/ProtoOutputFormatter.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/ProtoOutputFormatter.java
@@ -132,9 +132,9 @@ public class ProtoOutputFormatter extends OutputFormatter implements UnorderedFo
.setName(rule.getLabel().toString())
.setRuleClass(rule.getRuleClass())
.setLocation(location);
-
for (Attribute attr : rule.getAttributes()) {
- if (!includeDefaultValues && !rule.isAttributeValueExplicitlySpecified(attr)) {
+ if (!includeDefaultValues && !rule.isAttributeValueExplicitlySpecified(attr)
+ || !includeAttribute(attr)) {
continue;
}
rulePb.addAttribute(PackageSerializer.getAttributeProto(attr,
@@ -142,6 +142,8 @@ public class ProtoOutputFormatter extends OutputFormatter implements UnorderedFo
rule.isAttributeValueExplicitlySpecified(attr)));
}
+ postProcess(rule, rulePb);
+
Environment env = rule.getRuleClassObject().getRuleDefinitionEnvironment();
if (env != null) {
// The RuleDefinitionEnvironment is always defined for Skylark rules and
@@ -279,4 +281,12 @@ public class ProtoOutputFormatter extends OutputFormatter implements UnorderedFo
return targetPb.build();
}
+
+ /** Further customize the proto output */
+ protected void postProcess(Rule rule, Build.Rule.Builder rulePb) { }
+
+ /** Filter out some attributes */
+ protected boolean includeAttribute(Attribute attr) {
+ return true;
+ }
}