Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/main/java/org/frc5572/robotools/BoolVisitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.frc5572.robotools;

import javax.lang.model.util.SimpleAnnotationValueVisitor8;

/** Find all uses of a string in annotation values */
public class BoolVisitor extends SimpleAnnotationValueVisitor8<Boolean, Void> {

@Override
public Boolean visitBoolean(boolean arg0, Void arg1) {
return arg0;
}

}
8 changes: 7 additions & 1 deletion src/main/java/org/frc5572/robotools/RobotProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ private void processGenerateTypeStateBuilder(TypeElement annotation,
TypeElement parent = (TypeElement) parent_;
String builderName = parent.getSimpleName() + "Builder";
String builderPackage = getPackageName(parent);
boolean isLinear = false;
// System.out.println("Processing " + builderPackage + "." + builderName);
for (var mirror : constructorElement.getAnnotationMirrors()) {
if (!mirror.getAnnotationType().asElement().getSimpleName().toString()
Expand All @@ -84,6 +85,11 @@ private void processGenerateTypeStateBuilder(TypeElement annotation,
if (res != null) {
builderName = res;
}
} else if (ev.getKey().getSimpleName().toString().equals("linear")) {
Boolean res = ev.getValue().accept(new BoolVisitor(), null);
if (res != null) {
isLinear = res;
}
}
}
}
Expand Down Expand Up @@ -136,7 +142,7 @@ private void processGenerateTypeStateBuilder(TypeElement annotation,
var specBuilder =
TypeSpec.classBuilder(builderName).addModifiers(Modifier.PUBLIC, Modifier.FINAL);

TypeStateBuilder typeStateBuilder = new TypeStateBuilder(builderName,
TypeStateBuilder typeStateBuilder = new TypeStateBuilder(builderName, isLinear,
fields.toArray(TypeStateBuilder.Field[]::new), parent.asType());
typeStateBuilder.apply(specBuilder);

Expand Down
97 changes: 57 additions & 40 deletions src/main/java/org/frc5572/robotools/TypeStateBuilder.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package org.frc5572.robotools;

import java.util.ArrayList;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
Expand All @@ -22,12 +20,14 @@ public class TypeStateBuilder {
private final ArrayList<OptionalField> optionalFields = new ArrayList<>();
private final Field[] fields;
private final TypeMirror result;
private final boolean isLinear;

/** Template builder for TypeState Builders */
public TypeStateBuilder(String name, Field[] fields_, TypeMirror result) {
public TypeStateBuilder(String name, boolean isLinear, Field[] fields_, TypeMirror result) {
this.fields = fields_;
this.result = result;
this.name = name;
this.isLinear = isLinear;
for (var field : fields_) {
if (field instanceof RequiredField rField) {
requiredFields.add(rField);
Expand All @@ -39,10 +39,12 @@ public TypeStateBuilder(String name, Field[] fields_, TypeMirror result) {
}
}

private static boolean advance(boolean[] enabled) {
private static boolean advance(boolean[] enabled, boolean isLinear) {
for (int i = 0; i < enabled.length; i++) {
if (enabled[i]) {
enabled[i] = false;
if (!isLinear) {
enabled[i] = false;
}
} else {
enabled[i] = true;
return true;
Expand All @@ -57,60 +59,65 @@ public void apply(TypeSpec.Builder builder) {

MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
for (var field : initFields) {
builder.addField(FieldSpec
.builder(TypeName.get(field.type), field.name + "_", Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
builder.addField(FieldSpec.builder(TypeName.get(field.type), field.name + "_",
Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addCode("this." + field.name + "_ = " + field.name + "_;\n");
}
for (var field : optionalFields) {
builder.addField(FieldSpec
.builder(TypeName.get(field.type), field.name + "_", Modifier.PRIVATE, Modifier.FINAL).build());
builder.addField(FieldSpec.builder(TypeName.get(field.type), field.name + "_",
Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addCode("this." + field.name + "_ = " + field.default_code + ";\n");
}
builder.addMethod(constructor.addModifiers(Modifier.PUBLIC).build());
constructor = MethodSpec.constructorBuilder();
boolean isDifferent = false;
for (var field : initFields) {
constructor.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addCode("this." + field.name + "_ = " + field.name + "_;\n");
}
for (var field : optionalFields) {
constructor.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addCode("this." + field.name + "_ = " + field.name + "_;\n");
isDifferent = true;
}
if (isDifferent) {
builder.addMethod(constructor.addModifiers(Modifier.PRIVATE).build());
}
addMethods(builder, enabled);
while (advance(enabled)) {
while (advance(enabled, isLinear)) {
constructor = MethodSpec.constructorBuilder();
for (int i = 0; i < enabled.length; i++) {
if (enabled[i]) {
var field = requiredFields.get(i);
constructor.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addCode("this." + field.name + "_ = " + field.name + "_;\n");
}
}
TypeSpec.Builder stepClass = TypeSpec.classBuilder(getName(enabled));
for (int i = 0; i < enabled.length; i++) {
if (enabled[i]) {
var field = requiredFields.get(i);
stepClass.addField(FieldSpec
.builder(TypeName.get(field.type), field.name + "_", Modifier.PRIVATE, Modifier.FINAL)
.build());
stepClass.addField(FieldSpec.builder(TypeName.get(field.type), field.name + "_",
Modifier.PRIVATE, Modifier.FINAL).build());
}
}
for (var field : initFields) {
stepClass.addField(FieldSpec
.builder(TypeName.get(field.type), field.name + "_", Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
stepClass.addField(FieldSpec.builder(TypeName.get(field.type), field.name + "_",
Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addCode("this." + field.name + "_ = " + field.name + "_;\n");
}
for (var field : optionalFields) {
stepClass.addField(FieldSpec
.builder(TypeName.get(field.type), field.name + "_", Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
stepClass.addField(FieldSpec.builder(TypeName.get(field.type), field.name + "_",
Modifier.PRIVATE, Modifier.FINAL).build());
constructor.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
constructor.addCode("this." + field.name + "_ = " + field.name + "_;\n");
}
stepClass.addMethod(constructor.addModifiers(Modifier.PRIVATE).build());
Expand Down Expand Up @@ -143,8 +150,8 @@ private void addMethods(TypeSpec.Builder builder, boolean[] enabled) {
}
if (isFinishable) {
TypeName returnType = TypeName.get(result);
MethodSpec.Builder finish = MethodSpec.methodBuilder("finish").addModifiers(Modifier.PUBLIC)
.returns(returnType);
MethodSpec.Builder finish = MethodSpec.methodBuilder("finish")
.addModifiers(Modifier.PUBLIC).returns(returnType);
String code = "return new " + returnType + "(";
boolean isFirst = true;
for (Field field : fields) {
Expand All @@ -164,8 +171,10 @@ private void addMethods(TypeSpec.Builder builder, boolean[] enabled) {
System.arraycopy(enabled, 0, next, 0, enabled.length);
next[i] = true;
String nextName = getName(next);
MethodSpec.Builder method = MethodSpec.methodBuilder(field.name).returns(ClassName.get("", nextName));
method.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
MethodSpec.Builder method =
MethodSpec.methodBuilder(field.name).returns(ClassName.get("", nextName));
method.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
String code = "return new " + nextName + "(";
boolean isFirst = true;
for (int j = 0; j < enabled.length; j++) {
Expand Down Expand Up @@ -195,9 +204,10 @@ private void addMethods(TypeSpec.Builder builder, boolean[] enabled) {
builder.addMethod(method.addModifiers(Modifier.PUBLIC).build());

if (field.alt != null) {
method = MethodSpec.methodBuilder(field.name).returns(ClassName.get("", nextName));
method.addParameter(
ParameterSpec.builder(TypeName.get(field.alt.type), field.alt.parameterName).build());
method =
MethodSpec.methodBuilder(field.name).returns(ClassName.get("", nextName));
method.addParameter(ParameterSpec
.builder(TypeName.get(field.alt.type), field.alt.parameterName).build());
code = "return new " + nextName + "(";
isFirst = true;
for (int j = 0; j < enabled.length; j++) {
Expand Down Expand Up @@ -234,12 +244,17 @@ private void addMethods(TypeSpec.Builder builder, boolean[] enabled) {
method.addCode(code + ");\n");
builder.addMethod(method.addModifiers(Modifier.PUBLIC).build());
}
if (isLinear) {
break;
}
}
}
String thisName = getName(enabled);
for (var field : optionalFields) {
MethodSpec.Builder method = MethodSpec.methodBuilder(field.name).returns(ClassName.get("", thisName));
method.addParameter(ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
MethodSpec.Builder method =
MethodSpec.methodBuilder(field.name).returns(ClassName.get("", thisName));
method.addParameter(
ParameterSpec.builder(TypeName.get(field.type), field.name + "_").build());
String code = "return new " + thisName + "(";
boolean isFirst = true;
for (int i = 0; i < enabled.length; i++) {
Expand Down Expand Up @@ -270,8 +285,8 @@ private void addMethods(TypeSpec.Builder builder, boolean[] enabled) {

if (field.alt != null) {
method = MethodSpec.methodBuilder(field.name).returns(ClassName.get("", thisName));
method.addParameter(
ParameterSpec.builder(TypeName.get(field.alt.type), field.alt.parameterName).build());
method.addParameter(ParameterSpec
.builder(TypeName.get(field.alt.type), field.alt.parameterName).build());
code = "return new " + thisName + "(";
isFirst = true;
for (int i = 0; i < enabled.length; i++) {
Expand Down Expand Up @@ -361,11 +376,12 @@ public RequiredField(TypeMirror type, String name) {

/** A field that is required to finish the builder. */
public static RequiredField fromAnnotation(TypeMirror type, String name,
AnnotationMirror mirror) {
AnnotationMirror mirror) {
AltMethod alt = null;
for (var ev : mirror.getElementValues().entrySet()) {
if (ev.getKey().getSimpleName().toString().equals("alt")) {
AnnotationMirror altMirror = ev.getValue().accept(new AnnotationMirrorVisitor(), null);
AnnotationMirror altMirror =
ev.getValue().accept(new AnnotationMirrorVisitor(), null);
alt = AltMethod.fromAnnotation(altMirror, name);
}
}
Expand All @@ -392,14 +408,15 @@ public OptionalField(TypeMirror type, String name, String default_code) {

/** A field that has a default in case it is not specified. */
public static OptionalField fromAnnotation(TypeMirror type, String name,
AnnotationMirror mirror) {
AnnotationMirror mirror) {
String defaultCode = "";
AltMethod alt = null;
for (var ev : mirror.getElementValues().entrySet()) {
if (ev.getKey().getSimpleName().toString().equals("value")) {
defaultCode = ev.getValue().accept(new StringVisitor(), null);
} else if (ev.getKey().getSimpleName().toString().equals("alt")) {
AnnotationMirror altMirror = ev.getValue().accept(new AnnotationMirrorVisitor(), null);
AnnotationMirror altMirror =
ev.getValue().accept(new AnnotationMirrorVisitor(), null);
alt = AltMethod.fromAnnotation(altMirror, name);
}
}
Expand All @@ -417,9 +434,9 @@ public static AltMethod fromAnnotation(AnnotationMirror mirror, String defaultNa
}

if (!mirror.getAnnotationType().asElement().getSimpleName().toString()
.equals("AltMethod")) {
.equals("AltMethod")) {
System.out.println("annotation name doesn't match "
+ mirror.getAnnotationType().asElement().getSimpleName().toString());
+ mirror.getAnnotationType().asElement().getSimpleName().toString());
return null;
}
TypeMirror type = null;
Expand Down
Loading