Desugar R8 part in R8 partial before trace references
The introduction of the desugar step breaks PartialShrinkingPreviewApiTest, since this test does not expect a CF-to-CF desugaring marker. This CL therefore also ensures that a single "R8Partial" marker is inserted when using R8Partial.
Fixes: b/388452773
Fixes: b/388763735
Fixes: b/389577597
Change-Id: Ifd42a258208028fe1484a6be5f96bd98e411480c
diff --git a/src/main/java/com/android/tools/r8/R8Partial.java b/src/main/java/com/android/tools/r8/R8Partial.java
index 1a21bec..c5a573f 100644
--- a/src/main/java/com/android/tools/r8/R8Partial.java
+++ b/src/main/java/com/android/tools/r8/R8Partial.java
@@ -17,9 +17,12 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.partial.R8PartialD8DexResult;
import com.android.tools.r8.partial.R8PartialDataResourceConsumer;
+import com.android.tools.r8.partial.R8PartialDesugarResult;
import com.android.tools.r8.partial.R8PartialInput;
import com.android.tools.r8.partial.R8PartialInputToDumpFlags;
import com.android.tools.r8.partial.R8PartialR8Result;
+import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration.R8PartialD8SubCompilationConfiguration;
+import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration.R8PartialR8SubCompilationConfiguration;
import com.android.tools.r8.partial.R8PartialTraceReferencesResult;
import com.android.tools.r8.partial.R8PartialTraceResourcesResult;
import com.android.tools.r8.partial.ResourceTracingCallback;
@@ -27,7 +30,6 @@
import com.android.tools.r8.tracereferences.TraceReferencesBridge;
import com.android.tools.r8.tracereferences.TraceReferencesCommand;
import com.android.tools.r8.tracereferences.TraceReferencesKeepRules;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidAppConsumers;
import com.android.tools.r8.utils.ExceptionDiagnostic;
@@ -39,6 +41,7 @@
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.io.ByteStreams;
+import it.unimi.dsi.fastutil.ints.IntSets;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashSet;
@@ -87,10 +90,13 @@
R8PartialInput input = runProcessInputStep(app, timing);
R8PartialD8DexResult d8DexResult = runD8DexStep(input, executor);
- R8PartialTraceResourcesResult resourcesTraceResult = runTraceResourcesStep(d8DexResult);
- R8PartialTraceReferencesResult traceReferencesResult = runTraceReferencesStep(input);
+ R8PartialTraceResourcesResult traceResourcesResult = runTraceResourcesStep(d8DexResult);
+ R8PartialDesugarResult desugarResult = runDesugarStep(input, executor);
+ R8PartialTraceReferencesResult traceReferencesResult =
+ runTraceReferencesStep(input, desugarResult);
R8PartialR8Result r8Result =
- runR8PartialStep(input, traceReferencesResult, resourcesTraceResult, executor);
+ runR8PartialStep(
+ input, desugarResult, traceReferencesResult, traceResourcesResult, executor);
runD8MergeStep(input, d8DexResult, r8Result, executor);
// Feed the data resource output by R8 to the output consumer. Keeping this at the end after the
@@ -101,6 +107,9 @@
private R8PartialTraceResourcesResult runTraceResourcesStep(R8PartialD8DexResult d8DexResult)
throws IOException {
+ if (options.androidResourceProvider == null) {
+ return new R8PartialTraceResourcesResult(IntSets.EMPTY_SET);
+ }
// TODO(b/390135529): Consider tracing these in the enqueuer of R8.
ResourceTracingCallback resourceTracingCallback = new ResourceTracingCallback();
AndroidApp app = AndroidApp.builder().addProgramFile(d8DexResult.getOutputPath()).build();
@@ -174,6 +183,7 @@
private R8PartialD8DexResult runD8DexStep(R8PartialInput input, ExecutorService executor)
throws IOException {
// Compile D8 input with D8.
+ // TODO(b/389575762): Consume the DexProgramClasses directly instead of writing to a zip.
Path d8Output = resolveTmp("d8-output.zip");
D8Command.Builder d8Builder =
D8Command.builder(options.reporter)
@@ -191,8 +201,7 @@
}
InternalOptions d8Options = d8Command.getInternalOptions();
options.partialCompilationConfiguration.d8DexOptionsConsumer.accept(d8Options);
- assert d8Options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
- : "Default interface methods not yet supported";
+ d8Options.partialSubCompilationConfiguration = new R8PartialD8SubCompilationConfiguration();
D8.runInternal(d8App, d8Options, executor);
if (d8OutputAppConsumer != null) {
d8OutputAppConsumer.accept(d8OutputAppSink.build());
@@ -200,7 +209,32 @@
return new R8PartialD8DexResult(d8Output);
}
- private R8PartialTraceReferencesResult runTraceReferencesStep(R8PartialInput input)
+ private R8PartialDesugarResult runDesugarStep(R8PartialInput input, ExecutorService executor)
+ throws IOException {
+ // TODO(b/389575762): Consume the DexProgramClasses instead of writing to a zip.
+ // TODO(b/389039057): This will desugar the entire R8 part. For build speed, look into if some
+ // desugarings can be postponed to the R8 compilation, since we do not desugar dead code in R8.
+ // As a simple example, it should be safe to postpone backporting to the R8 compilation.
+ // TODO(b/389039057): This runs a full D8 compilation. For build speed, consider if the various
+ // passes in D8 can be disabled when the `partialSubCompilationConfiguration` is set.
+ Path desugarOutput = resolveTmp("desugar-output.zip");
+ D8Command.Builder d8Builder =
+ D8Command.builder(options.reporter).setOutput(desugarOutput, OutputMode.ClassFile);
+ // TODO(b/390327883): This should enable intermediate mode.
+ input.configureDesugar(d8Builder);
+ d8Builder.validate();
+ D8Command d8Command = d8Builder.makeCommand();
+ AndroidApp d8App = d8Command.getInputApp();
+ InternalOptions d8Options = d8Command.getInternalOptions();
+ options.partialCompilationConfiguration.d8DesugarOptionsConsumer.accept(d8Options);
+ d8Options.partialSubCompilationConfiguration = new R8PartialD8SubCompilationConfiguration();
+ D8.runInternal(d8App, d8Options, executor);
+ return new R8PartialDesugarResult(desugarOutput);
+ }
+
+ // TODO(b/389031823): Parallelize trace references.
+ private R8PartialTraceReferencesResult runTraceReferencesStep(
+ R8PartialInput input, R8PartialDesugarResult desugarResult)
throws IOException, ResourceException {
// Run trace references to produce keep rules for the D8 compiled part.
// TODO(b/309743298): Do not emit keep rules into a file.
@@ -210,7 +244,9 @@
.setOutputConsumer(new FileConsumer(traceReferencesRules))
.build();
TraceReferencesCommand.Builder trBuilder =
- TraceReferencesCommand.builder().setConsumer(keepRulesConsumer);
+ TraceReferencesCommand.builder()
+ .addTargetFiles(desugarResult.getOutputPath())
+ .setConsumer(keepRulesConsumer);
input.configure(trBuilder);
TraceReferencesCommand tr = TraceReferencesBridge.makeCommand(trBuilder);
TraceReferencesBridge.runInternal(tr);
@@ -219,8 +255,9 @@
private R8PartialR8Result runR8PartialStep(
R8PartialInput input,
+ R8PartialDesugarResult desugarResult,
R8PartialTraceReferencesResult traceReferencesResult,
- R8PartialTraceResourcesResult resourcesTraceResult,
+ R8PartialTraceResourcesResult traceResourcesResult,
ExecutorService executor)
throws IOException {
// Compile R8 input with R8 using the keep rules from trace references.
@@ -238,8 +275,10 @@
return super.modifyDiagnosticsLevel(level, diagnostic);
}
};
+ // TODO(b/390389764): Disable desugaring.
R8Command.Builder r8Builder =
R8Command.builder(r8DiagnosticsHandler)
+ .addProgramFiles(desugarResult.getOutputPath())
.addProguardConfigurationFiles(traceReferencesResult.getOutputPath())
.enableLegacyFullModeForKeepRules(true)
.setProgramConsumer(
@@ -262,12 +301,13 @@
}
InternalOptions r8Options = r8Command.getInternalOptions();
options.partialCompilationConfiguration.r8OptionsConsumer.accept(r8Options);
+ r8Options.partialSubCompilationConfiguration =
+ new R8PartialR8SubCompilationConfiguration(traceResourcesResult.getResourceIdsToTrace());
r8Options.mapConsumer = options.mapConsumer;
if (options.androidResourceProvider != null) {
r8Options.androidResourceProvider = options.androidResourceProvider;
r8Options.androidResourceConsumer = options.androidResourceConsumer;
r8Options.resourceShrinkerConfiguration = options.resourceShrinkerConfiguration;
- r8Options.d8TracedResourceIDs = resourcesTraceResult.getResourceIdsToTrace();
}
R8.runInternal(r8App, r8Options, executor);
if (r8OutputAppConsumer != null) {
@@ -293,6 +333,7 @@
AndroidApp mergeApp = mergeCommand.getInputApp();
InternalOptions mergeOptions = mergeCommand.getInternalOptions();
options.partialCompilationConfiguration.d8MergeOptionsConsumer.accept(mergeOptions);
+ mergeOptions.partialSubCompilationConfiguration = new R8PartialD8SubCompilationConfiguration();
D8.runInternal(mergeApp, mergeOptions, executor);
}
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index e03f7fb..53712e7 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -468,26 +468,35 @@
allMarkers.addAll(previousMarkers);
}
DexItemFactory factory = appView.dexItemFactory();
- currentMarker.ifPresent(
- marker -> {
- if (willComputeProguardMap()) {
- lazyDexStrings.add(
- new LazyDexString() {
+ currentMarker
+ .filter(this::includeMarker)
+ .ifPresent(
+ marker -> {
+ if (willComputeProguardMap()) {
+ lazyDexStrings.add(
+ new LazyDexString() {
- @Override
- public DexString internalCompute() {
- marker.setPgMapId(delayedProguardMapId.get().getId());
- return marker.toDexString(factory);
- }
- });
- } else {
- allMarkers.add(marker);
- }
- });
+ @Override
+ public DexString internalCompute() {
+ marker.setPgMapId(delayedProguardMapId.get().getId());
+ return marker.toDexString(factory);
+ }
+ });
+ } else {
+ allMarkers.add(marker);
+ }
+ });
allMarkers.sort(Comparator.comparing(Marker::toString));
markerStrings = ListUtils.map(allMarkers, marker -> marker.toDexString(factory));
}
+ private boolean includeMarker(Marker marker) {
+ if (options.partialSubCompilationConfiguration != null) {
+ return options.partialSubCompilationConfiguration.includeMarker();
+ }
+ return true;
+ }
+
private OriginalSourceFiles computeSourceFileString(
Box<ProguardMapId> delayedProguardMapId, List<LazyDexString> lazyDexStrings) {
if (options.sourceFileProvider == null) {
diff --git a/src/main/java/com/android/tools/r8/dex/Marker.java b/src/main/java/com/android/tools/r8/dex/Marker.java
index f0bd037..f7414d9 100644
--- a/src/main/java/com/android/tools/r8/dex/Marker.java
+++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -34,6 +34,7 @@
GlobalSyntheticsGenerator,
L8,
R8,
+ R8Partial,
Relocator,
TraceReferences;
@@ -51,6 +52,7 @@
private static final String PREFIX = "~~";
private static final String D8_PREFIX = PREFIX + Tool.D8 + "{";
private static final String R8_PREFIX = PREFIX + Tool.R8 + "{";
+ private static final String R8_PARTIAL_PREFIX = PREFIX + Tool.R8Partial + "{";
private static final String L8_PREFIX = PREFIX + Tool.L8 + "{";
private static final String RELOCATOR_PREFIX = PREFIX + Tool.Relocator + "{";
@@ -287,6 +289,9 @@
if (str.startsWith(R8_PREFIX)) {
return internalParse(Tool.R8, str.substring(R8_PREFIX.length() - 1));
}
+ if (str.startsWith(R8_PARTIAL_PREFIX)) {
+ return internalParse(Tool.R8Partial, str.substring(R8_PARTIAL_PREFIX.length() - 1));
+ }
if (str.startsWith(L8_PREFIX)) {
return internalParse(Tool.L8, str.substring(L8_PREFIX.length() - 1));
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index 4fff3f5..02a8d72 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -62,7 +62,7 @@
// Use InterfaceDesugaringForTesting for public accesses in tests.
static final String COMPANION_CLASS_NAME_SUFFIX = "$-CC";
- static final String DEFAULT_METHOD_PREFIX = "$default$";
+ public static final String DEFAULT_METHOD_PREFIX = "$default$";
public static final String PRIVATE_METHOD_PREFIX = "$private$";
private final AppView<?> appView;
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 3abb2cc..d2c9f54 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -133,6 +133,9 @@
if (marker.isRelocator()) {
return false;
}
+ if (options.partialSubCompilationConfiguration != null) {
+ return options.partialSubCompilationConfiguration.includeMarker();
+ }
assert marker.isCfBackend() || marker.isDexBackend();
if (options.desugarSpecificOptions().noCfMarkerForDesugaredCode) {
return !marker.isCfBackend() || !marker.isDesugared();
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java b/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
new file mode 100644
index 0000000..6885303
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.partial;
+
+import java.nio.file.Path;
+
+public class R8PartialDesugarResult {
+
+ private final Path outputPath;
+
+ public R8PartialDesugarResult(Path outputPath) {
+ this.outputPath = outputPath;
+ }
+
+ public Path getOutputPath() {
+ return outputPath;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialInput.java b/src/main/java/com/android/tools/r8/partial/R8PartialInput.java
index 3f07cd0..0c0bd91 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialInput.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialInput.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.dump.CompilerDump;
import com.android.tools.r8.tracereferences.TraceReferencesCommand;
+import com.android.tools.r8.utils.ArchiveDataResourceProvider;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -32,6 +33,11 @@
commandBuilder.addProgramFiles(d8Program).addClasspathFiles(r8Program);
}
+ public void configureDesugar(D8Command.Builder commandBuilder) throws IOException {
+ configureBase(commandBuilder);
+ commandBuilder.addProgramFiles(r8Program).addClasspathFiles(d8Program);
+ }
+
public void configureMerge(D8Command.Builder commandBuilder) throws IOException {
configureBase(commandBuilder);
}
@@ -40,16 +46,13 @@
configureBase(commandBuilder);
configureDesugaredLibrary(commandBuilder);
commandBuilder
- .addProgramFiles(r8Program)
+ .addProgramResourceProvider(new ArchiveDataResourceProvider(r8Program))
.addClasspathFiles(d8Program)
.addProguardConfigurationFiles(dump.getProguardConfigFile());
}
public void configure(TraceReferencesCommand.Builder commandBuilder) throws IOException {
- commandBuilder
- .addLibraryFiles(dump.getLibraryArchive())
- .addSourceFiles(d8Program)
- .addTargetFiles(r8Program);
+ commandBuilder.addLibraryFiles(dump.getLibraryArchive()).addSourceFiles(d8Program);
}
private void configureBase(BaseCompilerCommand.Builder<?, ?> commandBuilder) throws IOException {
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java b/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java
index 1823257..865c21f 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java
@@ -33,6 +33,7 @@
}
private void supplyDataResourceConsumer(DataResourceConsumer consumer, Reporter reporter) {
+ if (consumer == null) return;
for (DataResource dataResource : outputDataResources) {
if (dataResource instanceof DataDirectoryResource) {
consumer.accept((DataDirectoryResource) dataResource, reporter);
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java b/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
new file mode 100644
index 0000000..ee13cc8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
@@ -0,0 +1,42 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.partial;
+
+import it.unimi.dsi.fastutil.ints.IntSet;
+import it.unimi.dsi.fastutil.ints.IntSets;
+
+public abstract class R8PartialSubCompilationConfiguration {
+
+ public IntSet getD8TracedResourceIds() {
+ return IntSets.EMPTY_SET;
+ }
+
+ public boolean includeMarker() {
+ return false;
+ }
+
+ // Currently shared by all D8 compilations in R8 partial (i.e., dexing, desugaring, merging).
+ public static class R8PartialD8SubCompilationConfiguration
+ extends R8PartialSubCompilationConfiguration {}
+
+ public static class R8PartialR8SubCompilationConfiguration
+ extends R8PartialSubCompilationConfiguration {
+
+ public final IntSet d8TracedResourceIds;
+
+ public R8PartialR8SubCompilationConfiguration(IntSet d8TracedResourceIds) {
+ this.d8TracedResourceIds = d8TracedResourceIds;
+ }
+
+ @Override
+ public IntSet getD8TracedResourceIds() {
+ return d8TracedResourceIds;
+ }
+
+ @Override
+ public boolean includeMarker() {
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 6348333..61596b5 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3973,8 +3973,11 @@
if (options.isOptimizedResourceShrinking()) {
timing.begin("Trace AndroidManifest.xml files");
appView.getResourceShrinkerState().traceKeepXmlAndManifest();
- for (int d8TracedResourceID : options.d8TracedResourceIDs) {
- appView.getResourceShrinkerState().trace(d8TracedResourceID, "Non shrunken dex code");
+ if (options.partialSubCompilationConfiguration != null) {
+ for (int d8TracedResourceId :
+ options.partialSubCompilationConfiguration.getD8TracedResourceIds()) {
+ appView.getResourceShrinkerState().trace(d8TracedResourceId, "Non shrunken dex code");
+ }
}
timing.end();
}
diff --git a/src/main/java/com/android/tools/r8/utils/ArchiveDataResourceProvider.java b/src/main/java/com/android/tools/r8/utils/ArchiveDataResourceProvider.java
new file mode 100644
index 0000000..b93663e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/ArchiveDataResourceProvider.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils;
+
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.shaking.FilteredClassPath;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+
+public class ArchiveDataResourceProvider extends ArchiveResourceProvider {
+
+ public ArchiveDataResourceProvider(Path archive) {
+ super(FilteredClassPath.unfiltered(archive), false);
+ }
+
+ @Override
+ public Collection<ProgramResource> getProgramResources() throws ResourceException {
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index b2044f1..09c90d1 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -88,6 +88,7 @@
import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemovalOptions;
import com.android.tools.r8.optimize.singlecaller.SingleCallerInlinerOptions;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.profile.art.ArtProfileOptions;
import com.android.tools.r8.profile.startup.StartupOptions;
@@ -116,8 +117,6 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
-import it.unimi.dsi.fastutil.ints.IntSet;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -199,7 +198,6 @@
public AndroidResourceProvider androidResourceProvider = null;
public AndroidResourceConsumer androidResourceConsumer = null;
public List<String> androidResourceProguardMapStrings = null;
- public IntSet d8TracedResourceIDs = new IntOpenHashSet();
public ResourceShrinkerConfiguration resourceShrinkerConfiguration =
ResourceShrinkerConfiguration.DEFAULT_CONFIGURATION;
@@ -555,11 +553,18 @@
}
public Marker getMarker() {
- assert tool != null;
if (hasMarker) {
return marker;
}
- return createMarker(tool);
+ return createMarker(getMarkerTool());
+ }
+
+ public Tool getMarkerTool() {
+ assert tool != null;
+ if (partialSubCompilationConfiguration != null && tool == Tool.R8) {
+ return Tool.R8Partial;
+ }
+ return tool;
}
// Compute the marker to be placed in the main dex file.
@@ -1024,6 +1029,7 @@
R8PartialCompilationConfiguration.fromIncludeExcludePatterns(
System.getProperty("com.android.tools.r8.experimentalPartialShrinkingIncludePatterns"),
System.getProperty("com.android.tools.r8.experimentalPartialShrinkingExcludePatterns"));
+ public R8PartialSubCompilationConfiguration partialSubCompilationConfiguration = null;
public final TestingOptions testing = new TestingOptions();
public List<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
diff --git a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
index 4adb654..5156353 100644
--- a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
+++ b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
@@ -30,6 +30,7 @@
public Consumer<AndroidApp> d8OutputAppConsumer;
public Consumer<InternalOptions> d8DexOptionsConsumer = ConsumerUtils.emptyConsumer();
+ public Consumer<InternalOptions> d8DesugarOptionsConsumer = ConsumerUtils.emptyConsumer();
public Consumer<InternalOptions> d8MergeOptionsConsumer = ConsumerUtils.emptyConsumer();
public Consumer<InternalOptions> r8OptionsConsumer = ConsumerUtils.emptyConsumer();
diff --git a/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java b/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
index bfe2cd6..0c74460 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8PartialTestBuilder;
+import com.android.tools.r8.R8PartialTestCompileResult;
import com.android.tools.r8.R8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestBase.Backend;
@@ -32,7 +33,6 @@
import com.android.tools.r8.keepanno.annotations.KeepEdge;
import com.android.tools.r8.keepanno.annotations.KeepItemKind;
import com.android.tools.r8.keepanno.annotations.KeepTarget;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.lang.annotation.RetentionPolicy;
@@ -152,12 +152,18 @@
public BenchmarkConfig buildR8WithPartialShrinking(
ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
+ return buildR8WithPartialShrinking(configuration, ThrowableConsumer.empty());
+ }
+
+ public BenchmarkConfig buildR8WithPartialShrinking(
+ ThrowableConsumer<? super R8PartialTestBuilder> configuration,
+ ThrowableConsumer<? super R8PartialTestCompileResult> compileResultConsumer) {
verify();
return BenchmarkConfig.builder()
.setName(name)
.setTarget(BenchmarkTarget.R8)
.setSuite(BenchmarkSuite.OPENSOURCE_BENCHMARKS)
- .setMethod(runR8WithPartialShrinking(this, configuration))
+ .setMethod(runR8WithPartialShrinking(this, configuration, compileResultConsumer))
.setFromRevision(fromRevision)
.addDependency(dumpDependency)
.measureRunTime()
@@ -314,8 +320,9 @@
private static BenchmarkMethod runR8WithPartialShrinking(
AppDumpBenchmarkBuilder builder,
- ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
- return internalRunR8Partial(builder, configuration);
+ ThrowableConsumer<? super R8PartialTestBuilder> configuration,
+ ThrowableConsumer<? super R8PartialTestCompileResult> compileResultConsumer) {
+ return internalRunR8Partial(builder, configuration, compileResultConsumer);
}
private static BenchmarkMethod runR8WithResourceShrinking(
@@ -383,7 +390,8 @@
private static BenchmarkMethod internalRunR8Partial(
AppDumpBenchmarkBuilder builder,
- ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
+ ThrowableConsumer<? super R8PartialTestBuilder> configuration,
+ ThrowableConsumer<? super R8PartialTestCompileResult> compileResultConsumer) {
return environment ->
BenchmarkBase.runner(environment)
.setWarmupIterations(1)
@@ -406,8 +414,7 @@
.addProgramFiles(dump.getProgramArchive())
.addLibraryFiles(dump.getLibraryArchive())
.addKeepRuleFiles(dump.getProguardConfigFile())
- // TODO(b/388452773): Fix support for default interface methods.
- .setMinApi(Math.max(dumpProperties.getMinApi(), AndroidApiLevel.N.getLevel()))
+ .setMinApi(dumpProperties.getMinApi())
.setR8PartialConfiguration(
b -> {
if (builder.programPackages.isEmpty()) {
@@ -431,7 +438,8 @@
.benchmarkDexSegmentsCodeSize(results)
.benchmarkDex2OatCodeSize(
results,
- environment.getConfig().isDex2OatVerificationEnabled()));
+ environment.getConfig().isDex2OatVerificationEnabled())
+ .apply(compileResultConsumer));
});
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java b/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java
index 14b8f7e..931a36c 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java
@@ -3,12 +3,19 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks.appdumps;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8PartialTestBuilder;
+import com.android.tools.r8.R8PartialTestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.benchmarks.BenchmarkBase;
import com.android.tools.r8.benchmarks.BenchmarkConfig;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -75,7 +82,9 @@
.setName("JetCasterAppPartial")
.setDumpDependencyPath(dir.resolve("jetcaster"))
.setFromRevision(16457)
- .buildR8WithPartialShrinking(ComposeSamplesBenchmarks::configureJetCasterAppPartial),
+ .buildR8WithPartialShrinking(
+ ComposeSamplesBenchmarks::configureJetCasterAppPartial,
+ ComposeSamplesBenchmarks::inspectJetCasterAppPartial),
AppDumpBenchmarkBuilder.builder()
.setName("JetChatApp")
.setDumpDependencyPath(dir.resolve("jetchat"))
@@ -85,7 +94,9 @@
.setName("JetChatAppPartial")
.setDumpDependencyPath(dir.resolve("jetchat"))
.setFromRevision(16457)
- .buildR8WithPartialShrinking(ComposeSamplesBenchmarks::configureJetChatAppPartial),
+ .buildR8WithPartialShrinking(
+ ComposeSamplesBenchmarks::configureJetChatAppPartial,
+ ComposeSamplesBenchmarks::inspectJetChatAppPartial),
AppDumpBenchmarkBuilder.builder()
.setName("JetSnackApp")
.setDumpDependencyPath(dir.resolve("jetsnack"))
@@ -143,10 +154,47 @@
private static void configureJetCasterAppPartial(R8PartialTestBuilder testBuilder) {
testBuilder
- .allowDiagnosticInfoMessages()
+ .allowDiagnosticMessages()
.allowUnnecessaryDontWarnWildcards()
.allowUnusedDontWarnPatterns()
- .allowUnusedProguardConfigurationRules();
+ .allowUnusedProguardConfigurationRules()
+ .addR8PartialOptionsModification(
+ options -> options.getOpenClosedInterfacesOptions().disallowOpenInterfaces());
+ }
+
+ private static void inspectJetCasterAppPartial(R8PartialTestCompileResult compileResult) {
+ compileResult.inspectDiagnosticMessages(
+ diagnostics ->
+ diagnostics
+ .assertWarningsMatch(
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(
+ containsString("androidx.compose.animation.tooling.ComposeAnimation"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(containsString("androidx.paging.PositionalDataSource"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(
+ containsString("java.lang.instrument.ClassFileTransformer"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(
+ containsString("org.conscrypt.ConscryptHostnameVerifier"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(containsString("org.jaxen.DefaultNavigator"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(containsString("org.jaxen.NamespaceContext"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(containsString("org.jaxen.VariableContext"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(containsString("sun.misc.SignalHandler"))))
+ .assertNoErrors());
}
private static void configureJetChatApp(R8FullTestBuilder testBuilder) {
@@ -159,12 +207,31 @@
private static void configureJetChatAppPartial(R8PartialTestBuilder testBuilder) {
testBuilder
- .allowDiagnosticInfoMessages()
+ .allowDiagnosticMessages()
.allowUnnecessaryDontWarnWildcards()
.allowUnusedDontWarnPatterns()
.allowUnusedProguardConfigurationRules();
}
+ private static void inspectJetChatAppPartial(R8PartialTestCompileResult compileResult) {
+ compileResult.inspectDiagnosticMessages(
+ diagnostics ->
+ diagnostics
+ .assertWarningsMatch(
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(
+ containsString("androidx.compose.animation.tooling.ComposeAnimation"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(
+ containsString("java.lang.instrument.ClassFileTransformer"))),
+ allOf(
+ diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+ diagnosticMessage(containsString("sun.misc.SignalHandler"))))
+ .assertNoErrors());
+ }
+
@Ignore
@Test
@Override
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
index b6c55e9..791d1ee 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
@@ -8,13 +8,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.partial.pkg1.A1;
import com.android.tools.r8.partial.pkg1.A2;
import com.android.tools.r8.partial.pkg1.subpkg.B;
import com.android.tools.r8.partial.pkg2.C1;
import com.android.tools.r8.partial.pkg2.C2;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
@@ -38,12 +36,8 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24.
public static TestParametersCollection data() {
- return getTestParameters()
- .withDexRuntime(DexVm.Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
- .build();
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
}
private static final List<Class<?>> ALL_CLASSES =
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
index e55a8d5..c718f5c 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
@@ -10,8 +10,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.utils.AndroidApiLevel;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -25,12 +23,8 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24.
public static TestParametersCollection data() {
- return getTestParameters()
- .withDexRuntime(DexVm.Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
- .build();
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
}
@Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java
index be3c872..a350f1b 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java
@@ -9,8 +9,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -29,12 +27,8 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24.
public static TestParametersCollection data() {
- return getTestParameters()
- .withDexRuntimesStartingFromIncluding(DexVm.Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
- .build();
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
}
@Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java
index 1cd7ceb..d562f6a 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.io.InputStream;
@@ -34,11 +33,11 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24.
public static TestParametersCollection data() {
+ // This test uses StandardCharsets which was first introduced in API level 19.
return getTestParameters()
- .withDexRuntime(DexVm.Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
+ .withDexRuntimes()
+ .withApiLevelsStartingAtIncluding(AndroidApiLevel.K)
.build();
}
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
index 43ad334..c7dc4dc 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
@@ -19,7 +19,6 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.desugar.desugaredlibrary.jdk11.DesugaredLibraryJDK11Undesugarer;
import com.android.tools.r8.dump.CompilerDump;
import com.android.tools.r8.tracereferences.TraceReferences;
@@ -66,14 +65,8 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24 where default interface methods are supported instead fo using
- // dump.getBuildProperties().getMinApi(). Tivi has min API 23 and there are currently trace
- // references issues with CC classes for default interface methods.
public static TestParametersCollection data() {
- return getTestParameters()
- .withDexRuntime(DexVm.Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
- .build();
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
}
private void configureDesugaredLibrary(
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java
index e0140e0..e400faf 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java
@@ -9,9 +9,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -30,12 +28,8 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24.
public static TestParametersCollection data() {
- return getTestParameters()
- .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
- .build();
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
}
@Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationMarkerTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationMarkerTest.java
new file mode 100644
index 0000000..634b016
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationMarkerTest.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.partial;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.Marker.Tool;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PartialCompilationMarkerTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8Partial(parameters.getBackend())
+ .addR8IncludedClasses(Foo.class)
+ .addR8ExcludedClasses(Bar.class)
+ .addKeepClassAndMembersRules(Foo.class)
+ .setMinApi(parameters)
+ .compile()
+ .inspect(
+ inspector -> {
+ Collection<Marker> markers = inspector.getMarkers();
+ assertEquals(1, markers.size());
+
+ Marker marker = markers.iterator().next();
+ assertEquals(Tool.R8Partial, marker.getTool());
+ });
+ }
+
+ static class Foo {}
+
+ static class Bar {}
+}
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java
index 2d0f94b..943616f 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java
@@ -9,9 +9,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -30,12 +28,8 @@
public TestParameters parameters;
@Parameters(name = "{0}")
- // Test with min API level 24.
public static TestParametersCollection data() {
- return getTestParameters()
- .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
- .withApiLevel(AndroidApiLevel.N)
- .build();
+ return getTestParameters().withDexRuntimesAndAllApiLevels().build();
}
@Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java
index 9d07e01..cf98f60 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java
@@ -3,11 +3,19 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.partial;
-import static org.junit.Assume.assumeTrue;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.DEFAULT_METHOD_PREFIX;
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbstract;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -27,13 +35,41 @@
@Test
public void test() throws Exception {
- // TODO(b/388763735): Enable for all API levels.
- assumeTrue(parameters.canUseDefaultAndStaticInterfaceMethods());
testForR8Partial(parameters.getBackend())
.addR8IncludedClasses(I.class, J.class)
.addR8ExcludedClasses(Main.class, A.class)
.setMinApi(parameters)
.compile()
+ .inspect(
+ inspector -> {
+ if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
+ // Verify that the default interface method was kept.
+ ClassSubject jClassSubject = inspector.clazz(J.class);
+ assertThat(jClassSubject, isPresent());
+
+ MethodSubject jMethodSubject = jClassSubject.uniqueMethodWithOriginalName("m");
+ assertThat(jMethodSubject, isPresent());
+ assertThat(jMethodSubject, not(isAbstract()));
+ } else {
+ // Verify that a bridge was inserted in the D8 part that calls the companion class
+ // method in the R8 part.
+ ClassSubject jCompanionClassSubject =
+ inspector.clazz(SyntheticItemsTestUtils.syntheticCompanionClass(J.class));
+ assertThat(jCompanionClassSubject, isPresent());
+
+ MethodSubject jCompanionMethodSubject =
+ jCompanionClassSubject.uniqueMethodWithOriginalName(
+ DEFAULT_METHOD_PREFIX + "m");
+ assertThat(jCompanionMethodSubject, isPresent());
+
+ ClassSubject aClassSubject = inspector.clazz(A.class);
+ assertThat(aClassSubject, isPresent());
+
+ MethodSubject aMethodSubject = aClassSubject.uniqueMethodWithOriginalName("m");
+ assertThat(aMethodSubject, isPresent());
+ assertThat(aMethodSubject, invokesMethod(jCompanionMethodSubject));
+ }
+ })
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("Hello, world!");
}
diff --git a/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java b/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
index f5784c5..ed3093b 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
@@ -3,10 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.partial;
+import static com.android.tools.r8.MarkerMatcher.markerBackend;
+import static com.android.tools.r8.MarkerMatcher.markerCompilationMode;
import static com.android.tools.r8.MarkerMatcher.markerMinApi;
-import static com.android.tools.r8.MarkerMatcher.markerR8Mode;
+import static com.android.tools.r8.MarkerMatcher.markerTool;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.R8;
@@ -14,11 +18,14 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.compilerapi.CompilerApiTest;
import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.nio.file.Path;
+import java.util.Collection;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
@@ -44,12 +51,17 @@
private void runTest(ThrowingConsumer<ProgramConsumer, Exception> test) throws Exception {
Path output = temp.newFolder().toPath().resolve("out.jar");
test.accept(new DexIndexedConsumer.ArchiveConsumer(output));
+
+ Collection<Marker> markers = new CodeInspector(output).getMarkers();
+ assertEquals(1, markers.size());
assertThat(
- new CodeInspector(output).getMarkers(),
+ markers,
CoreMatchers.everyItem(
CoreMatchers.allOf(
+ markerBackend(Backend.DEX),
+ markerCompilationMode(CompilationMode.RELEASE),
markerMinApi(AndroidApiLevel.getAndroidApiLevel(MIN_API_LEVEL)),
- markerR8Mode("full"))));
+ markerTool(Tool.R8Partial))));
}
public static class ApiTest extends CompilerApiTest {
diff --git a/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java b/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java
index b643e54..3cd499e 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java
@@ -19,7 +19,7 @@
return fn.applyWithRuntimeException(self());
}
- public <T extends Throwable> CR apply(ThrowableConsumer<CR> fn) {
+ public <T extends Throwable> CR apply(ThrowableConsumer<? super CR> fn) {
fn.acceptWithRuntimeException(self());
return self();
}
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
index ed19826..4ba36aa 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -176,6 +176,8 @@
DEFAULT_OPTIONS.andThen(
options -> {
options.partialCompilationConfiguration.d8DexOptionsConsumer = DEFAULT_D8_OPTIONS;
+ options.partialCompilationConfiguration.d8DesugarOptionsConsumer =
+ DEFAULT_D8_OPTIONS;
options.partialCompilationConfiguration.d8MergeOptionsConsumer = DEFAULT_D8_OPTIONS;
options.partialCompilationConfiguration.r8OptionsConsumer = DEFAULT_R8_OPTIONS;
});