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 =