diff options
author | kmb <kmb@google.com> | 2018-02-24 15:46:40 -0800 |
---|---|---|
committer | Ivan Gavrilovic <gavra@google.com> | 2018-05-04 10:38:57 +0100 |
commit | dc5db10e28ac50cbd3bbbb48ff815267a82907ac (patch) | |
tree | f52607b576ade2d698dae9c18a4c83b33eeaa09d | |
parent | e3ba7606e4f4f8b65c7bebc0b81ecd768bc14abb (diff) | |
download | desugar-dc5db10e28ac50cbd3bbbb48ff815267a82907ac.tar.gz |
Rename and implement emulated interfaces as needed during android desugaring
RELNOTES: None.
PiperOrigin-RevId: 186904092
GitOrigin-RevId: 30af177d5cd2188ee6e23ba849d865b8a42ad8f8
Change-Id: I6ba0cd552638f560bdbfef1ff308ba436a2de720
-rw-r--r-- | java/com/google/devtools/build/android/desugar/Desugar.java | 3 | ||||
-rw-r--r-- | java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java | 65 |
2 files changed, 68 insertions, 0 deletions
diff --git a/java/com/google/devtools/build/android/desugar/Desugar.java b/java/com/google/devtools/build/android/desugar/Desugar.java index cd55655..eee8802 100644 --- a/java/com/google/devtools/build/android/desugar/Desugar.java +++ b/java/com/google/devtools/build/android/desugar/Desugar.java @@ -617,6 +617,7 @@ class Desugar { // Don't need a ClassReaderFactory b/c static interface methods should've been moved. ClassVisitor visitor = writer; if (coreLibrarySupport != null) { + visitor = new EmulatedInterfaceRewriter(visitor, coreLibrarySupport); visitor = new CorePackageRenamer(visitor, coreLibrarySupport); visitor = new CoreLibraryInvocationRewriter(visitor, coreLibrarySupport); } @@ -669,6 +670,7 @@ class Desugar { ClassVisitor visitor = checkNotNull(writer); if (coreLibrarySupport != null) { + visitor = new EmulatedInterfaceRewriter(visitor, coreLibrarySupport); visitor = new CorePackageRenamer(visitor, coreLibrarySupport); visitor = new CoreLibraryInvocationRewriter(visitor, coreLibrarySupport); } @@ -751,6 +753,7 @@ class Desugar { ClassVisitor visitor = checkNotNull(writer); if (coreLibrarySupport != null) { + visitor = new EmulatedInterfaceRewriter(visitor, coreLibrarySupport); visitor = new CorePackageRenamer(visitor, coreLibrarySupport); visitor = new CoreLibraryInvocationRewriter(visitor, coreLibrarySupport); } diff --git a/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java b/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java new file mode 100644 index 0000000..d3e786d --- /dev/null +++ b/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java @@ -0,0 +1,65 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.android.desugar; + +import java.util.ArrayList; +import java.util.Collections; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +/** + * Visitor that renames emulated interfaces and marks classes that extend emulated interfaces to + * also implement the renamed interfaces. {@link DefaultMethodClassFixer} makes sure the requisite + * methods are present. Doing this helps with dynamic dispatch on emulated interfaces. + */ +public class EmulatedInterfaceRewriter extends ClassVisitor { + + private final CoreLibrarySupport support; + + public EmulatedInterfaceRewriter(ClassVisitor dest, CoreLibrarySupport support) { + super(Opcodes.ASM6, dest); + this.support = support; + } + + @Override + public void visit( + int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) { + boolean isEmulated = support.isEmulatedCoreClassOrInterface(name); + if (interfaces != null && interfaces.length > 0 && !isEmulated) { + // Make classes implementing emulated interfaces also implement the renamed interfaces we + // create below. + ArrayList<String> newInterfaces = new ArrayList<>(interfaces.length + 2); + Collections.addAll(newInterfaces, interfaces); + for (String itf : interfaces) { + if (support.isEmulatedCoreClassOrInterface(itf)) { + newInterfaces.add(support.renameCoreLibrary(itf)); + } + } + if (interfaces.length != newInterfaces.size()) { + interfaces = newInterfaces.toArray(interfaces); + signature = null; // additional interfaces invalidate signature + } + } + + if (BitFlags.isInterface(access) && isEmulated) { + name = support.renameCoreLibrary(name); + } + super.visit(version, access, name, signature, superName, interfaces); + } +} |