18daf1cc87a760edfda738e11be41d61776b4e630kmb// Copyright 2017 The Bazel Authors. All rights reserved. 28daf1cc87a760edfda738e11be41d61776b4e630kmb// 38daf1cc87a760edfda738e11be41d61776b4e630kmb// Licensed under the Apache License, Version 2.0 (the "License"); 48daf1cc87a760edfda738e11be41d61776b4e630kmb// you may not use this file except in compliance with the License. 58daf1cc87a760edfda738e11be41d61776b4e630kmb// You may obtain a copy of the License at 68daf1cc87a760edfda738e11be41d61776b4e630kmb// 78daf1cc87a760edfda738e11be41d61776b4e630kmb// http://www.apache.org/licenses/LICENSE-2.0 88daf1cc87a760edfda738e11be41d61776b4e630kmb// 98daf1cc87a760edfda738e11be41d61776b4e630kmb// Unless required by applicable law or agreed to in writing, software 108daf1cc87a760edfda738e11be41d61776b4e630kmb// distributed under the License is distributed on an "AS IS" BASIS, 118daf1cc87a760edfda738e11be41d61776b4e630kmb// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128daf1cc87a760edfda738e11be41d61776b4e630kmb// See the License for the specific language governing permissions and 138daf1cc87a760edfda738e11be41d61776b4e630kmb// limitations under the License. 148daf1cc87a760edfda738e11be41d61776b4e630kmbpackage com.google.devtools.build.android.desugar; 158daf1cc87a760edfda738e11be41d61776b4e630kmb 168daf1cc87a760edfda738e11be41d61776b4e630kmbimport static com.google.common.base.Preconditions.checkNotNull; 178daf1cc87a760edfda738e11be41d61776b4e630kmbimport static com.google.common.base.Preconditions.checkState; 188daf1cc87a760edfda738e11be41d61776b4e630kmb 198daf1cc87a760edfda738e11be41d61776b4e630kmbimport java.util.HashMap; 208daf1cc87a760edfda738e11be41d61776b4e630kmbimport javax.annotation.Nullable; 218daf1cc87a760edfda738e11be41d61776b4e630kmbimport org.objectweb.asm.ClassReader; 228daf1cc87a760edfda738e11be41d61776b4e630kmb 238daf1cc87a760edfda738e11be41d61776b4e630kmb/** 248daf1cc87a760edfda738e11be41d61776b4e630kmb * Simple memoizer for whether types are classes or interfaces. 258daf1cc87a760edfda738e11be41d61776b4e630kmb */ 268daf1cc87a760edfda738e11be41d61776b4e630kmbclass ClassVsInterface { 278daf1cc87a760edfda738e11be41d61776b4e630kmb /** Map from internal names to whether they are an interface ({@code false} thus means class). */ 288daf1cc87a760edfda738e11be41d61776b4e630kmb private final HashMap<String, Boolean> known = new HashMap<>(); 298daf1cc87a760edfda738e11be41d61776b4e630kmb private final ClassReaderFactory classpath; 308daf1cc87a760edfda738e11be41d61776b4e630kmb 318daf1cc87a760edfda738e11be41d61776b4e630kmb public ClassVsInterface(ClassReaderFactory classpath) { 328daf1cc87a760edfda738e11be41d61776b4e630kmb this.classpath = classpath; 338daf1cc87a760edfda738e11be41d61776b4e630kmb } 348daf1cc87a760edfda738e11be41d61776b4e630kmb 358daf1cc87a760edfda738e11be41d61776b4e630kmb public ClassVsInterface addKnownClass(@Nullable String internalName) { 368daf1cc87a760edfda738e11be41d61776b4e630kmb if (internalName != null) { 378daf1cc87a760edfda738e11be41d61776b4e630kmb Boolean previous = known.put(internalName, false); 388daf1cc87a760edfda738e11be41d61776b4e630kmb checkState(previous == null || !previous, "Already recorded as interface: %s", internalName); 398daf1cc87a760edfda738e11be41d61776b4e630kmb } 408daf1cc87a760edfda738e11be41d61776b4e630kmb return this; 418daf1cc87a760edfda738e11be41d61776b4e630kmb } 428daf1cc87a760edfda738e11be41d61776b4e630kmb 438daf1cc87a760edfda738e11be41d61776b4e630kmb public ClassVsInterface addKnownInterfaces(String... internalNames) { 448daf1cc87a760edfda738e11be41d61776b4e630kmb for (String internalName : internalNames) { 458daf1cc87a760edfda738e11be41d61776b4e630kmb Boolean previous = known.put(internalName, true); 468daf1cc87a760edfda738e11be41d61776b4e630kmb checkState(previous == null || previous, "Already recorded as class: %s", internalName); 478daf1cc87a760edfda738e11be41d61776b4e630kmb } 488daf1cc87a760edfda738e11be41d61776b4e630kmb return this; 498daf1cc87a760edfda738e11be41d61776b4e630kmb } 508daf1cc87a760edfda738e11be41d61776b4e630kmb 518daf1cc87a760edfda738e11be41d61776b4e630kmb public boolean isOuterInterface(String outerName, String innerName) { 528daf1cc87a760edfda738e11be41d61776b4e630kmb Boolean result = known.get(outerName); 538daf1cc87a760edfda738e11be41d61776b4e630kmb if (result == null) { 548daf1cc87a760edfda738e11be41d61776b4e630kmb // We could just load the outer class here, but this tolerates incomplete classpaths better. 558daf1cc87a760edfda738e11be41d61776b4e630kmb // Note the outer class should be in the Jar we're desugaring, so it should always be there. 568daf1cc87a760edfda738e11be41d61776b4e630kmb ClassReader outerClass = checkNotNull(classpath.readIfKnown(outerName), 578daf1cc87a760edfda738e11be41d61776b4e630kmb "Couldn't find outer class %s of %s", outerName, innerName); 588daf1cc87a760edfda738e11be41d61776b4e630kmb result = BitFlags.isInterface(outerClass.getAccess()); 598daf1cc87a760edfda738e11be41d61776b4e630kmb known.put(outerName, result); 608daf1cc87a760edfda738e11be41d61776b4e630kmb } 618daf1cc87a760edfda738e11be41d61776b4e630kmb return result; 628daf1cc87a760edfda738e11be41d61776b4e630kmb } 638daf1cc87a760edfda738e11be41d61776b4e630kmb} 64