Merge commit 'b093b67b098827ca76be39196de7af7122b1fb16' into dev-release
diff --git a/.gitignore b/.gitignore
index 0629bac..aa4c9ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -135,12 +135,16 @@
third_party/protobuf-lite/
third_party/r8
third_party/r8.tar.gz
+third_party/r8-releases/2.0.74
+third_party/r8-releases/2.0.74.tar.gz
third_party/r8mappings
third_party/r8mappings.tar.gz
third_party/remapper
third_party/remapper.tar.gz
third_party/retrace_benchmark
third_party/retrace_benchmark.tar.gz
+third_party/retrace_internal
+third_party/retrace_internal.tar.gz
third_party/rhino-1.7.10
third_party/rhino-1.7.10.tar.gz
third_party/rhino-android-1.1.1
diff --git a/build.gradle b/build.gradle
index 6050eda..4428f58 100644
--- a/build.gradle
+++ b/build.gradle
@@ -335,6 +335,7 @@
"proguard/proguard5.2.1",
"proguard/proguard6.0.1",
"r8",
+ "r8-releases/2.0.74",
"r8mappings",
"tachiyomi"
],
@@ -427,6 +428,7 @@
"proguardsettings",
"proto",
"protobuf-lite",
+ "retrace_internal",
"youtube/youtube.android_12.10",
"youtube/youtube.android_12.17",
"youtube/youtube.android_12.22",
@@ -1050,12 +1052,6 @@
destinationDir file('build/libs')
}
-task buildD8ApiUsageSample(type: Jar) {
- from sourceSets.apiUsageSample.output
- baseName 'd8_api_usage_sample'
- destinationDir file('tests')
-}
-
task buildR8ApiUsageSample(type: Jar) {
from sourceSets.apiUsageSample.output
baseName 'r8_api_usage_sample'
@@ -1063,7 +1059,6 @@
}
task buildApiSampleJars {
- dependsOn buildD8ApiUsageSample
dependsOn buildR8ApiUsageSample
}
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 87562ad..afa5f60 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -29,6 +29,7 @@
builder_mixins {
name: "internal"
dimensions: "internal:true"
+ dimensions: "cores:2"
}
builder_mixins {
diff --git a/src/library_desugar/desugar_jdk_libs.json b/src/library_desugar/desugar_jdk_libs.json
index 8c023aa..5bdc91e 100644
--- a/src/library_desugar/desugar_jdk_libs.json
+++ b/src/library_desugar/desugar_jdk_libs.json
@@ -1,10 +1,73 @@
{
- "configuration_format_version": 4,
+ "configuration_format_version": 3,
"group_id" : "com.tools.android",
"artifact_id" : "desugar_jdk_libs",
- "version": "0.12.0",
+ "version": "1.0.9",
"required_compilation_api_level": 26,
"synthesized_library_classes_package_prefix": "j$.",
+ "common_flags": [
+ {
+ "api_level_below_or_equal": 25,
+ "wrapper_conversion": [
+ "java.time.Clock"
+ ]
+ },
+ {
+ "api_level_below_or_equal": 23,
+ "wrapper_conversion": [
+ "java.util.PrimitiveIterator$OfDouble",
+ "java.util.PrimitiveIterator$OfInt",
+ "java.util.PrimitiveIterator$OfLong",
+ "java.util.Spliterator",
+ "java.util.Spliterator$OfDouble",
+ "java.util.Spliterator$OfInt",
+ "java.util.Spliterator$OfLong",
+ "java.util.Spliterator$OfPrimitive",
+ "java.util.function.BiConsumer",
+ "java.util.function.BiFunction",
+ "java.util.function.BiPredicate",
+ "java.util.function.BinaryOperator",
+ "java.util.function.Consumer",
+ "java.util.function.DoubleBinaryOperator",
+ "java.util.function.DoubleConsumer",
+ "java.util.function.DoubleFunction",
+ "java.util.function.DoublePredicate",
+ "java.util.function.DoubleToIntFunction",
+ "java.util.function.DoubleToLongFunction",
+ "java.util.function.DoubleUnaryOperator",
+ "java.util.function.Function",
+ "java.util.function.IntBinaryOperator",
+ "java.util.function.IntConsumer",
+ "java.util.function.IntFunction",
+ "java.util.function.IntPredicate",
+ "java.util.function.IntToDoubleFunction",
+ "java.util.function.IntToLongFunction",
+ "java.util.function.IntUnaryOperator",
+ "java.util.function.LongBinaryOperator",
+ "java.util.function.LongConsumer",
+ "java.util.function.LongFunction",
+ "java.util.function.LongPredicate",
+ "java.util.function.LongToDoubleFunction",
+ "java.util.function.LongToIntFunction",
+ "java.util.function.LongUnaryOperator",
+ "java.util.function.ObjDoubleConsumer",
+ "java.util.function.ObjIntConsumer",
+ "java.util.function.ObjLongConsumer",
+ "java.util.function.Predicate",
+ "java.util.function.Supplier",
+ "java.util.function.ToDoubleFunction",
+ "java.util.function.ToIntFunction",
+ "java.util.function.ToLongFunction",
+ "java.util.function.UnaryOperator",
+ "java.util.stream.BaseStream",
+ "java.util.stream.Collector",
+ "java.util.stream.DoubleStream",
+ "java.util.stream.IntStream",
+ "java.util.stream.LongStream",
+ "java.util.stream.Stream"
+ ]
+ }
+ ],
"library_flags": [
{
"api_level_below_or_equal": 25,
@@ -22,6 +85,14 @@
"retarget_lib_member": {
"java.util.Date#toInstant": "java.util.DesugarDate",
"java.util.GregorianCalendar#toZonedDateTime": "java.util.DesugarGregorianCalendar"
+ },
+ "custom_conversion": {
+ "java.time.ZonedDateTime": "java.time.TimeConversions",
+ "java.time.LocalDate": "java.time.TimeConversions",
+ "java.time.Duration": "java.time.TimeConversions",
+ "java.time.ZoneId": "java.time.TimeConversions",
+ "java.time.MonthDay": "java.time.TimeConversions",
+ "java.time.Instant": "java.time.TimeConversions"
}
},
{
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index 7d5b31e..dcf33f1 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -69,7 +69,7 @@
private final Set<DexMethod> parallelMethods = Sets.newIdentityHashSet();
- private GenerateLintFiles(String desugarConfigurationPath, String outputDirectory) {
+ public GenerateLintFiles(String desugarConfigurationPath, String outputDirectory) {
this.desugaredLibraryConfiguration =
readDesugaredLibraryConfiguration(desugarConfigurationPath);
this.outputDirectory =
@@ -356,20 +356,24 @@
apiLevel >= desugaredLibraryConfiguration.getRequiredCompilationApiLevel().getLevel();
apiLevel--) {
System.out.println("Generating lint files for compile API " + apiLevel);
- generateLintFiles(
- AndroidApiLevel.getAndroidApiLevel(apiLevel),
- minApiLevel -> minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B,
- (minApiLevel, method) -> {
- assert minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B;
- if (minApiLevel == AndroidApiLevel.L) {
- return true;
- }
- assert minApiLevel == AndroidApiLevel.B;
- return !parallelMethods.contains(method.method);
- });
+ run(apiLevel);
}
}
+ public void run(int apiLevel) throws Exception {
+ generateLintFiles(
+ AndroidApiLevel.getAndroidApiLevel(apiLevel),
+ minApiLevel -> minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B,
+ (minApiLevel, method) -> {
+ assert minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B;
+ if (minApiLevel == AndroidApiLevel.L) {
+ return true;
+ }
+ assert minApiLevel == AndroidApiLevel.B;
+ return !parallelMethods.contains(method.method);
+ });
+ }
+
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println("Usage: GenerateLineFiles <desuage configuration> <output directory>");
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index 4bef8cec..4b35d17 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.LazyLoadedDexApplication;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
import com.android.tools.r8.jar.CfApplicationWriter;
@@ -118,11 +119,13 @@
// on it.
options.enableLoadStoreOptimization = false;
- DexApplication app = new ApplicationReader(inputApp, options, timing).read(executor);
+ LazyLoadedDexApplication lazyApp =
+ new ApplicationReader(inputApp, options, timing).read(executor);
+
PrefixRewritingMapper rewritePrefix =
options.desugaredLibraryConfiguration.createPrefixRewritingMapper(options);
- app = new L8TreePruner(options).prune(app, rewritePrefix);
+ DexApplication app = new L8TreePruner(options).prune(lazyApp, rewritePrefix);
AppInfo appInfo = new AppInfo(app);
AppView<?> appView = AppView.createForL8(appInfo, options, rewritePrefix);
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 9b0f9de..e116676 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -290,7 +290,7 @@
if (isShrinking()) {
R8Command.Builder r8Builder =
- R8Command.builder(getReporter())
+ new CompatProguardCommandBuilder(true, getReporter())
.addProgramResourceProvider(desugaredLibrary)
.setSynthesizedClassesPrefix(
libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 8f6bcca..5998450 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -51,6 +51,7 @@
import com.android.tools.r8.ir.optimize.enums.EnumValueInfoMapCollector;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.jar.CfApplicationWriter;
+import com.android.tools.r8.kotlin.KotlinMetadataRewriter;
import com.android.tools.r8.kotlin.KotlinMetadataUtils;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.Minifier;
@@ -805,6 +806,10 @@
namingLens = NamingLens.getIdentityLens();
}
+ timing.begin("MinifyKotlinMetadata");
+ new KotlinMetadataRewriter(appView, namingLens).run(executorService);
+ timing.end();
+
timing.begin("Line number remapping");
// When line number optimization is turned off the identity mapping for line numbers is
// used. We still run the line number optimizer to collect line numbers and inline frame
diff --git a/src/main/java/com/android/tools/r8/code/CheckCast.java b/src/main/java/com/android/tools/r8/code/CheckCast.java
index 57151fa..f472800 100644
--- a/src/main/java/com/android/tools/r8/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/code/CheckCast.java
@@ -38,6 +38,11 @@
}
@Override
+ public CheckCast asCheckCast() {
+ return this;
+ }
+
+ @Override
public boolean isCheckCast() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/code/InstanceOf.java b/src/main/java/com/android/tools/r8/code/InstanceOf.java
index 11b2d5c..4550406 100644
--- a/src/main/java/com/android/tools/r8/code/InstanceOf.java
+++ b/src/main/java/com/android/tools/r8/code/InstanceOf.java
@@ -23,6 +23,16 @@
}
@Override
+ public InstanceOf asInstanceOf() {
+ return this;
+ }
+
+ @Override
+ public boolean isInstanceOf() {
+ return true;
+ }
+
+ @Override
public String getName() {
return NAME;
}
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index b6b1f9c..86abac6 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -127,10 +127,22 @@
this.offset = offset;
}
+ public CheckCast asCheckCast() {
+ return null;
+ }
+
public boolean isCheckCast() {
return false;
}
+ public InstanceOf asInstanceOf() {
+ return null;
+ }
+
+ public boolean isInstanceOf() {
+ return false;
+ }
+
public ConstString asConstString() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index ede2193..ca70ab0 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -74,11 +74,11 @@
this.inputApp = inputApp;
}
- public DexApplication read() throws IOException {
+ public LazyLoadedDexApplication read() throws IOException {
return read((StringResource) null);
}
- public DexApplication read(StringResource proguardMap) throws IOException {
+ public LazyLoadedDexApplication read(StringResource proguardMap) throws IOException {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
return read(proguardMap, executor);
@@ -87,20 +87,20 @@
}
}
- public final DexApplication read(ExecutorService executorService) throws IOException {
+ public final LazyLoadedDexApplication read(ExecutorService executorService) throws IOException {
return read(
null, executorService, ProgramClassCollection.defaultConflictResolver(options.reporter));
}
- public final DexApplication read(StringResource proguardMap, ExecutorService executorService)
- throws IOException {
+ public final LazyLoadedDexApplication read(
+ StringResource proguardMap, ExecutorService executorService) throws IOException {
return read(
proguardMap,
executorService,
ProgramClassCollection.defaultConflictResolver(options.reporter));
}
- public final DexApplication read(
+ public final LazyLoadedDexApplication read(
StringResource proguardMap,
ExecutorService executorService,
ProgramClassConflictResolver resolver)
diff --git a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
index f327f21..9eb7caa 100644
--- a/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
+++ b/src/main/java/com/android/tools/r8/dex/CodeToKeep.java
@@ -64,7 +64,14 @@
}
private boolean shouldKeep(DexType type) {
- return namingLens.prefixRewrittenType(type) != null || potentialTypesToKeep.contains(type);
+ return namingLens.prefixRewrittenType(type) != null
+ || potentialTypesToKeep.contains(type)
+ // TODO(b/158632510): This should prefix match on DexString.
+ || type.toDescriptorString()
+ .startsWith(
+ "L"
+ + options.desugaredLibraryConfiguration
+ .getSynthesizedLibraryClassesPackagePrefix());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
index ef1b81b..037d769 100644
--- a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
+++ b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
@@ -112,6 +112,10 @@
desugaredLibraryCodeToKeep.recordMethod(method);
} else if (insn.isConstClass()) {
desugaredLibraryCodeToKeep.recordClass(insn.asConstClass().getType());
+ } else if (insn.isInstanceOf()) {
+ desugaredLibraryCodeToKeep.recordClass(insn.asInstanceOf().getType());
+ } else if (insn.isCheckCast()) {
+ desugaredLibraryCodeToKeep.recordClass(insn.asCheckCast().getType());
}
insn.write(shortBuffer, mapping);
}
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 867f32d..0047bf8 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -519,6 +519,7 @@
for (TypeAddrPair pair : handler.pairs) {
dest.putUleb128(mapping.getOffsetFor(pair.type));
dest.putUleb128(pair.addr);
+ desugaredLibraryCodeToKeep.recordClass(pair.type);
}
if (hasCatchAll) {
dest.putUleb128(handler.catchAllAddr);
diff --git a/src/main/java/com/android/tools/r8/graph/AccessFlags.java b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
index a6a9471..a0a1b99 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
@@ -3,20 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static kotlinx.metadata.FlagsKt.flagsOf;
-
import com.android.tools.r8.dex.Constants;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
import java.util.List;
import java.util.function.BooleanSupplier;
-import kotlinx.metadata.Flag;
/** Access flags common to classes, methods and fields. */
public abstract class AccessFlags<T extends AccessFlags<T>> {
- protected Flag[] EMPTY_FLAG = {};
-
protected static final int BASE_FLAGS
= Constants.ACC_PUBLIC
| Constants.ACC_PRIVATE
@@ -71,26 +65,6 @@
public abstract int getAsDexAccessFlags();
- public int getAsKotlinFlags() {
- List<Flag> flags = new ArrayList<>();
- if (isPrivate()) {
- flags.add(Flag.IS_PRIVATE);
- }
- if (isProtected()) {
- flags.add(Flag.IS_PROTECTED);
- }
- if (isPublic()) {
- flags.add(Flag.IS_PUBLIC);
- }
- if (isFinal()) {
- flags.add(Flag.IS_FINAL);
- }
- if (isOpen()) {
- flags.add(Flag.IS_OPEN);
- }
- return flagsOf(flags.toArray(EMPTY_FLAG));
- }
-
public final int getOriginalAccessFlags() {
return originalFlags;
}
diff --git a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
index e33792c..4dcc108 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
@@ -3,14 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static kotlinx.metadata.FlagsKt.flagsOf;
-
import com.android.tools.r8.dex.Constants;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
import java.util.List;
import java.util.function.BooleanSupplier;
-import kotlinx.metadata.Flag;
public class ClassAccessFlags extends AccessFlags<ClassAccessFlags> {
@@ -102,28 +98,6 @@
return flags;
}
- @Override
- public int getAsKotlinFlags() {
- int flag = super.getAsKotlinFlags();
- List<Flag> flags = new ArrayList<>();
- if (isAbstract()) {
- flags.add(Flag.IS_ABSTRACT);
- }
- if (isClass()) {
- flags.add(Flag.Class.IS_CLASS);
- }
- if (isInterface()) {
- flags.add(Flag.Class.IS_INTERFACE);
- }
- if (isAnnotation()) {
- flags.add(Flag.Class.IS_ANNOTATION_CLASS);
- }
- if (isEnum()) {
- flags.add(Flag.Class.IS_ENUM_CLASS);
- }
- return flag | flagsOf(flags.toArray(EMPTY_FLAG));
- }
-
/**
* Checks whether the constraints from
* https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1 are met.
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 74a31bf..5cbe06a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -1312,7 +1312,7 @@
accessFlags = from.accessFlags.copy();
annotations = from.annotations();
code = from.code;
- compilationState = from.compilationState;
+ compilationState = CompilationState.NOT_PROCESSED;
optimizationInfo = from.optimizationInfo.mutableCopy();
kotlinMemberInfo = from.kotlinMemberInfo;
classFileVersion = from.classFileVersion;
diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
index 652228c..bb39765 100644
--- a/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java
@@ -77,11 +77,6 @@
return materialize();
}
- @Override
- public int getAsKotlinFlags() {
- return super.getAsKotlinFlags();
- }
-
public boolean isVolatile() {
return isSet(Constants.ACC_VOLATILE);
}
diff --git a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
index 9e96ab4..7127794 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
@@ -88,6 +88,11 @@
return programClasses.get(type);
}
+ public DexLibraryClass libraryDefintionFor(DexType type) {
+ assert type.isClassType() : "Cannot lookup library definition for type: " + type;
+ return libraryClasses.get(type);
+ }
+
static class AllClasses {
// Mapping of all types to their definitions.
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
index c91b62d..8c9c20e 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
@@ -3,14 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static kotlinx.metadata.FlagsKt.flagsOf;
-
import com.android.tools.r8.dex.Constants;
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
import java.util.List;
import java.util.function.BooleanSupplier;
-import kotlinx.metadata.Flag;
public class MethodAccessFlags extends AccessFlags<MethodAccessFlags> {
@@ -110,16 +106,6 @@
return copy.materialize();
}
- @Override
- public int getAsKotlinFlags() {
- int flag = super.getAsKotlinFlags();
- List<Flag> flags = new ArrayList<>();
- if (isAbstract()) {
- flags.add(Flag.IS_ABSTRACT);
- }
- return flag | flagsOf(flags.toArray(EMPTY_FLAG));
- }
-
public boolean isSynchronized() {
return isSet(Constants.ACC_SYNCHRONIZED);
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
index 96b5de8..1fa68dd 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
@@ -4,28 +4,23 @@
package com.android.tools.r8.graph.analysis;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClasspathClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter.Mode;
-import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
-import java.util.ArrayList;
import java.util.IdentityHashMap;
-import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
public class DesugaredLibraryConversionWrapperAnalysis extends EnqueuerAnalysis
implements EnqueuerInvokeAnalysis {
private final AppView<?> appView;
private final DesugaredLibraryAPIConverter converter;
- private Map<DexType, DexProgramClass> synthesizedWrappers = new IdentityHashMap<>();
+ private Map<DexType, DexClasspathClass> synthesizedWrappers = new IdentityHashMap<>();
public DesugaredLibraryConversionWrapperAnalysis(AppView<?> appView) {
this.appView = appView;
@@ -71,34 +66,7 @@
return converter.generateCallbackMethods();
}
- public List<DexProgramClass> generateWrappers() {
- return converter.synthesizeWrappers(synthesizedWrappers);
- }
-
- // Generate a mock classpath class for all vivified types.
- // Types will be available at runtime in the desugared library dex file.
- public List<DexClasspathClass> generateWrappersSuperTypeMock(List<DexProgramClass> wrappers) {
- List<DexClasspathClass> classpathClasses = new ArrayList<>();
- for (DexProgramClass wrapper : wrappers) {
- boolean mockIsInterface = wrapper.interfaces.size() == 1;
- DexType mockType = mockIsInterface ? wrapper.interfaces.values[0] : wrapper.superType;
- if (appView.definitionFor(mockType) == null) {
- assert DesugaredLibraryAPIConverter.isVivifiedType(mockType);
- assert wrapper.instanceFields().size() == 1;
- DexType typeToMock = wrapper.instanceFields().get(0).field.type;
- DexClass classToMock = appView.definitionFor(typeToMock);
- assert classToMock != null;
- DexClasspathClass mockedSuperClass =
- converter.synthesizeClasspathMock(classToMock, mockType, mockIsInterface);
- classpathClasses.add(mockedSuperClass);
- for (DexEncodedMethod virtualMethod : wrapper.virtualMethods()) {
- // The mock is generated at the end of the enqueuing phase, so we need to manually set the
- // library override.
- assert mockedSuperClass.lookupVirtualMethod(virtualMethod.method) != null;
- virtualMethod.setLibraryMethodOverride(OptionalBool.TRUE);
- }
- }
- }
- return classpathClasses;
+ public void generateWrappers(Consumer<DexClasspathClass> synthesizedCallback) {
+ converter.synthesizeWrappers(synthesizedWrappers, synthesizedCallback);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index c53b686..5f6f83b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1195,20 +1195,16 @@
timing.end();
}
- if (method.isProcessed()) {
- // We loose locals information when processing dex code, so if in debug mode only process
- // synthesized methods.
- // TODO(b/158818229): Check if the synthesized check is needed.
- assert !isDebugMode || method.isD8R8Synthesized();
- assert !appView.enableWholeProgramOptimizations()
- || !appView.appInfo().withLiveness().neverReprocess.contains(method.method);
- } else {
- if (lambdaRewriter != null) {
- timing.begin("Desugar lambdas");
- lambdaRewriter.desugarLambdas(code);
- timing.end();
- assert code.isConsistentSSA();
- }
+ assert !method.isProcessed() || !isDebugMode;
+ assert !method.isProcessed()
+ || !appView.enableWholeProgramOptimizations()
+ || !appView.appInfo().withLiveness().neverReprocess.contains(method.method);
+
+ if (!method.isProcessed() && lambdaRewriter != null) {
+ timing.begin("Desugar lambdas");
+ lambdaRewriter.desugarLambdas(code);
+ timing.end();
+ assert code.isConsistentSSA();
}
if (lambdaMerger != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
index a91c1aa..401297e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
@@ -45,8 +45,8 @@
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
-// TODO(b/134732760): In progress.
// I convert library calls with desugared parameters/return values so they can work normally.
// In the JSON of the desugared library, one can specify conversions between desugared and
// non-desugared types. If no conversion is specified, D8/R8 simply generate wrapper classes around
@@ -287,7 +287,9 @@
}
SortedProgramMethodSet callbacks = generateCallbackMethods();
irConverter.processMethodsConcurrently(callbacks, executorService);
- wrapperSynthesizor.finalizeWrappersForD8(builder, irConverter, executorService);
+ if (appView.options().isDesugaredLibraryCompilation()) {
+ wrapperSynthesizor.finalizeWrappersForL8(builder, irConverter, executorService);
+ }
}
public SortedProgramMethodSet generateCallbackMethods() {
@@ -313,14 +315,10 @@
return allCallbackMethods;
}
- public List<DexProgramClass> synthesizeWrappers(
- Map<DexType, DexProgramClass> synthesizedWrappers) {
- return wrapperSynthesizor.synthesizeWrappers(synthesizedWrappers);
- }
-
- public DexClasspathClass synthesizeClasspathMock(
- DexClass classToMock, DexType mockType, boolean mockIsInterface) {
- return wrapperSynthesizor.synthesizeClasspathMock(classToMock, mockType, mockIsInterface);
+ public void synthesizeWrappers(
+ Map<DexType, DexClasspathClass> synthesizedWrappers,
+ Consumer<DexClasspathClass> synthesizedCallback) {
+ wrapperSynthesizor.synthesizeWrappersForClasspath(synthesizedWrappers, synthesizedCallback);
}
private ProgramMethod generateCallbackMethod(
@@ -352,20 +350,22 @@
public void reportInvalidInvoke(DexType type, DexMethod invokedMethod, String debugString) {
DexType desugaredType = appView.rewritePrefix.rewrittenType(type, appView);
- appView
- .options()
- .reporter
- .info(
- new StringDiagnostic(
- "Invoke to "
- + invokedMethod.holder
- + "#"
- + invokedMethod.name
- + " may not work correctly at runtime (Cannot convert "
- + debugString
- + "type "
- + desugaredType
- + ")."));
+ StringDiagnostic diagnostic =
+ new StringDiagnostic(
+ "Invoke to "
+ + invokedMethod.holder
+ + "#"
+ + invokedMethod.name
+ + " may not work correctly at runtime (Cannot convert "
+ + debugString
+ + "type "
+ + desugaredType
+ + ").");
+ if (appView.options().isDesugaredLibraryCompilation()) {
+ throw appView.options().reporter.fatalError(diagnostic);
+ } else {
+ appView.options().reporter.info(diagnostic);
+ }
}
public static DexType vivifiedTypeFor(DexType type, AppView<?> appView) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
index a7d5252..494831e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
@@ -12,24 +12,32 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.DesugarPrefixRewritingMapper;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
public class DesugaredLibraryConfiguration {
public static final String FALL_BACK_SYNTHESIZED_CLASSES_PACKAGE_PREFIX = "j$/";
- // TODO(b/134732760): should use DexString, DexType, DexMethod or so on when possible.
+ // TODO(b/158632510): should use DexString, DexType, DexMethod or so on when possible.
private final AndroidApiLevel requiredCompilationAPILevel;
private final boolean libraryCompilation;
private final String synthesizedLibraryClassesPackagePrefix;
@@ -41,9 +49,10 @@
private final Map<DexType, DexType> customConversions;
private final List<Pair<DexType, DexString>> dontRewriteInvocation;
private final List<String> extraKeepRules;
+ private final Set<DexType> wrapperConversions;
- public static Builder builder(DexItemFactory dexItemFactory) {
- return new Builder(dexItemFactory);
+ public static Builder builder(DexItemFactory dexItemFactory, Reporter reporter, Origin origin) {
+ return new Builder(dexItemFactory, reporter, origin);
}
public static DesugaredLibraryConfiguration withOnlyRewritePrefixForTesting(
@@ -58,6 +67,7 @@
ImmutableMap.of(),
ImmutableMap.of(),
ImmutableMap.of(),
+ ImmutableSet.of(),
ImmutableList.of(),
ImmutableList.of());
}
@@ -73,11 +83,12 @@
ImmutableMap.of(),
ImmutableMap.of(),
ImmutableMap.of(),
+ ImmutableSet.of(),
ImmutableList.of(),
ImmutableList.of());
}
- public DesugaredLibraryConfiguration(
+ private DesugaredLibraryConfiguration(
AndroidApiLevel requiredCompilationAPILevel,
boolean libraryCompilation,
String packagePrefix,
@@ -87,6 +98,7 @@
Map<DexString, Map<DexType, DexType>> retargetCoreLibMember,
Map<DexType, DexType> backportCoreLibraryMember,
Map<DexType, DexType> customConversions,
+ Set<DexType> wrapperConversions,
List<Pair<DexType, DexString>> dontRewriteInvocation,
List<String> extraKeepRules) {
this.requiredCompilationAPILevel = requiredCompilationAPILevel;
@@ -98,6 +110,7 @@
this.retargetCoreLibMember = retargetCoreLibMember;
this.backportCoreLibraryMember = backportCoreLibraryMember;
this.customConversions = customConversions;
+ this.wrapperConversions = wrapperConversions;
this.dontRewriteInvocation = dontRewriteInvocation;
this.extraKeepRules = extraKeepRules;
}
@@ -158,6 +171,10 @@
return customConversions;
}
+ public Set<DexType> getWrapperConversions() {
+ return wrapperConversions;
+ }
+
public List<Pair<DexType, DexString>> getDontRewriteInvocation() {
return dontRewriteInvocation;
}
@@ -169,6 +186,8 @@
public static class Builder {
private final DexItemFactory factory;
+ private final Reporter reporter;
+ private final Origin origin;
private AndroidApiLevel requiredCompilationAPILevel;
private boolean libraryCompilation = false;
@@ -176,15 +195,34 @@
FALL_BACK_SYNTHESIZED_CLASSES_PACKAGE_PREFIX;
private String identifier;
private Map<String, String> rewritePrefix = new HashMap<>();
- private Map<DexType, DexType> emulateLibraryInterface = new HashMap<>();
+ private Map<DexType, DexType> emulateLibraryInterface = new IdentityHashMap<>();
private Map<DexString, Map<DexType, DexType>> retargetCoreLibMember = new IdentityHashMap<>();
- private Map<DexType, DexType> backportCoreLibraryMember = new HashMap<>();
- private Map<DexType, DexType> customConversions = new HashMap<>();
+ private Map<DexType, DexType> backportCoreLibraryMember = new IdentityHashMap<>();
+ private Map<DexType, DexType> customConversions = new IdentityHashMap<>();
+ private Set<DexType> wrapperConversions = Sets.newIdentityHashSet();
private List<Pair<DexType, DexString>> dontRewriteInvocation = new ArrayList<>();
private List<String> extraKeepRules = Collections.emptyList();
- public Builder(DexItemFactory dexItemFactory) {
+ private Builder(DexItemFactory dexItemFactory, Reporter reporter, Origin origin) {
this.factory = dexItemFactory;
+ this.reporter = reporter;
+ this.origin = origin;
+ }
+
+ // Utility to set values. Currently assumes the key is fresh.
+ private <K, V> void put(Map<K, V> map, K key, V value, String desc) {
+ if (map.containsKey(key)) {
+ throw reporter.fatalError(
+ new StringDiagnostic(
+ "Invalid desugared library configuration. "
+ + " Duplicate assignment of key: '"
+ + key
+ + "' in sections for '"
+ + desc
+ + "'",
+ origin));
+ }
+ map.put(key, value);
}
public Builder setSynthesizedLibraryClassesPackagePrefix(String prefix) {
@@ -218,7 +256,11 @@
}
public Builder putRewritePrefix(String prefix, String rewrittenPrefix) {
- rewritePrefix.put(prefix, rewrittenPrefix);
+ put(
+ rewritePrefix,
+ prefix,
+ rewrittenPrefix,
+ DesugaredLibraryConfigurationParser.REWRITE_PREFIX_KEY);
return this;
}
@@ -226,14 +268,28 @@
String emulateLibraryItf, String rewrittenEmulateLibraryItf) {
DexType interfaceType = stringClassToDexType(emulateLibraryItf);
DexType rewrittenType = stringClassToDexType(rewrittenEmulateLibraryItf);
- emulateLibraryInterface.put(interfaceType, rewrittenType);
+ put(
+ emulateLibraryInterface,
+ interfaceType,
+ rewrittenType,
+ DesugaredLibraryConfigurationParser.EMULATE_INTERFACE_KEY);
return this;
}
public Builder putCustomConversion(String type, String conversionHolder) {
DexType dexType = stringClassToDexType(type);
DexType conversionType = stringClassToDexType(conversionHolder);
- customConversions.put(dexType, conversionType);
+ put(
+ customConversions,
+ dexType,
+ conversionType,
+ DesugaredLibraryConfigurationParser.CUSTOM_CONVERSION_KEY);
+ return this;
+ }
+
+ public Builder addWrapperConversion(String type) {
+ DexType dexType = stringClassToDexType(type);
+ wrapperConversions.add(dexType);
return this;
}
@@ -245,14 +301,22 @@
DexType originalType = stringClassToDexType(retarget.substring(0, index));
DexType finalType = stringClassToDexType(rewrittenRetarget);
assert !typeMap.containsKey(originalType);
- typeMap.put(originalType, finalType);
+ put(
+ typeMap,
+ originalType,
+ finalType,
+ DesugaredLibraryConfigurationParser.RETARGET_LIB_MEMBER_KEY);
return this;
}
public Builder putBackportCoreLibraryMember(String backport, String rewrittenBackport) {
DexType backportType = stringClassToDexType(backport);
DexType rewrittenBackportType = stringClassToDexType(rewrittenBackport);
- backportCoreLibraryMember.put(backportType, rewrittenBackportType);
+ put(
+ backportCoreLibraryMember,
+ backportType,
+ rewrittenBackportType,
+ DesugaredLibraryConfigurationParser.BACKPORT_KEY);
return this;
}
@@ -279,6 +343,7 @@
}
public DesugaredLibraryConfiguration build() {
+ validate();
return new DesugaredLibraryConfiguration(
requiredCompilationAPILevel,
libraryCompilation,
@@ -289,8 +354,22 @@
ImmutableMap.copyOf(retargetCoreLibMember),
ImmutableMap.copyOf(backportCoreLibraryMember),
ImmutableMap.copyOf(customConversions),
+ ImmutableSet.copyOf(wrapperConversions),
ImmutableList.copyOf(dontRewriteInvocation),
ImmutableList.copyOf(extraKeepRules));
}
+
+ private void validate() {
+ SetView<DexType> dups = Sets.intersection(customConversions.keySet(), wrapperConversions);
+ if (!dups.isEmpty()) {
+ throw reporter.fatalError(
+ new StringDiagnostic(
+ "Invalid desugared library configuration. "
+ + "Duplicate types in custom conversions and wrapper conversions: "
+ + String.join(
+ ", ", dups.stream().map(DexType::toString).collect(Collectors.toSet())),
+ origin));
+ }
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
index a659cc6..a1af388 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfigurationParser.java
@@ -6,7 +6,9 @@
import com.android.tools.r8.StringResource;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.gson.JsonArray;
@@ -19,142 +21,183 @@
public class DesugaredLibraryConfigurationParser {
- private static final int MAX_SUPPORTED_VERSION = 4;
+ public static final int MAX_SUPPORTED_VERSION = 4;
- private final DesugaredLibraryConfiguration.Builder configurationBuilder;
+ private static final String MIN_DESUGARED_LIBRARY_WITH_COMMON_FLAGS = "1.0.9";
+
+ private static final String UNSUPPORTED_MESSAGE =
+ "Unsupported desugared library version, please upgrade the"
+ + " desugared library to at least version "
+ + MIN_DESUGARED_LIBRARY_WITH_COMMON_FLAGS
+ + ".";
+
+ static final String CONFIGURATION_FORMAT_VERSION_KEY = "configuration_format_version";
+ static final String VERSION_KEY = "version";
+ static final String GROUP_ID_KEY = "group_id";
+ static final String ARTIFACT_ID_KEY = "artifact_id";
+ static final String REQUIRED_COMPILATION_API_LEVEL_KEY = "required_compilation_api_level";
+ static final String SYNTHESIZED_LIBRARY_CLASSES_PACKAGE_PREFIX_KEY =
+ "synthesized_library_classes_package_prefix";
+
+ static final String COMMON_FLAGS_KEY = "common_flags";
+ static final String LIBRARY_FLAGS_KEY = "library_flags";
+ static final String PROGRAM_FLAGS_KEY = "program_flags";
+
+ static final String API_LEVEL_BELOW_OR_EQUAL_KEY = "api_level_below_or_equal";
+ static final String WRAPPER_CONVERSION_KEY = "wrapper_conversion";
+ static final String CUSTOM_CONVERSION_KEY = "custom_conversion";
+ static final String REWRITE_PREFIX_KEY = "rewrite_prefix";
+ static final String RETARGET_LIB_MEMBER_KEY = "retarget_lib_member";
+ static final String EMULATE_INTERFACE_KEY = "emulate_interface";
+ static final String DONT_REWRITE_KEY = "dont_rewrite";
+ static final String BACKPORT_KEY = "backport";
+ static final String SHRINKER_CONFIG_KEY = "shrinker_config";
+
+ private final DexItemFactory dexItemFactory;
private final Reporter reporter;
private final boolean libraryCompilation;
private final int minAPILevel;
+ private DesugaredLibraryConfiguration.Builder configurationBuilder = null;
+ private Origin origin;
+
public DesugaredLibraryConfigurationParser(
DexItemFactory dexItemFactory,
Reporter reporter,
boolean libraryCompilation,
int minAPILevel) {
+ this.dexItemFactory = dexItemFactory;
this.reporter = reporter;
- this.configurationBuilder = DesugaredLibraryConfiguration.builder(dexItemFactory);
this.minAPILevel = minAPILevel;
this.libraryCompilation = libraryCompilation;
+ }
+
+ private JsonElement required(JsonObject json, String key) {
+ return required(
+ json,
+ key,
+ "Invalid desugared library configuration. " + "Expected required key '" + key + "'");
+ }
+
+ private JsonElement required(JsonObject json, String key, String message) {
+ if (!json.has(key)) {
+ throw reporter.fatalError(new StringDiagnostic(message, origin));
+ }
+ return json.get(key);
+ }
+
+ public DesugaredLibraryConfiguration parse(StringResource stringResource) {
+ origin = stringResource.getOrigin();
+ assert origin != null;
+ configurationBuilder = DesugaredLibraryConfiguration.builder(dexItemFactory, reporter, origin);
if (libraryCompilation) {
configurationBuilder.setLibraryCompilation();
} else {
configurationBuilder.setProgramCompilation();
}
- }
-
- public DesugaredLibraryConfiguration parse(StringResource stringResource) {
- String jsonConfigString;
+ JsonObject jsonConfig;
try {
- jsonConfigString = stringResource.getString();
+ String jsonConfigString = stringResource.getString();
+ JsonParser parser = new JsonParser();
+ jsonConfig = parser.parse(jsonConfigString).getAsJsonObject();
} catch (Exception e) {
- throw reporter.fatalError(
- new StringDiagnostic("Cannot access desugared library configuration."));
+ throw reporter.fatalError(new ExceptionDiagnostic(e, origin));
}
- JsonParser parser = new JsonParser();
- JsonObject jsonConfig = parser.parse(jsonConfigString).getAsJsonObject();
- int formatVersion = jsonConfig.get("configuration_format_version").getAsInt();
+ JsonElement formatVersionElement = required(jsonConfig, CONFIGURATION_FORMAT_VERSION_KEY);
+ int formatVersion = formatVersionElement.getAsInt();
if (formatVersion > MAX_SUPPORTED_VERSION) {
throw reporter.fatalError(
new StringDiagnostic(
"Unsupported desugared library configuration version, please upgrade the D8/R8"
- + " compiler."));
- }
- if (formatVersion == 1) {
- reporter.warning(
- new StringDiagnostic(
- "You are using an experimental version of the desugared library configuration, "
- + "distributed only in the early canary versions. Please update for "
- + "production releases and to fix this warning."));
+ + " compiler.",
+ origin));
}
- String version = jsonConfig.get("version").getAsString();
- String groupID;
- String artifactID;
- if (formatVersion < 4) {
- groupID = "com.tools.android";
- artifactID = "desugar_jdk_libs";
- } else {
- groupID = jsonConfig.get("group_id").getAsString();
- artifactID = jsonConfig.get("artifact_id").getAsString();
- }
+ String version = required(jsonConfig, VERSION_KEY).getAsString();
+ String groupID = required(jsonConfig, GROUP_ID_KEY).getAsString();
+ String artifactID = required(jsonConfig, ARTIFACT_ID_KEY).getAsString();
String identifier = String.join(":", groupID, artifactID, version);
configurationBuilder.setDesugaredLibraryIdentifier(identifier);
+ configurationBuilder.setSynthesizedLibraryClassesPackagePrefix(
+ required(jsonConfig, SYNTHESIZED_LIBRARY_CLASSES_PACKAGE_PREFIX_KEY).getAsString());
- if (jsonConfig.has("synthesized_library_classes_package_prefix")) {
- configurationBuilder.setSynthesizedLibraryClassesPackagePrefix(
- jsonConfig.get("synthesized_library_classes_package_prefix").getAsString());
- } else {
- reporter.warning(
- new StringDiagnostic(
- "Missing package_prefix, falling back to "
- + DesugaredLibraryConfiguration.FALL_BACK_SYNTHESIZED_CLASSES_PACKAGE_PREFIX
- + " prefix, update desugared library configuration."));
- }
int required_compilation_api_level =
- jsonConfig.get("required_compilation_api_level").getAsInt();
+ required(jsonConfig, REQUIRED_COMPILATION_API_LEVEL_KEY).getAsInt();
configurationBuilder.setRequiredCompilationAPILevel(
AndroidApiLevel.getAndroidApiLevel(required_compilation_api_level));
- JsonArray jsonFlags =
- libraryCompilation
- ? jsonConfig.getAsJsonArray("library_flags")
- : jsonConfig.getAsJsonArray("program_flags");
- for (JsonElement jsonFlagSet : jsonFlags) {
- int api_level_below_or_equal =
- jsonFlagSet.getAsJsonObject().get("api_level_below_or_equal").getAsInt();
- if (minAPILevel > api_level_below_or_equal) {
- continue;
- }
- parseFlags(jsonFlagSet.getAsJsonObject());
- }
- if (jsonConfig.has("shrinker_config")) {
- JsonArray jsonKeepRules = jsonConfig.get("shrinker_config").getAsJsonArray();
+ JsonElement commonFlags = required(jsonConfig, COMMON_FLAGS_KEY, UNSUPPORTED_MESSAGE);
+ JsonElement libraryFlags = required(jsonConfig, LIBRARY_FLAGS_KEY);
+ JsonElement programFlags = required(jsonConfig, PROGRAM_FLAGS_KEY);
+ parseFlagsList(commonFlags.getAsJsonArray());
+ parseFlagsList(
+ libraryCompilation ? libraryFlags.getAsJsonArray() : programFlags.getAsJsonArray());
+ if (jsonConfig.has(SHRINKER_CONFIG_KEY)) {
+ JsonArray jsonKeepRules = jsonConfig.get(SHRINKER_CONFIG_KEY).getAsJsonArray();
List<String> extraKeepRules = new ArrayList<>(jsonKeepRules.size());
for (JsonElement keepRule : jsonKeepRules) {
extraKeepRules.add(keepRule.getAsString());
}
configurationBuilder.setExtraKeepRules(extraKeepRules);
}
- return configurationBuilder.build();
+ DesugaredLibraryConfiguration config = configurationBuilder.build();
+ configurationBuilder = null;
+ origin = null;
+ return config;
+ }
+
+ private void parseFlagsList(JsonArray jsonFlags) {
+ for (JsonElement jsonFlagSet : jsonFlags) {
+ JsonObject flag = jsonFlagSet.getAsJsonObject();
+ int api_level_below_or_equal = required(flag, API_LEVEL_BELOW_OR_EQUAL_KEY).getAsInt();
+ if (minAPILevel <= api_level_below_or_equal) {
+ parseFlags(flag);
+ }
+ }
}
private void parseFlags(JsonObject jsonFlagSet) {
- if (jsonFlagSet.has("rewrite_prefix")) {
+ if (jsonFlagSet.has(REWRITE_PREFIX_KEY)) {
for (Map.Entry<String, JsonElement> rewritePrefix :
- jsonFlagSet.get("rewrite_prefix").getAsJsonObject().entrySet()) {
+ jsonFlagSet.get(REWRITE_PREFIX_KEY).getAsJsonObject().entrySet()) {
configurationBuilder.putRewritePrefix(
rewritePrefix.getKey(), rewritePrefix.getValue().getAsString());
}
}
- if (jsonFlagSet.has("retarget_lib_member")) {
+ if (jsonFlagSet.has(RETARGET_LIB_MEMBER_KEY)) {
for (Map.Entry<String, JsonElement> retarget :
- jsonFlagSet.get("retarget_lib_member").getAsJsonObject().entrySet()) {
+ jsonFlagSet.get(RETARGET_LIB_MEMBER_KEY).getAsJsonObject().entrySet()) {
configurationBuilder.putRetargetCoreLibMember(
retarget.getKey(), retarget.getValue().getAsString());
}
}
- if (jsonFlagSet.has("backport")) {
+ if (jsonFlagSet.has(BACKPORT_KEY)) {
for (Map.Entry<String, JsonElement> backport :
- jsonFlagSet.get("backport").getAsJsonObject().entrySet()) {
+ jsonFlagSet.get(BACKPORT_KEY).getAsJsonObject().entrySet()) {
configurationBuilder.putBackportCoreLibraryMember(
backport.getKey(), backport.getValue().getAsString());
}
}
- if (jsonFlagSet.has("emulate_interface")) {
+ if (jsonFlagSet.has(EMULATE_INTERFACE_KEY)) {
for (Map.Entry<String, JsonElement> itf :
- jsonFlagSet.get("emulate_interface").getAsJsonObject().entrySet()) {
+ jsonFlagSet.get(EMULATE_INTERFACE_KEY).getAsJsonObject().entrySet()) {
configurationBuilder.putEmulateLibraryInterface(itf.getKey(), itf.getValue().getAsString());
}
}
- if (jsonFlagSet.has("custom_conversion")) {
+ if (jsonFlagSet.has(CUSTOM_CONVERSION_KEY)) {
for (Map.Entry<String, JsonElement> conversion :
- jsonFlagSet.get("custom_conversion").getAsJsonObject().entrySet()) {
+ jsonFlagSet.get(CUSTOM_CONVERSION_KEY).getAsJsonObject().entrySet()) {
configurationBuilder.putCustomConversion(
conversion.getKey(), conversion.getValue().getAsString());
}
}
- if (jsonFlagSet.has("dont_rewrite")) {
- JsonArray dontRewrite = jsonFlagSet.get("dont_rewrite").getAsJsonArray();
+ if (jsonFlagSet.has(WRAPPER_CONVERSION_KEY)) {
+ for (JsonElement wrapper : jsonFlagSet.get(WRAPPER_CONVERSION_KEY).getAsJsonArray()) {
+ configurationBuilder.addWrapperConversion(wrapper.getAsString());
+ }
+ }
+ if (jsonFlagSet.has(DONT_REWRITE_KEY)) {
+ JsonArray dontRewrite = jsonFlagSet.get(DONT_REWRITE_KEY).getAsJsonArray();
for (JsonElement rewrite : dontRewrite) {
configurationBuilder.addDontRewriteInvocation(rewrite.getAsString());
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index 5fbf3df..23a6465 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
@@ -33,7 +34,6 @@
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperConversionCfCodeProvider;
import com.android.tools.r8.origin.SynthesizedOrigin;
-import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -48,6 +48,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
// I am responsible for the generation of wrappers used to call library APIs when desugaring
// libraries. Wrappers can be both ways, wrapping the desugarType as a type, or the type as
@@ -110,15 +112,19 @@
private final Set<DexType> invalidWrappers = Sets.newConcurrentHashSet();
private final DexItemFactory factory;
private final DesugaredLibraryAPIConverter converter;
- private final DexString vivifiedSourceFile;
DesugaredLibraryWrapperSynthesizer(AppView<?> appView, DesugaredLibraryAPIConverter converter) {
this.appView = appView;
this.factory = appView.dexItemFactory();
- dexWrapperPrefixString = "L" + appView.options().synthesizedClassPrefix + WRAPPER_PREFIX;
+ dexWrapperPrefixString =
+ "L"
+ + appView
+ .options()
+ .desugaredLibraryConfiguration
+ .getSynthesizedLibraryClassesPackagePrefix()
+ + WRAPPER_PREFIX;
dexWrapperPrefixDexString = factory.createString(dexWrapperPrefixString);
this.converter = converter;
- this.vivifiedSourceFile = appView.dexItemFactory().createString("vivified");
}
boolean hasSynthesized(DexType type) {
@@ -126,11 +132,7 @@
}
boolean canGenerateWrapper(DexType type) {
- DexClass dexClass = appView.definitionFor(type);
- if (dexClass == null || dexClass.accessFlags.isFinal()) {
- return false;
- }
- return dexClass.isLibraryClass() || appView.options().isDesugaredLibraryCompilation();
+ return appView.options().desugaredLibraryConfiguration.getWrapperConversions().contains(type);
}
DexType getTypeWrapper(DexType type) {
@@ -155,9 +157,10 @@
return wrappers.computeIfAbsent(
type,
t -> {
+ assert canGenerateWrapper(type) : type;
DexType wrapperType = createWrapperType(type, suffix);
assert converter.canGenerateWrappersAndCallbacks()
- || appView.definitionForProgramType(wrapperType) != null
+ || appView.definitionFor(wrapperType).isClasspathClass()
: "Wrapper " + wrapperType + " should have been generated in the enqueuer.";
return wrapperType;
});
@@ -176,10 +179,12 @@
return DesugaredLibraryAPIConverter.vivifiedTypeFor(type, appView);
}
- private DexProgramClass generateTypeWrapper(DexClass dexClass, DexType typeWrapperType) {
+ private DexClass generateTypeWrapper(
+ ClassKind classKind, DexClass dexClass, DexType typeWrapperType) {
DexType type = dexClass.type;
DexEncodedField wrapperField = synthesizeWrappedValueEncodedField(typeWrapperType, type);
return synthesizeWrapper(
+ classKind,
vivifiedTypeFor(type),
dexClass,
synthesizeVirtualMethodsForTypeWrapper(dexClass, wrapperField),
@@ -187,12 +192,13 @@
wrapperField);
}
- private DexProgramClass generateVivifiedTypeWrapper(
- DexClass dexClass, DexType vivifiedTypeWrapperType) {
+ private DexClass generateVivifiedTypeWrapper(
+ ClassKind classKind, DexClass dexClass, DexType vivifiedTypeWrapperType) {
DexType type = dexClass.type;
DexEncodedField wrapperField =
synthesizeWrappedValueEncodedField(vivifiedTypeWrapperType, vivifiedTypeFor(type));
return synthesizeWrapper(
+ classKind,
type,
dexClass,
synthesizeVirtualMethodsForVivifiedTypeWrapper(dexClass, wrapperField),
@@ -200,7 +206,8 @@
wrapperField);
}
- private DexProgramClass synthesizeWrapper(
+ private DexClass synthesizeWrapper(
+ ClassKind classKind,
DexType wrappingType,
DexClass clazz,
DexEncodedMethod[] virtualMethods,
@@ -210,9 +217,9 @@
DexType superType = isItf ? factory.objectType : wrappingType;
DexTypeList interfaces =
isItf ? new DexTypeList(new DexType[] {wrappingType}) : DexTypeList.empty();
- return new DexProgramClass(
+ return classKind.create(
wrapperField.holder(),
- null,
+ Kind.CF,
new SynthesizedOrigin("Desugared library API Converter", getClass()),
ClassAccessFlags.fromSharedAccessFlags(
Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC),
@@ -229,8 +236,7 @@
new DexEncodedMethod[] {synthesizeConstructor(wrapperField.field), conversionMethod},
virtualMethods,
factory.getSkipNameValidationForTesting(),
- DexProgramClass::checksumFromType,
- Collections.emptyList());
+ DexProgramClass::checksumFromType);
}
private DexEncodedMethod[] synthesizeVirtualMethodsForVivifiedTypeWrapper(
@@ -325,51 +331,6 @@
return finalizeWrapperMethods(generatedMethods, finalMethods);
}
- private DexEncodedMethod[] synthesizeVirtualMethodsForClasspathMock(
- DexClass dexClass, DexType mockType) {
- List<DexEncodedMethod> dexMethods = allImplementedMethods(dexClass);
- List<DexEncodedMethod> generatedMethods = new ArrayList<>();
- // Generate only abstract methods for library override detection.
- for (DexEncodedMethod dexEncodedMethod : dexMethods) {
- DexClass holderClass = appView.definitionFor(dexEncodedMethod.holder());
- assert holderClass != null || appView.options().isDesugaredLibraryCompilation();
- if (!dexEncodedMethod.isFinal()) {
- DexMethod methodToInstall =
- DesugaredLibraryAPIConverter.methodWithVivifiedTypeInSignature(
- dexEncodedMethod.method, mockType, appView);
- DexEncodedMethod newDexEncodedMethod =
- newSynthesizedMethod(methodToInstall, dexEncodedMethod, null);
- generatedMethods.add(newDexEncodedMethod);
- }
- }
- return generatedMethods.toArray(DexEncodedMethod.EMPTY_ARRAY);
- }
-
- DexClasspathClass synthesizeClasspathMock(
- DexClass classToMock, DexType mockType, boolean mockIsInterface) {
- return new DexClasspathClass(
- mockType,
- Kind.CF,
- new SynthesizedOrigin("Desugared library wrapper super class ", getClass()),
- ClassAccessFlags.fromDexAccessFlags(
- Constants.ACC_SYNTHETIC
- | Constants.ACC_PUBLIC
- | (BooleanUtils.intValue(mockIsInterface) * Constants.ACC_INTERFACE)),
- appView.dexItemFactory().objectType,
- DexTypeList.empty(),
- vivifiedSourceFile,
- null,
- Collections.emptyList(),
- null,
- Collections.emptyList(),
- DexAnnotationSet.empty(),
- DexEncodedField.EMPTY_ARRAY,
- DexEncodedField.EMPTY_ARRAY,
- DexEncodedMethod.EMPTY_ARRAY,
- synthesizeVirtualMethodsForClasspathMock(classToMock, mockType),
- appView.dexItemFactory().getSkipNameValidationForTesting());
- }
-
private DexEncodedMethod[] finalizeWrapperMethods(
List<DexEncodedMethod> generatedMethods, Set<DexMethod> finalMethods) {
if (finalMethods.isEmpty()) {
@@ -492,36 +453,69 @@
true);
}
- void finalizeWrappersForD8(
+ void finalizeWrappersForL8(
DexApplication.Builder<?> builder, IRConverter irConverter, ExecutorService executorService)
throws ExecutionException {
- List<DexProgramClass> synthesizedWrappers = synthesizeWrappers(new IdentityHashMap<>());
+ List<DexProgramClass> synthesizedWrappers = synthesizeWrappers();
registerAndProcessWrappers(builder, irConverter, executorService, synthesizedWrappers);
}
- List<DexProgramClass> synthesizeWrappers(Map<DexType, DexProgramClass> synthesizedWrappers) {
+ private List<DexProgramClass> synthesizeWrappers() {
+ DesugaredLibraryConfiguration conf = appView.options().desugaredLibraryConfiguration;
+ for (DexType type : conf.getWrapperConversions()) {
+ assert !conf.getCustomConversions().containsKey(type);
+ getTypeWrapper(type);
+ }
+ Map<DexType, DexClass> synthesizedWrappers = new IdentityHashMap<>();
List<DexProgramClass> additions = new ArrayList<>();
- // Generating a wrapper may require other wrappers to be generated, iterate until fix point.
- while (synthesizedWrappers.size() != typeWrappers.size() + vivifiedTypeWrappers.size()) {
+ int total = typeWrappers.size() + vivifiedTypeWrappers.size();
+ generateWrappers(
+ ClassKind.PROGRAM,
+ synthesizedWrappers.keySet(),
+ (type, wrapper) -> {
+ synthesizedWrappers.put(type, wrapper);
+ additions.add(wrapper.asProgramClass());
+ });
+ assert total == typeWrappers.size() + vivifiedTypeWrappers.size() : "unexpected additions";
+ return additions;
+ }
+
+ void synthesizeWrappersForClasspath(
+ Map<DexType, DexClasspathClass> synthesizedWrappers,
+ Consumer<DexClasspathClass> synthesizedCallback) {
+ generateWrappers(
+ ClassKind.CLASSPATH,
+ synthesizedWrappers.keySet(),
+ (type, wrapper) -> {
+ DexClasspathClass classpathWrapper = wrapper.asClasspathClass();
+ synthesizedWrappers.put(type, classpathWrapper);
+ synthesizedCallback.accept(classpathWrapper);
+ });
+ }
+
+ private void generateWrappers(
+ ClassKind classKind,
+ Set<DexType> synthesized,
+ BiConsumer<DexType, DexClass> generatedCallback) {
+ while (synthesized.size() != typeWrappers.size() + vivifiedTypeWrappers.size()) {
for (DexType type : typeWrappers.keySet()) {
DexType typeWrapperType = typeWrappers.get(type);
- if (!synthesizedWrappers.containsKey(typeWrapperType)) {
- DexProgramClass wrapper = generateTypeWrapper(getValidClassToWrap(type), typeWrapperType);
- synthesizedWrappers.put(typeWrapperType, wrapper);
- additions.add(wrapper);
+ if (!synthesized.contains(typeWrapperType)) {
+ DexClass wrapper =
+ generateTypeWrapper(classKind, getValidClassToWrap(type), typeWrapperType);
+ generatedCallback.accept(typeWrapperType, wrapper);
}
}
for (DexType type : vivifiedTypeWrappers.keySet()) {
DexType vivifiedTypeWrapperType = vivifiedTypeWrappers.get(type);
- if (!synthesizedWrappers.containsKey(vivifiedTypeWrapperType)) {
- DexProgramClass wrapper =
- generateVivifiedTypeWrapper(getValidClassToWrap(type), vivifiedTypeWrapperType);
- synthesizedWrappers.put(vivifiedTypeWrapperType, wrapper);
- additions.add(wrapper);
+ if (!synthesized.contains(vivifiedTypeWrapperType)) {
+ DexClass wrapper =
+ generateVivifiedTypeWrapper(
+ classKind, getValidClassToWrap(type), vivifiedTypeWrapperType);
+ generatedCallback.accept(vivifiedTypeWrapperType, wrapper);
}
}
}
- return additions;
}
private void registerAndProcessWrappers(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 73da99f..97dbb2e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.androidapi.AvailableApiExceptions;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AccessControl;
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -64,6 +65,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
@@ -981,6 +983,16 @@
continue;
}
+ OptionalBool methodAccessible =
+ AccessControl.isMethodAccessible(
+ singleTarget.getDefinition(),
+ singleTarget.getHolder().asDexClass(),
+ context.getHolder(),
+ appView.withClassHierarchy().appInfo());
+ if (!methodAccessible.isTrue()) {
+ continue;
+ }
+
DexEncodedMethod singleTargetMethod = singleTarget.getDefinition();
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter =
oracle.isForcedInliningOracle()
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index b3bbbfc..4e52743 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -9,6 +9,7 @@
import static com.google.common.base.Predicates.alwaysFalse;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AccessControl;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
@@ -58,6 +59,7 @@
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
@@ -307,6 +309,13 @@
return user; // Not eligible.
}
+ OptionalBool methodAccessible =
+ AccessControl.isMethodAccessible(
+ singleTargetMethod, singleTarget.getHolder().asDexClass(), method, appView);
+
+ if (!methodAccessible.isTrue()) {
+ return user; // Not eligible.
+ }
// Eligible constructor call (for new instance roots only).
if (user.isInvokeDirect()) {
InvokeDirect invoke = user.asInvokeDirect();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 29250dc..8dbb64a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
+import static com.android.tools.r8.utils.PredicateUtils.not;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
@@ -762,7 +763,8 @@
if (candidateClass.type != hostType) {
DexProgramClass hostClass = asProgramClassOrNull(appView.definitionFor(hostType));
assert hostClass != null;
- if (!classMembersConflict(candidateClass, hostClass)) {
+ if (!classMembersConflict(candidateClass, hostClass)
+ && !hasMembersNotStaticized(candidateClass, staticizedMethods)) {
// Move all members of the candidate class into host class.
moveMembersIntoHost(staticizedMethods,
candidateClass, hostType, hostClass, methodMapping, fieldMapping);
@@ -783,6 +785,16 @@
|| Streams.stream(a.methods()).anyMatch(method -> b.lookupMethod(method.method) != null);
}
+ private boolean hasMembersNotStaticized(
+ DexProgramClass candidateClass, ProgramMethodSet staticizedMethods) {
+ // TODO(b/159174309): Refine the analysis to allow for fields.
+ if (candidateClass.hasFields()) {
+ return true;
+ }
+ // TODO(b/158018192): Activate again when picking up all references.
+ return candidateClass.methods(not(staticizedMethods::contains)).iterator().hasNext();
+ }
+
private void moveMembersIntoHost(
ProgramMethodSet staticizedMethods,
DexProgramClass candidateClass,
diff --git a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
index b16b8b6..ef44b4b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
+++ b/src/main/java/com/android/tools/r8/kotlin/Kotlin.java
@@ -9,11 +9,8 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -21,17 +18,6 @@
/** Class provides basic information about symbols related to Kotlin support. */
public final class Kotlin {
- // Simply "kotlin", but to avoid being renamed by Shadow.relocate in build.gradle.
- public static final String NAME = String.join("", ImmutableList.of("k", "o", "t", "l", "i", "n"));
-
- // Simply "Lkotlin/", but to avoid being renamed by Shadow.relocate in build.gradle.
- private static final String KOTLIN =
- String.join("", ImmutableList.of("L", "k", "o", "t", "l", "i", "n", "/"));
-
- static String addKotlinPrefix(String str) {
- return KOTLIN + str;
- }
-
public final DexItemFactory factory;
public final Functional functional;
@@ -39,83 +25,22 @@
public final Metadata metadata;
public final _Assertions assertions;
+ public static final String NAME = "kotlin";
+ public static final String PACKAGE_PREFIX = "L" + NAME + "/";
+
public static final class ClassClassifiers {
public static final String arrayBinaryName = NAME + "/Array";
- public static final String anyDescriptor = "L" + NAME + "/Any;";
+ public static final String anyDescriptor = PACKAGE_PREFIX + "Any;";
public static final String anyName = NAME + "/Any";
}
- // Mappings from JVM types to Kotlin types (of type DexType)
- final Map<DexType, DexType> knownTypeConversion;
-
public Kotlin(DexItemFactory factory) {
this.factory = factory;
-
this.functional = new Functional();
this.intrinsics = new Intrinsics();
this.metadata = new Metadata();
this.assertions = new _Assertions();
-
- // See {@link org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite}
- this.knownTypeConversion =
- ImmutableMap.<DexType, DexType>builder()
- // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/index.html
- // Boxed primitives and arrays
- .put(factory.booleanType, factory.createType(addKotlinPrefix("Boolean;")))
- .put(factory.boxedBooleanType, factory.createType(addKotlinPrefix("Boolean;")))
- .put(factory.booleanArrayType, factory.createType(addKotlinPrefix("BooleanArray;")))
- .put(factory.byteType, factory.createType(addKotlinPrefix("Byte;")))
- .put(factory.byteArrayType, factory.createType(addKotlinPrefix("ByteArray;")))
- .put(factory.charType, factory.createType(addKotlinPrefix("Char;")))
- .put(factory.charArrayType, factory.createType(addKotlinPrefix("CharArray;")))
- .put(factory.shortType, factory.createType(addKotlinPrefix("Short;")))
- .put(factory.shortArrayType, factory.createType(addKotlinPrefix("ShortArray;")))
- .put(factory.intType, factory.createType(addKotlinPrefix("Int;")))
- .put(factory.boxedIntType, factory.createType(addKotlinPrefix("Int;")))
- .put(factory.intArrayType, factory.createType(addKotlinPrefix("IntArray;")))
- .put(factory.longType, factory.createType(addKotlinPrefix("Long;")))
- .put(factory.longArrayType, factory.createType(addKotlinPrefix("LongArray;")))
- .put(factory.floatType, factory.createType(addKotlinPrefix("Float;")))
- .put(factory.floatArrayType, factory.createType(addKotlinPrefix("FloatArray;")))
- .put(factory.doubleType, factory.createType(addKotlinPrefix("Double;")))
- .put(factory.doubleArrayType, factory.createType(addKotlinPrefix("DoubleArray;")))
- // Other intrinsics
- .put(factory.voidType, factory.createType(addKotlinPrefix("Unit;")))
- .put(factory.objectType, factory.createType(addKotlinPrefix("Any;")))
- .put(factory.boxedVoidType, factory.createType(addKotlinPrefix("Nothing;")))
- .put(factory.stringType, factory.createType(addKotlinPrefix("String;")))
- .put(factory.charSequenceType, factory.createType(addKotlinPrefix("CharSequence;")))
- .put(factory.throwableType, factory.createType(addKotlinPrefix("Throwable;")))
- .put(factory.cloneableType, factory.createType(addKotlinPrefix("Cloneable;")))
- .put(factory.boxedNumberType, factory.createType(addKotlinPrefix("Number;")))
- .put(factory.comparableType, factory.createType(addKotlinPrefix("Comparable;")))
- .put(factory.enumType, factory.createType(addKotlinPrefix("Enum;")))
- // Collections
- .put(factory.iteratorType, factory.createType(addKotlinPrefix("collections/Iterator;")))
- .put(
- factory.collectionType,
- factory.createType(addKotlinPrefix("collections/Collection;")))
- .put(factory.listType, factory.createType(addKotlinPrefix("collections/List;")))
- .put(factory.setType, factory.createType(addKotlinPrefix("collections/Set;")))
- .put(factory.mapType, factory.createType(addKotlinPrefix("collections/Map;")))
- .put(
- factory.listIteratorType,
- factory.createType(addKotlinPrefix("collections/ListIterator;")))
- .put(factory.iterableType, factory.createType(addKotlinPrefix("collections/Iterable;")))
- .put(
- factory.mapEntryType, factory.createType(addKotlinPrefix("collections/Map$Entry;")))
- // .../jvm/functions/FunctionN -> .../FunctionN
- .putAll(
- IntStream.rangeClosed(0, 22)
- .boxed()
- .collect(
- Collectors.toMap(
- i ->
- factory.createType(
- addKotlinPrefix("jvm/functions/Function" + i + ";")),
- i -> factory.createType(addKotlinPrefix("Function" + i + ";")))))
- .build();
}
public final class Functional {
@@ -129,12 +54,15 @@
// > "Error: A JNI error has occurred, please check your installation and try again"
//
// This implementation just ignores lambdas with arity > 22.
- private final Object2IntMap<DexType> functions = new Object2IntArrayMap<>(
- IntStream.rangeClosed(0, 22).boxed().collect(
- Collectors.toMap(
- i -> factory.createType(addKotlinPrefix("jvm/functions/Function") + i + ";"),
- Function.identity()))
- );
+ private final Object2IntMap<DexType> functions =
+ new Object2IntArrayMap<>(
+ IntStream.rangeClosed(0, 22)
+ .boxed()
+ .collect(
+ Collectors.toMap(
+ i ->
+ factory.createType(PACKAGE_PREFIX + "jvm/functions/Function" + i + ";"),
+ Function.identity())));
private Functional() {
}
@@ -142,8 +70,8 @@
public final DexString kotlinStyleLambdaInstanceName = factory.createString("INSTANCE");
public final DexType functionBase =
- factory.createType(addKotlinPrefix("jvm/internal/FunctionBase;"));
- public final DexType lambdaType = factory.createType(addKotlinPrefix("jvm/internal/Lambda;"));
+ factory.createType(PACKAGE_PREFIX + "jvm/internal/FunctionBase;");
+ public final DexType lambdaType = factory.createType(PACKAGE_PREFIX + "jvm/internal/Lambda;");
public final DexMethod lambdaInitializerMethod = factory.createMethod(
lambdaType,
@@ -173,7 +101,7 @@
}
public final class _Assertions {
- public final DexType type = factory.createType(addKotlinPrefix("_Assertions;"));
+ public final DexType type = factory.createType(PACKAGE_PREFIX + "_Assertions;");
public final DexString enabledFieldName = factory.createString("ENABLED");
public final DexField enabledField =
factory.createField(type, factory.booleanType, enabledFieldName);
@@ -181,7 +109,7 @@
// kotlin.jvm.internal.Intrinsics class
public final class Intrinsics {
- public final DexType type = factory.createType(addKotlinPrefix("jvm/internal/Intrinsics;"));
+ public final DexType type = factory.createType(PACKAGE_PREFIX + "jvm/internal/Intrinsics;");
public final DexMethod throwParameterIsNullException = factory.createMethod(type,
factory.createProto(factory.voidType, factory.stringType), "throwParameterIsNullException");
public final DexMethod checkParameterIsNotNull = factory.createMethod(type,
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java
index 6a9b23d..953766c 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationArgumentInfo.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Box;
import com.google.common.collect.ImmutableList;
@@ -30,8 +29,7 @@
private static final Map<String, KotlinAnnotationArgumentInfo> EMPTY_ARGUMENTS =
ImmutableMap.of();
- abstract KmAnnotationArgument<?> rewrite(
- AppView<AppInfoWithLiveness> appView, NamingLens namingLens);
+ abstract KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens);
private static KotlinAnnotationArgumentInfo createArgument(
KmAnnotationArgument<?> arg, DexItemFactory factory) {
@@ -77,7 +75,7 @@
}
@Override
- KmAnnotationArgument<?> rewrite(AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
return new KClassValue(
value.toRenamedBinaryNameOrDefault(appView, namingLens, ClassClassifiers.anyName));
}
@@ -105,7 +103,7 @@
}
@Override
- KmAnnotationArgument<?> rewrite(AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
return new EnumValue(
enumClassName.toRenamedBinaryNameOrDefault(appView, namingLens, ClassClassifiers.anyName),
enumEntryName);
@@ -132,7 +130,7 @@
}
@Override
- KmAnnotationArgument<?> rewrite(AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
Box<KmAnnotation> rewrittenAnnotation = new Box<>();
value.rewrite(rewrittenAnnotation::set, appView, namingLens);
if (rewrittenAnnotation.isSet()) {
@@ -172,7 +170,7 @@
}
@Override
- KmAnnotationArgument<?> rewrite(AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
List<KmAnnotationArgument<?>> rewrittenArguments = new ArrayList<>();
for (KotlinAnnotationArgumentInfo kotlinAnnotationArgumentInfo : value) {
KmAnnotationArgument<?> rewrittenArg =
@@ -203,7 +201,7 @@
}
@Override
- KmAnnotationArgument<?> rewrite(AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ KmAnnotationArgument<?> rewrite(AppView<?> appView, NamingLens namingLens) {
return argument;
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
index fd4d087..45adb46 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinAnnotationInfo.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
@@ -51,7 +50,7 @@
public void rewrite(
KmVisitorProviders.KmAnnotationVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
String renamedDescriptor =
annotationType.toRenamedDescriptorOrDefault(appView, namingLens, null);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
index c32bcc4..24947bf 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassInfo.java
@@ -16,7 +16,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -44,7 +43,6 @@
private final List<KotlinTypeInfo> superTypes;
private final List<KotlinTypeReference> sealedSubClasses;
private final List<KotlinTypeReference> nestedClasses;
- // TODO(b/154347404): Understand enum entries.
private final List<String> enumEntries;
private final KotlinVersionRequirementInfo versionRequirements;
private final KotlinTypeReference anonymousObjectOrigin;
@@ -201,8 +199,7 @@
}
@Override
- public KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
KmClass kmClass = new KmClass();
// TODO(b/154348683): Set flags.
kmClass.setFlags(flags);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
index 1a24001..fdb326e 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassLevelInfo.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import kotlinx.metadata.jvm.KotlinClassHeader;
@@ -57,8 +56,7 @@
return null;
}
- KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens);
+ KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens);
String getPackageName();
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
index ac19e28..c80ed32 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassifierInfo.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Reporter;
@@ -47,8 +46,7 @@
}
}
- abstract void rewrite(
- KmTypeVisitor visitor, AppView<AppInfoWithLiveness> appView, NamingLens namingLens);
+ abstract void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens);
public static class KotlinClassClassifierInfo extends KotlinClassifierInfo {
@@ -61,8 +59,7 @@
}
@Override
- void rewrite(
- KmTypeVisitor visitor, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
String descriptor =
type.toRenamedDescriptorOrDefault(appView, namingLens, ClassClassifiers.anyDescriptor);
// For local or anonymous classes, the classifier is prefixed with '.' and inner classes are
@@ -89,8 +86,7 @@
}
@Override
- void rewrite(
- KmTypeVisitor visitor, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
visitor.visitTypeParameter(typeId);
}
@@ -109,8 +105,7 @@
}
@Override
- void rewrite(
- KmTypeVisitor visitor, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
visitor.visitTypeAlias(typeAlias);
}
@@ -128,8 +123,7 @@
}
@Override
- void rewrite(
- KmTypeVisitor visitor, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
visitor.visitClass(classifier);
}
@@ -147,8 +141,7 @@
}
@Override
- void rewrite(
- KmTypeVisitor visitor, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ void rewrite(KmTypeVisitor visitor, AppView<?> appView, NamingLens namingLens) {
visitor.visitTypeAlias(classifier);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
index c28b4a7..2e4ee98 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinConstructorInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmClass;
@@ -51,10 +50,7 @@
}
public void rewrite(
- KmClass kmClass,
- DexEncodedMethod method,
- AppView<AppInfoWithLiveness> appView,
- NamingLens namingLens) {
+ KmClass kmClass, DexEncodedMethod method, AppView<?> appView, NamingLens namingLens) {
// Note that JvmExtensionsKt.setSignature does not have an overload for KmConstructorVisitor,
// thus we rely on creating the KmConstructor manually.
// TODO(b/154348683): Check for special flags to pass in.
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
index 21fb43a..fd0d60d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinContractInfo.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -52,7 +51,7 @@
public void rewrite(
KmVisitorProviders.KmContractVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
if (this == NO_EFFECT) {
return;
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
index a83f77a..79b4173 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.KotlinMetadataUtils.KmPropertyProcessor;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -155,7 +154,7 @@
KmVisitorProviders.KmPropertyVisitorProvider propertyProvider,
KmVisitorProviders.KmTypeAliasVisitorProvider typeAliasProvider,
DexClass clazz,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
// Type aliases only have a representation here, so we can generate them directly.
for (KotlinTypeAliasInfo typeAlias : typeAliases) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
index d3ce846..d6664d1 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectExpressionInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.KmVisitorProviders.KmEffectExpressionVisitorProvider;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -87,9 +86,7 @@
}
public void rewrite(
- KmEffectExpressionVisitorProvider provider,
- AppView<AppInfoWithLiveness> appView,
- NamingLens namingLens) {
+ KmEffectExpressionVisitorProvider provider, AppView<?> appView, NamingLens namingLens) {
if (this == NO_EXPRESSION) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
index e38f158..3b1c748 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinEffectInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.KmVisitorProviders.KmEffectVisitorProvider;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
@@ -52,10 +51,7 @@
conclusion.trace(definitionSupplier);
}
- void rewrite(
- KmEffectVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
- NamingLens namingLens) {
+ void rewrite(KmEffectVisitorProvider visitorProvider, AppView<?> appView, NamingLens namingLens) {
KmEffectVisitor kmEffectVisitor = visitorProvider.get(type, invocationKind);
conclusion.rewrite(kmEffectVisitor::visitConclusionOfConditionalEffect, appView, namingLens);
for (KotlinEffectExpressionInfo constructorArgument : constructorArguments) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
index 94617e1..886281f 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFileFacadeInfo.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import java.util.function.Consumer;
import kotlinx.metadata.KmPackage;
@@ -53,8 +52,7 @@
}
@Override
- public KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
KotlinClassMetadata.FileFacade.Writer writer = new KotlinClassMetadata.FileFacade.Writer();
KmPackage kmPackage = new KmPackage();
packageInfo.rewrite(kmPackage, clazz, appView, namingLens);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
index da2e960..91413c7 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFlexibleTypeUpperBoundInfo.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmFlexibleTypeUpperBound;
@@ -65,7 +64,7 @@
public void rewrite(
KmVisitorProviders.KmFlexibleUpperBoundVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
if (this == NO_FLEXIBLE_UPPER_BOUND) {
// Nothing to do.
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
index dfcbac5..f5ce062 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFunctionInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmFunction;
@@ -110,7 +109,7 @@
public void rewrite(
KmVisitorProviders.KmFunctionVisitorProvider visitorProvider,
DexEncodedMethod method,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
// TODO(b/154348683): Check method for flags to pass in.
String finalName = this.name;
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
index 6daf3d7..974e4a8 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmFieldSignatureInfo.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import kotlinx.metadata.jvm.JvmFieldSignature;
@@ -38,7 +37,7 @@
}
public JvmFieldSignature rewrite(
- DexEncodedField field, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ DexEncodedField field, AppView<?> appView, NamingLens namingLens) {
String finalName = name;
if (field != null) {
String fieldName = field.field.name.toString();
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
index f4674a1..2469a54 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinJvmMethodSignatureInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
@@ -73,7 +72,7 @@
}
public JvmMethodSignature rewrite(
- DexEncodedMethod method, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ DexEncodedMethod method, AppView<?> appView, NamingLens namingLens) {
if (invalidDescriptor != null) {
return new JvmMethodSignature(name, invalidDescriptor);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
index 459599b..cc215d5 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLambdaInfo.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmLambda;
@@ -53,7 +52,7 @@
boolean rewrite(
KmVisitorProviders.KmLambdaVisitorProvider visitorProvider,
DexClass clazz,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
if (!hasBacking) {
function.rewrite(visitorProvider.get()::visitFunction, null, appView, namingLens);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
index cab770f..fca17cf 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinLocalDelegatedPropertyInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.kotlin.KmVisitorProviders.KmPropertyVisitorProvider;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -54,9 +53,7 @@
}
public void rewrite(
- KmPropertyVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
- NamingLens namingLens) {
+ KmPropertyVisitorProvider visitorProvider, AppView<?> appView, NamingLens namingLens) {
for (KotlinPropertyInfo propertyInfo : propertyInfos) {
propertyInfo.rewrite(visitorProvider, null, null, null, appView, namingLens);
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index dfddc1d..d709ea4 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -16,7 +16,6 @@
import com.android.tools.r8.graph.DexValue.DexValueInt;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
@@ -26,12 +25,12 @@
public class KotlinMetadataRewriter {
- private final AppView<AppInfoWithLiveness> appView;
+ private final AppView<?> appView;
private final NamingLens lens;
private final DexItemFactory factory;
private final Kotlin kotlin;
- public KotlinMetadataRewriter(AppView<AppInfoWithLiveness> appView, NamingLens lens) {
+ public KotlinMetadataRewriter(AppView<?> appView, NamingLens lens) {
this.appView = appView;
this.lens = lens;
this.factory = appView.dexItemFactory();
@@ -54,7 +53,8 @@
}
if (oldMeta == null
|| kotlinInfo == NO_KOTLIN_INFO
- || !appView.appInfo().isPinned(clazz.type)) {
+ || (appView.appInfo().hasLiveness()
+ && !appView.withLiveness().appInfo().isPinned(clazz.type))) {
// Remove @Metadata in DexAnnotation when there is no kotlin info and the type is not
// missing.
if (oldMeta != null) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
index 1ee78a5..6ef7a0d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.shaking.ProguardKeepRule;
@@ -49,8 +48,7 @@
}
@Override
- public KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
throw new Unreachable("Should never be called");
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
index 1ccd35f..34c5248 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassFacadeInfo.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
@@ -51,8 +50,7 @@
}
@Override
- public KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
KotlinClassMetadata.MultiFileClassFacade.Writer writer =
new KotlinClassMetadata.MultiFileClassFacade.Writer();
List<String> partClassNameStrings = new ArrayList<>(partClassNames.size());
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
index 9470082..ca97d0b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMultiFileClassPartInfo.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import java.util.function.Consumer;
import kotlinx.metadata.KmPackage;
@@ -57,8 +56,7 @@
}
@Override
- public KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
KotlinClassMetadata.MultiFileClassPart.Writer writer =
new KotlinClassMetadata.MultiFileClassPart.Writer();
KmPackage kmPackage = new KmPackage();
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
index 3fab975..1ac03db 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPackageInfo.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import java.util.HashMap;
@@ -63,10 +62,7 @@
}
public void rewrite(
- KmPackage kmPackage,
- DexClass clazz,
- AppView<AppInfoWithLiveness> appView,
- NamingLens namingLens) {
+ KmPackage kmPackage, DexClass clazz, AppView<?> appView, NamingLens namingLens) {
containerInfo.rewrite(
kmPackage::visitFunction,
kmPackage::visitProperty,
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
index c718992..6fceb06 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinPropertyInfo.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
import kotlinx.metadata.KmProperty;
@@ -146,7 +145,7 @@
DexEncodedField field,
DexEncodedMethod getter,
DexEncodedMethod setter,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
// TODO(b/154348683): Flags again.
KmPropertyVisitor kmProperty = visitorProvider.get(flags, name, getterFlags, setterFlags);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
index 5af2a4c..79054f4 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClassInfo.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmLambda;
import kotlinx.metadata.jvm.KotlinClassHeader;
@@ -78,8 +77,7 @@
}
@Override
- public KotlinClassHeader rewrite(
- DexClass clazz, AppView<AppInfoWithLiveness> appView, NamingLens namingLens) {
+ public KotlinClassHeader rewrite(DexClass clazz, AppView<?> appView, NamingLens namingLens) {
Writer writer = new Writer();
if (lambda != null) {
KmLambda kmLambda = new KmLambda();
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
index bb75b7f..3ecbc2c 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeAliasInfo.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import java.util.List;
@@ -61,7 +60,7 @@
void rewrite(
KmVisitorProviders.KmTypeAliasVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
KmTypeAliasVisitor kmTypeAliasVisitor = visitorProvider.get(flags, name);
underlyingType.rewrite(kmTypeAliasVisitor::visitUnderlyingType, appView, namingLens);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
index f21db98..4e74391 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeInfo.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -32,7 +31,7 @@
private final KotlinTypeInfo outerType;
private final List<KotlinTypeProjectionInfo> arguments;
private final List<KotlinAnnotationInfo> annotations;
- private final KotlinFlexibleTypeUpperBoundInfo flexibleTypeUpperBoundInfo;
+ private final KotlinFlexibleTypeUpperBoundInfo flexibleTypeUpperBound;
KotlinTypeInfo(
int flags,
@@ -41,14 +40,14 @@
KotlinTypeInfo outerType,
List<KotlinTypeProjectionInfo> arguments,
List<KotlinAnnotationInfo> annotations,
- KotlinFlexibleTypeUpperBoundInfo flexibleTypeUpperBoundInfo) {
+ KotlinFlexibleTypeUpperBoundInfo flexibleTypeUpperBound) {
this.flags = flags;
this.classifier = classifier;
this.abbreviatedType = abbreviatedType;
this.outerType = outerType;
this.arguments = arguments;
this.annotations = annotations;
- this.flexibleTypeUpperBoundInfo = flexibleTypeUpperBoundInfo;
+ this.flexibleTypeUpperBound = flexibleTypeUpperBound;
}
static KotlinTypeInfo create(KmType kmType, DexItemFactory factory, Reporter reporter) {
@@ -80,7 +79,7 @@
public void rewrite(
KmVisitorProviders.KmTypeVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
// TODO(b/154348683): Check for correct flags
KmTypeVisitor kmTypeVisitor = visitorProvider.get(flags);
@@ -95,8 +94,7 @@
argument.rewrite(
kmTypeVisitor::visitArgument, kmTypeVisitor::visitStarProjection, appView, namingLens);
}
- flexibleTypeUpperBoundInfo.rewrite(
- kmTypeVisitor::visitFlexibleTypeUpperBound, appView, namingLens);
+ flexibleTypeUpperBound.rewrite(kmTypeVisitor::visitFlexibleTypeUpperBound, appView, namingLens);
if (annotations.isEmpty()) {
return;
}
@@ -119,7 +117,7 @@
outerType.trace(definitionSupplier);
}
forEachApply(arguments, argument -> argument::trace, definitionSupplier);
- flexibleTypeUpperBoundInfo.trace(definitionSupplier);
+ flexibleTypeUpperBound.trace(definitionSupplier);
forEachApply(annotations, annotation -> annotation::trace, definitionSupplier);
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
index 53c2eb2..d8457ed 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeParameterInfo.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -87,7 +86,7 @@
void rewrite(
KmVisitorProviders.KmTypeParameterVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
KmTypeParameterVisitor kmTypeParameterVisitor = visitorProvider.get(flags, name, id, variance);
for (KotlinTypeInfo originalUpperBound : originalUpperBounds) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
index 9ab3de0..1f2ce01 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeProjectionInfo.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import kotlinx.metadata.KmTypeProjection;
@@ -39,7 +38,7 @@
public void rewrite(
KmVisitorProviders.KmTypeProjectionVisitorProvider visitorProvider,
KmVisitorProviders.KmTypeStarProjectionVisitorProvider starProjectionProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
if (isStarProjection()) {
starProjectionProvider.get();
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
index dd2be72..088e7ec 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinTypeReference.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -58,7 +57,7 @@
}
String toRenamedDescriptorOrDefault(
- AppView<AppInfoWithLiveness> appView, NamingLens namingLens, String defaultValue) {
+ AppView<?> appView, NamingLens namingLens, String defaultValue) {
if (unknown != null) {
return unknown;
}
@@ -66,7 +65,8 @@
if (!known.isClassType()) {
return known.descriptor.toString();
}
- if (!appView.appInfo().isNonProgramTypeOrLiveProgramType(known)) {
+ if (appView.appInfo().hasLiveness()
+ && !appView.withLiveness().appInfo().isNonProgramTypeOrLiveProgramType(known)) {
return defaultValue;
}
DexString descriptor = namingLens.lookupDescriptor(known);
@@ -77,7 +77,7 @@
}
String toRenamedBinaryNameOrDefault(
- AppView<AppInfoWithLiveness> appView, NamingLens namingLens, String defaultValue) {
+ AppView<?> appView, NamingLens namingLens, String defaultValue) {
if (unknown != null) {
// Unknown values are always on the input form, so we can just return it.
return unknown;
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
index 83dd5d2..db54d35 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
@@ -69,7 +68,7 @@
void rewrite(
KmVisitorProviders.KmValueParameterVisitorProvider visitorProvider,
- AppView<AppInfoWithLiveness> appView,
+ AppView<?> appView,
NamingLens namingLens) {
KmValueParameterVisitor kmValueParameterVisitor = visitorProvider.get(flags, name);
type.rewrite(kmValueParameterVisitor::visitType, appView, namingLens);
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 182de8d..2ee7485 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.SubtypingInfo;
-import com.android.tools.r8.kotlin.KotlinMetadataRewriter;
import com.android.tools.r8.naming.ClassNameMinifier.ClassNamingStrategy;
import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
import com.android.tools.r8.naming.ClassNameMinifier.PackageNamingStrategy;
@@ -89,10 +88,6 @@
new IdentifierMinifier(appView, lens).run(executorService);
timing.end();
- timing.begin("MinifyKotlinMetadata");
- new KotlinMetadataRewriter(appView, lens).run(executorService);
- timing.end();
-
return lens;
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index 515d21f..57f63fa 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -19,7 +19,6 @@
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
-import com.android.tools.r8.kotlin.KotlinMetadataRewriter;
import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
@@ -175,10 +174,6 @@
new IdentifierMinifier(appView, lens).run(executorService);
timing.end();
- timing.begin("MinifyKotlinMetadata");
- new KotlinMetadataRewriter(appView, lens).run(executorService);
- timing.end();
-
return lens;
}
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index 0edcea8..af2b520 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -35,6 +35,13 @@
@Keep
public class Retrace {
+ // This is a slight modification of the default regular expression shown for proguard retrace
+ // that allow for retracing classes in the form <class>: lorem ipsum...
+ // Seems like Proguard retrace is expecting the form "Caused by: <class>".
+ public static final String DEFAULT_REGULAR_EXPRESSION =
+ "(?:.*?\\bat\\s+%c\\.%m\\s*\\(%s(?::%l)?\\)\\s*(?:~\\[.*\\])?)"
+ + "|(?:(?:(?:%c|.*)?[:\"]\\s+)?%c(?::.*)?)";
+
public static final String USAGE_MESSAGE =
StringUtils.lines(
"Usage: retrace <proguard-map> <stacktrace-file> [--regex <regexp>, --verbose, --info]",
@@ -45,6 +52,7 @@
Builder builder = RetraceCommand.builder(diagnosticsHandler);
boolean hasSetProguardMap = false;
boolean hasSetStackTrace = false;
+ boolean hasSetRegularExpression = false;
while (context.head() != null) {
Boolean help = OptionsParsing.tryParseBoolean(context, "--help");
if (help != null) {
@@ -63,6 +71,7 @@
String regex = OptionsParsing.tryParseSingle(context, "--regex", "r");
if (regex != null && !regex.isEmpty()) {
builder.setRegularExpression(regex);
+ hasSetRegularExpression = true;
continue;
}
if (!hasSetProguardMap) {
@@ -88,6 +97,9 @@
if (!hasSetStackTrace) {
builder.setStackTrace(getStackTraceFromStandardInput());
}
+ if (!hasSetRegularExpression) {
+ builder.setRegularExpression(DEFAULT_REGULAR_EXPRESSION);
+ }
return builder;
}
@@ -156,13 +168,30 @@
}
public static void run(String[] args) {
+ // To be compatible with standard retrace and remapper, we translate -arg into --arg.
+ String[] mappedArgs = new String[args.length];
+ boolean printInfo = false;
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg == null || arg.length() < 2) {
+ mappedArgs[i] = arg;
+ continue;
+ }
+ if (arg.charAt(0) == '-' && arg.charAt(1) != '-') {
+ mappedArgs[i] = "-" + arg;
+ } else {
+ mappedArgs[i] = arg;
+ }
+ if (mappedArgs[i].equals("--info")) {
+ printInfo = true;
+ }
+ }
RetraceDiagnosticsHandler retraceDiagnosticsHandler =
- new RetraceDiagnosticsHandler(
- new DiagnosticsHandler() {}, Arrays.asList(args).contains("--info"));
- Builder builder = parseArguments(args, retraceDiagnosticsHandler);
+ new RetraceDiagnosticsHandler(new DiagnosticsHandler() {}, printInfo);
+ Builder builder = parseArguments(mappedArgs, retraceDiagnosticsHandler);
if (builder == null) {
// --help was an argument to list
- assert Arrays.asList(args).contains("--help");
+ assert Arrays.asList(mappedArgs).contains("--help");
System.out.print(USAGE_MESSAGE);
return;
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java b/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java
index b561305..4973190 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java
@@ -390,7 +390,8 @@
}
// TODO(b/145731185): Extend support for identifiers with strings inside back ticks.
- private static final String javaIdentifierSegment = "[\\p{L}\\p{N}_\\p{Sc}]+";
+ private static final String javaIdentifierSegment =
+ "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
private abstract static class ClassNameGroup extends RegularExpressionGroup {
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 76c9e4c..e432e69 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2725,7 +2725,10 @@
Set<DexType> mainDexTypes = Sets.newIdentityHashSet();
boolean isEmpty() {
- boolean empty = syntheticInstantiations.isEmpty() && liveMethods.isEmpty();
+ boolean empty =
+ syntheticInstantiations.isEmpty()
+ && liveMethods.isEmpty()
+ && syntheticClasspathClasses.isEmpty();
assert !empty || (liveMethodsWithKeepActions.isEmpty() && mainDexTypes.isEmpty());
return empty;
}
@@ -2787,6 +2790,7 @@
enqueuer.markMethodAsTargeted(liveMethod, fakeReason);
enqueuer.enqueueMarkMethodLiveAction(liveMethod, fakeReason);
}
+ enqueuer.liveNonProgramTypes.addAll(syntheticClasspathClasses.values());
}
}
@@ -3099,21 +3103,8 @@
ProgramMethodSet callbacks = desugaredLibraryWrapperAnalysis.generateCallbackMethods();
callbacks.forEach(additions::addLiveMethod);
- // Generate the wrappers.
- List<DexProgramClass> wrappers = desugaredLibraryWrapperAnalysis.generateWrappers();
- for (DexProgramClass wrapper : wrappers) {
- additions.addInstantiatedClass(wrapper, null, false);
- // Mark all methods on the wrapper as live and targeted.
- for (DexEncodedMethod method : wrapper.methods()) {
- additions.addLiveMethod(new ProgramMethod(wrapper, method));
- }
- }
-
- // Add all vivified types as classpath classes.
- // They will be available at runtime in the desugared library dex file.
- desugaredLibraryWrapperAnalysis
- .generateWrappersSuperTypeMock(wrappers)
- .forEach(additions::addClasspathClass);
+ // Generate wrappers on classpath so types are defined.
+ desugaredLibraryWrapperAnalysis.generateWrappers(additions::addClasspathClass);
}
private void rewriteLambdaCallSites(
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 00853e0..8599b02 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -419,7 +419,8 @@
if (outputMode == OutputMode.DexIndexed) {
DexIndexedConsumer.ArchiveConsumer.writeResources(
archive, getDexProgramResourcesForTesting(), getDataEntryResourcesForTesting());
- } else if (outputMode == OutputMode.DexFilePerClassFile) {
+ } else if (outputMode == OutputMode.DexFilePerClassFile
+ || outputMode == OutputMode.DexFilePerClass) {
List<ProgramResource> resources = getDexProgramResourcesForTesting();
DexFilePerClassFileConsumer.ArchiveConsumer.writeResources(
archive, resources, programResourcesMainDescriptor);
diff --git a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
index 38cd73e..936395f 100644
--- a/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
+++ b/src/main/java/com/android/tools/r8/utils/CompileDumpCompatR8.java
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
-import static com.android.tools.r8.utils.FileUtils.isArchive;
-
import com.android.tools.r8.CompatProguardCommandBuilder;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.CompilationMode;
@@ -51,6 +49,14 @@
private static final List<String> VALID_OPTIONS_WITH_TWO_OPERANDS =
Arrays.asList("--feature-jar");
+ private static boolean FileUtils_isArchive(Path path) {
+ String name = path.getFileName().toString().toLowerCase();
+ return name.endsWith(".apk")
+ || name.endsWith(".jar")
+ || name.endsWith(".zip")
+ || name.endsWith(".aar");
+ }
+
public static void main(String[] args) throws CompilationFailedException {
boolean isCompatMode = false;
OutputMode outputMode = OutputMode.DexIndexed;
@@ -134,7 +140,7 @@
{
Path featureIn = Paths.get(firstOperand);
Path featureOut = Paths.get(secondOperand);
- if (!isArchive(featureIn)) {
+ if (!FileUtils_isArchive(featureIn)) {
throw new IllegalArgumentException(
"Expected an archive, got `" + featureIn.toString() + "`.");
}
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index e1572f5..367092b 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -308,8 +308,7 @@
// methods, we either did not rename them, we renamed them according to a supplied map or
// they may be bridges for interface methods with covariant return types.
sortMethods(methods);
- // TODO(b/149360203): Reenable assert.
- assert true || verifyMethodsAreKeptDirectlyOrIndirectly(appView, methods);
+ assert verifyMethodsAreKeptDirectlyOrIndirectly(appView, methods);
}
boolean identityMapping =
@@ -450,12 +449,15 @@
return true;
}
RootSet rootSet = appView.rootSet();
+ boolean allSeenAreInstanceInitializers = true;
DexString originalName = null;
for (DexEncodedMethod method : methods) {
// We cannot rename instance initializers.
if (method.isInstanceInitializer()) {
+ assert allSeenAreInstanceInitializers;
continue;
}
+ allSeenAreInstanceInitializers = false;
// If the method is pinned, we cannot minify it.
if (rootSet.mayNotBeMinified(method.method, appView)) {
continue;
@@ -474,7 +476,8 @@
}
String errorString = method.method.qualifiedName() + " is not kept but is overloaded";
assert lookupResult.getHolder().isInterface() : errorString;
- assert originalName == null || originalName.equals(method.method.name) : errorString;
+ // TODO(b/159113601): Reenable assert.
+ assert true || originalName == null || originalName.equals(method.method.name) : errorString;
originalName = method.method.name;
}
return true;
diff --git a/src/main/keep.txt b/src/main/keep.txt
index 7791d4e..84423da 100644
--- a/src/main/keep.txt
+++ b/src/main/keep.txt
@@ -10,6 +10,7 @@
-keep public class com.android.tools.r8.ExtractMarker { public static void main(java.lang.String[]); }
-keep public class com.android.tools.r8.dexsplitter.DexSplitter { public static void main(java.lang.String[]); }
+-keep public class com.android.tools.r8.Version { public static final java.lang.String LABEL; }
-keep public class com.android.tools.r8.Version { public static java.lang.String getVersionString(); }
-keep public class com.android.tools.r8.Version { public static int getMajorVersion(); }
-keep public class com.android.tools.r8.Version { public static int getMinorVersion(); }
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
index 8f57473..febd5e6 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
@@ -25,6 +25,8 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -409,8 +411,9 @@
try {
R8.run(
R8Command.builder(handler)
+ .setDisableTreeShaking(true)
.setMinApiLevel(minApiLevel)
- .setProgramConsumer(new R8ApiUsageSample.EnsureOutputConsumer())
+ .setProgramConsumer(new EnsureOutputConsumer())
.addLibraryFiles(libraries)
.addProgramFiles(inputs)
.addAssertionsConfiguration(b -> b.setScopeAll().setEnable().build())
@@ -558,6 +561,26 @@
}
private static void checkVersionApi() {
+ String labelValue;
+ int labelAccess;
+ try {
+ Field field = Version.class.getDeclaredField("LABEL");
+ labelAccess = field.getModifiers();
+ labelValue = (String) field.get(Version.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ if (!Modifier.isPublic(labelAccess)
+ || !Modifier.isStatic(labelAccess)
+ || !Modifier.isFinal(labelAccess)) {
+ throw new RuntimeException("Expected public static final LABEL");
+ }
+ if (labelValue.isEmpty()) {
+ throw new RuntimeException("Expected LABEL constant");
+ }
+ if (Version.LABEL.isEmpty()) {
+ throw new RuntimeException("Expected LABEL constant");
+ }
if (Version.getVersionString() == null) {
throw new RuntimeException("Expected getVersionString API");
}
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
index c5e44a3..846bc6b 100644
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
@@ -4,7 +4,9 @@
package com.android.tools.r8;
import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.FileUtils;
@@ -16,18 +18,26 @@
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Assert;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
-public class D8ApiBinaryCompatibilityTests {
+@RunWith(Parameterized.class)
+public class D8ApiBinaryCompatibilityTests extends TestBase {
- @Rule
- public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public D8ApiBinaryCompatibilityTests(TestParameters parameters) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ }
@Test
public void testCompatibility() throws IOException {
- Path jar = Paths.get("tests", "d8_api_usage_sample.jar");
+ Path jar = ToolHelper.API_SAMPLE_JAR;
String main = "com.android.tools.apiusagesample.D8ApiUsageSample";
int minApiLevel = AndroidApiLevel.K.getLevel();
@@ -79,7 +89,7 @@
ProcessBuilder builder = new ProcessBuilder(command);
ProcessResult result = ToolHelper.runProcess(builder);
- Assert.assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
+ assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
Assert.assertTrue(result.stdout, result.stdout.isEmpty());
Assert.assertTrue(result.stderr, result.stderr.isEmpty());
}
diff --git a/src/test/java/com/android/tools/r8/DiagnosticsMatcher.java b/src/test/java/com/android/tools/r8/DiagnosticsMatcher.java
index 70518d7..a800801 100644
--- a/src/test/java/com/android/tools/r8/DiagnosticsMatcher.java
+++ b/src/test/java/com/android/tools/r8/DiagnosticsMatcher.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.ExceptionDiagnostic;
+import org.hamcrest.CoreMatchers;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
@@ -71,15 +72,20 @@
}
public static Matcher<Diagnostic> diagnosticPosition(Position position) {
+ return diagnosticPosition(CoreMatchers.equalTo(position));
+ }
+
+ public static Matcher<Diagnostic> diagnosticPosition(Matcher<Position> positionMatcher) {
return new DiagnosticsMatcher() {
@Override
protected boolean eval(Diagnostic diagnostic) {
- return diagnostic.getPosition().equals(position);
+ return positionMatcher.matches(diagnostic.getPosition());
}
@Override
protected void explain(Description description) {
- description.appendText("position ").appendText(position.getDescription());
+ description.appendText("position ");
+ positionMatcher.describeTo(description);
}
};
}
diff --git a/src/test/java/com/android/tools/r8/PositionMatcher.java b/src/test/java/com/android/tools/r8/PositionMatcher.java
new file mode 100644
index 0000000..4fca1c6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/PositionMatcher.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, 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;
+
+import com.android.tools.r8.position.Position;
+import com.android.tools.r8.position.TextPosition;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+public abstract class PositionMatcher extends TypeSafeMatcher<Position> {
+
+ public static Matcher<Position> positionLine(int line) {
+ return new PositionMatcher() {
+ @Override
+ protected boolean matchesSafely(Position position) {
+ return position instanceof TextPosition && ((TextPosition) position).getLine() == line;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("with line " + line);
+ }
+ };
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
index 79017bc..954d773 100644
--- a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
@@ -6,6 +6,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.FileUtils;
@@ -16,17 +17,26 @@
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
-public class R8ApiBinaryCompatibilityTests {
+@RunWith(Parameterized.class)
+public class R8ApiBinaryCompatibilityTests extends TestBase {
- static final Path JAR = Paths.get("tests", "r8_api_usage_sample.jar");
+ static final Path JAR = ToolHelper.API_SAMPLE_JAR;
static final String MAIN = "com.android.tools.apiusagesample.R8ApiUsageSample";
static final AndroidApiLevel MIN_API = AndroidApiLevel.K;
- @Rule public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public R8ApiBinaryCompatibilityTests(TestParameters parameters) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ }
@Test
public void testCompatibility() throws IOException {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 3d00718..9ad7a70 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -120,6 +120,8 @@
public static final String JAVA_CLASSES_DIR = BUILD_DIR + "classes/java/";
public static final String JDK_11_TESTS_CLASSES_DIR = JAVA_CLASSES_DIR + "jdk11Tests/";
+ public static final Path API_SAMPLE_JAR = Paths.get("tests", "r8_api_usage_sample.jar");
+
public static final String LINE_SEPARATOR = StringUtils.LINE_SEPARATOR;
public static final String CLASSPATH_SEPARATOR = File.pathSeparator;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
new file mode 100644
index 0000000..54f3acb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BackwardsCompatibleSpecificationTest.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class BackwardsCompatibleSpecificationTest extends TestBase {
+
+ private static final List<String> RELEASES = ImmutableList.of("2.0.74");
+
+ @Parameterized.Parameters(name = "{1}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withNoneRuntime().build(), RELEASES);
+ }
+
+ private final Path desugaredLib = ToolHelper.getDesugarJDKLibs();
+ private final Path desugaredSpec = ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING;
+ private final String release;
+
+ public BackwardsCompatibleSpecificationTest(TestParameters parameters, String release) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ this.release = release;
+ }
+
+ private Path getReleaseJar() {
+ return Paths.get(ToolHelper.THIRD_PARTY_DIR, "r8-releases", release, "r8lib.jar");
+ }
+
+ @Test
+ public void test() throws Exception {
+ ProcessResult result =
+ ToolHelper.runJava(
+ getReleaseJar(),
+ "com.android.tools.r8.L8",
+ "--desugared-lib",
+ desugaredSpec.toString(),
+ desugaredLib.toString());
+ assertEquals(result.toString(), 0, result.exitCode);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java
new file mode 100644
index 0000000..3e819e2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibaryChecksumsTest.java
@@ -0,0 +1,69 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.L8;
+import com.android.tools.r8.L8Command;
+import com.android.tools.r8.OutputMode;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugaredLibaryChecksumsTest extends TestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public DesugaredLibaryChecksumsTest(TestParameters parameters) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path out = temp.newFolder().toPath().resolve("out.jar");
+ L8.run(
+ L8Command.builder()
+ .setIncludeClassesChecksum(true)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addProgramFiles(ToolHelper.getDesugarJDKLibs())
+ .addProgramFiles(ToolHelper.DESUGAR_LIB_CONVERSIONS)
+ .setMode(CompilationMode.DEBUG)
+ .addDesugaredLibraryConfiguration(
+ StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
+ .setMinApiLevel(AndroidApiLevel.B.getLevel())
+ .setOutput(out, OutputMode.DexIndexed)
+ .build());
+
+ try {
+ CodeInspector inspector = new CodeInspector(out);
+ for (FoundClassSubject clazz : inspector.allClasses()) {
+ assertTrue(clazz.getDexProgramClass().getChecksum() > 0);
+ }
+ } catch (CompilationError e) {
+ // TODO(b/158746302): Desugared library should support checksums.
+ // also, the failure should have occured in the L8.run above!
+ assertThat(e.getMessage(), containsString("has no checksum"));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
new file mode 100644
index 0000000..92fc7be
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryConfigurationParsingTest.java
@@ -0,0 +1,313 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticOrigin;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessages;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AbortException;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.StringUtils.BraceType;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugaredLibraryConfigurationParsingTest extends TestBase {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public DesugaredLibraryConfigurationParsingTest(TestParameters parameters) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ }
+
+ final AndroidApiLevel minApi = AndroidApiLevel.B;
+ final boolean libraryCompilation = true;
+
+ final DexItemFactory factory = new DexItemFactory();
+ final Origin origin =
+ new Origin(Origin.root()) {
+ @Override
+ public String part() {
+ return "Test Origin";
+ }
+ };
+
+ final Map<String, Object> TEMPLATE =
+ ImmutableMap.<String, Object>builder()
+ .put(
+ "configuration_format_version",
+ DesugaredLibraryConfigurationParser.MAX_SUPPORTED_VERSION)
+ .put("group_id", "com.tools.android")
+ .put("artifact_id", "desugar_jdk_libs")
+ .put("version", "0.0.0")
+ .put("required_compilation_api_level", 1)
+ .put("synthesized_library_classes_package_prefix", "j$.")
+ .put("common_flags", Collections.emptyList())
+ .put("program_flags", Collections.emptyList())
+ .put("library_flags", Collections.emptyList())
+ .build();
+
+ private LinkedHashMap<String, Object> template() {
+ return new LinkedHashMap<>(TEMPLATE);
+ }
+
+ private DesugaredLibraryConfigurationParser parser(DiagnosticsHandler handler) {
+ return new DesugaredLibraryConfigurationParser(
+ factory, new Reporter(handler), libraryCompilation, minApi.getLevel());
+ }
+
+ private DesugaredLibraryConfiguration runPassing(String resource) {
+ return runPassing(StringResource.fromString(resource, origin));
+ }
+
+ private DesugaredLibraryConfiguration runPassing(StringResource resource) {
+ TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
+ DesugaredLibraryConfiguration config = parser(handler).parse(resource);
+ handler.assertNoMessages();
+ return config;
+ }
+
+ private void runFailing(String json, Consumer<TestDiagnosticMessages> checker) {
+ TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
+ try {
+ parser(handler).parse(StringResource.fromString(json, origin));
+ fail("Expected failure");
+ } catch (AbortException e) {
+ checker.accept(handler);
+ }
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ // Just test that the reference file parses without issues.
+ DesugaredLibraryConfiguration config =
+ runPassing(StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING));
+ assertEquals(libraryCompilation, config.isLibraryCompilation());
+ }
+
+ @Test
+ public void testEmpty() {
+ runFailing(
+ "",
+ diagnostics -> {
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticMessage(containsString("Not a JSON Object")),
+ diagnosticOrigin(origin)));
+ });
+ }
+
+ @Test
+ public void testRequiredKeys() {
+ ImmutableList<String> requiredKeys =
+ ImmutableList.of(
+ "configuration_format_version",
+ "group_id",
+ "artifact_id",
+ "version",
+ "required_compilation_api_level",
+ "synthesized_library_classes_package_prefix",
+ "program_flags",
+ "library_flags");
+ for (String key : requiredKeys) {
+ Map<String, Object> data = template();
+ data.remove(key);
+ runFailing(
+ toJson(data),
+ diagnostics ->
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticMessage(containsString("Invalid desugared library configuration")),
+ diagnosticMessage(containsString("Expected required key '" + key + "'")),
+ diagnosticOrigin(origin))));
+ }
+ }
+
+ @Test
+ public void testUnsupportedFormatMissingFlags() {
+ LinkedHashMap<String, Object> data = template();
+ data.remove("common_flags");
+ runFailing(
+ toJson(data),
+ diagnostics ->
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticMessage(containsString("upgrade the desugared library")),
+ diagnosticOrigin(origin))));
+ }
+
+ @Test
+ public void testUnsupportedAbove() {
+ LinkedHashMap<String, Object> data = template();
+ data.put("configuration_format_version", 100000);
+ runFailing(
+ toJson(data),
+ diagnostics ->
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticMessage(containsString("upgrade the D8/R8 compiler")),
+ diagnosticOrigin(origin))));
+ }
+
+ @Test
+ public void testCustomAndWrapperOverlap() {
+ LinkedHashMap<String, Object> data = template();
+ data.put(
+ "common_flags",
+ ImmutableList.of(
+ ImmutableMap.of(
+ "api_level_below_or_equal",
+ 100000,
+ "custom_conversion",
+ ImmutableMap.of("java.util.Foo", "j$.util.FooConv"),
+ "wrapper_conversion",
+ ImmutableList.of("java.util.Foo"))));
+ runFailing(
+ toJson(data),
+ diagnostics ->
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticMessage(containsString("Duplicate types")),
+ diagnosticMessage(containsString("java.util.Foo")),
+ diagnosticOrigin(origin))));
+ }
+
+ @Test
+ public void testRedefinition() {
+ LinkedHashMap<String, Object> data = template();
+ data.put(
+ "common_flags",
+ ImmutableList.of(
+ ImmutableMap.of(
+ "api_level_below_or_equal",
+ 100000,
+ "custom_conversion",
+ ImmutableMap.of("java.util.Foo", "j$.util.FooConv1"))));
+ data.put(
+ "library_flags",
+ ImmutableList.of(
+ ImmutableMap.of(
+ "api_level_below_or_equal",
+ 100000,
+ "custom_conversion",
+ ImmutableMap.of("java.util.Foo", "j$.util.FooConv2"))));
+ runFailing(
+ toJson(data),
+ diagnostics ->
+ diagnostics.assertErrorsMatch(
+ allOf(
+ diagnosticMessage(containsString("Duplicate assignment of key")),
+ diagnosticMessage(containsString("java.util.Foo")),
+ diagnosticMessage(containsString("custom_conversion")),
+ diagnosticOrigin(origin))));
+ }
+
+ @Test
+ public void testDuplicate() {
+ LinkedHashMap<String, Object> data = template();
+ data.put(
+ "common_flags",
+ ImmutableList.of(
+ ImmutableMap.of(
+ "api_level_below_or_equal",
+ 100000,
+ "custom_conversion",
+ ImmutableMap.of(
+ "java.util.Foo", "j$.util.FooConv1",
+ "java.util.Foo2", "j$.util.FooConv2"))));
+ // The gson parser will overwrite the key in order during parsing, thus hiding potential issues.
+ DesugaredLibraryConfiguration config = runPassing(toJson(data).replace("Foo2", "Foo"));
+ assertEquals(
+ Collections.singletonList("java.util.Foo"),
+ config.getCustomConversions().keySet().stream()
+ .map(DexType::toString)
+ .collect(Collectors.toList()));
+ assertEquals(
+ Collections.singletonList("j$.util.FooConv2"),
+ config.getCustomConversions().values().stream()
+ .map(DexType::toString)
+ .collect(Collectors.toList()));
+ }
+
+ // JSON building helpers.
+ // This does not use gson to make the text input construction independent of gson.
+
+ private static String toJson(Map<String, Object> data) {
+ StringBuilder builder = new StringBuilder();
+ toJsonObject(data, builder);
+ return builder.toString();
+ }
+
+ private static void toJsonObject(Map<String, Object> data, StringBuilder builder) {
+ StringUtils.append(
+ builder,
+ ListUtils.map(
+ data.entrySet(),
+ entry -> "\n " + quote(entry.getKey()) + ": " + toJsonElement(entry.getValue())),
+ ", ",
+ BraceType.TUBORG);
+ }
+
+ private static String toJsonElement(Object element) {
+ StringBuilder builder = new StringBuilder();
+ toJsonElement(element, builder);
+ return builder.toString();
+ }
+
+ private static void toJsonElement(Object element, StringBuilder builder) {
+ if (element instanceof String) {
+ builder.append(quote((String) element));
+ } else if (element instanceof Integer) {
+ builder.append(element);
+ } else if (element instanceof List) {
+ toJsonList((List<Object>) element, builder);
+ } else if (element instanceof Map) {
+ toJsonObject((Map<String, Object>) element, builder);
+ } else {
+ throw new IllegalStateException("Unexpected object type: " + element.getClass());
+ }
+ }
+
+ private static void toJsonList(List<Object> element, StringBuilder builder) {
+ StringUtils.append(
+ builder, ListUtils.map(element, o -> "\n " + toJsonElement(o)), ", ", BraceType.SQUARE);
+ }
+
+ private static String quote(String str) {
+ return "\"" + str + "\"";
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
new file mode 100644
index 0000000..c1c4ce3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.time.LocalDate;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class DesugaredLocalDateReflectedTypePassedToStaticType extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+ private static final String EXPECTED = StringUtils.lines("1992");
+
+ @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(), BooleanUtils.values());
+ }
+
+ public DesugaredLocalDateReflectedTypePassedToStaticType(
+ TestParameters parameters, boolean shrinkDesugaredLibrary) {
+ this.parameters = parameters;
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ D8TestRunResult runResult =
+ testForD8()
+ .addInnerClasses(DesugaredLocalDateReflectedTypePassedToStaticType.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class);
+ if (shrinkDesugaredLibrary && parameters.getApiLevel().isLessThan(AndroidApiLevel.O)) {
+ runResult.assertFailureWithErrorThatMatches(
+ containsString("java.lang.NoSuchMethodException"));
+ } else {
+ runResult.assertSuccessWithOutput(EXPECTED);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ R8TestRunResult runResult =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(DesugaredLocalDateReflectedTypePassedToStaticType.class)
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class);
+ if (shrinkDesugaredLibrary && parameters.getApiLevel().isLessThan(AndroidApiLevel.O)) {
+ runResult.assertFailureWithErrorThatMatches(
+ containsString("java.lang.NoSuchMethodException"));
+ } else {
+ runResult.assertSuccessWithOutput(EXPECTED);
+ }
+ }
+
+ public static class Main {
+
+ public static void printYear(LocalDate date) {
+ System.out.println(date.getYear());
+ }
+
+ public static void main(String[] args) throws Exception {
+ LocalDate date =
+ (LocalDate)
+ LocalDate.class
+ .getMethod("of", int.class, int.class, int.class)
+ .invoke(null, 1992, 1, 1);
+ printYear(date);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java
new file mode 100644
index 0000000..980c9ff
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java
@@ -0,0 +1,98 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class DesugaredLocalDateReflectionTest extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+ private static final String EXPECTED = StringUtils.lines("1992");
+
+ @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(), BooleanUtils.values());
+ }
+
+ public DesugaredLocalDateReflectionTest(
+ TestParameters parameters, boolean shrinkDesugaredLibrary) {
+ this.parameters = parameters;
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ D8TestRunResult runResult =
+ testForD8()
+ .addInnerClasses(DesugaredLocalDateReflectionTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.getRuntime().asDex().getVm().isNewerThan(DexVm.ART_7_0_0_HOST)) {
+ runResult.assertSuccessWithOutput(EXPECTED);
+ } else {
+ runResult.assertFailureWithErrorThatMatches(
+ containsString("java.lang.ClassNotFoundException: java.time.LocalDate"));
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ R8TestRunResult runResult =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(DesugaredLocalDateReflectionTest.class)
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.getRuntime().asDex().getVm().isNewerThan(DexVm.ART_7_0_0_HOST)) {
+ runResult.assertSuccessWithOutput(EXPECTED);
+ } else {
+ runResult.assertFailureWithErrorThatMatches(
+ containsString("java.lang.ClassNotFoundException: java.time.LocalDate"));
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) throws Exception {
+ Class<?> localDateClass =
+ Class.forName(System.nanoTime() > 0 ? "java.time.LocalDate" : "java.lang.Object");
+ Object localDate =
+ localDateClass.getMethod("of", int.class, int.class, int.class).invoke(null, 1992, 1, 1);
+ System.out.println(localDateClass.getMethod("getYear").invoke(localDate));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
new file mode 100644
index 0000000..f56829c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
@@ -0,0 +1,105 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.time.LocalDate;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class DesugaredReflectedDesugaredTypePassedToStaticTypeTest
+ extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+ private static final String EXPECTED = StringUtils.lines("1992", "1992");
+
+ @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(), BooleanUtils.values());
+ }
+
+ public DesugaredReflectedDesugaredTypePassedToStaticTypeTest(
+ TestParameters parameters, boolean shrinkDesugaredLibrary) {
+ this.parameters = parameters;
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ D8TestRunResult runResult =
+ testForD8()
+ .addInnerClasses(DesugaredReflectedDesugaredTypePassedToStaticTypeTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)) {
+ runResult.assertFailureWithErrorThatMatches(
+ containsString("java.lang.ClassNotFoundException: j$.time.LocalDate"));
+ } else {
+ runResult.assertSuccessWithOutput(EXPECTED);
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ R8TestRunResult runResult =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(DesugaredReflectedDesugaredTypePassedToStaticTypeTest.class)
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)) {
+ runResult.assertFailureWithErrorThatMatches(
+ containsString("java.lang.ClassNotFoundException: j$.time.LocalDate"));
+ } else {
+ runResult.assertSuccessWithOutput(EXPECTED);
+ }
+ }
+
+ public static class Main {
+
+ public static void printYear(LocalDate date) {
+ System.out.println(date.getYear());
+ }
+
+ public static void main(String[] args) throws Exception {
+ printYear(LocalDate.of(1992, 1, 1));
+ printYear(
+ (LocalDate)
+ Class.forName("j$.time.LocalDate")
+ .getMethod("of", int.class, int.class, int.class)
+ .invoke(null, 1992, 1, 1));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
new file mode 100644
index 0000000..846b65d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ExtractWrapperTypesTest.java
@@ -0,0 +1,304 @@
+// Copyright (c) 2020, 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.desugar.desugaredlibrary;
+
+import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.GenerateLintFiles;
+import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.NoneRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.WorkList;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ExtractWrapperTypesTest extends TestBase {
+
+ // Filter on types that do not need to be considered for wrapping.
+ private static boolean doesNotNeedWrapper(String type, Set<String> customConversions) {
+ return excludePackage(type)
+ || NOT_NEEDED_NOT_IN_DOCS.contains(type)
+ || FINAL_CLASSES.contains(type)
+ || customConversions.contains(type);
+ }
+
+ private static boolean excludePackage(String type) {
+ return type.startsWith("java.lang.")
+ || type.startsWith("java.nio.")
+ || type.startsWith("java.security.")
+ || type.startsWith("java.net.")
+ || type.startsWith("java.awt.")
+ || type.startsWith("java.util.concurrent.");
+ }
+
+ // Types not picked up by the android.jar scan but for which wrappers are needed.
+ private static final Set<String> ADDITIONAL_WRAPPERS = ImmutableSet.of();
+
+ // Types not in API docs, referenced in android.jar and must be wrapped.
+ private static final Set<String> NEEDED_BUT_NOT_IN_DOCS = ImmutableSet.of();
+
+ // Types not in API docs, referenced in android.jar but need not be wrapped.
+ private static final Set<String> NOT_NEEDED_NOT_IN_DOCS =
+ ImmutableSet.of(
+ "java.util.Base64$Decoder",
+ "java.util.Base64$Encoder",
+ "java.util.Calendar$Builder",
+ "java.util.Locale$Builder",
+ "java.util.Locale$Category",
+ "java.util.Locale$FilteringMode",
+ "java.util.SplittableRandom");
+
+ // List of referenced final classes (cannot be wrapper converted) with no custom conversions.
+ private static final Set<String> FINAL_CLASSES =
+ ImmutableSet.of(
+ // TODO(b/159304624): Does this need custom conversion?
+ "java.time.Period");
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ // TODO: parameterize to check both api<=23 as well as 23<api<26 for which the spec differs.
+ private final AndroidApiLevel minApi = AndroidApiLevel.B;
+ private final AndroidApiLevel targetApi = AndroidApiLevel.Q;
+
+ public ExtractWrapperTypesTest(TestParameters parameters) {
+ assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
+ }
+
+ @Test
+ public void checkConsistency() {
+ List<Set<String>> sets =
+ ImmutableList.of(
+ ADDITIONAL_WRAPPERS, NEEDED_BUT_NOT_IN_DOCS, NOT_NEEDED_NOT_IN_DOCS, FINAL_CLASSES);
+ for (Set<String> set1 : sets) {
+ for (Set<String> set2 : sets) {
+ if (set1 != set2) {
+ assertEquals(Collections.emptySet(), Sets.intersection(set1, set2));
+ }
+ }
+ }
+ for (Set<String> set : sets) {
+ for (String type : set) {
+ assertFalse(excludePackage(type));
+ }
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ CodeInspector desugaredApiJar = getDesugaredApiJar();
+ Set<ClassReference> preDesugarTypes = getPreDesugarTypes();
+
+ DesugaredLibraryConfiguration conf = getDesugaredLibraryConfiguration();
+ Set<String> wrappersInSpec =
+ conf.getWrapperConversions().stream().map(DexType::toString).collect(Collectors.toSet());
+ Set<String> customConversionsInSpec =
+ conf.getCustomConversions().keySet().stream()
+ .map(DexType::toString)
+ .collect(Collectors.toSet());
+ assertEquals(
+ Collections.emptySet(), Sets.intersection(wrappersInSpec, customConversionsInSpec));
+ assertEquals(Collections.emptySet(), Sets.intersection(FINAL_CLASSES, customConversionsInSpec));
+
+ CodeInspector nonDesugaredJar = new CodeInspector(ToolHelper.getAndroidJar(targetApi));
+ Map<ClassReference, Set<MethodReference>> directWrappers =
+ getDirectlyReferencedWrapperTypes(
+ desugaredApiJar, preDesugarTypes, nonDesugaredJar, customConversionsInSpec);
+ Map<ClassReference, Set<ClassReference>> indirectWrappers =
+ getIndirectlyReferencedWrapperTypes(
+ directWrappers, preDesugarTypes, nonDesugaredJar, customConversionsInSpec);
+
+ {
+ Set<String> missingWrappers = getMissingWrappers(directWrappers, wrappersInSpec);
+ assertTrue(
+ "Missing direct wrappers:\n" + String.join("\n", missingWrappers),
+ missingWrappers.isEmpty());
+ }
+
+ {
+ Set<String> missingWrappers = getMissingWrappers(indirectWrappers, wrappersInSpec);
+ assertTrue(
+ "Missing indirect wrappers:\n" + String.join("\n", missingWrappers),
+ missingWrappers.isEmpty());
+ }
+
+ Set<String> additionalWrappers = new TreeSet<>();
+ for (String wrapper : wrappersInSpec) {
+ ClassReference item = Reference.classFromTypeName(wrapper);
+ if (!directWrappers.containsKey(item)
+ && !indirectWrappers.containsKey(item)
+ && !ADDITIONAL_WRAPPERS.contains(wrapper)) {
+ additionalWrappers.add(wrapper);
+ }
+ }
+ assertTrue(
+ "Additional wrapper:\n" + String.join("\n", additionalWrappers),
+ additionalWrappers.isEmpty());
+
+ assertEquals(
+ directWrappers.size() + indirectWrappers.size() + ADDITIONAL_WRAPPERS.size(),
+ wrappersInSpec.size());
+ }
+
+ private static <T> Set<String> getMissingWrappers(
+ Map<ClassReference, Set<T>> expected, Set<String> wrappersInSpec) {
+ Set<String> missingWrappers = new TreeSet<>();
+ for (ClassReference addition : expected.keySet()) {
+ String item = descriptorToJavaType(addition.getDescriptor());
+ if (!wrappersInSpec.contains(item)) {
+ missingWrappers.add(item + " referenced from: " + expected.get(addition));
+ }
+ }
+ return missingWrappers;
+ }
+
+ private DesugaredLibraryConfiguration getDesugaredLibraryConfiguration() {
+ DesugaredLibraryConfigurationParser parser =
+ new DesugaredLibraryConfigurationParser(
+ new DexItemFactory(), null, true, minApi.getLevel());
+ return parser.parse(StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING));
+ }
+
+ private Map<ClassReference, Set<MethodReference>> getDirectlyReferencedWrapperTypes(
+ CodeInspector desugaredApiJar,
+ Set<ClassReference> preDesugarTypes,
+ CodeInspector nonDesugaredJar,
+ Set<String> customConversions) {
+ Map<ClassReference, Set<MethodReference>> directWrappers = new HashMap<>();
+ nonDesugaredJar.forAllClasses(
+ clazz -> {
+ clazz.forAllMethods(
+ method -> {
+ if (!method.isPublic() && !method.isProtected()) {
+ return;
+ }
+ if (desugaredApiJar.method(method.asMethodReference()).isPresent()) {
+ return;
+ }
+ Consumer<ClassReference> adder =
+ t ->
+ directWrappers
+ .computeIfAbsent(t, k -> new HashSet<>())
+ .add(method.asMethodReference());
+ MethodSignature signature = method.getFinalSignature().asMethodSignature();
+ addType(adder, signature.type, preDesugarTypes, customConversions);
+ for (String parameter : signature.parameters) {
+ addType(adder, parameter, preDesugarTypes, customConversions);
+ }
+ });
+ });
+ return directWrappers;
+ }
+
+ private Map<ClassReference, Set<ClassReference>> getIndirectlyReferencedWrapperTypes(
+ Map<ClassReference, Set<MethodReference>> directWrappers,
+ Set<ClassReference> existing,
+ CodeInspector latest,
+ Set<String> customConversions) {
+ Map<ClassReference, Set<ClassReference>> indirectWrappers = new HashMap<>();
+ WorkList<ClassReference> worklist = WorkList.newEqualityWorkList(directWrappers.keySet());
+ while (worklist.hasNext()) {
+ ClassReference reference = worklist.next();
+ ClassSubject clazz = latest.clazz(reference);
+ clazz.forAllVirtualMethods(
+ method -> {
+ assertTrue(method.toString(), method.isPublic() || method.isProtected());
+ MethodSignature signature = method.getFinalSignature().asMethodSignature();
+ Consumer<ClassReference> adder =
+ t -> {
+ if (worklist.addIfNotSeen(t)) {
+ indirectWrappers.computeIfAbsent(t, k -> new HashSet<>()).add(reference);
+ }
+ };
+ addType(adder, signature.type, existing, customConversions);
+ for (String parameter : signature.parameters) {
+ addType(adder, parameter, existing, customConversions);
+ }
+ });
+ }
+ return indirectWrappers;
+ }
+
+ private Set<ClassReference> getPreDesugarTypes() throws IOException {
+ Set<ClassReference> existing = new HashSet<>();
+ Path androidJar = ToolHelper.getAndroidJar(minApi);
+ new CodeInspector(androidJar)
+ .forAllClasses(
+ clazz -> {
+ if (clazz.getFinalName().startsWith("java.")) {
+ existing.add(Reference.classFromTypeName(clazz.getFinalName()));
+ }
+ });
+ return existing;
+ }
+
+ private CodeInspector getDesugaredApiJar() throws Exception {
+ Path out = temp.newFolder().toPath();
+ GenerateLintFiles desugaredApi =
+ new GenerateLintFiles(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING.toString(), out.toString());
+ desugaredApi.run(targetApi.getLevel());
+ return new CodeInspector(
+ out.resolve("compile_api_level_" + targetApi.getLevel())
+ .resolve("desugared_apis_" + targetApi.getLevel() + "_" + minApi.getLevel() + ".jar"));
+ }
+
+ private void addType(
+ Consumer<ClassReference> additions,
+ String type,
+ Set<ClassReference> preDesugarTypes,
+ Set<String> customConversions) {
+ if (type.equals("void")) {
+ return;
+ }
+ TypeReference typeReference = Reference.typeFromTypeName(type);
+ if (typeReference.isArray()) {
+ typeReference = typeReference.asArray().getBaseType();
+ }
+ if (typeReference.isClass()) {
+ ClassReference clazz = typeReference.asClass();
+ String clazzType = descriptorToJavaType(clazz.getDescriptor());
+ if (clazzType.startsWith("java.")
+ && !doesNotNeedWrapper(clazzType, customConversions)
+ && !preDesugarTypes.contains(clazz)) {
+ additions.accept(clazz);
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
index 3cb6218..23d3658 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
@@ -6,18 +6,26 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.CheckCastInstructionSubject;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
-import java.util.Iterator;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.android.tools.r8.utils.codeinspector.TryCatchSubject;
+import com.android.tools.r8.utils.codeinspector.TypeSubject;
+import com.google.common.collect.ImmutableSet;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -28,7 +36,8 @@
private final TestParameters parameters;
private final boolean shrinkDesugaredLibrary;
- private static final String expectedOutput = StringUtils.lines("Hello, world");
+ private static final String expectedOutput =
+ StringUtils.lines("Caught java.time.format.DateTimeParseException", "true", "Hello, world");
@Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
public static List<Object[]> data() {
@@ -47,15 +56,52 @@
}
private void checkRewrittenInvokes(CodeInspector inspector) {
+ Set<String> expectedInvokeHolders;
+ Set<String> expectedCatchGuards;
+ Set<String> expectedCheckCastType;
+ String expectedInstanceOfTypes;
if (parameters.getApiLevel().getLevel() >= 26) {
- return;
+ expectedInvokeHolders =
+ ImmutableSet.of("java.time.Clock", "java.time.LocalDate", "java.time.ZoneOffset");
+ expectedCatchGuards = ImmutableSet.of("java.time.format.DateTimeParseException");
+ expectedCheckCastType = ImmutableSet.of("java.time.ZoneId");
+ expectedInstanceOfTypes = "java.time.ZoneOffset";
+ } else {
+ expectedInvokeHolders =
+ ImmutableSet.of("j$.time.Clock", "j$.time.LocalDate", "j$.time.ZoneOffset");
+ expectedCatchGuards = ImmutableSet.of("j$.time.format.DateTimeParseException");
+ expectedCheckCastType = ImmutableSet.of("j$.time.ZoneId");
+ expectedInstanceOfTypes = "j$.time.ZoneOffset";
}
ClassSubject classSubject = inspector.clazz(TestClass.class);
assertThat(classSubject, isPresent());
- Iterator<InvokeInstructionSubject> iterator =
- classSubject.uniqueMethodWithName("main").iterateInstructions(InstructionSubject::isInvoke);
- InvokeInstructionSubject invoke = iterator.next();
- assertTrue(invoke.holder().is("j$.time.Clock"));
+ MethodSubject main = classSubject.uniqueMethodWithName("main");
+ Set<String> foundInvokeHolders =
+ main.streamInstructions()
+ .filter(InstructionSubject::isInvoke)
+ .map(
+ instructionSubject ->
+ ((InvokeInstructionSubject) instructionSubject).holder().toString())
+ .filter(holder -> holder.startsWith("j$.time.") || holder.startsWith("java.time."))
+ .collect(Collectors.toSet());
+ assertEquals(expectedInvokeHolders, foundInvokeHolders);
+ main.streamInstructions()
+ .filter(InstructionSubject::isCheckCast)
+ .map(InstructionSubject::asCheckCast)
+ .map(CheckCastInstructionSubject::getType)
+ .map(DexType::toSourceString)
+ .collect(Collectors.toSet())
+ .equals(expectedCheckCastType);
+ assertEquals(
+ 1,
+ main.streamInstructions().filter(io -> io.isInstanceOf(expectedInstanceOfTypes)).count());
+
+ Set<String> foundCatchGuards =
+ main.streamTryCatches()
+ .flatMap(TryCatchSubject::streamGuards)
+ .map(TypeSubject::toString)
+ .collect(Collectors.toSet());
+ assertEquals(expectedCatchGuards, foundCatchGuards);
}
@Test
@@ -84,6 +130,7 @@
.addKeepMainRule(TestClass.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .enableInliningAnnotations()
.compile()
.inspect(this::checkRewrittenInvokes)
.addDesugaredCoreLibraryRunClassPath(
@@ -97,8 +144,28 @@
static class TestClass {
+ @NeverInline
+ public static Object newObjectInstance() {
+ return System.currentTimeMillis() > 0 ? new Object() : null;
+ }
+
+ @NeverInline
+ public static Object nullReference() {
+ return System.currentTimeMillis() > 0 ? null : new Object();
+ }
+
public static void main(String[] args) {
java.time.Clock.systemDefaultZone();
+ try {
+ java.time.LocalDate.parse("");
+ } catch (java.time.format.DateTimeParseException e) {
+ System.out.println("Caught java.time.format.DateTimeParseException");
+ }
+ java.time.ZoneId id = (java.time.ZoneId) nullReference();
+ if (newObjectInstance() instanceof java.time.ZoneOffset) {
+ System.out.println("NOT!");
+ }
+ System.out.println(java.time.ZoneOffset.getAvailableZoneIds().size() > 0);
System.out.println("Hello, world");
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java
index 579b6f6..ad8e74c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java
@@ -31,7 +31,7 @@
private static final AndroidApiLevel MIN_SUPPORTED = AndroidApiLevel.N;
private static final String EXPECTED_RESULT =
StringUtils.lines(
- "[5, 6, 7]", "$r8$wrapper$java$util$stream$IntStream$-V-WRP", "IntSummaryStatistics");
+ "[5, 6, 7]", "j$.$r8$wrapper$java$util$stream$IntStream$-V-WRP", "IntSummaryStatistics");
@Parameters(name = "{0}, shrinkDesugaredLibrary: {1}")
public static List<Object[]> data() {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java
index 4581211..382f55d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java
@@ -57,6 +57,7 @@
.addLibraryClasses(CustomLibClass.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
+ .assertNoMessages()
.addDesugaredCoreLibraryRunClassPath(
this::buildDesugaredLibrary,
parameters.getApiLevel(),
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
index 3d1b999..e8aa581 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -21,8 +20,7 @@
import java.util.function.IntSupplier;
import java.util.function.LongConsumer;
import java.util.function.LongSupplier;
-import org.junit.Assert;
-import org.junit.Assume;
+import java.util.function.Supplier;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -70,6 +68,7 @@
.addLibraryClasses(CustomLibClass.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
+ .assertNoMessages()
.addDesugaredCoreLibraryRunClassPath(
this::buildDesugaredLibrary,
parameters.getApiLevel(),
@@ -101,43 +100,6 @@
.assertSuccessWithOutput(EXPECTED_RESULT);
}
- @Test
- public void testWrapperWithChecksum() throws Exception {
- Assume.assumeTrue(
- shrinkDesugaredLibrary && parameters.getApiLevel().getLevel() <= MIN_SUPPORTED.getLevel());
- testForD8()
- .addProgramClasses(
- Executor.class, Executor.Object1.class, Executor.Object2.class, Executor.Object3.class)
- .addLibraryClasses(CustomLibClass.class)
- .setMinApi(parameters.getApiLevel())
- .enableCoreLibraryDesugaring(parameters.getApiLevel())
- .setIncludeClassesChecksum(true) // Compilation fails if some classes are missing checksum.
- .compile()
- .inspect(
- inspector -> {
- Assert.assertEquals(
- 9,
- inspector.allClasses().stream()
- .filter(
- clazz ->
- clazz
- .getFinalName()
- .contains(DesugaredLibraryWrapperSynthesizer.TYPE_WRAPPER_SUFFIX))
- .count());
- Assert.assertEquals(
- 9,
- inspector.allClasses().stream()
- .filter(
- clazz ->
- clazz
- .getFinalName()
- .contains(
- DesugaredLibraryWrapperSynthesizer
- .VIVIFIED_TYPE_WRAPPER_SUFFIX))
- .count());
- });
- }
-
static class Executor {
public static void main(String[] args) {
@@ -146,16 +108,16 @@
BiFunction<String, String, Character> biFunction =
CustomLibClass.mixBiFunctions((String i, String j) -> i + j, (String s) -> s.charAt(1));
System.out.println(biFunction.apply("1", "2"));
- BooleanSupplier booleanSupplier = CustomLibClass.mixBoolSuppliers(() -> true, () -> false);
+ BooleanSupplier booleanSupplier =
+ () -> CustomLibClass.mixBoolSuppliers(() -> true, () -> false).get();
System.out.println(booleanSupplier.getAsBoolean());
LongConsumer longConsumer = CustomLibClass.mixLong(() -> 1L, System.out::println);
longConsumer.accept(2L);
DoublePredicate doublePredicate =
CustomLibClass.mixPredicate(d -> d > 1.0, d -> d == 2.0, d -> d < 3.0);
System.out.println(doublePredicate.test(2.0));
- // Reverse wrapper should not exist.
System.out.println(CustomLibClass.extractInt(() -> 5));
- System.out.println(CustomLibClass.getDoubleSupplier().getAsDouble());
+ System.out.println(CustomLibClass.getDoubleSupplier().get());
}
static class Object1 {}
@@ -203,13 +165,18 @@
return operator.andThen(function);
}
- public static BooleanSupplier mixBoolSuppliers(
- BooleanSupplier supplier1, BooleanSupplier supplier2) {
- return () -> supplier1.getAsBoolean() && supplier2.getAsBoolean();
+ // BooleanSupplier is not a wrapped type, so it can't be placed on the boundary.
+ public static Supplier<Boolean> mixBoolSuppliers(
+ Supplier<Boolean> supplier1, Supplier<Boolean> supplier2) {
+ BooleanSupplier wrap1 = supplier1::get;
+ BooleanSupplier wrap2 = supplier2::get;
+ return () -> wrap1.getAsBoolean() && wrap2.getAsBoolean();
}
- public static LongConsumer mixLong(LongSupplier supplier, LongConsumer consumer) {
- return l -> consumer.accept(l + supplier.getAsLong());
+ // LongSupplier is not a wrapped type, so it can't be placed on the boundary.
+ public static LongConsumer mixLong(Supplier<Long> supplier, LongConsumer consumer) {
+ LongSupplier wrap = supplier::get;
+ return l -> consumer.accept(l + wrap.getAsLong());
}
public static DoublePredicate mixPredicate(
@@ -217,12 +184,16 @@
return predicate1.and(predicate2).and(predicate3);
}
- public static int extractInt(IntSupplier supplier) {
- return supplier.getAsInt();
+ // IntSupplier is not a wrapped type, so it can't be placed on the boundary.
+ public static int extractInt(Supplier<Integer> supplier) {
+ IntSupplier wrap = supplier::get;
+ return wrap.getAsInt();
}
- public static DoubleSupplier getDoubleSupplier() {
- return () -> 42.0;
+ // DoubleSupplier is not a wrapped type, so it can't be placed on the boundary.
+ public static Supplier<Double> getDoubleSupplier() {
+ DoubleSupplier supplier = () -> 42.0;
+ return supplier::getAsDouble;
}
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperMergeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java
similarity index 72%
rename from src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperMergeTest.java
rename to src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java
index 9a29671..cbab10c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperMergeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestParameters;
@@ -17,19 +17,17 @@
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
-import com.google.common.collect.Sets;
-import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
-import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
-import java.util.Set;
+import java.util.stream.Stream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
-public class WrapperMergeTest extends DesugaredLibraryTestBase {
+public class WrapperPlacementTest extends DesugaredLibraryTestBase {
private static final String EXPECTED = StringUtils.lines("[1, 2, 3]", "[2, 3, 4]");
@@ -40,7 +38,7 @@
private final TestParameters parameters;
- public WrapperMergeTest(TestParameters parameters) {
+ public WrapperPlacementTest(TestParameters parameters) {
this.parameters = parameters;
}
@@ -57,21 +55,28 @@
}
@Test
- public void testWrapperMerge() throws Exception {
+ public void testNoWrappers() throws Exception {
assumeTrue(parameters.isDexRuntime());
- // Multiple wrapper classes have to be merged here.
+ // No wrappers are made during program compilation.
Path path1 = compileWithCoreLibraryDesugaring(MyArrays1.class);
Path path2 = compileWithCoreLibraryDesugaring(MyArrays2.class);
testForD8()
- .addProgramFiles(path1, path2)
.addProgramClasses(TestClass.class)
.addAndroidBuildVersion()
.enableCoreLibraryDesugaring(parameters.getApiLevel())
.setMinApi(parameters.getApiLevel())
.compile()
- .inspect(this::assertWrappers)
- .inspect(this::assertNoDuplicates)
- .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, parameters.getApiLevel())
+ .inspect(this::assertNoWrappers)
+ .apply(
+ b -> {
+ if (!hasNativeIntUnaryOperator()) {
+ Path coreLib = buildDesugaredLibrary(parameters.getApiLevel());
+ assertCoreLibContainsWrappers(coreLib);
+ b.addRunClasspathFiles(coreLib);
+ }
+ })
+ // The previous compilations are appended to the classpath (no merge).
+ .addRunClasspathFiles(path1, path2)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(EXPECTED);
}
@@ -82,34 +87,29 @@
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
.compile()
- .inspect(this::assertWrappers)
+ .inspect(this::assertNoWrappers)
.writeToZip();
}
- private void assertNoDuplicates(CodeInspector inspector) {
- Object2ReferenceMap<String, Set<FoundClassSubject>> map = new Object2ReferenceOpenHashMap<>();
- for (FoundClassSubject clazz : inspector.allClasses()) {
- map.computeIfAbsent(clazz.getFinalName(), k -> Sets.newIdentityHashSet()).add(clazz);
- }
- for (Set<FoundClassSubject> duplicates : map.values()) {
- if (duplicates.size() > 1) {
- fail("Unexpected duplicates: " + duplicates);
- }
- }
- }
-
private boolean hasNativeIntUnaryOperator() {
return parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
}
- private void assertWrappers(CodeInspector inspector) {
- assertEquals(
- hasNativeIntUnaryOperator() ? 0 : 2,
- inspector.allClasses().stream()
- .filter(
- c ->
- c.getOriginalName().contains(DesugaredLibraryWrapperSynthesizer.WRAPPER_PREFIX))
- .count());
+ private void assertCoreLibContainsWrappers(Path coreLib) throws IOException {
+ CodeInspector inspector = new CodeInspector(coreLib);
+ Stream<FoundClassSubject> wrappers = getWrappers(inspector);
+ assertNotEquals(0, wrappers.count());
+ }
+
+ private void assertNoWrappers(CodeInspector inspector) {
+ Stream<FoundClassSubject> wrappers = getWrappers(inspector);
+ assertEquals(0, wrappers.count());
+ }
+
+ private Stream<FoundClassSubject> getWrappers(CodeInspector inspector) {
+ return inspector.allClasses().stream()
+ .filter(
+ c -> c.getOriginalName().contains(DesugaredLibraryWrapperSynthesizer.WRAPPER_PREFIX));
}
static class MyArrays1 {
diff --git a/src/test/java/com/android/tools/r8/internal/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/internal/retrace/RetraceTests.java
new file mode 100644
index 0000000..6fea76f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/retrace/RetraceTests.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2020, 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.internal.retrace;
+
+import static com.android.tools.r8.retrace.Retrace.DEFAULT_REGULAR_EXPRESSION;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.internal.retrace.stacktraces.CronetStackTrace;
+import com.android.tools.r8.internal.retrace.stacktraces.FinskyStackTrace;
+import com.android.tools.r8.internal.retrace.stacktraces.VelvetStackTrace;
+import com.android.tools.r8.retrace.Retrace;
+import com.android.tools.r8.retrace.RetraceCommand;
+import com.android.tools.r8.retrace.stacktraces.StackTraceForTest;
+import java.util.List;
+import java.util.function.BiConsumer;
+import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RetraceTests extends TestBase {
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ public RetraceTests(TestParameters parameters) {}
+
+ @Test
+ public void testCronetStackTrace() {
+ runRetraceTest(new CronetStackTrace());
+ }
+
+ @Test
+ public void testFinskyStackTrace() {
+ runRetraceTest(new FinskyStackTrace(), "(?:.*Finsky\\s+:\\s+\\[\\d+\\]\\s+%c\\.%m\\(%l\\):.*)");
+ }
+
+ @Test
+ public void testVelvetStackTrace() {
+ runRetraceTest(new VelvetStackTrace());
+ }
+
+ private TestDiagnosticMessagesImpl runRetraceTest(StackTraceForTest stackTraceForTest) {
+ return runRetraceTest(stackTraceForTest, DEFAULT_REGULAR_EXPRESSION);
+ }
+
+ private TestDiagnosticMessagesImpl runRetraceTest(
+ StackTraceForTest stackTraceForTest, String regularExpression) {
+ return runRetraceTest(stackTraceForTest, regularExpression, TestCase::assertEquals);
+ }
+
+ private TestDiagnosticMessagesImpl runRetraceTest(
+ StackTraceForTest stackTraceForTest,
+ String regularExpression,
+ BiConsumer<List<String>, List<String>> matcher) {
+ TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
+ RetraceCommand retraceCommand =
+ RetraceCommand.builder(diagnosticsHandler)
+ .setProguardMapProducer(stackTraceForTest::mapping)
+ .setStackTrace(stackTraceForTest.obfuscatedStackTrace())
+ .setRegularExpression(regularExpression)
+ .setRetracedStackTraceConsumer(
+ retraced -> matcher.accept(stackTraceForTest.retracedStackTrace(), retraced))
+ .build();
+ Retrace.run(retraceCommand);
+ return diagnosticsHandler;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/CronetStackTrace.java b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/CronetStackTrace.java
new file mode 100644
index 0000000..aa24fbc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/CronetStackTrace.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.internal.retrace.stacktraces;
+
+public class CronetStackTrace extends RetraceInternalStackTraceForTest {
+
+ public CronetStackTrace() {
+ super("cronet_obfuscated.txt", "cronet_deobfuscated.txt");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/FinskyStackTrace.java b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/FinskyStackTrace.java
new file mode 100644
index 0000000..6fde480
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/FinskyStackTrace.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.internal.retrace.stacktraces;
+
+public class FinskyStackTrace extends RetraceInternalStackTraceForTest {
+
+ public FinskyStackTrace() {
+ super("finsky_obfuscated.txt", "finsky_deobfuscated.txt");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/RetraceInternalStackTraceForTest.java b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/RetraceInternalStackTraceForTest.java
new file mode 100644
index 0000000..e4005de
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/RetraceInternalStackTraceForTest.java
@@ -0,0 +1,63 @@
+// Copyright (c) 2020, 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.internal.retrace.stacktraces;
+
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.retrace.stacktraces.StackTraceForTest;
+import com.android.tools.r8.utils.FileUtils;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+public class RetraceInternalStackTraceForTest implements StackTraceForTest {
+
+ private static final Path retraceInternal =
+ Paths.get(ToolHelper.THIRD_PARTY_DIR).resolve("retrace_internal");
+ private final Path obfuscatedPath;
+ private final Path deobfuscatedPath;
+
+ public RetraceInternalStackTraceForTest(String obfuscatedFile, String deobfuscatedFile) {
+ this.obfuscatedPath = retraceInternal.resolve(obfuscatedFile);
+ this.deobfuscatedPath = retraceInternal.resolve(deobfuscatedFile);
+ }
+
+ @Override
+ public List<String> obfuscatedStackTrace() {
+ try {
+ return FileUtils.readAllLines(obfuscatedPath);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not read file " + obfuscatedPath.toString());
+ }
+ }
+
+ @Override
+ public String mapping() {
+ Path mappingPath = retraceInternal.resolve("mapping.txt");
+ try {
+ return new String(Files.readAllBytes(mappingPath));
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not read mapping file " + mappingPath.toString());
+ }
+ }
+
+ @Override
+ public List<String> retracedStackTrace() {
+ try {
+ return FileUtils.readAllLines(deobfuscatedPath);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Could not read file " + deobfuscatedPath.toString());
+ }
+ }
+
+ @Override
+ public int expectedWarnings() {
+ return 0;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/VelvetStackTrace.java b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/VelvetStackTrace.java
new file mode 100644
index 0000000..a2f468e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/retrace/stacktraces/VelvetStackTrace.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.internal.retrace.stacktraces;
+
+public class VelvetStackTrace extends RetraceInternalStackTraceForTest {
+
+ public VelvetStackTrace() {
+ super("velvet_obfuscated.txt", "velvet_deobfuscated.txt");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/HostWithStaticMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/HostWithStaticMethodTest.java
new file mode 100644
index 0000000..0fcb3ee
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/HostWithStaticMethodTest.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, 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.ir.optimize.staticizer;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ir.optimize.staticizer.HostWithStaticMethodTest.Outer.SingletonHolder;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+// This is a reproduction of b/158018192.
+public class HostWithStaticMethodTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public HostWithStaticMethodTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Outer.class, SingletonHolder.class, Main.class)
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableNeverClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("foo", "bar", "foo");
+ }
+
+ @NeverClassInline
+ public static class Outer {
+
+ public static class SingletonHolder {
+
+ public static final Outer outer = new Outer();
+
+ @NeverInline
+ // This method should not be in conflict with any methods in Outer.
+ public static void foo2() {
+ foo();
+ }
+ }
+
+ @NeverInline
+ public static void foo() {
+ System.out.println("foo");
+ }
+
+ @NeverInline
+ public void bar() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ Outer.foo();
+ SingletonHolder.outer.bar();
+ SingletonHolder.foo2();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InstanceInsideCompanionTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InstanceInsideCompanionTest.java
index f28235b..5dabfaf 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InstanceInsideCompanionTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InstanceInsideCompanionTest.java
@@ -46,8 +46,9 @@
.enableNeverClassInliningAnnotations()
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), MAIN)
- .assertSuccessWithOutputLines("Candidate#foo(false)")
- .inspect(this::inspect);
+ .assertSuccessWithOutputLines("Candidate#foo(false)");
+ // TODO(b/159174309): Disable inspection until fixed.
+ // .inspect(this::inspect);
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InvokeStaticWithNullOutvalueTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InvokeStaticWithNullOutvalueTest.java
index e552581..4e3f691 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InvokeStaticWithNullOutvalueTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/InvokeStaticWithNullOutvalueTest.java
@@ -59,11 +59,13 @@
assertThat(instance, not(isPresent()));
ClassSubject companion = inspector.clazz(Host.Companion.class);
- assertThat(companion, not(isPresent()));
+ // TODO(b/158018192): This should not be present.
+ assertThat(companion, isPresent());
// Check if the candidate methods are staticized (if necessary) and migrated.
for (String name : ImmutableList.of("boo", "foo")) {
- MethodSubject oo = host.uniqueMethodWithName(name);
+ // TODO(b/158018192): This should be host and not companion.
+ MethodSubject oo = companion.uniqueMethodWithName(name);
assertThat(oo, isPresent());
assertTrue(oo.isStatic());
assertTrue(
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAllowAccessModificationTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAllowAccessModificationTest.java
new file mode 100644
index 0000000..549f834
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteAllowAccessModificationTest.java
@@ -0,0 +1,156 @@
+// Copyright (c) 2020, 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.kotlin.metadata;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRewriteAllowAccessModificationTest extends KotlinMetadataTestBase {
+
+ private static final String PKG_LIB = PKG + ".allow_access_modification_lib";
+ private static final String PKG_APP = PKG + ".allow_access_modification_app";
+ private final String EXPECTED =
+ StringUtils.lines(
+ "4",
+ "2",
+ "42",
+ "3",
+ "1",
+ "42",
+ "5",
+ "6",
+ "7",
+ "funPrivate",
+ "funInternal",
+ "funProtected",
+ "extensionPrivate",
+ "extensionInternal",
+ "companionPrivate",
+ "companionInternal",
+ "staticPrivate",
+ "staticInternal");
+
+ @Parameterized.Parameters(name = "{0} target: {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
+ }
+
+ public MetadataRewriteAllowAccessModificationTest(
+ TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ private static Map<KotlinTargetVersion, Path> libJars = new HashMap<>();
+ private static Map<KotlinTargetVersion, Path> libReferenceJars = new HashMap<>();
+ private final TestParameters parameters;
+
+ @BeforeClass
+ public static void createLibJar() throws Exception {
+ for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
+ libJars.put(
+ targetVersion,
+ kotlinc(KOTLINC, targetVersion)
+ .addSourceFiles(
+ getKotlinFileInTest(DescriptorUtils.getBinaryNameFromJavaType(PKG_LIB), "lib"))
+ .compile());
+ libReferenceJars.put(
+ targetVersion,
+ kotlinc(KOTLINC, targetVersion)
+ .addSourceFiles(
+ getKotlinFileInTest(
+ DescriptorUtils.getBinaryNameFromJavaType(PKG_LIB), "lib_reference"))
+ .compile());
+ }
+ }
+
+ @Test
+ public void smokeTest() throws Exception {
+ Path libJar = libReferenceJars.get(targetVersion);
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(
+ getKotlinFileInTest(DescriptorUtils.getBinaryNameFromJavaType(PKG_APP), "main"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
+ .addClasspath(output)
+ .run(parameters.getRuntime(), PKG_APP + ".MainKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataForLib() throws Exception {
+ // We compile libjar with -allowaccesmodification such that all visibility modifiers are updated
+ // to be public. We also compile it with a mapping file to rename Lib to LibReference. After
+ // running with R8, the output should be binary compatible with libReference.
+ Path libJar =
+ testForR8(parameters.getBackend())
+ .addProgramFiles(libJars.get(targetVersion))
+ .addKeepRules("-keepclassmembers,allowaccessmodification class **.Lib { *; }")
+ .addKeepRules("-keep,allowaccessmodification,allowobfuscation class **.Lib { *; }")
+ .addKeepRules("-keepclassmembers,allowaccessmodification class **.Lib$Comp { *; }")
+ .addKeepRules("-keep,allowaccessmodification,allowobfuscation class **.Lib$Comp { *; }")
+ .addKeepRules("-keep,allowaccessmodification,allowobfuscation class **.LibKt { *; }")
+ .addKeepRules("-allowaccessmodification")
+ .addApplyMapping(
+ StringUtils.lines(
+ PKG_LIB + ".Lib -> " + PKG_LIB + ".LibReference:",
+ PKG_LIB + ".Lib$Comp -> " + PKG_LIB + ".LibReference$Comp:",
+ PKG_LIB + ".LibKt -> " + PKG_LIB + ".LibReferenceKt:",
+ " void extensionPrivate(" + PKG_LIB + ".Lib) -> extensionPrivate",
+ " void extensionInternal(" + PKG_LIB + ".Lib) -> extensionInternal",
+ " void staticPrivate() -> staticPrivateReference",
+ " void staticInternal() -> staticInternalReference"))
+ .addKeepRuntimeVisibleAnnotations()
+ .compile()
+ .inspect(this::inspect)
+ .writeToZip();
+ ProcessResult mainResult =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(
+ getKotlinFileInTest(DescriptorUtils.getBinaryNameFromJavaType(PKG_APP), "main"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compileRaw();
+ assertEquals(1, mainResult.exitCode);
+ assertThat(mainResult.stderr, containsString("cannot access 'LibReference'"));
+ }
+
+ private void inspect(CodeInspector inspector) throws Exception {
+ // TODO(b/154348683): Assert equality between LibReference and Lib.
+ // assertEqualMetadata(new CodeInspector(libReferenceJars.get(targetVersion)), inspector);
+ ClassSubject lib = inspector.clazz(PKG_LIB + ".Lib");
+ MethodSubject funInline = lib.uniqueMethodWithName("funInline$main");
+ assertThat(funInline, isPresent());
+ // TODO(b/154348683): Keep the inline method package private.
+ // assertTrue(funInline.isPackagePrivate());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
index b2e0b8a..2c14c8d 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
@@ -58,7 +58,8 @@
"42",
"42",
"1",
- "Hello World!");
+ "Hello World!",
+ "class com.android.tools.r8.kotlin.metadata.typealias_lib.Super");
private final TestParameters parameters;
@@ -102,7 +103,8 @@
.compile();
testForJvm()
- .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
+ .addRunClasspathFiles(
+ ToolHelper.getKotlinStdlibJar(), ToolHelper.getKotlinReflectJar(), libJar)
.addClasspath(output)
.run(parameters.getRuntime(), PKG + ".typealias_app.MainKt")
.assertSuccessWithOutput(EXPECTED);
@@ -110,9 +112,11 @@
@Test
public void testMetadataInTypeAlias_renamed() throws Exception {
+ String superTypeName = "com.android.tools.r8.kotlin.metadata.typealias_lib.Super";
+ String renamedSuperTypeName = "com.android.tools.r8.kotlin.metadata.typealias_lib.FooBar";
Path libJar =
testForR8(parameters.getBackend())
- .addClasspathFiles(ToolHelper.getKotlinStdlibJar())
+ .addClasspathFiles(ToolHelper.getKotlinStdlibJar(), ToolHelper.getKotlinReflectJar())
.addProgramFiles(typeAliasLibJarMap.get(targetVersion))
// Keep non-private members of Impl
.addKeepRules("-keep class **.Impl { !private *; }")
@@ -128,6 +132,8 @@
// Keep the library test methods
.addKeepRules("-keep class " + PKG + ".typealias_lib.*Tester { *; }")
.addKeepRules("-keep class " + PKG + ".typealias_lib.*Tester$Companion { *; }")
+ .addKeepRules("-keep class " + PKG + ".typealias_lib.SubTypeOfAlias { *; }")
+ .addApplyMapping(superTypeName + " -> " + renamedSuperTypeName + ":")
.addKeepAttributes(
ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS,
ProguardKeepAttributes.SIGNATURE,
@@ -144,10 +150,11 @@
.compile();
testForJvm()
- .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
+ .addRunClasspathFiles(
+ ToolHelper.getKotlinStdlibJar(), ToolHelper.getKotlinReflectJar(), libJar)
.addClasspath(appJar)
.run(parameters.getRuntime(), PKG + ".typealias_app.MainKt")
- .assertSuccessWithOutput(EXPECTED);
+ .assertSuccessWithOutput(EXPECTED.replace(superTypeName, renamedSuperTypeName));
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePrunedObjectsTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePrunedObjectsTest.java
index 39e9d12..2a33484 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePrunedObjectsTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewritePrunedObjectsTest.java
@@ -6,15 +6,13 @@
import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.CoreMatchers.containsString;
+import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
-import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -85,24 +83,23 @@
Path libJar =
testForR8(parameters.getBackend())
.addProgramFiles(libJars.get(targetVersion))
- .addKeepRules("-keep class " + PKG_LIB + ".Sub { *** kept(); }")
+ .addKeepRules("-keep class " + PKG_LIB + ".Sub { <init>(); *** kept(); }")
.addKeepRuntimeVisibleAnnotations()
.noMinification()
.compile()
.inspect(this::checkPruned)
.writeToZip();
- // TODO(b/158766557): This should work.
- ProcessResult mainResult =
+ Path output =
kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
.addClasspathFiles(libJar)
.addSourceFiles(
getKotlinFileInTest(DescriptorUtils.getBinaryNameFromJavaType(PKG_APP), "main"))
- .setOutputPath(temp.newFolder().toPath())
- .compileRaw();
- assertEquals(1, mainResult.exitCode);
- assertThat(
- mainResult.stderr,
- containsString("cannot access 'com.android.tools.r8.kotlin.metadata.pruned_lib.Base'"));
+ .compile();
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
+ .addProgramFiles(output)
+ .run(parameters.getRuntime(), PKG_APP + ".MainKt")
+ .assertSuccessWithOutput(EXPECTED);
}
private void checkPruned(CodeInspector inspector) {
@@ -112,6 +109,7 @@
assertThat(sub, isPresent());
KmClassSubject kmClass = sub.getKmClass();
assertThat(kmClass, isPresent());
- // TODO(b/158766557): Assert that things are indeed removed.
+ assertEquals(0, kmClass.getSuperTypes().size());
+ assertThat(kmClass.kmFunctionWithUniqueName("notKept"), not(isPresent()));
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_app/main.kt
new file mode 100644
index 0000000..fc2e518
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_app/main.kt
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, 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.kotlin.metadata.allow_access_modification_app
+
+import com.android.tools.r8.kotlin.metadata.allow_access_modification_lib.LibReference
+import com.android.tools.r8.kotlin.metadata.allow_access_modification_lib.extensionInternal
+import com.android.tools.r8.kotlin.metadata.allow_access_modification_lib.extensionPrivate
+import com.android.tools.r8.kotlin.metadata.allow_access_modification_lib.staticInternalReference
+import com.android.tools.r8.kotlin.metadata.allow_access_modification_lib.staticPrivateReference
+
+fun main() {
+ val libReference = LibReference(1, 2, 3, 4)
+ println(libReference.propPrimaryPrivate)
+ println(libReference.propPrimaryInternal)
+ println(libReference.propPrivate)
+ libReference.propPrimaryPrivate = 5
+ libReference.propPrimaryInternal = 6
+ libReference.propPrivate = 7
+ println(libReference.readOnlyPropPrimaryPrivate)
+ println(libReference.readOnlyPropPrimaryInternal)
+ println(libReference.readOnlyPropInternal)
+ println(libReference.propPrimaryPrivate)
+ println(libReference.propPrimaryInternal)
+ println(libReference.propPrivate)
+
+ libReference.funPrivate()
+ libReference.funInternal()
+ libReference.funProtected()
+
+ libReference.extensionPrivate()
+ libReference.extensionInternal()
+
+ LibReference.companionPrivate()
+ LibReference.companionInternal()
+
+ staticPrivateReference()
+ staticInternalReference()
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_lib/lib.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_lib/lib.kt
new file mode 100644
index 0000000..f77d4f8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_lib/lib.kt
@@ -0,0 +1,59 @@
+// Copyright (c) 2020, 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.kotlin.metadata.allow_access_modification_lib
+
+internal class Lib internal constructor(
+ internal val readOnlyPropPrimaryInternal: Int,
+ internal var propPrimaryInternal : Int,
+ private val readOnlyPropPrimaryPrivate: Int,
+ internal var propPrimaryPrivate : Int) {
+
+ internal val propInternal: Int = 42
+ private var propPrivate: Int = 0
+
+ private fun funPrivate() {
+ println("funPrivate")
+ }
+
+ internal fun funInternal() {
+ println("funInternal")
+ }
+
+ protected fun funProtected() {
+ println("funProtected")
+ }
+
+ // Keep this internal to ensure we do not modify inline functions.
+ internal inline fun funInline() {
+ println("funInline")
+ }
+
+ internal companion object Comp {
+
+ private fun companionPrivate() {
+ println("companionPrivate")
+ }
+
+ internal fun companionInternal() {
+ println("companionInternal")
+ }
+ }
+}
+
+private fun Lib.extensionPrivate() {
+ println("extensionPrivate")
+}
+
+internal fun Lib.extensionInternal() {
+ println("extensionInternal")
+}
+
+private fun staticPrivate() {
+ println("staticPrivate")
+}
+
+internal fun staticInternal() {
+ println("staticInternal")
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_lib/lib_reference.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_lib/lib_reference.kt
new file mode 100644
index 0000000..a26d8d2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/allow_access_modification_lib/lib_reference.kt
@@ -0,0 +1,59 @@
+// Copyright (c) 2020, 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.kotlin.metadata.allow_access_modification_lib
+
+class LibReference(
+ val readOnlyPropPrimaryInternal: Int,
+ var propPrimaryInternal : Int,
+ val readOnlyPropPrimaryPrivate: Int,
+ var propPrimaryPrivate : Int) {
+
+ val readOnlyPropInternal: Int = 42
+ var propPrivate: Int = 42
+
+ fun funPrivate() {
+ println("funPrivate")
+ }
+
+ fun funInternal() {
+ println("funInternal")
+ }
+
+ fun funProtected() {
+ println("funProtected")
+ }
+
+ // Keep this internal to ensure we do not modify inline functions.
+ internal inline fun funInline() {
+ println("funInline")
+ }
+
+ companion object Factory {
+
+ fun companionPrivate() {
+ println("companionPrivate")
+ }
+
+ fun companionInternal() {
+ println("companionInternal")
+ }
+ }
+}
+
+fun LibReference.extensionPrivate() {
+ println("extensionPrivate")
+}
+
+fun LibReference.extensionInternal() {
+ println("extensionInternal")
+}
+
+fun staticPrivateReference() {
+ println("staticPrivate")
+}
+
+fun staticInternalReference() {
+ println("staticInternal")
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt
index f836216..71dc2aa 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt
@@ -23,6 +23,7 @@
import com.android.tools.r8.kotlin.metadata.typealias_lib.OuterTester
import com.android.tools.r8.kotlin.metadata.typealias_lib.SimpleClassTester
import com.android.tools.r8.kotlin.metadata.typealias_lib.StillCWithConstructor
+import com.android.tools.r8.kotlin.metadata.typealias_lib.SubTypeOfAlias
import com.android.tools.r8.kotlin.metadata.typealias_lib.UnderlyingTypeTester
import com.android.tools.r8.kotlin.metadata.typealias_lib.UnusedTypeArgument
import com.android.tools.r8.kotlin.metadata.typealias_lib.VerticalClassMergingTester
@@ -107,6 +108,10 @@
VerticalClassMergingTester.passThrough(apiImpl).foo()
}
+fun testSuperType() {
+ println(SubTypeOfAlias::class.supertypes[0].classifier)
+}
+
fun main() {
val instance = ProgramClass()
val l = seq(instance)
@@ -122,6 +127,7 @@
testNestedClasses()
testCompanion()
testConstructor()
- testUnderlyingType();
- testVerticalClassMerging();
+ testUnderlyingType()
+ testVerticalClassMerging()
+ testSuperType()
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
index 60d5bda..481adfc 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
@@ -420,6 +420,11 @@
fun i(a : MyAdvancedMap) : MutableMap<OuterNested, OuterNestedInner> {
return a;
}
-
}
}
+
+open class Super
+
+typealias TypeAliasForSuper = Super
+
+class SubTypeOfAlias : TypeAliasForSuper()
diff --git a/src/test/java/com/android/tools/r8/regress/b158429654/InliningNonAccessible.java b/src/test/java/com/android/tools/r8/regress/b158429654/InliningNonAccessible.java
new file mode 100644
index 0000000..acf084b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b158429654/InliningNonAccessible.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, 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.regress.b158429654;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.regress.b158429654.innerpackage.InnerClass;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InliningNonAccessible extends TestBase {
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
+ public InliningNonAccessible(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testCompileToInvalidFileD8() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(OuterAbstract.class, OuterImpl.class, InnerClass.class)
+ .addProgramClasses(Main.class)
+ .addKeepMainRule(Main.class)
+ .noMinification()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("42");
+ }
+
+ static class Main {
+ public static void main(String[] args) {
+ OuterImpl.register(args);
+ InnerClass inner = new InnerClass();
+ inner.foobar();
+ System.out.println("42");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b158429654/OuterAbstract.java b/src/test/java/com/android/tools/r8/regress/b158429654/OuterAbstract.java
new file mode 100644
index 0000000..0c5a078
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b158429654/OuterAbstract.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, 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.regress.b158429654;
+
+public abstract class OuterAbstract {
+ private static OuterAbstract sInstance;
+
+ public static OuterAbstract getInstance() {
+ return sInstance;
+ }
+
+ public static void setsInstance(OuterAbstract sInstance) {
+ OuterAbstract.sInstance = sInstance;
+ }
+
+ public abstract void theMethod();
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b158429654/OuterImpl.java b/src/test/java/com/android/tools/r8/regress/b158429654/OuterImpl.java
new file mode 100644
index 0000000..edca5c1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b158429654/OuterImpl.java
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, 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.regress.b158429654;
+
+class OuterImpl extends OuterAbstract {
+
+ public static void register(String[] args) {
+ OuterAbstract.setsInstance(new OuterImpl());
+ }
+
+ private OuterImpl() {}
+
+ @Override
+ public void theMethod() {}
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b158429654/innerpackage/InnerClass.java b/src/test/java/com/android/tools/r8/regress/b158429654/innerpackage/InnerClass.java
new file mode 100644
index 0000000..b2f8582
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b158429654/innerpackage/InnerClass.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, 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.regress.b158429654.innerpackage;
+
+import com.android.tools.r8.regress.b158429654.OuterAbstract;
+
+public class InnerClass {
+
+ public void foobar() {
+ OuterAbstract.getInstance().theMethod();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
index 102f7f0..e8494d6 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceCommandLineTests.java
@@ -4,10 +4,10 @@
package com.android.tools.r8.retrace;
-import static com.android.tools.r8.retrace.RetraceTests.DEFAULT_REGULAR_EXPRESSION;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -61,7 +61,8 @@
@Test
public void testVerbose() throws IOException {
FoundMethodVerboseStackTrace stackTrace = new FoundMethodVerboseStackTrace();
- runTest(
+ // TODO(b/159562137): Add proper support for -verbose when using regexp.
+ runTestNotEquals(
stackTrace.mapping(),
StringUtils.joinLines(stackTrace.obfuscatedStackTrace()),
false,
@@ -70,14 +71,35 @@
}
@Test
+ public void testVerboseSingleHyphen() throws IOException {
+ FoundMethodVerboseStackTrace stackTrace = new FoundMethodVerboseStackTrace();
+ // TODO(b/159562137): Add proper support for -verbose when using regexp.
+ runTestNotEquals(
+ stackTrace.mapping(),
+ StringUtils.joinLines(stackTrace.obfuscatedStackTrace()),
+ false,
+ StringUtils.joinLines(stackTrace.retracedStackTrace()) + StringUtils.LINE_SEPARATOR,
+ "-verbose");
+ }
+
+ @Test
public void testRegularExpression() throws IOException {
ActualRetraceBotStackTrace stackTrace = new ActualRetraceBotStackTrace();
runTest(
stackTrace.mapping(),
StringUtils.joinLines(stackTrace.obfuscatedStackTrace()),
false,
- StringUtils.joinLines(stackTrace.retracedStackTrace()) + StringUtils.LINE_SEPARATOR,
- "--regex=" + DEFAULT_REGULAR_EXPRESSION);
+ StringUtils.joinLines(stackTrace.retracedStackTrace()) + StringUtils.LINE_SEPARATOR);
+ }
+
+ @Test
+ public void testRegularExpressionSingleHyphen() throws IOException {
+ ActualRetraceBotStackTrace stackTrace = new ActualRetraceBotStackTrace();
+ runTest(
+ stackTrace.mapping(),
+ StringUtils.joinLines(stackTrace.obfuscatedStackTrace()),
+ false,
+ StringUtils.joinLines(stackTrace.retracedStackTrace()) + StringUtils.LINE_SEPARATOR);
}
@Test
@@ -88,7 +110,6 @@
StringUtils.joinLines(stackTrace.obfuscatedStackTrace()),
false,
StringUtils.joinLines(stackTrace.retracedStackTrace()) + StringUtils.LINE_SEPARATOR,
- "--regex=" + DEFAULT_REGULAR_EXPRESSION,
"--info");
}
@@ -123,6 +144,14 @@
assertEquals(expected, result.stdout);
}
+ private void runTestNotEquals(
+ String mapping, String stackTrace, boolean stacktraceStdIn, String expected, String... args)
+ throws IOException {
+ ProcessResult result = runRetrace(mapping, stackTrace, stacktraceStdIn, args);
+ assertEquals(0, result.exitCode);
+ assertNotEquals(expected, result.stdout);
+ }
+
private void runAbortTest(Matcher<String> errorMatch, String... args) throws IOException {
ProcessResult result = runRetraceCommandLine(null, Arrays.asList(args));
assertEquals(1, result.exitCode);
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
index 47dc5c3..9af9e28 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.retrace;
+import static com.android.tools.r8.retrace.Retrace.DEFAULT_REGULAR_EXPRESSION;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -45,12 +46,6 @@
@RunWith(Parameterized.class)
public class RetraceTests extends TestBase {
- // This is a slight modification of the default regular expression shown for proguard retrace
- // that allow for retracing classes in the form <class>: lorem ipsum...
- // Seems like Proguard retrace is expecting the form "Caused by: <class>".
- public static final String DEFAULT_REGULAR_EXPRESSION =
- "(?:.*?\\bat\\s+%c\\.%m\\s*\\(%s(?::%l)?\\)\\s*(?:~\\[.*\\])?)|(?:(?:(?:%c|.*)?[:\"]\\s+)?%c(?::.*)?)";
-
@Parameters(name = "{0}, use regular expression: {1}")
public static Collection<Object[]> data() {
return buildParameters(getTestParameters().withNoneRuntime().build(), BooleanUtils.values());
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java
index 3e47f3b..d6bac64 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CfTryCatchSubject.java
@@ -11,12 +11,17 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import java.util.Collection;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
class CfTryCatchSubject implements TryCatchSubject {
+ private final CodeInspector inspector;
private final CfCode cfCode;
private final CfTryCatch tryCatch;
- CfTryCatchSubject(CfCode cfCode, CfTryCatch tryCatch) {
+ CfTryCatchSubject(CodeInspector inspector, CfCode cfCode, CfTryCatch tryCatch) {
+ this.inspector = inspector;
this.cfCode = cfCode;
this.tryCatch = tryCatch;
}
@@ -62,6 +67,16 @@
}
@Override
+ public Stream<TypeSubject> streamGuards() {
+ return tryCatch.guards.stream().map(type -> new TypeSubject(inspector, type));
+ }
+
+ @Override
+ public Collection<TypeSubject> guards() {
+ return streamGuards().collect(Collectors.toList());
+ }
+
+ @Override
public int getNumberOfHandlers() {
return tryCatch.guards.size();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 2a4c7c5..f43c01c 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -386,11 +386,11 @@
}
TryCatchSubject createTryCatchSubject(DexCode code, Try tryElement, TryHandler tryHandler) {
- return new DexTryCatchSubject(code, tryElement, tryHandler);
+ return new DexTryCatchSubject(this, code, tryElement, tryHandler);
}
TryCatchSubject createTryCatchSubject(CfCode code, CfTryCatch tryCatch) {
- return new CfTryCatchSubject(code, tryCatch);
+ return new CfTryCatchSubject(this, code, tryCatch);
}
TryCatchIterator createTryCatchIterator(MethodSubject method) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/DexTryCatchSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/DexTryCatchSubject.java
index 4a96ff1..4624c33 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/DexTryCatchSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/DexTryCatchSubject.java
@@ -9,13 +9,20 @@
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.graph.DexCode.TryHandler;
import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
class DexTryCatchSubject implements TryCatchSubject {
+ private final CodeInspector inspector;
private final DexCode dexCode;
private final Try tryElement;
private final TryHandler tryHandler;
- DexTryCatchSubject(DexCode dexCode, Try tryElement, TryHandler tryHandler) {
+ DexTryCatchSubject(
+ CodeInspector inspector, DexCode dexCode, Try tryElement, TryHandler tryHandler) {
+ this.inspector = inspector;
this.dexCode = dexCode;
this.tryElement = tryElement;
this.tryHandler = tryHandler;
@@ -45,6 +52,18 @@
}
@Override
+ public Stream<TypeSubject> streamGuards() {
+ return Arrays.stream(tryHandler.pairs)
+ .map(pair -> pair.type)
+ .map(type -> new TypeSubject(inspector, type));
+ }
+
+ @Override
+ public Collection<TypeSubject> guards() {
+ return streamGuards().collect(Collectors.toList());
+ }
+
+ @Override
public int getNumberOfHandlers() {
if (tryHandler.catchAllAddr != NO_HANDLER) {
return tryHandler.pairs.length + 1;
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
index b158404..72b71b0 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -89,6 +89,10 @@
return Streams.stream(iterateInstructions());
}
+ public Stream<TryCatchSubject> streamTryCatches() {
+ return Streams.stream(iterateTryCatches());
+ }
+
public void getLineNumberForInstruction(InstructionSubject subject) {
assert hasLineNumberTable();
getLineNumberTable().getLineForInstruction(subject);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/TryCatchSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/TryCatchSubject.java
index 73e9ef1..d34f4e9 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/TryCatchSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/TryCatchSubject.java
@@ -3,10 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.codeinspector;
+import java.util.Collection;
+import java.util.stream.Stream;
+
public interface TryCatchSubject {
RangeSubject getRange();
boolean isCatching(String exceptionType);
boolean hasCatchAll();
+ Stream<TypeSubject> streamGuards();
+
+ Collection<TypeSubject> guards();
+
int getNumberOfHandlers();
}
diff --git a/tests/d8_api_usage_sample.jar b/tests/d8_api_usage_sample.jar
deleted file mode 100644
index da01fdb..0000000
--- a/tests/d8_api_usage_sample.jar
+++ /dev/null
Binary files differ
diff --git a/tests/r8_api_usage_sample.jar b/tests/r8_api_usage_sample.jar
index da01fdb..c50e110 100644
--- a/tests/r8_api_usage_sample.jar
+++ b/tests/r8_api_usage_sample.jar
Binary files differ
diff --git a/third_party/r8-releases/2.0.74.tar.gz.sha1 b/third_party/r8-releases/2.0.74.tar.gz.sha1
new file mode 100644
index 0000000..7359e6d
--- /dev/null
+++ b/third_party/r8-releases/2.0.74.tar.gz.sha1
@@ -0,0 +1 @@
+6903a4fb98ef23da4d40e1b08998a390578dd0ef
\ No newline at end of file
diff --git a/third_party/retrace_internal.tar.gz.sha1 b/third_party/retrace_internal.tar.gz.sha1
new file mode 100644
index 0000000..b840e19
--- /dev/null
+++ b/third_party/retrace_internal.tar.gz.sha1
@@ -0,0 +1 @@
+f00aa79849d9eb8a16accaca566ac275f4711d8e
\ No newline at end of file
diff --git a/tools/r8_release.py b/tools/r8_release.py
index 357b659..1224b1d 100755
--- a/tools/r8_release.py
+++ b/tools/r8_release.py
@@ -21,7 +21,7 @@
R8_VERSION_FILE = os.path.join(
'src', 'main', 'java', 'com', 'android', 'tools', 'r8', 'Version.java')
THIS_FILE_RELATIVE = os.path.join('tools', 'r8_release.py')
-ADMRT = '/google/data/ro/teams/android-devtools-infra/tools/admrt'
+GMAVEN_PUBLISHER = '/google/bin/releases/android-devtools/gmaven/publisher/gmaven-publisher'
DESUGAR_JDK_LIBS = 'desugar_jdk_libs'
DESUGAR_JDK_LIBS_CONFIGURATION = DESUGAR_JDK_LIBS + '_configuration'
@@ -223,6 +223,31 @@
return release_aosp
+def prepare_maven(args):
+ assert args.version
+
+ def release_maven(options):
+ gfile = '/bigstore/r8-releases/raw/%s/r8lib.zip' % args.version
+ release_id = gmaven_publisher_stage(options, [gfile])
+
+ print "Staged Release ID " + release_id + ".\n"
+ gmaven_publisher_stage_redir_test_info(
+ release_id, "com.android.tools:r8:%s" % args.version, "r8lib.jar")
+
+ print
+ input = raw_input("Continue with publishing [y/N]:")
+
+ if input != 'y':
+ print 'Aborting release to Google maven'
+ sys.exit(1)
+
+ gmaven_publisher_publish(args, release_id)
+
+ print
+ print "Published. Use the email workflow for approval."
+
+ return release_maven
+
def git_message_dev(version):
return """Update D8 R8 master to %s
@@ -297,6 +322,14 @@
('https://storage.googleapis.com/r8-releases/raw/%s/%s' % (version, file)),
dst)
+def download_gfile(gfile, dst):
+ if not gfile.startswith('/bigstore/r8-releases'):
+ print 'Unexpected gfile prefix for %s' % gfile
+ sys.exit(1)
+
+ urllib.urlretrieve(
+ 'https://storage.googleapis.com/%s' % gfile[len('/bigstore/'):],
+ dst)
def blaze_run(target):
return subprocess.check_output(
@@ -356,46 +389,52 @@
def make_release(args):
library_version = args.desugar_library[0]
- configuration_hash = args.desugar_library[1]
+ configuration_version = args.desugar_library[1]
library_archive = DESUGAR_JDK_LIBS + '.zip'
+ library_jar = DESUGAR_JDK_LIBS + '.jar'
library_artifact_id = \
'%s:%s:%s' % (ANDROID_TOOLS_PACKAGE, DESUGAR_JDK_LIBS, library_version)
+ configuration_archive = DESUGAR_JDK_LIBS_CONFIGURATION + '.zip'
+
with utils.TempDir() as temp:
with utils.ChangedWorkingDirectory(temp):
- download_file(
- '%s/%s' % (DESUGAR_JDK_LIBS, library_version),
- library_archive,
- library_archive)
- configuration_archive = DESUGAR_JDK_LIBS_CONFIGURATION + '.zip'
- configuration_artifact_id = \
- download_configuration(configuration_hash, configuration_archive)
+ library_gfile = ('/bigstore/r8-releases/raw/%s/%s/%s'
+ % (DESUGAR_JDK_LIBS, library_version, library_archive))
+ configuration_gfile = ('/bigstore/r8-releases/raw/master/%s/%s'
+ % (configuration_version, configuration_archive))
- print 'Preparing maven release of:'
- print ' %s' % library_artifact_id
- print ' %s' % configuration_artifact_id
+ download_gfile(library_gfile, library_archive)
+ download_gfile(configuration_gfile, configuration_archive)
+ check_configuration(configuration_archive)
+
+ release_id = gmaven_publisher_stage(
+ args, [library_gfile, configuration_gfile])
+
+ print "Staged Release ID " + release_id + ".\n"
+ gmaven_publisher_stage_redir_test_info(
+ release_id,
+ "com.android.tools:%s:%s" % (DESUGAR_JDK_LIBS, library_version),
+ library_jar)
+
print
+ input = raw_input("Continue with publishing [y/N]:")
- admrt_stage(
- [library_archive, configuration_archive],
- [library_artifact_id, configuration_artifact_id],
- args)
+ if input != 'y':
+ print 'Aborting release to Google maven'
+ sys.exit(1)
- admrt_lorry(
- [library_archive, configuration_archive],
- [library_artifact_id, configuration_artifact_id],
- args)
+ gmaven_publisher_publish(args, release_id)
+
+ print
+ print "Published. Use the email workflow for approval."
return make_release
-def download_configuration(hash, archive):
- print
- print 'Downloading %s from GCS' % archive
- print
- download_file('master/' + hash, archive, archive)
- zip = zipfile.ZipFile(archive)
+def check_configuration(configuration_archive):
+ zip = zipfile.ZipFile(configuration_archive)
zip.extractall()
dirs = os.listdir(
os.path.join('com', 'android', 'tools', DESUGAR_JDK_LIBS_CONFIGURATION))
@@ -415,9 +454,6 @@
if version != version_from_pom:
print 'Version mismatch, %s != %s' % (version, version_from_pom)
sys.exit(1)
- return '%s:%s:%s' % \
- (ANDROID_TOOLS_PACKAGE, DESUGAR_JDK_LIBS_CONFIGURATION, version)
-
def check_no_google3_client(args, client_name):
if not args.use_existing_work_branch:
@@ -437,68 +473,78 @@
return tree.getroot().find("{%s}version" % ns).text
-def admrt_stage(archives, artifact_ids, args):
+GMAVEN_PUBLISH_STAGE_RELEASE_ID_PATTERN = re.compile('Release ID = ([0-9a-f\-]+)')
+
+
+def gmaven_publisher_stage(args, gfiles):
if args.dry_run:
- print 'Dry-run, just copying archives to %s' % args.dry_run_output
- for archive in archives:
- print 'Copying: %s' % archive
- shutil.copyfile(archive, os.path.join(args.dry_run_output, archive))
- return
+ print 'Dry-run, would have staged %s' % gfiles
+ return 'dry-run-release-id'
- admrt(archives, 'stage')
-
- jdk9_home = os.path.join(
- utils.REPO_ROOT, 'third_party', 'openjdk', 'openjdk-9.0.4', 'linux')
- print
- print "Use the following commands to test with 'redir':"
- print
- print 'export BUCKET_PATH=/studio_staging/maven2/<user>/<id>'
- print '/google/data/ro/teams/android-devtools-infra/tools/redir \\'
- print ' --alsologtostderr \\'
- print ' --gcs_bucket_path=$BUCKET_PATH \\'
- print ' --port=1480'
- print
- print 'The path for BUCKET_PATH has to be taken from the admrt info line:'
- print ' INFO: Stage Available at: ...'
- print '(without the /bigstore prefix).'
- print
- print "When the 'redir' server is running use the following commands"
- print 'to retreive the artifact:'
- print
- print 'rm -rf /tmp/maven_repo_local'
- print ('JAVA_HOME=%s ' % jdk9_home
- + 'mvn org.apache.maven.plugins:maven-dependency-plugin:2.4:get \\')
- print ' -Dmaven.repo.local=/tmp/maven_repo_local \\'
- print ' -DremoteRepositories=http://localhost:1480 \\'
- print ' -Dartifact=%s \\' % artifact_ids[0]
- print ' -Ddest=%s' % archives[0]
+ print "Staging: %s" % ', '.join(gfiles)
print
+ cmd = [GMAVEN_PUBLISHER, 'stage', '--gfile', ','.join(gfiles)]
+ output = subprocess.check_output(cmd)
-def admrt_lorry(archives, artifact_ids, args):
- if args.dry_run:
- print 'Dry run - no lorry action'
- return
+ # Expect output to contain:
+ # [INFO] 06/19/2020 09:35:12 CEST: >>>>>>>>>> Staged
+ # [INFO] 06/19/2020 09:35:12 CEST: Release ID = 9171d015-18f6-4a90-9984-1c362589dc1b
+ # [INFO] 06/19/2020 09:35:12 CEST: Stage Path = /bigstore/studio_staging/maven2/sgjesse/9171d015-18f6-4a90-9984-1c362589dc1b
- print
- print 'Continue with running in lorry mode for release of:'
- for artifact_id in artifact_ids:
- print ' %s' % artifact_id
- input = raw_input('[y/N]:')
-
- if input != 'y':
- print 'Aborting release to Google maven'
+ matches = GMAVEN_PUBLISH_STAGE_RELEASE_ID_PATTERN.findall(output)
+ if matches == None or len(matches) > 1:
+ print ("Could not determine the release ID from the gmaven_publisher " +
+ "output. Expected a line with 'Release ID = <release id>'.")
+ print "Output was:"
+ print output
sys.exit(1)
- admrt(archives, 'lorry')
+ print output
+
+ release_id = matches[0]
+ return release_id
-def admrt(archives, action):
- cmd = [ADMRT, '--archives']
- cmd.append(','.join(archives))
- cmd.extend(['--action', action])
- subprocess.check_call(cmd)
+def gmaven_publisher_stage_redir_test_info(release_id, artifact, dst):
+ redir_command = ("/google/data/ro/teams/android-devtools-infra/tools/redir "
+ + "--alsologtostderr "
+ + "--gcs_bucket_path=/studio_staging/maven2/${USER}/%s "
+ + "--port=1480") % release_id
+
+ get_command = ("mvn org.apache.maven.plugins:maven-dependency-plugin:2.4:get "
+ + "-Dmaven.repo.local=/tmp/maven_repo_local "
+ + "-DremoteRepositories=http://localhost:1480 "
+ + "-Dartifact=%s "
+ + "-Ddest=%s") % (artifact, dst)
+
+ print """To test the staged content with 'redir' run:
+
+%s
+
+Add the following repository to gradle.build for using 'redir':
+
+repositories {
+ maven {
+ url 'http://localhost:1480'
+ }
+}
+
+Use this commands to get artifact from 'redir':
+
+rm -rf /tmp/maven_repo_local
+%s
+""" % (redir_command, get_command)
+
+
+def gmaven_publisher_publish(args, release_id):
+ if args.dry_run:
+ print 'Dry-run, would have published %s' % release_id
+ return
+
+ cmd = [GMAVEN_PUBLISHER, 'publish', release_id]
+ output = subprocess.check_output(cmd)
def branch_change_diff(diff, old_version, new_version):
invalid_line = None
@@ -658,6 +704,10 @@
metavar=('<path>'),
help='Release for aosp by setting the path to the '
'checkout')
+ result.add_argument('--maven',
+ default=False,
+ action='store_true',
+ help='Release to Google Maven')
result.add_argument('--google3',
default=False,
action='store_true',
@@ -683,8 +733,12 @@
metavar=('<path>'),
help='Location for dry run output.')
args = result.parse_args()
- if args.version and not 'dev' in args.version and args.bug == []:
- print "When releasing a release version add the list of bugs by using '--bug'"
+ if (args.studio
+ and args.version
+ and not 'dev' in args.version
+ and args.bug == []):
+ print ("When releasing a release version to Android Studio add the "
+ + "list of bugs by using '--bug'")
sys.exit(1)
if args.version and not 'dev' in args.version and args.google3:
@@ -711,6 +765,7 @@
targets_to_run.append(prepare_release(args))
if (args.google3
+ or args.maven
or (args.studio and not args.no_sync)
or (args.desugar_library and not args.dry_run)):
utils.check_prodacces()
@@ -721,6 +776,8 @@
targets_to_run.append(prepare_studio(args))
if args.aosp:
targets_to_run.append(prepare_aosp(args))
+ if args.maven:
+ targets_to_run.append(prepare_maven(args))
if args.desugar_library:
targets_to_run.append(prepare_desugar_library(args))
diff --git a/tools/test.py b/tools/test.py
index 95766ca..ad99485 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -162,7 +162,7 @@
gradle_args = ['--stacktrace']
if utils.is_bot():
- # Bots don't like dangling processes
+ # Bots don't like dangling processes.
gradle_args.append('--no-daemon')
# Set all necessary Gradle properties and options first.