Resolve "Allow multi line strings in comment"

This commit is contained in:
Hari Nair
2022-09-24 14:47:47 +00:00
parent cfc8641f82
commit fbc0a5ff0a
6 changed files with 114 additions and 90 deletions

View File

@@ -11,17 +11,24 @@ import jackfruit.annotations.ParserClass;
public abstract class DemoClass {
@Key("key")
@Comment("field comment")
@DefaultValue("0")
@Comment("One line comment")
@DefaultValue("1")
public abstract int intMethod();
@Comment("This is a very long comment line that really should be wrapped into more than one line")
@DefaultValue("0.")
public abstract Double doubleMethod();
@Comment("""
This is a multiline
java text block.
This is a new paragraph.
""")
@DefaultValue("Default String")
public abstract String StringMethod();
@Comment("This string is serialized into an object")
@Comment("This string is serialized into an object\n\tThis comment contains a newline character, and this line starts with a tab.")
@DefaultValue("serialized string")
@ParserClass(SomeRandomClassParser.class)
public abstract SomeRandomClass randomClass();
@@ -38,5 +45,5 @@ public abstract class DemoClass {
public void noAnnotationsOnThisMethod() {
System.out.println("This method was not processed");
}
}

View File

@@ -45,17 +45,24 @@ public interface DemoInterface {
// default key is field name
@Key("key")
@Comment("field comment")
@DefaultValue("0")
@Comment("One line comment")
@DefaultValue("1")
int intMethod();
@Comment("This is a very long comment line that really should be wrapped into more than one line")
@DefaultValue("0.")
Double doubleMethod();
@Comment("""
This is a multiline
java text block.
This is a new paragraph.
""")
@DefaultValue("Default String")
String StringMethod();
@Comment("This string is serialized into an object")
@Comment("This string is serialized into an object\n\tThis comment contains a newline character, and this line starts with a tab.")
@DefaultValue("serialized string")
@ParserClass(SomeRandomClassParser.class)
SomeRandomClass randomClass();
@@ -63,10 +70,10 @@ public interface DemoInterface {
@Comment("List of Doubles")
@DefaultValue("0. 5.34 17")
List<Double> doubles();
@Comment("List of RandomClass")
@DefaultValue("obj1 obj2")
@ParserClass(SomeRandomClassParser.class)
List<SomeRandomClass> randoms();
}

View File

@@ -19,7 +19,7 @@ public class JackfruitDemo {
// get an example config object
DemoClass template = factory.getTemplate();
/*-
// or if you prefer, use an interface
DemoInterfaceFactory factory = new DemoInterfaceFactory();

View File

@@ -55,6 +55,11 @@
<artifactId>log4j-api</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>

View File

@@ -18,14 +18,14 @@ public abstract class AnnotationBundle {
/**
*
* @return the return type of this method without any parameters (e.g. return List rather than
* List<String>}
* List&lt;String&gt;)
*/
public abstract TypeMirror erasure();
/**
*
* @return the parameterized types, if any of this method (e.g. return String if the annotated
* method returns List<String>)
* method returns List&lt;String&gt;)
*/
public abstract List<TypeMirror> typeArgs();

View File

@@ -31,6 +31,7 @@ import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.text.WordUtils;
import com.google.auto.service.AutoService;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
@@ -271,7 +272,7 @@ public class ConfigProcessor extends AbstractProcessor {
AnnotationBundle ab = annotationsMap.get(method);
String key = prefix + ab.key();
if (needBlank) {
methodBuilder.addStatement(String.format("$N.setBlancLinesBefore(\"%s\", 1)", key), layout);
methodBuilder.addStatement("$N.setBlancLinesBefore($S, 1)", layout, key);
needBlank = false;
}
@@ -292,33 +293,54 @@ public class ConfigProcessor extends AbstractProcessor {
ParameterizedTypeName.get(ClassName.get(java.util.ArrayList.class), stringType);
String listName = method.getSimpleName() + "List";
methodBuilder.addStatement("$T " + listName + " = new $T()", listType, arrayListType);
methodBuilder
.beginControlFlow(String.format("for (var element : t.%s())", method.getSimpleName()));
methodBuilder.beginControlFlow("for (var element : t.$L())", method.getSimpleName());
if (ab.parserClass().isPresent()) {
methodBuilder
.addStatement(String.format("%s.add(%s.toString(element))", listName, parserName));
methodBuilder.addStatement("$L.add($L.toString(element))", listName, parserName);
} else {
methodBuilder
.addStatement(String.format("%s.add(String.format(\"%%s\", element))", listName));
TypeMirror typeArg = ab.typeArgs().get(0);
if (ConfigProcessorUtils.isByte(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Byte.class);
if (ConfigProcessorUtils.isBoolean(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Boolean.class);
if (ConfigProcessorUtils.isDouble(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Double.class);
if (ConfigProcessorUtils.isFloat(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Float.class);
if (ConfigProcessorUtils.isInteger(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Integer.class);
if (ConfigProcessorUtils.isLong(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Long.class);
if (ConfigProcessorUtils.isShort(typeArg, processingEnv))
methodBuilder.addStatement("$L.add($T.toString(element))", listName,
java.lang.Short.class);
if (ConfigProcessorUtils.isString(typeArg, processingEnv))
methodBuilder.addStatement("$L.add(element)", listName);
}
methodBuilder.endControlFlow();
methodBuilder.addStatement(String.format("config.setProperty(\"%s\", %s)", key, listName));
methodBuilder.addStatement("config.setProperty($S, $L)", key, listName);
} else {
if (ab.parserClass().isPresent()) {
// store the serialized string as the property
methodBuilder
.addStatement(String.format("config.setProperty(\"%s\", %s.toString($N.%s()))", key,
parserName, method.getSimpleName()), ps);
methodBuilder.addStatement("config.setProperty($S, $L.toString($N.$L()))", key,
parserName, ps, method.getSimpleName());
} else {
methodBuilder.addStatement(
String.format("config.setProperty(\"%s\", t.%s())", key, method.getSimpleName()));
methodBuilder.addStatement("config.setProperty($S, t.$L())", key, method.getSimpleName());
}
}
// add the comment
if (ab.comment().length() > 0)
methodBuilder.addStatement(
String.format("$N.setComment(\"%s\", \"%s\")", key, ab.comment()), layout);
if (ab.comment().length() > 0) {
String commentName = String.format("%sComment", method.getSimpleName());
methodBuilder.addStatement("$T $L = $S", String.class, commentName, ab.comment());
methodBuilder.addStatement("$N.setComment($S, $T.wrap($L, 80))", layout, key,
WordUtils.class, commentName);
}
}
methodBuilder.addCode("return config;");
@@ -347,7 +369,7 @@ public class ConfigProcessor extends AbstractProcessor {
if (bundle.parserClass().isPresent()) {
parser = bundle.parserClass().get();
parserName = method.getSimpleName() + "Parser";
builder.addStatement(String.format("$T %s = new $T()", parserName), parser, parser);
builder.addStatement("$T $L = new $T()", parser, parserName, parser);
}
if (ConfigProcessorUtils.isList(bundle.erasure(), processingEnv)) {
@@ -360,49 +382,46 @@ public class ConfigProcessor extends AbstractProcessor {
String listName = method.getSimpleName() + "List";
builder.addStatement("$T " + listName + " = new $T()", listType, arrayListType);
builder.addStatement(
String.format("String [] parts = \"%s\".split(\"\\\\s+\")", bundle.defaultValue()));
builder.addStatement("String [] parts = $S.split($S)", bundle.defaultValue(), "\\s+");
builder.beginControlFlow("for (String part : parts)");
builder.beginControlFlow("if (part.trim().length() > 0)");
if (bundle.parserClass().isPresent()) {
builder.addStatement(String.format("%s.add(%s.fromString(part))", listName, parserName));
builder.addStatement("$L.add($L.fromString(part))", listName, parserName);
} else {
TypeMirror typeArg = bundle.typeArgs().get(0);
if (ConfigProcessorUtils.isByte(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Byte.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Byte.class);
if (ConfigProcessorUtils.isBoolean(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Boolean.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Boolean.class);
if (ConfigProcessorUtils.isDouble(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Double.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Double.class);
if (ConfigProcessorUtils.isFloat(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Float.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Float.class);
if (ConfigProcessorUtils.isInteger(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Integer.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Integer.class);
if (ConfigProcessorUtils.isLong(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Long.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Long.class);
if (ConfigProcessorUtils.isShort(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Short.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Short.class);
if (ConfigProcessorUtils.isString(typeArg, processingEnv))
builder.addStatement(String.format("%s.add(part)", listName));
builder.addStatement("$L.add(part)", listName);
}
builder.endControlFlow();
builder.addStatement(String.format("return %s", listName));
builder.endControlFlow();
builder.addStatement("return $L", listName);
} else {
if (bundle.parserClass().isPresent()) {
builder.addStatement(
String.format("return %s.fromString(\"%s\")", parserName, bundle.defaultValue()));
builder.addStatement("return $L.fromString($S)", parserName, bundle.defaultValue());
} else {
if (ConfigProcessorUtils.isString(bundle.erasure(), processingEnv)) {
builder.addStatement(String.format("return \"%s\"", bundle.defaultValue()));
builder.addStatement("return $S", bundle.defaultValue());
} else {
builder.addStatement(String.format("return %s", bundle.defaultValue()));
if (bundle.defaultValue().trim().length() == 0) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
String.format("Default value on method %s is blank!", method.getSimpleName()));
}
builder.addStatement("return $L", bundle.defaultValue());
}
}
}
@@ -432,7 +451,7 @@ public class ConfigProcessor extends AbstractProcessor {
if (bundle.parserClass().isPresent()) {
parser = bundle.parserClass().get();
parserName = method.getSimpleName() + "Parser";
builder.addStatement(String.format("$T %s = new $T()", parserName), parser, parser);
builder.addStatement("$T $L = new $T()", parser, parserName, parser);
}
if (ConfigProcessorUtils.isList(bundle.erasure(), processingEnv)) {
@@ -443,68 +462,54 @@ public class ConfigProcessor extends AbstractProcessor {
ParameterizedTypeName.get(ClassName.get(java.util.ArrayList.class), argType);
String listName = method.getSimpleName() + "List";
builder.addStatement("$T " + listName + " = new $T()", listType, arrayListType);
builder.addStatement(String.format("String [] parts = config.getStringArray(\"%s\")",
prefix + bundle.key()));
builder.addStatement("String [] parts = config.getStringArray($S)", prefix + bundle.key());
builder.beginControlFlow("for (String part : parts)");
builder.beginControlFlow("if (part.trim().length() > 0)");
if (bundle.parserClass().isPresent()) {
builder.addStatement(String.format("%s.add(%s.fromString(part))", listName, parserName));
builder.addStatement("$L.add($L.fromString(part))", listName, parserName);
} else {
TypeMirror typeArg = bundle.typeArgs().get(0);
if (ConfigProcessorUtils.isByte(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Byte.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Byte.class);
if (ConfigProcessorUtils.isBoolean(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Boolean.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Boolean.class);
if (ConfigProcessorUtils.isDouble(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Double.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Double.class);
if (ConfigProcessorUtils.isFloat(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Float.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Float.class);
if (ConfigProcessorUtils.isInteger(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Integer.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Integer.class);
if (ConfigProcessorUtils.isLong(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Long.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Long.class);
if (ConfigProcessorUtils.isShort(typeArg, processingEnv))
builder.addStatement(String.format("%s.add($T.valueOf(part))", listName),
java.lang.Short.class);
builder.addStatement("$L.add($T.valueOf(part))", listName, java.lang.Short.class);
if (ConfigProcessorUtils.isString(typeArg, processingEnv))
builder.addStatement(String.format("%s.add(part)", listName));
builder.addStatement("$L.add(part)", listName);
}
builder.endControlFlow();
builder.addStatement(String.format("return %s", listName));
builder.endControlFlow();
builder.addStatement("return $L", listName);
} else {
if (bundle.parserClass().isPresent()) {
builder.addStatement(String.format("return %s.fromString(config.getString(\"%s\"))",
parserName, prefix + bundle.key()));
builder.addStatement("return $L.fromString(config.getString($S))", parserName,
prefix + bundle.key());
} else {
if (ConfigProcessorUtils.isBoolean(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getBoolean(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getBoolean($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isByte(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getByte(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getByte($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isDouble(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getDouble(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getDouble($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isFloat(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getFloat(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getFloat($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isInteger(bundle.erasure(), processingEnv)) {
builder
.addStatement(String.format("return config.getInt(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getInt($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isLong(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getLong(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getLong($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isShort(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getShort(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getShort($S)", prefix + bundle.key());
} else if (ConfigProcessorUtils.isString(bundle.erasure(), processingEnv)) {
builder.addStatement(
String.format("return config.getString(\"%s\")", prefix + bundle.key()));
builder.addStatement("return config.getString($S)", prefix + bundle.key());
} else {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
"Can't handle return type " + m.getReturnType().getCanonicalName());