From c83e00e7022425e82027c7212383281c5658c37b Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Sun, 11 Jun 2023 18:52:30 +0200 Subject: [PATCH] Add TypeAdapterFactory for Optional --- .../lib/bazel/bzlmod/GsonTypeAdapterUtil.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/GsonTypeAdapterUtil.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/GsonTypeAdapterUtil.java index b1b047ba4d4a8b..f6d8d542f4decf 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/GsonTypeAdapterUtil.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/GsonTypeAdapterUtil.java @@ -26,11 +26,17 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import com.ryanharter.auto.value.gson.GenerateTypeAdapter; import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.List; +import java.util.Optional; /** * Utility class to hold type adapters and helper methods to get gson registered with type adapters @@ -88,6 +94,53 @@ public ModuleKey read(JsonReader jsonReader) throws IOException { } }; + public static final TypeAdapterFactory OPTIONAL = + new TypeAdapterFactory() { + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (typeToken.getRawType() != Optional.class) { + return null; + } + Type type = typeToken.getType(); + if (!(type instanceof ParameterizedType)) { + return null; + } + Type elementType = ((ParameterizedType) typeToken.getType()).getActualTypeArguments()[0]; + var elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); + if (elementTypeAdapter == null) { + return null; + } + return (TypeAdapter) new OptionalTypeAdapter<>(elementTypeAdapter); + } + }; + + private static final class OptionalTypeAdapter extends TypeAdapter> { + private final TypeAdapter elementTypeAdapter; + + public OptionalTypeAdapter(TypeAdapter elementTypeAdapter) { + this.elementTypeAdapter = elementTypeAdapter; + } + + @Override + public void write(JsonWriter jsonWriter, Optional t) throws IOException { + if (t == null || t.isEmpty()) { + jsonWriter.nullValue(); + } else { + elementTypeAdapter.write(jsonWriter, t.get()); + } + } + + @Override + public Optional read(JsonReader jsonReader) throws IOException { + if (jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + return Optional.empty(); + } else { + return Optional.of(elementTypeAdapter.read(jsonReader)); + } + } + } + public static final Gson LOCKFILE_GSON = new GsonBuilder() .setPrettyPrinting() @@ -98,6 +151,7 @@ public ModuleKey read(JsonReader jsonReader) throws IOException { .registerTypeAdapterFactory(IMMUTABLE_LIST) .registerTypeAdapterFactory(IMMUTABLE_BIMAP) .registerTypeAdapterFactory(IMMUTABLE_SET) + .registerTypeAdapterFactory(OPTIONAL) .registerTypeAdapter(Version.class, VERSION_TYPE_ADAPTER) .registerTypeAdapter(ModuleKey.class, MODULE_KEY_TYPE_ADAPTER) .registerTypeAdapter(AttributeValues.class, new AttributeValuesAdapter())