From d94ae7afb33b908e6601bde84ff6e08955c414af Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Fri, 13 Oct 2023 12:50:57 +0100 Subject: [PATCH] Switch format to nicely format multiline strings and consistent ordering --- build.gradle | 2 +- .../plugin/api/ApplyPatchesTask.java | 3 +- .../plugin/api/MakePatchesTask.java | 4 +- .../plugin/api/MissedPatchesTask.java | 4 +- .../docpatcher/plugin/impl/Data.java | 171 ++++++++++++++++++ .../docpatcher/plugin/impl/Utils.java | 53 ++---- 6 files changed, 190 insertions(+), 47 deletions(-) create mode 100644 src/main/java/dev/lukebemish/docpatcher/plugin/impl/Data.java diff --git a/build.gradle b/build.gradle index 172efc4..b2eb515 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'dev.lukebemish.docpatcher' -version = '0.2.6' +version = '0.3.0' java { // I don't feel like dealing with old java... diff --git a/src/main/java/dev/lukebemish/docpatcher/plugin/api/ApplyPatchesTask.java b/src/main/java/dev/lukebemish/docpatcher/plugin/api/ApplyPatchesTask.java index fae8f49..d27c59b 100644 --- a/src/main/java/dev/lukebemish/docpatcher/plugin/api/ApplyPatchesTask.java +++ b/src/main/java/dev/lukebemish/docpatcher/plugin/api/ApplyPatchesTask.java @@ -8,7 +8,6 @@ import net.neoforged.javadoctor.injector.JavadocProvider; import net.neoforged.javadoctor.injector.ast.JClassParser; import net.neoforged.javadoctor.injector.spoon.SpoonClassParser; -import net.neoforged.javadoctor.spec.ClassJavadoc; import org.gradle.api.DefaultTask; import org.gradle.api.Project; import org.gradle.api.file.ConfigurableFileCollection; @@ -129,7 +128,7 @@ private JavadocProvider createPatchInjector() { if (Files.exists(path)) { try { String contents = Files.readString(path); - return Utils.GSON.fromJson(contents, ClassJavadoc.class); + return Utils.fromJson(contents); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/dev/lukebemish/docpatcher/plugin/api/MakePatchesTask.java b/src/main/java/dev/lukebemish/docpatcher/plugin/api/MakePatchesTask.java index 1814d72..288d99b 100644 --- a/src/main/java/dev/lukebemish/docpatcher/plugin/api/MakePatchesTask.java +++ b/src/main/java/dev/lukebemish/docpatcher/plugin/api/MakePatchesTask.java @@ -1,6 +1,5 @@ package dev.lukebemish.docpatcher.plugin.api; -import com.google.gson.JsonElement; import dev.lukebemish.docpatcher.plugin.impl.SpoonJavadocVisitor; import dev.lukebemish.docpatcher.plugin.impl.Utils; import net.neoforged.javadoctor.spec.ClassJavadoc; @@ -94,8 +93,7 @@ public void generatePatches() { if (javadoc != null) { Path outputPath = getOutputDirectory().get().getAsFile().toPath().resolve(className + ".docpatcher.json"); Files.createDirectories(outputPath.getParent()); - JsonElement json = Utils.toJson(javadoc); - Files.writeString(outputPath, Utils.GSON.toJson(json)); + Files.writeString(outputPath, Utils.toJson(javadoc)); } } catch (IOException e) { throw new RuntimeException(e); diff --git a/src/main/java/dev/lukebemish/docpatcher/plugin/api/MissedPatchesTask.java b/src/main/java/dev/lukebemish/docpatcher/plugin/api/MissedPatchesTask.java index c0c738e..3690305 100644 --- a/src/main/java/dev/lukebemish/docpatcher/plugin/api/MissedPatchesTask.java +++ b/src/main/java/dev/lukebemish/docpatcher/plugin/api/MissedPatchesTask.java @@ -74,7 +74,7 @@ public void missedPatches() { if (remainder != null) { var output = getOutputDirectory().get().getAsFile().toPath().resolve(className+ ".docpatcher.json"); Files.createDirectories(output.getParent()); - Files.writeString(output, Utils.GSON.toJson(remainder)); + Files.writeString(output, Utils.toJson(remainder)); } } catch (IOException e) { throw new RuntimeException(e); @@ -90,7 +90,7 @@ private JavadocProvider makeProvider() { if (Files.exists(path)) { try { String contents = Files.readString(path); - return Utils.GSON.fromJson(contents, ClassJavadoc.class); + return Utils.fromJson(contents); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Data.java b/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Data.java new file mode 100644 index 0000000..1dacf88 --- /dev/null +++ b/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Data.java @@ -0,0 +1,171 @@ +package dev.lukebemish.docpatcher.plugin.impl; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import net.neoforged.javadoctor.spec.ClassJavadoc; +import net.neoforged.javadoctor.spec.JavadocEntry; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class Data { + private static JsonElement splitString(@Nullable String string) { + if (string == null) { + return new JsonPrimitive(""); + } + if (string.contains("\n")) { + JsonArray array = new JsonArray(); + for (String s : string.split("\n")) { + array.add(s); + } + return array; + } + return new JsonPrimitive(string); + } + + private static String processString(JsonElement element) { + if (element.isJsonArray()) { + StringBuilder builder = new StringBuilder(); + for (JsonElement e : element.getAsJsonArray()) { + builder.append(e.getAsString()).append("\n"); + } + return builder.substring(0, builder.length() - 1); + } + return element.getAsString(); + } + + public static JsonElement serialize(JavadocEntry entry) { + JsonObject object = new JsonObject(); + if (entry.doc() != null) { + object.add("doc", splitString(entry.doc())); + } + if (entry.tags() != null && !entry.tags().isEmpty()) { + JsonObject tags = new JsonObject(); + entry.tags().forEach((key, value) -> { + if (!value.isEmpty()) { + JsonArray values = new JsonArray(); + for (String v : value) { + values.add(splitString(v)); + } + tags.add(key, values); + } + }); + object.add("tags", tags); + } + if (entry.parameters() != null && entry.parameters().length != 0) { + JsonArray parameters = new JsonArray(); + for (String parameter : entry.parameters()) { + parameters.add(splitString(parameter)); + } + object.add("parameters", parameters); + } + if (entry.typeParameters() != null && entry.typeParameters().length != 0) { + JsonArray typeParameters = new JsonArray(); + for (String typeParameter : entry.typeParameters()) { + typeParameters.add(splitString(typeParameter)); + } + object.add("typeParameters", typeParameters); + } + return object; + } + + public static JavadocEntry deserializeJavadocEntry(JsonElement element) { + JsonObject object = element.getAsJsonObject(); + String doc; + JsonElement docElement = object.get("doc"); + if (docElement == null) { + doc = null; + } else { + doc = processString(docElement); + } + Map> tags = new HashMap<>(); + String[] parameters = null; + String[] typeParameters = null; + JsonObject tagsElement = object.getAsJsonObject("tags"); + if (tagsElement != null) { + tagsElement.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> { + JsonArray value = entry.getValue().getAsJsonArray(); + List values = new ArrayList<>(); + for (JsonElement e : value.getAsJsonArray()) { + values.add(processString(e)); + } + tags.put(entry.getKey(), values); + }); + } + JsonArray parametersElement = object.getAsJsonArray("parameters"); + if (parametersElement != null) { + parameters = new String[parametersElement.size()]; + for (int i = 0; i < parametersElement.size(); i++) { + parameters[i] = processString(parametersElement.get(i)); + } + } + JsonArray typeParametersElement = object.getAsJsonArray("typeParameters"); + if (typeParametersElement != null) { + typeParameters = new String[typeParametersElement.size()]; + for (int i = 0; i < typeParametersElement.size(); i++) { + typeParameters[i] = processString(typeParametersElement.get(i)); + } + } + return new JavadocEntry(doc, tags, parameters, typeParameters); + } + + public static JsonElement serialize(ClassJavadoc javadoc) { + JsonObject object = new JsonObject(); + if (javadoc.clazz() != null) { + object.add("clazz", serialize(javadoc.clazz())); + } + if (javadoc.methods() != null && !javadoc.methods().isEmpty()) { + JsonObject methods = new JsonObject(); + javadoc.methods().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> methods.add(entry.getKey(), serialize(entry.getValue()))); + object.add("methods", methods); + } + if (javadoc.fields() != null && !javadoc.fields().isEmpty()) { + JsonObject fields = new JsonObject(); + javadoc.fields().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> fields.add(entry.getKey(), serialize(entry.getValue()))); + object.add("fields", fields); + } + if (javadoc.innerClasses() != null && !javadoc.innerClasses().isEmpty()) { + JsonObject innerClasses = new JsonObject(); + javadoc.innerClasses().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> innerClasses.add(entry.getKey(), serialize(entry.getValue()))); + object.add("innerClasses", innerClasses); + } + return object; + } + + public static ClassJavadoc deserializeClassJavadoc(JsonElement node) { + JsonObject object = node.getAsJsonObject(); + var clazz = object.getAsJsonObject("clazz"); + var methods = object.getAsJsonObject("methods"); + var fields = object.getAsJsonObject("fields"); + var innerClasses = object.getAsJsonObject("innerClasses"); + Map methodsMap; + Map fieldsMap; + Map innerClassesMap; + if (methods != null) { + methodsMap = new HashMap<>(); + methods.entrySet().forEach(entry -> methodsMap.put(entry.getKey(), deserializeJavadocEntry(entry.getValue()))); + } else { + methodsMap = null; + } + if (fields != null) { + fieldsMap = new HashMap<>(); + fields.entrySet().forEach(entry -> fieldsMap.put(entry.getKey(), deserializeJavadocEntry(entry.getValue()))); + } else { + fieldsMap = null; + } + if (innerClasses != null) { + innerClassesMap = new HashMap<>(); + innerClasses.entrySet().forEach(entry -> innerClassesMap.put(entry.getKey(), deserializeClassJavadoc(entry.getValue()))); + } else { + innerClassesMap = null; + } + return new ClassJavadoc( + clazz != null ? deserializeJavadocEntry(clazz) : null, + methodsMap, + fieldsMap, + innerClassesMap + ); + } +} diff --git a/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Utils.java b/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Utils.java index 0d20fb4..5ab3b10 100644 --- a/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Utils.java +++ b/src/main/java/dev/lukebemish/docpatcher/plugin/impl/Utils.java @@ -3,15 +3,13 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import net.neoforged.javadoctor.io.gson.GsonJDocIO; import net.neoforged.javadoctor.spec.ClassJavadoc; -import net.neoforged.javadoctor.spec.JavadocEntry; import spoon.Launcher; import spoon.reflect.CtModel; import spoon.reflect.visitor.ForceFullyQualifiedProcessor; import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; @@ -20,13 +18,23 @@ public final class Utils { private Utils() {} - public static final Gson GSON = new GsonBuilder() + private static final Gson GSON = new GsonBuilder() .disableHtmlEscaping() - .registerTypeAdapter(ClassJavadoc.class, GsonJDocIO.JAVADOC_READER) - .registerTypeAdapter(JavadocEntry.class, GsonJDocIO.ENTRY_READER) .setPrettyPrinting() .create(); + public static String toJson(ClassJavadoc javadoc) { + return GSON.toJson(Data.serialize(javadoc)); + } + + public static ClassJavadoc fromJson(String json) throws IOException { + try { + return Data.deserializeClassJavadoc(GSON.fromJson(json, JsonElement.class)); + } catch (Exception e) { + throw new IOException(e); + } + } + public static Launcher makeLauncher(int javaVersion, ClassLoader classLoader) { final Launcher launcher = new Launcher(); launcher.getEnvironment().setCommentEnabled(true); @@ -54,37 +62,4 @@ public static CtModel buildModel(Launcher launcher) { launcher.process(); return launcher.getModel(); } - - public static JsonElement toJson(ClassJavadoc classJavadoc) { - JsonObject json = new JsonObject(); - if (classJavadoc.clazz() != null) { - json.add("clazz", toJson(classJavadoc.clazz())); - } - if (classJavadoc.innerClasses() != null && !classJavadoc.innerClasses().isEmpty()) { - JsonObject innerClasses = new JsonObject(); - for (var entry : classJavadoc.innerClasses().entrySet()) { - innerClasses.add(entry.getKey(), toJson(entry.getValue())); - } - json.add("innerClasses", innerClasses); - } - if (classJavadoc.methods() != null && !classJavadoc.methods().isEmpty()) { - JsonObject methods = new JsonObject(); - for (var entry : classJavadoc.methods().entrySet()) { - methods.add(entry.getKey(), toJson(entry.getValue())); - } - json.add("methods", methods); - } - if (classJavadoc.fields() != null && !classJavadoc.fields().isEmpty()) { - JsonObject fields = new JsonObject(); - for (var entry : classJavadoc.fields().entrySet()) { - fields.add(entry.getKey(), toJson(entry.getValue())); - } - json.add("fields", fields); - } - return json; - } - - public static JsonElement toJson(JavadocEntry javadocEntry) { - return GsonJDocIO.GSON.toJsonTree(javadocEntry); - } }