Skip to content

Commit 8d393b4

Browse files
authored
Merge branch 'main' into feat/source-set
2 parents 9b1955b + 4333885 commit 8d393b4

38 files changed

+2258
-132
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ This document is intended for Spotless developers.
1010
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
1111

1212
## [Unreleased]
13+
### Added
14+
* Added support for JSON formatting based on [Gson](https://github.com/google/gson) ([#1125](https://github.com/diffplug/spotless/pull/1125)).
15+
16+
### Changed
17+
18+
* Use SLF4J for logging ([#1116](https://github.com/diffplug/spotless/issues/1116))
1319

1420
## [2.22.2] - 2022-02-09
1521
### Changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ It's easy to build such a function, but there are some gotchas and lots of integ
3030
## Current feature matrix
3131

3232
<!---freshmark matrix
33-
function lib(className) { return '| [`' + className + '`](lib/src/main/java/com/diffplug/spotless/' + className.replace('.', '/') + '.java) | ' }
34-
function extra(className) { return '| [`' + className + '`](lib-extra/src/main/java/com/diffplug/spotless/extra/' + className.replace('.', '/') + '.java) | ' }
33+
function lib(className) { return '| [`' + className + '`](lib/src/main/java/com/diffplug/spotless/' + className.replaceAll('\\.', '/') + '.java) | ' }
34+
function extra(className) { return '| [`' + className + '`](lib-extra/src/main/java/com/diffplug/spotless/extra/' + className.replaceAll('\\.', '/') + '.java) | ' }
3535
3636
// | GRADLE | MAVEN | SBT | (new) |
3737
output = [
@@ -61,6 +61,8 @@ lib('java.ImportOrderStep') +'{{yes}} | {{yes}}
6161
lib('java.PalantirJavaFormatStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
6262
lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
6363
extra('java.EclipseJdtFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
64+
lib('json.gson.GsonStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
65+
lib('json.JsonSimpleStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
6466
lib('kotlin.KtLintStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
6567
lib('kotlin.KtfmtStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
6668
lib('kotlin.DiktatStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
@@ -102,6 +104,8 @@ extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}}
102104
| [`java.PalantirJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/PalantirJavaFormatStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
103105
| [`java.RemoveUnusedImportsStep`](lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
104106
| [`java.EclipseJdtFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseJdtFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
107+
| [`json.gson.GsonStep`](lib/src/main/java/com/diffplug/spotless/json/gson/GsonStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
108+
| [`json.JsonSimpleStep`](lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
105109
| [`kotlin.KtLintStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
106110
| [`kotlin.KtfmtStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
107111
| [`kotlin.DiktatStep`](lib/src/main/java/com/diffplug/spotless/kotlin/DiktatStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |

gradle/javadoc/java8/package-list

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ java.util.concurrent.atomic
5555
java.util.concurrent.locks
5656
java.util.function
5757
java.util.jar
58-
java.util.logging
5958
java.util.prefs
6059
java.util.regex
6160
java.util.spi

lib/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ for (glue in NEEDS_GLUE) {
2121
}
2222

2323
dependencies {
24+
compileOnly 'org.slf4j:slf4j-api:1.7.35'
2425
// zero runtime reqs is a hard requirements for spotless-lib
2526
// if you need a dep, put it in lib-extra
2627
testImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT"
@@ -29,6 +30,7 @@ dependencies {
2930

3031
// used for pom sorting
3132
sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0'
33+
sortPomCompileOnly 'org.slf4j:slf4j-api:1.7.35'
3234

3335
palantirJavaFormatCompileOnly 'com.palantir.javaformat:palantir-java-format:1.1.0'
3436

lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 DiffPlug
2+
* Copyright 2021-2022 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.
@@ -19,7 +19,6 @@
1919
import java.util.Collections;
2020
import java.util.List;
2121
import java.util.Map;
22-
import java.util.logging.Logger;
2322

2423
import com.pinterest.ktlint.core.KtLint;
2524
import com.pinterest.ktlint.core.KtLint.Params;
@@ -33,7 +32,6 @@
3332
import kotlin.jvm.functions.Function2;
3433

3534
public class KtlintFormatterFunc implements FormatterFunc.NeedsFile {
36-
private static final Logger logger = Logger.getLogger(KtlintFormatterFunc.class.getName());
3735

3836
private final List<RuleSet> rulesets;
3937
private final Map<String, String> userData;

lib/src/main/java/com/diffplug/spotless/FormatExceptionPolicyLegacy.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 DiffPlug
2+
* Copyright 2016-2022 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.
@@ -15,13 +15,13 @@
1515
*/
1616
package com.diffplug.spotless;
1717

18-
import java.util.logging.Level;
19-
import java.util.logging.Logger;
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
2020

2121
class FormatExceptionPolicyLegacy extends NoLambda.EqualityBasedOnSerialization implements FormatExceptionPolicy {
2222
private static final long serialVersionUID = 1L;
2323

24-
private static final Logger logger = Logger.getLogger(Formatter.class.getName());
24+
private static final Logger logger = LoggerFactory.getLogger(Formatter.class);
2525

2626
@Override
2727
public void handleError(Throwable e, FormatterStep step, String relativePath) {
@@ -34,10 +34,10 @@ public void handleError(Throwable e, FormatterStep step, String relativePath) {
3434
}
3535

3636
static void error(Throwable e, FormatterStep step, String relativePath) {
37-
logger.log(Level.SEVERE, "Step '" + step.getName() + "' found problem in '" + relativePath + "':\n" + e.getMessage(), e);
37+
logger.error("Step '{}' found problem in '{}':\n{}", step.getName(), relativePath, e.getMessage(), e);
3838
}
3939

4040
static void warning(Throwable e, FormatterStep step, String relativePath) {
41-
logger.log(Level.WARNING, "Unable to apply step '" + step.getName() + "' to '" + relativePath + "'", e);
41+
logger.warn("Unable to apply step '{}' to '{}'", step.getName(), relativePath, e);
4242
}
4343
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2022 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.lang.reflect.Constructor;
19+
import java.lang.reflect.Method;
20+
21+
import com.diffplug.spotless.JarState;
22+
23+
class GsonBuilderWrapper extends GsonWrapperBase {
24+
25+
private final Constructor<?> constructor;
26+
private final Method serializeNullsMethod;
27+
private final Method disableHtmlEscapingMethod;
28+
private final Method createMethod;
29+
30+
GsonBuilderWrapper(JarState jarState) {
31+
Class<?> clazz = loadClass(jarState.getClassLoader(), "com.google.gson.GsonBuilder");
32+
this.constructor = getConstructor(clazz);
33+
this.serializeNullsMethod = getMethod(clazz, "serializeNulls");
34+
this.disableHtmlEscapingMethod = getMethod(clazz, "disableHtmlEscaping");
35+
this.createMethod = getMethod(clazz, "create");
36+
}
37+
38+
Object createGsonBuilder() {
39+
return newInstance(constructor);
40+
}
41+
42+
Object serializeNulls(Object gsonBuilder) {
43+
return invoke(serializeNullsMethod, gsonBuilder);
44+
}
45+
46+
Object disableHtmlEscaping(Object gsonBuilder) {
47+
return invoke(disableHtmlEscapingMethod, gsonBuilder);
48+
}
49+
50+
Object create(Object gsonBuilder) {
51+
return invoke(createMethod, gsonBuilder);
52+
}
53+
54+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2022 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.IOException;
19+
import java.io.Serializable;
20+
import java.io.StringWriter;
21+
import java.util.Collections;
22+
import java.util.Objects;
23+
24+
import com.diffplug.spotless.FormatterFunc;
25+
import com.diffplug.spotless.FormatterStep;
26+
import com.diffplug.spotless.JarState;
27+
import com.diffplug.spotless.Provisioner;
28+
29+
public class GsonStep {
30+
private static final String MAVEN_COORDINATES = "com.google.code.gson:gson";
31+
32+
public static FormatterStep create(int indentSpaces, boolean sortByKeys, boolean escapeHtml, String version, Provisioner provisioner) {
33+
Objects.requireNonNull(provisioner, "provisioner cannot be null");
34+
return FormatterStep.createLazy("gson", () -> new State(indentSpaces, sortByKeys, escapeHtml, version, provisioner), State::toFormatter);
35+
}
36+
37+
private static final class State implements Serializable {
38+
private static final long serialVersionUID = -1493479043249379485L;
39+
40+
private final int indentSpaces;
41+
private final boolean sortByKeys;
42+
private final boolean escapeHtml;
43+
private final JarState jarState;
44+
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);
50+
}
51+
52+
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);
62+
}
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, " "));
103+
}
104+
}
105+
106+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2022 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.lang.reflect.Method;
19+
20+
import com.diffplug.spotless.JarState;
21+
22+
class GsonWrapper extends GsonWrapperBase {
23+
24+
private final Method fromJsonMethod;
25+
private final Method toJsonMethod;
26+
27+
GsonWrapper(JarState jarState, JsonElementWrapper jsonElementWrapper, JsonWriterWrapper jsonWriterWrapper) {
28+
Class<?> clazz = loadClass(jarState.getClassLoader(), "com.google.gson.Gson");
29+
this.fromJsonMethod = getMethod(clazz, "fromJson", String.class, Class.class);
30+
this.toJsonMethod = getMethod(clazz, "toJson", jsonElementWrapper.getWrappedClass(), jsonWriterWrapper.getWrappedClass());
31+
}
32+
33+
Object fromJson(Object gson, String json, Class<?> type) {
34+
return invoke(fromJsonMethod, gson, json, type);
35+
}
36+
37+
void toJson(Object gson, Object jsonElement, Object jsonWriter) {
38+
invoke(toJsonMethod, gson, jsonElement, jsonWriter);
39+
}
40+
41+
}

0 commit comments

Comments
 (0)