blob: e9a9dca254e5803dd078e1dc4e3a02dfe250f5bd [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.query2;
15
Janak Ramakrishnancbe26342015-08-17 18:57:57 +000016import com.google.common.base.Function;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010017import com.google.common.base.Predicate;
Ulf Adams43765af2017-02-07 16:06:39 +000018import com.google.common.collect.Collections2;
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +000019import com.google.common.collect.ImmutableSet;
Janak Ramakrishnancbe26342015-08-17 18:57:57 +000020import com.google.common.collect.Maps;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000021import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berkia6434362015-09-15 13:56:14 +000022import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000023import com.google.devtools.build.lib.cmdline.ResolvedTargets;
24import com.google.devtools.build.lib.cmdline.TargetParsingException;
Klaus Aehlig777b30d2017-02-24 16:30:15 +000025import com.google.devtools.build.lib.events.ExtendedEventHandler;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.devtools.build.lib.graph.Digraph;
27import com.google.devtools.build.lib.graph.Node;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010028import com.google.devtools.build.lib.packages.Attribute;
29import com.google.devtools.build.lib.packages.NoSuchThingException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.devtools.build.lib.packages.OutputFile;
31import com.google.devtools.build.lib.packages.Package;
32import com.google.devtools.build.lib.packages.Rule;
33import com.google.devtools.build.lib.packages.Target;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import com.google.devtools.build.lib.pkgcache.TargetEdgeObserver;
35import com.google.devtools.build.lib.pkgcache.TargetPatternEvaluator;
36import com.google.devtools.build.lib.pkgcache.TargetProvider;
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +000037import com.google.devtools.build.lib.pkgcache.TransitivePackageLoader;
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +000038import com.google.devtools.build.lib.query2.engine.Callback;
Miguel Alcon Pintob6510262015-12-10 17:50:15 +000039import com.google.devtools.build.lib.query2.engine.DigraphQueryEvalResult;
Nathan Harmatae9826b42017-03-07 18:05:21 +000040import com.google.devtools.build.lib.query2.engine.MinDepthUniquifier;
Nathan Harmatab869e582017-03-01 02:55:48 +000041import com.google.devtools.build.lib.query2.engine.OutputFormatterCallback;
Janak Ramakrishnana46125c2015-02-11 16:51:37 +000042import com.google.devtools.build.lib.query2.engine.QueryEvalResult;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043import com.google.devtools.build.lib.query2.engine.QueryException;
44import com.google.devtools.build.lib.query2.engine.QueryExpression;
Nathan Harmatab869e582017-03-01 02:55:48 +000045import com.google.devtools.build.lib.query2.engine.QueryExpressionEvalListener;
46import com.google.devtools.build.lib.query2.engine.QueryUtil;
Nathan Harmatab869e582017-03-01 02:55:48 +000047import com.google.devtools.build.lib.query2.engine.QueryUtil.AggregateAllCallback;
Nathan Harmatae9826b42017-03-07 18:05:21 +000048import com.google.devtools.build.lib.query2.engine.QueryUtil.ThreadSafeMinDepthUniquifierImpl;
49import com.google.devtools.build.lib.query2.engine.QueryUtil.UniquifierImpl;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050import com.google.devtools.build.lib.query2.engine.SkyframeRestartQueryException;
Nathan Harmatab869e582017-03-01 02:55:48 +000051import com.google.devtools.build.lib.query2.engine.ThreadSafeCallback;
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +000052import com.google.devtools.build.lib.query2.engine.Uniquifier;
Nathan Harmatab869e582017-03-01 02:55:48 +000053import com.google.devtools.build.lib.query2.engine.VariableContext;
Mark Schaller6df81792015-12-10 18:47:47 +000054import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010055import com.google.devtools.build.lib.vfs.PathFragment;
Nathan Harmata5bb9cc92016-09-30 21:28:30 +000056import java.io.IOException;
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +000057import java.util.ArrayList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010058import java.util.Collection;
Janak Ramakrishnanee6208b2016-01-07 20:17:41 +000059import java.util.HashMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060import java.util.HashSet;
61import java.util.Iterator;
62import java.util.LinkedHashSet;
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +000063import java.util.List;
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000064import java.util.Map;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065import java.util.Set;
Nathan Harmatab869e582017-03-01 02:55:48 +000066import java.util.concurrent.ForkJoinPool;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067
68/**
69 * The environment of a Blaze query. Not thread-safe.
70 */
Janak Ramakrishnana46125c2015-02-11 16:51:37 +000071public class BlazeQueryEnvironment extends AbstractBlazeQueryEnvironment<Target> {
Ulf Adams43765af2017-02-07 16:06:39 +000072 private static final Function<Target, Label> TO_LABEL = new Function<Target, Label>() {
73 @Override
74 public Label apply(Target input) {
75 return input.getLabel();
76 }
77 };
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +000078
79 private static final int MAX_DEPTH_FULL_SCAN_LIMIT = 20;
Janak Ramakrishnanee6208b2016-01-07 20:17:41 +000080 private final Map<String, Set<Target>> resolvedTargetPatterns = new HashMap<>();
Janak Ramakrishnane72d5222015-02-26 17:09:18 +000081 private final TargetPatternEvaluator targetPatternEvaluator;
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +000082 private final TransitivePackageLoader transitivePackageLoader;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010083 private final TargetProvider targetProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010084 private final Digraph<Target> graph = new Digraph<>();
85 private final ErrorPrintingTargetEdgeErrorObserver errorObserver;
86 private final LabelVisitor labelVisitor;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010087 protected final int loadingPhaseThreads;
88
Janak Ramakrishnana46125c2015-02-11 16:51:37 +000089 private final BlazeTargetAccessor accessor = new BlazeTargetAccessor(this);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090
91 /**
92 * Note that the correct operation of this class critically depends on the Reporter being a
93 * singleton object, shared by all cooperating classes contributing to Query.
Klaus Aehlig777b30d2017-02-24 16:30:15 +000094 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095 * @param strictScope if true, fail the whole query if a label goes out of scope.
Klaus Aehlig777b30d2017-02-24 16:30:15 +000096 * @param loadingPhaseThreads the number of threads to use during loading the packages for the
97 * query.
98 * @param labelFilter a predicate that determines if a specific label is allowed to be visited
99 * during query execution. If it returns false, the query execution is stopped with an error
100 * message.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101 * @param settings a set of enabled settings
102 */
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000103 BlazeQueryEnvironment(
104 TransitivePackageLoader transitivePackageLoader,
Ulf Adams1509cc82017-02-09 13:25:38 +0000105 TargetProvider targetProvider,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100106 TargetPatternEvaluator targetPatternEvaluator,
107 boolean keepGoing,
108 boolean strictScope,
109 int loadingPhaseThreads,
110 Predicate<Label> labelFilter,
Klaus Aehlig777b30d2017-02-24 16:30:15 +0000111 ExtendedEventHandler eventHandler,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100112 Set<Setting> settings,
Nathan Harmatab869e582017-03-01 02:55:48 +0000113 Iterable<QueryFunction> extraFunctions,
114 QueryExpressionEvalListener<Target> evalListener) {
115 super(
116 keepGoing, strictScope, labelFilter, eventHandler, settings, extraFunctions, evalListener);
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000117 this.targetPatternEvaluator = targetPatternEvaluator;
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +0000118 this.transitivePackageLoader = transitivePackageLoader;
Ulf Adams1509cc82017-02-09 13:25:38 +0000119 this.targetProvider = targetProvider;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100120 this.errorObserver = new ErrorPrintingTargetEdgeErrorObserver(this.eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100121 this.loadingPhaseThreads = loadingPhaseThreads;
Ulf Adams1509cc82017-02-09 13:25:38 +0000122 this.labelVisitor = new LabelVisitor(targetProvider, dependencyFilter);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100123 }
124
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100125 @Override
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000126 public DigraphQueryEvalResult<Target> evaluateQuery(
127 QueryExpression expr,
Nathan Harmatab869e582017-03-01 02:55:48 +0000128 final OutputFormatterCallback<Target> callback)
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000129 throws QueryException, InterruptedException, IOException {
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000130 eventHandler.resetErrors();
Janak Ramakrishnanee6208b2016-01-07 20:17:41 +0000131 resolvedTargetPatterns.clear();
Nathan Harmata5bb9cc92016-09-30 21:28:30 +0000132 QueryEvalResult queryEvalResult = super.evaluateQuery(expr, callback);
133 return new DigraphQueryEvalResult<>(
134 queryEvalResult.getSuccess(), queryEvalResult.isEmpty(), graph);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100135 }
136
137 @Override
Nathan Harmatab869e582017-03-01 02:55:48 +0000138 public void getTargetsMatchingPattern(
139 QueryExpression caller, String pattern, Callback<Target> callback)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +0000140 throws QueryException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100141 // We can safely ignore the boolean error flag. The evaluateQuery() method above wraps the
142 // entire query computation in an error sensor.
143
Janak Ramakrishnancbe26342015-08-17 18:57:57 +0000144 Set<Target> targets = new LinkedHashSet<>(resolvedTargetPatterns.get(pattern));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100145
146 // Sets.filter would be more convenient here, but can't deal with exceptions.
147 Iterator<Target> targetIterator = targets.iterator();
148 while (targetIterator.hasNext()) {
149 Target target = targetIterator.next();
150 if (!validateScope(target.getLabel(), strictScope)) {
151 targetIterator.remove();
152 }
153 }
154
155 Set<PathFragment> packages = new HashSet<>();
156 for (Target target : targets) {
157 packages.add(target.getLabel().getPackageFragment());
158 }
159
160 Set<Target> result = new LinkedHashSet<>();
161 for (Target target : targets) {
162 result.add(getOrCreate(target));
163
164 // Preservation of graph order: it is important that targets obtained via
165 // a wildcard such as p:* are correctly ordered w.r.t. each other, so to
166 // ensure this, we add edges between any pair of directly connected
167 // targets in this set.
168 if (target instanceof OutputFile) {
169 OutputFile outputFile = (OutputFile) target;
170 if (targets.contains(outputFile.getGeneratingRule())) {
171 makeEdge(outputFile, outputFile.getGeneratingRule());
172 }
173 } else if (target instanceof Rule) {
174 Rule rule = (Rule) target;
175 for (Label label : rule.getLabels(dependencyFilter)) {
176 if (!packages.contains(label.getPackageFragment())) {
177 continue; // don't cause additional package loading
178 }
179 try {
180 if (!validateScope(label, strictScope)) {
181 continue; // Don't create edges to targets which are out of scope.
182 }
183 Target to = getTargetOrThrow(label);
184 if (targets.contains(to)) {
185 makeEdge(rule, to);
186 }
187 } catch (NoSuchThingException e) {
188 /* ignore */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100189 }
190 }
191 }
192 }
Janak Ramakrishnan71cdea42016-08-16 15:14:41 +0000193 callback.process(result);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100194 }
195
Ulf Adams3ab82f72015-09-04 12:10:53 +0000196 @Override
Nathan Harmatab869e582017-03-01 02:55:48 +0000197 public void getTargetsMatchingPatternPar(
198 QueryExpression caller,
199 String pattern,
200 ThreadSafeCallback<Target> callback,
201 ForkJoinPool forkJoinPool) throws QueryException, InterruptedException {
202 getTargetsMatchingPattern(caller, pattern, callback);
203 }
204
205 @Override
Janak Ramakrishnan71cdea42016-08-16 15:14:41 +0000206 public Target getTarget(Label label)
207 throws TargetNotFoundException, QueryException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100208 // Can't use strictScope here because we are expecting a target back.
209 validateScope(label, true);
210 try {
Janak Ramakrishnana41a5032015-02-06 21:27:27 +0000211 return getNode(getTargetOrThrow(label)).getLabel();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100212 } catch (NoSuchThingException e) {
213 throw new TargetNotFoundException(e);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100214 }
215 }
216
217 private Node<Target> getNode(Target target) {
218 return graph.createNode(target);
219 }
220
221 private Collection<Node<Target>> getNodes(Iterable<Target> target) {
222 Set<Node<Target>> result = new LinkedHashSet<>();
223 for (Target t : target) {
224 result.add(getNode(t));
225 }
226 return result;
227 }
228
229 @Override
230 public Target getOrCreate(Target target) {
231 return getNode(target).getLabel();
232 }
233
234 @Override
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000235 public Collection<Target> getFwdDeps(Iterable<Target> targets) {
236 Set<Target> result = new HashSet<>();
237 for (Target target : targets) {
Janak Ramakrishnancda5b662015-06-18 23:46:36 +0000238 result.addAll(getTargetsFromNodes(getNode(target).getSuccessors()));
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000239 }
240 return result;
241 }
242
243 @Override
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000244 public Collection<Target> getReverseDeps(Iterable<Target> targets) {
245 Set<Target> result = new HashSet<>();
246 for (Target target : targets) {
Janak Ramakrishnancda5b662015-06-18 23:46:36 +0000247 result.addAll(getTargetsFromNodes(getNode(target).getPredecessors()));
Janak Ramakrishnan73dd2302015-06-16 17:04:25 +0000248 }
249 return result;
250 }
251
252 @Override
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100253 public Set<Target> getTransitiveClosure(Set<Target> targetNodes) {
254 for (Target node : targetNodes) {
255 checkBuilt(node);
256 }
257 return getTargetsFromNodes(graph.getFwdReachable(getNodes(targetNodes)));
258 }
259
260 /**
261 * Checks that the graph rooted at 'targetNode' has been completely built;
262 * fails if not. Callers of {@link #getTransitiveClosure} must ensure that
263 * {@link #buildTransitiveClosure} has been called before.
264 *
265 * <p>It would be inefficient and failure-prone to make getTransitiveClosure
266 * call buildTransitiveClosure directly. Also, it would cause
267 * nondeterministic behavior of the operators, since the set of packages
268 * loaded (and hence errors reported) would depend on the ordering details of
269 * the query operators' implementations.
270 */
271 private void checkBuilt(Target targetNode) {
272 Preconditions.checkState(
273 labelVisitor.hasVisited(targetNode.getLabel()),
274 "getTransitiveClosure(%s) called without prior call to buildTransitiveClosure()",
275 targetNode);
276 }
277
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100278 @Override
279 public void buildTransitiveClosure(QueryExpression caller,
280 Set<Target> targetNodes,
Janak Ramakrishnan89907392015-07-08 21:43:31 +0000281 int maxDepth) throws QueryException, InterruptedException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100282 Set<Target> targets = targetNodes;
283 preloadTransitiveClosure(targets, maxDepth);
Janak Ramakrishnan89907392015-07-08 21:43:31 +0000284 labelVisitor.syncWithVisitor(eventHandler, targets, keepGoing,
285 loadingPhaseThreads, maxDepth, errorObserver, new GraphBuildingObserver());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100286
287 if (errorObserver.hasErrors()) {
288 reportBuildFileError(caller, "errors were encountered while computing transitive closure");
289 }
290 }
291
292 @Override
293 public Set<Target> getNodesOnPath(Target from, Target to) {
294 return getTargetsFromNodes(graph.getShortestPath(getNode(from), getNode(to)));
295 }
296
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +0000297 @Override
Nathan Harmatab869e582017-03-01 02:55:48 +0000298 public void eval(QueryExpression expr, VariableContext<Target> context, Callback<Target> callback)
299 throws QueryException, InterruptedException {
300 AggregateAllCallback<Target> aggregator = QueryUtil.newAggregateAllCallback();
301 expr.eval(this, context, aggregator);
302 callback.process(aggregator.getResult());
303 }
304
305 @Override
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +0000306 public Uniquifier<Target> createUniquifier() {
Nathan Harmatae9826b42017-03-07 18:05:21 +0000307 return new UniquifierImpl<>(TargetKeyExtractor.INSTANCE);
308 }
309
310 @Override
311 public MinDepthUniquifier<Target> createMinDepthUniquifier() {
312 return new ThreadSafeMinDepthUniquifierImpl<>(
313 TargetKeyExtractor.INSTANCE, /*concurrencyLevel=*/ 1);
Miguel Alcon Pinto42984f32015-11-06 19:05:13 +0000314 }
315
Janak Ramakrishnan71cdea42016-08-16 15:14:41 +0000316 private void preloadTransitiveClosure(Set<Target> targets, int maxDepth)
Ulf Adams43765af2017-02-07 16:06:39 +0000317 throws InterruptedException {
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +0000318 if (maxDepth >= MAX_DEPTH_FULL_SCAN_LIMIT && transitivePackageLoader != null) {
319 // Only do the full visitation if "maxDepth" is large enough. Otherwise, the benefits of
320 // preloading will be outweighed by the cost of doing more work than necessary.
Ulf Adams43765af2017-02-07 16:06:39 +0000321 Set<Label> labels = ImmutableSet.copyOf(Collections2.transform(targets, TO_LABEL));
322 transitivePackageLoader.sync(eventHandler, labels, keepGoing, loadingPhaseThreads);
Janak Ramakrishnanfe1056f2015-02-11 21:16:06 +0000323 }
324 }
325
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100326 /**
327 * It suffices to synchronize the modifications of this.graph from within the
328 * GraphBuildingObserver, because that's the only concurrent part.
329 * Concurrency is always encapsulated within the evaluation of a single query
330 * operator (e.g. deps(), somepath(), etc).
331 */
332 private class GraphBuildingObserver implements TargetEdgeObserver {
333
334 @Override
335 public synchronized void edge(Target from, Attribute attribute, Target to) {
336 Preconditions.checkState(attribute == null ||
337 dependencyFilter.apply(((Rule) from), attribute),
338 "Disallowed edge from LabelVisitor: %s --> %s", from, to);
339 makeEdge(from, to);
340 }
341
342 @Override
343 public synchronized void node(Target node) {
344 graph.createNode(node);
345 }
346
347 @Override
348 public void missingEdge(Target target, Label to, NoSuchThingException e) {
349 // No - op.
350 }
351 }
352
353 private void makeEdge(Target from, Target to) {
354 graph.addEdge(from, to);
355 }
356
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100357 private Target getTargetOrThrow(Label label)
358 throws NoSuchThingException, SkyframeRestartQueryException, InterruptedException {
359 Target target = targetProvider.getTarget(eventHandler, label);
360 if (target == null) {
361 throw new SkyframeRestartQueryException();
362 }
363 return target;
364 }
365
366 // TODO(bazel-team): rename this to getDependentFiles when all implementations
367 // of QueryEnvironment is fixed.
368 @Override
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +0000369 public Set<Target> getBuildFiles(
370 final QueryExpression caller,
371 Set<Target> nodes,
372 boolean buildFiles,
373 boolean subincludes,
374 boolean loads)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100375 throws QueryException {
376 Set<Target> dependentFiles = new LinkedHashSet<>();
377 Set<Package> seenPackages = new HashSet<>();
378 // Keep track of seen labels, to avoid adding a fake subinclude label that also exists as a
379 // real target.
380 Set<Label> seenLabels = new HashSet<>();
381
382 // Adds all the package definition files (BUILD files and build
383 // extensions) for package "pkg", to "buildfiles".
384 for (Target x : nodes) {
385 Package pkg = x.getPackage();
386 if (seenPackages.add(pkg)) {
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +0000387 if (buildFiles) {
388 addIfUniqueLabel(getNode(pkg.getBuildFile()), seenLabels, dependentFiles);
389 }
390
391 List<Label> extensions = new ArrayList<>();
392 if (subincludes) {
393 extensions.addAll(pkg.getSubincludeLabels());
394 }
395 if (loads) {
396 extensions.addAll(pkg.getSkylarkFileDependencies());
397 }
398
399 for (Label subinclude : extensions) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100400 addIfUniqueLabel(getSubincludeTarget(subinclude, pkg), seenLabels, dependentFiles);
401
402 // Also add the BUILD file of the subinclude.
Han-Wen Nienhuysc13c0022015-12-15 19:08:38 +0000403 if (buildFiles) {
404 try {
405 addIfUniqueLabel(
406 getSubincludeTarget(subinclude.getLocalTargetLabel("BUILD"), pkg),
407 seenLabels,
408 dependentFiles);
409
410 } catch (LabelSyntaxException e) {
411 throw new AssertionError("BUILD should always parse as a target name", e);
412 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100413 }
414 }
415 }
416 }
417 return dependentFiles;
418 }
419
Janak Ramakrishnancbe26342015-08-17 18:57:57 +0000420 private static final Function<ResolvedTargets<Target>, Set<Target>> RESOLVED_TARGETS_TO_TARGETS =
421 new Function<ResolvedTargets<Target>, Set<Target>>() {
422 @Override
423 public Set<Target> apply(ResolvedTargets<Target> resolvedTargets) {
424 return resolvedTargets.getTargets();
425 }
426 };
427
Ulf Adams3ab82f72015-09-04 12:10:53 +0000428 @Override
Janak Ramakrishnanee6208b2016-01-07 20:17:41 +0000429 protected void preloadOrThrow(QueryExpression caller, Collection<String> patterns)
Janak Ramakrishnan71cdea42016-08-16 15:14:41 +0000430 throws TargetParsingException, InterruptedException {
Janak Ramakrishnanee6208b2016-01-07 20:17:41 +0000431 if (!resolvedTargetPatterns.keySet().containsAll(patterns)) {
Janak Ramakrishnan71cdea42016-08-16 15:14:41 +0000432 // Note that this may throw a RuntimeException if deps are missing in Skyframe and this is
433 // being called from within a SkyFunction.
434 resolvedTargetPatterns.putAll(
435 Maps.transformValues(
436 targetPatternEvaluator.preloadTargetPatterns(eventHandler, patterns, keepGoing),
437 RESOLVED_TARGETS_TO_TARGETS));
Janak Ramakrishnane72d5222015-02-26 17:09:18 +0000438 }
439 }
440
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100441 private static void addIfUniqueLabel(Node<Target> node, Set<Label> labels, Set<Target> nodes) {
442 if (labels.add(node.getLabel().getLabel())) {
443 nodes.add(node.getLabel());
444 }
445 }
446
447 private Node<Target> getSubincludeTarget(final Label label, Package pkg) {
Mark Schallerb817e3f2015-06-04 17:14:18 +0000448 return getNode(new FakeSubincludeTarget(label, pkg));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100449 }
450
451 @Override
452 public TargetAccessor<Target> getAccessor() {
453 return accessor;
454 }
455
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100456 /** Given a set of target nodes, returns the targets. */
457 private static Set<Target> getTargetsFromNodes(Iterable<Node<Target>> input) {
458 Set<Target> result = new LinkedHashSet<>();
459 for (Node<Target> node : input) {
460 result.add(node.getLabel());
461 }
462 return result;
463 }
464}