blob: c81a27f84e11077fbe18eafded8fdf3135e25bc4 [file] [log] [blame]
// Copyright (c) 2024, 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.keepanno.doctests;
import com.android.tools.r8.keepanno.annotations.KeepConstraint;
import com.android.tools.r8.keepanno.annotations.KeepItemKind;
import com.android.tools.r8.keepanno.annotations.KeepTarget;
import com.android.tools.r8.keepanno.annotations.UsedByReflection;
import com.android.tools.r8.keepanno.annotations.UsesReflection;
import java.lang.reflect.Type;
/* INCLUDE DOC: GenericSignaturePrinter
Imagine we had code that is making use of the template parameters for implementations of a
generic interface. The code below assumes direct implementations of the `WrappedValue` interface
and simply prints the type parameter used.
Since we are reflecting on the class structure of implementations of `WrappedValue` we need to
keep it and any instance of it.
We must also preserve the generic signatures of these classes. We add the
`@KeepConstraint#GENERIC_SIGNATURE` constraint by using the `@KeepTarget#constraintAdditions`
property. This ensures that the default constraints are still in place in addition to the
constraint on generic signatures.
INCLUDE END */
// INCLUDE CODE: GenericSignaturePrinter
public class GenericSignaturePrinter {
interface WrappedValue<T> {
T getValue();
}
@UsesReflection(
@KeepTarget(
instanceOfClassConstant = WrappedValue.class,
constraintAdditions = KeepConstraint.GENERIC_SIGNATURE))
public static void printSignature(WrappedValue<?> obj) {
Class<? extends WrappedValue> clazz = obj.getClass();
for (Type iface : clazz.getGenericInterfaces()) {
String typeName = iface.getTypeName();
String param = typeName.substring(typeName.lastIndexOf('<') + 1, typeName.lastIndexOf('>'));
System.out.println(clazz.getName() + " uses type " + param);
}
}
// INCLUDE END
static class MyBool implements WrappedValue<Boolean> {
private boolean value;
public MyBool(boolean value) {
this.value = value;
}
@Override
public Boolean getValue() {
return value;
}
}
static class MyString implements WrappedValue<String> {
private String value;
public MyString(String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
}
static class TestClass {
@UsedByReflection(kind = KeepItemKind.CLASS_AND_METHODS)
public static void main(String[] args) throws Exception {
GenericSignaturePrinter.printSignature(new MyString("foo"));
GenericSignaturePrinter.printSignature(new MyBool(true));
}
}
}