Skip to content

Commit c0aad05

Browse files
authored
Convert Gson integration to compile-only source set (#1510)
2 parents 2353037 + 92b3cf8 commit c0aad05

File tree

14 files changed

+197
-384
lines changed

14 files changed

+197
-384
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1919
* The default list of type annotations used by `formatAnnotations` has had 8 more annotations from the Checker Framework added [#1494](https://github.com/diffplug/spotless/pull/1494)
2020
### Changes
2121
* Rename `YamlJacksonStep` into `JacksonYamlStep` while normalizing Jackson usage ([#1492](https://github.com/diffplug/spotless/pull/1492))
22+
* Convert `gson` integration to use a compile-only source set ([#1510](https://github.com/diffplug/spotless/pull/1510)).
2223

2324
## [2.32.0] - 2023-01-13
2425
### Added

lib/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def NEEDS_GLUE = [
1515
'flexmark',
1616
'diktat',
1717
'scalafmt',
18-
'jackson'
18+
'jackson',
19+
'gson'
1920
]
2021
for (glue in NEEDS_GLUE) {
2122
sourceSets.register(glue) {
@@ -108,6 +109,8 @@ dependencies {
108109

109110
// used for markdown formatting
110111
flexmarkCompileOnly 'com.vladsch.flexmark:flexmark-all:0.62.2'
112+
113+
gsonCompileOnly 'com.google.code.gson:gson:2.10.1'
111114
}
112115

113116
// we'll hold the core lib to a high standard
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2023 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.glue.gson;
17+
18+
import java.io.IOException;
19+
import java.io.StringWriter;
20+
import java.util.Collections;
21+
22+
import com.google.gson.Gson;
23+
import com.google.gson.GsonBuilder;
24+
import com.google.gson.JsonElement;
25+
import com.google.gson.JsonObject;
26+
import com.google.gson.stream.JsonWriter;
27+
28+
import com.diffplug.spotless.FormatterFunc;
29+
import com.diffplug.spotless.ThrowingEx;
30+
import com.diffplug.spotless.json.gson.GsonConfig;
31+
32+
public class GsonFormatterFunc implements FormatterFunc {
33+
34+
private static final String FAILED_TO_PARSE_ERROR_MESSAGE = "Unable to format JSON";
35+
36+
private final Gson gson;
37+
private final GsonConfig gsonConfig;
38+
private final String generatedIndent;
39+
40+
public GsonFormatterFunc(GsonConfig gsonConfig) {
41+
GsonBuilder gsonBuilder = new GsonBuilder().serializeNulls();
42+
if (!gsonConfig.isEscapeHtml()) {
43+
gsonBuilder = gsonBuilder.disableHtmlEscaping();
44+
}
45+
this.gson = gsonBuilder.create();
46+
this.gsonConfig = gsonConfig;
47+
this.generatedIndent = generateIndent(gsonConfig.getIndentSpaces());
48+
}
49+
50+
@Override
51+
public String apply(String inputString) {
52+
String result;
53+
if (inputString.isEmpty()) {
54+
result = "";
55+
} else {
56+
JsonElement jsonElement = gson.fromJson(inputString, JsonElement.class);
57+
if (jsonElement == null) {
58+
throw new AssertionError(FAILED_TO_PARSE_ERROR_MESSAGE);
59+
}
60+
if (gsonConfig.isSortByKeys() && jsonElement.isJsonObject()) {
61+
jsonElement = sortByKeys(jsonElement.getAsJsonObject());
62+
}
63+
try (StringWriter stringWriter = new StringWriter()) {
64+
JsonWriter jsonWriter = new JsonWriter(stringWriter);
65+
jsonWriter.setIndent(this.generatedIndent);
66+
gson.toJson(jsonElement, jsonWriter);
67+
result = stringWriter + "\n";
68+
} catch (IOException ioException) {
69+
throw ThrowingEx.asRuntime(ioException);
70+
}
71+
}
72+
return result;
73+
}
74+
75+
private JsonElement sortByKeys(JsonObject jsonObject) {
76+
JsonObject result = new JsonObject();
77+
jsonObject.keySet().stream().sorted()
78+
.forEach(key -> {
79+
JsonElement element = jsonObject.get(key);
80+
if (element.isJsonObject()) {
81+
element = sortByKeys(element.getAsJsonObject());
82+
}
83+
result.add(key, element);
84+
});
85+
return result;
86+
}
87+
88+
private String generateIndent(int indentSpaces) {
89+
return String.join("", Collections.nCopies(indentSpaces, " "));
90+
}
91+
92+
}

lib/src/main/java/com/diffplug/spotless/json/gson/GsonBuilderWrapper.java

Lines changed: 0 additions & 54 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2023 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.json.gson;
17+
18+
import java.io.Serializable;
19+
20+
public class GsonConfig implements Serializable {
21+
private static final long serialVersionUID = 6039715618937332633L;
22+
23+
private boolean sortByKeys;
24+
private boolean escapeHtml;
25+
private int indentSpaces;
26+
private String version;
27+
28+
public GsonConfig(boolean sortByKeys, boolean escapeHtml, int indentSpaces, String version) {
29+
this.sortByKeys = sortByKeys;
30+
this.escapeHtml = escapeHtml;
31+
this.indentSpaces = indentSpaces;
32+
this.version = version;
33+
}
34+
35+
public boolean isSortByKeys() {
36+
return sortByKeys;
37+
}
38+
39+
public void setSortByKeys(boolean sortByKeys) {
40+
this.sortByKeys = sortByKeys;
41+
}
42+
43+
public boolean isEscapeHtml() {
44+
return escapeHtml;
45+
}
46+
47+
public void setEscapeHtml(boolean escapeHtml) {
48+
this.escapeHtml = escapeHtml;
49+
}
50+
51+
public int getIndentSpaces() {
52+
return indentSpaces;
53+
}
54+
55+
public void setIndentSpaces(int indentSpaces) {
56+
this.indentSpaces = indentSpaces;
57+
}
58+
59+
public String getVersion() {
60+
return version;
61+
}
62+
63+
public void setVersion(String version) {
64+
this.version = version;
65+
}
66+
}

lib/src/main/java/com/diffplug/spotless/json/gson/GsonStep.java

Lines changed: 22 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 DiffPlug
2+
* Copyright 2022-2023 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,8 +17,8 @@
1717

1818
import java.io.IOException;
1919
import java.io.Serializable;
20-
import java.io.StringWriter;
21-
import java.util.Collections;
20+
import java.lang.reflect.Constructor;
21+
import java.lang.reflect.InvocationTargetException;
2222
import java.util.Objects;
2323

2424
import com.diffplug.spotless.FormatterFunc;
@@ -28,78 +28,38 @@
2828

2929
public class GsonStep {
3030
private static final String MAVEN_COORDINATES = "com.google.code.gson:gson";
31+
private static final String INCOMPATIBLE_ERROR_MESSAGE = "There was a problem interacting with Gson; maybe you set an incompatible version?";
3132

33+
@Deprecated
3234
public static FormatterStep create(int indentSpaces, boolean sortByKeys, boolean escapeHtml, String version, Provisioner provisioner) {
35+
return create(new GsonConfig(sortByKeys, escapeHtml, indentSpaces, version), provisioner);
36+
}
37+
38+
public static FormatterStep create(GsonConfig gsonConfig, Provisioner provisioner) {
3339
Objects.requireNonNull(provisioner, "provisioner cannot be null");
34-
return FormatterStep.createLazy("gson", () -> new State(indentSpaces, sortByKeys, escapeHtml, version, provisioner), State::toFormatter);
40+
return FormatterStep.createLazy("gson", () -> new State(gsonConfig, provisioner), State::toFormatter);
3541
}
3642

3743
private static final class State implements Serializable {
38-
private static final long serialVersionUID = -1493479043249379485L;
44+
private static final long serialVersionUID = -3240568265160440420L;
3945

40-
private final int indentSpaces;
41-
private final boolean sortByKeys;
42-
private final boolean escapeHtml;
4346
private final JarState jarState;
47+
private final GsonConfig gsonConfig;
4448

45-
private State(int indentSpaces, boolean sortByKeys, boolean escapeHtml, String version, Provisioner provisioner) throws IOException {
46-
this.indentSpaces = indentSpaces;
47-
this.sortByKeys = sortByKeys;
48-
this.escapeHtml = escapeHtml;
49-
this.jarState = JarState.from(MAVEN_COORDINATES + ":" + version, provisioner);
49+
private State(GsonConfig gsonConfig, Provisioner provisioner) throws IOException {
50+
this.gsonConfig = gsonConfig;
51+
this.jarState = JarState.from(MAVEN_COORDINATES + ":" + gsonConfig.getVersion(), provisioner);
5052
}
5153

5254
FormatterFunc toFormatter() {
53-
JsonWriterWrapper jsonWriterWrapper = new JsonWriterWrapper(jarState);
54-
JsonElementWrapper jsonElementWrapper = new JsonElementWrapper(jarState);
55-
JsonObjectWrapper jsonObjectWrapper = new JsonObjectWrapper(jarState, jsonElementWrapper);
56-
GsonBuilderWrapper gsonBuilderWrapper = new GsonBuilderWrapper(jarState);
57-
GsonWrapper gsonWrapper = new GsonWrapper(jarState, jsonElementWrapper, jsonWriterWrapper);
58-
59-
Object gsonBuilder = gsonBuilderWrapper.serializeNulls(gsonBuilderWrapper.createGsonBuilder());
60-
if (!escapeHtml) {
61-
gsonBuilder = gsonBuilderWrapper.disableHtmlEscaping(gsonBuilder);
55+
try {
56+
Class<?> formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.gson.GsonFormatterFunc");
57+
Constructor<?> constructor = formatterFunc.getConstructor(GsonConfig.class);
58+
return (FormatterFunc) constructor.newInstance(gsonConfig);
59+
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException
60+
| InstantiationException | IllegalAccessException | NoClassDefFoundError cause) {
61+
throw new IllegalStateException(INCOMPATIBLE_ERROR_MESSAGE, cause);
6262
}
63-
Object gson = gsonBuilderWrapper.create(gsonBuilder);
64-
65-
return inputString -> {
66-
String result;
67-
if (inputString.isEmpty()) {
68-
result = "";
69-
} else {
70-
Object jsonElement = gsonWrapper.fromJson(gson, inputString, jsonElementWrapper.getWrappedClass());
71-
if (jsonElement == null) {
72-
throw new AssertionError(GsonWrapperBase.FAILED_TO_PARSE_ERROR_MESSAGE);
73-
}
74-
if (sortByKeys && jsonElementWrapper.isJsonObject(jsonElement)) {
75-
jsonElement = sortByKeys(jsonObjectWrapper, jsonElementWrapper, jsonElement);
76-
}
77-
try (StringWriter stringWriter = new StringWriter()) {
78-
Object jsonWriter = jsonWriterWrapper.createJsonWriter(stringWriter);
79-
jsonWriterWrapper.setIndent(jsonWriter, generateIndent(indentSpaces));
80-
gsonWrapper.toJson(gson, jsonElement, jsonWriter);
81-
result = stringWriter + "\n";
82-
}
83-
}
84-
return result;
85-
};
86-
}
87-
88-
private Object sortByKeys(JsonObjectWrapper jsonObjectWrapper, JsonElementWrapper jsonElementWrapper, Object jsonObject) {
89-
Object result = jsonObjectWrapper.createJsonObject();
90-
jsonObjectWrapper.keySet(jsonObject).stream().sorted()
91-
.forEach(key -> {
92-
Object element = jsonObjectWrapper.get(jsonObject, key);
93-
if (jsonElementWrapper.isJsonObject(element)) {
94-
element = sortByKeys(jsonObjectWrapper, jsonElementWrapper, element);
95-
}
96-
jsonObjectWrapper.add(result, key, element);
97-
});
98-
return result;
99-
}
100-
101-
private String generateIndent(int indentSpaces) {
102-
return String.join("", Collections.nCopies(indentSpaces, " "));
10363
}
10464
}
10565

lib/src/main/java/com/diffplug/spotless/json/gson/GsonWrapper.java

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)