blob: 7707d9e3ba69419d6c4cddff736117441ef3b933 [file] [log] [blame]
// Copyright (c) 2020, 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.conversion;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
public class LibraryDesugaredChecker {
private final AppView<?> appView;
private final DexString jDollarDescriptorPrefix;
LibraryDesugaredChecker(AppView<?> appView) {
this.appView = appView;
this.jDollarDescriptorPrefix = appView.dexItemFactory().createString("Lj$/");
}
public boolean isClassLibraryDesugared(DexProgramClass clazz) {
IsLibraryDesugaredTracer tracer =
new IsLibraryDesugaredTracer(appView, jDollarDescriptorPrefix, clazz);
tracer.run();
return tracer.isLibraryDesugared();
}
private static class IsLibraryDesugaredTracer extends UseRegistry {
private final DexString jDollarDescriptorPrefix;
private final AppView<?> appView;
private final DexProgramClass clazz;
private boolean isLibraryDesugared = false;
public IsLibraryDesugaredTracer(
AppView<?> appView, DexString jDollarDescriptorPrefix, DexProgramClass clazz) {
super(appView.dexItemFactory());
this.jDollarDescriptorPrefix = jDollarDescriptorPrefix;
this.appView = appView;
this.clazz = clazz;
}
public void run() {
registerClass(clazz);
}
public boolean isLibraryDesugared() {
return isLibraryDesugared;
}
private void registerClass(DexProgramClass clazz) {
if (clazz.superType != null) {
registerTypeReference(clazz.superType);
}
for (DexType implementsType : clazz.interfaces.values) {
registerTypeReference(implementsType);
}
if (isLibraryDesugared) {
return;
}
for (DexEncodedMethod method : clazz.methods()) {
registerMethod(new ProgramMethod(clazz, method));
if (isLibraryDesugared) {
return;
}
}
clazz.forEachField(this::registerField);
}
private void registerType(DexType type) {
isLibraryDesugared =
isLibraryDesugared || type.descriptor.startsWith(jDollarDescriptorPrefix);
}
private void registerField(DexField field) {
registerType(field.getHolderType());
registerType(field.getType());
}
private void registerMethod(DexMethod method) {
for (DexType type : method.getParameters().values) {
registerTypeReference(type);
}
registerTypeReference(method.getReturnType());
}
private void registerField(DexEncodedField field) {
registerField(field.getReference());
}
private void registerMethod(ProgramMethod method) {
registerMethod(method.getReference());
for (DexAnnotation annotation : method.getDefinition().annotations().annotations) {
if (annotation.annotation.type == appView.dexItemFactory().annotationThrows) {
DexValueArray dexValues = annotation.annotation.elements[0].value.asDexValueArray();
for (DexValue dexValType : dexValues.getValues()) {
registerType(dexValType.asDexValueType().value);
}
}
}
method.registerCodeReferences(this);
}
@Override
public void registerInitClass(DexType type) {
registerType(type);
}
@Override
public void registerInvokeVirtual(DexMethod method) {
registerMethod(method);
}
@Override
public void registerInvokeDirect(DexMethod method) {
registerMethod(method);
}
@Override
public void registerInvokeStatic(DexMethod method) {
registerMethod(method);
}
@Override
public void registerInvokeInterface(DexMethod method) {
registerMethod(method);
}
@Override
public void registerInvokeStatic(DexMethod method, boolean itf) {
registerMethod(method);
}
@Override
public void registerInvokeSuper(DexMethod method) {
registerMethod(method);
}
@Override
public void registerInstanceFieldRead(DexField field) {
registerField(field);
}
@Override
public void registerInstanceFieldWrite(DexField field) {
registerField(field);
}
@Override
public void registerNewInstance(DexType type) {
registerType(type);
}
@Override
public void registerStaticFieldRead(DexField field) {
registerField(field);
}
@Override
public void registerStaticFieldWrite(DexField field) {
registerField(field);
}
@Override
public void registerTypeReference(DexType type) {
registerType(type);
}
@Override
public void registerInstanceOf(DexType type) {
registerType(type);
}
}
}