Skip to content

Commit

Permalink
Merge branch 'main' into feat/source-set
Browse files Browse the repository at this point in the history
  • Loading branch information
nedtwigg authored Feb 15, 2022
2 parents 9b1955b + 4333885 commit 8d393b4
Show file tree
Hide file tree
Showing 38 changed files with 2,258 additions and 132 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
* Added support for JSON formatting based on [Gson](https://github.com/google/gson) ([#1125](https://github.com/diffplug/spotless/pull/1125)).

### Changed

* Use SLF4J for logging ([#1116](https://github.com/diffplug/spotless/issues/1116))

## [2.22.2] - 2022-02-09
### Changed
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ It's easy to build such a function, but there are some gotchas and lots of integ
## Current feature matrix

<!---freshmark matrix
function lib(className) { return '| [`' + className + '`](lib/src/main/java/com/diffplug/spotless/' + className.replace('.', '/') + '.java) | ' }
function extra(className) { return '| [`' + className + '`](lib-extra/src/main/java/com/diffplug/spotless/extra/' + className.replace('.', '/') + '.java) | ' }
function lib(className) { return '| [`' + className + '`](lib/src/main/java/com/diffplug/spotless/' + className.replaceAll('\\.', '/') + '.java) | ' }
function extra(className) { return '| [`' + className + '`](lib-extra/src/main/java/com/diffplug/spotless/extra/' + className.replaceAll('\\.', '/') + '.java) | ' }
// | GRADLE | MAVEN | SBT | (new) |
output = [
Expand Down Expand Up @@ -61,6 +61,8 @@ lib('java.ImportOrderStep') +'{{yes}} | {{yes}}
lib('java.PalantirJavaFormatStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
extra('java.EclipseJdtFormatterStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
lib('json.gson.GsonStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
lib('json.JsonSimpleStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
lib('kotlin.KtLintStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
lib('kotlin.KtfmtStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
lib('kotlin.DiktatStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
Expand Down Expand Up @@ -102,6 +104,8 @@ extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}}
| [`java.PalantirJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/PalantirJavaFormatStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
| [`java.RemoveUnusedImportsStep`](lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
| [`java.EclipseJdtFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseJdtFormatterStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
| [`json.gson.GsonStep`](lib/src/main/java/com/diffplug/spotless/json/gson/GsonStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
| [`json.JsonSimpleStep`](lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
| [`kotlin.KtLintStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
| [`kotlin.KtfmtStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
| [`kotlin.DiktatStep`](lib/src/main/java/com/diffplug/spotless/kotlin/DiktatStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
Expand Down
1 change: 0 additions & 1 deletion gradle/javadoc/java8/package-list
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ java.util.concurrent.atomic
java.util.concurrent.locks
java.util.function
java.util.jar
java.util.logging
java.util.prefs
java.util.regex
java.util.spi
Expand Down
2 changes: 2 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ for (glue in NEEDS_GLUE) {
}

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

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

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 DiffPlug
* Copyright 2021-2022 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,7 +19,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.pinterest.ktlint.core.KtLint;
import com.pinterest.ktlint.core.KtLint.Params;
Expand All @@ -33,7 +32,6 @@
import kotlin.jvm.functions.Function2;

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

private final List<RuleSet> rulesets;
private final Map<String, String> userData;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016 DiffPlug
* Copyright 2016-2022 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,13 +15,13 @@
*/
package com.diffplug.spotless;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

private static final Logger logger = Logger.getLogger(Formatter.class.getName());
private static final Logger logger = LoggerFactory.getLogger(Formatter.class);

@Override
public void handleError(Throwable e, FormatterStep step, String relativePath) {
Expand All @@ -34,10 +34,10 @@ public void handleError(Throwable e, FormatterStep step, String relativePath) {
}

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

static void warning(Throwable e, FormatterStep step, String relativePath) {
logger.log(Level.WARNING, "Unable to apply step '" + step.getName() + "' to '" + relativePath + "'", e);
logger.warn("Unable to apply step '{}' to '{}'", step.getName(), relativePath, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2022 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.json.gson;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import com.diffplug.spotless.JarState;

class GsonBuilderWrapper extends GsonWrapperBase {

private final Constructor<?> constructor;
private final Method serializeNullsMethod;
private final Method disableHtmlEscapingMethod;
private final Method createMethod;

GsonBuilderWrapper(JarState jarState) {
Class<?> clazz = loadClass(jarState.getClassLoader(), "com.google.gson.GsonBuilder");
this.constructor = getConstructor(clazz);
this.serializeNullsMethod = getMethod(clazz, "serializeNulls");
this.disableHtmlEscapingMethod = getMethod(clazz, "disableHtmlEscaping");
this.createMethod = getMethod(clazz, "create");
}

Object createGsonBuilder() {
return newInstance(constructor);
}

Object serializeNulls(Object gsonBuilder) {
return invoke(serializeNullsMethod, gsonBuilder);
}

Object disableHtmlEscaping(Object gsonBuilder) {
return invoke(disableHtmlEscapingMethod, gsonBuilder);
}

Object create(Object gsonBuilder) {
return invoke(createMethod, gsonBuilder);
}

}
106 changes: 106 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/json/gson/GsonStep.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2022 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.json.gson;

import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Objects;

import com.diffplug.spotless.FormatterFunc;
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.JarState;
import com.diffplug.spotless.Provisioner;

public class GsonStep {
private static final String MAVEN_COORDINATES = "com.google.code.gson:gson";

public static FormatterStep create(int indentSpaces, boolean sortByKeys, boolean escapeHtml, String version, Provisioner provisioner) {
Objects.requireNonNull(provisioner, "provisioner cannot be null");
return FormatterStep.createLazy("gson", () -> new State(indentSpaces, sortByKeys, escapeHtml, version, provisioner), State::toFormatter);
}

private static final class State implements Serializable {
private static final long serialVersionUID = -1493479043249379485L;

private final int indentSpaces;
private final boolean sortByKeys;
private final boolean escapeHtml;
private final JarState jarState;

private State(int indentSpaces, boolean sortByKeys, boolean escapeHtml, String version, Provisioner provisioner) throws IOException {
this.indentSpaces = indentSpaces;
this.sortByKeys = sortByKeys;
this.escapeHtml = escapeHtml;
this.jarState = JarState.from(MAVEN_COORDINATES + ":" + version, provisioner);
}

FormatterFunc toFormatter() {
JsonWriterWrapper jsonWriterWrapper = new JsonWriterWrapper(jarState);
JsonElementWrapper jsonElementWrapper = new JsonElementWrapper(jarState);
JsonObjectWrapper jsonObjectWrapper = new JsonObjectWrapper(jarState, jsonElementWrapper);
GsonBuilderWrapper gsonBuilderWrapper = new GsonBuilderWrapper(jarState);
GsonWrapper gsonWrapper = new GsonWrapper(jarState, jsonElementWrapper, jsonWriterWrapper);

Object gsonBuilder = gsonBuilderWrapper.serializeNulls(gsonBuilderWrapper.createGsonBuilder());
if (!escapeHtml) {
gsonBuilder = gsonBuilderWrapper.disableHtmlEscaping(gsonBuilder);
}
Object gson = gsonBuilderWrapper.create(gsonBuilder);

return inputString -> {
String result;
if (inputString.isEmpty()) {
result = "";
} else {
Object jsonElement = gsonWrapper.fromJson(gson, inputString, jsonElementWrapper.getWrappedClass());
if (jsonElement == null) {
throw new AssertionError(GsonWrapperBase.FAILED_TO_PARSE_ERROR_MESSAGE);
}
if (sortByKeys && jsonElementWrapper.isJsonObject(jsonElement)) {
jsonElement = sortByKeys(jsonObjectWrapper, jsonElementWrapper, jsonElement);
}
try (StringWriter stringWriter = new StringWriter()) {
Object jsonWriter = jsonWriterWrapper.createJsonWriter(stringWriter);
jsonWriterWrapper.setIndent(jsonWriter, generateIndent(indentSpaces));
gsonWrapper.toJson(gson, jsonElement, jsonWriter);
result = stringWriter + "\n";
}
}
return result;
};
}

private Object sortByKeys(JsonObjectWrapper jsonObjectWrapper, JsonElementWrapper jsonElementWrapper, Object jsonObject) {
Object result = jsonObjectWrapper.createJsonObject();
jsonObjectWrapper.keySet(jsonObject).stream().sorted()
.forEach(key -> {
Object element = jsonObjectWrapper.get(jsonObject, key);
if (jsonElementWrapper.isJsonObject(element)) {
element = sortByKeys(jsonObjectWrapper, jsonElementWrapper, element);
}
jsonObjectWrapper.add(result, key, element);
});
return result;
}

private String generateIndent(int indentSpaces) {
return String.join("", Collections.nCopies(indentSpaces, " "));
}
}

}
41 changes: 41 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/json/gson/GsonWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2022 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.json.gson;

import java.lang.reflect.Method;

import com.diffplug.spotless.JarState;

class GsonWrapper extends GsonWrapperBase {

private final Method fromJsonMethod;
private final Method toJsonMethod;

GsonWrapper(JarState jarState, JsonElementWrapper jsonElementWrapper, JsonWriterWrapper jsonWriterWrapper) {
Class<?> clazz = loadClass(jarState.getClassLoader(), "com.google.gson.Gson");
this.fromJsonMethod = getMethod(clazz, "fromJson", String.class, Class.class);
this.toJsonMethod = getMethod(clazz, "toJson", jsonElementWrapper.getWrappedClass(), jsonWriterWrapper.getWrappedClass());
}

Object fromJson(Object gson, String json, Class<?> type) {
return invoke(fromJsonMethod, gson, json, type);
}

void toJson(Object gson, Object jsonElement, Object jsonWriter) {
invoke(toJsonMethod, gson, jsonElement, jsonWriter);
}

}
Loading

0 comments on commit 8d393b4

Please sign in to comment.