aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Lukacs Berki <lberki@google.com>2015-06-10 08:24:43 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2015-06-10 16:03:01 +0000
commitbcb81ab35c02124e72acd03fcf0638144a9eb242 (patch)
treeefcff2eec8a31a1a482090d587ed9284eb67da1c /src/main
parentde7cd0b3663a62da20607369a3cfad82cc7c627f (diff)
Description redacted.
-- MOS_MIGRATED_REVID=95615442
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Rule.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/AspectResolver.java152
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/ConservativeAspectResolver.java62
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/NullAspectResolver.java42
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/PreciseAspectResolver.java129
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/ProtoOutputFormatter.java30
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/QueryOptions.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/query2/output/XmlOutputFormatter.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java7
11 files changed, 327 insertions, 164 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
index 0c2368b6ea..10ba3ffbff 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
@@ -109,11 +109,11 @@ public final class AspectDefinition {
*/
public static ImmutableMultimap<Attribute, Label> visitAspectsIfRequired(
Target from, Attribute attribute, Target to) {
- ImmutableMultimap.Builder<Attribute, Label> labelBuilder = ImmutableMultimap.builder();
// Aspect can be declared only for Rules.
if (!(from instanceof Rule) || !(to instanceof Rule)) {
- return labelBuilder.build();
+ return ImmutableMultimap.of();
}
+ LinkedHashMultimap<Attribute, Label> result = LinkedHashMultimap.create();
RuleClass ruleClass = ((Rule) to).getRuleClassObject();
for (Class<? extends AspectFactory<?, ?, ?>> candidateClass : attribute.getAspects()) {
AspectFactory<?, ?, ?> candidate = AspectFactory.Util.create(candidateClass);
@@ -123,16 +123,16 @@ public final class AspectDefinition {
candidate.getDefinition().getRequiredProviders())) {
continue;
}
- addAllAttributesOfAspect((Rule) from, labelBuilder, candidate.getDefinition(), Rule.ALL_DEPS);
+ addAllAttributesOfAspect((Rule) from, result, candidate.getDefinition(), Rule.ALL_DEPS);
}
- return labelBuilder.build();
+ return ImmutableMultimap.copyOf(result);
}
/**
* Collects all attribute labels from the specified aspectDefinition.
*/
public static void addAllAttributesOfAspect(Rule from,
- ImmutableMultimap.Builder<Attribute, Label> labelBuilder, AspectDefinition aspectDefinition,
+ Multimap<Attribute, Label> labelBuilder, AspectDefinition aspectDefinition,
BinaryPredicate<Rule, Attribute> predicate) {
ImmutableMap<String, Attribute> attributes = aspectDefinition.getAttributes();
for (Attribute aspectAttribute : attributes.values()) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
index 75101f25d4..76f6d47428 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java
@@ -20,9 +20,9 @@ import com.google.common.base.Predicates;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
@@ -704,14 +704,14 @@ public final class Rule implements Target {
*/
public Collection<? extends Label> getAspectLabelsSuperset(
BinaryPredicate<Rule, Attribute> predicate) {
- ImmutableMultimap.Builder<Attribute, Label> labelBuilder = ImmutableMultimap.builder();
+ LinkedHashMultimap<Attribute, Label> labels = LinkedHashMultimap.create();
for (Attribute attribute : this.getAttributes()) {
for (Class<? extends AspectFactory<?, ?, ?>> candidateClass : attribute.getAspects()) {
AspectFactory<?, ?, ?> candidate = AspectFactory.Util.create(candidateClass);
- AspectDefinition.addAllAttributesOfAspect(Rule.this, labelBuilder,
+ AspectDefinition.addAllAttributesOfAspect(Rule.this, labels,
candidate.getDefinition(), predicate);
}
}
- return labelBuilder.build().values();
+ return labels.values();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/AspectResolver.java b/src/main/java/com/google/devtools/build/lib/query2/output/AspectResolver.java
index 6acdc9ea8d..83af084408 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/output/AspectResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/AspectResolver.java
@@ -13,79 +13,51 @@
// limitations under the License.
package com.google.devtools.build.lib.query2.output;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
+import com.google.common.collect.ImmutableMultimap;
import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.packages.AspectDefinition;
-import com.google.devtools.build.lib.packages.AspectFactory;
import com.google.devtools.build.lib.packages.Attribute;
-import com.google.devtools.build.lib.packages.NoSuchPackageException;
-import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.Package;
-import com.google.devtools.build.lib.packages.PackageIdentifier;
-import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.PackageProvider;
import com.google.devtools.build.lib.syntax.Label;
-import com.google.devtools.build.lib.util.BinaryPredicate;
import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
-import javax.annotation.Nullable;
-
/** Utility class that determines additional dependencies of a target from its aspects. */
-public class AspectResolver {
- private final PackageProvider packageProvider;
- private final EventHandler eventHandler;
-
- public AspectResolver(PackageProvider packageProvider, EventHandler eventHandler) {
- this.packageProvider = packageProvider;
- this.eventHandler = eventHandler;
- }
+public interface AspectResolver {
/**
- * Compute additional dependencies of target from aspects. This method is going to load direct
- * deps of target to determine their types. Returns map of attributes and corresponding label
- * values.
+ * How to resolve aspect dependencies in 'blaze query'.
*/
- Map<Attribute, Collection<Label>> computeAspectDependenciesWithAttributes(Target target)
- throws InterruptedException {
- Map<Attribute, Collection<Label>> aspectDependencies = new LinkedHashMap<>();
- if (target instanceof Rule) {
- Multimap<Attribute, Label> transitions =
- ((Rule) target).getTransitions(Rule.NO_NODEP_ATTRIBUTES);
- for (Entry<Attribute, Label> entry : transitions.entries()) {
- Target toTarget;
- try {
- toTarget = packageProvider.getTarget(eventHandler, entry.getValue());
- Map<Attribute, Collection<Label>> deps = Multimaps.asMap(
- AspectDefinition.visitAspectsIfRequired(target, entry.getKey(), toTarget));
- aspectDependencies.putAll(deps);
- } catch (NoSuchThingException e) {
- // Do nothing. One of target direct deps has an error. The dependency on the BUILD file
- // (or one of the files included in it) will be reported in the query result of :BUILD.
- }
+ public enum Mode {
+ // Do not report aspect dependencies
+ OFF {
+ @Override
+ public AspectResolver createResolver(PackageProvider provider, EventHandler eventHandler) {
+ return new NullAspectResolver();
}
- }
- return aspectDependencies;
- }
+ },
- /**
- * Compute additional dependencies of target from aspects. This method is going to load direct
- * deps of target to determine their types. Returns set of labels.
- */
- Set<Label> computeAspectDependencies(Target target) throws InterruptedException {
- Set<Label> labels = new LinkedHashSet<Label>();
- for (Collection<Label> labelCollection :
- computeAspectDependenciesWithAttributes(target).values()) {
- labels.addAll(labelCollection);
- }
- return labels;
+ // Do not load dependent packages; report deps assuming all aspects defined on a rule are
+ // triggered
+ CONSERVATIVE {
+ @Override
+ public AspectResolver createResolver(PackageProvider provider, EventHandler eventHandler) {
+ return new ConservativeAspectResolver();
+ }
+ },
+
+ // Load direct dependencies and report aspects that can be triggered based on their types.
+ PRECISE {
+ @Override
+ public AspectResolver createResolver(PackageProvider provider, EventHandler eventHandler) {
+ return new PreciseAspectResolver(provider, eventHandler);
+ }
+ };
+
+ public abstract AspectResolver createResolver(
+ PackageProvider provider, EventHandler eventHandler);
}
/** The way aspect dependencies for a BUILD file are calculated. */
@@ -108,59 +80,19 @@ public class AspectResolver {
};
protected abstract Collection<Label> getDependencies(Package pkg);
- };
-
- Set<Label> computeBuildFileDependencies(Package pkg, BuildFileDependencyMode mode)
- throws InterruptedException {
- Set<Label> result = new LinkedHashSet<>();
- result.addAll(mode.getDependencies(pkg));
-
- Set<PackageIdentifier> dependentPackages = new LinkedHashSet<>();
- // First compute with packages can possibly affect the aspect attributes of this package:
- // Iterate over all rules...
- for (Target target : pkg.getTargets()) {
-
- if (!(target instanceof Rule)) {
- continue;
- }
-
- // ...figure out which direct dependencies can possibly have aspects attached to them...
- Multimap<Attribute, Label> depsWithPossibleAspects = ((Rule) target).getTransitions(
- new BinaryPredicate<Rule, Attribute>() {
- @Override
- public boolean apply(@Nullable Rule rule, @Nullable Attribute attribute) {
- for (Class<? extends AspectFactory<?, ?, ?>> aspectFactory : attribute.getAspects()) {
- if (!AspectFactory.Util.create(aspectFactory).getDefinition()
- .getAttributes().isEmpty()) {
- return true;
- }
- }
-
- return false;
- }
- });
-
- // ...and add the package of the aspect.
- for (Label depLabel : depsWithPossibleAspects.values()) {
- dependentPackages.add(depLabel.getPackageIdentifier());
- }
- }
+ }
- // Then add all the subinclude labels of the packages thus found to the result.
- for (PackageIdentifier packageIdentifier : dependentPackages) {
- try {
- result.add(Label.create(packageIdentifier, "BUILD"));
- Package dependentPackage = packageProvider.getPackage(eventHandler, packageIdentifier);
- result.addAll(mode.getDependencies(dependentPackage));
- } catch (NoSuchPackageException e) {
- // If the package is not found, just add its BUILD file, which is already done above.
- // Hopefully this error is not raised when there is a syntax error in a subincluded file
- // or something.
- } catch (Label.SyntaxException e) {
- throw new IllegalStateException(e);
- }
- }
+ /**
+ * Compute additional dependencies of target from aspects. This method may load the direct deps
+ * of target to determine their types. Returns map of attributes and corresponding label values.
+ */
+ ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target)
+ throws InterruptedException;
- return result;
- }
+ /**
+ * Compute the labels of the BUILD and subinclude and Skylark files on which the results of the
+ * other two methods depend for a target in the given package.
+ */
+ Set<Label> computeBuildFileDependencies(Package pkg, BuildFileDependencyMode mode)
+ throws InterruptedException;
}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/ConservativeAspectResolver.java b/src/main/java/com/google/devtools/build/lib/query2/output/ConservativeAspectResolver.java
new file mode 100644
index 0000000000..0bdba9a4de
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/ConservativeAspectResolver.java
@@ -0,0 +1,62 @@
+// Copyright 2015 Google Inc. 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.query2.output;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.syntax.Label;
+
+import java.util.Set;
+
+/**
+ * An aspect resolver that overestimates the required aspect dependencies.
+ *
+ * <p>Does not need to load any packages other than the one containing the target being processed.
+ */
+public class ConservativeAspectResolver implements AspectResolver {
+ @Override
+ public ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target)
+ throws InterruptedException {
+ if (!(target instanceof Rule)) {
+ return ImmutableMultimap.of();
+ }
+
+ Multimap<Attribute, Label> result = LinkedHashMultimap.create();
+ for (Attribute attribute : ((Rule) target).getAttributes()) {
+ for (Class<? extends AspectFactory<?, ?, ?>> aspectFactory : attribute.getAspects()) {
+ AspectDefinition.addAllAttributesOfAspect(
+ (Rule) target,
+ result,
+ AspectFactory.Util.create(aspectFactory).getDefinition(),
+ Rule.ALL_DEPS);
+ }
+ }
+
+ return ImmutableMultimap.copyOf(result);
+ }
+
+ @Override
+ public Set<Label> computeBuildFileDependencies(com.google.devtools.build.lib.packages.Package pkg,
+ BuildFileDependencyMode mode) throws InterruptedException {
+ // We do a conservative estimate precisely so that we don't depend on any other BUILD files.
+ return ImmutableSet.copyOf(mode.getDependencies(pkg));
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/NullAspectResolver.java b/src/main/java/com/google/devtools/build/lib/query2/output/NullAspectResolver.java
new file mode 100644
index 0000000000..95ed28e967
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/NullAspectResolver.java
@@ -0,0 +1,42 @@
+// Copyright 2015 Google Inc. 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.query2.output;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.syntax.Label;
+
+import java.util.Set;
+
+/**
+ * An aspect resolver that does not return any aspect dependencies.
+ *
+ * <p>Simple, fast, wrong.
+ */
+public class NullAspectResolver implements AspectResolver {
+ @Override
+ public ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target)
+ throws InterruptedException {
+ return ImmutableMultimap.of();
+ }
+
+ @Override
+ public Set<Label> computeBuildFileDependencies(
+ Package pkg, BuildFileDependencyMode mode) throws InterruptedException {
+ return ImmutableSet.copyOf(mode.getDependencies(pkg));
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/PreciseAspectResolver.java b/src/main/java/com/google/devtools/build/lib/query2/output/PreciseAspectResolver.java
new file mode 100644
index 0000000000..3074323b64
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/PreciseAspectResolver.java
@@ -0,0 +1,129 @@
+// Copyright 2015 Google Inc. 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.query2.output;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Multimap;
+import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.NoSuchThingException;
+import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.lib.packages.PackageIdentifier;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.pkgcache.PackageProvider;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.util.BinaryPredicate;
+
+import java.util.LinkedHashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/**
+ * An aspect resolver that returns only those aspects that are possibly active given the rule
+ * classes of direct dependencies.
+ *
+ * <p>Needs to load the packages that contain dependencies through attributes with aspects.
+ */
+public class PreciseAspectResolver implements AspectResolver {
+ private final PackageProvider packageProvider;
+ private final EventHandler eventHandler;
+
+ public PreciseAspectResolver(PackageProvider packageProvider, EventHandler eventHandler) {
+ this.packageProvider = packageProvider;
+ this.eventHandler = eventHandler;
+ }
+
+ @Override
+ public ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target)
+ throws InterruptedException {
+ Multimap<Attribute, Label> result = LinkedListMultimap.create();
+ if (target instanceof Rule) {
+ Multimap<Attribute, Label> transitions =
+ ((Rule) target).getTransitions(Rule.NO_NODEP_ATTRIBUTES);
+ for (Entry<Attribute, Label> entry : transitions.entries()) {
+ Target toTarget;
+ try {
+ toTarget = packageProvider.getTarget(eventHandler, entry.getValue());
+ result.putAll(AspectDefinition.visitAspectsIfRequired(target, entry.getKey(), toTarget));
+ } catch (NoSuchThingException e) {
+ // Do nothing. One of target direct deps has an error. The dependency on the BUILD file
+ // (or one of the files included in it) will be reported in the query result of :BUILD.
+ }
+ }
+ }
+ return ImmutableMultimap.copyOf(result);
+ }
+
+ @Override
+ public Set<Label> computeBuildFileDependencies(Package pkg, BuildFileDependencyMode mode)
+ throws InterruptedException {
+ Set<Label> result = new LinkedHashSet<>();
+ result.addAll(mode.getDependencies(pkg));
+
+ Set<PackageIdentifier> dependentPackages = new LinkedHashSet<>();
+ // First compute with packages can possibly affect the aspect attributes of this package:
+ // Iterate over all rules...
+ for (Target target : pkg.getTargets()) {
+
+ if (!(target instanceof Rule)) {
+ continue;
+ }
+
+ // ...figure out which direct dependencies can possibly have aspects attached to them...
+ Multimap<Attribute, Label> depsWithPossibleAspects = ((Rule) target).getTransitions(
+ new BinaryPredicate<Rule, Attribute>() {
+ @Override
+ public boolean apply(@Nullable Rule rule, @Nullable Attribute attribute) {
+ for (Class<? extends AspectFactory<?, ?, ?>> aspectFactory : attribute.getAspects()) {
+ if (!AspectFactory.Util.create(aspectFactory).getDefinition()
+ .getAttributes().isEmpty()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ });
+
+ // ...and add the package of the aspect.
+ for (Label depLabel : depsWithPossibleAspects.values()) {
+ dependentPackages.add(depLabel.getPackageIdentifier());
+ }
+ }
+
+ // Then add all the subinclude labels of the packages thus found to the result.
+ for (PackageIdentifier packageIdentifier : dependentPackages) {
+ try {
+ result.add(Label.create(packageIdentifier, "BUILD"));
+ Package dependentPackage = packageProvider.getPackage(eventHandler, packageIdentifier);
+ result.addAll(mode.getDependencies(dependentPackage));
+ } catch (NoSuchPackageException e) {
+ // If the package is not found, just add its BUILD file, which is already done above.
+ // Hopefully this error is not raised when there is a syntax error in a subincluded file
+ // or something.
+ } catch (Label.SyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ return result;
+ }
+}
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 77761efbea..1143b6a235 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
@@ -19,6 +19,7 @@ import static com.google.devtools.build.lib.query2.proto.proto2api.Build.Target.
import static com.google.devtools.build.lib.query2.proto.proto2api.Build.Target.Discriminator.RULE;
import static com.google.devtools.build.lib.query2.proto.proto2api.Build.Target.Discriminator.SOURCE_FILE;
+import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.graph.Digraph;
import com.google.devtools.build.lib.packages.Attribute;
@@ -42,12 +43,9 @@ import java.io.IOException;
import java.io.PrintStream;
import java.util.Collection;
import java.util.LinkedHashSet;
-import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import javax.annotation.Nullable;
-
/**
* An output formatter that outputs a protocol buffer representation
* of a query result and outputs the proto bytes to the output print stream.
@@ -63,7 +61,7 @@ public class ProtoOutputFormatter extends OutputFormatter implements UnorderedFo
private BinaryPredicate<Rule, Attribute> dependencyFilter;
private boolean relativeLocations = false;
- @Nullable protected AspectResolver aspectResolver = null; // null if aspect deps are not required
+ protected AspectResolver aspectResolver;
protected void setDependencyFilter(QueryOptions options) {
this.dependencyFilter = OutputFormatter.getDependencyFilter(options);
@@ -139,20 +137,16 @@ public class ProtoOutputFormatter extends OutputFormatter implements UnorderedFo
.setStringValue(env.getTransitiveFileContentHashCode()));
}
- if (aspectResolver != null) {
- Map<Attribute, Collection<Label>> aspectsDependencies =
- aspectResolver.computeAspectDependenciesWithAttributes(target);
- // Add information about additional attributes from aspects.
- for (Entry<Attribute, Collection<Label>> entry : aspectsDependencies.entrySet()) {
- PackageSerializer.addAttributeToProto(rulePb, entry.getKey(),
- Lists.<Object>newArrayList(entry.getValue()), null, false, false);
- }
- // Add all deps from aspects as rule inputs of current target.
- for (Collection<Label> labelCollection : aspectsDependencies.values()) {
- for (Label label : labelCollection) {
- rulePb.addRuleInput(label.toString());
- }
- }
+ ImmutableMultimap<Attribute, Label> aspectsDependencies =
+ aspectResolver.computeAspectDependencies(target);
+ // Add information about additional attributes from aspects.
+ for (Entry<Attribute, Collection<Label>> entry : aspectsDependencies.asMap().entrySet()) {
+ PackageSerializer.addAttributeToProto(rulePb, entry.getKey(),
+ Lists.<Object>newArrayList(entry.getValue()), null, false, false);
+ }
+ // Add all deps from aspects as rule inputs of current target.
+ for (Label label : aspectsDependencies.values()) {
+ rulePb.addRuleInput(label.toString());
}
// Include explicit elements for all direct inputs and outputs of a rule;
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/QueryOptions.java b/src/main/java/com/google/devtools/build/lib/query2/output/QueryOptions.java
index 417981ec2e..b653220d2b 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/output/QueryOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/QueryOptions.java
@@ -15,6 +15,7 @@ package com.google.devtools.build.lib.query2.output;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.common.options.Converters;
+import com.google.devtools.common.options.EnumConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;
@@ -26,6 +27,12 @@ import java.util.Set;
* Command-line options for the Blaze query language, revision 2.
*/
public class QueryOptions extends OptionsBase {
+ /** An enum converter for {@code AspectResolver.Mode} . Should be used internally only. */
+ public static class AspectResolutionModeConverter extends EnumConverter<AspectResolver.Mode> {
+ public AspectResolutionModeConverter() {
+ super(AspectResolver.Mode.class, "Aspect resolution mode");
+ }
+ }
@Option(name = "output",
defaultValue = "label",
@@ -138,11 +145,19 @@ public class QueryOptions extends OptionsBase {
public boolean relativeLocations;
@Option(name = "aspect_deps",
- defaultValue = "false",
+ converter = AspectResolutionModeConverter.class,
+ defaultValue = "off",
category = "query",
- help = "If true, the dependencies from aspects should be added to targets. By default, this "
- + "information about aspects is missing when --output is set to xml, proto or record.")
- public boolean withAspectDeps;
+ help = "How to resolve aspect dependencies when the output format is one of "
+ + "{xml,proto,record}. 'off' (the default) means no aspect dependencies are resolved, "
+ + "'conservative' means all possible aspect dependencies are added regardless of whether "
+ + "they are possible given the rule class of direct dependencies, 'precise' means that "
+ + "only those aspects are added that are possibly active given the rule class of the "
+ + "direct dependencies. Note that precise mode requires loading other packages to "
+ + "evaluate a single target thus making it slower than the other modes. Also note that "
+ + "even precise mode is not completely precise: the decision whether to compute an "
+ + "aspect is decided in the analysis phase, which is not run during 'blaze query'.")
+ public AspectResolver.Mode aspectDeps;
/**
* Return the current options as a set of QueryEnvironment settings.
diff --git a/src/main/java/com/google/devtools/build/lib/query2/output/XmlOutputFormatter.java b/src/main/java/com/google/devtools/build/lib/query2/output/XmlOutputFormatter.java
index 4d3dca8c8a..b24b26761e 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/output/XmlOutputFormatter.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/output/XmlOutputFormatter.java
@@ -41,7 +41,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import javax.annotation.Nullable;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
@@ -60,7 +59,7 @@ class XmlOutputFormatter extends OutputFormatter implements OutputFormatter.Unor
private boolean xmlLineNumbers;
private boolean showDefaultValues;
private boolean relativeLocations;
- @Nullable private AspectResolver aspectResolver; // Null if aspect dependencies are not needed
+ private AspectResolver aspectResolver;
private BinaryPredicate<Rule, Attribute> dependencyFilter;
@Override
@@ -146,12 +145,10 @@ class XmlOutputFormatter extends OutputFormatter implements OutputFormatter.Unor
inputElem.setAttribute("name", label.toString());
elem.appendChild(inputElem);
}
- if (aspectResolver != null) {
- for (Label label : aspectResolver.computeAspectDependencies(target)) {
- Element inputElem = doc.createElement("rule-input");
- inputElem.setAttribute("name", label.toString());
- elem.appendChild(inputElem);
- }
+ for (Label label : aspectResolver.computeAspectDependencies(target).values()) {
+ Element inputElem = doc.createElement("rule-input");
+ inputElem.setAttribute("name", label.toString());
+ elem.appendChild(inputElem);
}
for (OutputFile outputFile: rule.getOutputFiles()) {
Element outputElem = doc.createElement("rule-output");
@@ -249,9 +246,7 @@ class XmlOutputFormatter extends OutputFormatter implements OutputFormatter.Unor
private void addSubincludedFilesToElement(Document doc, Element parent, InputFile inputFile)
throws InterruptedException {
- Iterable<Label> dependencies = aspectResolver == null
- ? inputFile.getPackage().getSubincludeLabels()
- : aspectResolver.computeBuildFileDependencies(
+ Iterable<Label> dependencies = aspectResolver.computeBuildFileDependencies(
inputFile.getPackage(), BuildFileDependencyMode.SUBINCLUDE);
for (Label subinclude : dependencies) {
@@ -263,10 +258,8 @@ class XmlOutputFormatter extends OutputFormatter implements OutputFormatter.Unor
private void addSkylarkFilesToElement(Document doc, Element parent, InputFile inputFile)
throws InterruptedException {
- Iterable<Label> dependencies = aspectResolver == null
- ? inputFile.getPackage().getSkylarkFileDependencies()
- : aspectResolver.computeBuildFileDependencies(
- inputFile.getPackage(), BuildFileDependencyMode.SKYLARK);
+ Iterable<Label> dependencies = aspectResolver.computeBuildFileDependencies(
+ inputFile.getPackage(), BuildFileDependencyMode.SKYLARK);
for (Label skylarkFileDep : dependencies) {
Element elem = doc.createElement("load");
diff --git a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
index ba13325123..2aae12f91a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/genquery/GenQuery.java
@@ -53,7 +53,6 @@ import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunctio
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.SkyframeRestartQueryException;
-import com.google.devtools.build.lib.query2.output.AspectResolver;
import com.google.devtools.build.lib.query2.output.OutputFormatter;
import com.google.devtools.build.lib.query2.output.QueryOptions;
import com.google.devtools.build.lib.query2.output.QueryOutputUtils;
@@ -283,9 +282,7 @@ public class GenQuery implements RuleConfiguredTargetFactory {
try {
QueryOutputUtils.output(queryOptions, queryResult, formatter, printStream,
- queryOptions.withAspectDeps
- ? new AspectResolver(packageProvider, getEventHandler(ruleContext))
- : null);
+ queryOptions.aspectDeps.createResolver(packageProvider, getEventHandler(ruleContext)));
} catch (ClosedByInterruptException e) {
throw new InterruptedException(e.getMessage());
} catch (IOException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java
index 5b655feb83..72ec9ad8f7 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/QueryCommand.java
@@ -26,7 +26,6 @@ import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
-import com.google.devtools.build.lib.query2.output.AspectResolver;
import com.google.devtools.build.lib.query2.output.OutputFormatter;
import com.google.devtools.build.lib.query2.output.QueryOptions;
import com.google.devtools.build.lib.query2.output.QueryOutputUtils;
@@ -136,9 +135,9 @@ public final class QueryCommand implements BlazeCommand {
// 3. Output results:
PrintStream output = new PrintStream(runtime.getReporter().getOutErr().getOutputStream());
try {
- QueryOutputUtils.output(queryOptions, result, formatter, output, queryOptions.withAspectDeps
- ? new AspectResolver(runtime.getPackageManager(), runtime.getReporter())
- : null);
+ QueryOutputUtils.output(queryOptions, result, formatter, output,
+ queryOptions.aspectDeps.createResolver(
+ runtime.getPackageManager(), runtime.getReporter()));
} catch (ClosedByInterruptException | InterruptedException e) {
runtime.getReporter().handle(Event.error("query interrupted"));
return ExitCode.INTERRUPTED;