| // Copyright (c) 2021, 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.desugar.desugaredlibrary.legacyspecification; |
| |
| import com.android.tools.r8.graph.AppView; |
| import com.android.tools.r8.graph.DexClassAndMethod; |
| import com.android.tools.r8.graph.DexEncodedMethod; |
| import com.android.tools.r8.graph.DexItemFactory; |
| import com.android.tools.r8.graph.DexMethod; |
| import com.android.tools.r8.graph.DexReference; |
| import com.android.tools.r8.graph.DexString; |
| import com.android.tools.r8.graph.DexType; |
| import com.android.tools.r8.ir.desugar.PrefixRewritingMapper; |
| import com.android.tools.r8.ir.desugar.PrefixRewritingMapper.DesugarPrefixRewritingMapper; |
| 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 java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| public class LegacyDesugaredLibrarySpecification { |
| |
| private final boolean libraryCompilation; |
| private final LegacyTopLevelFlags topLevelFlags; |
| private final LegacyRewritingFlags rewritingFlags; |
| private final PrefixRewritingMapper prefixRewritingMapper; |
| |
| public static LegacyDesugaredLibrarySpecification withOnlyRewritePrefixForTesting( |
| Map<String, String> prefix, InternalOptions options) { |
| return new LegacyDesugaredLibrarySpecification( |
| LegacyTopLevelFlags.empty(), |
| LegacyRewritingFlags.withOnlyRewritePrefixForTesting(prefix, options), |
| true, |
| options.itemFactory); |
| } |
| |
| public static LegacyDesugaredLibrarySpecification empty() { |
| return new LegacyDesugaredLibrarySpecification( |
| LegacyTopLevelFlags.empty(), LegacyRewritingFlags.empty(), false, null) { |
| |
| @Override |
| public boolean isSupported(DexReference reference, AppView<?> appView) { |
| return false; |
| } |
| |
| @Override |
| public boolean isEmptyConfiguration() { |
| return true; |
| } |
| }; |
| } |
| |
| public LegacyDesugaredLibrarySpecification( |
| LegacyTopLevelFlags topLevelFlags, |
| LegacyRewritingFlags rewritingFlags, |
| boolean libraryCompilation, |
| DexItemFactory factory) { |
| this.libraryCompilation = libraryCompilation; |
| this.topLevelFlags = topLevelFlags; |
| this.rewritingFlags = rewritingFlags; |
| this.prefixRewritingMapper = |
| rewritingFlags.getRewritePrefix().isEmpty() |
| ? PrefixRewritingMapper.empty() |
| : new DesugarPrefixRewritingMapper( |
| rewritingFlags.getRewritePrefix(), factory, libraryCompilation); |
| } |
| |
| public LegacyTopLevelFlags getTopLevelFlags() { |
| return topLevelFlags; |
| } |
| |
| public LegacyRewritingFlags getRewritingFlags() { |
| return rewritingFlags; |
| } |
| |
| public boolean supportAllCallbacksFromLibrary() { |
| return topLevelFlags.supportAllCallbacksFromLibrary(); |
| } |
| |
| public PrefixRewritingMapper getPrefixRewritingMapper() { |
| return prefixRewritingMapper; |
| } |
| |
| public AndroidApiLevel getRequiredCompilationApiLevel() { |
| return topLevelFlags.getRequiredCompilationAPILevel(); |
| } |
| |
| public boolean isLibraryCompilation() { |
| return libraryCompilation; |
| } |
| |
| public String getSynthesizedLibraryClassesPackagePrefix() { |
| return topLevelFlags.getSynthesizedLibraryClassesPackagePrefix(); |
| } |
| |
| // TODO(b/183918843): We are currently computing a new name for the class by replacing the |
| // initial package prefix by the synthesized library class package prefix, it would be better |
| // to make the rewriting explicit in the desugared library json file. |
| public String convertJavaNameToDesugaredLibrary(DexType type) { |
| String prefix = |
| DescriptorUtils.getJavaTypeFromBinaryName(getSynthesizedLibraryClassesPackagePrefix()); |
| String interfaceType = type.toString(); |
| int firstPackage = interfaceType.indexOf('.'); |
| return prefix + interfaceType.substring(firstPackage + 1); |
| } |
| |
| public String getIdentifier() { |
| return topLevelFlags.getIdentifier(); |
| } |
| |
| public Map<String, String> getRewritePrefix() { |
| return rewritingFlags.getRewritePrefix(); |
| } |
| |
| public boolean hasEmulatedLibraryInterfaces() { |
| return !getEmulateLibraryInterface().isEmpty(); |
| } |
| |
| public Map<DexType, DexType> getEmulateLibraryInterface() { |
| return rewritingFlags.getEmulateLibraryInterface(); |
| } |
| |
| public boolean isSupported(DexReference reference, AppView<?> appView) { |
| return prefixRewritingMapper.hasRewrittenType(reference.getContextType(), appView); |
| } |
| |
| // If the method is retargeted, answers the retargeted method, else null. |
| public DexMethod retargetMethod(DexEncodedMethod method, AppView<?> appView) { |
| Map<DexString, Map<DexType, DexType>> retargetCoreLibMember = |
| rewritingFlags.getRetargetCoreLibMember(); |
| Map<DexType, DexType> typeMap = retargetCoreLibMember.get(method.getName()); |
| if (typeMap != null && typeMap.containsKey(method.getHolderType())) { |
| return appView |
| .dexItemFactory() |
| .createMethod( |
| typeMap.get(method.getHolderType()), |
| appView.dexItemFactory().prependHolderToProto(method.getReference()), |
| method.getName()); |
| } |
| return null; |
| } |
| |
| public DexMethod retargetMethod(DexClassAndMethod method, AppView<?> appView) { |
| return retargetMethod(method.getDefinition(), appView); |
| } |
| |
| public Map<DexString, Map<DexType, DexType>> getRetargetCoreLibMember() { |
| return rewritingFlags.getRetargetCoreLibMember(); |
| } |
| |
| public Map<DexType, DexType> getBackportCoreLibraryMember() { |
| return rewritingFlags.getBackportCoreLibraryMember(); |
| } |
| |
| public Map<DexType, DexType> getCustomConversions() { |
| return rewritingFlags.getCustomConversions(); |
| } |
| |
| public Set<DexType> getWrapperConversions() { |
| return rewritingFlags.getWrapperConversions(); |
| } |
| |
| public List<Pair<DexType, DexString>> getDontRewriteInvocation() { |
| return rewritingFlags.getDontRewriteInvocation(); |
| } |
| |
| public Set<DexType> getDontRetargetLibMember() { |
| return rewritingFlags.getDontRetargetLibMember(); |
| } |
| |
| public List<String> getExtraKeepRules() { |
| return topLevelFlags.getExtraKeepRules(); |
| } |
| |
| public String getJsonSource() { |
| return topLevelFlags.getJsonSource(); |
| } |
| |
| public boolean isEmptyConfiguration() { |
| return false; |
| } |
| } |