MethodDescriptor.call: don't convert unchecked exceptions into EvalException.
Also, move some code that doesn't need to be in the try block out of it.
Closes #8266.
PiperOrigin-RevId: 251673653
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
index 839e228..c251bac 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryFunction.java
@@ -146,12 +146,11 @@
// all label-arguments can be resolved to paths.
try {
skylarkRepositoryContext.enforceLabelAttributes();
+ } catch (RepositoryMissingDependencyException e) {
+ // Missing values are expected; just restart before we actually start the rule
+ return null;
} catch (EvalException e) {
- if (e instanceof RepositoryMissingDependencyException) {
- // Missing values are expected; just restart before we actually start the rule
- return null;
- }
- // Other EvalExceptions indicate labels not referring to existing files. This is fine,
+ // EvalExceptions indicate labels not referring to existing files. This is fine,
// as long as they are never resolved to files in the execution of the rule; we allow
// non-strict rules. So now we have to start evaluating the actual rule, even if that
// means the rule might get restarted for legitimate reasons.
@@ -193,18 +192,17 @@
}
}
env.getListener().post(resolved);
- } catch (EvalException e) {
- if (e.getCause() instanceof RepositoryMissingDependencyException) {
- // A dependency is missing, cleanup and returns null
- try {
- if (outputDirectory.exists()) {
- outputDirectory.deleteTree();
- }
- } catch (IOException e1) {
- throw new RepositoryFunctionException(e1, Transience.TRANSIENT);
+ } catch (RepositoryMissingDependencyException e) {
+ // A dependency is missing, cleanup and returns null
+ try {
+ if (outputDirectory.exists()) {
+ outputDirectory.deleteTree();
}
- return null;
+ } catch (IOException e1) {
+ throw new RepositoryFunctionException(e1, Transience.TRANSIENT);
}
+ return null;
+ } catch (EvalException e) {
env.getListener()
.handle(
Event.error(
diff --git a/src/main/java/com/google/devtools/build/lib/exec/local/XcodeLocalEnvProvider.java b/src/main/java/com/google/devtools/build/lib/exec/local/XcodeLocalEnvProvider.java
index c2c5ea6..f64291e 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/local/XcodeLocalEnvProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/local/XcodeLocalEnvProvider.java
@@ -93,7 +93,7 @@
String developerDir = "";
if (containsXcodeVersion) {
String version = env.get(AppleConfiguration.XCODE_VERSION_ENV_NAME);
- developerDir = getDeveloperDir(binTools, DottedVersion.fromString(version));
+ developerDir = getDeveloperDir(binTools, DottedVersion.fromStringUnchecked(version));
newEnvBuilder.put("DEVELOPER_DIR", developerDir);
}
if (containsAppleSdkVersion) {
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 86730ac..4528501 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
@@ -211,7 +211,15 @@
* 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 static final class RuleErrorException extends Exception {
+ public RuleErrorException() {
+ super();
+ }
+
+ public RuleErrorException(String message) {
+ super(message);
+ }
+ }
}
/**
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 8b63425..68dc985 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
@@ -55,7 +55,7 @@
*/
default RuleErrorException throwWithRuleError(String message) throws RuleErrorException {
ruleError(message);
- throw new RuleErrorException();
+ throw new RuleErrorException(message);
}
/**
@@ -70,7 +70,7 @@
default RuleErrorException throwWithAttributeError(String attrName, String message)
throws RuleErrorException {
attributeError(attrName, message);
- throw new RuleErrorException();
+ throw new RuleErrorException(message);
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
index 6f8da8a..5da1090 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
@@ -91,12 +91,11 @@
PathFragment path = file.getExecPath();
assetRoots.add(path.subFragment(0, path.segmentCount() - relativePath.segmentCount()));
} else {
- errorConsumer.attributeError(
+ errorConsumer.throwWithAttributeError(
ASSETS_ATTR,
String.format(
"'%s' (generated by '%s') is not beneath '%s'",
file.getRootRelativePath(), target.getLabel(), assetsDir));
- throw new RuleErrorException();
}
assets.add(file);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java b/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java
index d33ebe6..959c05e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/ApplePlatform.java
@@ -192,6 +192,13 @@
printer.append(toString());
}
+ /** Exception indicating an unknown or unsupported Apple platform type. */
+ public static class UnsupportedPlatformTypeException extends Exception {
+ public UnsupportedPlatformTypeException(String msg) {
+ super(msg);
+ }
+ }
+
/**
* Value used to describe Apple platform "type". A {@link ApplePlatform} is implied from a
* platform type (for example, watchOS) together with a cpu value (for example, armv7).
@@ -222,15 +229,16 @@
/**
* Returns the {@link PlatformType} with given name (case insensitive).
*
- * @throws IllegalArgumentException if the name does not match a valid platform type.
+ * @throws UnsupportedPlatformTypeException if the name does not match a valid platform type.
*/
- public static PlatformType fromString(String name) {
+ public static PlatformType fromString(String name) throws UnsupportedPlatformTypeException {
for (PlatformType platformType : PlatformType.values()) {
if (name.equalsIgnoreCase(platformType.toString())) {
return platformType;
}
}
- throw new IllegalArgumentException(String.format("Unsupported platform type \"%s\"", name));
+ throw new UnsupportedPlatformTypeException(
+ String.format("Unsupported platform type \"%s\"", name));
}
/** Returns a Skylark struct that contains the instances of this enum. */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java
index a19fa35..99a47c7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleToolchain.java
@@ -106,7 +106,7 @@
case IOS_SIMULATOR:
if (xcodeConfig
.getSdkVersionForPlatform(targetPlatform)
- .compareTo(DottedVersion.fromString("9.0"))
+ .compareTo(DottedVersion.fromStringUnchecked("9.0"))
>= 0) {
relativePath = SYSTEM_FRAMEWORK_PATH;
} else {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersion.java b/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersion.java
index b4cc5ff..3ab3aea 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersion.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersion.java
@@ -129,14 +129,37 @@
private static final String NO_ALPHA_SEQUENCE = null;
private static final Component ZERO_COMPONENT = new Component(0, NO_ALPHA_SEQUENCE, 0, "0");
+ /** Exception thrown when parsing an invalid dotted version. */
+ public static class InvalidDottedVersionException extends Exception {
+ InvalidDottedVersionException(String msg) {
+ super(msg);
+ }
+
+ InvalidDottedVersionException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+
+ /**
+ * Create a dotted version by parsing the given version string. Throws an unchecked exception if
+ * the argument is malformed.
+ */
+ public static DottedVersion fromStringUnchecked(String version) {
+ try {
+ return fromString(version);
+ } catch (InvalidDottedVersionException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
/**
* Generates a new dotted version from the given version string.
*
- * @throws IllegalArgumentException if the passed string is not a valid dotted version
+ * @throws InvalidDottedVersionException if the passed string is not a valid dotted version
*/
- public static DottedVersion fromString(String version) {
+ public static DottedVersion fromString(String version) throws InvalidDottedVersionException {
if (Strings.isNullOrEmpty(version)) {
- throw new IllegalArgumentException(String.format(ILLEGAL_VERSION, version));
+ throw new InvalidDottedVersionException(String.format(ILLEGAL_VERSION, version));
}
ArrayList<Component> components = new ArrayList<>();
for (String component : DOT_SPLITTER.split(version)) {
@@ -158,10 +181,11 @@
return new DottedVersion(ImmutableList.copyOf(components), version, numOriginalComponents);
}
- private static Component toComponent(String component, String version) {
+ private static Component toComponent(String component, String version)
+ throws InvalidDottedVersionException {
Matcher parsedComponent = COMPONENT_PATTERN.matcher(component);
if (!parsedComponent.matches()) {
- throw new IllegalArgumentException(String.format(ILLEGAL_VERSION, version));
+ throw new InvalidDottedVersionException(String.format(ILLEGAL_VERSION, version));
}
int firstNumber;
@@ -180,12 +204,13 @@
return new Component(firstNumber, alphaSequence, secondNumber, component);
}
- private static int parseNumber(Matcher parsedComponent, int group, String version) {
+ private static int parseNumber(Matcher parsedComponent, int group, String version)
+ throws InvalidDottedVersionException {
int firstNumber;
try {
firstNumber = Integer.parseInt(parsedComponent.group(group));
} catch (NumberFormatException e) {
- throw new IllegalArgumentException(String.format(ILLEGAL_VERSION, version), e);
+ throw new InvalidDottedVersionException(String.format(ILLEGAL_VERSION, version), e);
}
return firstNumber;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java b/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java
index 44ba329..cb26b3e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/DottedVersionConverter.java
@@ -26,7 +26,7 @@
public DottedVersion.Option convert(String input) throws OptionsParsingException {
try {
return DottedVersion.option(DottedVersion.fromString(input));
- } catch (IllegalArgumentException e) {
+ } catch (DottedVersion.InvalidDottedVersionException e) {
throw new OptionsParsingException(e.getMessage());
}
}
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 445db9b..19a2a99 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
@@ -37,7 +37,8 @@
* Implementation for the {@code xcode_config} rule.
*/
public class XcodeConfig implements RuleConfiguredTargetFactory {
- private static final DottedVersion MINIMUM_BITCODE_XCODE_VERSION = DottedVersion.fromString("7");
+ private static final DottedVersion MINIMUM_BITCODE_XCODE_VERSION =
+ DottedVersion.fromStringUnchecked("7");
/**
* An exception that signals that an Xcode config setup was invalid.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java
index 83e13ef..0d9bd86 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionProperties.java
@@ -79,20 +79,20 @@
this.xcodeVersion = Optional.fromNullable(xcodeVersion);
this.defaultIosSdkVersion =
Strings.isNullOrEmpty(defaultIosSdkVersion)
- ? DottedVersion.fromString(DEFAULT_IOS_SDK_VERSION)
- : DottedVersion.fromString(defaultIosSdkVersion);
+ ? DottedVersion.fromStringUnchecked(DEFAULT_IOS_SDK_VERSION)
+ : DottedVersion.fromStringUnchecked(defaultIosSdkVersion);
this.defaultWatchosSdkVersion =
Strings.isNullOrEmpty(defaultWatchosSdkVersion)
- ? DottedVersion.fromString(DEFAULT_WATCHOS_SDK_VERSION)
- : DottedVersion.fromString(defaultWatchosSdkVersion);
+ ? DottedVersion.fromStringUnchecked(DEFAULT_WATCHOS_SDK_VERSION)
+ : DottedVersion.fromStringUnchecked(defaultWatchosSdkVersion);
this.defaultTvosSdkVersion =
Strings.isNullOrEmpty(defaultTvosSdkVersion)
- ? DottedVersion.fromString(DEFAULT_TVOS_SDK_VERSION)
- : DottedVersion.fromString(defaultTvosSdkVersion);
+ ? DottedVersion.fromStringUnchecked(DEFAULT_TVOS_SDK_VERSION)
+ : DottedVersion.fromStringUnchecked(defaultTvosSdkVersion);
this.defaultMacosSdkVersion =
Strings.isNullOrEmpty(defaultMacosSdkVersion)
- ? DottedVersion.fromString(DEFAULT_MACOS_SDK_VERSION)
- : DottedVersion.fromString(defaultMacosSdkVersion);
+ ? DottedVersion.fromStringUnchecked(DEFAULT_MACOS_SDK_VERSION)
+ : DottedVersion.fromStringUnchecked(defaultMacosSdkVersion);
}
/** Returns the xcode version, or null if the xcode version is unknown. */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java
index e98bb23..a482abe 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/XcodeVersionRuleData.java
@@ -45,8 +45,9 @@
NonconfigurableAttributeMapper.of(rule);
this.label = label;
- DottedVersion xcodeVersion = DottedVersion.fromString(
- attrMapper.get(XcodeVersionRule.VERSION_ATTR_NAME, Type.STRING));
+ DottedVersion xcodeVersion =
+ DottedVersion.fromStringUnchecked(
+ attrMapper.get(XcodeVersionRule.VERSION_ATTR_NAME, Type.STRING));
String iosSdkVersionString =
attrMapper.get(XcodeVersionRule.DEFAULT_IOS_SDK_VERSION_ATTR_NAME, Type.STRING);
String watchosSdkVersionString =
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 02a8d61..51a066b 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
@@ -218,7 +218,7 @@
ruleErrorConsumer.ruleError(errorMessage);
}
- throw new RuleErrorException();
+ throw new RuleErrorException(errorMessages.get(0));
}
return result;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
index ea014b2..f25fdb3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
@@ -182,9 +182,7 @@
@Override
// This method is registered statically for skylark, and never called directly.
public ObjcProvider newObjcProvider(
- Boolean usesSwift,
- SkylarkDict<?, ?> kwargs,
- Environment environment) {
+ Boolean usesSwift, SkylarkDict<?, ?> kwargs, Environment environment) throws EvalException {
ObjcProvider.Builder resultBuilder = new ObjcProvider.Builder(environment.getSemantics());
if (usesSwift) {
resultBuilder.add(ObjcProvider.FLAG, ObjcProvider.Flag.USES_SWIFT);
@@ -198,7 +196,7 @@
} else if (entry.getKey().equals("direct_dep_providers")) {
resultBuilder.addDirectDepProvidersFromSkylark(entry.getValue());
} else {
- throw new IllegalArgumentException(String.format(BAD_KEY_ERROR, entry.getKey()));
+ throw new EvalException(null, String.format(BAD_KEY_ERROR, entry.getKey()));
}
}
return resultBuilder.build();
@@ -253,8 +251,12 @@
}
@Override
- public DottedVersion dottedVersion(String version) {
- return DottedVersion.fromString(version);
+ public DottedVersion dottedVersion(String version) throws EvalException {
+ try {
+ return DottedVersion.fromString(version);
+ } catch (DottedVersion.InvalidDottedVersionException e) {
+ throw new EvalException(null, e.getMessage());
+ }
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java
index dd6646f..762d64f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/MultiArchSplitTransitionProvider.java
@@ -76,7 +76,9 @@
ruleContext.attributes().get(PlatformRule.PLATFORM_TYPE_ATTR_NAME, STRING);
try {
return getPlatformType(attributeValue);
- } catch (IllegalArgumentException exception) {
+ } catch (
+ @SuppressWarnings("UnusedException")
+ ApplePlatform.UnsupportedPlatformTypeException exception) {
throw ruleContext.throwWithAttributeError(
PlatformRule.PLATFORM_TYPE_ATTR_NAME,
String.format(UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT, attributeValue));
@@ -87,13 +89,14 @@
* Returns the apple platform type for the given platform type string (corresponding directly with
* platform type attribute value).
*
- * @throws IllegalArgumentException if the given platform type string is not a valid type
+ * @throws UnsupportedPlatformTypeException if the given platform type string is not a valid type
*/
- public static PlatformType getPlatformType(String platformTypeString) {
+ private static PlatformType getPlatformType(String platformTypeString)
+ throws ApplePlatform.UnsupportedPlatformTypeException {
PlatformType platformType = PlatformType.fromString(platformTypeString);
if (!SUPPORTED_PLATFORM_TYPES.contains(platformType)) {
- throw new IllegalArgumentException(
+ throw new ApplePlatform.UnsupportedPlatformTypeException(
String.format(UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT, platformTypeString));
} else {
return platformType;
@@ -122,7 +125,7 @@
PlatformRule.MINIMUM_OS_VERSION,
String.format(INVALID_VERSION_STRING_ERROR_FORMAT, attributeValue));
}
- } catch (IllegalArgumentException exception) {
+ } catch (DottedVersion.InvalidDottedVersionException exception) {
ruleContext.throwWithAttributeError(
PlatformRule.MINIMUM_OS_VERSION,
String.format(INVALID_VERSION_STRING_ERROR_FORMAT, attributeValue));
@@ -144,7 +147,8 @@
} else {
minimumOsVersion = Optional.of(DottedVersion.fromString(minimumOsVersionString));
}
- } catch (IllegalArgumentException exception) {
+ } catch (ApplePlatform.UnsupportedPlatformTypeException
+ | DottedVersion.InvalidDottedVersionException exception) {
// There's no opportunity to propagate exception information up cleanly at the transition
// provider level. This should later be registered as a rule error during the initialization
// of the rule.
@@ -208,7 +212,7 @@
AppleConfiguration.iosCpuFromCpu(buildOptions.get(CoreOptions.class).cpu));
}
if (actualMinimumOsVersion != null
- && actualMinimumOsVersion.compareTo(DottedVersion.fromString("11.0")) >= 0) {
+ && actualMinimumOsVersion.compareTo(DottedVersion.fromStringUnchecked("11.0")) >= 0) {
List<String> non32BitCpus =
cpus.stream()
.filter(cpu -> !ApplePlatform.is32Bit(PlatformType.IOS, cpu))
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java
index ad82eb2..973c6ef 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java
@@ -39,6 +39,7 @@
import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext;
import com.google.devtools.build.lib.skylarkbuildapi.apple.ObjcProviderApi;
+import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
@@ -1128,7 +1129,7 @@
* Add elements in toAdd with the given key from skylark. An error is thrown if toAdd is not an
* appropriate SkylarkNestedSet.
*/
- void addElementsFromSkylark(Key<?> key, Object skylarkToAdd) {
+ void addElementsFromSkylark(Key<?> key, Object skylarkToAdd) throws EvalException {
NestedSet<?> toAdd = ObjcProviderSkylarkConverters.convertToJava(key, skylarkToAdd);
uncheckedAddTransitive(key, toAdd, this.items);
if (ObjcProvider.KEYS_FOR_DIRECT.contains(key)) {
@@ -1141,16 +1142,18 @@
* ObjcProvider instances.
*/
@SuppressWarnings("unchecked")
- void addProvidersFromSkylark(Object toAdd) {
+ void addProvidersFromSkylark(Object toAdd) throws EvalException {
if (!(toAdd instanceof Iterable)) {
- throw new IllegalArgumentException(
+ throw new EvalException(
+ null,
String.format(
AppleSkylarkCommon.BAD_PROVIDERS_ITER_ERROR, EvalUtils.getDataTypeName(toAdd)));
} else {
Iterable<Object> toAddIterable = (Iterable<Object>) toAdd;
for (Object toAddObject : toAddIterable) {
if (!(toAddObject instanceof ObjcProvider)) {
- throw new IllegalArgumentException(
+ throw new EvalException(
+ null,
String.format(
AppleSkylarkCommon.BAD_PROVIDERS_ELEM_ERROR,
EvalUtils.getDataTypeName(toAddObject)));
@@ -1162,21 +1165,22 @@
}
/**
- * Adds the given providers from skylark, but propagate any normally-propagated items
- * only to direct dependers. An error is thrown if toAdd is not an iterable of ObjcProvider
- * instances.
+ * Adds the given providers from skylark, but propagate any normally-propagated items only to
+ * direct dependers. An error is thrown if toAdd is not an iterable of ObjcProvider instances.
*/
@SuppressWarnings("unchecked")
- void addDirectDepProvidersFromSkylark(Object toAdd) {
+ void addDirectDepProvidersFromSkylark(Object toAdd) throws EvalException {
if (!(toAdd instanceof Iterable)) {
- throw new IllegalArgumentException(
+ throw new EvalException(
+ null,
String.format(
AppleSkylarkCommon.BAD_PROVIDERS_ITER_ERROR, EvalUtils.getDataTypeName(toAdd)));
} else {
Iterable<Object> toAddIterable = (Iterable<Object>) toAdd;
for (Object toAddObject : toAddIterable) {
if (!(toAddObject instanceof ObjcProvider)) {
- throw new IllegalArgumentException(
+ throw new EvalException(
+ null,
String.format(
AppleSkylarkCommon.BAD_PROVIDERS_ELEM_ERROR,
EvalUtils.getDataTypeName(toAddObject)));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java
index 1cde2ee..a1b3d4e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProviderSkylarkConverters.java
@@ -22,6 +22,7 @@
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.objc.ObjcProvider.Key;
+import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.syntax.SkylarkType;
@@ -52,7 +53,8 @@
}
/** Returns a value for a java ObjcProvider given a key and a corresponding skylark value. */
- public static NestedSet<?> convertToJava(Key<?> javaKey, Object skylarkValue) {
+ public static NestedSet<?> convertToJava(Key<?> javaKey, Object skylarkValue)
+ throws EvalException {
return CONVERTERS.get(javaKey.getType()).valueForJava(javaKey, skylarkValue);
}
@@ -74,7 +76,7 @@
Object valueForSkylark(Key<?> javaKey, NestedSet<?> javaValue);
/** Translates a skylark ObjcProvider value to a java ObjcProvider value. */
- NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue);
+ NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) throws EvalException;
}
/**
@@ -89,7 +91,7 @@
}
@Override
- public NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) {
+ public NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) throws EvalException {
validateTypes(skylarkValue, javaKey.getType(), javaKey.getSkylarkKeyName());
return ((SkylarkNestedSet) skylarkValue).getSet(javaKey.getType());
}
@@ -108,7 +110,7 @@
@SuppressWarnings("unchecked")
@Override
- public NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) {
+ public NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) throws EvalException {
validateTypes(skylarkValue, String.class, javaKey.getSkylarkKeyName());
NestedSetBuilder<PathFragment> result = NestedSetBuilder.stableOrder();
for (String path : ((SkylarkNestedSet) skylarkValue).toCollection(String.class)) {
@@ -117,7 +119,7 @@
return result.build();
}
}
-
+
/**
* A converter that that translates between a java {@link SdkFramework} and a skylark string.
*/
@@ -135,7 +137,7 @@
@SuppressWarnings("unchecked")
@Override
- public NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) {
+ public NestedSet<?> valueForJava(Key<?> javaKey, Object skylarkValue) throws EvalException {
validateTypes(skylarkValue, String.class, javaKey.getSkylarkKeyName());
NestedSetBuilder<SdkFramework> result = NestedSetBuilder.stableOrder();
for (String path : ((SkylarkNestedSet) skylarkValue).toCollection(String.class)) {
@@ -145,15 +147,15 @@
}
}
- /**
- * Throws an error if the given object is not a nested set of the given type.
- */
- private static void validateTypes(Object toCheck, Class<?> expectedSetType, String keyName) {
+ /** Throws an error if the given object is not a nested set of the given type. */
+ private static void validateTypes(Object toCheck, Class<?> expectedSetType, String keyName)
+ throws EvalException {
if (!(toCheck instanceof SkylarkNestedSet)) {
- throw new IllegalArgumentException(
- String.format(NOT_SET_ERROR, keyName, EvalUtils.getDataTypeName(toCheck)));
+ throw new EvalException(
+ null, String.format(NOT_SET_ERROR, keyName, EvalUtils.getDataTypeName(toCheck)));
} else if (!((SkylarkNestedSet) toCheck).getContentType().canBeCastTo(expectedSetType)) {
- throw new IllegalArgumentException(
+ throw new EvalException(
+ null,
String.format(
BAD_SET_TYPE_ERROR,
keyName,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
index a996df9..2bab9f5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
@@ -138,6 +138,11 @@
RepositoryMissingDependencyException() {
super(Location.BUILTIN, "Internal exception");
}
+
+ @Override
+ public boolean canBeAddedToStackTrace() {
+ return false;
+ }
}
/**
* repository functions can throw the result of this function to notify the RepositoryFunction
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java
index 28d62b0..b5d9a23 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/apple/AppleCommonApi.java
@@ -279,32 +279,27 @@
public SplitTransitionProviderApi getMultiArchSplitProvider();
@SkylarkCallable(
- name = "new_objc_provider",
- doc = "Creates a new ObjcProvider instance.",
- parameters = {
- @Param(
- name = "uses_swift",
- type = Boolean.class,
- defaultValue = "False",
- named = true,
- positional = false,
- doc = "Whether this provider should enable Swift support."
- )
- },
- extraKeywords =
+ name = "new_objc_provider",
+ doc = "Creates a new ObjcProvider instance.",
+ parameters = {
@Param(
- name = "kwargs",
- type = SkylarkDict.class,
- defaultValue = "{}",
- doc = "Dictionary of arguments."
- ),
- useEnvironment = true
- )
+ name = "uses_swift",
+ type = Boolean.class,
+ defaultValue = "False",
+ named = true,
+ positional = false,
+ doc = "Whether this provider should enable Swift support.")
+ },
+ extraKeywords =
+ @Param(
+ name = "kwargs",
+ type = SkylarkDict.class,
+ defaultValue = "{}",
+ doc = "Dictionary of arguments."),
+ useEnvironment = true)
// This method is registered statically for skylark, and never called directly.
public ObjcProviderApi<?> newObjcProvider(
- Boolean usesSwift,
- SkylarkDict<?, ?> kwargs,
- Environment environment);
+ Boolean usesSwift, SkylarkDict<?, ?> kwargs, Environment environment) throws EvalException;
@SkylarkCallable(
name = "new_dynamic_framework_provider",
@@ -403,17 +398,15 @@
throws EvalException, InterruptedException;
@SkylarkCallable(
- name = "dotted_version",
- doc = "Creates a new <a href=\"DottedVersion.html\">DottedVersion</a> instance.",
- parameters = {
- @Param(
- name = "version",
- type = String.class,
- doc = "The string representation of the DottedVersion."
- )
- }
- )
- public DottedVersionApi<?> dottedVersion(String version);
+ name = "dotted_version",
+ doc = "Creates a new <a href=\"DottedVersion.html\">DottedVersion</a> instance.",
+ parameters = {
+ @Param(
+ name = "version",
+ type = String.class,
+ doc = "The string representation of the DottedVersion.")
+ })
+ public DottedVersionApi<?> dottedVersion(String version) throws EvalException;
@SkylarkCallable(
name = "objc_proto_aspect",
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java
index b322d23..3ae488f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodDescriptor.java
@@ -130,46 +130,54 @@
public Object call(Object obj, Object[] args, Location loc, Environment env)
throws EvalException, InterruptedException {
Preconditions.checkNotNull(obj);
+ Object result;
try {
- Object result = method.invoke(obj, args);
- if (method.getReturnType().equals(Void.TYPE)) {
- return Runtime.NONE;
- }
- if (result == null) {
- if (isAllowReturnNones()) {
- return Runtime.NONE;
- } else {
- throw new EvalException(
- loc,
- "method invocation returned None, please file a bug report: "
- + getName()
- + Printer.printAbbreviatedList(ImmutableList.copyOf(args), "(", ", ", ")", null));
- }
- }
- // TODO(bazel-team): get rid of this, by having everyone use the Skylark data structures
- result = SkylarkType.convertToSkylark(result, method, env);
- if (result != null && !EvalUtils.isSkylarkAcceptable(result.getClass())) {
- throw new EvalException(
- loc,
- Printer.format(
- "method '%s' returns an object of invalid type %r", getName(), result.getClass()));
- }
- return result;
+ result = method.invoke(obj, args);
} catch (IllegalAccessException e) {
// TODO(bazel-team): Print a nice error message. Maybe the method exists
// and an argument is missing or has the wrong type.
throw new EvalException(loc, "Method invocation failed: " + e);
- } catch (InvocationTargetException e) {
- if (e.getCause() instanceof FuncallExpression.FuncallException) {
- throw new EvalException(loc, e.getCause().getMessage());
- } else if (e.getCause() != null) {
- Throwables.throwIfInstanceOf(e.getCause(), InterruptedException.class);
- throw new EvalException.EvalExceptionWithJavaCause(loc, e.getCause());
+ } catch (InvocationTargetException x) {
+ Throwable e = x.getCause();
+ if (e == null) {
+ // This is unlikely to happen.
+ throw new IllegalStateException(
+ String.format(
+ "causeless InvocationTargetException when calling %s with arguments %s at %s",
+ obj, Arrays.toString(args), loc),
+ x);
+ }
+ Throwables.propagateIfPossible(e, InterruptedException.class);
+ if (e instanceof FuncallExpression.FuncallException) {
+ throw new EvalException(loc, e.getMessage());
+ }
+ if (e instanceof EvalException) {
+ throw ((EvalException) e).ensureLocation(loc);
+ }
+ throw new EvalException.EvalExceptionWithJavaCause(loc, e);
+ }
+ if (method.getReturnType().equals(Void.TYPE)) {
+ return Runtime.NONE;
+ }
+ if (result == null) {
+ if (isAllowReturnNones()) {
+ return Runtime.NONE;
} else {
- // This is unlikely to happen
- throw new EvalException(loc, "method invocation failed: " + e);
+ throw new IllegalStateException(
+ "method invocation returned None "
+ + getName()
+ + Printer.printAbbreviatedList(ImmutableList.copyOf(args), "(", ", ", ")", null));
}
}
+ // TODO(bazel-team): get rid of this, by having everyone use the Skylark data structures
+ result = SkylarkType.convertToSkylark(result, method, env);
+ if (result != null && !EvalUtils.isSkylarkAcceptable(result.getClass())) {
+ throw new EvalException(
+ loc,
+ Printer.format(
+ "method '%s' returns an object of invalid type %r", getName(), result.getClass()));
+ }
+ return result;
}
/** @see SkylarkCallable#name() */
diff --git a/src/test/java/com/google/devtools/build/lib/rules/apple/DottedVersionTest.java b/src/test/java/com/google/devtools/build/lib/rules/apple/DottedVersionTest.java
index 311de1e..a62d83d 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/apple/DottedVersionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/apple/DottedVersionTest.java
@@ -124,28 +124,33 @@
@Test
public void testIllegalVersion_noLeadingInteger() throws Exception {
- IllegalArgumentException expected =
- assertThrows(IllegalArgumentException.class, () -> DottedVersion.fromString("a"));
+ Throwable expected =
+ assertThrows(
+ DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("a"));
assertThat(expected).hasMessageThat().contains("a");
}
@Test
public void testIllegalVersion_empty() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> DottedVersion.fromString(""));
+ assertThrows(
+ DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString(""));
}
@Test
public void testIllegalVersion_punctuation() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> DottedVersion.fromString("2:3"));
+ assertThrows(
+ DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("2:3"));
}
@Test
public void testIllegalVersion_emptyComponent() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> DottedVersion.fromString("1..3"));
+ assertThrows(
+ DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("1..3"));
}
@Test
public void testIllegalVersion_negativeComponent() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> DottedVersion.fromString("1.-1"));
+ assertThrows(
+ DottedVersion.InvalidDottedVersionException.class, () -> DottedVersion.fromString("1.-1"));
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java
index b4e96a2..b612509 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java
@@ -112,7 +112,7 @@
}
@Test
- public void directFieldsAddFromSkylark() {
+ public void directFieldsAddFromSkylark() throws Exception {
ImmutableList<Artifact> artifacts =
ImmutableList.of(createArtifact("/foo"), createArtifact("/bar"));
SkylarkNestedSet set =
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java
index 33f4148..133c6ae 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java
@@ -85,8 +85,7 @@
protected static final ImmutableList<String> FASTBUILD_COPTS = ImmutableList.of("-O0", "-DDEBUG");
protected static final DottedVersion DEFAULT_IOS_SDK_VERSION =
- DottedVersion.fromString(AppleCommandLineOptions.DEFAULT_IOS_SDK_VERSION);
-
+ DottedVersion.fromStringUnchecked(AppleCommandLineOptions.DEFAULT_IOS_SDK_VERSION);
/**
* Returns the configuration obtained by applying the apple crosstool configuration transtion to
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
index 2e8fdc7..bbcde18 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -511,6 +511,11 @@
return "with_args_and_kwargs(" + foo + ", " + argsString + ", " + kwargsString + ")";
}
+ @SkylarkCallable(name = "raise_unchecked_exception", documented = false)
+ public void raiseUncheckedException() {
+ throw new InternalError("buggy code");
+ }
+
@Override
public String toString() {
return "<mock>";
@@ -1309,6 +1314,12 @@
}
@Test
+ public void testCallingMethodThatRaisesUncheckedException() throws Exception {
+ update("mock", new Mock());
+ assertThrows(InternalError.class, () -> eval("mock.raise_unchecked_exception()"));
+ }
+
+ @Test
public void testJavaFunctionWithExtraInterpreterParams() throws Exception {
new SkylarkTest()
.update("mock", new Mock())
@@ -1470,12 +1481,10 @@
@Test
public void testJavaFunctionReturnsNullFails() throws Exception {
- new SkylarkTest()
- .update("mock", new Mock())
- .testIfErrorContains(
- "method invocation returned None,"
- + " please file a bug report: nullfunc_failing(\"abc\", 1)",
- "mock.nullfunc_failing('abc', 1)");
+ update("mock", new Mock());
+ IllegalStateException e =
+ assertThrows(IllegalStateException.class, () -> eval("mock.nullfunc_failing('abc', 1)"));
+ assertThat(e).hasMessageThat().contains("method invocation returned None");
}
@Test
@@ -1947,6 +1956,7 @@
"nullfunc_failing",
"nullfunc_working",
"proxy_methods_object",
+ "raise_unchecked_exception",
"return_bad",
"string",
"string_list",