diff options
author | kmb <kmb@google.com> | 2018-02-24 15:46:40 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-02-24 15:48:42 -0800 |
commit | 30af177d5cd2188ee6e23ba849d865b8a42ad8f8 (patch) | |
tree | 4dfdfd6687f3ee5868ff0dfbf757e8f5ce099f7c /src/tools/android | |
parent | bde43ec8a96a62b8fbf67ad60d5154cf121647d9 (diff) |
Rename and implement emulated interfaces as needed during android desugaring
RELNOTES: None.
PiperOrigin-RevId: 186904092
Diffstat (limited to 'src/tools/android')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java | 3 | ||||
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java | 65 |
2 files changed, 68 insertions, 0 deletions
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 cd55655d53..eee88027b4 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 @@ -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/src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java b/src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java new file mode 100644 index 0000000000..d3e786d3f3 --- /dev/null +++ b/src/tools/android/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); + } +} |