aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar kmb <kmb@google.com>2018-02-21 21:34:01 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-21 21:36:41 -0800
commitdeb99ccfb4e6b236c21e6d425281870aa598804a (patch)
treedaf1155b4cdcbf9af657d79a3fa8fea843fd9e5e
parentcfb8a74908459d839c755abcc1c68bfa2ed25f2a (diff)
add ability to move individual core library methods
RELNOTES: None. PiperOrigin-RevId: 186565673
-rw-r--r--src/test/java/com/google/devtools/build/android/desugar/CoreLibrarySupportTest.java55
-rw-r--r--src/test/java/com/google/devtools/build/android/desugar/CorePackageRenamerTest.java20
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibraryInvocationRewriter.java12
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibrarySupport.java30
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java15
5 files changed, 115 insertions, 17 deletions
diff --git a/src/test/java/com/google/devtools/build/android/desugar/CoreLibrarySupportTest.java b/src/test/java/com/google/devtools/build/android/desugar/CoreLibrarySupportTest.java
index 853dbbe3b1..cc177482c9 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/CoreLibrarySupportTest.java
+++ b/src/test/java/com/google/devtools/build/android/desugar/CoreLibrarySupportTest.java
@@ -32,7 +32,11 @@ public class CoreLibrarySupportTest {
public void testIsRenamedCoreLibrary() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
- new CoreLibraryRewriter(""), null, ImmutableList.of("java/time/"), ImmutableList.of());
+ new CoreLibraryRewriter(""),
+ null,
+ ImmutableList.of("java/time/"),
+ ImmutableList.of(),
+ ImmutableList.of());
assertThat(support.isRenamedCoreLibrary("java/time/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("java/time/y/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("java/io/X")).isFalse();
@@ -48,6 +52,7 @@ public class CoreLibrarySupportTest {
new CoreLibraryRewriter("__/"),
null,
ImmutableList.of("java/time/"),
+ ImmutableList.of(),
ImmutableList.of());
assertThat(support.isRenamedCoreLibrary("__/java/time/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("__/java/time/y/X")).isTrue();
@@ -60,7 +65,11 @@ public class CoreLibrarySupportTest {
public void testRenameCoreLibrary() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
- new CoreLibraryRewriter(""), null, ImmutableList.of(), ImmutableList.of());
+ new CoreLibraryRewriter(""),
+ null,
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of());
assertThat(support.renameCoreLibrary("java/time/X")).isEqualTo("j$/time/X");
assertThat(support.renameCoreLibrary("com/google/X")).isEqualTo("com/google/X");
}
@@ -69,19 +78,39 @@ public class CoreLibrarySupportTest {
public void testRenameCoreLibrary_prefixedLoader() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
- new CoreLibraryRewriter("__/"), null, ImmutableList.of(), ImmutableList.of());
+ new CoreLibraryRewriter("__/"),
+ null,
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableList.of());
assertThat(support.renameCoreLibrary("__/java/time/X")).isEqualTo("j$/time/X");
assertThat(support.renameCoreLibrary("com/google/X")).isEqualTo("com/google/X");
}
@Test
+ public void testMoveTarget() throws Exception {
+ CoreLibrarySupport support =
+ new CoreLibrarySupport(
+ new CoreLibraryRewriter("__/"),
+ null,
+ ImmutableList.of("java/util/Helper"),
+ ImmutableList.of(),
+ ImmutableList.of("java/util/Existing#match -> java/util/Helper"));
+ assertThat(support.getMoveTarget("__/java/util/Existing", "match")).isEqualTo("j$/util/Helper");
+ assertThat(support.getMoveTarget("java/util/Existing", "match")).isEqualTo("j$/util/Helper");
+ assertThat(support.getMoveTarget("__/java/util/Existing", "matchesnot")).isNull();
+ assertThat(support.getMoveTarget("__/java/util/ExistingOther", "match")).isNull();
+ }
+
+ @Test
public void testIsEmulatedCoreClassOrInterface() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/concurrent/"),
- ImmutableList.of("java/util/Map"));
+ ImmutableList.of("java/util/Map"),
+ ImmutableList.of());
assertThat(support.isEmulatedCoreClassOrInterface("java/util/Map")).isTrue();
assertThat(support.isEmulatedCoreClassOrInterface("java/util/Map$$Lambda$17")).isFalse();
assertThat(support.isEmulatedCoreClassOrInterface("java/util/Map$$CC")).isFalse();
@@ -98,7 +127,8 @@ public class CoreLibrarySupportTest {
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
- ImmutableList.of("java/util/Collection"));
+ ImmutableList.of("java/util/Collection"),
+ ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
@@ -132,7 +162,8 @@ public class CoreLibrarySupportTest {
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
- ImmutableList.of("java/util/Collection"));
+ ImmutableList.of("java/util/Collection"),
+ ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
@@ -158,7 +189,8 @@ public class CoreLibrarySupportTest {
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
- ImmutableList.of("java/util/Map"));
+ ImmutableList.of("java/util/Map"),
+ ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
@@ -192,7 +224,8 @@ public class CoreLibrarySupportTest {
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
- ImmutableList.of("java/util/Comparator"));
+ ImmutableList.of("java/util/Comparator"),
+ ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESTATIC,
@@ -208,12 +241,13 @@ public class CoreLibrarySupportTest {
* {@link InterfaceDesugaring}.
*/
@Test
- public void testGetEmulatedCoreLibraryInvocationTarget_renamed() throws Exception {
+ public void testGetCoreInterfaceRewritingTarget_renamed() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/"),
+ ImmutableList.of(),
ImmutableList.of());
// regular invocations of default methods: ignored
@@ -281,7 +315,8 @@ public class CoreLibrarySupportTest {
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/concurrent/"), // should return null for these
- ImmutableList.of("java/util/Map"));
+ ImmutableList.of("java/util/Map"),
+ ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
diff --git a/src/test/java/com/google/devtools/build/android/desugar/CorePackageRenamerTest.java b/src/test/java/com/google/devtools/build/android/desugar/CorePackageRenamerTest.java
index 0626b469fd..0ff0f25ea3 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/CorePackageRenamerTest.java
+++ b/src/test/java/com/google/devtools/build/android/desugar/CorePackageRenamerTest.java
@@ -29,10 +29,15 @@ public class CorePackageRenamerTest {
@Test
public void testSymbolRewrite() throws Exception {
MockClassVisitor out = new MockClassVisitor();
- CorePackageRenamer renamer = new CorePackageRenamer(
- out,
- new CoreLibrarySupport(
- new CoreLibraryRewriter(""), null, ImmutableList.of("java/time/"), ImmutableList.of()));
+ CorePackageRenamer renamer =
+ new CorePackageRenamer(
+ out,
+ new CoreLibrarySupport(
+ new CoreLibraryRewriter(""),
+ null,
+ ImmutableList.of("java/time/"),
+ ImmutableList.of(),
+ ImmutableList.of("java/util/A#m->java/time/B")));
MethodVisitor mv = renamer.visitMethod(0, "test", "()V", null, null);
mv.visitMethodInsn(
@@ -40,6 +45,13 @@ public class CorePackageRenamerTest {
assertThat(out.mv.owner).isEqualTo("j$/time/Instant");
assertThat(out.mv.desc).isEqualTo("()Lj$/time/Instant;");
+ // Ignore moved methods but not their descriptors
+ mv.visitMethodInsn(
+ Opcodes.INVOKESTATIC, "java/util/A", "m", "()Ljava/time/Instant;", false);
+ assertThat(out.mv.owner).isEqualTo("java/util/A");
+ assertThat(out.mv.desc).isEqualTo("()Lj$/time/Instant;");
+
+ // Ignore arbitrary other methods but not their descriptors
mv.visitMethodInsn(
Opcodes.INVOKESTATIC, "other/time/Instant", "now", "()Ljava/time/Instant;", false);
assertThat(out.mv.owner).isEqualTo("other/time/Instant");
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibraryInvocationRewriter.java b/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibraryInvocationRewriter.java
index e83ae41189..b4bc98b788 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibraryInvocationRewriter.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibraryInvocationRewriter.java
@@ -52,8 +52,18 @@ public class CoreLibraryInvocationRewriter extends ClassVisitor {
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
Class<?> coreInterface =
support.getCoreInterfaceRewritingTarget(opcode, owner, name, desc, itf);
+ String newOwner = support.getMoveTarget(owner, name);
- if (coreInterface != null) {
+ if (newOwner != null) {
+ checkState(coreInterface == null,
+ "Can't move and use companion: %s.%s : %s", owner, name, desc);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ // assuming a static method
+ desc = InterfaceDesugaring.companionDefaultMethodDescriptor(owner, desc);
+ opcode = Opcodes.INVOKESTATIC;
+ }
+ itf = false; // assuming a class
+ } else if (coreInterface != null) {
String coreInterfaceName = coreInterface.getName().replace('.', '/');
name =
InterfaceDesugaring.normalizeInterfaceMethodName(
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibrarySupport.java b/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibrarySupport.java
index 9f0163814e..76eb346b66 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibrarySupport.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/CoreLibrarySupport.java
@@ -16,9 +16,12 @@ package com.google.devtools.build.android.desugar;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
@@ -36,9 +39,12 @@ class CoreLibrarySupport {
private final ImmutableList<String> renamedPrefixes;
/** Internal names of interfaces whose default and static interface methods we'll emulate. */
private final ImmutableList<Class<?>> emulatedInterfaces;
+ /** Map from {@code owner#name} core library members to their new owners. */
+ private final ImmutableMap<String, String> memberMoves;
public CoreLibrarySupport(CoreLibraryRewriter rewriter, ClassLoader targetLoader,
- ImmutableList<String> renamedPrefixes, ImmutableList<String> emulatedInterfaces) {
+ ImmutableList<String> renamedPrefixes, ImmutableList<String> emulatedInterfaces,
+ List<String> memberMoves) {
this.rewriter = rewriter;
this.targetLoader = targetLoader;
checkArgument(
@@ -52,6 +58,23 @@ class CoreLibrarySupport {
classBuilder.add(clazz);
}
this.emulatedInterfaces = classBuilder.build();
+
+ // We can call isRenamed and rename below b/c we initialized the necessary fields above
+ ImmutableMap.Builder<String, String> movesBuilder = ImmutableMap.builder();
+ Splitter splitter = Splitter.on("->").trimResults().omitEmptyStrings();
+ for (String move : memberMoves) {
+ List<String> pair = splitter.splitToList(move);
+ checkArgument(pair.size() == 2, "Doesn't split as expected: %s", move);
+ checkArgument(pair.get(0).startsWith("java/"), "Unexpected member: %s", move);
+ int sep = pair.get(0).indexOf('#');
+ checkArgument(sep > 0 && sep == pair.get(0).lastIndexOf('#'), "invalid member: %s", move);
+ checkArgument(!isRenamedCoreLibrary(pair.get(0).substring(0, sep)),
+ "Original renamed, no need to move it: %s", move);
+ checkArgument(isRenamedCoreLibrary(pair.get(1)), "Target not renamed: %s", move);
+
+ movesBuilder.put(pair.get(0), renameCoreLibrary(pair.get(1)));
+ }
+ this.memberMoves = movesBuilder.build();
}
public boolean isRenamedCoreLibrary(String internalName) {
@@ -73,6 +96,11 @@ class CoreLibrarySupport {
: internalName;
}
+ @Nullable
+ public String getMoveTarget(String owner, String name) {
+ return memberMoves.get(rewriter.unprefix(owner) + '#' + name);
+ }
+
/**
* Returns {@code true} for java.* classes or interfaces that are subtypes of emulated interfaces.
* Note that implies that this method always returns {@code false} for user-written classes.
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java b/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java
index 58b9b885cf..cd55655d53 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java
@@ -271,6 +271,18 @@ class Desugar {
)
public List<String> emulateCoreLibraryInterfaces;
+ /** Members that we will retarget to the given new owner. */
+ @Option(
+ name = "retarget_core_library_member",
+ defaultValue = "", // ignored
+ allowMultiple = true,
+ documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ help = "Method invocations to retarget, given as \"class/Name#member->new/class/Name\". "
+ + "The new owner is blindly assumed to exist."
+ )
+ public List<String> retargetCoreLibraryMembers;
+
/** Set to work around b/62623509 with JaCoCo versions prior to 0.7.9. */
// TODO(kmb): Remove when Android Studio doesn't need it anymore (see b/37116789)
@Option(
@@ -388,7 +400,8 @@ class Desugar {
rewriter,
loader,
ImmutableList.copyOf(options.rewriteCoreLibraryPrefixes),
- ImmutableList.copyOf(options.emulateCoreLibraryInterfaces));
+ ImmutableList.copyOf(options.emulateCoreLibraryInterfaces),
+ options.retargetCoreLibraryMembers);
desugarClassesInInput(
inputFiles,