blob: 9c1ba085e3bc30f43b901c16ee69aa822ee00e27 [file] [log] [blame]
// Copyright 2014 The Bazel Authors. 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.pkgcache;
import com.google.common.base.Preconditions;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.buildeventstream.BuildEventContext;
import com.google.devtools.build.lib.buildeventstream.BuildEventIdUtil;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.PatternExpanded;
import com.google.devtools.build.lib.buildeventstream.BuildEventWithOrderConstraint;
import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import java.util.Collection;
import javax.annotation.Nullable;
/** This event is fired just after target pattern evaluation is completed. */
public final class TargetParsingCompleteEvent implements BuildEventWithOrderConstraint {
/** A target-like object that is lighter than a target but has all data needed by callers. */
public static final class ThinTarget {
private final Label label;
@Nullable private final String ruleClass;
private final String targetKind;
private ThinTarget(Target target) {
this.label = target.getLabel();
this.targetKind = target.getTargetKind();
this.ruleClass = (target instanceof Rule) ? ((Rule) target).getRuleClass() : null;
}
public boolean isRule() {
return ruleClass != null;
}
public String getTargetKind() {
return targetKind;
}
public Label getLabel() {
return label;
}
/** Gets the rule class of this target. Caller must already know it {@link #isRule}. */
public String getRuleClass() {
return Preconditions.checkNotNull(ruleClass, label);
}
public boolean isTestSuiteRule() {
return isRule() && TargetUtils.isTestSuiteRuleName(getRuleClass());
}
public boolean isNotATestOrTestSuite() {
return !isRule() || (!isTestSuiteRule() && !TargetUtils.isTestRuleName(getRuleClass()));
}
}
private final ImmutableList<String> originalTargetPattern;
private final ImmutableList<String> failedTargetPatterns;
private final ImmutableSet<ThinTarget> targets;
private final ImmutableSet<ThinTarget> filteredTargets;
private final ImmutableSet<ThinTarget> testFilteredTargets;
private final ImmutableSet<ThinTarget> expandedTargets;
private final ImmutableSetMultimap<String, Label> originalPatternsToLabels;
private final ImmutableMap<Label, ImmutableSet<Label>> testSuiteExpansions;
public TargetParsingCompleteEvent(
Collection<Target> targets,
Collection<Target> filteredTargets,
Collection<Target> testFilteredTargets,
ImmutableList<String> originalTargetPattern,
Collection<Target> expandedTargets,
ImmutableList<String> failedTargetPatterns,
ImmutableSetMultimap<String, Label> originalPatternsToLabels,
ImmutableMap<Label, ImmutableSet<Label>> testSuiteExpansions) {
this.targets = asThinTargets(targets);
this.filteredTargets = asThinTargets(filteredTargets);
this.testFilteredTargets = asThinTargets(testFilteredTargets);
this.originalTargetPattern = Preconditions.checkNotNull(originalTargetPattern);
this.expandedTargets = asThinTargets(expandedTargets);
this.failedTargetPatterns = Preconditions.checkNotNull(failedTargetPatterns);
this.originalPatternsToLabels = Preconditions.checkNotNull(originalPatternsToLabels);
this.testSuiteExpansions = Preconditions.checkNotNull(testSuiteExpansions);
}
public ImmutableList<String> getOriginalTargetPattern() {
return originalTargetPattern;
}
public ImmutableList<String> getFailedTargetPatterns() {
return failedTargetPatterns;
}
/** @return the parsed targets, which will subsequently be loaded */
public ImmutableSet<ThinTarget> getTargets() {
return targets;
}
public Iterable<Label> getLabels() {
return Iterables.transform(targets, ThinTarget::getLabel);
}
public Iterable<Label> getFilteredLabels() {
return Iterables.transform(filteredTargets, ThinTarget::getLabel);
}
public Iterable<Label> getTestFilteredLabels() {
return Iterables.transform(testFilteredTargets, ThinTarget::getLabel);
}
/** @return the filtered targets (i.e., using -//foo:bar on the command-line) */
public ImmutableSet<ThinTarget> getFilteredTargets() {
return filteredTargets;
}
/** @return the test-filtered targets, if --build_test_only is in effect */
public ImmutableSet<ThinTarget> getTestFilteredTargets() {
return testFilteredTargets;
}
/**
* Returns a mapping from patterns originally passed on the command line to the labels they were
* expanded to.
*
* <p>Negative patterns are not included here. Neither are labels of targets that are skipped due
* to matching a negative pattern (even if they also matched a positive pattern).
*
* <p>Test suite labels are included here, but not the labels of the tests that the suite expanded
* to.
*/
public ImmutableSetMultimap<String, Label> getOriginalPatternsToLabels() {
return originalPatternsToLabels;
}
@Override
public BuildEventId getEventId() {
return BuildEventIdUtil.targetPatternExpanded(originalTargetPattern);
}
@Override
public Collection<BuildEventId> postedAfter() {
return ImmutableList.of(BuildEventIdUtil.buildStartedId());
}
@Override
public Collection<BuildEventId> getChildrenEvents() {
ImmutableList.Builder<BuildEventId> childrenBuilder = ImmutableList.builder();
for (String failedTargetPattern : failedTargetPatterns) {
childrenBuilder.add(
BuildEventIdUtil.targetPatternExpanded(ImmutableList.of(failedTargetPattern)));
}
for (ThinTarget target : expandedTargets) {
// Test suites won't produce target configuration and target-complete events, so do not
// announce here completion as children.
if (!target.isTestSuiteRule()) {
childrenBuilder.add(BuildEventIdUtil.targetConfigured(target.getLabel()));
}
}
return childrenBuilder.build();
}
@Override
public BuildEventStreamProtos.BuildEvent asStreamProto(BuildEventContext converters) {
PatternExpanded.Builder expanded = PatternExpanded.newBuilder();
testSuiteExpansions.forEach(
(suite, tests) ->
expanded
.addTestSuiteExpansionsBuilder()
.setSuiteLabel(suite.toString())
.addAllTestLabels(Collections2.transform(tests, Label::toString)));
return GenericBuildEvent.protoChaining(this).setExpanded(expanded).build();
}
@Override
public boolean storeForReplay() {
return true;
}
private static ImmutableSet<ThinTarget> asThinTargets(Collection<Target> targets) {
return targets.stream().map(ThinTarget::new).collect(ImmutableSet.toImmutableSet());
}
}