Compare commits
2 Commits
7395be2090
...
3f86f09606
Author | SHA1 | Date |
---|---|---|
Johannes Frohnmeyer | 3f86f09606 | |
Johannes Frohnmeyer | 943d9134b3 |
|
@ -68,6 +68,14 @@ public class Main {
|
|||
public Map<Integer, String> map3;
|
||||
|
||||
public Map<UUID, String> map4;
|
||||
|
||||
public Inner inner;
|
||||
|
||||
@GSerializable
|
||||
public record Inner(String s, Inner2 inner2) {
|
||||
@GSerializable
|
||||
public record Inner2(String s) {}
|
||||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
`java-library`
|
||||
id("jf.maven-publish")
|
||||
id("jf.manifold")
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package extensions.com.squareup.javapoet.ClassName;
|
||||
|
||||
import com.squareup.javapoet.ClassName;
|
||||
import manifold.ext.rt.api.Extension;
|
||||
import manifold.ext.rt.api.This;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Extension
|
||||
public class ClassNameExt {
|
||||
public static String getSimpleName(@This ClassName thiz) {
|
||||
return thiz.simpleName();
|
||||
}
|
||||
|
||||
public static String getPackageName(@This ClassName thiz) {
|
||||
return thiz.packageName();
|
||||
}
|
||||
|
||||
public static List<String> getSimpleNames(@This ClassName thiz) {
|
||||
return thiz.simpleNames();
|
||||
}
|
||||
}
|
|
@ -43,9 +43,9 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
} catch (ClassNotFoundException e) {
|
||||
hasManifold = false;
|
||||
}
|
||||
message = processingEnv.getMessager();
|
||||
filer = processingEnv.getFiler();
|
||||
elements = processingEnv.getElementUtils();
|
||||
message = processingEnv.messager;
|
||||
filer = processingEnv.filer;
|
||||
elements = processingEnv.elementUtils;
|
||||
seen = new LinkedHashMap<>();
|
||||
valueCreator = new ValueCreator(processingEnv);
|
||||
for (Adapter adapter : Adapters.ADAPTERS) {
|
||||
|
@ -59,9 +59,9 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
// Gather all serializable types
|
||||
for (TypeElement annotation : annotations) {
|
||||
for (Element element : roundEnvironment.getElementsAnnotatedWith(annotation)) {
|
||||
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
|
||||
for (AnnotationMirror mirror : element.annotationMirrors) {
|
||||
try {
|
||||
if (mirror.getAnnotationType().toString().equals(GSerializable.class.getCanonicalName())) {
|
||||
if (mirror.annotationType.toString().equals(GSerializable.class.getCanonicalName())) {
|
||||
var bld = new Object() {
|
||||
TypeMirror with = null;
|
||||
TypeMirror builder = null;
|
||||
|
@ -69,23 +69,23 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
Boolean generateAdapter = null;
|
||||
};
|
||||
elements.getElementValuesWithDefaults(mirror).forEach((executableElement, value) -> {
|
||||
String name = executableElement.getSimpleName().toString();
|
||||
String name = executableElement.simpleName.toString();
|
||||
switch (name) {
|
||||
case "with" -> {
|
||||
if (bld.with != null) throw new IllegalArgumentException("Duplicate annotation parameter: with");
|
||||
bld.with = (TypeMirror) value.getValue();
|
||||
bld.with = (TypeMirror) value.value;
|
||||
}
|
||||
case "builder" -> {
|
||||
if (bld.builder != null) throw new IllegalArgumentException("Duplicate annotation parameter: builder");
|
||||
bld.builder = (TypeMirror) value.getValue();
|
||||
bld.builder = (TypeMirror) value.value;
|
||||
}
|
||||
case "configure" -> {
|
||||
if (bld.configure != null) throw new IllegalArgumentException("Duplicate annotation parameter: configure");
|
||||
bld.configure = (TypeMirror) value.getValue();
|
||||
bld.configure = (TypeMirror) value.value;
|
||||
}
|
||||
case "generateAdapter" -> {
|
||||
if (bld.generateAdapter != null) throw new IllegalArgumentException("Duplicate annotation parameter: generateAdapter");
|
||||
bld.generateAdapter = (Boolean) value.getValue();
|
||||
bld.generateAdapter = (Boolean) value.value;
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Unexpected annotation parameter: " + name);
|
||||
}
|
||||
|
@ -114,7 +114,13 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
}
|
||||
for (var entry : seen.keySet().stream().collect(Collectors.groupingBy(ClassName::packageName)).entrySet()) {
|
||||
Map<List<String>, TypeSpec.Builder> known = entry.getValue().stream().collect(Collectors.toMap(ClassName::simpleNames, seen::get));
|
||||
Map<List<String>, TypeSpec.Builder> known = entry.value.stream()
|
||||
.collect(Collectors.toMap(
|
||||
ClassName::simpleNames,
|
||||
seen::get,
|
||||
(u, v) -> u,
|
||||
() -> new TreeMap<>(StringListComparator.INSTANCE.reversed())
|
||||
));
|
||||
// Generate additional parent classes
|
||||
for (List<String> klazz : known.keySet().stream().toList()) {
|
||||
List<String> current = new LinkedList<>();
|
||||
|
@ -131,21 +137,21 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
// Add to parent class
|
||||
for (var entry1 : known.entrySet()) {
|
||||
if (entry1.getKey().size() == 1) continue;
|
||||
find(known, entry1.getKey().subList(0, entry1.getKey().size() - 1)).addType(entry1.getValue().build());
|
||||
if (entry1.key.size() == 1) continue;
|
||||
find(known, entry1.key.subList(0, entry1.key.size() - 1)).addType(entry1.value.build());
|
||||
}
|
||||
// Print
|
||||
// System.out.println("Got " + known.size() + " classes");
|
||||
// for (var entry1 : known.entrySet()) {
|
||||
// System.out.println("Class " + entry.getKey() + '.' + String.join(".", entry1.getKey()));
|
||||
// for (TypeSpec typeSpec : entry1.getValue().typeSpecs) {
|
||||
// System.out.println("Class " + entry.key + '.' + String.join(".", entry1.key));
|
||||
// for (TypeSpec typeSpec : entry1.value.typeSpecs) {
|
||||
// System.out.println("- " + typeSpec.name);
|
||||
// }
|
||||
// }
|
||||
// Write top-level classes
|
||||
for (var entry1 : known.entrySet()) {
|
||||
if (entry1.getKey().size() == 1) {
|
||||
JavaFile javaFile = JavaFile.builder(entry.getKey(), entry1.getValue().build())
|
||||
if (entry1.key.size() == 1) {
|
||||
JavaFile javaFile = JavaFile.builder(entry.key, entry1.value.build())
|
||||
.skipJavaLangImports(true)
|
||||
.indent(" ")
|
||||
.build();
|
||||
|
@ -162,14 +168,14 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
|
||||
private <K, V> V find(Map<List<K>, V> map, List<K> key) {
|
||||
for (var entry : map.entrySet()) if (entry.getKey().equals(key)) return entry.getValue();
|
||||
for (var entry : map.entrySet()) if (entry.key.equals(key)) return entry.value;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void process(SerializableClass toProcess, Set<SerializableClass> other) throws ElementException {
|
||||
if (seen.containsKey(toProcess.generatedClassName())) return; // Don't process the same class more than once
|
||||
if (seen.containsKey(toProcess.generatedClassName)) return; // Don't process the same class more than once
|
||||
|
||||
TypeName classType = toProcess.getTypeName();
|
||||
TypeName classType = toProcess.typeName;
|
||||
List<TypeVariableName> typeVariables = new ArrayList<>();
|
||||
if (classType instanceof ParameterizedTypeName type) {
|
||||
for (TypeName argument : type.typeArguments) {
|
||||
|
@ -177,18 +183,18 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
}
|
||||
|
||||
TypeSpec.Builder spec = TypeSpec.classBuilder(toProcess.generatedClassName().simpleName())
|
||||
.addOriginatingElement(toProcess.classElement())
|
||||
TypeSpec.Builder spec = TypeSpec.classBuilder(toProcess.generatedClassName.simpleName())
|
||||
.addOriginatingElement(toProcess.classElement)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addTypeVariables(typeVariables);
|
||||
|
||||
seen.put(toProcess.generatedClassName(), spec);
|
||||
seen.put(toProcess.generatedClassName, spec);
|
||||
|
||||
if (toProcess.adapter() != null) {
|
||||
generateDelegateToAdapter(spec, classType, toProcess.adapter());
|
||||
if (toProcess.adapter != null) {
|
||||
generateDelegateToAdapter(spec, classType, toProcess.adapter);
|
||||
} else {
|
||||
if (toProcess.generateAdapter()) {
|
||||
generateDelegatingAdapter(spec, classType, toProcess.generatedClassName());
|
||||
if (toProcess.generateAdapter) {
|
||||
generateDelegatingAdapter(spec, classType, toProcess.generatedClassName);
|
||||
}
|
||||
generateSerialisation(spec, toProcess, typeVariables, other);
|
||||
}
|
||||
|
@ -207,7 +213,7 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
.addParameter(Cl.GSON_WRITER, "writer")
|
||||
.addParameter(classType, "value")
|
||||
.addException(IOException.class)
|
||||
.addCode(generatedClassName.simpleName() + ".write(value, writer);")
|
||||
.addCode(generatedClassName.simpleName + ".write(value, writer);")
|
||||
.build())
|
||||
.addMethod(MethodSpec.methodBuilder("read")
|
||||
.addAnnotation(Override.class)
|
||||
|
@ -215,7 +221,7 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
.addParameter(Cl.GSON_READER, "reader")
|
||||
.addException(IOException.class)
|
||||
.returns(classType)
|
||||
.addCode("return " + generatedClassName.simpleName() + ".read(reader);")
|
||||
.addCode("return " + generatedClassName.simpleName + ".read(reader);")
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
|
@ -358,9 +364,9 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
|
||||
private void generateSerialisation(TypeSpec.Builder spec, SerializableClass self, List<TypeVariableName> typeVariables, Set<SerializableClass> otherAdapters) throws ElementException {
|
||||
Value value = self.builder() == null ? valueCreator.from(self.classElement(), false) : valueCreator.from(TypeHelper.asDeclaredType(self.builder()).asElement(), true);
|
||||
ConstructionSource constructionSource = value.getConstructionSource();
|
||||
Properties properties = value.getProperties();
|
||||
Value value = self.builder == null ? valueCreator.from(self.classElement, false) : valueCreator.from(TypeHelper.asDeclaredType(self.builder).asElement(), true);
|
||||
ConstructionSource constructionSource = value.constructionSource;
|
||||
Properties properties = value.properties;
|
||||
|
||||
// public static void write(JsonWriter writer, T value) throws IOException
|
||||
{
|
||||
|
@ -373,16 +379,16 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
code.addStatement("writer.beginObject()");
|
||||
for (Property.Field param : properties.fields) {
|
||||
if (Properties.containsName(properties.getters, param)) continue;
|
||||
Runnable writeGet = () -> code.add("value.$N", param.getCallableName());
|
||||
if (param.getType().getKind().isPrimitive()) {
|
||||
Runnable writeGet = () -> code.add("value.$N", param.callableName);
|
||||
if (param.type.kind.isPrimitive) {
|
||||
generateComments(param, code);
|
||||
code.addStatement("writer.name($S)", getSerializedName(param));
|
||||
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, writeGet);
|
||||
} else {
|
||||
code.beginControlFlow("if (value.$N != null || writer.getSerializeNulls())", param.getCallableName());
|
||||
code.beginControlFlow("if (value.$N != null || writer.getSerializeNulls())", param.callableName);
|
||||
generateComments(param, code);
|
||||
code.addStatement("writer.name($S)", getSerializedName(param));
|
||||
code.addStatement("if (value.$N == null) writer.nullValue()", param.getCallableName());
|
||||
code.addStatement("if (value.$N == null) writer.nullValue()", param.callableName);
|
||||
code.beginControlFlow("else");
|
||||
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, writeGet);
|
||||
code.endControlFlow();
|
||||
|
@ -390,25 +396,25 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
}
|
||||
for (Property.Getter param : properties.getters) {
|
||||
if (param.getType().getKind().isPrimitive()) {
|
||||
if (param.type.kind.isPrimitive) {
|
||||
generateComments(param, code);
|
||||
code.addStatement("writer.name($S)", getSerializedName(param));
|
||||
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, () -> code.add("value.$N()", param.getCallableName()));
|
||||
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, () -> code.add("value.$N()", param.callableName));
|
||||
} else {
|
||||
code.addStatement("$T $L$N = value.$N()", param.getType(), "$", param.getCallableName(), param.getCallableName());
|
||||
code.beginControlFlow("if ($L$N != null || writer.getSerializeNulls())", "$", param.getCallableName());
|
||||
code.addStatement("$T $L$N = value.$N()", param.type, "$", param.callableName, param.callableName);
|
||||
code.beginControlFlow("if ($L$N != null || writer.getSerializeNulls())", "$", param.callableName);
|
||||
generateComments(param, code);
|
||||
code.addStatement("writer.name($S)", getSerializedName(param));
|
||||
code.addStatement("if ($L$N == null) writer.nullValue()", "$", param.getCallableName());
|
||||
code.addStatement("if ($L$N == null) writer.nullValue()", "$", param.callableName);
|
||||
code.beginControlFlow("else");
|
||||
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, () -> code.add("$L$N", "$", param.getCallableName()));
|
||||
Adapters.generateWrite(param, spec, code, typeVariables, otherAdapters, message, () -> code.add("$L$N", "$", param.callableName));
|
||||
code.endControlFlow();
|
||||
code.endControlFlow();
|
||||
}
|
||||
}
|
||||
code.addStatement("writer.endObject()");
|
||||
|
||||
spec.addMethod(extension(MethodSpec.methodBuilder("write"), self.getTypeName())
|
||||
spec.addMethod(extension(MethodSpec.methodBuilder("write"), self.typeName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.addParameter(Cl.GSON_WRITER, "writer")
|
||||
.addException(IOException.class)
|
||||
|
@ -427,7 +433,7 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
boolean isEmpty = true;
|
||||
for (Property<?> param : properties.names) {
|
||||
isEmpty = false;
|
||||
code.addStatement("$T _$N = $L", param.getType(), param.getName(), TypeHelper.getDefaultValue(param.getType()));
|
||||
code.addStatement("$T _$N = $L", param.type, param.name, TypeHelper.getDefaultValue(param.type));
|
||||
}
|
||||
if (isEmpty) {
|
||||
code.addStatement("reader.skipValue()");
|
||||
|
@ -436,16 +442,16 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
.beginControlFlow("while (reader.hasNext())")
|
||||
.beginControlFlow("switch (reader.nextName())");
|
||||
for (Property<?> param : properties.names) {
|
||||
if (param.getType().getKind().isPrimitive()) {
|
||||
code.add("case $S -> _$N = ", getSerializedName(param), param.getName());
|
||||
if (param.type.kind.isPrimitive) {
|
||||
code.add("case $S -> _$N = ", getSerializedName(param), param.name);
|
||||
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, message);
|
||||
code.add(";\n");
|
||||
} else {
|
||||
code.beginControlFlow("case $S ->", getSerializedName(param))
|
||||
.beginControlFlow("if (reader.peek() == $T.NULL)", Cl.GSON_TOKEN)
|
||||
.addStatement("reader.nextNull()")
|
||||
.addStatement("_$N = null", param.getName());
|
||||
code.unindent().add("} else _$N = ", param.getName());
|
||||
.addStatement("_$N = null", param.name);
|
||||
code.unindent().add("} else _$N = ", param.name);
|
||||
Adapters.generateRead(param, spec, code, typeVariables, otherAdapters, message);
|
||||
code.add(";\n")
|
||||
.endControlFlow();
|
||||
|
@ -459,48 +465,48 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
.addStatement("reader.endObject()");
|
||||
}
|
||||
|
||||
code.addStatement("$T result", self.getTypeName());
|
||||
ClassName creatorName = ClassName.get((TypeElement) constructionSource.getConstructionElement().getEnclosingElement());
|
||||
code.addStatement("$T result", self.typeName);
|
||||
ClassName creatorName = ClassName.get((TypeElement) constructionSource.constructionElement.enclosingElement);
|
||||
if (constructionSource instanceof ConstructionSource.Builder builder) {
|
||||
StringBuilder args = new StringBuilder();
|
||||
for (Property.ConstructorParam param : properties.constructorParams) {
|
||||
args.append(", _").append(param.getName());
|
||||
args.append(", _").append(param.name);
|
||||
}
|
||||
code.add("$T builder = ", builder.getBuilderClass());
|
||||
if (constructionSource.isConstructor()) {
|
||||
code.add("new $T($L)", builder.getBuilderClass(), args.length() > 0 ? args.substring(2) : "");
|
||||
code.add("$T builder = ", builder.builderClass);
|
||||
if (constructionSource.isConstructor) {
|
||||
code.add("new $T($L)", builder.builderClass, args.length() > 0 ? args.substring(2) : "");
|
||||
} else {
|
||||
code.add("$T.$N($L)", creatorName, self.classElement().getSimpleName(), args.length() > 0 ? args.substring(2) : "");
|
||||
code.add("$T.$N($L)", creatorName, self.classElement.simpleName, args.length() > 0 ? args.substring(2) : "");
|
||||
}
|
||||
code.add(";\n");
|
||||
for (Property.Setter param : properties.builderParams) {
|
||||
code.addStatement("builder.$N(_$N)", param.getCallableName(), param.getName());
|
||||
code.addStatement("builder.$N(_$N)", param.callableName, param.name);
|
||||
}
|
||||
code.addStatement("result = builder.$N()", builder.getBuildMethod().getSimpleName());
|
||||
code.addStatement("result = builder.$N()", builder.buildMethod.simpleName);
|
||||
} else {
|
||||
StringBuilder args = new StringBuilder();
|
||||
for (Property.Param param : properties.params) {
|
||||
args.append(", _").append(param.getName());
|
||||
args.append(", _").append(param.name);
|
||||
}
|
||||
if (constructionSource.isConstructor()) {
|
||||
code.addStatement("result = new $T($L)", self.getTypeName(), args.length() > 0 ? args.substring(2) : "");
|
||||
if (constructionSource.isConstructor) {
|
||||
code.addStatement("result = new $T($L)", self.typeName, args.length() > 0 ? args.substring(2) : "");
|
||||
} else {
|
||||
code.addStatement("result = $T.$N($L)", creatorName, constructionSource.getConstructionElement().getSimpleName(), args.length() > 0 ? args.substring(2) : "");
|
||||
code.addStatement("result = $T.$N($L)", creatorName, constructionSource.constructionElement.simpleName, args.length() > 0 ? args.substring(2) : "");
|
||||
}
|
||||
}
|
||||
for (Property.Setter setter : properties.setters) {
|
||||
code.addStatement("result.$N(_$N)", setter.getCallableName(), setter.getName());
|
||||
code.addStatement("result.$N(_$N)", setter.callableName, setter.name);
|
||||
}
|
||||
for (Property.Field field : properties.fields) {
|
||||
if (Properties.containsName(properties.setters, field)) continue;
|
||||
if (Properties.containsName(properties.params, field)) continue;
|
||||
code.addStatement("result.$N = _$N", field.getName(), field.getCallableName());
|
||||
code.addStatement("result.$N = _$N", field.name, field.callableName);
|
||||
}
|
||||
code.addStatement("return result");
|
||||
|
||||
spec.addMethod(extension(MethodSpec.methodBuilder("read"))
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.returns(self.getTypeName())
|
||||
.returns(self.typeName)
|
||||
.addParameter(Cl.GSON_READER, "reader")
|
||||
.addException(IOException.class)
|
||||
.addCode(code.build())
|
||||
|
@ -509,21 +515,21 @@ public class GsonCompileProcessor extends AbstractProcessor2 {
|
|||
}
|
||||
|
||||
private void generateComments(Property<?> prop, CodeBlock.Builder code) {
|
||||
for (AnnotationMirror annotation : prop.getAnnotations()) {
|
||||
if (annotation.getAnnotationType().asElement().toString().equals(Cl.GCOMMENT.toString())) {
|
||||
String comment = (String) annotation.getElementValues().values().iterator().next().getValue();
|
||||
for (AnnotationMirror annotation : prop.annotations) {
|
||||
if (annotation.annotationType.asElement().toString().equals(Cl.GCOMMENT.toString())) {
|
||||
String comment = (String) annotation.elementValues.values().iterator().next().value;
|
||||
code.addStatement("if (writer.isLenient()) writer.comment($S)", comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSerializedName(Property<?> property) {
|
||||
for (AnnotationMirror annotationMirror : property.getAnnotations()) {
|
||||
if (annotationMirror.getAnnotationType().asElement().toString().equals(Cl.SERIALIZED_NAME.toString())) {
|
||||
return (String) annotationMirror.getElementValues().values().iterator().next().getValue();
|
||||
for (AnnotationMirror annotationMirror : property.annotations) {
|
||||
if (annotationMirror.annotationType.asElement().toString().equals(Cl.SERIALIZED_NAME.toString())) {
|
||||
return (String) annotationMirror.elementValues.values().iterator().next().value;
|
||||
}
|
||||
}
|
||||
return property.getName();
|
||||
return property.name;
|
||||
}
|
||||
|
||||
private MethodSpec.Builder extension(MethodSpec.Builder method) {
|
||||
|
|
|
@ -11,8 +11,8 @@ import javax.lang.model.type.TypeMirror;
|
|||
public record SerializableClass(TypeElement classElement, ClassName generatedClassName, @Nullable TypeMirror adapter, @Nullable TypeMirror builder, @Nullable TypeMirror configure, boolean generateAdapter) {
|
||||
public static SerializableClass of(TypeElement element, @Nullable TypeMirror with, @Nullable TypeMirror builder, @Nullable TypeMirror configure, boolean generateAdapter, boolean manifold) throws ElementException {
|
||||
ClassName className = ClassName.get(element);
|
||||
String pkg = manifold ? "gsoncompile.extensions." + className.packageName() + '.' + className.simpleNames().get(0) : className.packageName();
|
||||
ClassName generatedClassName = ClassName.get(pkg, "GC_" + className.simpleNames().get(0), className.simpleNames().subList(1, className.simpleNames().size()).toArray(String[]::new));
|
||||
String pkg = manifold ? "gsoncompile.extensions." + className.packageName + '.' + className.simpleNames[0] : className.packageName;
|
||||
ClassName generatedClassName = ClassName.get(pkg, "GC_" + className.simpleNames[0], className.simpleNames.subList(1, className.simpleNames.size()).toArray(String[]::new));
|
||||
return new SerializableClass(element, generatedClassName, voidToNull(with), voidToNull(builder), voidToNull(configure), generateAdapter).validate();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package io.gitlab.jfronny.gson.compile.processor;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public enum StringListComparator implements Comparator<List<String>> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public int compare(List<String> left, List<String> right) {
|
||||
int dif = left.size() - right.size();
|
||||
if (dif != 0) return dif;
|
||||
for (int i = 0; i < left.size(); i++) {
|
||||
dif = left.get(i).compareTo(right.get(i));
|
||||
if (dif != 0) return dif;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -10,11 +10,11 @@ public class TypeHelper {
|
|||
public static boolean isComplexType(TypeMirror type, Types typeUtils) {
|
||||
Element element = typeUtils.asElement(type);
|
||||
if (!(element instanceof TypeElement typeElement)) return false;
|
||||
return !typeElement.getTypeParameters().isEmpty();
|
||||
return !typeElement.typeParameters.isEmpty;
|
||||
}
|
||||
|
||||
public static boolean isGenericType(TypeMirror type) {
|
||||
return type.getKind() == TypeKind.TYPEVAR;
|
||||
return type.kind == TypeKind.TYPEVAR;
|
||||
}
|
||||
|
||||
public static List<? extends TypeMirror> getGenericTypes(TypeMirror type) {
|
||||
|
@ -23,8 +23,8 @@ public class TypeHelper {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
ArrayList<TypeMirror> result = new ArrayList<>();
|
||||
for (TypeMirror argType : declaredType.getTypeArguments()) {
|
||||
if (argType.getKind() == TypeKind.TYPEVAR) {
|
||||
for (TypeMirror argType : declaredType.typeArguments) {
|
||||
if (argType.kind == TypeKind.TYPEVAR) {
|
||||
result.add(argType);
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +52,10 @@ public class TypeHelper {
|
|||
public static boolean isInstance(DeclaredType type, String parentClassName, Types typeUtils) {
|
||||
if (type == null) return false;
|
||||
TypeElement element = (TypeElement) type.asElement();
|
||||
for (TypeMirror interfaceType : element.getInterfaces()) {
|
||||
for (TypeMirror interfaceType : element.interfaces) {
|
||||
if (typeUtils.erasure(interfaceType).toString().equals(parentClassName)) return true;
|
||||
}
|
||||
TypeMirror superclassType = element.getSuperclass();
|
||||
TypeMirror superclassType = element.superclass;
|
||||
if (superclassType != null) {
|
||||
if (typeUtils.erasure(superclassType).toString().equals(parentClassName)) {
|
||||
return true;
|
||||
|
@ -67,7 +67,7 @@ public class TypeHelper {
|
|||
}
|
||||
|
||||
static String getDefaultValue(TypeMirror type) {
|
||||
return switch (type.getKind()) {
|
||||
return switch (type.kind) {
|
||||
case BYTE, SHORT, INT, LONG, FLOAT, CHAR, DOUBLE -> "0";
|
||||
case BOOLEAN -> "false";
|
||||
default -> "null";
|
||||
|
|
|
@ -38,7 +38,7 @@ public abstract class AdapterAdapter<T extends AdapterAdapter<T>.Hydrated> exten
|
|||
if (TypeHelper.isComplexType(type, typeUtils)) {
|
||||
TypeName typeTokenType = ParameterizedTypeName.get(Cl.TYPE_TOKEN, typeName);
|
||||
List<? extends TypeMirror> typeParams = TypeHelper.getGenericTypes(type);
|
||||
if (typeParams.isEmpty()) {
|
||||
if (typeParams.isEmpty) {
|
||||
code.add("new $T() {}", typeTokenType);
|
||||
} else {
|
||||
code.add("($T) $T.getParameterized($T.class, ", typeTokenType, Cl.TYPE_TOKEN, typeUtils.erasure(type));
|
||||
|
|
|
@ -37,7 +37,7 @@ public class Adapters {
|
|||
}
|
||||
|
||||
private static void withAdapter(Property<?> prop, TypeSpec.Builder klazz, CodeBlock.Builder code, List<TypeVariableName> typeVariables, Set<SerializableClass> otherAdapters, Messager message, Consumer<Adapter<?>.Hydrated> action) {
|
||||
withAdapter(klazz, code, typeVariables, otherAdapters, prop.getType(), prop.getName(), prop.getAnnotations(), prop.getElement(), message, action);
|
||||
withAdapter(klazz, code, typeVariables, otherAdapters, prop.type, prop.name, prop.annotations, prop.element, message, action);
|
||||
}
|
||||
|
||||
public static void generateRead(TypeSpec.Builder klazz, CodeBlock.Builder code, List<TypeVariableName> typeVariables, Set<SerializableClass> other, TypeMirror type, String propName, List<? extends AnnotationMirror> annotations, Element sourceElement, Messager message) {
|
||||
|
|
|
@ -30,7 +30,7 @@ public class ArrayAdapter extends Adapter<ArrayAdapter.Hydrated> {
|
|||
@Override
|
||||
protected void afterHydrate() {
|
||||
type = TypeHelper.asArrayType(super.type);
|
||||
componentType = type == null ? null : type.getComponentType();
|
||||
componentType = type == null ? null : type.componentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +41,7 @@ public class ArrayAdapter extends Adapter<ArrayAdapter.Hydrated> {
|
|||
.beginControlFlow("if ($N == null)", argName)
|
||||
.addStatement("if (writer.getSerializeNulls()) writer.nullValue()")
|
||||
.nextControlFlow("else");
|
||||
generateWrite(code, componentType, argName, componentType.getAnnotationMirrors(), () -> code.add(argName));
|
||||
generateWrite(code, componentType, argName, componentType.annotationMirrors, () -> code.add(argName));
|
||||
code.endControlFlow().endControlFlow();
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class ArrayAdapter extends Adapter<ArrayAdapter.Hydrated> {
|
|||
// Coerce
|
||||
kode.beginControlFlow("if (reader.isLenient() && reader.peek() != $T.BEGIN_ARRAY)", Cl.GSON_TOKEN)
|
||||
.add("return new $T[] { ", componentType);
|
||||
generateRead(kode, componentType, argName, componentType.getAnnotationMirrors());
|
||||
generateRead(kode, componentType, argName, componentType.annotationMirrors);
|
||||
kode.add(" };\n").endControlFlow();
|
||||
|
||||
kode.addStatement("$T<$T> list = new $T<>()", List.class, componentType, ArrayList.class)
|
||||
|
@ -62,7 +62,7 @@ public class ArrayAdapter extends Adapter<ArrayAdapter.Hydrated> {
|
|||
.addStatement("list.add(null)")
|
||||
.nextControlFlow("else")
|
||||
.add("list.add(");
|
||||
generateRead(kode, componentType, argName, componentType.getAnnotationMirrors());
|
||||
generateRead(kode, componentType, argName, componentType.annotationMirrors);
|
||||
kode.add(");\n")
|
||||
.endControlFlow()
|
||||
.endControlFlow()
|
||||
|
|
|
@ -40,15 +40,15 @@ public class CollectionAdapter extends Adapter<CollectionAdapter.Hydrated> {
|
|||
type = TypeHelper.asDeclaredType(super.type);
|
||||
componentType = null;
|
||||
if (type == null) return;
|
||||
List<? extends TypeMirror> typeArguments = type.getTypeArguments();
|
||||
List<? extends TypeMirror> typeArguments = type.typeArguments;
|
||||
if (typeArguments.size() == 0) {
|
||||
type = null;
|
||||
} else {
|
||||
componentType = typeArguments.get(0);
|
||||
String ts = TypeHelper.asDeclaredType(typeUtils.erasure(type)).asElement().toString();
|
||||
for (Map.Entry<Class<?>, List<Class<?>>> entry : SUPPORTED.entrySet()) {
|
||||
if (entry.getKey().getCanonicalName().equals(ts)) {
|
||||
implType = TypeName.get(entry.getValue().get(0));
|
||||
if (entry.key.getCanonicalName().equals(ts)) {
|
||||
implType = TypeName.get(entry.value[0]);
|
||||
return;
|
||||
}
|
||||
for (Class<?> klazz : entry.getValue()) {
|
||||
|
@ -72,7 +72,7 @@ public class CollectionAdapter extends Adapter<CollectionAdapter.Hydrated> {
|
|||
.beginControlFlow("if ($N == null)", argName)
|
||||
.addStatement("if (writer.getSerializeNulls()) writer.nullValue()")
|
||||
.nextControlFlow("else");
|
||||
generateWrite(code, componentType, argName, componentType.getAnnotationMirrors(), () -> code.add(argName));
|
||||
generateWrite(code, componentType, argName, componentType.annotationMirrors, () -> code.add(argName));
|
||||
code.endControlFlow().endControlFlow().addStatement("writer.endArray()");
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class CollectionAdapter extends Adapter<CollectionAdapter.Hydrated> {
|
|||
// Coerce
|
||||
kode.beginControlFlow("if (reader.isLenient() && reader.peek() != $T.BEGIN_ARRAY)", Cl.GSON_TOKEN)
|
||||
.add("list.add(");
|
||||
generateRead(kode, componentType, argName, componentType.getAnnotationMirrors());
|
||||
generateRead(kode, componentType, argName, componentType.annotationMirrors);
|
||||
kode.add(");\n").addStatement("return list").endControlFlow();
|
||||
|
||||
kode.addStatement("reader.beginArray()")
|
||||
|
@ -93,7 +93,7 @@ public class CollectionAdapter extends Adapter<CollectionAdapter.Hydrated> {
|
|||
.addStatement("list.add(null)")
|
||||
.nextControlFlow("else")
|
||||
.add("list.add(");
|
||||
generateRead(kode, componentType, argName, componentType.getAnnotationMirrors());
|
||||
generateRead(kode, componentType, argName, componentType.annotationMirrors);
|
||||
kode.add(");\n")
|
||||
.endControlFlow()
|
||||
.endControlFlow()
|
||||
|
|
|
@ -57,10 +57,10 @@ public class DeclaredAdapter extends AdapterAdapter<DeclaredAdapter.Hydrated> {
|
|||
|
||||
private static DeclaredType findTypeAdapterClass(List<? extends AnnotationMirror> annotations) {
|
||||
for (AnnotationMirror annotation : annotations) {
|
||||
String typeName = annotation.getAnnotationType().toString();
|
||||
String typeName = annotation.annotationType.toString();
|
||||
if (typeName.equals(Cl.JSON_ADAPTER.toString())) {
|
||||
Map<? extends ExecutableElement, ? extends AnnotationValue> elements = annotation.getElementValues();
|
||||
if (!elements.isEmpty()) {
|
||||
Map<? extends ExecutableElement, ? extends AnnotationValue> elements = annotation.elementValues;
|
||||
if (!elements.isEmpty) {
|
||||
AnnotationValue value = elements.values().iterator().next();
|
||||
return (DeclaredType) value.getValue();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class EnumAdapter extends Adapter<EnumAdapter.Hydrated> {
|
|||
tel = null;
|
||||
DeclaredType declared = TypeHelper.asDeclaredType(type);
|
||||
if (declared == null) return;
|
||||
if (declared.asElement().getKind() != ElementKind.ENUM) return;
|
||||
if (declared.asElement().kind != ElementKind.ENUM) return;
|
||||
tel = declared;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,20 +37,20 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
type = TypeHelper.asDeclaredType(super.type);
|
||||
componentType1 = componentType2 = null;
|
||||
if (type == null) return;
|
||||
List<? extends TypeMirror> typeArguments = type.getTypeArguments();
|
||||
List<? extends TypeMirror> typeArguments = type.typeArguments;
|
||||
if (typeArguments.size() != 2) {
|
||||
type = null;
|
||||
} else {
|
||||
componentType1 = typeArguments.get(0);
|
||||
componentType1 = typeArguments[0];
|
||||
if (!isValidKey(componentType1)) {
|
||||
type = null;
|
||||
componentType1 = null;
|
||||
return;
|
||||
}
|
||||
componentType2 = typeArguments.get(1);
|
||||
componentType2 = typeArguments[1];
|
||||
String ts = TypeHelper.asDeclaredType(typeUtils.erasure(type)).asElement().toString();
|
||||
if (Map.class.getCanonicalName().equals(ts)) {
|
||||
implType = TypeName.get(SUPPORTED.get(0));
|
||||
implType = TypeName.get(SUPPORTED[0]);
|
||||
return;
|
||||
}
|
||||
for (Class<?> klazz : SUPPORTED) {
|
||||
|
@ -67,7 +67,7 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
private boolean isValidKey(TypeMirror tm) {
|
||||
if (tm.toString().equals(String.class.getCanonicalName())) return true;
|
||||
if (tm.toString().equals(UUID.class.getCanonicalName())) return true;
|
||||
if (unbox(tm).getKind().isPrimitive()) return true;
|
||||
if (unbox(tm).kind.isPrimitive) return true;
|
||||
if (isEnum(tm)) return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -79,8 +79,8 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
else if (componentType1.toString().equals(UUID.class.getCanonicalName())) {
|
||||
kode.add("name == null ? null : $T.fromString(name)", UUID.class);
|
||||
}
|
||||
else if (unbox(componentType1).getKind().isPrimitive()) {
|
||||
kode.add("name == null ? null : " + switch (unbox(componentType1).getKind()) {
|
||||
else if (unbox(componentType1).kind.isPrimitive) {
|
||||
kode.add("name == null ? null : " + switch (unbox(componentType1).kind) {
|
||||
case BOOLEAN -> "Boolean.parseBoolean(name)";
|
||||
case BYTE -> "Byte.parseByte(name)";
|
||||
case SHORT -> "Short.parseShort(name)";
|
||||
|
@ -89,7 +89,7 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
case CHAR -> "name.length() == 0 ? '\\0' : name.charAt(0)";
|
||||
case FLOAT -> "Float.parseFloat(name)";
|
||||
case DOUBLE -> "Double.parseDouble(name)";
|
||||
default -> throw new IllegalArgumentException("Unsupported primitive: " + unbox(componentType1).getKind());
|
||||
default -> throw new IllegalArgumentException("Unsupported primitive: " + unbox(componentType1).kind);
|
||||
});
|
||||
}
|
||||
else if (isEnum(componentType1)) {
|
||||
|
@ -124,7 +124,7 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
|
||||
private boolean isEnum(TypeMirror tm) {
|
||||
DeclaredType declared = TypeHelper.asDeclaredType(tm);
|
||||
return declared != null && declared.asElement().getKind() == ElementKind.ENUM;
|
||||
return declared != null && declared.asElement().kind == ElementKind.ENUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -145,7 +145,7 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
.beginControlFlow("if (value$N == null)", argName)
|
||||
.addStatement("if (writer.getSerializeNulls()) writer.nullValue()")
|
||||
.nextControlFlow("else");
|
||||
generateWrite(code, componentType2, "value" + argName, componentType2.getAnnotationMirrors(), () -> code.add("value" + argName));
|
||||
generateWrite(code, componentType2, "value" + argName, componentType2.annotationMirrors, () -> code.add("value" + argName));
|
||||
code.endControlFlow().endControlFlow().endControlFlow().addStatement("writer.endObject()");
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ public class MapAdapter extends Adapter<MapAdapter.Hydrated> {
|
|||
.add("map.put(");
|
||||
generateConvertKey(kode);
|
||||
kode.add(", ");
|
||||
generateRead(kode, componentType2, argName, componentType2.getAnnotationMirrors());
|
||||
generateRead(kode, componentType2, argName, componentType2.annotationMirrors);
|
||||
kode.addStatement(")")
|
||||
.endControlFlow()
|
||||
.endControlFlow()
|
||||
|
|
|
@ -26,9 +26,9 @@ public class OtherSerializableAdapter extends AdapterAdapter<OtherSerializableAd
|
|||
@Override
|
||||
protected void afterHydrate() {
|
||||
for (SerializableClass adapter : other) {
|
||||
if (TypeName.get(adapter.classElement().asType()).equals(typeName)) {
|
||||
if (TypeName.get(adapter.classElement.asType()).equals(typeName)) {
|
||||
// Use self-made adapter
|
||||
this.adapter = adapter.generatedClassName().toString();
|
||||
this.adapter = adapter.generatedClassName.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public class PrimitiveAdapter extends Adapter<PrimitiveAdapter.Hydrated> {
|
|||
public class Hydrated extends Adapter<Hydrated>.Hydrated {
|
||||
@Override
|
||||
public boolean applies() {
|
||||
return unboxedType.getKind().isPrimitive();
|
||||
return unboxedType.kind.isPrimitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,7 +23,7 @@ public class PrimitiveAdapter extends Adapter<PrimitiveAdapter.Hydrated> {
|
|||
|
||||
@Override
|
||||
public void generateRead() {
|
||||
code.add(switch (unboxedType.getKind()) {
|
||||
code.add(switch (unboxedType.kind) {
|
||||
case BOOLEAN -> "reader.nextBoolean()";
|
||||
case BYTE -> "(byte) reader.nextInt()";
|
||||
case SHORT -> "(short) reader.nextInt()";
|
||||
|
@ -32,7 +32,7 @@ public class PrimitiveAdapter extends Adapter<PrimitiveAdapter.Hydrated> {
|
|||
case CHAR -> "(char) reader.nextInt()";
|
||||
case FLOAT -> "(float) reader.nextDouble()";
|
||||
case DOUBLE -> "reader.nextDouble()";
|
||||
default -> throw new IllegalArgumentException("Unsupported primitive: " + unboxedType.getKind());
|
||||
default -> throw new IllegalArgumentException("Unsupported primitive: " + unboxedType.kind);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@Override
|
||||
public TypeElement getTargetClass() {
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) constructor.getEnclosingElement());
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) constructor.enclosingElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,7 +72,7 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@Override
|
||||
public TypeElement getTargetClass() {
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) types.asElement(method.getReturnType()));
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) types.asElement(method.returnType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,7 +115,7 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@Override
|
||||
public TypeElement getTargetClass() {
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) types.asElement(getBuildMethod().getReturnType()));
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) types.asElement(getBuildMethod().returnType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -130,12 +130,12 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@Override
|
||||
public TypeElement getBuilderClass() {
|
||||
return builderClass != null ? builderClass : (builderClass = (TypeElement) constructor.getEnclosingElement());
|
||||
return builderClass != null ? builderClass : (builderClass = (TypeElement) constructor.enclosingElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableElement getBuildMethod() {
|
||||
return buildMethod != null ? buildMethod : (buildMethod = findBuildMethod((TypeElement) constructor.getEnclosingElement()));
|
||||
return buildMethod != null ? buildMethod : (buildMethod = findBuildMethod((TypeElement) constructor.enclosingElement));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@Override
|
||||
public TypeElement getTargetClass() {
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) types.asElement(getBuildMethod().getReturnType()));
|
||||
return targetClass != null ? targetClass : (targetClass = (TypeElement) types.asElement(getBuildMethod().returnType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -168,12 +168,12 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@Override
|
||||
public TypeElement getBuilderClass() {
|
||||
return builderClass != null ? builderClass : (builderClass = (TypeElement) types.asElement(method.getReturnType()));
|
||||
return builderClass != null ? builderClass : (builderClass = (TypeElement) types.asElement(method.returnType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableElement getBuildMethod() {
|
||||
return buildMethod != null ? buildMethod : (buildMethod = findBuildMethod((TypeElement) types.asElement(method.getReturnType())));
|
||||
return buildMethod != null ? buildMethod : (buildMethod = findBuildMethod((TypeElement) types.asElement(method.returnType)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ public sealed interface ConstructionSource {
|
|||
ExecutableElement candidate = null;
|
||||
boolean foundMultipleCandidates = false;
|
||||
boolean isCandidateReasonableBuilderMethodName = false;
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(builderClass.getEnclosedElements())) {
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(builderClass.enclosedElements)) {
|
||||
if (isPossibleBuilderMethod(method, builderClass)) {
|
||||
if (candidate == null) {
|
||||
candidate = method;
|
||||
|
@ -210,10 +210,10 @@ public sealed interface ConstructionSource {
|
|||
}
|
||||
// Last try, check to see if the immediate parent class makes sense.
|
||||
{
|
||||
Element candidate = builderClass.getEnclosingElement();
|
||||
if (candidate.getKind() == ElementKind.CLASS) {
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(builderClass.getEnclosedElements())) {
|
||||
if (method.getReturnType().equals(candidate.asType()) && method.getParameters().isEmpty()) {
|
||||
Element candidate = builderClass.enclosingElement;
|
||||
if (candidate.kind == ElementKind.CLASS) {
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(builderClass.enclosedElements)) {
|
||||
if (method.returnType.equals(candidate.asType()) && method.parameters.isEmpty) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
@ -230,10 +230,10 @@ public sealed interface ConstructionSource {
|
|||
*/
|
||||
@ApiStatus.Internal
|
||||
static boolean isPossibleBuilderMethod(ExecutableElement method, TypeElement builderClass) {
|
||||
if (!method.getParameters().isEmpty()) return false;
|
||||
TypeMirror returnType = method.getReturnType();
|
||||
if (returnType.getKind() == TypeKind.VOID) return false;
|
||||
if (returnType.getKind().isPrimitive()) return false;
|
||||
if (!method.parameters.isEmpty) return false;
|
||||
TypeMirror returnType = method.returnType;
|
||||
if (returnType.kind == TypeKind.VOID) return false;
|
||||
if (returnType.kind.isPrimitive) return false;
|
||||
if (returnType.equals(builderClass.asType())) return false;
|
||||
String returnTypeName = returnType.toString();
|
||||
return !(returnTypeName.startsWith("java.") || returnTypeName.startsWith("javax.") || returnTypeName.startsWith("android."));
|
||||
|
@ -241,7 +241,7 @@ public sealed interface ConstructionSource {
|
|||
|
||||
@ApiStatus.Internal
|
||||
static boolean isReasonableBuilderMethodName(ExecutableElement method) {
|
||||
String methodName = method.getSimpleName().toString().toLowerCase(Locale.ROOT);
|
||||
String methodName = method.simpleName.toString().toLowerCase(Locale.ROOT);
|
||||
return methodName.startsWith("build") || methodName.startsWith("create");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,5 +25,5 @@ public class ElementException extends Exception {
|
|||
}
|
||||
}
|
||||
|
||||
public static record Message(String message, Element element) {}
|
||||
public record Message(String message, Element element) {}
|
||||
}
|
||||
|
|
|
@ -21,18 +21,18 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
public static Properties build(Types types, ConstructionSource constructionSource) throws ElementException {
|
||||
Builder builder = new Builder(types);
|
||||
// constructor params
|
||||
for (VariableElement param : constructionSource.getConstructionElement().getParameters()) {
|
||||
for (VariableElement param : constructionSource.constructionElement.parameters) {
|
||||
builder.addConstructorParam(param);
|
||||
}
|
||||
|
||||
if (constructionSource instanceof ConstructionSource.Builder csb) {
|
||||
var builderClass = csb.getBuilderClass();
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(builderClass.getEnclosedElements())) {
|
||||
var builderClass = csb.builderClass;
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(builderClass.enclosedElements)) {
|
||||
builder.addBuilderParam(method);
|
||||
}
|
||||
}
|
||||
|
||||
var targetClass = constructionSource.getTargetClass();
|
||||
var targetClass = constructionSource.targetClass;
|
||||
builder.addFieldsAndAccessors(targetClass);
|
||||
|
||||
return builder.build();
|
||||
|
@ -90,32 +90,32 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
|
||||
public void addFieldsAndAccessors(TypeElement targetClass) {
|
||||
// accessors
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(targetClass.getEnclosedElements())) {
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(targetClass.enclosedElements)) {
|
||||
addGetter(targetClass, method);
|
||||
addSetter(targetClass, method);
|
||||
}
|
||||
|
||||
// fields
|
||||
for (VariableElement field : ElementFilter.fieldsIn(targetClass.getEnclosedElements())) {
|
||||
for (VariableElement field : ElementFilter.fieldsIn(targetClass.enclosedElements)) {
|
||||
addField(field);
|
||||
}
|
||||
|
||||
for (TypeMirror superInterface : targetClass.getInterfaces()) {
|
||||
for (TypeMirror superInterface : targetClass.interfaces) {
|
||||
addFieldsAndAccessors((TypeElement) types.asElement(superInterface));
|
||||
}
|
||||
|
||||
TypeMirror superclass = targetClass.getSuperclass();
|
||||
if (superclass.getKind() != TypeKind.NONE && !superclass.toString().equals("java.lang.Object")) {
|
||||
TypeMirror superclass = targetClass.superclass;
|
||||
if (superclass.kind != TypeKind.NONE && !superclass.toString().equals("java.lang.Object")) {
|
||||
addFieldsAndAccessors((TypeElement) types.asElement(superclass));
|
||||
}
|
||||
}
|
||||
|
||||
public void addGetter(TypeElement classElement, ExecutableElement method) {
|
||||
Set<Modifier> modifiers = method.getModifiers();
|
||||
Set<Modifier> modifiers = method.modifiers;
|
||||
if (modifiers.contains(Modifier.PRIVATE)
|
||||
|| modifiers.contains(Modifier.STATIC)
|
||||
|| method.getReturnType().getKind() == TypeKind.VOID
|
||||
|| !method.getParameters().isEmpty()
|
||||
|| method.returnType.kind == TypeKind.VOID
|
||||
|| !method.parameters.isEmpty
|
||||
|| isMethodToSkip(classElement, method)) {
|
||||
return;
|
||||
}
|
||||
|
@ -123,20 +123,20 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
}
|
||||
|
||||
public void addSetter(TypeElement classElement, ExecutableElement method) {
|
||||
Set<Modifier> modifiers = method.getModifiers();
|
||||
Set<Modifier> modifiers = method.modifiers;
|
||||
if (modifiers.contains(Modifier.PRIVATE)
|
||||
|| modifiers.contains(Modifier.STATIC)
|
||||
|| method.getReturnType().getKind() != TypeKind.VOID
|
||||
|| method.getParameters().size() != 1
|
||||
|| method.returnType.kind != TypeKind.VOID
|
||||
|| method.parameters.size() != 1
|
||||
|| isMethodToSkip(classElement, method)
|
||||
|| !method.getSimpleName().toString().startsWith("set")) {
|
||||
|| !method.simpleName.toString().startsWith("set")) {
|
||||
return;
|
||||
}
|
||||
setters.add(new Property.Setter(method));
|
||||
}
|
||||
|
||||
public void addField(VariableElement field) {
|
||||
Set<Modifier> modifiers = field.getModifiers();
|
||||
Set<Modifier> modifiers = field.modifiers;
|
||||
if (modifiers.contains(Modifier.STATIC)) return;
|
||||
fields.add(new Property.Field(field));
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
}
|
||||
|
||||
public void addBuilderParam(ExecutableElement method) {
|
||||
if (method.getParameters().size() == 1 && method.getSimpleName().toString().startsWith("set")) {
|
||||
if (method.getParameters().size() == 1 && method.simpleName.toString().startsWith("set")) {
|
||||
Property.Setter prop = new Property.Setter(method);
|
||||
builderParams.add(prop);
|
||||
params.add(prop);
|
||||
|
@ -194,7 +194,7 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
|
||||
private void removeExtraFields() {
|
||||
fields.removeIf(field -> {
|
||||
Set<Modifier> modifiers = field.element.getModifiers();
|
||||
Set<Modifier> modifiers = field.element.modifiers;
|
||||
return modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.TRANSIENT);
|
||||
});
|
||||
}
|
||||
|
@ -202,19 +202,19 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
private void removeGettersForTransientFields() {
|
||||
getters.removeIf(getter -> {
|
||||
Property<?> field = findName(fields, getter);
|
||||
return field != null && field.element.getModifiers().contains(Modifier.TRANSIENT);
|
||||
return field != null && field.element.modifiers.contains(Modifier.TRANSIENT);
|
||||
});
|
||||
}
|
||||
|
||||
private void removeSettersForTransientFields() {
|
||||
getters.removeIf(getter -> {
|
||||
Property<?> field = findName(fields, getter);
|
||||
return field != null && field.element.getModifiers().contains(Modifier.TRANSIENT);
|
||||
return field != null && field.element.modifiers.contains(Modifier.TRANSIENT);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isMethodToSkip(TypeElement classElement, ExecutableElement method) {
|
||||
String name = method.getSimpleName().toString();
|
||||
String name = method.simpleName.toString();
|
||||
if (METHODS_TO_SKIP.contains(name)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -227,10 +227,10 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
List<AnnotationMirror> annotations = null;
|
||||
for (Property<?> name : properties) {
|
||||
if (name == null) continue;
|
||||
if (!name.getAnnotations().isEmpty()) {
|
||||
if (annotations == null) annotations = new ArrayList<>(name.getAnnotations());
|
||||
if (!name.annotations.isEmpty) {
|
||||
if (annotations == null) annotations = new ArrayList<>(name.annotations);
|
||||
else {
|
||||
for (AnnotationMirror annotation : name.getAnnotations()) {
|
||||
for (AnnotationMirror annotation : name.annotations) {
|
||||
if (annotations.contains(annotation)) {
|
||||
throw new ElementException("Duplicate annotation " + annotation + " found on " + name, name.element);
|
||||
} else annotations.add(annotation);
|
||||
|
@ -260,7 +260,7 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
}
|
||||
|
||||
public static <N extends Property<?>> N findName(List<N> names, Property<?> property) {
|
||||
return names.stream().filter(n -> n.getName().equals(property.getName())).findFirst().orElse(null);
|
||||
return names.stream().filter(n -> n.name.equals(property.name)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static boolean containsName(List<? extends Property<?>> properties, Property<?> property) {
|
||||
|
@ -268,6 +268,6 @@ public class Properties extends DelegateList<Property<?>> {
|
|||
}
|
||||
|
||||
private static boolean isKotlinClass(TypeElement element) {
|
||||
return element.getAnnotationMirrors().stream().anyMatch(m -> m.getAnnotationType().toString().equals("kotlin.Metadata"));
|
||||
return element.annotationMirrors.stream().anyMatch(m -> m.annotationType.toString().equals("kotlin.Metadata"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public abstract sealed class Property<T extends Element> {
|
|||
|
||||
public Property(T element) {
|
||||
this.element = element;
|
||||
this.annotations = element.getAnnotationMirrors();
|
||||
this.annotations = element.annotationMirrors;
|
||||
}
|
||||
|
||||
public T getElement() {
|
||||
|
@ -26,7 +26,7 @@ public abstract sealed class Property<T extends Element> {
|
|||
* @see #getCallableName()
|
||||
*/
|
||||
public String getName() {
|
||||
return element.getSimpleName().toString();
|
||||
return element.simpleName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,7 +113,7 @@ public abstract sealed class Property<T extends Element> {
|
|||
|
||||
@Override
|
||||
public TypeMirror getType() {
|
||||
return element.getReturnType();
|
||||
return element.returnType;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
@ -123,7 +123,7 @@ public abstract sealed class Property<T extends Element> {
|
|||
|
||||
private String getBeanPrefix() {
|
||||
String name = super.getName();
|
||||
if (element.getReturnType().getKind() == TypeKind.BOOLEAN) {
|
||||
if (element.returnType.kind == TypeKind.BOOLEAN) {
|
||||
if (name.length() > BEAN_PREFIX_BOOL.length() && name.startsWith(BEAN_PREFIX_BOOL)) {
|
||||
return BEAN_PREFIX_BOOL;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ public abstract sealed class Property<T extends Element> {
|
|||
public Setter(ExecutableElement method) {
|
||||
super(method.getParameters().get(0));
|
||||
this.method = method;
|
||||
name = Character.toLowerCase(method.getSimpleName().toString().charAt(3)) + method.getSimpleName().toString().substring(4);
|
||||
name = Character.toLowerCase(method.simpleName.toString().charAt(3)) + method.simpleName.toString().substring(4);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -161,7 +161,7 @@ public abstract sealed class Property<T extends Element> {
|
|||
|
||||
@Override
|
||||
public String getCallableName() {
|
||||
return method.getSimpleName().toString();
|
||||
return method.simpleName.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ public class Value {
|
|||
public Value(ProcessingEnvironment env, ConstructionSource constructionSource) {
|
||||
this.env = env;
|
||||
this.constructionSource = constructionSource;
|
||||
this.element = constructionSource.getTargetClass();
|
||||
this.element = constructionSource.targetClass;
|
||||
}
|
||||
|
||||
public Properties getProperties() throws ElementException {
|
||||
return properties != null ? properties : (properties = Properties.build(env.getTypeUtils(), constructionSource));
|
||||
return properties != null ? properties : (properties = Properties.build(env.typeUtils, constructionSource));
|
||||
}
|
||||
|
||||
public ConstructionSource getConstructionSource() {
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ValueCreator {
|
|||
*/
|
||||
public Value fromBuilderConstructor(ExecutableElement constructor) {
|
||||
checkKind(constructor, ElementKind.CONSTRUCTOR);
|
||||
return create(new ConstructionSource.BuilderConstructor(env.getTypeUtils(), constructor));
|
||||
return create(new ConstructionSource.BuilderConstructor(env.typeUtils, constructor));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,7 @@ public class ValueCreator {
|
|||
*/
|
||||
public Value fromFactory(ExecutableElement factory) {
|
||||
checkKind(factory, ElementKind.METHOD);
|
||||
return create(new ConstructionSource.Factory(env.getTypeUtils(), factory));
|
||||
return create(new ConstructionSource.Factory(env.typeUtils, factory));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,7 +82,7 @@ public class ValueCreator {
|
|||
*/
|
||||
public Value fromBuilderFactory(ExecutableElement builderFactory) {
|
||||
checkKind(builderFactory, ElementKind.METHOD);
|
||||
return create(new ConstructionSource.BuilderFactory(env.getTypeUtils(), builderFactory));
|
||||
return create(new ConstructionSource.BuilderFactory(env.typeUtils, builderFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,27 +115,27 @@ public class ValueCreator {
|
|||
|
||||
private static ExecutableElement findConstructorOrFactory(TypeElement klazz) throws ElementException {
|
||||
ExecutableElement noArgConstructor = null;
|
||||
List<ExecutableElement> constructors = ElementFilter.constructorsIn(klazz.getEnclosedElements());
|
||||
List<ExecutableElement> constructors = ElementFilter.constructorsIn(klazz.enclosedElements);
|
||||
if (constructors.size() == 1) {
|
||||
ExecutableElement constructor = constructors.get(0);
|
||||
if (constructor.getParameters().isEmpty()) {
|
||||
ExecutableElement constructor = constructors[0];
|
||||
if (constructor.parameters.isEmpty) {
|
||||
noArgConstructor = constructor;
|
||||
constructors.remove(0);
|
||||
}
|
||||
}
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(klazz.getEnclosedElements())) {
|
||||
Set<Modifier> modifiers = method.getModifiers();
|
||||
for (ExecutableElement method : ElementFilter.methodsIn(klazz.enclosedElements)) {
|
||||
Set<Modifier> modifiers = method.modifiers;
|
||||
if (modifiers.contains(Modifier.STATIC)
|
||||
&& !modifiers.contains(Modifier.PRIVATE)
|
||||
&& method.getReturnType().equals(klazz.asType())) {
|
||||
&& method.returnType.equals(klazz.asType())) {
|
||||
constructors.add(method);
|
||||
}
|
||||
}
|
||||
if (constructors.isEmpty()) {
|
||||
if (constructors.isEmpty) {
|
||||
if (noArgConstructor != null) return noArgConstructor;
|
||||
else throw new ElementException("Lacking constructor or factory method", klazz);
|
||||
}
|
||||
if (constructors.size() == 1) return constructors.get(0);
|
||||
if (constructors.size() == 1) return constructors[0];
|
||||
if (noArgConstructor != null) constructors.add(noArgConstructor);
|
||||
List<ExecutableElement> preferred = new ArrayList<>();
|
||||
for (ExecutableElement constructor : constructors) {
|
||||
|
@ -143,7 +143,7 @@ public class ValueCreator {
|
|||
preferred.add(constructor);
|
||||
}
|
||||
}
|
||||
if (preferred.size() == 1) return preferred.get(0);
|
||||
if (preferred.size() == 1) return preferred[0];
|
||||
List<ElementException.Message> messages = new ArrayList<>();
|
||||
messages.add(new ElementException.Message("More than one constructor or factory method found.", klazz));
|
||||
constructors.stream().map(s -> new ElementException.Message(" " + s, s)).forEach(messages::add);
|
||||
|
@ -151,7 +151,7 @@ public class ValueCreator {
|
|||
}
|
||||
|
||||
private static void checkKind(Element element, ElementKind kind) {
|
||||
if (element.getKind() != kind) {
|
||||
if (element.kind != kind) {
|
||||
throw new IllegalArgumentException("Expected " + kind + " but got: " + element);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ pluginManagement {
|
|||
}
|
||||
plugins {
|
||||
id("jf.maven-publish") version "1.2-SNAPSHOT"
|
||||
id("jf.manifold") version "1.2-SNAPSHOT"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue