Assert that the repackaging tree-fixer can always be applied.
Change-Id: I8f0abbb7f5f474c53506469e54d84a02c2fdea80
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 089c747..f2e9746 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -849,6 +849,7 @@
lens, appBuilder.build(), memberRebindingLens.getPrevious());
}
}
+ assert Repackaging.verifyIdentityRepackaging(appView);
// Add automatic main dex classes to an eventual manual list of classes.
if (!options.mainDexKeepRules.isEmpty()) {
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 8e0800b..603e994 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -90,7 +90,7 @@
// TODO(b/169115389): Remove
private Set<DexMethod> cfByteCodePassThrough = ImmutableSet.of();
- private Map<DexClass, DexValueString> sourceDebugExtensions = new IdentityHashMap<>();
+ private Map<DexType, DexValueString> sourceDebugExtensions = new IdentityHashMap<>();
// When input has been (partially) desugared these are the classes which has been library
// desugared. This information is populated in the IR converter.
@@ -251,11 +251,11 @@
}
public void setSourceDebugExtensionForType(DexClass clazz, DexValueString sourceDebugExtension) {
- this.sourceDebugExtensions.put(clazz, sourceDebugExtension);
+ sourceDebugExtensions.put(clazz.type, sourceDebugExtension);
}
public DexValueString getSourceDebugExtensionForType(DexClass clazz) {
- return this.sourceDebugExtensions.get(clazz);
+ return sourceDebugExtensions.get(clazz.type);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 0faef1b..1ace989 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -46,9 +46,6 @@
public static final DexProgramClass[] EMPTY_ARRAY = {};
- private static final DexEncodedArray SENTINEL_NOT_YET_COMPUTED =
- new DexEncodedArray(DexValue.EMPTY_ARRAY);
-
private final ProgramResource.Kind originKind;
private final Collection<DexProgramClass> synthesizedFrom;
private CfVersion initialClassFileVersion = null;
diff --git a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
index 79b2e1e..120c580 100644
--- a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
+++ b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
@@ -8,11 +8,13 @@
import static com.android.tools.r8.utils.DescriptorUtils.DESCRIPTOR_PACKAGE_SEPARATOR;
import static com.android.tools.r8.utils.DescriptorUtils.INNER_CLASS_SEPARATOR;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.DirectMappedDexApplication.Builder;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.ProgramPackage;
import com.android.tools.r8.graph.ProgramPackageCollection;
@@ -23,6 +25,7 @@
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@@ -63,6 +66,34 @@
return lens;
}
+ public static boolean verifyIdentityRepackaging(
+ AppView<? extends AppInfoWithClassHierarchy> appView) {
+ // Running the tree fixer with an identity mapping helps ensure that the fixup of of items is
+ // complete as the rewrite replaces all items regardless of repackaging.
+ Builder builder = appView.appInfo().app().asDirect().builder();
+ RepackagingTreeFixer treeFixer =
+ new RepackagingTreeFixer(builder, appView, Collections.emptyMap());
+ assert treeFixer.verifyRun();
+ if (appView.appInfo().hasLiveness()) {
+ appView
+ .withLiveness()
+ .setAppInfo(
+ appView
+ .withLiveness()
+ .appInfo()
+ .rebuildWithLiveness(
+ appView.getSyntheticItems().commit(builder.build()), Collections.emptySet()));
+ } else {
+ appView
+ .withClassHierarchy()
+ .setAppInfo(
+ appView
+ .appInfo()
+ .rebuildWithClassHierarchy(appView.getSyntheticItems().commit(builder.build())));
+ }
+ return true;
+ }
+
private RepackagingLens run(
DirectMappedDexApplication.Builder appBuilder, ExecutorService executorService)
throws ExecutionException {
@@ -80,7 +111,7 @@
if (mappings.isEmpty()) {
return null;
}
- return new RepackagingTreeFixer(appBuilder, appView, mappings).run();
+ return new RepackagingTreeFixer(appBuilder, appView, mappings).run(appView);
}
private void processPackagesInDesiredLocation(
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java
index 17d06a3..ca82712 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingTreeFixer.java
@@ -30,7 +30,7 @@
public class RepackagingTreeFixer {
private final DirectMappedDexApplication.Builder appBuilder;
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<?> appView;
private final DexItemFactory dexItemFactory;
private final RepackagingLens.Builder lensBuilder = new RepackagingLens.Builder();
private final Map<DexType, DexType> repackagedClasses;
@@ -41,7 +41,7 @@
public RepackagingTreeFixer(
DirectMappedDexApplication.Builder appBuilder,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
Map<DexType, DexType> repackagedClasses) {
this.appBuilder = appBuilder;
this.appView = appView;
@@ -49,15 +49,24 @@
this.repackagedClasses = repackagedClasses;
}
- public RepackagingLens run() {
+ public RepackagingLens run(AppView<AppInfoWithLiveness> appView) {
// Globally substitute repackaged class types.
+ fixupApplication();
+ RepackagingLens lens = lensBuilder.build(appView);
+ new AnnotationFixer(lens).run(newProgramClasses.values());
+ return lens;
+ }
+
+ public boolean verifyRun() {
+ fixupApplication();
+ return true;
+ }
+
+ private void fixupApplication() {
for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) {
newProgramClasses.computeIfAbsent(clazz.getType(), ignore -> fixupClass(clazz));
}
appBuilder.replaceProgramClasses(new ArrayList<>(newProgramClasses.values()));
- RepackagingLens lens = lensBuilder.build(appView);
- new AnnotationFixer(lens).run(newProgramClasses.values());
- return lens;
}
private DexProgramClass fixupClass(DexProgramClass clazz) {
@@ -93,6 +102,17 @@
fixupMethods(
clazz.getMethodCollection().virtualMethods(),
clazz.getMethodCollection().numberOfVirtualMethods()));
+ // Transfer properties that are not passed to the constructor.
+ if (clazz.hasClassFileVersion()) {
+ newClass.setInitialClassFileVersion(clazz.getInitialClassFileVersion());
+ }
+ if (clazz.isDeprecated()) {
+ newClass.setDeprecated();
+ }
+ if (clazz.getKotlinInfo() != null) {
+ newClass.setKotlinInfo(clazz.getKotlinInfo());
+ }
+ // If the class type changed, record the move in the lens.
if (newClass.getType() != clazz.getType()) {
lensBuilder.recordMove(clazz.getType(), newClass.getType());
}
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
index 0eac295..563ba1c 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
@@ -8,7 +8,9 @@
import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.ClassFileConsumer.ForwardingConsumer;
import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -116,6 +118,28 @@
}
}
+ @Test
+ public void testR8() throws Exception {
+ R8FullTestBuilder builder =
+ testForR8(parameters.getBackend())
+ .addProgramClasses(TestClass.class)
+ .addKeepClassAndMembersRules(TestClass.class)
+ .addKeepAllAttributes()
+ .setMinApi(parameters.getApiLevel());
+ if (parameters.isCfRuntime()) {
+ builder.setProgramConsumer(
+ new ForwardingConsumer(null) {
+ @Override
+ public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) {
+ checkDeprecatedAttributes(data.getBuffer());
+ }
+ });
+ }
+ builder
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello, world!");
+ }
+
@Deprecated
public static class TestClass {
@Deprecated public Object object = new Object();