blob: c94302853b8794e7d7782b54b4aa3103152b2466 [file] [log] [blame]
// Copyright (c) 2022, 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;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.utils.Reporter;
import java.util.Map;
/**
* The LibraryAmender is responsible in amending the library so that desugared library can be
* applied. For example, it can insert missing methods which are not present in the library but are
* supported in desugared library.
*/
public class DesugaredLibraryAmender {
private final DexDefinitionSupplier definitions;
private final Reporter reporter;
private final ComputedApiLevel minAPILevel;
public static void run(AppView<?> appView) {
run(
appView.options().machineDesugaredLibrarySpecification.getAmendLibraryMethods(),
appView,
appView.options().reporter,
appView.computedMinApiLevel());
}
public static void run(
Map<DexMethod, MethodAccessFlags> amendLibrary,
DexDefinitionSupplier definitions,
Reporter reporter,
ComputedApiLevel minAPILevel) {
if (amendLibrary.isEmpty()) {
return;
}
new DesugaredLibraryAmender(definitions, reporter, minAPILevel).run(amendLibrary);
}
private DesugaredLibraryAmender(
DexDefinitionSupplier definitions, Reporter reporter, ComputedApiLevel minAPILevel) {
this.definitions = definitions;
this.reporter = reporter;
this.minAPILevel = minAPILevel;
}
private void run(Map<DexMethod, MethodAccessFlags> amendLibrary) {
amendLibrary.forEach(this::amendLibraryMethod);
}
private void amendLibraryMethod(DexMethod method, MethodAccessFlags methodAccessFlags) {
DexClass dexClass = definitions.contextIndependentDefinitionFor(method.getHolderType());
if (dexClass == null || !dexClass.isLibraryClass()) {
// Consider just throwing an error.
reporter.warning(
"Desugared library: Cannot amend library method "
+ method
+ " because the holder is not a library class"
+ (dexClass == null ? "(null)." : "."));
return;
}
if (dexClass.lookupMethod(method) != null) {
return;
}
DexEncodedMethod encodedMethod =
DexEncodedMethod.syntheticBuilder()
.setMethod(method)
.setAccessFlags(methodAccessFlags)
.setCode(null)
.setApiLevelForDefinition(minAPILevel)
.build();
dexClass.getMethodCollection().addMethod(encodedMethod);
}
}