From e39552c5402726bb00af7ebc069d8b84faa58d0a Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Fri, 13 Dec 2024 20:14:52 -0500 Subject: [PATCH 1/8] initial --- .../processor/AnnotationProcessor.java | 9 ++- .../processor/AnnotationProcessorTest.java | 55 ++++++++++++++++ epilogue-runtime/build.gradle | 1 + .../first/epilogue/EpilogueConfiguration.java | 5 +- .../first/epilogue/logging/FileBackend.java | 6 ++ ...{NTEpilogueBackend.java => NTBackend.java} | 66 ++++++++++++++++++- 6 files changed, 136 insertions(+), 6 deletions(-) rename epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/{NTEpilogueBackend.java => NTBackend.java} (72%) diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java index 2781c055c8c..abae9b7aeae 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java @@ -143,12 +143,19 @@ private Set getLoggedTypes(RoundEnvironment roundEnv) { annotatedElements.stream() .filter(e -> e instanceof TypeElement) .map(e -> (TypeElement) e), - // 2. All type elements containing a field or method with the @Logged annotation + // 2. All type elements containing a field or method with the @Logged annotation, + // or interfaces which have an implementing class with an @Logged annotation annotatedElements.stream() .filter(e -> e instanceof VariableElement || e instanceof ExecutableElement) .map(Element::getEnclosingElement) .filter(e -> e instanceof TypeElement) .map(e -> (TypeElement) e)) + .flatMap( + e -> + Stream.concat( + Stream.of(e), + e.getInterfaces().stream() + .map(i -> (TypeElement) ((DeclaredType) i).asElement()))) .sorted(Comparator.comparing(e -> e.getSimpleName().toString())) .collect( Collectors.toCollection(LinkedHashSet::new)); // Collect to a set to avoid duplicates 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 ec4e52d5f4f..4661fe83a19 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 @@ -99,6 +99,61 @@ public void update(EpilogueBackend backend, Example object) { assertLoggerGenerates(source, expectedGeneratedSource); } + @Test + void optInInheritance() { + String source = + """ + package edu.wpi.first.epilogue; + + class Example { + @Logged public ABC inst = new Base2(); + } + + class Base implements ABC { + double x; + } + + class Base2 implements ABC { + @Logged double x; + } + + interface ABC { + default double a() { return 2.0; } + } + """; + + 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; + + public class ExampleLogger extends ClassSpecificLogger { + public ExampleLogger() { + super(Example.class); + } + + @Override + public void update(EpilogueBackend backend, Example object) { + if (Epilogue.shouldLog(Logged.Importance.DEBUG)) { + var $$inst = object.inst; + if ($$inst instanceof edu.wpi.first.epilogue.Base2 edu_wpi_first_epilogue_Base2) { + Epilogue.base2Logger.tryUpdate(backend.getNested("inst"), edu_wpi_first_epilogue_Base2, Epilogue.getConfig().errorHandler); + } else { + // Base type edu.wpi.first.epilogue.ABC + Epilogue.abcLogger.tryUpdate(backend.getNested("inst"), $$inst, Epilogue.getConfig().errorHandler); + }; + } + } + } + """; + + assertLoggerGenerates(source, expectedGeneratedSource); + } + @Test void optInMethods() { String source = diff --git a/epilogue-runtime/build.gradle b/epilogue-runtime/build.gradle index fb96095a0a5..303c090c9c7 100644 --- a/epilogue-runtime/build.gradle +++ b/epilogue-runtime/build.gradle @@ -13,4 +13,5 @@ dependencies { api(project(':ntcore')) api(project(':wpiutil')) api(project(':wpiunits')) + api(project(':wpilibj')) } diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java index a35f98d41a4..96111dea531 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java @@ -5,10 +5,9 @@ package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.epilogue.logging.NTEpilogueBackend; +import edu.wpi.first.epilogue.logging.NTBackend; import edu.wpi.first.epilogue.logging.errors.ErrorHandler; import edu.wpi.first.epilogue.logging.errors.ErrorPrinter; -import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.units.measure.Time; /** @@ -22,7 +21,7 @@ public class EpilogueConfiguration { * NetworkTables. NetworkTable data can be mirrored to a log file on disk by calling {@code * DataLogManager.start()} in your {@code robotInit} method. */ - public EpilogueBackend backend = new NTEpilogueBackend(NetworkTableInstance.getDefault()); + public EpilogueBackend backend = new NTBackend(); /** * The period Epilogue will log at. By default this is the period that the robot runs at. This is diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java index 2b5b6b2071b..6b6a82b3a09 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java @@ -22,6 +22,7 @@ import edu.wpi.first.util.datalog.StructArrayLogEntry; import edu.wpi.first.util.datalog.StructLogEntry; import edu.wpi.first.util.struct.Struct; +import edu.wpi.first.wpilibj.DataLogManager; import java.util.HashMap; import java.util.Map; import java.util.function.BiFunction; @@ -41,6 +42,11 @@ public FileBackend(DataLog dataLog) { this.m_dataLog = requireNonNullParam(dataLog, "dataLog", "FileBackend"); } + /** Creates a new file-based backend. */ + public FileBackend() { + this(DataLogManager.getLog()); + } + @Override public EpilogueBackend getNested(String path) { return m_subLoggers.computeIfAbsent(path, k -> new NestedBackend(k, this)); diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTEpilogueBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java similarity index 72% rename from epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTEpilogueBackend.java rename to epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java index cf381a2f021..22406bfc303 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTEpilogueBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java @@ -22,13 +22,15 @@ import edu.wpi.first.util.struct.Struct; import java.util.HashMap; import java.util.Map; +import java.util.function.BooleanSupplier; /** * A backend implementation that sends data over network tables. Be careful when using this, since * sending too much data may cause bandwidth or CPU starvation. */ -public class NTEpilogueBackend implements EpilogueBackend { +public class NTBackend implements EpilogueBackend { private final NetworkTableInstance m_nt; + private BooleanSupplier m_enabledSupplier; private final Map m_publishers = new HashMap<>(); private final Map m_nestedBackends = new HashMap<>(); @@ -38,10 +40,25 @@ public class NTEpilogueBackend implements EpilogueBackend { * * @param nt the NetworkTable instance to use to send data to */ - public NTEpilogueBackend(NetworkTableInstance nt) { + public NTBackend(NetworkTableInstance nt) { this.m_nt = nt; } + /** Creates a logging backend that sends information to NetworkTables. */ + public NTBackend() { + this.m_nt = NetworkTableInstance.getDefault(); + } + + /** + * Creates a logging backend that sends information to NetworkTables. + * + * @param enabledSupplier whether to enable networktables logging + */ + public NTBackend(BooleanSupplier enabledSupplier) { + this.m_nt = NetworkTableInstance.getDefault(); + this.m_enabledSupplier = enabledSupplier; + } + @Override public EpilogueBackend getNested(String path) { return m_nestedBackends.computeIfAbsent(path, k -> new NestedBackend(k, this)); @@ -49,6 +66,9 @@ public EpilogueBackend getNested(String path) { @Override public void log(String identifier, int value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((IntegerPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getIntegerTopic(k).publish())) .set(value); @@ -56,6 +76,9 @@ public void log(String identifier, int value) { @Override public void log(String identifier, long value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((IntegerPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getIntegerTopic(k).publish())) .set(value); @@ -63,6 +86,9 @@ public void log(String identifier, long value) { @Override public void log(String identifier, float value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((FloatPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getFloatTopic(k).publish())) .set(value); @@ -70,6 +96,9 @@ public void log(String identifier, float value) { @Override public void log(String identifier, double value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((DoublePublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getDoubleTopic(k).publish())) .set(value); @@ -77,6 +106,9 @@ public void log(String identifier, double value) { @Override public void log(String identifier, boolean value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((BooleanPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getBooleanTopic(k).publish())) .set(value); @@ -84,6 +116,9 @@ public void log(String identifier, boolean value) { @Override public void log(String identifier, byte[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((RawPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getRawTopic(k).publish("raw"))) .set(value); @@ -92,6 +127,9 @@ public void log(String identifier, byte[] value) { @Override @SuppressWarnings("PMD.UnnecessaryCastRule") public void log(String identifier, int[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } // NT backend only supports int64[], so we have to manually widen to 64 bits before sending long[] widened = new long[value.length]; @@ -106,6 +144,9 @@ public void log(String identifier, int[] value) { @Override public void log(String identifier, long[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((IntegerArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getIntegerArrayTopic(k).publish())) .set(value); @@ -113,6 +154,9 @@ public void log(String identifier, long[] value) { @Override public void log(String identifier, float[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((FloatArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getFloatArrayTopic(k).publish())) .set(value); @@ -120,6 +164,9 @@ public void log(String identifier, float[] value) { @Override public void log(String identifier, double[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((DoubleArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getDoubleArrayTopic(k).publish())) .set(value); @@ -127,6 +174,9 @@ public void log(String identifier, double[] value) { @Override public void log(String identifier, boolean[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((BooleanArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getBooleanArrayTopic(k).publish())) .set(value); @@ -134,6 +184,9 @@ public void log(String identifier, boolean[] value) { @Override public void log(String identifier, String value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((StringPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getStringTopic(k).publish())) .set(value); @@ -141,6 +194,9 @@ public void log(String identifier, String value) { @Override public void log(String identifier, String[] value) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } ((StringArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getStringArrayTopic(k).publish())) .set(value); @@ -149,6 +205,9 @@ public void log(String identifier, String[] value) { @Override @SuppressWarnings("unchecked") public void log(String identifier, S value, Struct struct) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } m_nt.addSchema(struct); ((StructPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getStructTopic(k, struct).publish())) @@ -158,6 +217,9 @@ public void log(String identifier, S value, Struct struct) { @Override @SuppressWarnings("unchecked") public void log(String identifier, S[] value, Struct struct) { + if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + return; + } m_nt.addSchema(struct); ((StructArrayPublisher) m_publishers.computeIfAbsent( From 06b4233114911b2f8006e9cd9c5ae125040d32d0 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Sat, 14 Dec 2024 11:58:17 -0500 Subject: [PATCH 2/8] Improved api --- .../wpi/first/epilogue/logging/NTBackend.java | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java index 22406bfc303..ba2b4de4ff3 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java @@ -30,7 +30,7 @@ */ public class NTBackend implements EpilogueBackend { private final NetworkTableInstance m_nt; - private BooleanSupplier m_enabledSupplier; + private BooleanSupplier m_disabledSupplier; private final Map m_publishers = new HashMap<>(); private final Map m_nestedBackends = new HashMap<>(); @@ -49,14 +49,16 @@ public NTBackend() { this.m_nt = NetworkTableInstance.getDefault(); } - /** - * Creates a logging backend that sends information to NetworkTables. - * - * @param enabledSupplier whether to enable networktables logging - */ - public NTBackend(BooleanSupplier enabledSupplier) { - this.m_nt = NetworkTableInstance.getDefault(); - this.m_enabledSupplier = enabledSupplier; + /** Creates a new NTBackend that is disabled whenever the disabledSupplier returns true. */ + public NTBackend disableWhen(BooleanSupplier disabledSupplier) { + var newBackend = new NTBackend(this.m_nt); + if (m_disabledSupplier == null) { + newBackend.m_disabledSupplier = disabledSupplier; + } else { + newBackend.m_disabledSupplier = + () -> m_disabledSupplier.getAsBoolean() || disabledSupplier.getAsBoolean(); + } + return newBackend; } @Override @@ -66,7 +68,7 @@ public EpilogueBackend getNested(String path) { @Override public void log(String identifier, int value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((IntegerPublisher) @@ -76,7 +78,7 @@ public void log(String identifier, int value) { @Override public void log(String identifier, long value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((IntegerPublisher) @@ -86,7 +88,7 @@ public void log(String identifier, long value) { @Override public void log(String identifier, float value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((FloatPublisher) @@ -96,7 +98,7 @@ public void log(String identifier, float value) { @Override public void log(String identifier, double value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((DoublePublisher) @@ -106,7 +108,7 @@ public void log(String identifier, double value) { @Override public void log(String identifier, boolean value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((BooleanPublisher) @@ -116,7 +118,7 @@ public void log(String identifier, boolean value) { @Override public void log(String identifier, byte[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((RawPublisher) @@ -127,7 +129,7 @@ public void log(String identifier, byte[] value) { @Override @SuppressWarnings("PMD.UnnecessaryCastRule") public void log(String identifier, int[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } // NT backend only supports int64[], so we have to manually widen to 64 bits before sending @@ -144,7 +146,7 @@ public void log(String identifier, int[] value) { @Override public void log(String identifier, long[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((IntegerArrayPublisher) @@ -154,7 +156,7 @@ public void log(String identifier, long[] value) { @Override public void log(String identifier, float[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((FloatArrayPublisher) @@ -164,7 +166,7 @@ public void log(String identifier, float[] value) { @Override public void log(String identifier, double[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((DoubleArrayPublisher) @@ -174,7 +176,7 @@ public void log(String identifier, double[] value) { @Override public void log(String identifier, boolean[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((BooleanArrayPublisher) @@ -184,7 +186,7 @@ public void log(String identifier, boolean[] value) { @Override public void log(String identifier, String value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((StringPublisher) @@ -194,7 +196,7 @@ public void log(String identifier, String value) { @Override public void log(String identifier, String[] value) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } ((StringArrayPublisher) @@ -205,7 +207,7 @@ public void log(String identifier, String[] value) { @Override @SuppressWarnings("unchecked") public void log(String identifier, S value, Struct struct) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } m_nt.addSchema(struct); @@ -217,7 +219,7 @@ public void log(String identifier, S value, Struct struct) { @Override @SuppressWarnings("unchecked") public void log(String identifier, S[] value, Struct struct) { - if (m_enabledSupplier != null && !m_enabledSupplier.getAsBoolean()) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { return; } m_nt.addSchema(struct); From 9ed9912ceadef9dbab64b820344a169fc3bef536 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Sat, 14 Dec 2024 12:21:21 -0500 Subject: [PATCH 3/8] Added forgotten docs --- .../main/java/edu/wpi/first/epilogue/logging/NTBackend.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java index ba2b4de4ff3..3a7e675baf1 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java @@ -49,7 +49,11 @@ public NTBackend() { this.m_nt = NetworkTableInstance.getDefault(); } - /** Creates a new NTBackend that is disabled whenever the disabledSupplier returns true. */ + /** + * Creates a new NTBackend that is disabled whenever the disabledSupplier returns true. + * + * @param disabledSupplier the disable condition for NT logging + */ public NTBackend disableWhen(BooleanSupplier disabledSupplier) { var newBackend = new NTBackend(this.m_nt); if (m_disabledSupplier == null) { From 4aadccb51fbdfada518e2e9d7a6b1ff8907b7cf2 Mon Sep 17 00:00:00 2001 From: Daniel Chen <108989218+Daniel1464@users.noreply.github.com> Date: Sat, 14 Dec 2024 13:12:03 -0500 Subject: [PATCH 4/8] Added forgotten @return --- .../src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java | 1 + 1 file changed, 1 insertion(+) diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java index 3a7e675baf1..aaac8dfa27d 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java @@ -53,6 +53,7 @@ public NTBackend() { * Creates a new NTBackend that is disabled whenever the disabledSupplier returns true. * * @param disabledSupplier the disable condition for NT logging + * @return a new NTBackend */ public NTBackend disableWhen(BooleanSupplier disabledSupplier) { var newBackend = new NTBackend(this.m_nt); From 82f929d6c2efaef7bf2c529225835adcc583697d Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Tue, 24 Dec 2024 12:37:23 -0500 Subject: [PATCH 5/8] Reverted annotation processor changes --- .../processor/AnnotationProcessor.java | 143 +++++++++--------- .../processor/AnnotationProcessorTest.java | 55 ------- 2 files changed, 68 insertions(+), 130 deletions(-) diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java index abae9b7aeae..384be368820 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java @@ -37,8 +37,8 @@ import javax.tools.Diagnostic; @SupportedAnnotationTypes({ - "edu.wpi.first.epilogue.CustomLoggerFor", - "edu.wpi.first.epilogue.Logged" + "edu.wpi.first.epilogue.CustomLoggerFor", + "edu.wpi.first.epilogue.Logged" }) @SupportedSourceVersion(SourceVersion.RELEASE_17) public class AnnotationProcessor extends AbstractProcessor { @@ -46,20 +46,20 @@ public class AnnotationProcessor extends AbstractProcessor { private static final String kClassSpecificLoggerFqn = "edu.wpi.first.epilogue.logging.ClassSpecificLogger"; private static final String kLoggedFqn = "edu.wpi.first.epilogue.Logged"; - + private EpilogueGenerator m_epiloguerGenerator; private LoggerGenerator m_loggerGenerator; private List m_handlers; - + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (annotations.isEmpty()) { // Nothing to do, don't claim return false; } - + Map customLoggers = new HashMap<>(); - + annotations.stream() .filter(ann -> kCustomLoggerFqn.contentEquals(ann.getQualifiedName())) .findAny() @@ -67,7 +67,7 @@ public boolean process(Set annotations, RoundEnvironment customLogger -> { customLoggers.putAll(processCustomLoggers(roundEnv, customLogger)); }); - + roundEnv.getRootElements().stream() .filter( e -> @@ -92,9 +92,9 @@ public boolean process(Set annotations, RoundEnvironment "[EPILOGUE] Custom logger classes should have a @CustomLoggerFor annotation", e); }); - + var loggedTypes = getLoggedTypes(roundEnv); - + // Handlers are declared in order of priority. If an element could be logged in more than one // way (eg a class implements both Sendable and StructSerializable), the order of the handlers // in this list will determine how it gets logged. @@ -112,10 +112,10 @@ public boolean process(Set annotations, RoundEnvironment new SupplierHandler(processingEnv), new StructHandler(processingEnv), // prioritize struct over sendable new SendableHandler(processingEnv)); - + m_epiloguerGenerator = new EpilogueGenerator(processingEnv, customLoggers); m_loggerGenerator = new LoggerGenerator(processingEnv, m_handlers); - + annotations.stream() .filter(ann -> kLoggedFqn.contentEquals(ann.getQualifiedName())) .findAny() @@ -123,10 +123,10 @@ public boolean process(Set annotations, RoundEnvironment epilogue -> { processEpilogue(roundEnv, epilogue, loggedTypes); }); - + return false; } - + /** * Gets the set of all loggable types in the compilation unit. A type is considered loggable if it * is directly annotated with {@code @Logged} or contains a field or method with a {@code @Logged} @@ -143,33 +143,26 @@ private Set getLoggedTypes(RoundEnvironment roundEnv) { annotatedElements.stream() .filter(e -> e instanceof TypeElement) .map(e -> (TypeElement) e), - // 2. All type elements containing a field or method with the @Logged annotation, - // or interfaces which have an implementing class with an @Logged annotation + // 2. All type elements containing a field or method with the @Logged annotation annotatedElements.stream() .filter(e -> e instanceof VariableElement || e instanceof ExecutableElement) .map(Element::getEnclosingElement) .filter(e -> e instanceof TypeElement) .map(e -> (TypeElement) e)) - .flatMap( - e -> - Stream.concat( - Stream.of(e), - e.getInterfaces().stream() - .map(i -> (TypeElement) ((DeclaredType) i).asElement()))) - .sorted(Comparator.comparing(e -> e.getSimpleName().toString())) - .collect( - Collectors.toCollection(LinkedHashSet::new)); // Collect to a set to avoid duplicates + .sorted(Comparator.comparing(e -> e.getSimpleName().toString())) + .collect( + Collectors.toCollection(LinkedHashSet::new)); // Collect to a set to avoid duplicates } - + private boolean validateFields(Set annotatedElements) { var fields = annotatedElements.stream() .filter(e -> e instanceof VariableElement) .map(e -> (VariableElement) e) .toList(); - + boolean valid = true; - + for (VariableElement field : fields) { // Field is explicitly tagged // And is not opted out of @@ -187,16 +180,16 @@ private boolean validateFields(Set annotatedElements) { } return valid; } - + private boolean validateMethods(Set annotatedElements) { var methods = annotatedElements.stream() .filter(e -> e instanceof ExecutableElement) .map(e -> (ExecutableElement) e) .toList(); - + boolean valid = true; - + for (ExecutableElement method : methods) { // Field is explicitly tagged if (method.getAnnotation(NotLogged.class) == null) { @@ -212,36 +205,36 @@ private boolean validateMethods(Set annotatedElements) { method); valid = false; } - + if (!method.getModifiers().contains(Modifier.PUBLIC)) { // Only public methods can be logged - + processingEnv .getMessager() .printMessage( Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods must be public", method); - + valid = false; } - + if (method.getModifiers().contains(Modifier.STATIC)) { processingEnv .getMessager() .printMessage( Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods cannot be static", method); - + valid = false; } - + if (method.getReturnType().getKind() == TypeKind.NONE) { processingEnv .getMessager() .printMessage( Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods cannot be void", method); - + valid = false; } - + if (!method.getParameters().isEmpty()) { processingEnv .getMessager() @@ -249,14 +242,14 @@ private boolean validateMethods(Set annotatedElements) { Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods cannot accept arguments", method); - + valid = false; } } } return valid; } - + /** * Checks if a type is not loggable. * @@ -267,13 +260,13 @@ private boolean isNotLoggable(Element element, TypeMirror type) { // e.g. void, cannot log return true; } - + boolean loggable = m_handlers.stream().anyMatch(h -> h.isLoggable(element)); - + if (loggable) { return false; } - + processingEnv .getMessager() .printMessage( @@ -282,21 +275,21 @@ private boolean isNotLoggable(Element element, TypeMirror type) { element); return true; } - + @SuppressWarnings("unchecked") private Map processCustomLoggers( RoundEnvironment roundEnv, TypeElement customLoggerAnnotation) { // map logged type to its custom logger, eg // { Point.class => CustomPointLogger.class } var customLoggers = new HashMap(); - + var annotatedElements = roundEnv.getElementsAnnotatedWith(customLoggerAnnotation); - + var loggerSuperClass = processingEnv .getElementUtils() .getTypeElement("edu.wpi.first.epilogue.logging.ClassSpecificLogger"); - + for (Element annotatedElement : annotatedElements) { List targetTypes = List.of(); for (AnnotationMirror annotationMirror : annotatedElement.getAnnotationMirrors()) { @@ -306,7 +299,7 @@ private Map processCustomLoggers( } } } - + boolean hasPublicNoArgConstructor = annotatedElement.getEnclosedElements().stream() .anyMatch( @@ -315,7 +308,7 @@ private Map processCustomLoggers( && exe.getKind() == ElementKind.CONSTRUCTOR && exe.getModifiers().contains(Modifier.PUBLIC) && exe.getParameters().isEmpty()); - + if (!hasPublicNoArgConstructor) { processingEnv .getMessager() @@ -325,11 +318,11 @@ private Map processCustomLoggers( annotatedElement); continue; } - + for (AnnotationValue value : targetTypes) { var targetType = (DeclaredType) value.getValue(); var reflectedTarget = targetType.asElement(); - + // eg ClassSpecificLogger var requiredSuperClass = processingEnv @@ -337,7 +330,7 @@ private Map processCustomLoggers( .getDeclaredType( loggerSuperClass, processingEnv.getTypeUtils().getWildcardType(null, reflectedTarget.asType())); - + if (customLoggers.containsKey(targetType)) { processingEnv .getMessager() @@ -347,7 +340,7 @@ private Map processCustomLoggers( annotatedElement); continue; } - + if (annotatedElement instanceof TypeElement t && !t.getTypeParameters().isEmpty()) { processingEnv .getMessager() @@ -357,10 +350,10 @@ private Map processCustomLoggers( annotatedElement); continue; } - + if (!processingEnv - .getTypeUtils() - .isAssignable(annotatedElement.asType(), requiredSuperClass)) { + .getTypeUtils() + .isAssignable(annotatedElement.asType(), requiredSuperClass)) { processingEnv .getMessager() .printMessage( @@ -369,42 +362,42 @@ private Map processCustomLoggers( annotatedElement); continue; } - + customLoggers.put(targetType, (DeclaredType) annotatedElement.asType()); } } - + return customLoggers; } - + private void processEpilogue( RoundEnvironment roundEnv, TypeElement epilogueAnnotation, Set loggedTypes) { var annotatedElements = roundEnv.getElementsAnnotatedWith(epilogueAnnotation); - + List loggerClassNames = new ArrayList<>(); var mainRobotClasses = new ArrayList(); - + // Used to check for a main robot class var robotBaseClass = processingEnv.getElementUtils().getTypeElement("edu.wpi.first.wpilibj.TimedRobot").asType(); - + boolean validFields = validateFields(annotatedElements); boolean validMethods = validateMethods(annotatedElements); - + if (!(validFields && validMethods)) { // Generate nothing and bail return; } - + for (TypeElement clazz : loggedTypes) { try { warnOfNonLoggableElements(clazz); m_loggerGenerator.writeLoggerFile(clazz); - + if (processingEnv.getTypeUtils().isAssignable(clazz.getSuperclass(), robotBaseClass)) { mainRobotClasses.add(clazz); } - + loggerClassNames.add(StringUtils.loggerClassName(clazz)); } catch (IOException e) { processingEnv @@ -416,41 +409,41 @@ private void processEpilogue( e.printStackTrace(System.err); } } - + // Sort alphabetically mainRobotClasses.sort(Comparator.comparing(c -> c.getSimpleName().toString())); m_epiloguerGenerator.writeEpilogueFile(loggerClassNames, mainRobotClasses); } - + private void warnOfNonLoggableElements(TypeElement clazz) { var config = clazz.getAnnotation(Logged.class); if (config == null || config.strategy() == Logged.Strategy.OPT_IN) { // field and method validations will have already checked everything return; } - + for (Element element : clazz.getEnclosedElements()) { if (element.getAnnotation(NotLogged.class) != null) { // Explicitly opted out from, don't need to check continue; } - + if (element.getModifiers().contains(Modifier.STATIC)) { // static elements are never logged continue; } - + if (element instanceof VariableElement v) { // isNotLoggable will internally print a warning message isNotLoggable(v, v.asType()); } - + if (element instanceof ExecutableElement exe - && exe.getModifiers().contains(Modifier.PUBLIC) - && exe.getParameters().isEmpty()) { + && exe.getModifiers().contains(Modifier.PUBLIC) + && exe.getParameters().isEmpty()) { // isNotLoggable will internally print a warning message isNotLoggable(exe, exe.getReturnType()); } } } -} +} \ No newline at end of file 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 4661fe83a19..ec4e52d5f4f 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 @@ -99,61 +99,6 @@ public void update(EpilogueBackend backend, Example object) { assertLoggerGenerates(source, expectedGeneratedSource); } - @Test - void optInInheritance() { - String source = - """ - package edu.wpi.first.epilogue; - - class Example { - @Logged public ABC inst = new Base2(); - } - - class Base implements ABC { - double x; - } - - class Base2 implements ABC { - @Logged double x; - } - - interface ABC { - default double a() { return 2.0; } - } - """; - - 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; - - public class ExampleLogger extends ClassSpecificLogger { - public ExampleLogger() { - super(Example.class); - } - - @Override - public void update(EpilogueBackend backend, Example object) { - if (Epilogue.shouldLog(Logged.Importance.DEBUG)) { - var $$inst = object.inst; - if ($$inst instanceof edu.wpi.first.epilogue.Base2 edu_wpi_first_epilogue_Base2) { - Epilogue.base2Logger.tryUpdate(backend.getNested("inst"), edu_wpi_first_epilogue_Base2, Epilogue.getConfig().errorHandler); - } else { - // Base type edu.wpi.first.epilogue.ABC - Epilogue.abcLogger.tryUpdate(backend.getNested("inst"), $$inst, Epilogue.getConfig().errorHandler); - }; - } - } - } - """; - - assertLoggerGenerates(source, expectedGeneratedSource); - } - @Test void optInMethods() { String source = From 145ba624653da473fc261a02ab41ecd436e70361 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Tue, 24 Dec 2024 20:48:18 -0500 Subject: [PATCH 6/8] style fixes --- .../processor/AnnotationProcessor.java | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java index 384be368820..2781c055c8c 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java @@ -37,8 +37,8 @@ import javax.tools.Diagnostic; @SupportedAnnotationTypes({ - "edu.wpi.first.epilogue.CustomLoggerFor", - "edu.wpi.first.epilogue.Logged" + "edu.wpi.first.epilogue.CustomLoggerFor", + "edu.wpi.first.epilogue.Logged" }) @SupportedSourceVersion(SourceVersion.RELEASE_17) public class AnnotationProcessor extends AbstractProcessor { @@ -46,20 +46,20 @@ public class AnnotationProcessor extends AbstractProcessor { private static final String kClassSpecificLoggerFqn = "edu.wpi.first.epilogue.logging.ClassSpecificLogger"; private static final String kLoggedFqn = "edu.wpi.first.epilogue.Logged"; - + private EpilogueGenerator m_epiloguerGenerator; private LoggerGenerator m_loggerGenerator; private List m_handlers; - + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (annotations.isEmpty()) { // Nothing to do, don't claim return false; } - + Map customLoggers = new HashMap<>(); - + annotations.stream() .filter(ann -> kCustomLoggerFqn.contentEquals(ann.getQualifiedName())) .findAny() @@ -67,7 +67,7 @@ public boolean process(Set annotations, RoundEnvironment customLogger -> { customLoggers.putAll(processCustomLoggers(roundEnv, customLogger)); }); - + roundEnv.getRootElements().stream() .filter( e -> @@ -92,9 +92,9 @@ public boolean process(Set annotations, RoundEnvironment "[EPILOGUE] Custom logger classes should have a @CustomLoggerFor annotation", e); }); - + var loggedTypes = getLoggedTypes(roundEnv); - + // Handlers are declared in order of priority. If an element could be logged in more than one // way (eg a class implements both Sendable and StructSerializable), the order of the handlers // in this list will determine how it gets logged. @@ -112,10 +112,10 @@ public boolean process(Set annotations, RoundEnvironment new SupplierHandler(processingEnv), new StructHandler(processingEnv), // prioritize struct over sendable new SendableHandler(processingEnv)); - + m_epiloguerGenerator = new EpilogueGenerator(processingEnv, customLoggers); m_loggerGenerator = new LoggerGenerator(processingEnv, m_handlers); - + annotations.stream() .filter(ann -> kLoggedFqn.contentEquals(ann.getQualifiedName())) .findAny() @@ -123,10 +123,10 @@ public boolean process(Set annotations, RoundEnvironment epilogue -> { processEpilogue(roundEnv, epilogue, loggedTypes); }); - + return false; } - + /** * Gets the set of all loggable types in the compilation unit. A type is considered loggable if it * is directly annotated with {@code @Logged} or contains a field or method with a {@code @Logged} @@ -149,20 +149,20 @@ private Set getLoggedTypes(RoundEnvironment roundEnv) { .map(Element::getEnclosingElement) .filter(e -> e instanceof TypeElement) .map(e -> (TypeElement) e)) - .sorted(Comparator.comparing(e -> e.getSimpleName().toString())) - .collect( - Collectors.toCollection(LinkedHashSet::new)); // Collect to a set to avoid duplicates + .sorted(Comparator.comparing(e -> e.getSimpleName().toString())) + .collect( + Collectors.toCollection(LinkedHashSet::new)); // Collect to a set to avoid duplicates } - + private boolean validateFields(Set annotatedElements) { var fields = annotatedElements.stream() .filter(e -> e instanceof VariableElement) .map(e -> (VariableElement) e) .toList(); - + boolean valid = true; - + for (VariableElement field : fields) { // Field is explicitly tagged // And is not opted out of @@ -180,16 +180,16 @@ private boolean validateFields(Set annotatedElements) { } return valid; } - + private boolean validateMethods(Set annotatedElements) { var methods = annotatedElements.stream() .filter(e -> e instanceof ExecutableElement) .map(e -> (ExecutableElement) e) .toList(); - + boolean valid = true; - + for (ExecutableElement method : methods) { // Field is explicitly tagged if (method.getAnnotation(NotLogged.class) == null) { @@ -205,36 +205,36 @@ private boolean validateMethods(Set annotatedElements) { method); valid = false; } - + if (!method.getModifiers().contains(Modifier.PUBLIC)) { // Only public methods can be logged - + processingEnv .getMessager() .printMessage( Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods must be public", method); - + valid = false; } - + if (method.getModifiers().contains(Modifier.STATIC)) { processingEnv .getMessager() .printMessage( Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods cannot be static", method); - + valid = false; } - + if (method.getReturnType().getKind() == TypeKind.NONE) { processingEnv .getMessager() .printMessage( Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods cannot be void", method); - + valid = false; } - + if (!method.getParameters().isEmpty()) { processingEnv .getMessager() @@ -242,14 +242,14 @@ private boolean validateMethods(Set annotatedElements) { Diagnostic.Kind.ERROR, "[EPILOGUE] Logged methods cannot accept arguments", method); - + valid = false; } } } return valid; } - + /** * Checks if a type is not loggable. * @@ -260,13 +260,13 @@ private boolean isNotLoggable(Element element, TypeMirror type) { // e.g. void, cannot log return true; } - + boolean loggable = m_handlers.stream().anyMatch(h -> h.isLoggable(element)); - + if (loggable) { return false; } - + processingEnv .getMessager() .printMessage( @@ -275,21 +275,21 @@ private boolean isNotLoggable(Element element, TypeMirror type) { element); return true; } - + @SuppressWarnings("unchecked") private Map processCustomLoggers( RoundEnvironment roundEnv, TypeElement customLoggerAnnotation) { // map logged type to its custom logger, eg // { Point.class => CustomPointLogger.class } var customLoggers = new HashMap(); - + var annotatedElements = roundEnv.getElementsAnnotatedWith(customLoggerAnnotation); - + var loggerSuperClass = processingEnv .getElementUtils() .getTypeElement("edu.wpi.first.epilogue.logging.ClassSpecificLogger"); - + for (Element annotatedElement : annotatedElements) { List targetTypes = List.of(); for (AnnotationMirror annotationMirror : annotatedElement.getAnnotationMirrors()) { @@ -299,7 +299,7 @@ private Map processCustomLoggers( } } } - + boolean hasPublicNoArgConstructor = annotatedElement.getEnclosedElements().stream() .anyMatch( @@ -308,7 +308,7 @@ private Map processCustomLoggers( && exe.getKind() == ElementKind.CONSTRUCTOR && exe.getModifiers().contains(Modifier.PUBLIC) && exe.getParameters().isEmpty()); - + if (!hasPublicNoArgConstructor) { processingEnv .getMessager() @@ -318,11 +318,11 @@ private Map processCustomLoggers( annotatedElement); continue; } - + for (AnnotationValue value : targetTypes) { var targetType = (DeclaredType) value.getValue(); var reflectedTarget = targetType.asElement(); - + // eg ClassSpecificLogger var requiredSuperClass = processingEnv @@ -330,7 +330,7 @@ private Map processCustomLoggers( .getDeclaredType( loggerSuperClass, processingEnv.getTypeUtils().getWildcardType(null, reflectedTarget.asType())); - + if (customLoggers.containsKey(targetType)) { processingEnv .getMessager() @@ -340,7 +340,7 @@ private Map processCustomLoggers( annotatedElement); continue; } - + if (annotatedElement instanceof TypeElement t && !t.getTypeParameters().isEmpty()) { processingEnv .getMessager() @@ -350,10 +350,10 @@ private Map processCustomLoggers( annotatedElement); continue; } - + if (!processingEnv - .getTypeUtils() - .isAssignable(annotatedElement.asType(), requiredSuperClass)) { + .getTypeUtils() + .isAssignable(annotatedElement.asType(), requiredSuperClass)) { processingEnv .getMessager() .printMessage( @@ -362,42 +362,42 @@ private Map processCustomLoggers( annotatedElement); continue; } - + customLoggers.put(targetType, (DeclaredType) annotatedElement.asType()); } } - + return customLoggers; } - + private void processEpilogue( RoundEnvironment roundEnv, TypeElement epilogueAnnotation, Set loggedTypes) { var annotatedElements = roundEnv.getElementsAnnotatedWith(epilogueAnnotation); - + List loggerClassNames = new ArrayList<>(); var mainRobotClasses = new ArrayList(); - + // Used to check for a main robot class var robotBaseClass = processingEnv.getElementUtils().getTypeElement("edu.wpi.first.wpilibj.TimedRobot").asType(); - + boolean validFields = validateFields(annotatedElements); boolean validMethods = validateMethods(annotatedElements); - + if (!(validFields && validMethods)) { // Generate nothing and bail return; } - + for (TypeElement clazz : loggedTypes) { try { warnOfNonLoggableElements(clazz); m_loggerGenerator.writeLoggerFile(clazz); - + if (processingEnv.getTypeUtils().isAssignable(clazz.getSuperclass(), robotBaseClass)) { mainRobotClasses.add(clazz); } - + loggerClassNames.add(StringUtils.loggerClassName(clazz)); } catch (IOException e) { processingEnv @@ -409,41 +409,41 @@ private void processEpilogue( e.printStackTrace(System.err); } } - + // Sort alphabetically mainRobotClasses.sort(Comparator.comparing(c -> c.getSimpleName().toString())); m_epiloguerGenerator.writeEpilogueFile(loggerClassNames, mainRobotClasses); } - + private void warnOfNonLoggableElements(TypeElement clazz) { var config = clazz.getAnnotation(Logged.class); if (config == null || config.strategy() == Logged.Strategy.OPT_IN) { // field and method validations will have already checked everything return; } - + for (Element element : clazz.getEnclosedElements()) { if (element.getAnnotation(NotLogged.class) != null) { // Explicitly opted out from, don't need to check continue; } - + if (element.getModifiers().contains(Modifier.STATIC)) { // static elements are never logged continue; } - + if (element instanceof VariableElement v) { // isNotLoggable will internally print a warning message isNotLoggable(v, v.asType()); } - + if (element instanceof ExecutableElement exe - && exe.getModifiers().contains(Modifier.PUBLIC) - && exe.getParameters().isEmpty()) { + && exe.getModifiers().contains(Modifier.PUBLIC) + && exe.getParameters().isEmpty()) { // isNotLoggable will internally print a warning message isNotLoggable(exe, exe.getReturnType()); } } } -} \ No newline at end of file +} From c138e7b3fae0a3aabb88787499175068a39f4e71 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Thu, 26 Dec 2024 21:00:13 -0500 Subject: [PATCH 7/8] changed no-args FileBackend constructor to boolean; removed other constructors --- .../edu/wpi/first/epilogue/logging/FileBackend.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java index 6b6a82b3a09..40cf7a48200 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java @@ -38,13 +38,18 @@ public class FileBackend implements EpilogueBackend { * * @param dataLog the data log to save data to */ - public FileBackend(DataLog dataLog) { + FileBackend(DataLog dataLog) { this.m_dataLog = requireNonNullParam(dataLog, "dataLog", "FileBackend"); } - /** Creates a new file-based backend. */ - public FileBackend() { - this(DataLogManager.getLog()); + /** + * Creates a new file-based backend. + * + * @param enableNtCapture enables capture of networktables data to datalog if true + */ + public FileBackend(boolean enableNtCapture) { + this.m_dataLog = DataLogManager.getLog(); + DataLogManager.logNetworkTables(enableNtCapture); } @Override From 9b7b33ae8c046861df46364d89fa3e5f5f38b103 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Thu, 26 Dec 2024 21:00:38 -0500 Subject: [PATCH 8/8] added forgotten file --- .../src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java index aaac8dfa27d..9295a22ac66 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java @@ -40,7 +40,7 @@ public class NTBackend implements EpilogueBackend { * * @param nt the NetworkTable instance to use to send data to */ - public NTBackend(NetworkTableInstance nt) { + NTBackend(NetworkTableInstance nt) { this.m_nt = nt; }