blob: f52b8b7a39ad3ccbddc11cfa585d015e06d3f0d9 [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.repackaging;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.ParameterAnnotationsList;
public class RepackagingAnnotationTracer {
private final AppInfoWithClassHierarchy appInfo;
private final RepackagingUseRegistry registry;
public RepackagingAnnotationTracer(
AppView<? extends AppInfoWithClassHierarchy> appView, RepackagingUseRegistry registry) {
this.appInfo = appView.appInfo();
this.registry = registry;
}
public void trace(DexAnnotationSet annotations) {
annotations.forEach(this::traceAnnotation);
}
public void trace(ParameterAnnotationsList annotations) {
annotations.forEachAnnotation(this::traceAnnotation);
}
private void traceAnnotation(DexAnnotation annotation) {
traceEncodedAnnotation(annotation.annotation);
}
private void traceEncodedAnnotation(DexEncodedAnnotation annotation) {
registry.registerTypeReference(annotation.type);
annotation.forEachElement(this::traceAnnotationElement);
}
private void traceAnnotationElement(DexAnnotationElement element) {
traceDexValue(element.value);
}
private void traceDexValue(DexValue value) {
switch (value.getValueKind()) {
case BOOLEAN:
case BYTE:
case CHAR:
case DOUBLE:
case FLOAT:
case INT:
case LONG:
case NULL:
case SHORT:
case STRING:
break;
case ANNOTATION:
traceEncodedAnnotation(value.asDexValueAnnotation().getValue());
break;
case ARRAY:
value.asDexValueArray().forEachElement(this::traceDexValue);
break;
case ENUM:
registry.registerFieldAccess(value.asDexValueEnum().getValue());
break;
case FIELD:
registry.registerFieldAccess(value.asDexValueField().getValue());
break;
case METHOD:
registry.registerMethodReference(value.asDexValueMethod().getValue());
break;
case METHOD_HANDLE:
{
DexMethodHandle handle = value.asDexValueMethodHandle().getValue();
if (handle.isFieldHandle()) {
registry.registerFieldAccess(handle.asField());
} else {
assert handle.isMethodHandle();
registry.registerMethodReference(handle.asMethod());
}
}
break;
case METHOD_TYPE:
value.asDexValueMethodType().getValue().forEachType(registry::registerTypeReference);
break;
case TYPE:
registry.registerTypeReference(value.asDexValueType().getValue());
break;
default:
throw new Unreachable();
}
}
}