diff options
author | Ian Zerny <zerny@google.com> | 2022-06-22 09:34:30 +0200 |
---|---|---|
committer | Ian Zerny <zerny@google.com> | 2022-08-16 10:00:48 +0000 |
commit | ad807a703c7720187d93e75af2fea8fdb344abea (patch) | |
tree | 915fae3124d3d0183d32d69c3821f0b83f026a6e | |
parent | d5c523b482d0dfb1a6fd15099ff507af02cc9f5d (diff) | |
download | base-ad807a703c7720187d93e75af2fea8fdb344abea.tar.gz |
Use D8 unsupported features diagnostics API.
Bug: b/154778581
Test: DexDisabledIssueCheckerTest DexDisabledIssueCheckerIntegrationTest
Change-Id: Ib9a8d31fdcf5feaba9c941f1c8775b790674c32c
-rw-r--r-- | build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java | 89 | ||||
-rw-r--r-- | build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java | 6 |
2 files changed, 75 insertions, 20 deletions
diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java b/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java index 51c0aadec0..1aa65b4fb6 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java +++ b/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java @@ -26,17 +26,22 @@ import com.android.tools.r8.D8Command; import com.android.tools.r8.Diagnostic; import com.android.tools.r8.OutputMode; import com.android.tools.r8.StringConsumer.FileConsumer; +import com.android.tools.r8.errors.UnsupportedFeatureDiagnostic; import com.google.common.util.concurrent.MoreExecutors; import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; final class D8DexArchiveBuilder extends DexArchiveBuilder { private static final String INVOKE_CUSTOM = - "Invoke-customs are only supported starting with Android O"; + "Invoke-customs are only supported starting with Android O (--min-api 26)"; private static final String DEFAULT_INTERFACE_METHOD = "Default interface methods are only supported starting with Android N (--min-api 24)"; @@ -56,10 +61,10 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder { @NonNull Path output, @Nullable DependencyGraphUpdater<File> desugarGraphUpdater) throws DexArchiveBuilderException { - D8DiagnosticsHandler d8DiagnosticsHandler = new InterceptingDiagnosticsHandler(); + InterceptingDiagnosticsHandler diagnosticsHandler = new InterceptingDiagnosticsHandler(); try { - D8Command.Builder builder = D8Command.builder(d8DiagnosticsHandler); + D8Command.Builder builder = D8Command.builder(diagnosticsHandler); AtomicInteger entryCount = new AtomicInteger(); input.forEach( entry -> { @@ -114,7 +119,7 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder { D8.run(builder.build(), MoreExecutors.newDirectExecutorService()); } catch (Throwable e) { - throw getExceptionToRethrow(e, d8DiagnosticsHandler); + throw getExceptionToRethrow(e, diagnosticsHandler, dexParams.getWithDesugaring()); } } @@ -129,14 +134,52 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder { @NonNull private static DexArchiveBuilderException getExceptionToRethrow( - @NonNull Throwable t, D8DiagnosticsHandler d8DiagnosticsHandler) { + @NonNull Throwable t, + InterceptingDiagnosticsHandler diagnosticsHandler, + boolean isDesugaring) { StringBuilder msg = new StringBuilder(); msg.append("Error while dexing."); - for (String hint : d8DiagnosticsHandler.getPendingHints()) { + Set<String> unsupportedFeatures = diagnosticsHandler.getUnsupportedFeatures(); + if (!unsupportedFeatures.isEmpty()) { + // Get the largest required level needed to support the features. + int minSdkVersion = diagnosticsHandler.getRequiredSdkVersion(); + if (!isDesugaring) { + diagnosticsHandler.addHint(getEnableDesugaringHint(minSdkVersion)); + } else if (minSdkVersion != -1) { + diagnosticsHandler.addHint( + "Increase the minSdkVersion to " + minSdkVersion + " or above.\n"); + } + // Construct a new exception to replace the D8 thrown exception. + // This avoids the need to maintain pattern-match on D8 exceptions and + // instead base matching on the stable diagnostics API. + StringBuilder builder = new StringBuilder(); + if (unsupportedFeatures.contains("invoke-custom")) { + builder.append("Error: ").append(INVOKE_CUSTOM); + } else if (unsupportedFeatures.contains("default-interface-method")) { + builder.append("Error: ").append(DEFAULT_INTERFACE_METHOD); + } else if (unsupportedFeatures.contains("static-interface-method")) { + builder.append("Error: ").append(STATIC_INTERFACE_METHOD); + } else { + // If not one of the three above legacy cases, construct an error message with a + // line + // for each unsupported feature. These are not currently pattern-matched on, so + // generalizing the reporting of these can be changed at a later point. + List<String> sorted = new ArrayList<>(unsupportedFeatures); + sorted.sort(String::compareTo); + for (String featureDescriptor : sorted) { + builder.append("Error: UnsupportedFeature(") + .append(featureDescriptor) + .append(")\n"); + } + } + Throwable rt = new RuntimeException(builder.toString()); + rt.addSuppressed(t); + t = rt; + } + for (String hint : diagnosticsHandler.getPendingHints()) { msg.append(System.lineSeparator()); msg.append(hint); } - return new DexArchiveBuilderException(msg.toString(), t); } @@ -156,25 +199,33 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder { } private class InterceptingDiagnosticsHandler extends D8DiagnosticsHandler { + + private Set<String> unsupportedFeatureDescriptors = new HashSet<>(); + private int requiredSdkVersion = -1; + public InterceptingDiagnosticsHandler() { super(D8DexArchiveBuilder.this.dexParams.getMessageReceiver()); } - @Override - protected Message convertToMessage(Message.Kind kind, Diagnostic diagnostic) { - - if (diagnostic.getDiagnosticMessage().startsWith(INVOKE_CUSTOM)) { - addHint(getEnableDesugaringHint(26)); - } + public int getRequiredSdkVersion() { + return requiredSdkVersion; + } - if (diagnostic.getDiagnosticMessage().startsWith(DEFAULT_INTERFACE_METHOD)) { - addHint(getEnableDesugaringHint(24)); - } + public Set<String> getUnsupportedFeatures() { + return unsupportedFeatureDescriptors; + } - if (diagnostic.getDiagnosticMessage().startsWith(STATIC_INTERFACE_METHOD)) { - addHint(getEnableDesugaringHint(24)); + @Override + protected Message convertToMessage(Message.Kind kind, Diagnostic diagnostic) { + if (diagnostic instanceof UnsupportedFeatureDiagnostic) { + UnsupportedFeatureDiagnostic feature = (UnsupportedFeatureDiagnostic) diagnostic; + String featureDescriptor = feature.getFeatureDescriptor(); + int minSdkVersion = feature.getSupportedApiLevel(); + unsupportedFeatureDescriptors.add(featureDescriptor); + if (requiredSdkVersion < minSdkVersion) { + requiredSdkVersion = minSdkVersion; + } } - return super.convertToMessage(kind, diagnostic); } } diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java b/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java index bc24ba79b7..c270ab712f 100644 --- a/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java +++ b/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java @@ -107,9 +107,13 @@ public class D8DiagnosticsHandler implements DiagnosticsHandler { protected Message convertToMessage(Message.Kind kind, Diagnostic diagnostic) { String textMessage = diagnostic.getDiagnosticMessage(); - Origin origin = diagnostic.getOrigin(); Position positionInOrigin = diagnostic.getPosition(); + return convertToMessage(kind, textMessage, origin, positionInOrigin); + } + + protected Message convertToMessage( + Message.Kind kind, String textMessage, Origin origin, Position positionInOrigin) { SourceFilePosition position; if (origin instanceof PathOrigin) { File originFile = ((PathOrigin) origin).getPath().toFile(); |