diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/ElementHandler.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/ElementHandler.java index 894225046f8..b3ccee6f80a 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/ElementHandler.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/ElementHandler.java @@ -127,8 +127,10 @@ public String elementAccess(Element element) { 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(); diff --git a/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java b/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java index 19b2ae43d1a..b3ae8c22433 100644 --- a/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java +++ b/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java @@ -141,7 +141,7 @@ public ExampleLogger() { @Override public void update(DataLogger dataLogger, Example object) { if (Epilogue.shouldLog(Logged.Importance.DEBUG)) { - dataLogger.log("x", (double) $x.get(object)); + dataLogger.log("x", ((double) $x.get(object))); } } } @@ -150,6 +150,59 @@ public void update(DataLogger dataLogger, Example object) { 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.DataLogger; + import java.lang.invoke.MethodHandles; + import java.lang.invoke.VarHandle; + + public class ExampleLogger extends ClassSpecificLogger { + 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(DataLogger dataLogger, Example object) { + if (Epilogue.shouldLog(Logged.Importance.DEBUG)) { + dataLogger.log("x", ((java.util.function.DoubleSupplier) $x.get(object)).getAsDouble()); + } + } + } + """; + + assertLoggerGenerates(source, expectedGeneratedSource); + } + @Test void privateWithGenerics() { String source = @@ -192,7 +245,7 @@ public ExampleLogger() { @Override public void update(DataLogger dataLogger, Example object) { if (Epilogue.shouldLog(Logged.Importance.DEBUG)) { - logSendable(dataLogger.getSubLogger("chooser"), (edu.wpi.first.wpilibj.smartdashboard.SendableChooser) $chooser.get(object)); + logSendable(dataLogger.getSubLogger("chooser"), ((edu.wpi.first.wpilibj.smartdashboard.SendableChooser) $chooser.get(object))); } } } @@ -1275,7 +1328,7 @@ public ExampleLogger() { @Override public void update(DataLogger dataLogger, 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(dataLogger.getSubLogger("theField"), edu_wpi_first_epilogue_Base, Epilogue.getConfig().errorHandler); } else {