From 66c569d402bacb1aa7a3a5270d66bb57142819cf Mon Sep 17 00:00:00 2001 From: Wilson Watson Date: Tue, 30 Jul 2024 14:58:25 -0500 Subject: [PATCH] lombok inspo --- .gitignore | 3 +- .../frc5572/util/profiler/AutoProfile.java | 4 + .../frc5572/util/profiler/EmptyProfiler.java | 2 - .../util/profiler/LoggingProfiler.java | 34 ++- .../util/profiler/ProfileResultImpl.java | 1 - .../util/profiler/ReadableProfiler.java | 2 - .../util/profiler/ValidatingProfiler.java | 13 +- .../java/org/frc5572/util/serde/Alias.java | 15 ++ .../java/org/frc5572/util/serde/Aliases.java | 12 + .../java/org/frc5572/util/serde/Casing.java | 12 + .../frc5572/util/serde/DefaultSerializer.java | 6 + .../java/org/frc5572/util/serde/Rename.java | 13 + .../org/frc5572/util/serde/RenameAll.java | 13 + .../java/org/frc5572/util/serde/Serde.java | 11 + .../org/frc5572/util/serde/Serialize.java | 9 + .../frc5572/util/serde/SingleSerdeItem.java | 7 + .../java/org/frc5572/util/serde/Skip.java | 5 + .../java/org/frc5572/util/serde/With.java | 13 + .../java/org/frc5572/robotools/Checks.java | 20 -- .../frc5572/robotools/CompilationData.java | 154 ++---------- .../java/org/frc5572/robotools/IOTypes.java | 223 ------------------ .../org/frc5572/robotools/RobotProcessor.java | 38 ++- .../autoprofile/AutoProfileProcessor.java | 11 + .../org/frc5572/robotools/checks/Check.java | 12 - .../org/frc5572/robotools/checks/IOCheck.java | 136 ----------- .../robotools/serde/SerdeProcessor.java | 11 + .../robotools/util/ReflectionUtil.java | 203 ++++++++++++++++ .../robotools/util/tree/JCClassTree.java | 29 +++ .../services/com.sun.source.util.Plugin | 1 - 29 files changed, 438 insertions(+), 575 deletions(-) create mode 100755 lib/src/main/java/org/frc5572/util/profiler/AutoProfile.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Alias.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Aliases.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Casing.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/DefaultSerializer.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Rename.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/RenameAll.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Serde.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Serialize.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/SingleSerdeItem.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/Skip.java create mode 100755 lib/src/main/java/org/frc5572/util/serde/With.java delete mode 100644 processor/src/main/java/org/frc5572/robotools/Checks.java delete mode 100644 processor/src/main/java/org/frc5572/robotools/IOTypes.java create mode 100755 processor/src/main/java/org/frc5572/robotools/autoprofile/AutoProfileProcessor.java delete mode 100755 processor/src/main/java/org/frc5572/robotools/checks/Check.java delete mode 100755 processor/src/main/java/org/frc5572/robotools/checks/IOCheck.java create mode 100755 processor/src/main/java/org/frc5572/robotools/serde/SerdeProcessor.java create mode 100755 processor/src/main/java/org/frc5572/robotools/util/ReflectionUtil.java create mode 100755 processor/src/main/java/org/frc5572/robotools/util/tree/JCClassTree.java delete mode 100644 processor/src/main/resources/META-INF/services/com.sun.source.util.Plugin diff --git a/.gitignore b/.gitignore index e403f14..44736e7 100644 --- a/.gitignore +++ b/.gitignore @@ -137,8 +137,7 @@ $RECYCLE.BIN/ ### Gradle ### .gradle -/build/ -/checker/build/ +*/build/ # Ignore Gradle GUI config gradle-app.setting diff --git a/lib/src/main/java/org/frc5572/util/profiler/AutoProfile.java b/lib/src/main/java/org/frc5572/util/profiler/AutoProfile.java new file mode 100755 index 0000000..42be446 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/profiler/AutoProfile.java @@ -0,0 +1,4 @@ +package org.frc5572.util.profiler; + +/** Automatically profile a method. */ +public @interface AutoProfile {} diff --git a/lib/src/main/java/org/frc5572/util/profiler/EmptyProfiler.java b/lib/src/main/java/org/frc5572/util/profiler/EmptyProfiler.java index a4fb6de..2141fb3 100644 --- a/lib/src/main/java/org/frc5572/util/profiler/EmptyProfiler.java +++ b/lib/src/main/java/org/frc5572/util/profiler/EmptyProfiler.java @@ -1,9 +1,7 @@ package org.frc5572.util.profiler; -import it.unimi.dsi.fastutil.Pair; import org.jetbrains.annotations.Nullable; -import java.util.Set; import java.util.function.Supplier; public final class EmptyProfiler implements ReadableProfiler { diff --git a/lib/src/main/java/org/frc5572/util/profiler/LoggingProfiler.java b/lib/src/main/java/org/frc5572/util/profiler/LoggingProfiler.java index 120a296..4f3e4da 100644 --- a/lib/src/main/java/org/frc5572/util/profiler/LoggingProfiler.java +++ b/lib/src/main/java/org/frc5572/util/profiler/LoggingProfiler.java @@ -1,14 +1,15 @@ package org.frc5572.util.profiler; -import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongList; import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongMaps; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArraySet; import org.jetbrains.annotations.Nullable; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; import java.util.*; import java.util.function.IntSupplier; import java.util.function.LongSupplier; @@ -60,13 +61,28 @@ public LocatedInfo getInfo(String name) { @Override public void save() { - + try { + try(var outStream = new PrintStream(new FileOutputStream(filePath))) { + outStream.println("Performance Log\n================================================================================"); + for(var entry : locationInfos.entrySet()) { + var info = entry.getValue(); + outStream.println(entry.getKey().replace(SPLIT_CHAR, '.')); + outStream.println(" visitCount: " + info.getVisitCount()); + outStream.println(" totalTime: " + info.getTotalTime()); + outStream.println(" maxTime: " + info.getMaxTime()); + outStream.println(" minTime: " + info.minTime); + outStream.println(" avgTime: " + info.getTotalTime() / info.getVisitCount()); + } + } + } catch(IOException e) { + e.printStackTrace(); + } } @Override public void startTick() { if(this.tickStarted) { - // TODO error: Profiler tick already started - missing endTick()? + throw new RuntimeException("Profiler tick already started. Missing endTick()?"); } else { this.tickStarted = true; this.fullPath = ""; @@ -78,12 +94,12 @@ public void startTick() { @Override public void endTick() { if(!this.tickStarted) { - // TODO error: Profiler tick already ended - missing startTick()? + throw new RuntimeException("Profiler tick already ended. Missing startTick()?"); } else { this.pop(); this.tickStarted = false; if(!this.fullPath.isEmpty()) { - // TODO error: Profiler tick ended before path was fully popped (remainder: '{}'). Mismatched push/pop? + throw new RuntimeException("Profiler tick ended before path was fully popped. Mismatched push/pop?"); } } } @@ -91,7 +107,7 @@ public void endTick() { @Override public void push(String location) { if(!this.tickStarted) { - // TODO error: Cannot push '{}' to profiler if profiler tick hasn't started - missing startTick()? + throw new RuntimeException("Cannot push '" + location + "' to the profiler if profiler tick hasn't started. Missing startTick()?"); } else { if(!this.fullPath.isEmpty()) { this.fullPath = this.fullPath + SPLIT_CHAR; @@ -111,9 +127,9 @@ public void push(Supplier locationGetter) { @Override public void pop() { if(!this.tickStarted) { - // TODO error: Cannot pop from profiler if profiler tick hasn't started - missing startTick()? + throw new RuntimeException("Cannot pop from profiler if profiler tick hasn't started. Missing startTick()?"); } else if(this.timeList.isEmpty()) { - // TODO error: Tried to pop one too many times! Mismatched push() and pop()? + throw new RuntimeException("Tried to pop one too many times! Mismatched push() and pop()?"); } else { this.path.remove(this.path.size() - 1); diff --git a/lib/src/main/java/org/frc5572/util/profiler/ProfileResultImpl.java b/lib/src/main/java/org/frc5572/util/profiler/ProfileResultImpl.java index 95a5452..7284c4f 100644 --- a/lib/src/main/java/org/frc5572/util/profiler/ProfileResultImpl.java +++ b/lib/src/main/java/org/frc5572/util/profiler/ProfileResultImpl.java @@ -3,7 +3,6 @@ import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongMaps; -import java.nio.file.Path; import java.util.*; public final class ProfileResultImpl implements ProfileResult { diff --git a/lib/src/main/java/org/frc5572/util/profiler/ReadableProfiler.java b/lib/src/main/java/org/frc5572/util/profiler/ReadableProfiler.java index 8b6ff8d..c805174 100644 --- a/lib/src/main/java/org/frc5572/util/profiler/ReadableProfiler.java +++ b/lib/src/main/java/org/frc5572/util/profiler/ReadableProfiler.java @@ -1,9 +1,7 @@ package org.frc5572.util.profiler; -import it.unimi.dsi.fastutil.Pair; import org.jetbrains.annotations.Nullable; -import java.util.Set; public sealed interface ReadableProfiler extends Profiler permits EmptyProfiler, LoggingProfiler, ValidatingProfiler { diff --git a/lib/src/main/java/org/frc5572/util/profiler/ValidatingProfiler.java b/lib/src/main/java/org/frc5572/util/profiler/ValidatingProfiler.java index beb2321..6fdab5d 100644 --- a/lib/src/main/java/org/frc5572/util/profiler/ValidatingProfiler.java +++ b/lib/src/main/java/org/frc5572/util/profiler/ValidatingProfiler.java @@ -33,7 +33,7 @@ public void save() { @Override public void startTick() { if(this.tickStarted) { - // TODO error: Profiler tick already started - missing endTick()? + throw new RuntimeException("Profiler tick already started. Missing endTick()?"); } else { tickStarted = true; pathLen = 0; @@ -45,20 +45,19 @@ public void startTick() { @Override public void endTick() { if(!this.tickStarted) { - // TODO error: Profiler tick already ended - missing startTick()? + throw new RuntimeException("Profiler tick already ended. Missing startTick()?"); } else { this.pop(); this.tickStarted = false; if(!this.fullPathEmpty) { - // TODO error: Profiler tick ended before path was fully popped (remainder: '{}'). Mismatched push/pop? - } + throw new RuntimeException("Profiler tick ended before path was fully popped. Mismatched push/pop?"); } } } @Override public void push(String location) { if(!this.tickStarted) { - // TODO error: Cannot push '{}' to profiler if profiler tick hasn't started - missing startTick()? + throw new RuntimeException("Cannot push '" + location + "' to the profiler if profiler tick hasn't started. Missing startTick()?"); } else { fullPathEmpty = false; pathLen += 1; @@ -73,9 +72,9 @@ public void push(Supplier locationGetter) { @Override public void pop() { if(!this.tickStarted) { - // TODO error: Cannot pop from profiler if profiler tick hasn't started - missing startTick()? + throw new RuntimeException("Cannot pop from profiler if profiler tick hasn't started. Missing startTick()?"); } else if(pathLen == 0) { - // TODO error: Tried to pop one too many times! Mismatched push() and pop()? + throw new RuntimeException("Tried to pop one too many times! Mismatched push() and pop()?"); } else { pathLen -= 1; } diff --git a/lib/src/main/java/org/frc5572/util/serde/Alias.java b/lib/src/main/java/org/frc5572/util/serde/Alias.java new file mode 100755 index 0000000..9f9b89b --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Alias.java @@ -0,0 +1,15 @@ +package org.frc5572.util.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Additional name this field could go by. Only used for deserialization, and only used if previous names/aliases are missing in log files. */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.FIELD}) +@Repeatable(Aliases.class) +public @interface Alias { + String value(); +} diff --git a/lib/src/main/java/org/frc5572/util/serde/Aliases.java b/lib/src/main/java/org/frc5572/util/serde/Aliases.java new file mode 100755 index 0000000..d991826 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Aliases.java @@ -0,0 +1,12 @@ +package org.frc5572.util.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.FIELD}) +public @interface Aliases { + Alias[] value(); +} diff --git a/lib/src/main/java/org/frc5572/util/serde/Casing.java b/lib/src/main/java/org/frc5572/util/serde/Casing.java new file mode 100755 index 0000000..991ff99 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Casing.java @@ -0,0 +1,12 @@ +package org.frc5572.util.serde; + +public enum Casing { + LOWERCASE, + UPPERCASE, + PASCAL_CASE, + CAMEL_CASE, + SNAKE_CASE, + SCREAMING_SNAKE_CASE, + KEBAB_CASE, + SCREAMING_KEBAB_CASE, +} diff --git a/lib/src/main/java/org/frc5572/util/serde/DefaultSerializer.java b/lib/src/main/java/org/frc5572/util/serde/DefaultSerializer.java new file mode 100755 index 0000000..0aeb06e --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/DefaultSerializer.java @@ -0,0 +1,6 @@ +package org.frc5572.util.serde; + +/** Mark this class as the default serialization implementation for a given class. */ +public @interface DefaultSerializer { + Class value(); +} diff --git a/lib/src/main/java/org/frc5572/util/serde/Rename.java b/lib/src/main/java/org/frc5572/util/serde/Rename.java new file mode 100755 index 0000000..2fee0bf --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Rename.java @@ -0,0 +1,13 @@ +package org.frc5572.util.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Rename field in log table using the given name. */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.FIELD}) +public @interface Rename { + String value(); +} diff --git a/lib/src/main/java/org/frc5572/util/serde/RenameAll.java b/lib/src/main/java/org/frc5572/util/serde/RenameAll.java new file mode 100755 index 0000000..e406097 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/RenameAll.java @@ -0,0 +1,13 @@ +package org.frc5572.util.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Rename all fields in serialized table using the given case conversions. This is ignored for any field with an explicit {@link Rename} annotation. */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +public @interface RenameAll { + Casing value(); +} diff --git a/lib/src/main/java/org/frc5572/util/serde/Serde.java b/lib/src/main/java/org/frc5572/util/serde/Serde.java new file mode 100755 index 0000000..3be8359 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Serde.java @@ -0,0 +1,11 @@ +package org.frc5572.util.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** File supports serialization to and from a log table. */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE}) +public @interface Serde {} diff --git a/lib/src/main/java/org/frc5572/util/serde/Serialize.java b/lib/src/main/java/org/frc5572/util/serde/Serialize.java new file mode 100755 index 0000000..63fb567 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Serialize.java @@ -0,0 +1,9 @@ +package org.frc5572.util.serde; + +/** Implementation for serialization/deserialization of a type. */ +public interface Serialize { + + void toTable(String name, T value); + T fromTable(String name); + +} diff --git a/lib/src/main/java/org/frc5572/util/serde/SingleSerdeItem.java b/lib/src/main/java/org/frc5572/util/serde/SingleSerdeItem.java new file mode 100755 index 0000000..148b981 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/SingleSerdeItem.java @@ -0,0 +1,7 @@ +package org.frc5572.util.serde; + +/** Indicates this item should be updated every call to `periodic()`. */ +public @interface SingleSerdeItem { + String name(); + String updateInputs(); +} diff --git a/lib/src/main/java/org/frc5572/util/serde/Skip.java b/lib/src/main/java/org/frc5572/util/serde/Skip.java new file mode 100755 index 0000000..82b0592 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/Skip.java @@ -0,0 +1,5 @@ +package org.frc5572.util.serde; + + +/** Indicates this field should be skipped during serialization and deserialization. */ +public @interface Skip {} diff --git a/lib/src/main/java/org/frc5572/util/serde/With.java b/lib/src/main/java/org/frc5572/util/serde/With.java new file mode 100755 index 0000000..9933075 --- /dev/null +++ b/lib/src/main/java/org/frc5572/util/serde/With.java @@ -0,0 +1,13 @@ +package org.frc5572.util.serde; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Use a field with type that implements {@link Serialize} for serialization instead of the default. */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.FIELD}) +public @interface With { + Class> value(); +} diff --git a/processor/src/main/java/org/frc5572/robotools/Checks.java b/processor/src/main/java/org/frc5572/robotools/Checks.java deleted file mode 100644 index 1971cc8..0000000 --- a/processor/src/main/java/org/frc5572/robotools/Checks.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.frc5572.robotools; - -import org.frc5572.robotools.checks.Check; -import org.frc5572.robotools.checks.IOCheck; - -/** All checks to run. */ -public class Checks { - - private static final Check[] CHECKS = new Check[] {new IOCheck()}; - - /** Run through all checks */ - public static boolean process(CompilationData data) { - boolean fatal = false; - for (Check c : CHECKS) { - fatal = fatal || c.check(data); - } - return fatal; - } - -} diff --git a/processor/src/main/java/org/frc5572/robotools/CompilationData.java b/processor/src/main/java/org/frc5572/robotools/CompilationData.java index c7866ce..3028019 100755 --- a/processor/src/main/java/org/frc5572/robotools/CompilationData.java +++ b/processor/src/main/java/org/frc5572/robotools/CompilationData.java @@ -1,137 +1,17 @@ -package org.frc5572.robotools; - -import javax.annotation.processing.Messager; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.LineMap; -import com.sun.source.tree.Tree; -import com.sun.source.util.JavacTask; -import com.sun.source.util.SourcePositions; -import com.sun.source.util.TaskEvent; -import com.sun.source.util.Trees; - -/** - * Wrapper around a TypeElement. Includes helpers for printing errors, warnings etc. - */ -public class CompilationData { - - /** Type Information for entire classpath. */ - public Types types; - private Trees trees; - private SourcePositions positions; - private CompilationUnitTree compilationUnitTree; - /** Element being processed */ - public TypeElement element; - private Messager messager; - - /** Basic constructor. */ - public CompilationData(Types types, Trees trees, SourcePositions positions, - CompilationUnitTree compilationUnitTree, TypeElement element, Messager messager) { - this.types = types; - this.trees = trees; - this.positions = positions; - this.compilationUnitTree = compilationUnitTree; - this.element = element; - this.messager = messager; - } - - /** Constructor from Javac Plugin context. */ - public CompilationData(JavacTask task, TaskEvent event) { - this(task.getTypes(), Trees.instance(task), Trees.instance(task).getSourcePositions(), - event.getCompilationUnit(), event.getTypeElement(), null); - } - - /** Constructor from Annotation Processor context. */ - public CompilationData(ProcessingEnvironment processingEnv, TypeElement element) { - this(processingEnv.getTypeUtils(), null, null, null, element, processingEnv.getMessager()); - } - - /** Show error */ - public void error(Element element, Object object) { - echo(element, object.toString(), Diagnostic.Kind.ERROR, "error", "Error"); - } - - /** Show warning */ - public void warn(Element element, Object object) { - echo(element, object.toString(), Diagnostic.Kind.MANDATORY_WARNING, "warning", "Warning"); - } - - /** Show note (this doesn't work in VS Code yet) */ - public void note(Element element, Object object) { - echo(element, object.toString(), Diagnostic.Kind.NOTE, "notice", "Note"); - } - - private void echo(Element element, String errString, Diagnostic.Kind kind, String ghString, - String humanString) { - if (compilationUnitTree == null) { - messager.printMessage(kind, errString, element); - } else { - Tree tree = trees.getTree(element); - LineMap linemap = compilationUnitTree.getLineMap(); - long pos = positions.getStartPosition(compilationUnitTree, tree); - long row = linemap.getLineNumber(pos); - String name = compilationUnitTree.getSourceFile().toUri().toString().split("/src/")[1]; - System.out - .println("::" + ghString + " file=src/" + name + ",line=" + row + "::" + errString); - } - } - - private boolean _implements(String qualifiedName, TypeElement elem) { - if (elem.getQualifiedName().toString().equals(qualifiedName)) { - return true; - } - Element superClass = types.asElement(elem.getSuperclass()); - if (superClass instanceof TypeElement) { - if (_implements(qualifiedName, (TypeElement) superClass)) { - return true; - } - } - for (var iface : elem.getInterfaces()) { - Element interface_ = types.asElement(iface); - if (interface_ instanceof TypeElement) { - if (_implements(qualifiedName, (TypeElement) interface_)) { - return true; - } - } - } - return false; - } - - private boolean _extends(String qualifiedName, TypeElement elem) { - if (elem.getQualifiedName().toString().equals(qualifiedName)) { - return true; - } - Element superClass = types.asElement(elem.getSuperclass()); - if (superClass instanceof TypeElement) { - if (_extends(qualifiedName, (TypeElement) superClass)) { - return true; - } - } - return false; - } - - /** Get if this type implements an interface by name. */ - public boolean implementsInterface(String qualifiedName) { - return _implements(qualifiedName, this.element); - } - - /** Get if the specified type implements an interface by name. */ - public boolean implementsInterface(TypeElement e, String qualifiedName) { - return _implements(qualifiedName, e); - } - - /** Get if this type extends a class by name. */ - public boolean extendsClass(String qualifiedName) { - return _extends(qualifiedName, this.element); - } - - /** Get if the specified type extends a class by name. */ - public boolean extendsClass(TypeElement e, String qualifiedName) { - return _extends(qualifiedName, e); - } - -} +package org.frc5572.robotools; + +import java.util.Collection; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.TypeElement; + +public class CompilationData { + + public final TypeElement[] types; + + + public CompilationData(Collection types, ProcessingEnvironment processingEnvironment) { + this.types = types.toArray(TypeElement[]::new); + } + +} diff --git a/processor/src/main/java/org/frc5572/robotools/IOTypes.java b/processor/src/main/java/org/frc5572/robotools/IOTypes.java deleted file mode 100644 index cc11c01..0000000 --- a/processor/src/main/java/org/frc5572/robotools/IOTypes.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.frc5572.robotools; - -/** Auto-generated list of IO interfaces and classes. */ -public class IOTypes { - - /** List of interfaces disallowed a direct path to Robot.java. */ - public static String[] ioInterfaces = { - "edu.wpi.first.wpilibj.interfaces.Gyro", - "edu.wpi.first.wpilibj.interfaces.Accelerometer", - "edu.wpi.first.wpilibj.motorcontrol.MotorController", - "com.revrobotics.SparkMaxPIDController", - "com.revrobotics.CANSensor", - "com.revrobotics.CANEncoder", - "com.revrobotics.CANAnalog", - "com.revrobotics.RelativeEncoder", - "com.revrobotics.SparkMaxAbsoluteEncoder", - "com.revrobotics.AbsoluteEncoder", - "com.revrobotics.MotorFeedbackSensor", - "com.revrobotics.CANPIDController", - "com.revrobotics.SparkMaxLimitSwitch", - "com.revrobotics.SparkMaxRelativeEncoder", - "com.revrobotics.CANDigitalInput", - "com.revrobotics.AnalogInput", - "com.revrobotics.SparkMaxAnalogSensor", - "com.ctre.phoenix6.ISerializable", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest", - "com.ctre.phoenix6.hardware.ParentDevice.MapGenerator", - "com.ctre.phoenix6.configs.ParentConfiguration", - "com.kauailabs.navx.frc.ITimestampedDataSubscriber", - }; - /** List of classes disallowed a direct path to Robot.java. */ - public static String[] ioClasses = { - "edu.wpi.first.wpilibj.AnalogEncoder", - "edu.wpi.first.wpilibj.AnalogGyro", - "edu.wpi.first.wpilibj.AnalogInput", - "edu.wpi.first.wpilibj.AnalogOutput", - "edu.wpi.first.wpilibj.AnalogPotentiometer", - "edu.wpi.first.wpilibj.AnalogTrigger", - "edu.wpi.first.wpilibj.AnalogTriggerOutput", - "edu.wpi.first.wpilibj.DMA", - "edu.wpi.first.wpilibj.DigitalSource", - "edu.wpi.first.wpilibj.DoubleSolenoid", - "edu.wpi.first.wpilibj.Encoder", - "edu.wpi.first.wpilibj.I2C", - "edu.wpi.first.wpilibj.PWM", - "edu.wpi.first.wpilibj.PneumaticsBase", - "edu.wpi.first.wpilibj.PowerDistribution", - "edu.wpi.first.wpilibj.Relay", - "edu.wpi.first.wpilibj.SPI", - "edu.wpi.first.wpilibj.SerialPort", - "edu.wpi.first.wpilibj.Solenoid", - "com.revrobotics.CANSparkBase.ExternalFollower", - "com.revrobotics.ColorSensorV3", - "com.revrobotics.jni.CANSparkMaxJNI", - "com.revrobotics.jni.RevJNIWrapper", - "com.revrobotics.jni.CANSWDLJNI", - "com.revrobotics.SparkAbsoluteEncoder", - "com.revrobotics.SparkFlexExternalEncoder", - "com.revrobotics.ColorSensorV3.RawColor", - "com.revrobotics.CANSparkMaxLowLevel.PeriodicStatus2", - "com.revrobotics.SparkAnalogSensor", - "com.revrobotics.CANSparkMaxLowLevel", - "com.revrobotics.CIEColor", - "com.revrobotics.SparkRelativeEncoder", - "com.revrobotics.CANSparkLowLevel", - "com.revrobotics.CANSparkFlex", - "com.revrobotics.ColorMatchResult", - "com.revrobotics.CANSparkMax", - "com.revrobotics.SparkMaxAlternateEncoder", - "com.revrobotics.CANSparkLowLevel.PeriodicStatus1", - "com.revrobotics.CANSparkLowLevel.PeriodicStatus2", - "com.revrobotics.CANSparkLowLevel.FollowConfig", - "com.revrobotics.SparkLimitSwitch", - "com.revrobotics.CANSparkMaxLowLevel.PeriodicStatus0", - "com.revrobotics.ColorMatch", - "com.revrobotics.SparkPIDController", - "com.revrobotics.CANSparkLowLevel.FollowConfig.Config", - "com.revrobotics.CANSparkLowLevel.PeriodicStatus0", - "com.revrobotics.REVPhysicsSim", - "com.revrobotics.CANSparkBase", - "com.revrobotics.CANSparkMaxLowLevel.PeriodicStatus1", - "com.revrobotics.DataPortConfigUtil", - "com.ctre.phoenix6.Orchestra", - "com.ctre.phoenix6.sim.TalonFXSimState", - "com.ctre.phoenix6.sim.CANcoderSimState", - "com.ctre.phoenix6.sim.Pigeon2SimState", - "com.ctre.phoenix6.jni.ErrorReportingJNI", - "com.ctre.phoenix6.jni.StatusSignalJNI", - "com.ctre.phoenix6.jni.OrchestraJNI", - "com.ctre.phoenix6.jni.CANBusJNI", - "com.ctre.phoenix6.jni.SignalLoggerJNI", - "com.ctre.phoenix6.jni.PlatformJNI", - "com.ctre.phoenix6.jni.CtreJniWrapper", - "com.ctre.phoenix6.wpiutils.AutoFeedEnable", - "com.ctre.phoenix6.wpiutils.MotorSafetyImplem", - "com.ctre.phoenix6.wpiutils.CallbackHelper", - "com.ctre.phoenix6.SignalLogger", - "com.ctre.phoenix6.Utils", - "com.ctre.phoenix6.BaseStatusSignal", - "com.ctre.phoenix6.controls.jni.ControlJNI", - "com.ctre.phoenix6.controls.jni.ControlConfigJNI", - "com.ctre.phoenix6.controls.compound.Diff_VelocityDutyCycle_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_MotionMagicTorqueCurrentFOC_Position", - "com.ctre.phoenix6.controls.compound.Diff_VelocityDutyCycle_Position", - "com.ctre.phoenix6.controls.compound.Diff_VelocityTorqueCurrentFOC_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_VelocityVoltage_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_PositionTorqueCurrentFOC_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_MotionMagicDutyCycle_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_DutyCycleOut_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_TorqueCurrentFOC_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_VoltageOut_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_PositionVoltage_Position", - "com.ctre.phoenix6.controls.compound.Diff_PositionTorqueCurrentFOC_Position", - "com.ctre.phoenix6.controls.compound.Diff_MotionMagicVoltage_Position", - "com.ctre.phoenix6.controls.compound.Diff_PositionVoltage_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_VoltageOut_Position", - "com.ctre.phoenix6.controls.compound.Diff_PositionDutyCycle_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_MotionMagicTorqueCurrentFOC_Velocity", - "com.ctre.phoenix6.controls.compound.Diff_PositionDutyCycle_Position", - "com.ctre.phoenix6.controls.compound.Diff_VelocityTorqueCurrentFOC_Position", - "com.ctre.phoenix6.controls.compound.Diff_MotionMagicDutyCycle_Position", - "com.ctre.phoenix6.controls.compound.Diff_VelocityVoltage_Position", - "com.ctre.phoenix6.controls.compound.Diff_DutyCycleOut_Position", - "com.ctre.phoenix6.controls.compound.Diff_TorqueCurrentFOC_Position", - "com.ctre.phoenix6.controls.compound.Diff_MotionMagicVoltage_Velocity", - "com.ctre.phoenix6.CANBus", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.SwerveControlRequestParameters", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.RobotCentric", - "com.ctre.phoenix6.mechanisms.swerve.SwerveDrivetrain.OdometryThread", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.SwerveDriveBrake", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.ApplyChassisSpeeds", - "com.ctre.phoenix6.mechanisms.swerve.SwerveDrivetrainConstants", - "com.ctre.phoenix6.mechanisms.swerve.SwerveModuleConstants", - "com.ctre.phoenix6.mechanisms.swerve.utility.PhoenixPIDController", - "com.ctre.phoenix6.mechanisms.swerve.SwerveDrivetrain", - "com.ctre.phoenix6.mechanisms.swerve.SwerveModule", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.PointWheelsAt", - "com.ctre.phoenix6.mechanisms.swerve.SimSwerveDrivetrain.SimSwerveModule", - "com.ctre.phoenix6.mechanisms.swerve.SwerveModuleConstantsFactory", - "com.ctre.phoenix6.mechanisms.swerve.SimSwerveDrivetrain", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.FieldCentricFacingAngle", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.FieldCentric", - "com.ctre.phoenix6.mechanisms.swerve.SwerveDrivetrain.SwerveDriveState", - "com.ctre.phoenix6.mechanisms.swerve.SwerveRequest.Idle", - "com.ctre.phoenix6.mechanisms.DifferentialMechanism", - "com.ctre.phoenix6.mechanisms.SimpleDifferentialMechanism", - "com.ctre.phoenix6.StatusSignal.SignalMeasurement", - "com.ctre.phoenix6.unmanaged.jni.UnmanagedJNI", - "com.ctre.phoenix6.unmanaged.Unmanaged", - "com.ctre.phoenix6.AllTimestamps", - "com.ctre.phoenix6.StatusSignal", - "com.ctre.phoenix6.hardware.CANcoder", - "com.ctre.phoenix6.hardware.Pigeon2", - "com.ctre.phoenix6.hardware.jni.HardwareJNI", - "com.ctre.phoenix6.hardware.ParentDevice", - "com.ctre.phoenix6.hardware.DeviceIdentifier", - "com.ctre.phoenix6.hardware.core.CorePigeon2", - "com.ctre.phoenix6.hardware.core.CoreTalonFX", - "com.ctre.phoenix6.hardware.core.CoreCANcoder", - "com.ctre.phoenix6.hardware.TalonFX", - "com.ctre.phoenix6.CANBus.CANBusStatus", - "com.ctre.phoenix6.Timestamp", - "com.ctre.phoenix6.configs.CurrentLimitsConfigs", - "com.ctre.phoenix6.configs.ClosedLoopGeneralConfigs", - "com.ctre.phoenix6.configs.TalonFXConfiguration", - "com.ctre.phoenix6.configs.DifferentialConstantsConfigs", - "com.ctre.phoenix6.configs.AudioConfigs", - "com.ctre.phoenix6.configs.VoltageConfigs", - "com.ctre.phoenix6.configs.jni.ConfigJNI", - "com.ctre.phoenix6.configs.SoftwareLimitSwitchConfigs", - "com.ctre.phoenix6.configs.ParentConfigurator", - "com.ctre.phoenix6.configs.MagnetSensorConfigs", - "com.ctre.phoenix6.configs.CANcoderConfiguration", - "com.ctre.phoenix6.configs.MotionMagicConfigs", - "com.ctre.phoenix6.configs.SlotConfigs", - "com.ctre.phoenix6.configs.ClosedLoopRampsConfigs", - "com.ctre.phoenix6.configs.MountPoseConfigs", - "com.ctre.phoenix6.configs.Pigeon2Configuration", - "com.ctre.phoenix6.configs.MotorOutputConfigs", - "com.ctre.phoenix6.configs.OpenLoopRampsConfigs", - "com.ctre.phoenix6.configs.DifferentialSensorsConfigs", - "com.ctre.phoenix6.configs.GyroTrimConfigs", - "com.ctre.phoenix6.configs.Pigeon2FeaturesConfigs", - "com.ctre.phoenix6.configs.TorqueCurrentConfigs", - "com.ctre.phoenix6.configs.TalonFXConfigurator", - "com.ctre.phoenix6.configs.Pigeon2Configurator", - "com.ctre.phoenix6.configs.FeedbackConfigs", - "com.ctre.phoenix6.configs.CANcoderConfigurator", - "com.ctre.phoenix6.configs.Slot0Configs", - "com.ctre.phoenix6.configs.CustomParamsConfigs", - "com.ctre.phoenix6.configs.HardwareLimitSwitchConfigs", - "com.ctre.phoenix6.configs.Slot1Configs", - "com.ctre.phoenix6.configs.Slot2Configs", - "com.kauailabs.vmx.AHRSJNI", - "com.kauailabs.navx.AHRSProtocol.AHRSUpdate", - "com.kauailabs.navx.IMUProtocol.YPRUpdate", - "com.kauailabs.navx.AHRSProtocol.AHRSPosTSRawUpdate", - "com.kauailabs.navx.IMUProtocol.GyroUpdate", - "com.kauailabs.navx.frc.Tracer", - "com.kauailabs.navx.frc.AHRS.BoardYawAxis", - "com.kauailabs.navx.frc.IIOCompleteNotification.BoardState", - "com.kauailabs.navx.frc.AHRS", - "com.kauailabs.navx.frc.Quaternion", - "com.kauailabs.navx.IMUProtocol.QuaternionUpdate", - "com.kauailabs.navx.AHRSProtocol.AHRS_TUNING_VAR_ID", - "com.kauailabs.navx.IMUProtocol.StreamCommand", - "com.kauailabs.navx.AHRSProtocol.AHRSPosUpdate", - "com.kauailabs.navx.AHRSProtocol.AHRS_DATA_TYPE", - "com.kauailabs.navx.IMUProtocol", - "com.kauailabs.navx.AHRSProtocol.AHRSPosTSUpdate", - "com.kauailabs.navx.AHRSProtocol", - "com.kauailabs.navx.AHRSProtocol.AHRS_DATA_ACTION", - "com.kauailabs.navx.AHRSProtocol.MagCalData", - "com.kauailabs.navx.AHRSProtocol.AHRSUpdateBase", - "com.kauailabs.navx.AHRSProtocol.DataSetResponse", - "com.kauailabs.navx.AHRSProtocol.IntegrationControl", - "com.kauailabs.navx.IMURegisters", - "com.kauailabs.navx.IMUProtocol.StreamResponse", - "com.kauailabs.navx.AHRSProtocol.BoardID", - "com.kauailabs.navx.AHRSProtocol.TuningVar", - }; -} - diff --git a/processor/src/main/java/org/frc5572/robotools/RobotProcessor.java b/processor/src/main/java/org/frc5572/robotools/RobotProcessor.java index 7c0ebfe..f622930 100644 --- a/processor/src/main/java/org/frc5572/robotools/RobotProcessor.java +++ b/processor/src/main/java/org/frc5572/robotools/RobotProcessor.java @@ -1,11 +1,12 @@ package org.frc5572.robotools; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedOptions; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; @@ -13,24 +14,16 @@ import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import org.frc5572.robotools.autoprofile.AutoProfileProcessor; +import org.frc5572.robotools.serde.SerdeProcessor; + /** - * Annotation processor for checks. Used by VS Code. + * Annotation processor for RobotTools. */ @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_11) -@SupportedOptions("frc_check.skip") +@SupportedSourceVersion(SourceVersion.RELEASE_17) public class RobotProcessor extends AbstractProcessor { - private boolean processTypeElement(TypeElement typeElement) { - for (Element e3 : typeElement.getEnclosedElements()) { - if (e3 instanceof TypeElement) { - processTypeElement((TypeElement) e3); - } - } - CompilationData data = new CompilationData(processingEnv, typeElement); - return Checks.process(data); - } - private boolean hasProcessed; /** Initialization function */ @@ -47,26 +40,25 @@ public boolean process(Set arg0, RoundEnvironment roundEn return false; } hasProcessed = true; - boolean fatal = false; + List typeElements = new ArrayList<>(); for (ModuleElement mod : processingEnv.getElementUtils().getAllModuleElements()) { if (!mod.isUnnamed()) { continue; } for (Element element : mod.getEnclosedElements()) { if (element instanceof PackageElement packageElement) { - if (packageElement.getQualifiedName().toString().startsWith("frc.")) { - for (Element element2 : packageElement.getEnclosedElements()) { - if (element2 instanceof TypeElement typeElement) { - fatal = fatal || processTypeElement(typeElement); - } + for (Element element2 : packageElement.getEnclosedElements()) { + if (element2 instanceof TypeElement typeElement) { + typeElements.add(typeElement); } } + } } } - if (fatal) { - throw new RuntimeException("Checks failed!"); - } + CompilationData compilationData = new CompilationData(typeElements, processingEnv); + SerdeProcessor.processTypes(compilationData); + AutoProfileProcessor.processTypes(compilationData); return false; } diff --git a/processor/src/main/java/org/frc5572/robotools/autoprofile/AutoProfileProcessor.java b/processor/src/main/java/org/frc5572/robotools/autoprofile/AutoProfileProcessor.java new file mode 100755 index 0000000..159ccc8 --- /dev/null +++ b/processor/src/main/java/org/frc5572/robotools/autoprofile/AutoProfileProcessor.java @@ -0,0 +1,11 @@ +package org.frc5572.robotools.autoprofile; + +import org.frc5572.robotools.CompilationData; + +public class AutoProfileProcessor { + + public static void processTypes(CompilationData compilationData) { + + } + +} diff --git a/processor/src/main/java/org/frc5572/robotools/checks/Check.java b/processor/src/main/java/org/frc5572/robotools/checks/Check.java deleted file mode 100755 index 03a76dc..0000000 --- a/processor/src/main/java/org/frc5572/robotools/checks/Check.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.frc5572.robotools.checks; - -import org.frc5572.robotools.CompilationData; - -/** A code checker */ -@FunctionalInterface -public interface Check { - - /** Check if code is fine. Returns true if error is fatal. */ - public boolean check(CompilationData data); - -} diff --git a/processor/src/main/java/org/frc5572/robotools/checks/IOCheck.java b/processor/src/main/java/org/frc5572/robotools/checks/IOCheck.java deleted file mode 100755 index 001b780..0000000 --- a/processor/src/main/java/org/frc5572/robotools/checks/IOCheck.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.frc5572.robotools.checks; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.SimpleAnnotationValueVisitor9; -import org.frc5572.robotools.CompilationData; -import org.frc5572.robotools.IOTypes; - -/** Performs checks to see that Subsystems do not contain raw IO types. */ -public class IOCheck implements Check { - - private void checkType(CompilationData data, Element[] warnPos, String path, TypeElement elem, - Set skip, String post) { - for (String iface : IOTypes.ioInterfaces) { - if (data.implementsInterface(elem, iface)) { - String[] parts = iface.split("\\."); - for (Element warnElem : warnPos) { - - data.error(warnElem, path + " is a " + parts[parts.length - 1] - + " which performs IO. It should be in an IO class!"); - - } - return; - } - } - for (String class_ : IOTypes.ioClasses) { - if (data.extendsClass(elem, class_)) { - String[] parts = class_.split("\\."); - for (Element warnElem : warnPos) { - - data.error(warnElem, path + " is a " + parts[parts.length - 1] - + " which performs IO. It should be in an IO class!"); - - } - return; - } - } - if (skip.contains(elem.getQualifiedName().toString())) { - return; - } - skip.add(elem.getQualifiedName().toString()); - outer: for (var item : elem.getEnclosedElements()) { - if (item instanceof VariableElement) { - VariableElement variable = (VariableElement) item; - for (AnnotationMirror mirror : item.getAnnotationMirrors()) { - Element annotationElement = mirror.getAnnotationType().asElement(); - if (annotationElement instanceof TypeElement) { - TypeElement annotationType = (TypeElement) annotationElement; - if (annotationType.getQualifiedName().toString() - .equals("java.lang.SuppressWarnings")) { - for (var entry : mirror.getElementValues().entrySet()) { - if (entry.getValue() - .accept(new SimpleAnnotationValueVisitor9() { - - @Override - public Boolean visitArray( - List vals, Void p) { - for (AnnotationValue v : vals) { - if (v.accept(this, null)) { - return true; - } - } - return false; - } - - @Override - public Boolean visitString(String s, Void p) { - if (s.equals("IOCheck")) { - return true; - } - return false; - } - }, null)) { - continue outer; - } - } - } - } - } - String post2 = ""; - TypeMirror typeMirror = variable.asType(); - while (typeMirror instanceof ArrayType) { - typeMirror = ((ArrayType) typeMirror).getComponentType(); - post2 += "[*]"; - } - Element element = data.types.asElement(typeMirror); - Element[] newElements = new Element[warnPos.length + 1]; - for (int i = 0; i < warnPos.length; i++) { - newElements[i] = warnPos[i]; - } - newElements[warnPos.length] = variable; - if (element instanceof TypeElement) { - TypeElement type = (TypeElement) element; - checkType(data, newElements, - path + post + "." + variable.getSimpleName().toString(), type, skip, post2); - } - } - } - } - - /** Perform check. */ - @Override - public boolean check(CompilationData data) { - if (data.implementsInterface("edu.wpi.first.wpilibj.RobotBase")) { - for (var item : data.element.getEnclosedElements()) { - if (item instanceof VariableElement) { - VariableElement variable = (VariableElement) item; - String path = - data.element.getQualifiedName() + "." + variable.getSimpleName().toString(); - String post = ""; - TypeMirror typeMirror = variable.asType(); - while (typeMirror instanceof ArrayType) { - typeMirror = ((ArrayType) typeMirror).getComponentType(); - post += "[*]"; - } - Element element = data.types.asElement(typeMirror); - if (element instanceof TypeElement) { - TypeElement type = (TypeElement) element; - Set skip = new HashSet<>(); - checkType(data, new Element[] {variable}, path, type, skip, post); - } - } - } - } - return false; - } - -} diff --git a/processor/src/main/java/org/frc5572/robotools/serde/SerdeProcessor.java b/processor/src/main/java/org/frc5572/robotools/serde/SerdeProcessor.java new file mode 100755 index 0000000..7e970ff --- /dev/null +++ b/processor/src/main/java/org/frc5572/robotools/serde/SerdeProcessor.java @@ -0,0 +1,11 @@ +package org.frc5572.robotools.serde; + +import org.frc5572.robotools.CompilationData; + +public class SerdeProcessor { + + public static void processTypes(CompilationData compilationData) { + + } + +} diff --git a/processor/src/main/java/org/frc5572/robotools/util/ReflectionUtil.java b/processor/src/main/java/org/frc5572/robotools/util/ReflectionUtil.java new file mode 100755 index 0000000..8b8add7 --- /dev/null +++ b/processor/src/main/java/org/frc5572/robotools/util/ReflectionUtil.java @@ -0,0 +1,203 @@ +package org.frc5572.robotools.util; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public final class ReflectionUtil { + private ReflectionUtil() {} + + private static final sun.misc.Unsafe UNSAFE = (sun.misc.Unsafe) staticFieldAccess(sun.misc.Unsafe.class, "theUnsafe"); + + private static final long ACCESSIBLE_OVERRIDE_FIELD_OFFSET; + private static final IllegalAccessException INIT_ERROR; + + @SuppressWarnings("deprecation") + private static long getOverrideFieldOffset() throws Throwable { + Field f = null; + Throwable saved = null; + try { + f = AccessibleObject.class.getDeclaredField("override"); + } catch(Throwable t) { + saved = t; + } + + if (f != null) { + return UNSAFE.objectFieldOffset(f); + } + + try{ + return UNSAFE.objectFieldOffset(Fake.class.getDeclaredField("override")); + } catch(Throwable t) { + throw saved; + } + } + + static { + long g; + Throwable ex; + try { + g = getOverrideFieldOffset(); + ex = null; + } catch (Throwable t) { + g = -1L; + ex = t; + } + + ACCESSIBLE_OVERRIDE_FIELD_OFFSET = g; + if(ex == null) { + INIT_ERROR = null; + } else if(ex instanceof IllegalAccessException ex2) { + INIT_ERROR = ex2; + } else { + INIT_ERROR = new IllegalAccessException("Cannot initialize Unsafe-based Reflection Util."); + INIT_ERROR.initCause(ex); + } + } + + private static Object staticFieldAccess(Class clazz, String name) { + try { + Field f = clazz.getDeclaredField(name); + f.setAccessible(true); + return f.get(null); + } catch(Exception e) { + return null; + } + } + + static class Fake { + boolean override; + Object accessCheckCache; + } + + public static T setAccessible(T accessor) { + if(INIT_ERROR == null) { + UNSAFE.putBoolean(accessor, ACCESSIBLE_OVERRIDE_FIELD_OFFSET, true); + } else { + accessor.setAccessible(true); + } + + return accessor; + } + + public static Method getMethod(Class c, String mName, Class... parameterTypes) throws NoSuchMethodException { + Method m = null; + Class oc = c; + while (c != null) { + try { + m = c.getDeclaredMethod(mName, parameterTypes); + break; + } catch (NoSuchMethodException e) {} + c = c.getSuperclass(); + } + + if (m == null) throw new NoSuchMethodException(oc.getName() + " :: " + mName + "(args)"); + return setAccessible(m); + } + + public static Method permissiveGetMethod(Class c, String mName, Class... parameterTypes) { + try { + return getMethod(c, mName, parameterTypes); + } catch (Exception ignore) { + return null; + } + } + + public static Field getField(Class c, String fName) throws NoSuchFieldException { + Field f = null; + Class oc = c; + while (c != null) { + try { + f = c.getDeclaredField(fName); + break; + } catch (NoSuchFieldException e) {} + c = c.getSuperclass(); + } + + if (f == null) throw new NoSuchFieldException(oc.getName() + " :: " + fName); + + return setAccessible(f); + } + + public static Field permissiveGetField(Class c, String fName) { + try { + return getField(c, fName); + } catch (Exception ignore) { + return null; + } + } + + public static T permissiveReadField(Class type, Field f, Object instance) { + try { + return type.cast(f.get(instance)); + } catch (Exception ignore) { + return null; + } + } + + public static Constructor getConstructor(Class c, Class... parameterTypes) throws NoSuchMethodException { + return setAccessible(c.getDeclaredConstructor(parameterTypes)); + } + + public static Object invoke(Method m, Object receiver, Object... args) throws IllegalAccessException, InvocationTargetException { + return invoke(null, m, receiver, args); + } + + public static Object invoke(Throwable initError, Method m, Object receiver, Object... args) throws IllegalAccessException, InvocationTargetException { + try { + return m.invoke(receiver, args); + } catch (IllegalAccessException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } + } + + public static T newInstance(Constructor c, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException { + return newInstance(null, c, args); + } + + public static T newInstance(Throwable initError, Constructor c, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException { + try { + return c.newInstance(args); + } catch (IllegalAccessException e) { + throw e; + } catch (InstantiationException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } + } + + @SuppressWarnings("unchecked") + public static T get(Field f, Object receiver) throws IllegalAccessException { + try { + return (T) f.get(receiver); + } catch (IllegalAccessException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } + } + + public static void set(Field f, Object receiver, Object newValue) throws IllegalAccessException { + try { + f.set(receiver, newValue); + } catch (IllegalAccessException e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Error e) { + throw e; + } + } + +} diff --git a/processor/src/main/java/org/frc5572/robotools/util/tree/JCClassTree.java b/processor/src/main/java/org/frc5572/robotools/util/tree/JCClassTree.java new file mode 100755 index 0000000..772dc96 --- /dev/null +++ b/processor/src/main/java/org/frc5572/robotools/util/tree/JCClassTree.java @@ -0,0 +1,29 @@ +package org.frc5572.robotools.util.tree; + +import java.lang.reflect.Field; + +import org.frc5572.robotools.util.ReflectionUtil; + +public class JCClassTree { + + private final Object underlyingJavacObject; + + public JCClassTree(Object object) { + this.underlyingJavacObject = object; + } + + private static final Field defs; + + static { + Field defs_ = null; + try { + Class clazz = Class.forName("com.sun.tools.javac.tree.JCTree.JCClassDecl"); + defs_ = ReflectionUtil.getField(clazz, "defs"); + Field extending = ReflectionUtil.getField(clazz, "extending"); + } catch (Exception e) { + e.printStackTrace(); + } + defs = defs_; + } + +} diff --git a/processor/src/main/resources/META-INF/services/com.sun.source.util.Plugin b/processor/src/main/resources/META-INF/services/com.sun.source.util.Plugin deleted file mode 100644 index 2057c50..0000000 --- a/processor/src/main/resources/META-INF/services/com.sun.source.util.Plugin +++ /dev/null @@ -1 +0,0 @@ -org.frc5572.robotools.RobotPlugin \ No newline at end of file