blob: 575a0ff30e9ef740e6df7bedd3c200fd44e9f8dc [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Marian Loburbe3171e2015-06-26 16:03:14 +00002//
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.skyframe;
15
Marian Loburbe3171e2015-06-26 16:03:14 +000016import com.google.common.collect.Maps;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000017import com.google.devtools.build.lib.cmdline.Label;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000018import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Marian Loburbe3171e2015-06-26 16:03:14 +000019import com.google.devtools.build.lib.cmdline.ResolvedTargets;
20import com.google.devtools.build.lib.cmdline.TargetParsingException;
Marian Loburbe3171e2015-06-26 16:03:14 +000021import com.google.devtools.build.lib.packages.NoSuchTargetException;
22import com.google.devtools.build.lib.packages.Package;
Marian Loburbe3171e2015-06-26 16:03:14 +000023import com.google.devtools.build.lib.packages.Target;
Mark Schaller6df81792015-12-10 18:47:47 +000024import com.google.devtools.build.lib.util.Preconditions;
Marian Loburbe3171e2015-06-26 16:03:14 +000025import com.google.devtools.build.skyframe.WalkableGraph;
26
27import java.util.HashSet;
28import java.util.Map;
29import java.util.Set;
30
31/**
32 * This class encapsulates logic behind computing final target set based on separate results from a
33 * list of target patterns (eg, //foo:all -//bar/... //foo:test).
34 */
35abstract class TargetPatternsResultBuilder {
36 private Map<PackageIdentifier, Package> packages = null;
37 private boolean hasError = false;
38
39 /**
40 * Sets that there was an error, during evaluation.
41 */
42 public void setError() {
43 hasError = true;
44 }
45
46 /**
47 * Returns final set of targets and sets error flag if required.
48 */
49 public ResolvedTargets<Target> build(WalkableGraph walkableGraph) throws TargetParsingException {
50 precomputePackages(walkableGraph);
51 ResolvedTargets.Builder<Target> resolvedTargetsBuilder = buildInternal();
52 if (hasError) {
53 resolvedTargetsBuilder.setError();
54 }
55 return resolvedTargetsBuilder.build();
56 }
57
58 /**
59 * Transforms {@code ResolvedTargets<Label>} to {@code ResolvedTargets<Target>}. Note that this
60 * method is using information about packages, so {@link #precomputePackages} has to be called
61 * before this method.
62 */
63 protected ResolvedTargets.Builder<Target> transformLabelsIntoTargets(
64 ResolvedTargets<Label> resolvedLabels) {
65 // precomputePackages has to be called before this method.
66 ResolvedTargets.Builder<Target> resolvedTargetsBuilder = ResolvedTargets.builder();
67 Preconditions.checkNotNull(packages);
68 for (Label label : resolvedLabels.getTargets()) {
69 resolvedTargetsBuilder.add(getExistingTarget(label));
70 }
71 for (Label label : resolvedLabels.getFilteredTargets()) {
72 resolvedTargetsBuilder.remove(getExistingTarget(label));
73 }
74 return resolvedTargetsBuilder;
75 }
76
77 private void precomputePackages(WalkableGraph walkableGraph) {
78 Set<PackageIdentifier> packagesToRequest = getPackagesIdentifiers();
79 packages = Maps.newHashMapWithExpectedSize(packagesToRequest.size());
80 for (PackageIdentifier pkgIdentifier : packagesToRequest) {
81 packages.put(pkgIdentifier, findPackageInGraph(pkgIdentifier, walkableGraph));
82 }
83 }
84
85 private Target getExistingTarget(Label label) {
86 Package pkg = Preconditions.checkNotNull(packages.get(label.getPackageIdentifier()), label);
87 try {
88 return pkg.getTarget(label.getName());
89 } catch (NoSuchTargetException e) {
90 // This exception should not raise, because we are processing it during TargetPatternValues
91 // evaluation in SkyframeTargetPatternEvaluator#parseTargetPatternKeys and values with errors
92 // are not added to final result.
93 throw new IllegalStateException(e);
94 }
95 }
96
97 private Set<PackageIdentifier> getPackagesIdentifiers() {
98 Set<PackageIdentifier> packagesIdentifiers = new HashSet<>();
99 for (Label label : getLabels()) {
100 packagesIdentifiers.add(label.getPackageIdentifier());
101 }
102 return packagesIdentifiers;
103 }
104
105 private Package findPackageInGraph(PackageIdentifier pkgIdentifier,
106 WalkableGraph walkableGraph) {
Janak Ramakrishnan0a4c6e42015-09-17 00:37:58 +0000107 return Preconditions.checkNotNull(
108 ((PackageValue) walkableGraph.getValue(PackageValue.key(pkgIdentifier))), pkgIdentifier)
109 .getPackage();
Marian Loburbe3171e2015-06-26 16:03:14 +0000110 }
111
112 /**
113 * Adds the result from expansion of positive target pattern (eg, "//foo:all").
114 */
115 abstract void addLabelsOfNegativePattern(ResolvedTargets<Label> labels);
116
117 /**
118 * Adds the result from expansion of negative target pattern (eg, "-//foo:all").
119 */
120 abstract void addLabelsOfPositivePattern(ResolvedTargets<Label> labels);
121
122 /**
123 * Returns {@code ResolvedTargets.Builder<Target>} with final set of targets. Note that this
124 * method doesn't set error flag in result.
125 */
126 abstract ResolvedTargets.Builder<Target> buildInternal() throws TargetParsingException;
127
128 /**
129 * Returns target labels from all individual results.
130 */
131 protected abstract Iterable<Label> getLabels();
132}