Clean up Label validation, and introduce a factory method for constructing a Label without validation.
RELNOTES: None
PiperOrigin-RevId: 164479651
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index ec58068..9e4ab19 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -444,7 +444,7 @@
return events;
}
- /** Returns an (immutable, unordered) view of all the targets belonging to this package. */
+ /** Returns an (immutable, ordered) view of all the targets belonging to this package. */
public ImmutableSortedKeyMap<String, Target> getTargets() {
return targets;
}
@@ -457,7 +457,7 @@
}
/**
- * Returns a (read-only, unordered) iterator of all the targets belonging
+ * Returns a (read-only, ordered) iterable of all the targets belonging
* to this package which are instances of the specified class.
*/
public <T extends Target> Iterable<T> getTargets(Class<T> targetClass) {
@@ -1312,12 +1312,14 @@
// current instance here.
buildFile = (InputFile) Preconditions.checkNotNull(targets.get(buildFileLabel.getName()));
- List<Rule> rules = Lists.newArrayList(getTargets(Rule.class));
+ // The Iterable returned by getTargets is sorted, so when we build up the list of tests by
+ // processing it in order below, that list will be sorted too.
+ Iterable<Rule> sortedRules = Lists.newArrayList(getTargets(Rule.class));
if (discoverAssumedInputFiles) {
// All labels mentioned in a rule that refer to an unknown target in the
// current package are assumed to be InputFiles, so let's create them:
- for (final Rule rule : rules) {
+ for (final Rule rule : sortedRules) {
AggregatingAttributeMapper.of(rule).visitLabels(new AcceptsLabelAttribute() {
@Override
public void acceptLabelAttribute(Label label, Attribute attribute) {
@@ -1332,18 +1334,17 @@
// Note, we implement this here when the Package is fully constructed,
// since clearly this information isn't available at Rule construction
// time, as forward references are permitted.
- List<Label> allTests = new ArrayList<>();
- for (Rule rule : rules) {
+ List<Label> sortedTests = new ArrayList<>();
+ for (Rule rule : sortedRules) {
if (TargetUtils.isTestRule(rule) && !TargetUtils.hasManualTag(rule)) {
- allTests.add(rule.getLabel());
+ sortedTests.add(rule.getLabel());
}
}
- Collections.sort(allTests);
- for (Rule rule : rules) {
+ for (Rule rule : sortedRules) {
AttributeMap attributes = NonconfigurableAttributeMapper.of(rule);
if (rule.getRuleClass().equals("test_suite")
&& attributes.get("tests", BuildType.LABEL_LIST).isEmpty()) {
- rule.setAttributeValueByName("$implicit_tests", allTests);
+ rule.setAttributeValueByName("$implicit_tests", sortedTests);
}
}
return this;
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 1a7cc36d..b751f87 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
@@ -473,13 +473,29 @@
*/
void populateOutputFiles(EventHandler eventHandler, Package.Builder pkgBuilder)
throws LabelSyntaxException, InterruptedException {
+ populateOutputFilesInternal(eventHandler, pkgBuilder, /*performChecks=*/ true);
+ }
+
+ void populateOutputFilesUnchecked(EventHandler eventHandler, Package.Builder pkgBuilder)
+ throws InterruptedException {
+ try {
+ populateOutputFilesInternal(eventHandler, pkgBuilder, /*performChecks=*/ false);
+ } catch (LabelSyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ void populateOutputFilesInternal(
+ EventHandler eventHandler, Package.Builder pkgBuilder, boolean performChecks)
+ throws LabelSyntaxException, InterruptedException {
Preconditions.checkState(outputFiles == null);
// Order is important here: implicit before explicit
ImmutableList.Builder<OutputFile> outputFilesBuilder = ImmutableList.builder();
ImmutableListMultimap.Builder<String, OutputFile> outputFileMapBuilder =
ImmutableListMultimap.builder();
- populateImplicitOutputFiles(eventHandler, pkgBuilder, outputFilesBuilder);
- populateExplicitOutputFiles(eventHandler, outputFilesBuilder, outputFileMapBuilder);
+ populateImplicitOutputFiles(eventHandler, pkgBuilder, outputFilesBuilder, performChecks);
+ populateExplicitOutputFiles(
+ eventHandler, outputFilesBuilder, outputFileMapBuilder, performChecks);
outputFiles = outputFilesBuilder.build();
outputFileMap = outputFileMapBuilder.build();
}
@@ -488,7 +504,8 @@
private void populateExplicitOutputFiles(
EventHandler eventHandler,
ImmutableList.Builder<OutputFile> outputFilesBuilder,
- ImmutableListMultimap.Builder<String, OutputFile> outputFileMapBuilder)
+ ImmutableListMultimap.Builder<String, OutputFile> outputFileMapBuilder,
+ boolean performChecks)
throws LabelSyntaxException {
NonconfigurableAttributeMapper nonConfigurableAttributes =
NonconfigurableAttributeMapper.of(this);
@@ -499,11 +516,22 @@
Label outputLabel = nonConfigurableAttributes.get(name, BuildType.OUTPUT);
if (outputLabel != null) {
addLabelOutput(
- attribute, outputLabel, eventHandler, outputFilesBuilder, outputFileMapBuilder);
+ attribute,
+ outputLabel,
+ eventHandler,
+ outputFilesBuilder,
+ outputFileMapBuilder,
+ performChecks);
}
} else if (type == BuildType.OUTPUT_LIST) {
for (Label label : nonConfigurableAttributes.get(name, BuildType.OUTPUT_LIST)) {
- addLabelOutput(attribute, label, eventHandler, outputFilesBuilder, outputFileMapBuilder);
+ addLabelOutput(
+ attribute,
+ label,
+ eventHandler,
+ outputFilesBuilder,
+ outputFileMapBuilder,
+ performChecks);
}
}
}
@@ -516,23 +544,31 @@
private void populateImplicitOutputFiles(
EventHandler eventHandler,
Package.Builder pkgBuilder,
- ImmutableList.Builder<OutputFile> outputFilesBuilder)
+ ImmutableList.Builder<OutputFile> outputFilesBuilder,
+ boolean performChecks)
throws InterruptedException {
try {
RawAttributeMapper attributeMap = RawAttributeMapper.of(this);
for (String out : implicitOutputsFunction.getImplicitOutputs(attributeMap)) {
- try {
- addOutputFile(pkgBuilder.createLabel(out), eventHandler, outputFilesBuilder);
- } catch (LabelSyntaxException e) {
- reportError(
- "illegal output file name '"
- + out
- + "' in rule "
- + getLabel()
- + " due to: "
- + e.getMessage(),
- eventHandler);
+ Label label;
+ if (performChecks) {
+ try {
+ label = pkgBuilder.createLabel(out);
+ } catch (LabelSyntaxException e) {
+ reportError(
+ "illegal output file name '"
+ + out
+ + "' in rule "
+ + getLabel()
+ + " due to: "
+ + e.getMessage(),
+ eventHandler);
+ continue;
+ }
+ } else {
+ label = Label.createUnvalidated(pkgBuilder.getPackageIdentifier(), out);
}
+ addOutputFile(label, eventHandler, outputFilesBuilder);
}
} catch (EvalException e) {
reportError(String.format("In rule %s: %s", getLabel(), e.print()), eventHandler);
@@ -544,16 +580,19 @@
Label label,
EventHandler eventHandler,
ImmutableList.Builder<OutputFile> outputFilesBuilder,
- ImmutableListMultimap.Builder<String, OutputFile> outputFileMapBuilder)
+ ImmutableListMultimap.Builder<String, OutputFile> outputFileMapBuilder,
+ boolean performChecks)
throws LabelSyntaxException {
- if (!label.getPackageIdentifier().equals(pkg.getPackageIdentifier())) {
- throw new IllegalStateException("Label for attribute " + attribute
- + " should refer to '" + pkg.getName()
- + "' but instead refers to '" + label.getPackageFragment()
- + "' (label '" + label.getName() + "')");
- }
- if (label.getName().equals(".")) {
- throw new LabelSyntaxException("output file name can't be equal '.'");
+ if (performChecks) {
+ if (!label.getPackageIdentifier().equals(pkg.getPackageIdentifier())) {
+ throw new IllegalStateException("Label for attribute " + attribute
+ + " should refer to '" + pkg.getName()
+ + "' but instead refers to '" + label.getPackageFragment()
+ + "' (label '" + label.getName() + "')");
+ }
+ if (label.getName().equals(".")) {
+ throw new LabelSyntaxException("output file name can't be equal '.'");
+ }
}
OutputFile outputFile = addOutputFile(label, eventHandler, outputFilesBuilder);
outputFileMapBuilder.put(attribute.getName(), outputFile);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 625130f..efc9d3c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -1498,7 +1498,7 @@
Location location,
AttributeContainer attributeContainer,
ImplicitOutputsFunction implicitOutputsFunction)
- throws LabelSyntaxException, InterruptedException, CannotPrecomputeDefaultsException {
+ throws InterruptedException, CannotPrecomputeDefaultsException {
Rule rule = pkgBuilder.createRule(
ruleLabel,
this,
@@ -1506,7 +1506,7 @@
attributeContainer,
implicitOutputsFunction);
populateRuleAttributeValues(rule, pkgBuilder, attributeValues, NullEventHandler.INSTANCE);
- rule.populateOutputFiles(NullEventHandler.INSTANCE, pkgBuilder);
+ rule.populateOutputFilesUnchecked(NullEventHandler.INSTANCE, pkgBuilder);
return rule;
}