Merge "Use R8 error handling utilities in DexSplitter."
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index ab86367..1fcd70a 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FeatureClassMapping;
import com.android.tools.r8.utils.FeatureClassMapping.FeatureMappingException;
import com.android.tools.r8.utils.InternalOptions;
@@ -33,14 +34,14 @@
public class DexSplitterHelper {
public static void run(
- D8Command command,
- FeatureClassMapping featureClassMapping,
- String output,
- String proguardMap)
- throws IOException, CompilationException, ExecutionException {
+ D8Command command, FeatureClassMapping featureClassMapping, String output, String proguardMap)
+ throws CompilationFailedException {
ExecutorService executor = ThreadUtils.getExecutorService(ThreadUtils.NOT_SPECIFIED);
try {
- run(command, featureClassMapping, output, proguardMap, executor);
+ ExceptionUtils.withCompilationHandler(
+ command.getReporter(),
+ () -> run(command, featureClassMapping, output, proguardMap, executor),
+ CompilationException::getMessage);
} finally {
executor.shutdown();
}
@@ -52,7 +53,7 @@
String output,
String proguardMap,
ExecutorService executor)
- throws IOException, CompilationException, ExecutionException {
+ throws IOException, CompilationException {
InternalOptions options = command.getInternalOptions();
options.enableDesugaring = false;
options.enableMainDexListCheck = false;
diff --git a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
index b2fe1bc..f452cf1 100644
--- a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
+++ b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
@@ -4,23 +4,25 @@
package com.android.tools.r8.dexsplitter;
-import com.android.tools.r8.CompilationException;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DexSplitterHelper;
-import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.utils.AbortException;
+import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
+import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FeatureClassMapping;
import com.android.tools.r8.utils.FeatureClassMapping.FeatureMappingException;
import com.android.tools.r8.utils.OptionsParsing;
import com.android.tools.r8.utils.OptionsParsing.ParseContext;
+import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
-import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutionException;
public class DexSplitter {
@@ -29,6 +31,37 @@
private static final boolean PRINT_ARGS = false;
+ public static class Reporter implements DiagnosticsHandler {
+
+ private final DiagnosticsHandler handler = new DefaultDiagnosticsHandler();
+ private boolean reportedErrors = false;
+
+ public RuntimeException fatal(Diagnostic error) {
+ error(error);
+ throw new AbortException();
+ }
+
+ public boolean hasReportedErrors() {
+ return reportedErrors;
+ }
+
+ @Override
+ public void error(Diagnostic error) {
+ handler.error(error);
+ reportedErrors = true;
+ }
+
+ @Override
+ public void warning(Diagnostic warning) {
+ handler.warning(warning);
+ }
+
+ @Override
+ public void info(Diagnostic info) {
+ handler.info(info);
+ }
+ }
+
public static class FeatureJar {
private String jar;
private String outputName;
@@ -62,6 +95,7 @@
}
public static class Options {
+ private final Reporter reporter = new Reporter();
private List<String> inputArchives = new ArrayList<>();
private List<FeatureJar> featureJars = new ArrayList<>();
private String baseOutputName = DEFAULT_BASE_NAME;
@@ -69,6 +103,10 @@
private String featureSplitMapping;
private String proguardMap;
+ public Reporter getReporter() {
+ return reporter;
+ }
+
public String getOutput() {
return output;
}
@@ -124,6 +162,11 @@
public ImmutableList<FeatureJar> getFeatureJars() {
return ImmutableList.copyOf(featureJars);
}
+
+ // Shorthand error messages.
+ public void error(String msg) {
+ reporter.error(new StringDiagnostic(msg));
+ }
}
/**
@@ -144,7 +187,7 @@
return new FeatureJar(argument);
}
- private static Options parseArguments(String[] args) throws IOException {
+ private static Options parseArguments(String[] args) {
Options options = new Options();
ParseContext context = new ParseContext(args);
while (context.head() != null) {
@@ -185,32 +228,35 @@
}
private static FeatureClassMapping createFeatureClassMapping(Options options)
- throws IOException, FeatureMappingException, ResourceException {
+ throws FeatureMappingException {
if (options.getFeatureSplitMapping() != null) {
- return FeatureClassMapping.fromSpecification(Paths.get(options.getFeatureSplitMapping()));
+ return FeatureClassMapping.fromSpecification(
+ Paths.get(options.getFeatureSplitMapping()), options.getReporter());
}
assert !options.getFeatureJars().isEmpty();
- return FeatureClassMapping.fromJarFiles(options.getFeatureJars(), options.getBaseOutputName());
+ return FeatureClassMapping.fromJarFiles(
+ options.getFeatureJars(), options.getBaseOutputName(), options.getReporter());
}
private static void run(String[] args)
- throws CompilationFailedException, IOException, CompilationException, ExecutionException,
- ResourceException, FeatureMappingException {
+ throws CompilationFailedException, FeatureMappingException {
Options options = parseArguments(args);
run(options);
}
public static void run(Options options)
- throws IOException, FeatureMappingException, ResourceException, CompilationException,
- ExecutionException, CompilationFailedException {
+ throws FeatureMappingException, CompilationFailedException {
if (options.getInputArchives().isEmpty()) {
- throw new RuntimeException("Need at least one --input");
+ options.error("Need at least one --input");
}
if (options.getFeatureSplitMapping() == null && options.getFeatureJars().isEmpty()) {
- throw new RuntimeException("You must supply a feature split mapping or feature jars");
+ options.error("You must supply a feature split mapping or feature jars");
}
if (options.getFeatureSplitMapping() != null && !options.getFeatureJars().isEmpty()) {
- throw new RuntimeException("You can't supply both a feature split mapping and feature jars");
+ options.error("You can't supply both a feature split mapping and feature jars");
+ }
+ if (options.getReporter().hasReportedErrors()) {
+ throw new AbortException();
}
D8Command.Builder builder = D8Command.builder();
@@ -228,20 +274,19 @@
}
public static void main(String[] args) {
- try {
- if (PRINT_ARGS) {
- printArgs(args);
- }
- run(args);
- } catch (CompilationFailedException
- | IOException
- | CompilationException
- | ExecutionException
- | ResourceException
- | FeatureMappingException e) {
- System.err.println("Splitting failed: " + e.getMessage());
- System.exit(1);
+ if (PRINT_ARGS) {
+ printArgs(args);
}
+ ExceptionUtils.withMainProgramHandler(
+ () -> {
+ try {
+ run(args);
+ } catch (FeatureMappingException e) {
+ // TODO(ricow): Report feature mapping errors via the reporter.
+ System.err.println("Splitting failed: " + e.getMessage());
+ System.exit(1);
+ }
+ });
}
private static void printArgs(String[] args) {
diff --git a/src/main/java/com/android/tools/r8/utils/FeatureClassMapping.java b/src/main/java/com/android/tools/r8/utils/FeatureClassMapping.java
index 1c969f6..e8c6df9 100644
--- a/src/main/java/com/android/tools/r8/utils/FeatureClassMapping.java
+++ b/src/main/java/com/android/tools/r8/utils/FeatureClassMapping.java
@@ -4,7 +4,9 @@
package com.android.tools.r8.utils;
import com.android.tools.r8.ArchiveClassFileProvider;
+import com.android.tools.r8.dexsplitter.DexSplitter;
import com.android.tools.r8.dexsplitter.DexSplitter.FeatureJar;
+import com.android.tools.r8.origin.PathOrigin;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -51,11 +53,39 @@
static final String COMMENT = "#";
static final String SEPARATOR = ":";
+ private static class SpecificationOrigin extends PathOrigin {
- public static FeatureClassMapping fromSpecification(Path file)
- throws FeatureMappingException, IOException {
+ public SpecificationOrigin(Path path) {
+ super(path);
+ }
+
+ @Override
+ public String part() {
+ return "specification file '" + super.part() + "'";
+ }
+ }
+
+ private static class JarFileOrigin extends PathOrigin {
+
+ public JarFileOrigin(Path path) {
+ super(path);
+ }
+
+ @Override
+ public String part() {
+ return "jar file '" + super.part() + "'";
+ }
+ }
+
+ public static FeatureClassMapping fromSpecification(Path file, DexSplitter.Reporter reporter)
+ throws FeatureMappingException {
FeatureClassMapping mapping = new FeatureClassMapping();
- List<String> lines = FileUtils.readAllLines(file);
+ List<String> lines = null;
+ try {
+ lines = FileUtils.readAllLines(file);
+ } catch (IOException e) {
+ throw reporter.fatal(new ExceptionDiagnostic(e, new SpecificationOrigin(file)));
+ }
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
mapping.parseAndAdd(line, i);
@@ -63,15 +93,21 @@
return mapping;
}
- public static FeatureClassMapping fromJarFiles(List<FeatureJar> featureJars, String baseName)
- throws FeatureMappingException, IOException {
+ public static FeatureClassMapping fromJarFiles(
+ List<FeatureJar> featureJars, String baseName, DexSplitter.Reporter reporter)
+ throws FeatureMappingException {
FeatureClassMapping mapping = new FeatureClassMapping();
if (mapping.baseName != null) {
mapping.baseName = baseName;
}
for (FeatureJar featureJar : featureJars) {
Path jarPath = Paths.get(featureJar.getJar());
- ArchiveClassFileProvider provider = new ArchiveClassFileProvider(jarPath);
+ ArchiveClassFileProvider provider = null;
+ try {
+ provider = new ArchiveClassFileProvider(jarPath);
+ } catch (IOException e) {
+ throw reporter.fatal(new ExceptionDiagnostic(e, new JarFileOrigin(jarPath)));
+ }
for (String javaDescriptor : provider.getClassDescriptors()) {
String javaType = DescriptorUtils.descriptorToJavaType(javaDescriptor);
mapping.addMapping(javaType, featureJar.getOutputName());
@@ -94,7 +130,7 @@
}
}
- public String featureForClass(String clazz) throws FeatureMappingException {
+ public String featureForClass(String clazz) {
if (usesOnlyExactMappings) {
return parsedRules.getOrDefault(clazz, baseName);
} else {