[epilogue] Add extra parentheses around cast when using varhandle (#7428)

* [epilogue] Add extra parentheses around cast when using varhandle

* Fixed tests and added one for private suppliers

* Fix tests

* Formatting fixes

* Update epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java

Co-authored-by: Gold856 <117957790+Gold856@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gold856 <117957790+Gold856@users.noreply.github.com>
Co-authored-by: Sam Carlberg <sam@slfc.dev>
This commit is contained in:
shueja
2024-12-07 13:09:35 -08:00
committed by GitHub
parent 278efa6384
commit f772bb141d
2 changed files with 60 additions and 5 deletions

View File

@@ -127,8 +127,10 @@ public abstract class ElementHandler {
private static String fieldAccess(VariableElement field) {
if (field.getModifiers().contains(Modifier.PRIVATE)) {
// (com.example.Foo) $fooField.get(object)
return "(" + field.asType() + ") $" + field.getSimpleName() + ".get(object)";
// ((com.example.Foo) $fooField.get(object))
// Extra parentheses so cast evaluates before appended methods
// (e.g. when appending .getAsDouble())
return "((" + field.asType() + ") $" + field.getSimpleName() + ".get(object))";
} else {
// object.fooField
return "object." + field.getSimpleName();

View File

@@ -243,7 +243,7 @@ class AnnotationProcessorTest {
@Override
public void update(EpilogueBackend backend, Example object) {
if (Epilogue.shouldLog(Logged.Importance.DEBUG)) {
backend.log("x", (double) $x.get(object));
backend.log("x", ((double) $x.get(object)));
}
}
}
@@ -252,6 +252,59 @@ class AnnotationProcessorTest {
assertLoggerGenerates(source, expectedGeneratedSource);
}
@Test
void privateSuppliers() {
String source =
"""
package edu.wpi.first.epilogue;
import java.util.function.DoubleSupplier;
@Logged
class Example {
private DoubleSupplier x;
}
""";
String expectedGeneratedSource =
"""
package edu.wpi.first.epilogue;
import edu.wpi.first.epilogue.Logged;
import edu.wpi.first.epilogue.Epilogue;
import edu.wpi.first.epilogue.logging.ClassSpecificLogger;
import edu.wpi.first.epilogue.logging.EpilogueBackend;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public class ExampleLogger extends ClassSpecificLogger<Example> {
private static final VarHandle $x;
static {
try {
var lookup = MethodHandles.privateLookupIn(Example.class, MethodHandles.lookup());
$x = lookup.findVarHandle(Example.class, "x", java.util.function.DoubleSupplier.class);
} catch (ReflectiveOperationException e) {
throw new RuntimeException("[EPILOGUE] Could not load private fields for logging!", e);
}
}
public ExampleLogger() {
super(Example.class);
}
@Override
public void update(EpilogueBackend backend, Example object) {
if (Epilogue.shouldLog(Logged.Importance.DEBUG)) {
backend.log("x", ((java.util.function.DoubleSupplier) $x.get(object)).getAsDouble());
}
}
}
""";
assertLoggerGenerates(source, expectedGeneratedSource);
}
@Test
void privateWithGenerics() {
String source =
@@ -294,7 +347,7 @@ class AnnotationProcessorTest {
@Override
public void update(EpilogueBackend backend, Example object) {
if (Epilogue.shouldLog(Logged.Importance.DEBUG)) {
logSendable(backend.getNested("chooser"), (edu.wpi.first.wpilibj.smartdashboard.SendableChooser<java.lang.String>) $chooser.get(object));
logSendable(backend.getNested("chooser"), ((edu.wpi.first.wpilibj.smartdashboard.SendableChooser<java.lang.String>) $chooser.get(object)));
}
}
}
@@ -1503,7 +1556,7 @@ class AnnotationProcessorTest {
@Override
public void update(EpilogueBackend backend, Example object) {
if (Epilogue.shouldLog(Logged.Importance.DEBUG)) {
var $$theField = (edu.wpi.first.epilogue.I) $theField.get(object);
var $$theField = ((edu.wpi.first.epilogue.I) $theField.get(object));
if ($$theField instanceof edu.wpi.first.epilogue.Base edu_wpi_first_epilogue_Base) {
Epilogue.baseLogger.tryUpdate(backend.getNested("theField"), edu_wpi_first_epilogue_Base, Epilogue.getConfig().errorHandler);
} else {