|
20 | 20 | import static com.google.devtools.build.lib.bazel.bzlmod.DelegateTypeAdapterFactory.IMMUTABLE_MAP;
|
21 | 21 | import static com.google.devtools.build.lib.bazel.bzlmod.DelegateTypeAdapterFactory.IMMUTABLE_SET;
|
22 | 22 |
|
| 23 | +import com.google.auto.value.AutoValue; |
23 | 24 | import com.google.common.base.Preconditions;
|
24 | 25 | import com.google.common.base.Splitter;
|
25 | 26 | import com.google.devtools.build.lib.bazel.bzlmod.Version.ParseException;
|
26 | 27 | import com.google.devtools.build.lib.cmdline.Label;
|
27 | 28 | import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
|
| 29 | +import com.google.devtools.build.lib.vfs.Path; |
28 | 30 | import com.google.gson.Gson;
|
29 | 31 | import com.google.gson.GsonBuilder;
|
30 | 32 | import com.google.gson.JsonParseException;
|
|
42 | 44 | import java.util.List;
|
43 | 45 | import java.util.Optional;
|
44 | 46 | import javax.annotation.Nullable;
|
| 47 | +import net.starlark.java.syntax.Location; |
45 | 48 |
|
46 | 49 | /**
|
47 | 50 | * Utility class to hold type adapters and helper methods to get gson registered with type adapters
|
@@ -188,24 +191,102 @@ public Optional<T> read(JsonReader jsonReader) throws IOException {
|
188 | 191 | }
|
189 | 192 | }
|
190 | 193 |
|
191 |
| - public static final Gson LOCKFILE_GSON = |
192 |
| - new GsonBuilder() |
193 |
| - .setPrettyPrinting() |
194 |
| - .disableHtmlEscaping() |
195 |
| - .enableComplexMapKeySerialization() |
196 |
| - .registerTypeAdapterFactory(GenerateTypeAdapter.FACTORY) |
197 |
| - .registerTypeAdapterFactory(DICT) |
198 |
| - .registerTypeAdapterFactory(IMMUTABLE_MAP) |
199 |
| - .registerTypeAdapterFactory(IMMUTABLE_LIST) |
200 |
| - .registerTypeAdapterFactory(IMMUTABLE_BIMAP) |
201 |
| - .registerTypeAdapterFactory(IMMUTABLE_SET) |
202 |
| - .registerTypeAdapterFactory(OPTIONAL) |
203 |
| - .registerTypeAdapter(Version.class, VERSION_TYPE_ADAPTER) |
204 |
| - .registerTypeAdapter(ModuleKey.class, MODULE_KEY_TYPE_ADAPTER) |
205 |
| - .registerTypeAdapter(ModuleExtensionId.class, MODULE_EXTENSION_ID_TYPE_ADAPTER) |
206 |
| - .registerTypeAdapter(AttributeValues.class, new AttributeValuesAdapter()) |
207 |
| - .registerTypeAdapter(byte[].class, BYTE_ARRAY_TYPE_ADAPTER) |
208 |
| - .create(); |
| 194 | + /** |
| 195 | + * A variant of {@link Location} that converts the absolute path to the root module file to a |
| 196 | + * constant and back. |
| 197 | + */ |
| 198 | + // protected only for @AutoValue |
| 199 | + @GenerateTypeAdapter |
| 200 | + @AutoValue |
| 201 | + protected abstract static class RootModuleFileEscapingLocation { |
| 202 | + // This marker string is neither a valid absolute path nor a valid URL and thus cannot conflict |
| 203 | + // with any real module file location. |
| 204 | + private static final String ROOT_MODULE_FILE_LABEL = "@@//:MODULE.bazel"; |
| 205 | + |
| 206 | + public abstract String file(); |
| 207 | + |
| 208 | + public abstract int line(); |
| 209 | + |
| 210 | + public abstract int column(); |
| 211 | + |
| 212 | + public Location toLocation(String moduleFilePath) { |
| 213 | + String file; |
| 214 | + if (file().equals(ROOT_MODULE_FILE_LABEL)) { |
| 215 | + file = moduleFilePath; |
| 216 | + } else { |
| 217 | + file = file(); |
| 218 | + } |
| 219 | + return Location.fromFileLineColumn(file, line(), column()); |
| 220 | + } |
| 221 | + |
| 222 | + public static RootModuleFileEscapingLocation fromLocation( |
| 223 | + Location location, String moduleFilePath) { |
| 224 | + String file; |
| 225 | + if (location.file().equals(moduleFilePath)) { |
| 226 | + file = ROOT_MODULE_FILE_LABEL; |
| 227 | + } else { |
| 228 | + file = location.file(); |
| 229 | + } |
| 230 | + return new AutoValue_GsonTypeAdapterUtil_RootModuleFileEscapingLocation( |
| 231 | + file, location.line(), location.column()); |
| 232 | + } |
| 233 | + } |
| 234 | + |
| 235 | + private static final class LocationTypeAdapterFactory implements TypeAdapterFactory { |
| 236 | + |
| 237 | + private final String moduleFilePath; |
| 238 | + |
| 239 | + public LocationTypeAdapterFactory(Path moduleFilePath) { |
| 240 | + this.moduleFilePath = moduleFilePath.getPathString(); |
| 241 | + } |
| 242 | + |
| 243 | + @Nullable |
| 244 | + @Override |
| 245 | + @SuppressWarnings("unchecked") |
| 246 | + public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { |
| 247 | + if (typeToken.getRawType() != Location.class) { |
| 248 | + return null; |
| 249 | + } |
| 250 | + TypeAdapter<RootModuleFileEscapingLocation> relativizedLocationTypeAdapter = |
| 251 | + gson.getAdapter(RootModuleFileEscapingLocation.class); |
| 252 | + return (TypeAdapter<T>) |
| 253 | + new TypeAdapter<Location>() { |
| 254 | + |
| 255 | + @Override |
| 256 | + public void write(JsonWriter jsonWriter, Location location) throws IOException { |
| 257 | + relativizedLocationTypeAdapter.write( |
| 258 | + jsonWriter, |
| 259 | + RootModuleFileEscapingLocation.fromLocation(location, moduleFilePath)); |
| 260 | + } |
| 261 | + |
| 262 | + @Override |
| 263 | + public Location read(JsonReader jsonReader) throws IOException { |
| 264 | + return relativizedLocationTypeAdapter.read(jsonReader).toLocation(moduleFilePath); |
| 265 | + } |
| 266 | + }; |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + public static Gson createLockFileGson(Path moduleFilePath) { |
| 271 | + return new GsonBuilder() |
| 272 | + .setPrettyPrinting() |
| 273 | + .disableHtmlEscaping() |
| 274 | + .enableComplexMapKeySerialization() |
| 275 | + .registerTypeAdapterFactory(GenerateTypeAdapter.FACTORY) |
| 276 | + .registerTypeAdapterFactory(DICT) |
| 277 | + .registerTypeAdapterFactory(IMMUTABLE_MAP) |
| 278 | + .registerTypeAdapterFactory(IMMUTABLE_LIST) |
| 279 | + .registerTypeAdapterFactory(IMMUTABLE_BIMAP) |
| 280 | + .registerTypeAdapterFactory(IMMUTABLE_SET) |
| 281 | + .registerTypeAdapterFactory(OPTIONAL) |
| 282 | + .registerTypeAdapterFactory(new LocationTypeAdapterFactory(moduleFilePath)) |
| 283 | + .registerTypeAdapter(Version.class, VERSION_TYPE_ADAPTER) |
| 284 | + .registerTypeAdapter(ModuleKey.class, MODULE_KEY_TYPE_ADAPTER) |
| 285 | + .registerTypeAdapter(ModuleExtensionId.class, MODULE_EXTENSION_ID_TYPE_ADAPTER) |
| 286 | + .registerTypeAdapter(AttributeValues.class, new AttributeValuesAdapter()) |
| 287 | + .registerTypeAdapter(byte[].class, BYTE_ARRAY_TYPE_ADAPTER) |
| 288 | + .create(); |
| 289 | + } |
209 | 290 |
|
210 | 291 | private GsonTypeAdapterUtil() {}
|
211 | 292 | }
|
0 commit comments