Prevent aspects with the same attributes but different names from outputting duplicates of those attributes in query's proto output format.
@@ -57,6 +57,7 @@ import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.Type;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -64,6 +65,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
@@ -205,9 +207,10 @@ public class ProtoOutputFormatter extends AbstractUnorderedFormatter {
attributeValue,
rule.isAttributeValueExplicitlySpecified(attr),
/*encodeBooleanAndTriStateAsIntegerAndString=*/ true);
- rulePb.addAttribute(serializedAttribute);
serializedAttributes.put(attr, serializedAttribute);
}
+ rulePb.addAllAttribute(
+ serializedAttributes.values().stream().distinct().collect(Collectors.toList()));
postProcess(rule, rulePb, serializedAttributes);
@@ -225,6 +228,7 @@ public class ProtoOutputFormatter extends AbstractUnorderedFormatter {
ImmutableMultimap<Attribute, Label> aspectsDependencies =
aspectResolver.computeAspectDependencies(target, dependencyFilter);
// Add information about additional attributes from aspects.
+ List<Build.Attribute> attributes = new ArrayList<>(aspectsDependencies.asMap().size());
for (Entry<Attribute, Collection<Label>> entry : aspectsDependencies.asMap().entrySet()) {
Attribute attribute = entry.getKey();
Collection<Label> labels = entry.getValue();
@@ -238,25 +242,28 @@ public class ProtoOutputFormatter extends AbstractUnorderedFormatter {
attributeValue,
/*explicitlySpecified=*/ false,
/*encodeBooleanAndTriStateAsIntegerAndString=*/ true);
- rulePb.addAttribute(serializedAttribute);
+ attributes.add(serializedAttribute);
}
+ rulePb.addAllAttribute(attributes.stream().distinct().collect(Collectors.toList()));
if (includeRuleInputsAndOutputs()) {
// Add all deps from aspects as rule inputs of current target.
- for (Label label : aspectsDependencies.values()) {
- rulePb.addRuleInput(label.toString());
- }
-
+ aspectsDependencies
+ .values()
+ .stream()
+ .distinct()
+ .forEach(dep -> rulePb.addRuleInput(dep.toString()));
// Include explicit elements for all direct inputs and outputs of a rule;
// this goes beyond what is available from the attributes above, since it
// may also (depending on options) include implicit outputs,
// host-configuration outputs, and default values.
- for (Label label : rule.getLabels(dependencyFilter)) {
- rulePb.addRuleInput(label.toString());
- }
- for (OutputFile outputFile : rule.getOutputFiles()) {
- Label fileLabel = outputFile.getLabel();
- rulePb.addRuleOutput(fileLabel.toString());
- }
+ rule.getLabels(dependencyFilter)
+ .stream()
+ .distinct()
+ .forEach(input -> rulePb.addRuleInput(input.toString()));
+ rule.getOutputFiles()
+ .stream()
+ .distinct()
+ .forEach(output -> rulePb.addRuleOutput(output.getLabel().toString()));
}
for (String feature : rule.getFeatures()) {
rulePb.addDefaultSetting(feature);
