Clean up RuleErrorException: stop allowing it to be called directly, require that it go through RuleErrorConsumer, and allow it to take a cause.
PiperOrigin-RevId: 296014466
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
index 0c4cae2..4cdbab6 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
@@ -266,7 +266,7 @@
try {
makeVariables = ruleContext.getConfigurationMakeVariableContext().collectMakeVariables();
} catch (ExpansionException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java
index 930ba34..db819f5 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java
@@ -69,7 +69,7 @@
public ConfiguredTarget create(RuleContext ruleContext)
throws InterruptedException, RuleErrorException, ActionConflictException {
if (!ruleContext.getAnalysisEnvironment().getSkylarkSemantics().experimentalNinjaActions()) {
- throw new RuleErrorException(
+ throw ruleContext.throwWithRuleError(
"Usage of ninja_graph is only allowed with --experimental_ninja_actions flag");
}
Artifact mainArtifact = ruleContext.getPrerequisiteArtifact("main", Mode.TARGET);
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
index e5d4fc3..8b142c2 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java
@@ -135,10 +135,9 @@
return primaryOutput;
} else {
// If the extensions don't match, we should always respect mainFile's extension.
- ruleContext.ruleError(
+ throw ruleContext.throwWithRuleError(
"Source file is a Windows executable file,"
+ " target name extension should match source file extension");
- throw new RuleErrorException();
}
}
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 1531c8a..301cc77 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
@@ -210,14 +210,22 @@
* messaging should be done via {@link RuleErrorConsumer}; this exception only interrupts
* configured target creation in cases where it can no longer continue.
*/
- public static final class RuleErrorException extends Exception {
- public RuleErrorException() {
+ final class RuleErrorException extends Exception {
+ RuleErrorException() {
super();
}
- public RuleErrorException(String message) {
+ RuleErrorException(String message) {
super(message);
}
+
+ RuleErrorException(Throwable cause) {
+ super(cause);
+ }
+
+ RuleErrorException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleErrorConsumer.java b/src/main/java/com/google/devtools/build/lib/packages/RuleErrorConsumer.java
index 68dc985..9f033b5 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleErrorConsumer.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleErrorConsumer.java
@@ -48,16 +48,29 @@
void attributeError(String attrName, String message);
/**
- * Convenience function to report non-attribute-specific errors in the current rule and then
- * throw a {@link RuleErrorException}, immediately exiting the build invocation. Alternatively,
- * invoke {@link #ruleError} instead to collect additional error information before ending the
- * invocation.
+ * Convenience function to report non-attribute-specific errors in the current rule and then throw
+ * a {@link RuleErrorException}, immediately exiting the current rule, and shutting down the
+ * invocation in a no-keep-going build. If multiple errors are present, invoke {@link #ruleError}
+ * to collect additional error information before calling this method.
*/
default RuleErrorException throwWithRuleError(String message) throws RuleErrorException {
ruleError(message);
throw new RuleErrorException(message);
}
+ /** See {@link #throwWithRuleError(String)}. */
+ default RuleErrorException throwWithRuleError(Throwable cause) throws RuleErrorException {
+ ruleError(cause.getMessage());
+ throw new RuleErrorException(cause);
+ }
+
+ /** See {@link #throwWithRuleError(String)}. */
+ default RuleErrorException throwWithRuleError(String message, Throwable cause)
+ throws RuleErrorException {
+ ruleError(message);
+ throw new RuleErrorException(message, cause);
+ }
+
/**
* Convenience function to report attribute-specific errors in the current rule, and then throw a
* {@link RuleErrorException}, immediately exiting the build invocation. Alternatively, invoke
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java
index f1cf604..765ab64 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java
@@ -93,30 +93,34 @@
}
if (!ConfigFeatureFlag.isAvailable(ruleContext)) {
- ruleContext.attributeError(
+ throw ruleContext.throwWithAttributeError(
FEATURE_FLAG_ATTR,
String.format(
"the %s attribute is not available in package '%s'",
FEATURE_FLAG_ATTR, ruleContext.getLabel().getPackageIdentifier()));
- throw new RuleErrorException();
}
Iterable<? extends TransitiveInfoCollection> actualTargets =
ruleContext.getPrerequisites(FEATURE_FLAG_ATTR, Mode.TARGET);
- boolean aliasFound = false;
+ RuleErrorException exception = null;
for (TransitiveInfoCollection target : actualTargets) {
Label label = AliasProvider.getDependencyLabel(target);
if (!label.equals(target.getLabel())) {
- ruleContext.attributeError(
- FEATURE_FLAG_ATTR,
- String.format(
- "Feature flags must be named directly, not through aliases; use '%s', not '%s'",
- target.getLabel(), label));
- aliasFound = true;
+ try {
+ exception =
+ ruleContext.throwWithAttributeError(
+ FEATURE_FLAG_ATTR,
+ String.format(
+ "Feature flags must be named directly, not through aliases; use '%s', not"
+ + " '%s'",
+ target.getLabel(), label));
+ } catch (RuleErrorException e) {
+ exception = e;
+ }
}
}
- if (aliasFound) {
- throw new RuleErrorException();
+ if (exception != null) {
+ throw exception;
}
return Optional.of(ImmutableMap.copyOf(expectedValues));
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestBase.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestBase.java
index d2e5d91..7f78611 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestBase.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidInstrumentationTestBase.java
@@ -318,8 +318,8 @@
AndroidInstrumentationTestBase.class, TEST_SUITE_PROPERTY_NAME_FILE)
.trim();
} catch (IOException e) {
- ruleContext.throwWithRuleError("Cannot load test suite property name: " + e.getMessage());
- return null;
+ throw ruleContext.throwWithRuleError(
+ "Cannot load test suite property name: " + e.getMessage(), e);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java
index ff18b30..84a2382 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResources.java
@@ -211,14 +211,13 @@
throws RuleErrorException {
PathFragment resourceDir = findResourceDir(file);
if (resourceDir == null) {
- ruleErrorConsumer.attributeError(
+ throw ruleErrorConsumer.throwWithAttributeError(
resourcesAttr,
String.format(INCORRECT_RESOURCE_LAYOUT_MESSAGE, file.getRootRelativePath()));
- throw new RuleErrorException();
}
if (lastResourceDir != null && !resourceDir.equals(lastResourceDir)) {
- ruleErrorConsumer.attributeError(
+ throw ruleErrorConsumer.throwWithAttributeError(
resourcesAttr,
String.format(
"'%s' (generated by '%s') is not in the same directory '%s' (derived from %s)."
@@ -227,7 +226,6 @@
file.getOwnerLabel(),
lastResourceDir,
lastFile.getRootRelativePath()));
- throw new RuleErrorException();
}
PathFragment packageFragment = file.getOwnerLabel().getPackageIdentifier().getSourceRoot();
@@ -239,7 +237,7 @@
0,
path.segmentCount() - segmentCountAfterAncestor(resourceDir, packageRelativePath)));
} catch (IllegalArgumentException e) {
- ruleErrorConsumer.attributeError(
+ throw ruleErrorConsumer.throwWithAttributeError(
resourcesAttr,
String.format(
"'%s' (generated by '%s') is not under the directory '%s' (derived from %s).",
@@ -247,7 +245,6 @@
file.getOwnerLabel(),
packageRelativePath,
file.getRootRelativePath()));
- throw new RuleErrorException();
}
return resourceDir;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
index 5814866..adc0af1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeConfig.java
@@ -228,7 +228,7 @@
try {
aliasesToVersionMap = aliasesToVersionMap(explicitVersions);
} catch (XcodeConfigException e) {
- ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
if (!Strings.isNullOrEmpty(versionOverrideFlag)) {
// The version override flag is not necessarily an actual version - it may be a version
@@ -271,7 +271,7 @@
localAliasesToVersionMap = aliasesToVersionMap(localVersions.getAvailableVersions());
remoteAliasesToVersionMap = aliasesToVersionMap(remoteVersions.getAvailableVersions());
} catch (XcodeConfigException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
// Mutually available Xcode versions are versions that are available both locally and remotely,
// but are referred to by the aliases listed in remote_xcodes.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlag.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlag.java
index 2a8ce3e..6417a4b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlag.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigFeatureFlag.java
@@ -91,12 +91,11 @@
public ConfiguredTarget create(RuleContext ruleContext)
throws InterruptedException, RuleErrorException, ActionConflictException {
if (!ConfigFeatureFlag.isAvailable(ruleContext)) {
- ruleContext.ruleError(
+ throw ruleContext.throwWithRuleError(
String.format(
"the %s rule is not available in package '%s'",
ruleContext.getRuleClassNameForLogging(),
ruleContext.getLabel().getPackageIdentifier()));
- throw new RuleErrorException();
}
List<String> specifiedValues = ruleContext.attributes().get("allowed_values", STRING_LIST);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
index 7fba4fb..ad42202 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
@@ -221,7 +221,7 @@
try {
builder.addTransitiveArtifacts(toolchain.getDynamicRuntimeLinkInputs(featureConfiguration));
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
}
if (linkCompileOutputSeparately) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
index 92da26c..7c19b43 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -347,7 +347,7 @@
ArtifactCategory.DYNAMIC_LIBRARY, ruleContext.getLabel().getName()));
targetBuilder.addOutputGroup(DEF_FILE_OUTPUT_GROUP_NAME, generatedDefFile);
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
}
linkingHelper.setDefFile(
@@ -447,7 +447,7 @@
builder.addTransitiveArtifacts(
ccToolchain.getDynamicRuntimeLinkInputs(featureConfiguration));
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
}
Runfiles runfiles = builder.build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java
index 0938d5f..6effe70 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLinkingHelper.java
@@ -699,7 +699,7 @@
ccToolchain.getDynamicRuntimeLinkMiddleman(ruleErrorConsumer, featureConfiguration),
ccToolchain.getDynamicRuntimeLinkInputs(featureConfiguration));
} catch (EvalException e) {
- throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
+ throw ruleErrorConsumer.throwWithRuleError(e);
}
} else {
try {
@@ -708,7 +708,7 @@
ccToolchain.getStaticRuntimeLinkMiddleman(ruleErrorConsumer, featureConfiguration),
ccToolchain.getStaticRuntimeLinkInputs(featureConfiguration));
} catch (EvalException e) {
- throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
+ throw ruleErrorConsumer.throwWithRuleError(e);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java
index bdc62d4..3205910 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderHelper.java
@@ -81,7 +81,7 @@
toolPaths = computeToolPaths(toolchainConfigInfo, toolsDirectory);
toolchainFeatures = new CcToolchainFeatures(toolchainConfigInfo, toolsDirectory);
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
FdoContext fdoContext =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
index 8c1d2d6..0205e1e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
@@ -208,18 +208,21 @@
* <p>This method may be called multiple times to create multiple compile actions (usually after
* calling some setters to modify the generated action).
*/
- public CppCompileAction buildOrThrowRuleError(RuleErrorConsumer ruleErrorConsumer)
+ CppCompileAction buildOrThrowRuleError(RuleErrorConsumer ruleErrorConsumer)
throws RuleErrorException {
List<String> errorMessages = new ArrayList<>();
CppCompileAction result =
buildAndVerify((String errorMessage) -> errorMessages.add(errorMessage));
if (!errorMessages.isEmpty()) {
- for (String errorMessage : errorMessages) {
- ruleErrorConsumer.ruleError(errorMessage);
+ RuleErrorException exception = null;
+ try {
+ exception = ruleErrorConsumer.throwWithRuleError(errorMessages.get(0));
+ } catch (RuleErrorException e) {
+ exception = e;
}
-
- throw new RuleErrorException(errorMessages.get(0));
+ errorMessages.stream().skip(1L).forEach(ruleErrorConsumer::ruleError);
+ throw exception;
}
return result;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
index bd0aded..397081f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
@@ -247,7 +247,7 @@
try {
return getDefaultCcToolchainDynamicRuntimeInputsFromStarlark(ruleContext);
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
}
@@ -287,7 +287,7 @@
try {
return defaultToolchain.getStaticRuntimeLinkInputs(featureConfiguration);
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
}
@@ -748,7 +748,7 @@
try {
return ImmutableList.copyOf(featureConfiguration.getCommandLine(actionName, variables));
} catch (ExpansionException e) {
- throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
+ throw ruleErrorConsumer.throwWithRuleError(e);
}
}
@@ -761,7 +761,7 @@
try {
return featureConfiguration.getEnvironmentVariables(actionName, variables);
} catch (ExpansionException e) {
- throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
+ throw ruleErrorConsumer.throwWithRuleError(e);
}
}
@@ -814,7 +814,7 @@
try {
return toolchain.getFeatures().getArtifactNameForCategory(category, outputName);
} catch (EvalException e) {
- ruleErrorConsumer.throwWithRuleError(e.getMessage());
+ ruleErrorConsumer.throwWithRuleError(e);
throw new IllegalStateException("Should not be reached");
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java
index e51444d..1d45935 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaBinary.java
@@ -328,7 +328,7 @@
try {
dynamicRuntimeActionInputs = ccToolchain.getDynamicRuntimeLinkInputs(featureConfiguration);
} catch (EvalException e) {
- throw ruleContext.throwWithRuleError(e.getMessage());
+ throw ruleContext.throwWithRuleError(e);
}
collectDefaultRunfiles(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java
index 8a42747f..fb8e021 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleBinary.java
@@ -226,8 +226,7 @@
new AppleLoadableBundleBinaryInfo(outputArtifact, objcProvider);
break;
default:
- ruleContext.ruleError("Unhandled binary type " + getBinaryType(ruleContext));
- throw new RuleErrorException();
+ throw ruleContext.throwWithRuleError("Unhandled binary type " + getBinaryType(ruleContext));
}
AppleDebugOutputsInfo.Builder builder = AppleDebugOutputsInfo.Builder.create();
@@ -355,8 +354,7 @@
outputArtifact = loadableBundleProvider.getAppleLoadableBundleBinary();
break;
default:
- ruleContext.ruleError("Unhandled binary type " + getBinaryType(ruleContext));
- throw new RuleErrorException();
+ throw ruleContext.throwWithRuleError("Unhandled binary type " + getBinaryType(ruleContext));
}
NestedSetBuilder<Artifact> filesToBuild =