diff options
author | Lukacs Berki <lberki@google.com> | 2015-06-10 08:24:43 +0000 |
---|---|---|
committer | Philipp Wollermann <philwo@google.com> | 2015-06-10 16:03:01 +0000 |
commit | bcb81ab35c02124e72acd03fcf0638144a9eb242 (patch) | |
tree | efcff2eec8a31a1a482090d587ed9284eb67da1c /src/main/java | |
parent | de7cd0b3663a62da20607369a3cfad82cc7c627f (diff) |
Description redacted.
--
MOS_MIGRATED_REVID=95615442
Diffstat (limited to 'src/main/java')
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; |